douyin/src/pages/home/index.vue

461 lines
13 KiB
Vue

<template>
<div class="test-slide-wrapper" id="home-index">
<SlideHorizontal name="first" v-model:index="state.baseIndex">
<SlideItem class="sidebar">
<div class="header">
<div class="left">下午好</div>
<div class="right" @click="nav('/home/live')">
<Icon icon="iconamoon:scanner" />
<span>扫一扫</span>
</div>
</div>
<div class="card">
<div class="header">
<div class="left">常用小程序</div>
<div class="right">
<span>全部</span>
<Icon icon="icon-park-outline:right" />
</div>
</div>
<div class="content">
<div class="item" @click="_no">
<img
class="xcx"
src="https://lf3-static.bytednsdoc.com/obj/eden-cn/pipieh7nupabozups/toutiao_web_pc/tt-icon.png"
alt=""
/>
<span>今日头条</span>
</div>
<div class="item" @click="_no">
<img
class="xcx"
src="https://gd-hbimg.huaban.com/65130a3e6a139530bb03bd118e21a2603af7df4e1303b-OOzcBu_fw658webp"
alt=""
/>
<span>西瓜视频</span>
</div>
</div>
</div>
<div class="card">
<div class="header">
<div class="left">最近常看</div>
<div class="right">
<span>全部</span>
<Icon icon="icon-park-outline:right" />
</div>
</div>
<div class="content">
<div class="item avatar" @click="_no" :key="i" v-for="i in 6">
<img
src="https://img.tol.vip/avatar/WEIXIN/3aSuTGYTzjHvcHy0y0tH1eiShKRk9Sgd.jpg?_upt=de4a5c251709635127"
/>
<span>随机名字</span>
</div>
</div>
</div>
<div class="card">
<div class="header">
<div class="left">常用功能</div>
<div class="right"></div>
</div>
<div class="content">
<div class="item" @click="_no">
<Icon icon="ion:wallet-outline" />
<span>我的钱包</span>
</div>
<div class="item" @click="_no">
<Icon icon="mingcute:coupon-line" />
<span>券包</span>
</div>
<div class="item" @click="_no">
<Icon icon="icon-park-outline:bytedance-applets" />
<span>小程序</span>
</div>
<div class="item" @click="_no">
<Icon icon="solar:history-linear" />
<span>观看历史</span>
</div>
<div class="item" @click="_no">
<Icon icon="fluent:content-settings-24-regular" />
<span>内容偏好</span>
</div>
<div class="item" @click="_no">
<Icon icon="iconoir:cloud-download" />
<span>离线模式</span>
</div>
<div class="item" @click="_no">
<Icon icon="ep:setting" />
<span>设置</span>
</div>
<div class="item" @click="_no">
<Icon icon="icon-park-outline:baggage-delay" />
<span>稍后再看</span>
</div>
</div>
</div>
</SlideItem>
<SlideItem>
<IndicatorHome
v-if="!state.fullScreen"
:loading="baseStore.loading"
name="second"
@showSlidebar="state.baseIndex = 0"
v-model:index="state.navIndex"
/>
<SlideHorizontal
class="first-horizontal-item"
name="second"
:change-active-index-use-anim="false"
v-model:index="state.navIndex"
>
<!-- <SlideItem></SlideItem>-->
<Slide0 :active="state.navIndex === 0 && state.baseIndex === 1" />
<SlideItem>
<LongVideo :active="state.navIndex === 1 && state.baseIndex === 1" />
</SlideItem>
<!-- <SlideItem></SlideItem>-->
<Slide2 :active="state.navIndex === 2 && state.baseIndex === 1" />
<SlideItem>
<Community :active="state.navIndex === 3 && state.baseIndex === 1" />
</SlideItem>
<Slide4 :active="state.navIndex === 4 && state.baseIndex === 1" />
</SlideHorizontal>
<BaseFooter v-bind:init-tab="1" />
<BaseMask
v-if="state.baseIndex === 0"
@click="state.baseIndex = 1"
mode="white"
style="position: absolute"
/>
</SlideItem>
<SlideItem>
<UserPanel
ref="uploader"
v-model:currentItem="state.currentItem"
:active="state.baseIndex === 2"
@toggleCanMove="(e) => (state.canMove = e)"
@back="state.baseIndex = 1"
@showFollowSetting="state.showFollowSetting = true"
@showFollowSetting2="state.showFollowSetting2 = true"
/>
</SlideItem>
</SlideHorizontal>
<Comment
page-id="home-index"
:video-id="state.currentItem.aweme_id"
v-model="state.commentVisible"
@close="closeComments"
/>
<Share
v-model="state.isSharing"
ref="share"
page-id="home-index"
@dislike="dislike"
:item="state.currentItem"
:videoId="state.recommendList[state.itemIndex]?.id"
:canDownload="state.recommendList[state.itemIndex]?.canDownload"
@play-feedback="state.showPlayFeedback = true"
@shareToFriend="delayShowDialog(() => (state.shareToFriend = true))"
@showDouyinCode="state.showDouyinCode = true"
@download="state.shareType = 9"
/>
<PlayFeedback v-model="state.showPlayFeedback" />
<DouyinCode :item="state.currentItem" v-model="state.showDouyinCode" />
<ShareTo
v-model:type="state.shareType"
:videoId="state.recommendList[state.itemIndex]?.id"
:canDownload="state.recommendList[state.itemIndex]?.canDownload"
/>
<FollowSetting
v-model:currentItem="state.currentItem"
@showChangeNote="delayShowDialog((e) => (state.showChangeNote = true))"
@showBlockDialog="delayShowDialog((e) => (state.showBlockDialog = true))"
@showShare="delayShowDialog((e) => (state.isSharing = true))"
v-model="state.showFollowSetting"
/>
<FollowSetting2
v-model:currentItem="state.currentItem"
@cancelFollow="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="tsx">
import SlideHorizontal from '@/components/slide/SlideHorizontal.vue'
import SlideItem from '@/components/slide/SlideItem.vue'
import Comment from '../../components/Comment.vue'
import Share from '../../components/Share.vue'
import IndicatorHome from './components/IndicatorHome.vue'
import { onActivated, onDeactivated, onMounted, onUnmounted, reactive, ref } from 'vue'
import bus, { EVENT_KEY } from '../../utils/bus'
import { useNav } from '@/utils/hooks/useNav'
import PlayFeedback from '@/pages/home/components/PlayFeedback.vue'
import ShareTo from '@/pages/home/components/ShareTo.vue'
import DouyinCode from '../../components/DouyinCode.vue'
import FollowSetting from '@/pages/home/components/FollowSetting.vue'
import BlockDialog from '../message/components/BlockDialog.vue'
import Search from '../../components/Search.vue'
import ConfirmDialog from '../../components/dialog/ConfirmDialog.vue'
import FollowSetting2 from '@/pages/home/components/FollowSetting2.vue'
import ShareToFriend from '@/pages/home/components/ShareToFriend.vue'
import UserPanel from '@/components/UserPanel.vue'
import Community from '@/pages/home/slide/Community.vue'
import Slide0 from '@/pages/home/slide/Slide0.vue'
import Slide2 from '@/pages/home/slide/Slide2.vue'
import Slide4 from '@/pages/home/slide/Slide4.vue'
import { DefaultUser } from '@/utils/const_var'
import { _no } from '@/utils'
import LongVideo from '@/pages/home/slide/LongVideo.vue'
import { useBaseStore } from '@/store/pinia'
const nav = useNav()
const baseStore = useBaseStore()
const uploader = ref()
const state = reactive({
active: true,
baseIndex: 1,
navIndex: 4,
itemIndex: 0,
test: '',
recommendList: [],
isSharing: false,
canMove: true,
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,
currentItem: {
aweme_id: '',
author: DefaultUser,
isRequest: false,
aweme_list: []
}
})
function delayShowDialog(cb: Function) {
setTimeout(cb, 400)
}
function setCurrentItem(item) {
if (!state.active) return
// console.log('sss',item,state.baseIndex)
if (state.baseIndex !== 1) return
if (state.currentItem.author.uid !== item.author.uid) {
state.currentItem = {
...item,
isRequest: false,
aweme_list: []
}
}
// console.log('item', item)
}
onMounted(() => {
bus.on(EVENT_KEY.ENTER_FULLSCREEN, () => {
if (!state.active) return
state.fullScreen = true
})
bus.on(EVENT_KEY.EXIT_FULLSCREEN, () => {
if (!state.active) return
state.fullScreen = false
})
bus.on(EVENT_KEY.OPEN_COMMENTS, () => {
if (!state.active) return
bus.emit(EVENT_KEY.ENTER_FULLSCREEN)
state.commentVisible = true
})
bus.on(EVENT_KEY.CLOSE_COMMENTS, () => {
if (!state.active) return
bus.emit(EVENT_KEY.EXIT_FULLSCREEN)
state.commentVisible = false
})
bus.on(EVENT_KEY.SHOW_SHARE, () => {
if (!state.active) return
state.isSharing = true
})
bus.on(EVENT_KEY.NAV, ({ path, query }) => {
if (!state.active) return
nav(path, query)
})
bus.on(EVENT_KEY.GO_USERINFO, () => {
if (!state.active) return
state.baseIndex = 2
})
bus.on(EVENT_KEY.CURRENT_ITEM, setCurrentItem)
})
onUnmounted(() => {
bus.offAll()
})
onActivated(() => {
state.active = true
bus.emit(EVENT_KEY.TOGGLE_CURRENT_VIDEO)
})
onDeactivated(() => {
state.active = false
bus.emit(EVENT_KEY.TOGGLE_CURRENT_VIDEO)
})
function closeComments() {
bus.emit(EVENT_KEY.CLOSE_COMMENTS)
}
function dislike() {
// listRef.value.dislike(state.list[1])
// state.list[state.index] = state.list[1]
// _notice('操作成功,将减少此类视频的推荐')
}
</script>
<style scoped lang="less">
.test-slide-wrapper {
font-size: 14rem;
width: 100%;
height: 100%;
background: black;
overflow: hidden;
.sidebar {
touch-action: pan-y;
width: 80%;
height: calc(var(--vh, 1vh) * 100);
overflow: auto;
background: rgb(22, 22, 22);
padding: 10rem;
padding-bottom: 20rem;
box-sizing: border-box;
& > .header {
font-size: 16rem;
display: flex;
color: white;
justify-content: space-between;
align-items: center;
.right {
border-radius: 20rem;
padding: 8rem 15rem;
background: rgb(36, 36, 36);
display: flex;
align-items: center;
font-size: 14rem;
gap: 10rem;
svg {
font-size: 18rem;
}
}
}
.card {
margin-top: 10rem;
border-radius: 12rem;
padding: 15rem;
background: rgb(29, 29, 29);
.header {
margin-bottom: 8rem;
font-size: 14rem;
display: flex;
color: white;
justify-content: space-between;
align-items: center;
.right {
display: flex;
align-items: center;
font-size: 12rem;
gap: 4rem;
color: gray;
svg {
font-size: 16rem;
}
}
}
.content {
color: white;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
.item {
min-height: 20vw;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-size: 14rem;
gap: 8rem;
svg {
font-size: 28rem;
}
.xcx {
border-radius: 12rem;
width: 50rem;
height: 50rem;
}
}
.avatar {
height: 25vw;
img {
border-radius: 50%;
width: 50rem;
}
}
}
}
}
.slide-content {
width: 100%;
height: 100%;
}
}
.first-horizontal-item {
//width: 90vw;
//height: 80vh;
width: 100%;
height: calc(var(--vh, 1vh) * 100 - var(--footer-height)) !important;
overflow: hidden;
border-radius: 10rem;
}
</style>