Browse Source

优化

pull/29/head
zyronon 2 years ago
parent
commit
7d7995ff88
  1. 6
      src/assets/less/custom.less
  2. 14
      src/components/BaseMusic.vue
  3. 10
      src/components/slide/ItemToolbar.vue
  4. 3
      src/components/slide/SlideVerticalInfinite.vue
  5. 139
      src/pages/home/index.vue
  6. 241
      src/pages/home/slide/Slide1.vue
  7. 155
      src/pages/home/slide/SlideList.vue
  8. 34
      src/pages/slideHooks/InfiniteList.vue
  9. 3
      src/utils/bus.js
  10. 32
      src/utils/hooks/useSlideListItemRender.jsx
  11. 4
      src/utils/mixin.js

6
src/assets/less/custom.less

@ -128,6 +128,12 @@ p { @@ -128,6 +128,12 @@ p {
position: relative;
overflow: hidden;
.slide-infinite {
z-index: 1;
margin-top: 0;
transition: all .3s;
}
.slide-list {
height: 100%;
width: 100%;

14
src/components/BaseMusic.vue

@ -1,18 +1,22 @@ @@ -1,18 +1,22 @@
<template>
<div class="music-wrapper">
<img class="music" :src="props.cover" :style="style" @click.stop="bus.emit('nav','/home/music')">
<img class="music" :src="props.item.music?.cover" :style="style"
@click.stop="bus.emit(EVENT_KEY.NAV,{path:'/home/music',query:{id:props.item.id}})">
</div>
</template>
<script setup>
import {computed, inject} from "vue";
import bus from "../utils/bus";
import bus, {EVENT_KEY} from "@/utils/bus";
const props = defineProps({
cover: {
type: String,
default: ''
item: {
type: Object,
default: () => {
return {}
}
},
})
const isPlaying = inject('isPlaying')
const style = computed(() => {

10
src/components/slide/ItemToolbar.vue

@ -45,6 +45,7 @@ function attention(e) { @@ -45,6 +45,7 @@ function attention(e) {
}
function showComments() {
// emit('showComments')
bus.emit(EVENT_KEY.OPEN_COMMENTS, props.item.id)
}
@ -54,14 +55,13 @@ function showComments() { @@ -54,14 +55,13 @@ function showComments() {
<div class="toolbar mb1r">
<div class="avatar-ctn mb3r">
<img class="avatar" :src="props.item.author.avatar" alt=""
@click.stop="$emit('goUserInfo')">
@click.stop="bus.emit(EVENT_KEY.GO_USERINFO)">
<transition name="fade">
<div v-if="!props.item.isAttention" @click.stop="attention" class="options">
<img class="no" src="../../assets/img/icon/add-light.png" alt="">
<img class="yes" src="../../assets/img/icon/ok-red.png" alt="">
</div>
</transition>
</div>
<div class="love mb2r" @click.stop="loved($event)">
<div>
@ -80,11 +80,11 @@ function showComments() { @@ -80,11 +80,11 @@ function showComments() {
<img v-else src="@/assets/img/icon/components/video/star.png" alt="" class="message-image">
<span>{{ Utils.formatNumber(props.item.comment_count) }}</span>
</div>
<div v-if="!isMy" class="share mb2r" @click.stop="$emit('showShare')">
<div v-if="!isMy" class="share mb2r" @click.stop="bus.emit(EVENT_KEY.SHOW_SHARE)">
<img src="../../assets/img/icon/share-white-full.png" alt="" class="share-image">
<span>{{ Utils.formatNumber(props.item.share_count) }}</span>
</div>
<div v-else class="share mb2r" @click.stop="$emit('showShare')">
<div v-else class="share mb2r" @click.stop="bus.emit(EVENT_KEY.SHOW_SHARE)">
<img src="../../assets/img/icon/menu-white.png" alt="" class="share-image">
</div>
<!-- <BaseMusic-->
@ -92,7 +92,7 @@ function showComments() { @@ -92,7 +92,7 @@ function showComments() {
<!-- @click.stop="$nav('/home/music')"-->
<!-- /> -->
<BaseMusic
:cover="props.item.music.cover"
:item="props.item"
/>
</div>
</template>

3
src/components/slide/SlideVerticalInfinite.vue

@ -245,14 +245,13 @@ function touchEnd(e) { @@ -245,14 +245,13 @@ function touchEnd(e) {
slideReset(wrapperEl.value, state, SlideType.VERTICAL, emit)
}
function canNext(isNext) {
return !((state.localIndex === 0 && !isNext) || (state.localIndex === props.list.length - 1 && isNext));
}
</script>
<template>
<div class="slide v-infinite">
<div class="slide slide-infinite">
<div class="slide-list flex-direction-column"
ref="wrapperEl"
@click="null"

139
src/pages/home/index.vue

@ -15,69 +15,7 @@ @@ -15,69 +15,7 @@
id="home-index"
:change-active-index-use-anim="false"
v-model:index="state.navIndex">
<SlideItem id="slide0">
<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>
<Loading v-if="state.slide0.loading && state.slide0.list.length === 0"/>
<SlideVerticalInfinite
@touchstart="pageClick"
v-love="'slide0-infinite'"
:style="{background: 'black',marginTop:state.subTypeVisible?state.subTypeHeight:0}"
name="main"
id="slide0-infinite"
v-model:index="state.slide0.index"
:render="render"
:list="state.slide0.list"
:position="{
baseIndex:0,
navIndex:0,
}"
@loadMore="loadSlide1More"
@refresh="() => getSlide0Data(true)"
/>
</SlideItem>
<Slide1 :cbs="p" :active="state.navIndex === 0 && state.baseIndex === 0"/>
<SlideItem>
<Community/>
</SlideItem>
@ -205,6 +143,7 @@ import UserPanel from "@/components/UserPanel.vue"; @@ -205,6 +143,7 @@ import UserPanel from "@/components/UserPanel.vue";
import Community from "@/pages/home/components/Community.vue";
import Shop from "@/pages/home/components/Shop.vue";
import Loading from "@/components/Loading.vue";
import Slide1 from "@/pages/home/slide/Slide1.vue";
const nav = useNav()
@ -212,6 +151,12 @@ function stop(e) { @@ -212,6 +151,12 @@ function stop(e) {
e.stopPropagation()
}
const p = {
onGoUserInfo() {
console.log('parent-goUserInfo')
}
}
const store = useStore()
const friends = computed(() => store.state.friends)
const bodyHeight = computed(() => store.state.bodyHeight)
@ -311,7 +256,6 @@ watch( @@ -311,7 +256,6 @@ watch(
() => state.navIndex,
(newVal, oldValue) => {
if (newVal === 0 && state.slide0.list.length === 0) {
return getSlide0Data()
}
if (newVal === 4 && state.slide4.list.length === 0) {
return getSlide4Data()
@ -340,29 +284,6 @@ watch( @@ -340,29 +284,6 @@ watch(
})
function loadSlide1More() {
if (!state.loading) {
state.slide0.pageNo++
getSlide0Data()
}
}
async function getSlide0Data(refresh = false) {
if (state.slide0.loading) return
state.slide0.loading = true
let res = await api.videos.recommended({pageNo: refresh ? 0 : state.slide0.pageNo, pageSize: state.slide0.pageSize})
console.log('getSlide0Data-', 'refresh', refresh, res)
state.slide0.loading = false
if (res.code === 200) {
state.slide0.totalSize = res.data.total
if (refresh) {
state.slide0.list = []
}
state.slide0.list = state.slide0.list.concat(res.data.list)
} else {
state.slide0.pageNo--
}
}
async function getSlide4Data(refresh = false) {
if (state.slide4.loading) return
@ -388,24 +309,6 @@ function loadSlide4More() { @@ -388,24 +309,6 @@ function loadSlide4More() {
}
}
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()
@ -423,23 +326,7 @@ function end() { @@ -423,23 +326,7 @@ function end() {
}
onMounted(() => {
// getData()
getSlide0Data()
bus.on(EVENT_KEY.SINGLE_CLICK, () => {
let itemIndex = -1
if (state.navIndex === 4) {
itemIndex = state.slide4.index
}
if (state.navIndex === 0) {
itemIndex = state.slide0.index
}
bus.emit(EVENT_KEY.SINGLE_CLICK_BROADCAST, {
baseIndex: state.baseIndex,
navIndex: state.navIndex,
itemIndex,
type: EVENT_KEY.ITEM_TOGGLE
})
})
bus.on('update:item', val => {
const {baseIndex, navIndex, itemIndex} = val.position
if (navIndex === 5) {
@ -457,7 +344,13 @@ onMounted(() => { @@ -457,7 +344,13 @@ onMounted(() => {
bus.emit(EVENT_KEY.EXIT_FULLSCREEN)
state.commentVisible = false
})
bus.on('nav', path => nav(path))
bus.on(EVENT_KEY.SHOW_SHARE, (e) => {
state.isSharing = true
})
bus.on(EVENT_KEY.NAV, ({path, query}) => nav(path, query))
bus.on(EVENT_KEY.GO_USERINFO, () => {
state.baseIndex = 1
})
})
onUnmounted(() => {
bus.offAll()

241
src/pages/home/slide/Slide1.vue

@ -0,0 +1,241 @@ @@ -0,0 +1,241 @@
<template>
<SlideItem id="slide0">
<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>
<SlideList
:style="{background: 'black',marginTop:state.subTypeVisible?state.subTypeHeight:0}"
:api="api.videos.recommended"
@touchstart="pageClick"
html-id="slide0-list"
/>
</SlideItem>
</template>
<script setup lang="jsx">
import SlideItem from '@/components/slide/SlideItem.vue'
import {onMounted, onUnmounted, reactive, ref, watch} from "vue";
import bus, {EVENT_KEY} from "@/utils/bus";
import Utils from "@/utils";
import api from "@/api";
import Loading from "@/components/Loading.vue";
import {useSlideListItemRender} from "@/utils/hooks/useSlideListItemRender";
import SlideList from './SlideList.vue';
const props = defineProps({
cbs: {
type: Object,
default() {
return {}
}
},
active: {
type: Boolean,
default: false
}
})
const emit = defineEmits([
'update:item',
'goUserInfo',
'showComments',
'showShare',
'goMusic',
])
function stop(e) {
e.stopPropagation()
}
const p = {
onShowComments() {
console.log('onShowComments')
}
}
watch(
() => props.active,
(newVal, oldVal) => {
console.log('newVal', newVal, 'oldVal', oldVal)
if (newVal === false) {
bus.emit(EVENT_KEY.SINGLE_CLICK_BROADCAST, {
baseIndex: 0,
navIndex: 0,
itemIndex: state.index,
type: EVENT_KEY.ITEM_STOP
})
} else {
bus.emit(EVENT_KEY.SINGLE_CLICK_BROADCAST, {
baseIndex: 0,
navIndex: 0,
itemIndex: state.index,
type: EVENT_KEY.ITEM_PLAY
})
}
})
const render = useSlideListItemRender({...props.cbs, ...p})
const subTypeRef = ref(null)
const listRef = ref(null)
const state = reactive({
loading: false,
index: 0,
subType: -1,
subTypeVisible: false,
subTypeHeight: '0',
//zindexslidesubType.
subTypeIsTop: false,
})
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 dislike() {
listRef.value.dislike(state.list[1])
state.list[state.index] = state.list[1]
Utils.$notice('操作成功,将减少此类视频的推荐')
}
function end() {
// this.$notice('')
}
onMounted(() => {
// getData()
})
onUnmounted(() => {
})
</script>
<style scoped lang="less">
@import "@/assets/less/index";
#slide0 {
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;
}
#slide0-infinite {
z-index: 1;
margin-top: 0;
transition: all .3s;
}
}
</style>

155
src/pages/home/slide/SlideList.vue

@ -0,0 +1,155 @@ @@ -0,0 +1,155 @@
<template>
<Loading v-if="state.loading && state.list.length === 0"/>
<SlideVerticalInfinite
ref="listRef"
v-love="htmlId"
name="main"
:id="htmlId"
v-model:index="state.index"
:render="render"
:list="state.list"
:position="{
baseIndex:0,
navIndex:0,
}"
@loadMore="loadMore"
@refresh="() => getData(true)"
/>
</template>
<script setup lang="jsx">
import SlideVerticalInfinite from '@/components/slide/SlideVerticalInfinite.vue'
import {onMounted, onUnmounted, reactive, ref, watch} from "vue";
import bus, {EVENT_KEY} from "@/utils/bus";
import Utils from "@/utils";
import {useSlideListItemRender} from "@/utils/hooks/useSlideListItemRender";
import Loading from "@/components/Loading.vue";
const props = defineProps({
cbs: {
type: Object,
default() {
return {}
}
},
active: {
type: Boolean,
default: false
},
api: {
type: Function,
default: void 0
},
htmlId: {
type: String,
default: 'guid'
}
})
const emit = defineEmits([
'update:item',
'goUserInfo',
'showComments',
'showShare',
'goMusic',
])
function stop(e) {
e.stopPropagation()
}
const p = {
onShowComments() {
console.log('onShowComments')
}
}
watch(
() => props.active,
(newVal, oldVal) => {
console.log('newVal', newVal, 'oldVal', oldVal)
if (newVal === false) {
bus.emit(EVENT_KEY.SINGLE_CLICK_BROADCAST, {
baseIndex: 0,
navIndex: 0,
itemIndex: state.index,
type: EVENT_KEY.ITEM_STOP
})
} else {
bus.emit(EVENT_KEY.SINGLE_CLICK_BROADCAST, {
baseIndex: 0,
navIndex: 0,
itemIndex: state.index,
type: EVENT_KEY.ITEM_PLAY
})
}
})
const render = useSlideListItemRender({...props.cbs, ...p})
const subTypeRef = ref(null)
const listRef = ref(null)
const state = reactive({
loading: false,
index: 0,
list: [
// {
// type: 'user',
// src: `http://douyin.ttentau.top/0.mp4?vframe/jpg/offset/0/w/${document.body.clientWidth}`
// },
],
totalSize: 0,
pageSize: 10,
pageNo: 0,
})
function loadMore() {
if (!state.loading) {
state.pageNo++
getData()
}
}
async function getData(refresh = false) {
if (state.loading) return
state.loading = true
let res = await props.api({pageNo: refresh ? 0 : state.pageNo, pageSize: state.pageSize})
console.log('getSlide0Data-', 'refresh', refresh, res)
state.loading = false
if (res.code === 200) {
state.totalSize = res.data.total
if (refresh) {
state.list = []
}
state.list = state.list.concat(res.data.list)
} else {
state.pageNo--
}
}
function dislike() {
listRef.value.dislike(state.list[1])
state.list[state.index] = state.list[1]
Utils.$notice('操作成功,将减少此类视频的推荐')
}
function end() {
// this.$notice('')
}
function click(htmlId) {
if (htmlId !== props.htmlId) return
bus.emit(EVENT_KEY.SINGLE_CLICK_BROADCAST, {
baseIndex: 0,
navIndex: 0,
itemIndex: state.index,
type: EVENT_KEY.ITEM_TOGGLE
})
}
onMounted(() => {
// getData()
getData()
bus.on(EVENT_KEY.SINGLE_CLICK, click)
})
onUnmounted(() => {
bus.off(EVENT_KEY.SINGLE_CLICK, click)
})
</script>

34
src/pages/slideHooks/InfiniteList.vue

@ -39,7 +39,7 @@ const bodyHeight = computed(() => store.state.bodyHeight) @@ -39,7 +39,7 @@ const bodyHeight = computed(() => store.state.bodyHeight)
const bodyWidth = computed(() => store.state.bodyWidth)
const subTypeRef = ref(null)
const state = reactive( {
const state = reactive({
baseIndex: 0,
navIndex: 4,
itemIndex: 0,
@ -125,38 +125,6 @@ function end() { @@ -125,38 +125,6 @@ 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)
}

3
src/utils/bus.js

@ -57,4 +57,7 @@ export const EVENT_KEY = { @@ -57,4 +57,7 @@ export const EVENT_KEY = {
ITEM_TOGGLE: 'ITEM_TOGGLE',
ITEM_PLAY: 'ITEM_PLAY',
ITEM_STOP: 'ITEM_STOP',
NAV: 'NAV',
GO_USERINFO: 'GO_USERINFO',
SHOW_SHARE: 'SHOW_SHARE',
}

32
src/utils/hooks/useSlideListItemRender.jsx

@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
import SlideAlbum from "@/components/slide/SlideAlbum.vue";
import SlideUser from "@/components/slide/SlideUser.vue";
import BVideo from "@/components/slide/BVideo.vue";
export function useSlideListItemRender(props) {
return 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 {...props}/>
}
if (item.type === 'send-video') {
node = <video src={item.src} style="height:100%;"/>
}
// onGoUserInfo={() => cb('onGoUserInfo')}
if (item.type === 'recommend-video') {
node = <BVideo
isPlay={play}
item={item}
position={{...position, itemIndex}}
{...props}
/>
}
return node
}
}

4
src/utils/mixin.js

@ -151,8 +151,8 @@ export default { @@ -151,8 +151,8 @@ export default {
dbClickTimer = setTimeout(() => isDbClick = false, dbCheckCancelTime);
} else {
clickTimer = setTimeout(() => {
console.log('单击')
bus.emit(EVENT_KEY.SINGLE_CLICK)
console.log('单击', binding.value)
bus.emit(EVENT_KEY.SINGLE_CLICK, binding.value)
}, checkTime);
}
lastClickTime = nowTime;

Loading…
Cancel
Save