Files
xdd-uniapp-new/pkg-video/views/watch.vue
T

370 lines
11 KiB
Vue

<template>
<view class="pkg-video-watch" v-if="ready">
<cover-view class="fixed-header flex ai-start">
<cover-view class="bold">推荐</cover-view>
<cover-view class="flex ai-center" style="margin-left: 100rpx" @click="navToCity">
<cover-view>{{ cityName }}</cover-view>
<cover-image style="width: 48rpx;height: 48rpx" :src="webUrl+'/20240113230523321737.png'" mode="scaleToFill"/>
</cover-view>
</cover-view>
<swiper style="height:100%" vertical @change="onChange">
<swiper-item v-for="(item,index) in list" :key="index">
<view class="item">
<video :id="`video-${index}`" :src="item['video']" loop :controls="false" :show-center-play-btn="false"/>
<cover-view class="btn-play flex jc-center ai-center" @click="controlVideo">
<cover-image style="width:57rpx;height:65rpx" :src="webUrl+'/20240123093125710999.png'" v-if="showPlay"/>
</cover-view>
</view>
<cover-view class="fixed-footer flex jc-between ai-end"
:style="{'bottom':systemInfo['safeAreaInsets']['bottom']+'px'}" v-if="!showDialog">
<cover-view class="flex ai-center">
<cover-image style="width: 80rpx;height: 80rpx;border-radius: 50%;z-index: 10" :src="item['hotelLogo']"
@click="navToStore(item['hotelId'])"/>
<cover-view class="more-t">{{ item['hotelName'] }}</cover-view>
</cover-view>
<cover-view class="flex ai-center">
<cover-view class="flex flex-col ai-center" style="width:78rpx;margin-right: 16rpx;"
@click="changeLike(item)">
<cover-image style="width: 60rpx;height: 60rpx" :src="webUrl+'/20240113230547221591.png'"
v-if="item['hasLike']"/>
<cover-image style="width: 60rpx;height: 60rpx" :src="webUrl+'/20240113230552152511.png'" v-else/>
<cover-view class="one-t tc">{{ item['likeCount'] }}</cover-view>
</cover-view>
<cover-view class="flex flex-col ai-center" style="width:78rpx;margin-right: 16rpx;"
@click="changeFav(item)">
<cover-image style="width: 60rpx;height: 60rpx" :src="webUrl+'/20240113230535491918.png'"
v-if="item['hasFavorite']"/>
<cover-image style="width: 60rpx;height: 60rpx" :src="webUrl+'/20240113230541207016.png'" v-else/>
<cover-view class="one-t tc">{{ item['favoriteCount'] }}</cover-view>
</cover-view>
<cover-view class="flex flex-col ai-center" style="width:78rpx" @click="showDialog=true">
<cover-image style="width: 60rpx;height: 60rpx" :src="webUrl+'/20240113230529202260.png'"/>
<cover-view class="one-t tc">{{ item['replyCount'] }}</cover-view>
</cover-view>
</cover-view>
</cover-view>
</swiper-item>
</swiper>
<u-popup :show="showDialog" :round="10" mode="bottom" overlay overlayOpacity="0"
closeOnClickOverlay
@close="dialogClose" @open="dialogOpen">
<view style="z-index: 100">
<cover-view class="tc" style="padding: 20rpx 0 40rpx;font-size: 28rpx">{{
list[current]['replyCount']
}}条评论
</cover-view>
<scroll-view style="max-height: 740rpx" scroll-y @scrolltolower="fetchReply">
<view class="flex" style="margin: 0 30rpx 30rpx" v-for="(item,index) in replyList" :key="index">
<cover-image class="flex-0" style="width: 64rpx;height: 64rpx;margin-right: 18rpx;border-radius: 50%"
:src="item['userAvatar']"/>
<cover-view>
<cover-view style="color:#999999;font-size: 28rpx">{{ item['userNickname'] }}</cover-view>
<cover-view class="more-t" style="font-size: 32rpx;line-height: 48rpx">{{ item['comment'] }}</cover-view>
<cover-view style="color:#999999;font-size: 28rpx">{{ item['time'] }}</cover-view>
</cover-view>
</view>
</scroll-view>
<view class="flex jc-between ai-center" style="padding: 20rpx;border-top:2rpx solid #DCDCDC;">
<u-input :customStyle="{'border':'none','background': '#F6F6F6'}" v-model="comment"
placeholder="请输入评论..." maxlength="200" shape="circle"/>
<cover-view class="btn-submit flex jc-center ai-center" @click="onSubmit">发布</cover-view>
</view>
</view>
</u-popup>
</view>
</template>
<script>
import {getReplyList, likeVideo, randomList, removeFavoriteVideo, removeLikeVideo, submitReply} from "@/api/video";
import {addVideo} from "@/api/favorite";
import {getCurAddress, getLocation} from "@/utils/common";
export default {
data() {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
systemInfo: null,
ready: false,
cityName: '',
videoId: '',
list: [],
current: 0,
showPlay: false,
currentContext: null,
showDialog: false,
comment: '',
page: 1,
replyList: []
}
},
onLoad(options) {
let that = this
uni.getSystemInfo({
success(res) {
that.systemInfo = res
}
})
that.videoId = options.videoId || ''
const name = options.name
if (name) {
that.cityName = name
that.fetchList()
} else {
that.getMapData()
}
},
onShow() {
this.ready = false
setTimeout(() => {
if (this.cityName) this.fetchList()
}, 1000)
},
methods: {
navToCity() {
uni.redirectTo({url: '/pkg-video/views/city'})
},
navToHome() {
uni.switchTab({url: '/pages/home/index'})
},
navToStore(id) {
uni.navigateTo({url: '/pagesInn/inn/innHome?id=' + id})
},
async getMapData() {
uni.showLoading({
title: '定位中...'
})
const map = await getLocation()
if (map.length > 1) {
const {latitude, longitude} = map[1]
getCurAddress(latitude, longitude, address => {
this.cityName = address.city
this.fetchList()
})
}
},
async fetchList() {
let that = this
let param
if (this.videoId) {
param = {
videoId: this.videoId,
limit: 2
}
} else {
param = {
cityName: this.cityName,
limit: 2
}
}
const res = await randomList(param)
if (res.success) {
res.data?.forEach(item => this.list.push(item))
if (!this.ready && this.list.length === 0) {
uni.showModal({
title: '',
content: '当前城市还没有视频,可以先看看其他城市的喔~',
cancelText: '返回',
cancelColor: '#3A87FC',
confirmText: '选择城市',
confirmColor: '#3A87FC',
success(res) {
if (res.confirm) {
that.navToCity()
} else if (res.cancel) {
that.navToHome()
}
}
})
}
that.ready = true
if (that.list.length > 0) that.handleVideoPlay()
}
},
async changeLike(item) {
const videoId = item['id']
if (item['hasLike']) {
const res = await removeLikeVideo(videoId)
if (res.success) {
item['hasLike'] = false
item['likeCount'] = res.data['likeCount']
}
} else {
const res = await likeVideo(videoId)
if (res.success) {
item['hasLike'] = true
item['likeCount'] = res.data['likeCount']
}
}
},
async changeFav(item) {
const videoId = item['id']
if (item['hasFavorite']) {
const res = await removeFavoriteVideo(videoId)
if (res.success) {
item['hasFavorite'] = false
item['favoriteCount'] = res.data['favoriteCount']
}
} else {
const res = await addVideo(videoId)
if (res.success) {
item['hasFavorite'] = true
item['favoriteCount'] = res.data['favoriteCount']
}
}
},
onChange(event) {
this.current = event.detail.current
if (this.current + 2 >= this.list.length) this.fetchList()
this.handleVideoPlay()
},
handleVideoPlay() {
for (let i = 0; i < this.list.length; i++) {
let id = `video-${i}`
let videoContext = uni.createVideoContext(id)
videoContext.pause()
if (this.current === i) videoContext.play()
}
},
controlVideo() {
let id = `video-${current.value}`
this.currentContext = uni.createVideoContext(id)
if (this.showPlay) {
this.currentContext.play()
} else {
this.currentContext.pause()
}
this.showPlay = !this.showPlay
},
dialogClose() {
this.showDialog = false
},
dialogOpen() {
this.comment = ''
this.page = 1
this.replyList = []
this.fetchReply()
},
async fetchReply() {
const id = this.list[this.current]['id']
const res = await getReplyList(id, this.page)
if (res.success && res.data['records']?.length > 0) {
res.data['records']?.forEach(item => {
item.time = uni.$u.timeFrom(Date.parse(item.createTime))
this.replyList.push(item)
})
this.page++
}
},
async onSubmit() {
if (this.comment.trim().length === 0) return
const videoId = this.list[this.current]['id']
const res = await submitReply(videoId, this.comment)
if (res.success) {
uni.showToast({
title: '评论已发布',
icon: 'none',
success() {
this.list[this.current]['replyCount']++
this.showDialog = false
}
})
}
}
}
}
</script>
<style scoped lang="less">
.pkg-video-watch {
position: relative;
height: 100vh;
box-sizing: border-box;
background: #000000;
overflow: hidden;
}
.fixed-header {
position: absolute;
left: 200rpx;
top: 32rpx;
color: #FFFFFF;
font-size: 44rpx;
z-index: 10;
.bold {
border-bottom: 10rpx solid #FFFFFF;
}
}
video {
width: 100vw;
height: 100vh;
}
.fixed-footer {
position: absolute;
left: 0;
width: 100vw;
box-sizing: border-box;
padding: 20rpx 32rpx;
z-index: 10;
.more-t {
width: 216rpx;
margin-left: 10rpx;
color: #FFFFFF;
font-size: 36rpx;
line-height: 52rpx;
white-space: pre-wrap;
z-index: 10;
}
.one-t {
width: 100%;
margin-top: 8rpx;
color: #FFFFFF;
font-size: 28rpx;
}
}
.btn-submit {
width: 120rpx;
height: 64rpx;
margin-left: 20rpx;
border-radius: 12rpx;
background: #FD5749;
color: #FFFFFF;
font-size: 32rpx;
}
.btn-play {
position: absolute;
left: 0;
top: 50%;
transform: translate(0, -50%);
width: 100vw;
height: 50vh;
}
</style>