refactor: optimize the code

This commit is contained in:
zyronon 2024-04-25 17:46:13 +08:00
parent b18664a3a6
commit bdb5651a65
18 changed files with 149 additions and 167 deletions

View File

@ -12,6 +12,10 @@ export function recommendedVideo(params?: any, data?: any) {
return request({ url: '/video/recommended', method: 'get', params, data })
}
export function recommendedLongVideo(params?: any, data?: any) {
return request({ url: '/video/long/recommended/', method: 'get', params, data })
}
export function myVideo(params?: any, data?: any) {
return request({ url: '/video/my', method: 'get', params, data })
}

View File

@ -16,7 +16,7 @@
<div class="num">{{ _formatNumber(comments.length) }}条评论</div>
<div class="right">
<Icon icon="prime:arrow-up-right-and-arrow-down-left-from-center" @click.stop="_no" />
<Icon icon="ic:round-close" @click.stop="cancel" />
<Icon icon="ic:round-close" v-click="cancel" />
</div>
</div>
</template>
@ -328,10 +328,8 @@ export default {
@import '../assets/less/index';
.title {
z-index: 2;
position: fixed;
left: 0;
right: 0;
box-sizing: border-box;
width: 100%;
height: 40rem;
padding: 0 15rem;
background: white;
@ -371,15 +369,12 @@ export default {
.comment {
color: #000;
width: 100%;
height: v-bind(height);
background: #fff;
z-index: 5;
border-radius: 10rem 10rem 0 0;
.wrapper {
width: 100%;
position: relative;
padding-top: 40rem;
padding-bottom: 60rem;
}
@ -601,7 +596,7 @@ export default {
}
.auto-input {
width: calc(100% - 180rem);
width: calc(100% - 160rem);
}
}

View File

@ -61,5 +61,3 @@ async function getData(refresh = false) {
onMounted(getData)
</script>
<style scoped lang="less"></style>

View File

@ -7,7 +7,7 @@
:show-heng-gang="false"
:touch-moved="false"
maskMode="light"
height="370rem"
height="320rem"
mode="dark"
>
<div class="share">
@ -227,6 +227,7 @@ export default {
.share {
width: 100%;
height: 100%;
background: black;
border-radius: 10px 10px 0 0;
color: white;

View File

@ -1,20 +1,11 @@
<template>
<!-- <transition name="from-bottom"> -->
<transition
@before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter"
@before-leave="beforeLeave"
@leave="leave"
@after-leave="afterLeave"
:css="false"
>
<!-- <transition> -->
<Transition name="test">
<div
ref="dialog"
class="FromBottomDialog"
v-if="modelValue"
:class="[mode, showHengGang ? '' : 'no-heng-gang']"
:style="{ 'max-height': height }"
@touchstart="start"
@touchmove="move"
@touchend="end"
@ -23,9 +14,11 @@
<div class="heng-gang" :class="mode" v-if="showHengGang">
<div class="content"></div>
</div>
<slot></slot>
<div class="wrapper" ref="wrapper">
<slot></slot>
</div>
</div>
</transition>
</Transition>
</template>
<script>
import Dom, { _css } from '../../utils/dom'
@ -106,8 +99,8 @@ export default {
data() {
return {
scroll: 0,
startLocationY: 0,
moveYDistance: 0,
startY: 0,
moveY: 0,
startTime: 0,
pagePosition: null
}
@ -115,76 +108,41 @@ export default {
computed: {},
created() {},
methods: {
beforeEnter(el) {
_css(el, 'transition-duration', `250ms`)
_css(el, 'transform', `translate3d(0,${this.height},0)`)
},
enter(el, done) {
setTimeout(() => {
_css(el, 'transform', `translate3d(0,0,0)`)
}, 0)
setTimeout(() => {
// _css(el, 'transition-duration', `0ms`)
_css(el, 'transform', `none`)
done()
}, 250)
},
afterEnter() {},
beforeLeave(el) {
_css(el, 'transition-duration', `250ms`)
_css(el, 'transform', `translate3d(0,0,0)`)
},
leave(el, done) {
//ref
let maxHeight = new Dom('.FromBottomDialog').css('max-height')
_css(el, 'transform', `translate3d(0,${maxHeight},0)`)
setTimeout(done, 250)
},
afterLeave() {},
hide(val = false) {
this.$emit('update:modelValue', val)
this.$emit('cancel')
},
start(e) {
if (this.$refs.dialog.scrollTop !== 0) return
this.startLocationY = e.touches[0].pageY
if (this.$refs.wrapper.scrollTop !== 0) return
this.startY = e.touches[0].pageY
this.startTime = Date.now()
_css(this.$refs.dialog, 'transition-duration', `0ms`)
},
move(e) {
if (this.$refs.dialog.scrollTop !== 0) return
this.moveYDistance = e.touches[0].pageY - this.startLocationY
if (this.moveYDistance > 0) {
if (this.$refs.wrapper.scrollTop !== 0) return
this.moveY = e.touches[0].pageY - this.startY
if (this.moveY > 0) {
bus.emit(EVENT_KEY.DIALOG_MOVE, {
tag: this.tag,
e: this.moveYDistance
e: this.moveY
})
_css(this.$refs.dialog, 'transform', `translate3d(0,${this.moveYDistance}px,0)`)
_css(this.$refs.dialog, 'transform', `translate3d(0,${this.moveY}px,0)`)
}
},
end() {
//
if (Date.now() - this.startTime < 150 && Math.abs(this.moveYDistance) < 30) {
return
}
//
if (this.$refs.dialog.scrollTop !== 0) return
//modelValueref
if (!this.$refs.dialog) return
if (Date.now() - this.startTime < 150 && Math.abs(this.moveY) < 30) return
let clientHeight = this.$refs.dialog.clientHeight
_css(this.$refs.dialog, 'transition-duration', `250ms`)
if (Math.abs(this.moveYDistance) > clientHeight / 2) {
_css(this.$refs.dialog, 'transform', `translate3d(0,${clientHeight}px,0)`)
if (Math.abs(this.moveY) > clientHeight / 2) {
_css(this.$refs.dialog, 'transform', `translate3d(0,100%,0)`)
bus.emit(EVENT_KEY.DIALOG_END, { tag: this.tag, isClose: true })
setTimeout(this.hide, 250)
} else {
_css(this.$refs.dialog, 'transform', `translate3d(0,0,0)`)
bus.emit(EVENT_KEY.DIALOG_END, { tag: this.tag, isClose: false })
setTimeout(() => {
_css(this.$refs.dialog, 'transform', 'none')
// _css(this.$refs.dialog, 'transition-duration', `0ms`)
}, 250)
}
this.moveYDistance = 0
}
}
}
@ -193,17 +151,31 @@ export default {
<style scoped lang="less">
@import '../../assets/less/index';
.test-enter-active,
.test-leave-active {
transition-duration: 250ms !important;
}
.test-enter-from,
.test-leave-to {
transform: translate3d(0, 101%, 0) !important;
}
.FromBottomDialog {
z-index: 9;
position: fixed;
width: 100%;
overflow-y: auto;
padding-top: 24rem;
bottom: 0;
left: 0;
box-sizing: border-box;
border-radius: v-bind(borderRadius);
transition: all 0.3s;
border-radius: 15rem 15rem 0 0;
transform: translate3d(0, 0, 0);
overflow: hidden;
display: flex;
height: v-bind(height);
max-height: v-bind(height);
flex-direction: column;
&.dark {
background: var(--main-bg);
@ -231,6 +203,7 @@ export default {
transform: translateY(-24rem);
justify-content: center;
align-items: center;
touch-action: pan-y;
&.dark {
background: var(--main-bg);
@ -262,5 +235,10 @@ export default {
width: 30rem;
}
}
.wrapper {
flex: 1;
overflow: auto;
}
}
</style>

View File

@ -88,7 +88,7 @@ import { Icon } from '@iconify/vue'
import { _css } from '@/utils/dom'
export default {
name: 'BVideo',
name: 'BaseVideo',
components: {
Loading,
ItemToolbar,
@ -178,7 +178,7 @@ export default {
}
},
mounted() {
// console.log('video', this.localItem.id)
// console.log('video', this.localItem.aweme_id)
// console.log(this.commentVisible)
this.height = document.body.clientHeight
this.width = document.body.clientWidth
@ -200,7 +200,7 @@ export default {
video.addEventListener(
e,
() => {
// console.log('eventTester', e, this.item.id)
// console.log('eventTester', e, this.item.aweme_id)
if (e === 'playing') this.loading = false
if (e === 'waiting') {
if (!this.paused && !this.ignoreWaiting) {
@ -285,7 +285,7 @@ export default {
}
},
onOpenComments(id) {
if (id === this.item.id) {
if (id === this.item.aweme_id) {
_css(this.$refs.video, 'transition-duration', `300ms`)
_css(this.$refs.video, 'height', 'calc(var(--vh, 1vh) * 30)')
this.commentVisible = true
@ -306,7 +306,7 @@ export default {
this.pause()
bus.emit(EVENT_KEY.NAV, {
path: '/home/live',
query: { id: this.item.id }
query: { id: this.item.aweme_id }
})
}
} else {

View File

@ -1,8 +1,9 @@
<script setup>
import BaseMusic from '../BaseMusic'
import { _dateFormat, _formatNumber, _updateItem } from '@/utils'
<script setup lang="ts">
import BaseMusic from '../BaseMusic.vue'
import { _dateFormat, _formatNumber, _stopPropagation, _updateItem } from '@/utils'
import bus, { EVENT_KEY } from '@/utils/bus'
import { Icon } from '@iconify/vue'
import { useClick } from '@/utils/hooks/useClick'
const props = defineProps({
item: {
@ -38,14 +39,10 @@ function attention(e) {
}
function showComments() {
console.log('showComments', _dateFormat(Date.now()))
// emit('showComments')
bus.emit(EVENT_KEY.OPEN_COMMENTS, props.item.id)
bus.emit(EVENT_KEY.OPEN_COMMENTS, props.item.aweme_id)
}
function s() {
console.log('ss', _dateFormat(Date.now()))
}
const vClick = useClick()
</script>
<template>
@ -55,45 +52,45 @@ function s() {
class="avatar"
:src="props.item.author.avatar_168x168.url_list[0]"
alt=""
@pointerup="bus.emit(EVENT_KEY.GO_USERINFO)"
v-click="() => bus.emit(EVENT_KEY.GO_USERINFO)"
/>
<transition name="fade">
<div v-if="!props.item.isAttention" @pointerup="attention" class="options">
<div v-if="!props.item.isAttention" v-click="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" @pointerup="loved($event)">
<div class="love mb2r" v-click="loved">
<div>
<img src="../../assets/img/icon/love.svg" class="love-image" v-if="!props.item.isLoved" />
<img src="../../assets/img/icon/loved.svg" class="love-image" v-if="props.item.isLoved" />
</div>
<span>{{ _formatNumber(props.item.statistics.digg_count) }}</span>
</div>
<div class="message mb2r" @pointerup="showComments">
<div class="message mb2r" v-click="showComments">
<Icon icon="mage:message-dots-round-fill" class="icon" style="color: white" />
<span>{{ _formatNumber(props.item.statistics.comment_count) }}</span>
</div>
<!--TODO -->
<div
class="message mb2r"
@pointerup="_updateItem(props, 'isCollect', !props.item.isCollect, emit)"
v-click="() => _updateItem(props, 'isCollect', !props.item.isCollect, emit)"
>
<Icon v-if="props.item.isCollect" icon="ic:round-star" class="icon" style="color: yellow" />
<Icon v-else icon="ic:round-star" class="icon" style="color: white" />
<span>{{ _formatNumber(props.item.statistics.comment_count) }}</span>
</div>
<div v-if="!props.isMy" class="share mb2r" @pointerup="bus.emit(EVENT_KEY.SHOW_SHARE)">
<div v-if="!props.isMy" class="share mb2r" v-click="() => bus.emit(EVENT_KEY.SHOW_SHARE)">
<img src="../../assets/img/icon/share-white-full.png" alt="" class="share-image" />
<span>{{ _formatNumber(props.item.statistics.share_count) }}</span>
</div>
<div v-else class="share mb2r" @pointerup="bus.emit(EVENT_KEY.SHOW_SHARE)">
<div v-else class="share mb2r" v-click="() => bus.emit(EVENT_KEY.SHOW_SHARE)">
<img src="../../assets/img/icon/menu-white.png" alt="" class="share-image" />
</div>
<!-- <BaseMusic-->
<!-- :cover="props.item.music.cover"-->
<!-- @pointerup="$nav('/home/music')"-->
<!-- v-click="$nav('/home/music')"-->
<!-- /> -->
<BaseMusic :item="props.item" />
</div>

View File

@ -335,7 +335,6 @@ function canNext(state, isNext) {
<div
class="slide-list flex-direction-column"
ref="slideListEl"
@click="null"
@pointerdown.prevent="touchStart"
@pointermove.prevent="touchMove"
@pointerup.prevent="touchEnd"

View File

@ -7,20 +7,21 @@ import router from './router'
import mixin from './utils/mixin'
import VueLazyload from '@jambonn/vue-lazyload'
import { createPinia } from 'pinia'
import { useClick } from '@/utils/hooks/useClick'
window.isMoved = false
HTMLElement.prototype.addEventListener = new Proxy(HTMLElement.prototype.addEventListener, {
apply(target, ctx, args) {
const eventName = args[0]
const listener = args[1]
// console.log('e', eventName, '')
if (listener instanceof Function && eventName === 'click') {
args[1] = new Proxy(listener, {
apply(target, ctx, args) {
console.log('点击', window.isMoved)
apply(target1, ctx1, args1) {
// console.log('e', args1)
// console.log('click点击', window.isMoved)
if (window.isMoved) return
try {
return target.apply(ctx, args)
return target1.apply(ctx1, args1)
} catch (e) {
console.error(`[proxyPlayerEvent][${eventName}]`, listener, e)
}
@ -31,6 +32,7 @@ HTMLElement.prototype.addEventListener = new Proxy(HTMLElement.prototype.addEven
}
})
const vClick = useClick()
const pinia = createPinia()
const emitter = mitt()
const app = createApp(App)
@ -46,6 +48,7 @@ app.use(VueLazyload, {
app.use(pinia)
app.use(router)
app.mount('#app')
app.directive('click', vClick)
//放到最后才可以使用pinia
startMock()

View File

@ -148,6 +148,20 @@ export async function startMock() {
}
]
})
mock.onGet(/video\/long\/recommended/).reply(async (config) => {
const page = getPage2(config.params)
return [
200,
{
data: {
total: 844,
list: allRecommendVideos.slice(page.offset, page.limit)
},
code: 200,
msg: ''
}
]
})
mock.onGet(/video\/comments/).reply(async (config) => {
const videoIds = [

View File

@ -1,7 +1,7 @@
<script setup>
import { reactive, ref, watch } from 'vue'
import { _checkImgUrl, _duration, _formatNumber, _stopPropagation } from '@/utils'
import { recommendedVideo } from '@/api/videos'
import { recommendedLongVideo, recommendedVideo } from '@/api/videos'
import ScrollList from '@/components/ScrollList.vue'
import { useNav } from '@/utils/hooks/useNav'
@ -79,7 +79,7 @@ const nav = useNav()
<template>
<div class="long-video" @dragstart="(e) => _stopPropagation(e)">
<ScrollList class="Scroll" v-if="state.show" :api="recommendedVideo">
<ScrollList class="Scroll" v-if="state.show" :api="recommendedLongVideo">
<template v-slot="{ list }">
<div class="list">
<div

View File

@ -492,6 +492,9 @@ export default {
_getUserDouyinId,
_checkImgUrl,
_formatNumber,
$nav(path) {
this.$router.push(path)
},
setLoadingFalse() {
this.loadings.loading0 = false
this.loadings.loading1 = false

View File

@ -310,7 +310,7 @@
</div>
</template>
<div class="btn-wrapper">
<div class="btn" :class="selectFriends ? 'primary' : ''">发起聊天</div>
<div class="btn primary">发起群聊{{ selectFriends ? `(${selectFriends})` : '' }}</div>
</div>
</div>
<div class="joined-chat-wrapper" v-show="data.showJoinedChat">
@ -615,21 +615,17 @@ async function loadRecommendData() {
display: flex;
align-items: center;
justify-content: center;
padding-bottom: 20rem;
.btn {
margin-bottom: 20rem;
width: calc(100% - 40rem);
height: 40rem;
display: flex;
align-items: center;
font-size: 14rem;
justify-content: center;
background: #3f445c;
border-radius: 2rem;
&.primary {
background: var(--primary-btn-color);
}
border-radius: 10rem;
background: var(--primary-btn-color);
}
}

View File

@ -1,53 +1,18 @@
<template>
<div class="body">
test
<canvas ref="canvasEl"></canvas>
<!-- <video ref="videoEl" :src="v1" controls></video>-->
<Slide4 :active="state.navIndex === 4 && state.baseIndex === 1" />
</div>
</template>
<script setup lang="ts">
import { onMounted, ref } from 'vue'
import { reactive } from 'vue'
import Slide4 from '@/pages/home/slide/Slide4.vue'
defineOptions({
name: 'Test'
})
const canvasEl = ref()
const videoEl = ref()
onMounted(() => {
console.log(canvasEl.value, videoEl.value)
let ctx = canvasEl.value.getContext('2d')
videoEl.value.addEventListener('play', () => {
console.log(videoEl.value.videoWidth)
console.log(videoEl.value.videoHeight)
// ctx.drawImage(videoEl.value, 0, 0, videoEl.value.videoWidth / 20, videoEl.value.videoHeight / 20);
ctx.drawImage(videoEl.value, 0, 0, videoEl.value.naturalWidth, videoEl.value.naturalHeight)
// ctx.drawImage(videoEl.value, 0, 0, 500, 500);
})
const state = reactive({
navIndex: 4,
baseIndex: 1
})
</script>
<style scoped lang="less">
.body {
display: flex;
align-items: center;
justify-content: center;
padding: 0;
margin: 0;
height: calc(var(--vh, 1vh) * 100);
width: 100vw;
overflow: hidden;
transform-origin: 0 0;
color: white;
font-size: 14px;
}
video,
canvas {
width: 500px;
height: 500px;
}
.wrapper {
background: black;
overflow: hidden;
}
</style>
<style scoped lang="less"></style>

View File

@ -34,7 +34,7 @@ export default {
this.eventMap = new Map()
},
emit(eventType, val?) {
console.log('emit', eventType, val)
// console.log('emit', eventType, val)
const cbs = this.eventMap.get(eventType)
if (cbs) {
cbs.map((cb) => cb(val))

View File

@ -0,0 +1,18 @@
import { _stopPropagation } from '@/utils'
//解决SlideVerticalInfinite组件每次滑动之后click事件总是要等到2秒之后点击会发触发的bug
//具体原因未知
export function useClick() {
return {
mounted: function (el: HTMLElement, binding: any) {
el.addEventListener('pointerdown', (e) => _stopPropagation(e))
el.addEventListener('pointerup', (e) => {
_stopPropagation(e)
binding.value?.()
})
},
unmounted(el: HTMLDivElement) {
el = null
}
}
}

View File

@ -10,7 +10,7 @@ import BaseButton from '../components/BaseButton.vue'
import CONST_VAR from './const_var'
import Dom from './dom'
import bus, { EVENT_KEY } from './bus'
import { random } from '@/utils'
import { _stopPropagation, random } from '@/utils'
import { Icon } from '@iconify/vue'
import SlideHorizontal from '@/components/slide/SlideHorizontal.vue'
@ -104,11 +104,13 @@ export default {
}
},
love: {
beforeMount: function (el: HTMLDivElement, binding) {
mounted: function (el: HTMLDivElement, binding) {
let isDbClick = false
let clickTimer = null
let dbClickTimer = null
let lastClickTime = null
let isDown = false
let isMove = false
const checkTime = 200
const dbCheckCancelTime = 500
@ -141,13 +143,22 @@ export default {
dbClickTimer = setTimeout(() => (isDbClick = false), dbCheckCancelTime)
} else {
clickTimer = setTimeout(() => {
console.log('单击', binding.value)
// console.log('单击', binding.value)
bus.emit(EVENT_KEY.SINGLE_CLICK, binding.value)
}, checkTime)
}
lastClickTime = nowTime
}
el.addEventListener('click', check)
const up = (e) => {
if (!isDown) return
if (!isMove) check(e)
isMove = isDown = false
}
el.addEventListener('pointerdown', () => (isDown = true))
el.addEventListener('pointermove', () => isDown && (isMove = true))
el.addEventListener('pointerup', up)
}
}
}

View File

@ -79,7 +79,7 @@ function canNext(state, isNext) {
* @param state
*/
export function slideTouchStart(e, el, state) {
// console.log('e', e, state.name)
// console.log('start', state.name)
if (!checkEvent(e)) return
_css(el, 'transition-duration', `0ms`)
//记录起点坐标用于move事件计算移动距离
@ -107,9 +107,9 @@ export function slideTouchMove(
notNextCb = null,
slideOtherDirectionCb = null
) {
console.log('move', state.name)
if (!checkEvent(e)) return
if (!state.isDown) return
// console.log('move', state.name)
//计算移动距离
state.move.x = e.touches[0].pageX - state.start.x
@ -174,15 +174,15 @@ export function slideTouchMove(
export function slideTouchEnd(e, state, canNextCb = null, nextCb = null, notNextCb = null) {
if (!checkEvent(e)) return
if (!state.isDown) return
const isHorizontal = state.type === SlideType.HORIZONTAL
const isNext = isHorizontal ? state.move.x < 0 : state.move.y < 0
// console.log('end', state.name)
if (state.next) {
const isHorizontal = state.type === SlideType.HORIZONTAL
const isNext = isHorizontal ? state.move.x < 0 : state.move.y < 0
//同move事件
if (!canNextCb) canNextCb = canNext
if (canNextCb(state, isNext)) {
//能滑动,那就把事件捕获,不能给父组件处理
//2024-04-25换成pointer事件之后不能捕获了需要让父组件重置自己的isDown不然PC上move事件会一直触发
// _stopPropagation(e)
//结合时间、距离来判断是否成功滑动