505 lines
14 KiB
Vue
505 lines
14 KiB
Vue
<template>
|
||
<div class="test-slide-wrapper">
|
||
<H v-model:index="state.baseIndex">
|
||
<SlideItem>
|
||
<IndicatorHome
|
||
:isLight="state.subTypeVisible"
|
||
v-if="!state.fullScreen"
|
||
:loading="state.loading"
|
||
name="main"
|
||
v-model:index="state.navIndex"
|
||
/>
|
||
|
||
<div class="slide-content"
|
||
>
|
||
<H class="first-horizontal-item"
|
||
name="main"
|
||
id="slideHook"
|
||
v-model:index="state.navIndex">
|
||
<SlideItem id="slide1">
|
||
<div class="sub-type"
|
||
:class="state.subTypeIsTop?'top':''"
|
||
ref="subTypeRef">
|
||
<div class="local">
|
||
<div class="card" @touchmove.capture="stop">
|
||
<div class="nav-item">
|
||
<img src="../../assets/img/icon/msg-icon9.webp" alt="">
|
||
<span>美食</span>
|
||
</div>
|
||
<div class="nav-item">
|
||
<img src="../../assets/img/icon/msg-icon9.webp" alt="">
|
||
<span>休闲娱乐</span>
|
||
</div>
|
||
<div class="nav-item">
|
||
<img src="../../assets/img/icon/msg-icon9.webp" alt="">
|
||
<span>游玩</span>
|
||
</div>
|
||
<div class="nav-item">
|
||
<img src="../../assets/img/icon/msg-icon9.webp" alt="">
|
||
<span>丽人/美发</span>
|
||
</div>
|
||
<div class="nav-item">
|
||
<img src="../../assets/img/icon/msg-icon9.webp" alt="">
|
||
<span>住宿</span>
|
||
</div>
|
||
<div class="nav-item">
|
||
<img src="../../assets/img/icon/msg-icon9.webp" alt="">
|
||
<span>游玩</span>
|
||
</div>
|
||
<div class="nav-item">
|
||
<img src="../../assets/img/icon/msg-icon9.webp" alt="">
|
||
<span>丽人/美发</span>
|
||
</div>
|
||
<div class="nav-item">
|
||
<img src="../../assets/img/icon/msg-icon9.webp" alt="">
|
||
<span>住宿</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="sub-type-notice"
|
||
v-if="state.subType===-1 && !state.subTypeVisible"
|
||
@click="showSubType">附近吃喝玩乐
|
||
</div>
|
||
<VInfinite
|
||
@touchstart="pageClick"
|
||
v-love="'slideHook'"
|
||
:style="{background: 'black',marginTop:state.subTypeVisible?state.subTypeHeight:0}"
|
||
name="main"
|
||
id="slide1-infinite"
|
||
v-model:index="state.itemIndex"
|
||
:render="render"
|
||
:list="state.recommendVideos"
|
||
:position="{
|
||
baseIndex:0,
|
||
navIndex:5,
|
||
}"
|
||
@loadMore="loadMore"
|
||
@refresh="() => getData(true)"
|
||
>
|
||
</VInfinite>
|
||
</SlideItem>
|
||
<SlideItem>
|
||
<Community/>
|
||
</SlideItem>
|
||
<SlideItem class=" gray">
|
||
<div class="big">关注</div>
|
||
</SlideItem>
|
||
<SlideItem>
|
||
<Shop/>
|
||
</SlideItem>
|
||
<SlideItem>
|
||
<VInfinite
|
||
:style="{background: 'black'}"
|
||
name="main"
|
||
v-model:index="state.itemIndex"
|
||
:render="render"
|
||
:list="state.recommendVideos"
|
||
:position="{
|
||
baseIndex:0,
|
||
navIndex:5,
|
||
}"
|
||
@loadMore="loadMore"
|
||
@refresh="() => getData(true)"
|
||
>
|
||
</VInfinite>
|
||
</SlideItem>
|
||
</H>
|
||
</div>
|
||
<Footer v-bind:init-tab="1"/>
|
||
</SlideItem>
|
||
<SlideItem>
|
||
<UserPanel
|
||
ref="uploader"
|
||
:isOnThisPage="state.baseIndex === 1"
|
||
:author="state.recommendVideos[state.itemIndex]?.author"
|
||
@toggleCanMove="e => state.canMove = e"
|
||
@back="state.baseIndex = 0"
|
||
@showFollowSetting="state.showFollowSetting = true"
|
||
@showFollowSetting2="state.showFollowSetting2 = true"
|
||
/>
|
||
</SlideItem>
|
||
</H>
|
||
|
||
<Comment page-id="slideHook" v-model="state.commentVisible"
|
||
@close="closeComments"
|
||
/>
|
||
|
||
<Share v-model="state.isSharing"
|
||
ref="share"
|
||
page-id="slideHook"
|
||
@dislike="dislike"
|
||
:videoId="state.recommendVideos[state.itemIndex]?.id"
|
||
:canDownload="state.recommendVideos[state.itemIndex]?.canDownload"
|
||
@play-feedback="state.showPlayFeedback = true"
|
||
@showShareDuoshan="delayShowDialog(e => state.showShareDuoshan = true)"
|
||
@shareToFriend="delayShowDialog(e => state.shareToFriend = true)"
|
||
@showDouyinCode="state.showDouyinCode = true"
|
||
@showShare2WeChatZone="state.shareType = 2"
|
||
@share2WeChat="state.shareType = 3"
|
||
@share2QQZone="state.shareType = 4"
|
||
@share2QQ="state.shareType = 5"
|
||
@share2Webo="state.shareType = 8"
|
||
@download="state.shareType = 9"
|
||
/>
|
||
|
||
<PlayFeedback v-model="state.showPlayFeedback"/>
|
||
|
||
<DouyinCode v-model="state.showDouyinCode"/>
|
||
|
||
<Duoshan v-model="state.showShareDuoshan"/>
|
||
|
||
<ShareTo v-model:type="state.shareType"
|
||
:videoId="state.recommendVideos[state.itemIndex]?.id"
|
||
:canDownload="state.recommendVideos[state.itemIndex]?.canDownload"
|
||
/>
|
||
|
||
<FollowSetting
|
||
@showChangeNote="delayShowDialog( e => state.showChangeNote = true)"
|
||
@showBlockDialog="delayShowDialog(e => state.showBlockDialog = true)"
|
||
@showShare="delayShowDialog( e => state.isSharing = true)"
|
||
v-model="state.showFollowSetting"/>
|
||
|
||
<FollowSetting2
|
||
@cancelFollow="$refs.uploader.cancelFollow()"
|
||
v-model="state.showFollowSetting2"/>
|
||
|
||
<BlockDialog v-model="state.showBlockDialog"/>
|
||
|
||
<ConfirmDialog
|
||
title="设置备注名"
|
||
ok-text="确认"
|
||
v-model:visible="state.showChangeNote"
|
||
>
|
||
<Search mode="light" v-model="state.test" :isShowSearchIcon="false"/>
|
||
</ConfirmDialog>
|
||
|
||
<ShareToFriend v-model="state.shareToFriend"/>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="jsx">
|
||
import H from './H'
|
||
import VInfinite from './VInfinite.vue'
|
||
import SlideItem from './SlideItem'
|
||
import SlideAlbum from "../../components/slide/SlideAlbum";
|
||
import SlideUser from "../../components/slide/SlideUser";
|
||
import BVideo from "../../components/slide/BVideo";
|
||
import Comment from "../../components/Comment";
|
||
import Share from "../../components/Share";
|
||
import IndicatorHome from "./IndicatorHome.vue";
|
||
import {computed, onMounted, onUnmounted, reactive, ref} from "vue";
|
||
import bus, {EVENT_KEY} from "../../utils/bus";
|
||
import {useNav} from "@/utils/hooks/useNav";
|
||
import Utils from "@/utils";
|
||
import api from "@/api";
|
||
import {useStore} from "vuex";
|
||
import PlayFeedback from "@/pages/home/components/PlayFeedback";
|
||
import FromBottomDialog from "../../components/dialog/FromBottomDialog";
|
||
import Duoshan from "@/pages/home/components/Duoshan";
|
||
import ShareTo from "@/pages/home/components/ShareTo";
|
||
import DouyinCode from "../../components/DouyinCode";
|
||
import Uploader from "../me/Uploader";
|
||
import FollowSetting from "@/pages/home/components/FollowSetting";
|
||
import BlockDialog from "../message/components/BlockDialog";
|
||
import Search from "../../components/Search";
|
||
import ConfirmDialog from "../../components/dialog/ConfirmDialog";
|
||
import FollowSetting2 from "@/pages/home/components/FollowSetting2";
|
||
import Dom from "../../utils/dom";
|
||
import ShareToFriend from "@/pages/home/components/ShareToFriend";
|
||
import resource from "@/assets/data/resource";
|
||
import UserPanel from "@/components/UserPanel.vue";
|
||
import Community from "@/pages/slideHooks/Community.vue";
|
||
import Shop from "@/pages/slideHooks/Shop.vue";
|
||
|
||
const nav = useNav()
|
||
|
||
function stop(e) {
|
||
e.stopPropagation()
|
||
}
|
||
|
||
const store = useStore()
|
||
const friends = computed(() => store.state.friends)
|
||
const bodyHeight = computed(() => store.state.bodyHeight)
|
||
const bodyWidth = computed(() => store.state.bodyWidth)
|
||
|
||
const subTypeRef = ref(null)
|
||
const state = reactive({
|
||
baseIndex: 0,
|
||
navIndex: 4,
|
||
itemIndex: 0,
|
||
test: '',
|
||
recommendVideos: [
|
||
// {
|
||
// type: 'img',
|
||
// src: `http://douyin.ttentau.top/0.mp4?vframe/jpg/offset/0/w/${document.body.clientWidth}`
|
||
// },
|
||
// {
|
||
// type: 'imgs',
|
||
// src: `http://douyin.ttentau.top/0.mp4?vframe/jpg/offset/0/w/${document.body.clientWidth}`
|
||
// },
|
||
// {
|
||
// type: 'user',
|
||
// src: `http://douyin.ttentau.top/0.mp4?vframe/jpg/offset/0/w/${document.body.clientWidth}`
|
||
// },
|
||
],
|
||
|
||
isSharing: false,
|
||
canMove: true,
|
||
loading: false,
|
||
|
||
shareType: -1,
|
||
|
||
showPlayFeedback: false,
|
||
showShareDuoshan: false,
|
||
showShareDialog: false,
|
||
showShare2WeChatZone: false,
|
||
showDouyinCode: false,
|
||
showFollowSetting: false,
|
||
showFollowSetting2: false,
|
||
showBlockDialog: false,
|
||
showChangeNote: false,
|
||
shareToFriend: false,
|
||
|
||
commentVisible: false,
|
||
fullScreen: false,
|
||
subType: -1,
|
||
subTypeVisible: false,
|
||
subTypeHeight: '0',
|
||
//用于改变zindex的层级到上层,反正比slide高就行。不然摸不到subType.
|
||
subTypeIsTop: false,
|
||
totalSize: 0,
|
||
pageSize: 10,
|
||
pageNo: 0,
|
||
})
|
||
|
||
async function getData(refresh = false) {
|
||
// if (process.env.NODE_ENV !== 'development') {
|
||
// state.totalSize = 11
|
||
// return state.recommendVideos = resource.videos
|
||
// }
|
||
if (state.loading) return
|
||
state.loading = true
|
||
let res = await api.videos.recommended({pageNo: refresh ? 0 : state.pageNo, pageSize: state.pageSize})
|
||
console.log('loadMore-', 'refresh', refresh, res)
|
||
state.loading = false
|
||
if (res.code === 200) {
|
||
state.totalSize = res.data.total
|
||
if (refresh) {
|
||
state.recommendVideos = []
|
||
}
|
||
state.recommendVideos = state.recommendVideos.concat(res.data.list)
|
||
} else {
|
||
state.pageNo--
|
||
}
|
||
}
|
||
|
||
function loadMore() {
|
||
if (!state.loading) {
|
||
state.pageNo++
|
||
getData()
|
||
}
|
||
}
|
||
|
||
function showSubType(e) {
|
||
Utils.$stopPropagation(e)
|
||
console.log('subTypeRef',)
|
||
state.subTypeHeight = subTypeRef.value.getBoundingClientRect().height + 'px'
|
||
state.subTypeVisible = true
|
||
setTimeout(() => state.subTypeIsTop = true, 300)
|
||
bus.emit(EVENT_KEY.OPEN_SUB_TYPE,)
|
||
}
|
||
|
||
function pageClick(e) {
|
||
// console.log('pageClick')
|
||
if (state.subTypeVisible) {
|
||
state.subTypeIsTop = state.subTypeVisible = false
|
||
bus.emit(EVENT_KEY.CLOSE_SUB_TYPE,)
|
||
Utils.$stopPropagation(e)
|
||
}
|
||
}
|
||
|
||
function delayShowDialog(cb) {
|
||
setTimeout(() => {
|
||
cb()
|
||
}, 400)
|
||
}
|
||
|
||
function dislike() {
|
||
// this.$refs.virtualList.dislike(this.videos[10])
|
||
// this.videos[this.videoIndex] = this.videos[10]
|
||
// this.$notice('操作成功,将减少此类视频的推荐')
|
||
}
|
||
|
||
function end() {
|
||
// this.$notice('暂时没有更多了')
|
||
}
|
||
|
||
onMounted(() => {
|
||
getData()
|
||
bus.on(EVENT_KEY.SINGLE_CLICK, () => {
|
||
let id = ''
|
||
if (state.navIndex === 4) {
|
||
id = state.recommendVideos[state.itemIndex].id
|
||
}
|
||
bus.emit(EVENT_KEY.SINGLE_CLICK_BROADCAST, {id, type: EVENT_KEY.ITEM_TOGGLE})
|
||
})
|
||
bus.on('update:item', val => {
|
||
const {baseIndex, navIndex, itemIndex} = val.position
|
||
if (navIndex === 5) {
|
||
state.recommendVideos[itemIndex] = val.item
|
||
}
|
||
})
|
||
|
||
bus.on(EVENT_KEY.ENTER_FULLSCREEN, (e) => state.fullScreen = true)
|
||
bus.on(EVENT_KEY.EXIT_FULLSCREEN, (e) => state.fullScreen = false)
|
||
bus.on(EVENT_KEY.OPEN_COMMENTS, (e) => {
|
||
bus.emit(EVENT_KEY.ENTER_FULLSCREEN)
|
||
state.commentVisible = true
|
||
})
|
||
bus.on(EVENT_KEY.CLOSE_COMMENTS, (e) => {
|
||
bus.emit(EVENT_KEY.EXIT_FULLSCREEN)
|
||
state.commentVisible = false
|
||
})
|
||
bus.on('nav', path => nav(path))
|
||
})
|
||
onUnmounted(() => {
|
||
bus.offAll()
|
||
})
|
||
|
||
function closeComments() {
|
||
bus.emit(EVENT_KEY.CLOSE_COMMENTS)
|
||
}
|
||
|
||
function render(item, itemIndex, play, position) {
|
||
// console.log('item', item)
|
||
let node
|
||
if (item.type === 'img') {
|
||
node = <img src={item.src} style="height:100%;"/>
|
||
}
|
||
if (item.type === 'imgs') {
|
||
node = <SlideAlbum/>
|
||
}
|
||
if (item.type === 'user') {
|
||
node = <SlideUser/>
|
||
}
|
||
if (item.type === 'send-video') {
|
||
node = <video src={item.src} style="height:100%;"/>
|
||
}
|
||
if (item.type === 'recommend-video') {
|
||
node = <BVideo
|
||
isPlay={false}
|
||
item={item}
|
||
position={{...position, itemIndex}}
|
||
onGoMusic={e => nav('/home/music')}
|
||
onShowShare={e => state.isSharing = true}
|
||
onGoUserInfo={e => state.baseIndex = 1}
|
||
/>
|
||
}
|
||
return node
|
||
}
|
||
|
||
</script>
|
||
|
||
<style scoped lang="less">
|
||
@import "@/assets/less/index";
|
||
|
||
.test-slide-wrapper {
|
||
font-size: 14rem;
|
||
width: 100%;
|
||
height: 100%;
|
||
overflow: hidden;
|
||
|
||
.big {
|
||
font-weight: bold;
|
||
font-size: 100rem;
|
||
}
|
||
|
||
.slide-content {
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
}
|
||
|
||
.first-horizontal-item {
|
||
//width: 90vw;
|
||
//height: 80vh;
|
||
width: 100vw;
|
||
height: calc(100vh - @footer-height);
|
||
overflow: hidden;
|
||
|
||
#slide1 {
|
||
position: relative;
|
||
|
||
.sub-type {
|
||
width: 100%;
|
||
position: fixed;
|
||
top: 0;
|
||
|
||
&.top {
|
||
z-index: 2;
|
||
}
|
||
|
||
.local {
|
||
transition: all .3s;
|
||
font-size: 14rem;
|
||
color: gray;
|
||
background: #f9f9f9;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
|
||
.card {
|
||
margin: 20rem;
|
||
margin-top: @header-height;
|
||
padding: 20rem;
|
||
border-radius: 8rem;
|
||
width: 100%;
|
||
background: white;
|
||
box-sizing: border-box;
|
||
display: flex;
|
||
align-items: flex-end;
|
||
justify-content: space-between;
|
||
overflow: auto;
|
||
}
|
||
|
||
.nav-item {
|
||
@width: 35rem;
|
||
display: flex;
|
||
align-items: center;
|
||
flex-direction: column;
|
||
flex-shrink: 0;
|
||
width: 17vw;
|
||
|
||
img {
|
||
width: @width;
|
||
height: @width;
|
||
margin-bottom: 5rem;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.sub-type-notice {
|
||
position: fixed;
|
||
background: rgba(black, .4);
|
||
top: 100rem;
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
padding: 3rem 12rem;
|
||
border-radius: 10rem;
|
||
z-index: 3;
|
||
font-size: 12rem;
|
||
color: white;
|
||
}
|
||
|
||
#slide1-infinite {
|
||
z-index: 1;
|
||
margin-top: 0;
|
||
transition: height, margin-top .3s;
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
</style> |