Files
new_app/components/my-video-list/my-video-list.vue
2025-01-09 09:28:23 +08:00

742 lines
17 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<!-- #ifdef H5 -->
<view class=" w-full box" style="width: 100vw;">
<swiper v-if="videoList.length" @change="swiperChange" :current="current" :circular="true" vertical
class="u-flex-1" @transition="transition" :indicator-dots="false" :autoplay="false" :interval="0"
:duration="200">
<swiper-item v-for="(item,index) in videoList" :key="index">
<list-item-vue :total="list.length" :item="item" :current="current" :isCollect="isCollect"
:index="index" :nowIndex="nowIndex" @dianzanClick="dianzanClick(item,index)" @share="share(item)"
@zhuijuClick="zhuijuClick(item)" @popupShow="popupShow"></list-item-vue>
</swiper-item>
</swiper>
</view>
<!-- #endif -->
<!-- #ifdef APP -->
<list :bounce="false" :loadmoreoffset="wHeight*3" :show-scrollbar="false" ref="listBox" :pagingEnabled="true"
@loadmore="loadmore" :scrollable="true">
<cell v-for="(item,index) in list" :key="item.courseDetailsId" :ref="setRefList(index)">
<view class="swipers-items" :style="boxStyle">
<list-item-vue :total="list.length" :item="item" :current="current" :isCollect="isCollect"
:index="index" :instance="instance" :nowIndex="nowIndex" @appear="appear(item,index)"
@disappear="disappear(item,index)" @dianzanClick="dianzanClick(item,index)" @share="share(item)"
@zhuijuClick="zhuijuClick(item)" @popupShow="popupShow"></list-item-vue>
</view>
</cell>
</list>
<!-- #endif -->
<!-- 选集 -->
<up-popup :show="popup.show" :round="10" @close="popupClose('show')">
<view class="u-p-30">
<view class="u-flex u-flex-row u-row-between">
<view class="u-flex u-flex-row" style="align-items: baseline;">
<text class="color-333 u-font-32 ">{{info.title}}</text>
<text class="u-font-28 color-666 u-m-l-20">{{list.length}}</text>
</view>
<up-icon name="close" :size="16" color="#333" bold @click="popupClose('show')"></up-icon>
</view>
<scroll-view scroll-y="true" class="u-m-t-30" style="height: 400px;box-sizing: border-box;"
:show-scrollbar="false">
<view class="ji-list u-flex u-flex-row u-flex-wrap">
<view class="ji-item u-flex-xy-center u-text-center" @click="jiClick(item,index)"
:class="{active:nowIndex==index,'mr-0':(index+1)%3==0}" v-for="(item,index) in list"
:key="index">
<text class="u-font-28" :class="{'color-fff':nowIndex==index}">{{index+1}}</text>
<view class="lock u-flex-xy-center" v-if="!item.videoUrl">
<up-icon name="lock" :size="14" color="#fff"></up-icon>
</view>
<image v-if="nowIndex==index" class="playing" src="@/static/images/playIng.png" mode="">
</image>
</view>
</view>
</scroll-view>
</view>
</up-popup>
<!-- 支付 -->
<up-popup :show="popup.pay" :round="10" @close="popupClose('pay')">
<view class="u-p-30">
<view class="u-flex u-flex-row u-row-between">
<view class="u-flex u-flex-row" style="align-items: baseline;">
<text class="color-333 u-font-32 ">当前视频 没有播放权限</text>
</view>
<up-icon name="close" :size="16" color="#333" bold @click="popupClose('pay')"></up-icon>
</view>
<view class="u-m-t-30">
<text class=" color-999 u-font-24">每日前10次付款均可获取抽奖机会抽奖保底抽中付款金额等额红包红包可直接提现当前为第1次付款</text>
</view>
<view class="colo-333 pay-list font-bold u-font-28 u-m-t-20">
<view class="pay-list-item" v-if="info&&info.price" @click="payBtnClick">
<image class="hot" src="@/static/images/hot.png" mode=""></image>
<text class="u-font-28 font-bold">{{info.price}}元解锁全剧</text>
</view>
<view class="pay-list-item" @click="payBtnClick">
<image class="hot" src="@/static/images/hot.png" mode=""></image>
<text class="u-font-28 font-bold">{{nowDanjiPrice*jinbiBili}}金币解锁单集视频</text>
</view>
<view class="pay-list-item" @click="payBtnClick">
<!-- <image class="hot" src="@/static/images/hot.png" mode=""></image> -->
<text class="u-font-28 font-bold">{{nowDanjiPrice}}元解锁单集视频</text>
</view>
</view>
</view>
</up-popup>
<!-- 支付确认 -->
<up-popup :show="popup.payTips" :round="10" @close="popupClose('payTips')">
<view class="u-p-30">
<view class="u-flex u-flex-row u-row-between">
<view class="u-flex u-flex-row" style="align-items: baseline;">
<text class="color-333 u-font-32 ">购买后继续观看</text>
</view>
<up-icon name="close" :size="16" color="#333" bold @click="popupClose('payTips')"></up-icon>
</view>
<view class="u-flex u-m-t-24 u-flex-row u-row-between u-font-28">
<view class="u-flex u-flex-row u-flex-y-center">
<image src="@/static/images/zhifubao.png" class="zhifubao" mode=""></image>
<text class="u-m-l-20 u-flex-xy-center u-font-28">支付宝</text>
</view>
<view>
<up-radio-group>
<up-radio :icon-size="20" :size="26" :activeColor="color.main"></up-radio>
</up-radio-group>
</view>
</view>
<view class="u-m-t-10">
<text class="font-bold u-font-26 color-333">温馨提示</text>
<text class="u-m-t-10 u-font-24 color-999">一经购买不予退款未满18岁需在监护人的指导同意下进行付费操作</text>
</view>
<view class="u-flex u-flex-row u-m-t-30 u-flex-y-center u-font-28">
<view class="u-flex-y-center">
<up-checkbox usedAlone shape="circle" v-model="isAgree" :activeColor="color.main"></up-checkbox>
</view>
<view class="u-flex u-flex-row u-flex-y-center">
<text class="u-font-28 color-333">我已经阅读并同意</text>
<text class="color-main u-font-28">付费须知说明</text>
</view>
</view>
<view class="u-m-t-30 my-bg-main payConfirm">
<text class="u-font-28 color-fff">确认支付</text>
</view>
</view>
</up-popup>
<!-- 倍速 -->
<up-popup :show="popup.speed" :round="0" @close="popupClose('speed')">
<view class="u-p-20 u-flex u-flex-row u-row-between u-flex-y-center">
<text class="font-bold color-333 u-font-28">倍速:</text>
<view class="u-flex u-flex-row speed-list">
<text class="speed-list-item u-font-28" @click="changeSpeed(index)" :class="{active:index==speeds.active}"
v-for="(item,index) in speeds.list">{{item.num}}x</text>
</view>
</view>
</up-popup>
</template>
<script setup>
// #ifdef APP
const domModule = uni.requireNativePlugin('dom')
// #endif
import listItemVue from './list-item.vue';
import {
returnShareUrl
} from '@/commons/config.js'
import color from '@/commons/color.js'
import {
debounce
} from 'lodash';
import * as Api from '@/api/video/index.js'
import infoBox from '@/utils/infoBox.js'
import {
computed,
reactive,
ref,
watch,
nextTick,
onMounted,
getCurrentInstance
} from 'vue';
const speeds = reactive({
list: [{
name: '0.5x',
num: 0.5
}, {
name: '1x',
num: 1
}, {
name: '1.25x',
num: 1.25
}, {
name: '1.5x',
num: 1.5
}],
active: 1
})
function changeSpeed(index){
speeds.active=index
uni.showToast({
title: '已切换' + speeds[index].num + '倍播放',
icon: 'none',
duration: 2000
})
}
const instance = getCurrentInstance()
let isAgree = ref(false);
const cutomStyle = {
background: 'rgb(255, 117, 129)',
height: '100rpx',
'border-radius': '100px'
}
const popup = reactive({
show: false,
pay: false,
payTips: false,
speed: false
})
function openBs() {
}
let cacheIndex = null
function appear(item, index) {
console.log(item.courseDetailsName + 'appear');
cacheIndex = index
}
function disappear(item, index) {
console.log('disappear');
if (index == nowIndex.value && cacheIndex != null) {
nowIndex.value = cacheIndex
console.log(nowIndex.value);
cacheIndex = null
}
}
//确认支付
function payConfirm() {
if (!isAgree.value) {
return infoBox.showToast('请阅读并同意 《付费须知说明》')
}
}
function payBtnClick() {
popupClose()
popupShow('payTips')
}
function jiClick(item, index) {
let newCurrent = (current.value + 1) % 3;
videoList.value[newCurrent] = item;
current.value = newCurrent;
popupClose('show')
// #ifdef APP
goListPosition(index)
// #endif
}
let refList = ref([])
function setRefList(index) {
refList.value[index] = null;
return (el) => {
if (el) {
refList.value[index] = el;
}
};
}
//滚动到指定位置
function goListPosition(index) {
console.log('index');
console.log(index);
const el = refList.value[index]
domModule.scrollToElement(el, {
animated: false
})
const item = props.list[index]
setVideoList(item)
insertHistory()
}
function popupClose(key) {
if (key) {
popup[key] = false
return
}
for (let i in popup) {
popup[i] = false
}
}
function popupShow(key = 'show') {
popup[key] = true
}
const props = defineProps({
list: {
type: Array,
default: () => {
[]
}
},
info: {
tpye: Object,
default: () => {
return {
collect: 0,
current: {},
list: [],
price: 0,
title: ''
}
}
}
})
let jinbiBili = ref(0)
let wHeight = ref(0)
async function configInit() {
const res = await Api.getJinbiBili()
jinbiBili.value = res.value
const sysInfo = uni.getSystemInfoSync()
wHeight.value = sysInfo.screenHeight
}
let isCollect = ref(props.info.collect)
watch(() => props.collect, (newval) => {
isCollect.value = newval
})
function posterError() {
}
function posterSuccess() {
}
const posterData = reactive({
show: false,
// 用户姓名
name: '小明',
// 用户头像
logo: '/static/images/share.png',
// 商品名称
title: '精美时尚苹果手机一部',
// 商品价格
money: '5200.90',
// 商品图片(小程序需要换成自己服务器白名单设置的地址)
img: '',
// 商品链接
url: 'https://www.apple.com.cn/iphone/'
})
let nowIndex = ref(0)
let current = ref(0)
let videoList = ref([])
function init() {
if (JSON.stringify(props.current) !== '{}') {
// #ifdef H5
setVideoList(props.info.current)
// #endif
// #ifdef APP
const index = props.list.findIndex(v => v.courseDetailsId == props.info.current.courseDetailsId)
console.log('index' + index);
goListPosition(index)
// #endif
}
}
const emits = defineEmits(['zhuijuClick', 'swiperChange', 'share', 'update'])
function zhuijuClick(item) {
isCollect.value = !isCollect.value
zhuiju({
courseId: item.courseId,
type: isCollect.value ? 1 : 0
})
emits('zhuijuClick')
}
const zhuiju = debounce((data) => {
Api.zhuiju(data)
}, 500)
let dianZanTimer = null
function dianzanClick(item, index) {
item.isGood = !item.isGood
const newval = item.goodNum + (item.isGood ? 1 : -1)
item.goodNum = newval < 0 ? 0 : newval
emits('update', {
index,
item
})
dianzan(item, index)
}
const dianzan = debounce((item, index) => {
Api.dianzan({
courseId: item.courseId,
courseDetailsId: item.courseDetailsId,
type: item.isGood ? 1 : 0
})
}, 500)
let showControls = ref(false)
function openShowPay(current, index, videoUrl) {
showControls.value = true
}
function controlstoggles() {
}
function videoPlay(videoId, courseDetailsId) {
}
function ended() {
}
function share(item) {
const urls = returnShareUrl() + '/me/detail/detail?id=' + item.courseId + '&courseDetailsId=' + item
.courseDetailsId + '&invitation=' + uni.getStorageSync('invitationCode') + '&qdCode=' + this.qdCode;
console.log(urls);
posterData.img = item.titleImg
posterData.show = true
}
function posterHide() {
posterData.show = false
}
const insertHistory = debounce(() => {
const item = videoList.value[current.value]
Api.insertHistory({
courseId: item.courseId,
courseDetailsId: item.courseDetailsId
})
}, 1000)
function swiperChange(e) {
console.log(e.detail.current);
current.value = e.detail.current
const item = videoList.value[e.detail.current]
insertHistory()
setVideoList(item)
}
function setVideoList(item) {
const listLen = props.list.length
const lastIndex = listLen - 1
const index = props.list.findIndex(v => v.courseDetailsId == item.courseDetailsId)
nowIndex.value = index
let position = ''
if (index === 0) {
position = 'start'
}
if (index === props.list.length - 1) {
position = 'end'
}
console.log(position);
if (current.value == 0) {
if (position === 'start') {
videoList.value = [item, props.list[index + 1], props.list[lastIndex]]
} else if (position === 'end') {
videoList.value = [item, props.list[0], props.list[lastIndex]]
} else {
videoList.value = [item, props.list[index + 1], props.list[index - 1]]
}
}
if (current.value == 1) {
if (position === 'start') {
videoList.value = [props.list[lastIndex], item, props.list[index + 1]]
} else if (position === 'end') {
videoList.value = [props.list[lastIndex - 1], item, props.list[0]]
} else {
videoList.value = [props.list[index - 1], item, props.list[index + 1]]
}
}
if (current.value == 2) {
if (position === 'start') {
videoList.value = [props.list[1], props.list[lastIndex], item]
} else if (position === 'end') {
videoList.value = [props.list[0], props.list[lastIndex - 1], item]
} else {
videoList.value = [props.list[index + 1], props.list[index - 1], item]
}
}
console.log(videoList.value);
if (!item.videoUrl) {
// popupShow('pay')
}
}
function transition(e) {
if (e.detail.dy > 0) {
//down
} else {
//up
}
}
function waiting() {
}
configInit()
onMounted(() => {
nextTick(() => {
init()
})
})
watch(() => props.list.length, (newval) => {
// #ifdef H5
init()
// #endif
})
const nowDanjiPrice = computed(() => {
return videoList.value[current.value].price
})
function loadmore() {
console.log('loadmore');
}
const boxStyle = computed(() => {
return {
'height': wHeight.value + 'px',
'width': '750rpx',
}
})
</script>
<style lang="scss" scoped>
.box {
/* #ifdef H5 */
flex: 1;
/* #endif */
}
.u-flex-1 {
flex: 1;
width: 100%;
height: 100%;
}
.u-popup {
position: fixed !important;
}
::v-deep .u-popup {
position: fixed !important;
}
.video {
width: 100%;
height: 100%;
}
.poster {
/* #ifdef H5 */
position: absolute;
width: 100%;
height: 90%;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
/* #endif */
/* #ifdef APP */
width: 750rpx;
flex: 1;
/* #endif */
}
.u-text-center {
text-align: center;
}
.u-flex-row {
flex-direction: row !important;
}
.info {
width: 80%;
height: auto;
position: absolute !important;
bottom: 50px;
left: 10px;
color: #ffffff;
font-size: 15px;
z-index: 9999;
}
.u-flex-y-center {
align-items: center !important;
}
.swipers-items {
width: 750rpx;
flex: 1;
position: relative;
background-color: #000;
}
.right {
width: 60rpx;
position: absolute !important;
right: 20rpx;
top: 50%;
transform: translate(0, -50%);
z-index: 999;
color: #fff;
font-size: 24rpx;
.icon {
width: 60rpx;
height: 60rpx;
}
.share {
.text {
white-space: nowrap;
}
}
.zhuiju {}
}
.poster-popup {
position: fixed !important;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.6);
z-index: 9999;
justify-content: center;
align-items: center;
}
.ji-list {
.ji-item {
width: 210rpx;
margin-bottom: 20rpx;
margin-right: 30rpx;
height: 88rpx;
font-size: 28rpx;
color: #333;
border-radius: 12rpx;
background-color: #F5F7FF;
position: relative;
&.active {
background-color: $my-main-color;
color: #fff;
}
&.mr-0 {
margin-right: 0;
}
.lock {
position: absolute;
border-radius: 0px 6px 0px 6px;
background-color: #ccc;
padding: 2rpx 4rpx;
top: 0;
right: 0;
}
.playing {
position: absolute;
width: 32rpx;
height: 24rpx;
bottom: 5px;
right: 7px;
}
}
}
.ji-item:nth-of-type(3n) {
margin-right: 0;
}
.hot {
width: 40rpx;
height: 40rpx;
}
.pay-list {
.pay-list-item {
flex-direction: row;
justify-content: center;
background-color: #F2F2F2;
padding: 24rpx;
border-radius: 20rpx;
margin-bottom: 40rpx;
}
}
.payConfirm {
border-radius: 100px;
height: 100rpx;
line-height: 100rpx;
text-align: center;
justify-content: center;
align-items: center;
}
.zhifubao {
width: 56rpx;
height: 56rpx;
}
.speed-list {
align-items: center;
background-color: #eeeeef;
padding: 5px 10px;
border-radius: 5px;
.speed-list-item {
border-radius: 3px;
width: 50px;
padding: 8px 0;
justify-content: center;
align-items: center;
text-align: center;
&.active {
background-color: #ffffff;
}
}
}
</style>