This commit is contained in:
zby 2022-10-26 11:14:13 +08:00
commit cffd287924
492 changed files with 46047 additions and 0 deletions

24
.hbuilderx/launch.json Normal file
View File

@ -0,0 +1,24 @@
{ // launch.json configurations app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/
// launchtypelocalremote, localremote
"version": "0.0",
"configurations": [{
"default" :
{
"launchtype" : "local"
},
"mp-kuaishou" :
{
"launchtype" : "local"
},
"mp-toutiao" :
{
"launchtype" : "local"
},
"mp-weixin" :
{
"launchtype" : "local"
},
"type" : "uniCloud"
}
]
}

42
App.vue Normal file
View File

@ -0,0 +1,42 @@
<script>
export default {
onLaunch: function() {
// #ifdef MP-TOUTIAO
var updateManager = tt.getUpdateManager();
updateManager.onUpdateReady(res => {
tt.showModal({
title: '更新提示',
content: '新版本已经准备好,是否重启小程序?',
success: res => {
if (res.confirm) {
// applyUpdate
updateManager.applyUpdate();
}
}
});
});
updateManager.onUpdateFailed(err => {
//
console.log('版本下载失败原因', err);
tt.showToast({
title: '新版本下载失败,请稍后再试',
icon: 'none'
});
});
// #endif
},
onShow: function() {
console.log('App Show');
},
onHide: function() {
console.log('App Hide');
}
};
</script>
<style lang="scss">
/*每个页面公共css */
@import '@/uni_modules/uview-ui/index.scss';
@import '@/stylesheet/index.scss';
</style>

155
api/index.js Normal file
View File

@ -0,0 +1,155 @@
// const http = uni.$u.http;
// console.log(uni.$u);
// export const reg = (params, config = {}) => http.post('/ebapi/public_api/index', params, config);
import request from '@/utils/http/index.js';
export function reg(data) {
return request({
url: '/reg',
method: 'get',
data
});
}
export function getIndexList(data) {
return request({
url: '/index',
method: 'get',
data
});
}
export function chasingdrama(data) {
return request({
url: '/chasingdrama',
method: 'get',
data
});
}
export function signin(data) {
return request({
url: '/signin',
method: 'get',
data
});
}
export function searchFilm(data) {
return request({
url: '/find',
method: 'POST',
data
});
}
export function history(data) {
return request({
url: '/history',
method: 'POST',
data
});
}
export function getUserInfo(data) {
return request({
url: '/user',
method: 'POST',
data
});
}
export function findindex(data) {
return request({
url: '/findindex',
method: 'POST',
data
});
}
export function rechargerecord(data) {
return request({
url: '/rechargerecord',
method: 'POST',
data
});
}
export function getkefu(data) {
return request({
url: '/getkefu',
method: 'POST',
data
});
}
export function paysetting(data) {
return request({
url: '/paysetting',
method: 'POST',
data
});
}
export function payback(data) {
return request({
url: '/payback',
method: 'POST',
data
});
}
export function batchlist(data) {
return request({
url: '/batchlist',
method: 'POST',
data
});
}
export function videoread(data) {
return request({
url: '/videoread',
method: 'POST',
data
});
}
export function buyall(data) {
return request({
url: '/buyall',
method: 'POST',
data
});
}
export function addkeep(data) {
return request({
url: '/addkeep',
method: 'POST',
data
});
}
export function chasingdramadel(data) {
return request({
url: '/chasingdramadel',
method: 'POST',
data
});
}
export function delhistory(data) {
return request({
url: '/delhistory',
method: 'POST',
data
});
}
export function renew(data) {
return request({
url: '/renew',
method: 'POST',
data
});
}
export function getTiktokpay(data) {
return request({
url: '/getTiktokpay',
method: 'POST',
data
});
}

View File

@ -0,0 +1,24 @@
<template>
<view class="g-footer">
<text class="fs-28 text-secondary">
- 到底啦别滑了 -
</text>
</view>
</template>
<script>
export default {
name: 'Gfooter',
data() {
return {};
}
};
</script>
<style scoped lang="scss">
.g-footer {
text-align: center;
padding: 20rpx 0;
align-items: center;
}
</style>

150
components/global/GList.vue Normal file
View File

@ -0,0 +1,150 @@
<template>
<u-list
:paging-enabled="pagingEnabled"
:list-id="listId"
class="flex-1 list"
:triggered="triggered"
:lower-threshold="loadmoreoffset"
:scrollable="scrollable"
:refresher-enabled="refresh"
:bounce="bounce"
:offset-accuracy="offsetAccuracy"
:scroll-top="scrollTop"
:scroll-into-view="scrollIntoView"
@scrolltolower="scrolltolowerHandler"
@scroll="scrollHandler"
@refresherrefresh="refresherrefreshHandler"
@init="initHandler"
>
<!-- #ifdef APP-VUE -->
<refresh
v-if="refresh"
class="refresh flex-center"
:display="triggered ? 'show' : 'hide'"
@refresh="refresherrefreshHandler"
>
<image
src="@/static/images/loading.gif"
mode="aspectFit"
class="loading"
/>
<text class="fs-24 text-regular mt-10">
加载中
</text>
</refresh>
<slot v-if="isPage" /><cell v-else>
<slot />
</cell>
<!-- #endif -->
<!-- #ifndef APP-NVUE -->
<slot />
<!-- #endif -->
</u-list>
</template>
<script>
// #ifdef APP-NVUE
const animation = uni.requireNativePlugin('animation');
// #endif
export default {
name: 'GList',
props: {
triggered: {
type: Boolean,
default: false
},
bounce: {
type: Boolean,
default: true
},
listId: {
type: String,
default: ''
},
loadmoreoffset: {
type: Number,
default: 100
},
pagingEnabled: {
type: Boolean,
default: false
},
refresh: {
type: Boolean,
default: false
},
refreshWidth: {
type: String,
default: '750rpx'
},
scrollable: {
type: Boolean,
default: true
},
offsetAccuracy: {
type: Number,
default: 10
},
scrollTop: {
type: Number,
default: 0
},
scrollIntoView:{
type: String,
default: ''
}
},
data() {
return {
refreshHeight: 0
};
},
computed: {
isPage() {
return !!this.$listeners.scrolltolower;
}
},
created() {
// #ifdef APP-NVUE
const { platform } = uni.getSystemInfoSync();
if (this.refresh && platform === 'android') {
this.refreshHeight = uni.upx2px(106);
}
// #endif
},
methods: {
scrolltolowerHandler() {
if (this.isPage) {
this.$emit('scrolltolower');
}
},
refresherrefreshHandler() {
this.$emit('refresherrefresh');
},
scrollHandler(e) {
this.$emit('scroll', e - this.refreshHeight);
},
initHandler(list) {
this.$emit('init', list);
}
}
};
</script>
<style lang="scss" scoped>
.list {
position: relative;
}
.loading {
width: 72rpx;
height: 72rpx;
}
.refresh {
left: 0;
right: 0;
position: absolute;
height: 106rpx;
}
.list {
justify-content: flex-start;
}
</style>

View File

@ -0,0 +1,92 @@
<template>
<view
v-show="show"
class="loading-box"
:style="{
'background-color': backColor
}"
@click="dismiss"
>
<image
class="rotateKey"
src="@/static/images/loading-svg.png"
/>
<view class="loading">
<text class="loading-text">
{{ text }}
</text>
</view>
</view>
</template>
<script>
export default {
props:{
backColor:{
type:String,
default:()=>{
return '#fff';
}
},
text:{
type:String,
default:()=>{
return '加载中....';
}
}
},
data() {
return {};
},
computed: {
show() {
return this.$store.state.loading;
}
},
methods: {
dismiss() {
this.$store.commit('showLoading', false);
}
}
};
</script>
<style>
.loading-box {
width: 100%;
height: 100vh;
position: fixed;
left: 0;
top: 0;
z-index: 10000;
display: flex;
justify-content: center;
align-items: center;
}
.loading-box image {
margin-bottom: 40px;
}
.rotateKey {
width: 108rpx;
height: 108rpx;
animation: rotateKey 1s ease-in-out infinite;
}
@keyframes rotateKey {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.loading-text {
font-size: 28rpx;
color: #666;
}
</style>

View File

@ -0,0 +1,78 @@
<template>
<u-modal
:title="title"
:show="show"
:showCancelButton="true"
:showConfirmButton="true"
:show-title="showTitle"
:confirmText="options['confirm-text']"
:cancelText="options['cancel-text']"
confirmColor="#FF779E"
@confirm="confirmHandler"
@cancel="cancelHandler"
>
<view class="slot-content">
<text class="fs-32 text-center">{{ content }}</text>
</view>
</u-modal>
</template>
<script>
export default {
name: 'GModal',
props:{
showTitle:{
type:Boolean,
default:()=> false
},
title:{
type:String,
default:()=> ''
}
},
data() {
return {
show: false,
content: '',
resolve: null,
reject: null,
options: {},
timer: null
};
},
methods: {
open(content, options = {}) {
this.show = true;
this.content = content;
this.options = {
'confirm-text': '确定',
'cancel-text': '取消',
...options
};
return new Promise((resolve, reject) => {
this.reject = reject;
this.resolve = resolve;
});
},
confirmHandler() {
clearTimeout(this.timer);
this.timer = setTimeout(() => {
this.resolve();
this.show = false;
});
},
cancelHandler() {
this.reject();
this.show = false;
}
}
};
</script>
<style lang="scss" scoped>
.slot-content {
font-size: 32rpx;
padding: 54rpx 48rpx;
width: 650rpx;
}
</style>

View File

@ -0,0 +1,41 @@
<template>
<view class="empty flex-1 flex-center">
<image
v-if="type === 'normal'"
:src="`/static/images/${image}.png`"
mode="aspectFit"
:style="{ width: size + 'rpx', height: size + 'rpx' }"
/>
<text class="fs-28 text-secondary">
{{ text }}
</text>
</view>
</template>
<script>
export default {
name: 'GNoData',
props: {
text: {
type: String,
default: '抱歉,暂无数据~'
},
size: {
type: Number,
default: 352
},
type: {
type: String,
default: 'normal'
},
image: {
type: String,
default: 'no-data'
}
},
data() {
return {};
}
};
</script>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,149 @@
<template>
<view
class="dataItem"
@click="navGetVideo"
>
<view
class="dataItem-header"
>
<u--image
:fade="true"
:lazy-load="true"
height="484rpx"
width="348rpx"
:src="data.cover"
duration="50"
mode="aspectFill"
/>
<view
v-if="data.history === 1"
class="trace flex-center"
>
<text class="trace-text">
你正在追
</text>
</view>
<view class="bottomRight-number">
<text class="bottomRight-number-text">
{{ data.new || 0 }}集全
</text>
</view>
</view>
<view class="dataItem-bottom px-10 py-16">
<text class="dataItem-bottom-title mb-16 text-one">
{{ data.name || '-' }}
</text>
<view
class="flex-row "
style="align-items: center;"
>
<image
src="@/static/icon/pursue.png"
class="chase mr-8"
mode="aspectFit"
/>
<view class="flex-1">
<view class="remake text-one">
{{ data.description || '-' }}
</view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
props:{
data:{
type:Object,
default:()=>{
return {};
}
},
},
data() {
return {};
},
methods:{
navGetVideo(){
uni.navigateTo({
url:`/pages/video/index?sid=${this.data.id}`
});
}
}
};
</script>
<style lang="scss">
.dataItem {
width: 348rpx;
height: 620rpx;
background: #ffffff;
border-radius: 10rpx;
overflow: hidden;
.dataItem-header {
position: relative;
height: 484rpx;
width: 348rpx;
}
.dataItem-bottom-title {
font-size: 32rpx;
font-weight: bold;
color: #1a1a1a;
}
.chase {
width: 78rpx;
height: 30rpx;
}
.chase_text {
font-size: 20rpx;
color: #ff779e;
}
.remake {
font-size: 24rpx;
color: #666666;
}
.trace {
position: absolute;
top: 0;
left: 0;
width: 116rpx;
height: 48rpx;
background: linear-gradient(134deg, #ffa077 0%, #ff5722 100%);
border-radius: 10rpx 0px 10rpx 0px;
.trace-text {
font-size: 22rpx;
color: #ffffff;
}
}
.bottomRight-number {
padding: 20rpx 10rpx;
position: absolute;
bottom: 0;
right: 0;
.bottomRight-number-text {
font-size: 24rpx;
color: #ffffff;
text-shadow: 0px 0px 4rpx rgba(0,0,0,0.25);
}
}
.update {
position: absolute;
top: 0;
right: 0;
width: 88rpx;
height: 48rpx;
background: linear-gradient(134deg, #ffde88 0%, #ffa24d 100%);
border-radius: 0px 10rpx 0px 10rpx;
.update-text {
font-size: 22rpx;
color: #563a0f;
}
}
}
</style>

View File

@ -0,0 +1,129 @@
<template>
<u-overlay
:show="show"
@click="show = false"
>
<view class="flex-1 flex-center">
<view class="content">
<view class="flex-row pt-120 pl-40">
<text class="content-one">
连续签到
</text>
<text class="content-to mx-10">
{{ content.day || 0 }}
</text>
<text class="content-one">
</text>
</view>
<view class="flex-row pt-100 pl-40">
<text class="content-text-one">
获得 {{ content.money || 0 }} K币
</text>
<u-icon
name="/static/images/member.png"
size="45rpx"
/>
</view>
<view
class="flex-row pl-36 mt-40"
>
<view
class="bottom-button flex-center"
@click="confirmHandler"
>
<text class="bottom-button-text">
去追剧
</text>
</view>
</view>
</view>
<view class="flex-center pt-100">
<image
class="close"
src="@/static/images/close.png"
mode="aspectFill"
/>
</view>
</view>
</u-overlay>
</template>
<script>
export default {
data() {
return {
show: false,
resolve: null,
reject: null,
content:{
money:0,
day:0
},
};
},
methods: {
open(data) {
this.content = data;
this.show = true;
return new Promise((resolve, reject) => {
this.reject = reject;
this.resolve = resolve;
});
},
cancelHandler() {
this.reject();
this.show = false;
},
confirmHandler() {
clearTimeout(this.timer);
this.timer = setTimeout(() => {
this.resolve();
this.show = false;
});
},
}
};
</script>
<style lang="scss">
.content {
width: 554rpx;
height: 526rpx;
background: url('https://diyyhdapi.qinjiu8.com/signInSuccess.png');
background-size: 100% 100%;
}
.bottom-button {
width: 496rpx;
height: 140rpx;
background: url('https://diyyhdapi.qinjiu8.com/signButton.png');
background-size: cover
}
.content-one {
font-size: 32rpx;
font-weight: 400;
color: #313131;
}
.content-to {
font-size: 32rpx;
font-weight: 400;
color: #FF6D35;
}
.content-text-one {
font-size: 40rpx;
font-weight: 400;
color: #FF6D35;
margin-right: 14rpx;
}
.bottom-button-text {
font-size: 36rpx;
font-weight: 500;
color: #FFFFFF;
}
.close {
width: 66rpx;
height: 66rpx;
}
</style>

View File

@ -0,0 +1,285 @@
<template>
<view :style="{height: height+'rpx'}" style="overflow: hidden;">
<esc-swiper :mode="mode" v-if="normalList.length" :autoplay="autoplay" :scale="1.1666" :circular="circular"
:current.sync="current" :size="normalList.length" :plus="plus" :width="width" :height="height"
:itemWidth="itemWidth" :itemHeight="itemHeight" :space="space" :interval="interval">
<esc-swiper-item @click="itemClick(item)" v-for="(item, idx) in normalList" :index="idx" :key="idx">
<esc-bg-view :src="item.cover" :width="itemWidth" :height="itemHeight">
<view v-if="dotMode === 'nav'" key="nav" :style="{
bottom: '0',
width:itemWidth + 'rpx'
}" class="uni-swiper__dots-box uni-swiper__dots-nav flex-row">
<text :style="{ color: dots.color }" class="flex-1 uni-swiper__dots-nav-item">{{
item[field]
}}</text>
</view>
</esc-bg-view>
</esc-swiper-item>
<!-- <template slot="dot">
<view v-if="dotMode === 'default' || dotMode === 'nav'"
:style="{ bottom: dots.bottom + 'px', 'justify-content': dotMode === 'nav' ? 'right' : 'center', right: dotMode === 'nav' ? '50rpx' : 0, 'flex-direction': dotMode === 'nav' ? 'row-reverse' : 'row' }"
class="uni-swiper__dots-box" key="default">
<view v-for="(item, index) in swiperList" @click="clickItem(index)"
:class="[index === current && 'uni-swiper__dots-bar']" :style="{
width: (index === current ? dots.width * 3 : dots.width) + 'rpx',
height: dots.height + 'rpx',
'background-color':
index !== current
? dots.backgroundColor
: dots.selectedBackgroundColor,
border: index !== current ? dots.border : dots.selectedBorder,
}" :key="index" class="uni-swiper__dots-item" />
</view>
<view v-else-if="dotMode === 'dot'" :style="{ bottom: dots.bottom + 'px' }" class="uni-swiper__dots-box"
key="dot">
<view v-for="(item, index) in swiperList" @click="clickItem(index)" :style="{
width: dots.width + 'rpx',
height: dots.height + 'rpx',
'background-color':
index !== current
? dots.backgroundColor
: dots.selectedBackgroundColor,
border: index !== current ? dots.border : dots.selectedBorder
}" :key="index" class="uni-swiper__dots-item" />
</view>
</template> -->
</esc-swiper>
</view>
</template>
<script>
import { getSwiperList } from '@/components/sn-swiper/esc-swiper/helper.js';
export default {
// * @description swiper (使class)
// * @property {String} mode = [normal|3d]
// * @property {Number} width
// * @property {Number} height
// * @property {Number} itemWidth
// * @property {Number} itemHeight
// * @property {Number} space
// * @property {Number} plus (2)
// * @property {Boolean} autoplay
// * @property {Boolean} circular ,3
// * @property {String} mode = [default|dot|nav|]
// * @value round
// * @value round
// * @value dot
// * @property {String} field mode nav mode = nav
// * @property {String} swiperList
// * @property {Object} dotsStyles
// * @value width
// * @value height
// * @value bottom
// * @value color
// * @value backgroundColor
// * @value border
// * @value selectedBackgroundColor
// * @value selectedBorder
// * @property {function} itemClick
props: {
mode: {
type: String,
default: '3d'
},
width: {
type: Number,
default: () => 680
},
height: {
type: Number,
default: () => 550
},
itemWidth: {
type: Number,
default: () => 326
},
itemHeight: {
type: Number,
default: () => 452
},
space: {
type: Number,
default: () => 40
},
plus: {
type: Number,
default: () => 0
},
autoplay: {
type: Boolean,
default: () => true
},
// ,3
circular: {
type: Boolean,
default: () => false
},
swiperList: {
type: Array,
default: () => []
},
//
isCard: {
type: Boolean,
default: () => true
},
// default()
dotMode: {
type: String,
default: () => 'dot'
},
dotsStyles: {
type: Object,
default: () => { }
},
// dotMode nav
field: {
type: String,
default: 'title'
},
interval: {
type: Number,
default: () => 3000
}
},
data() {
return {
current: 0,
dots: {
width: 10,
height: 10,
bottom: 10,
color: '#FFFFFF',
backgroundColor: '#FFFFFF',
border: 'none',
selectedBackgroundColor: '#c59f71',
selectedBorder: '1px #c59f71 solid'
}
};
},
computed: {
normalList() {
//33+43
return getSwiperList(this.swiperList, {
circular: this.circular,
plus: this.plus
});
}
},
switch: {
dotsStyles(newVal) {
this.dots = Object.assign(this.dots, this.dotsStyles);
},
},
watch: {
current(){
this.$emit('change',this.current)
}
},
methods: {
itemClick(i) {
this.$emit('itemClick', i);
}
}
};
</script>
<style lang="scss" scoped>
.img-row {
position: relative;
}
.uni-swiper__dots-box {
position: absolute;
bottom: 10px;
left: 0;
right: 0;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex: 1;
flex-direction: row;
justify-content: center;
align-items: center;
}
.uni-swiper__dots-box-nav {
flex: 1;
flex-direction: row;
justify-content: center;
align-items: center;
}
.uni-swiper__dots-item {
width: 8px;
border-radius: 100px;
margin-left: 6px;
background-color: rgba(0, 0, 0, 0.4);
/* #ifndef APP-NVUE */
cursor: pointer;
/* #endif */
/* #ifdef H5 */
// border-width: 5px 0;
// border-style: solid;
// border-color: transparent;
// background-clip: padding-box;
/* #endif */
// transition: width 0.2s linear;
}
.uni-swiper__dots-bar {
border-radius: 100rpx;
}
.uni-swiper__dots-nav {
bottom: 0px;
// height: 26px;
padding: 0px 20rpx;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex: 1;
flex-direction: row;
justify-content: flex-start;
align-items: center;
height: 60rpx;
}
.uni-swiper__dots-nav-item {
/* overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap; */
font-size: 28rpx;
color: #fff;
overflow: hidden;
text-overflow: ellipsis;
/* #ifndef APP-NVUE */
overflow: hidden;
word-break: break-all;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
/* #endif */
/* #ifdef APP-NVUE */
lines: 1;
/* #endif */
}
.item-default {
border-radius: 20rpx;
transition-property: transform;
transition-duration: 1s;
transform: scaleY(0.8);
}
.item-swiper-current {
transform: scaleY(1);
}
</style>

View File

@ -0,0 +1,138 @@
<template>
<u-overlay :show="show">
<view class="flex-1 flex-center">
<view
class="content"
@click="confirmHandler"
>
<view
class="flex-row"
style="justify-content: center;align-items: center;"
>
<text class="content-text-one">
</text>
<text class="content-text-to">
{{ content.price || 0 }}
</text>
<text class="content-text-one">
</text>
<text class="content-text-to">
{{ content.giveegold || 0 }}
</text>
<text class="content-text-one">
</text>
</view>
<view
class="flex-row"
style="justify-content: center;align-items: center;"
>
<text class="content-text-three">
</text>
<text class="content-text-four">
{{ content.egold || 0 }}
</text>
<text class="content-text-three">
K币
</text>
</view>
</view>
<view class="flex-center pt-100">
<image
class="close"
src="@/static/images/close.png"
mode="aspectFill"
@click="cancelHandler"
/>
</view>
</view>
</u-overlay>
</template>
<script>
export default {
data() {
return {
show: false,
resolve: null,
reject: null,
content: {}
};
},
methods: {
open(data) {
this.content = data;
this.show = true;
uni.setStorageSync('isPopup', false);
return new Promise((resolve, reject) => {
this.reject = reject;
this.resolve = resolve;
});
},
cancelHandler() {
this.reject();
this.show = false;
},
confirmHandler() {
this.$emit('success',this.content);
}
}
};
</script>
<style lang="scss">
.content {
width: 706rpx;
height: 616rpx;
background: url('https://diyyhdapi.qinjiu8.com/paybj.png');
background-size: 100% 100%;
padding: 164rpx 0;
}
.content-one {
font-size: 32rpx;
font-weight: 400;
color: #313131;
}
.content-to {
font-size: 32rpx;
font-weight: 400;
color: #ff6d35;
}
.content-text-one {
font-size: 52rpx;
font-weight: 400;
color: #1a1a1a;
}
.content-text-to {
font-size: 80rpx;
font-weight: bold;
color: #f1540d;
margin: 0 14rpx;
}
.content-text-three {
font-size: 36rpx;
font-weight: 400;
color: #1a1a1a;
margin-right: 14rpx;
}
.content-text-four {
font-size: 52rpx;
font-weight: bold;
color: #f1540d;
margin-right: 14rpx;
}
.bottom-button-text {
font-size: 36rpx;
font-weight: 500;
color: #ffffff;
}
.close {
width: 66rpx;
height: 66rpx;
}
</style>

View File

@ -0,0 +1,81 @@
<template>
<view
style="width: 210rpx;"
@click="navGetVideo"
>
<view class="dataItem-header">
<image
:src="data.cover"
mode="aspectFill"
style="width:210rpx;height:280rpx;"
/>
<image
v-if="isEdit"
style="position: absolute;top: 0;left:0;width:210rpx;height:280rpx;"
src="/static/images/edit-show.png"
mode="aspectFill"
@click="delItem(data)"
/>
</view>
<text class="dataItem-title text-one">
{{ data.name }}
</text>
<text class="dataItem-text text-one">
{{ data.description }}
</text>
</view>
</template>
<script>
export default {
props: {
data: {
type: Object,
default: () => {
return {};
}
},
isEdit: {
type: Boolean,
defaule: false
}
},
methods: {
navGetVideo() {
if (!this.isEdit) {
uni.navigateTo({
url: `/pages/video/index?sid=${this.data.id}`
});
}
},
delItem(item) {
this.$emit('del', item);
this.$forceUpdate();
}
}
};
</script>
<style lang="scss">
.dataItem-header {
position: relative;
width: 210rpx;
height: 280rpx;
border-radius: 10rpx;
overflow: hidden;
}
.dataItem-title {
font-size: 28rpx;
font-weight: 500;
color: #1a1a1a;
margin-top: 12rpx;
margin-bottom: 8rpx;
}
.dataItem-text {
font-size: 24rpx;
font-weight: 400;
color: #999999;
}
</style>

View File

@ -0,0 +1,66 @@
<template>
<view class="esc__bg" :style="styleStr">
<image class="esc__abs" :style="styleStr" :src="src" mode="aspectFill" />
<view class="esc__abs">
<slot></slot>
</view>
</view>
</template>
<script>
import {
getStyleStr
} from '../../utils/style.js'
/**
* esc-bg-view (仅支持固定高的场景)
* @description 带背景的View
* @property {ImageURIString} src 背景图
* @property {Number} width 图片宽
* @property {Number} height 图片高
*/
export default {
name: 'esc-bg-view',
props: {
src: {
type: String,
required: true
},
width: {
type: Number,
required: true
},
height: {
type: Number,
required: true
}
},
computed: {
styleStr() {
return getStyleStr({
width: this.width + 'rpx',
height: this.height + 'rpx'
})
}
}
}
</script>
<style lang="less" scoped>
.esc {
&__bg {
position: relative;
}
&__abs {
// #ifndef APP-NVUE
display: flex;
// #endif
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
border-radius: 16rpx;
}
}
</style>

View File

@ -0,0 +1,251 @@
<template>
<view class="swiper-item" ref="swiper_item" :style="itemStyle">
<view class="item-cntent" bubble="true" @click.stop="onClick"><slot></slot></view>
</view>
</template>
<script>
import { getStyleStr } from '../../utils/style.js';
// #ifdef APP-NVUE
const animation = uni.requireNativePlugin('animation');
// #endif
/**
* esc-swiper-item
* @description esc-swiper-item (不支持使用class)
* @property {Number} index 索引(必填)
* @property {Boolean} clickAny 可以点击任意项
* @event {Function} click 点击事件
*/
export default {
name: 'esc-swiper-item',
inject: ['config'],
props: {
index: {
type: Number,
default: 0
},
clickAny: {
type: Boolean,
default: false
},
},
data() {
return {
isAnimated: false,
timingFunction: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',
duration: 0,
current: 0,
position: 0,
mScale: 0,
canClick: true
};
},
created() {},
computed: {
size() {
return this.config.size;
},
width() {
return this.config.width;
},
height() {
return this.config.height;
},
itemWidth() {
return this.config.itemWidth;
},
itemHeight() {
return this.config.itemHeight;
},
space() {
return this.config.space;
},
itemStyle() {
if (this.index == this.size - 1) {
return this.rightSpaceStyle();
} else if (this.index == this.size - 2) {
return this.centerSpaceStyle();
} else {
return this.leftSpaceStyle();
}
},
scale() {
if (!this.config.is3D) {
return 1;
}
if (this.myCurrent == this.current) {
return this.mScale || this.config.scale;
} else {
return this.mScale || 1;
}
},
// swiper-itemcurrent
myCurrent() {
if (!this.config.isCircular) {
return this.index;
}
const p = this.index;
const plus = this.config.plus;
const actSize = this.size - plus * 2;
let current = 0;
if (p < plus) {
current = p + (actSize - plus);
} else if (p >= this.size - plus) {
current = p - (actSize + plus);
} else {
current = p - plus;
}
return current;
}
},
methods: {
itemSize() {
let style = {
width: this.itemWidth + 'rpx',
height: (this.itemHeight || this.height) + 'rpx'
};
if (this.config.is3D) {
// #ifndef APP-NVUE
if (this.isAnimated) {
style.transition = 'transform ' + this.duration + 'ms ' + this.timingFunction;
} else {
style.transition = '';
}
style.transform = 'scale(' + this.scale + ')';
// #endif
// #ifdef APP-NVUE
const isIOS = uni.getSystemInfoSync().platform == 'ios';
if (isIOS) {
style.transform = 'scale(' + this.scale + ')';
} else {
if (!this.isAnimated) style.transform = 'scale(' + this.scale + ')';
}
// #endif
}
return style;
},
leftSpaceStyle() {
return getStyleStr({
...this.itemSize(),
marginLeft: this.space + 'rpx'
});
},
centerSpaceStyle() {
return getStyleStr({
...this.itemSize(),
marginLeft: this.space + 'rpx',
marginRight: this.space + 'rpx'
});
},
rightSpaceStyle() {
return getStyleStr({
...this.itemSize(),
marginRight: this.space + 'rpx'
});
},
onClick(e) {
if (!this.canClick) {
return;
}
// #ifdef APP-NVUE
e.stopPropagation();
// #endif
//
if (this.clickAny) {
this.$emit('click', e);
return;
}
//
if (this.myCurrent == this.current) {
this.$emit('click', e);
}
},
restoreScale(duration) {
if (!this.config.is3D) {
return;
}
// #ifndef APP-NVUE
this.duration = duration;
this.isAnimated = true;
this.mScale = 0;
setTimeout(() => {
this.duration = 0;
this.isAnimated = false;
}, duration);
// #endif
// #ifdef APP-NVUE
this.isAnimated = true;
this.mScale = 0;
animation.transition(
this.$refs['swiper_item'].ref,
{
styles: {
transform: 'scale(' + this.scale + ')'
},
duration, //ms
timingFunction: this.timingFunction,
needLayout: false,
delay: 0 //ms
},
() => {
this.isAnimated = false;
}
);
// #endif
},
restoreToScale(scale, duration) {
if (!this.config.is3D) {
return;
}
// #ifndef APP-NVUE
this.duration = duration;
this.isAnimated = true;
this.mScale = scale;
setTimeout(() => {
this.duration = 0;
this.isAnimated = false;
this.mScale = 0;
}, duration);
// #endif
// #ifdef APP-NVUE
this.isAnimated = true;
animation.transition(
this.$refs['swiper_item'].ref,
{
styles: {
transform: 'scale(' + scale + ')'
},
duration, //ms
timingFunction: this.timingFunction,
needLayout: false,
delay: 0 //ms
},
() => {
this.isAnimated = false;
this.mScale = 0;
}
);
// #endif
}
}
};
</script>
<style scoped>
.swiper-item {
position: relative;
}
.item-cntent {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
}
</style>

View File

@ -0,0 +1,21 @@
/**
* getSwiperList
* @description 获取Swiper数据
* @param {Array} list 原数据
* @param {Object} options 配置
* @param {Boolean} options.circular 是否循环
* @param {Number} options.plus 左右追加个数(开启循环必填至少为2)
* @return {Array}
*/
export function getSwiperList(list, options = {
circular: true,
plus: 2
}) {
if (!options.circular) {
return list
}
const plus = options.plus || 2
const leftPlusList = [...list].reverse().slice(0, plus).reverse();
const rightPlusList = [...list].slice(0, plus);
return [].concat(leftPlusList).concat(list).concat(rightPlusList);
}

View File

@ -0,0 +1,231 @@
<template>
<!-- #ifdef APP-VUE || H5 -->
<view
class="box"
:style="boxStyle"
>
<view
ref="container"
class="container"
:change:prop="swipe.changeData"
:prop="wxsData"
:style="containerStyle"
@touchstart.stop="swipe.touchstart"
@touchmove.stop="swipe.touchmove"
@touchend.stop="swipe.touchend"
>
<slot />
</view>
<slot name="dot" />
</view>
<!-- #endif -->
<!-- #ifdef MP-WEIXIN -->
<view
class="box"
:style="boxStyle"
>
<view
ref="container"
class="container"
:change:prop="swipe.changeData"
:prop="wxsData"
:style="containerStyle"
@touchstart="swipe.touchstart"
@touchmove="swipe.touchmove"
@touchend="swipe.touchend"
>
<slot />
</view>
<slot name="dot" />
</view>
<!-- #endif -->
<!-- #ifdef APP-NVUE -->
<view
class="box"
:style="boxStyle"
>
<view
ref="container"
class="container"
:style="containerStyle"
@horizontalpan="touchstart"
>
<slot />
</view>
<slot name="dot" />
</view>
<!-- #endif -->
<!-- 其他平台使用 js 长列表性能可能会有影响-->
<!-- #ifndef APP-PLUS || MP-WEIXIN || H5 -->
<view
class="box"
:style="boxStyle"
@touchstart="touchstart"
@touchmove="touchmove"
@touchend="touchend"
>
<view
ref="container"
class="container"
:style="containerStyle"
>
<slot />
</view>
<slot name="dot" />
</view>
<!-- #endif -->
</template>
<script src="./mixins/index.wxs" module="swipe" lang="wxs"></script>
<script>
import SwiperMixin from "./mixins/base.mixin.js";
// #ifdef APP-VUE || MP-WEIXIN || H5
import MpMixin from "./mixins/mpwxs.js";
// #endif
// #ifdef APP-NVUE
import BindingxMixin from "./mixins/bindingx.js";
// #endif
// #ifndef APP-PLUS || MP-WEIXIN || H5
import OtherMixin from "./mixins/mpother.js";
// #endif
const mixins = [
// #ifdef APP-VUE || MP-WEIXIN || H5
MpMixin,
// #endif
// #ifdef APP-NVUE
BindingxMixin,
// #endif
// #ifndef APP-PLUS || MP-WEIXIN || H5
OtherMixin,
// #endif
SwiperMixin,
];
/**
* esc-swiper
* @description 自定义swiper (不支持使用class)
* @property {String} mode = [normal|3d] 模式
* @property {Number} scale 3D模式选中项的scale
* @property {Number} width
* @property {Number} height
* @property {Number} itemWidth 项宽
* @property {Number} itemHeight 项高
* @property {Number} space 间距
* @property {Number} plus 左右追加个数(开启循环必填至少为2)
* @property {Number} current 选中项索引
* @property {Boolean} autoplay 自动轮播
* @property {Boolean} circular 是否循环,如果开启至少需要3项
* @property {Boolean} bounce 阻尼效果
* @event {Function} change 索引变化
*/
export default {
name: 'esc-swiper',
mixins,
props: {
mode: {
type: String,
default: 'normal'
},
scale: Number,
width: Number,
height: Number,
itemWidth: {
type: Number,
default: 0
},
itemHeight: {
type: Number,
default: 0
},
space: {
type: Number,
default: 0
},
plus: {
type: Number,
default: 0
},
autoplay: {
type: Boolean,
default: false
},
current: {
type: Number,
default: 0
},
interval: {
type: Number,
default: 5000
},
duration: {
type: Number,
default: 500
},
circular: {
type: Boolean,
default: false
},
bounce: {
type: Boolean,
default: true
},
size: {
type: Number,
default: 0
},
},
provide() {
return {
config: {
is3D: this.is3D,
isCircular: this.circular,
scale: this.scale,
size: this._size,
width: this.width,
height: this.height,
itemWidth: this.itemWidth,
itemHeight: this.itemHeight,
space: this.space,
plus: this.plus
}
};
},
mounted() {
if (this.autoplay) {
this.autoplayInterval = setInterval(() => {
this.next();
}, this.interval);
}
},
watch: {
autoplay(newV) {
if (!newV) {
clearInterval(this.autoplayInterval);
} else {
this.autoplayInterval = setInterval(() => {
this.next();
}, this.interval);
}
}
},
methods: {}
};
</script>
<style scoped>
.box {
position: relative;
overflow: hidden;
}
.container {
position: absolute;
top: 0;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
align-items: center;
}
</style>

View File

@ -0,0 +1,311 @@
import {
getStyleStr
} from '../../../utils/style.js';
// #ifdef APP-NVUE
const animation = uni.requireNativePlugin('animation')
// #endif
export default {
data() {
return {
timingFunction: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',
isAnimated: false,
isScrolling: false,
customDuration: 0,
left: 0,
mCurrent: this.current
};
},
created() { },
mounted() {
// #ifdef MP
this.swiperViews = this.$children
// #endif
// #ifdef APP-PLUS || H5
// setTimeout(()=>{
// this.swiperViews = this.$slots.default.map(it => it.child)
// },1000)
this.swiperViews = this.$slots.default.map(it => it.child)
// #endif
this._setLeft();
this.mCurrent = this.current
this._notifyCurrentForItems(this.current, this.position)
},
watch: {
mCurrent() {
let current = this.mCurrent
if (this.circular) {
if (this.position == 1) {
current = this.actualSize - (this.plus - 1)
// console.log('最前了', current)
} else if (this.position == this._size - 2) {
current = this.plus - 2;
// console.log('最后了', current)
}
if (current < 0) {
current = this.position + 1
}
current %= this.actualSize
}
// console.log('position', this.position, current)
this.$emit('update:current', current)
this.$emit('change', current)
this._notifyCurrentForItems(current, this.position)
}
},
computed: {
is3D() {
return this.mode == '3d'
},
position() {
return this.circular ? (this.mCurrent + this.plus) : this.mCurrent
},
manualDuration() {
if (this.customDuration > 0)
return this.customDuration
return this.isAnimated ? this.duration : 0
},
boxStyle() {
return getStyleStr({
width: this.width + 'rpx',
height: this.height + 'rpx'
});
},
containerStyle() {
const style = {
height: this.height + 'rpx'
};
// #ifdef APP-NVUE
// FIXME: 理论isAnimated=false应该不设置transform,但是ios有个奇怪的问题top不为0导致布局错位
const isIOS = uni.getSystemInfoSync().platform == 'ios'
if (isIOS) {
style.transform = 'translate(' + uni.upx2px(this.left) + 'px' + ',0px)'
} else {
if (this.isAnimated == false) {
style.transform = 'translate(' + uni.upx2px(this.left) + 'px' + ',0px)'
}
}
// #endif
// #ifndef APP-NVUE
style.left = this.left+2 + 'rpx'
style.transition = 'left ' + this.manualDuration + 'ms ' + this.timingFunction
// #endif
return getStyleStr(style);
},
_size() {
return (this.$slots && this.$slots.default && this.$slots.default.length) || this.size;
},
// plus * 2
plusSize() {
return this.circular ? this.plus * 2 : 0;
},
// 真实长度
actualSize() {
return this._size - this.plusSize;
}
},
methods: {
prev() {
if (this.isAnimated) return;
if (this.isScrolling) return;
if (this.mCurrent == 0 && this.circular == false) return
this.mCurrent--;
this._run()
},
next() {
if (this.isAnimated) return;
if (this.isScrolling) return;
if (this.circular == true) {
this.mCurrent++;
if (this.mCurrent == this._size) {
this.mCurrent = 0;
}
} else {
if (this.mCurrent == this._size - 1) return
this.mCurrent++;
}
this._run()
},
moveTo(e) {
if (this.isAnimated) return
const {
deltaX,
left
} = e
this.isScrolling = true
if (!this.circular) {
if (
// 第一项,不能向右滑(上一项)
(deltaX > 0 && this.mCurrent == 0) ||
// 最后一项,不能向左滑(下一项)
(deltaX < 0 && this.mCurrent == this._size - 1)
) {
if (!this.bounce) return
// 添加阻尼滑动
const _left = this._left || this.wxsData.left
this.left = _left + (deltaX * (1 - Math.abs(deltaX) * 3 / (this.width * 5)))
this._set3DScale(deltaX)
return
}
}
this.left = left
// console.log(this.left);
this._set3DScale(deltaX)
},
moveEnd(e) {
const {
velocity,
deltaX,
deltaY
} = e
this.isScrolling = false
if (!this.circular) {
// 第一项,不能向右滑(上一项)
if (deltaX > 0 && this.mCurrent == 0) {
this._restoreStartTouch()
return
}
// 最后一项,不能向左滑(下一项)
if (deltaX < 0 && this.mCurrent == this._size - 1) {
this._restoreStartTouch()
return
}
}
const isTurnPage = Math.abs(deltaX) > this.itemWidth / 2
if (isTurnPage || velocity > 0.2) {
if (deltaX < 0) {
this.customDuration = 350
this.next()
} else if (deltaX > 0) {
this.customDuration = 350
this.prev()
}
} else {
this._restoreStartTouch()
}
},
_set3DScale(deltaX) {
if (this.is3D) {
const min = Math.min
const maxScale = Math.abs(this.scale - 1)
const mScale = deltaX * maxScale / this.width
const mRealScale = min(this.scale, this.scale - Math.abs(mScale))
this.swiperViews[this.position].mScale = mRealScale < 1 ? 1 : mRealScale
if (this.position - 1 > -1) {
this.swiperViews[this.position - 1].mScale = mScale > 0 ? min(this.scale, 1 + mScale) : min(1, 1 + mScale)
}
if (this.position + 1 < this._size) {
this.swiperViews[this.position + 1].mScale = mScale > 0 ? min(1, 1 - mScale) : min(this.scale, 1 - mScale)
}
}
},
_restoreStartTouch() {
const self = this
this.customDuration = 300
// #ifdef APP-VUE || MP-WEIXIN || H5
this.left = this.wxsData.left
// #endif
// #ifndef APP-PLUS || MP-WEIXIN || H5
this.left = this._left
// #endif
this._run(false)
if (this.is3D) {
this.swiperViews[this.position].restoreScale(this.manualDuration)
if (this.position - 1 > -1) {
this.swiperViews[this.position - 1].restoreScale(this.manualDuration)
}
if (this.position + 1 < this._size) {
this.swiperViews[this.position + 1].restoreScale(this.manualDuration)
}
}
},
_notifyCurrentForItems(current, position) {
this.swiperViews && this.swiperViews.forEach(it => {
it.current = current
it.position = position
})
},
_run(isSet = true) {
this.isAnimated = true;
if (isSet)
this._setLeft();
const self = this;
if (this.is3D) {
this.swiperViews[this.position].restoreToScale(this.scale, this.manualDuration)
if (this.position - 1 > -1) {
this.swiperViews[this.position - 1].restoreToScale(1, this.manualDuration)
}
if (this.position + 1 < this._size) {
this.swiperViews[this.position + 1].restoreToScale(1, this.manualDuration)
}
}
// #ifdef APP-NVUE
animation.transition(this.$refs.container, {
styles: {
transform: 'translate(' + uni.upx2px(this.left) + 'px' + ',0px)',
},
duration: this.manualDuration, //ms
timingFunction: this.timingFunction,
needLayout: false,
delay: 0 //ms
}, function () {
self._reset();
})
// #endif
// #ifndef APP-NVUE
setTimeout(() => {
this._reset();
}, this.manualDuration);
// #endif
},
_setLeft() {
if (this.circular == true) {
const s1 = (this.width - this.itemWidth - this.space * 2) / 2;
let left = (this.plus + this.mCurrent) * (this.space + this.itemWidth) - s1;
this.left = -left;
} else {
this.left = -(this.itemWidth + this.space) * this.mCurrent
}
// #ifdef APP-VUE || MP-WEIXIN || H5
this.wxsData = {
left: this.left,
bounce: this.bounce
}
// #endif
},
_reset() {
this.isScrolling = false
this.isAnimated = false
this.customDuration = 0
if (this.circular == true) {
if (this.position == 1) {
this.mCurrent = this.actualSize - (this.plus - 1);
this._setLeft();
this._restoreScale()
}
// -2原数组索引-1 + plus数组索引-1
if (this.position == this._size - 2) {
this.mCurrent = this.plus - 2;
this._setLeft();
this._restoreScale()
}
}
},
_restoreScale() {
if (this.is3D) {
this.swiperViews[this.position].restoreToScale(this.scale, 0)
if (this.position - 1 > -1) {
this.swiperViews[this.position - 1].restoreToScale(1, 0)
}
if (this.position + 1 < this._size) {
this.swiperViews[this.position + 1].restoreToScale(1, 0)
}
}
}
}
}

View File

@ -0,0 +1,93 @@
const BindingX = uni.requireNativePlugin('bindingx');
const animation = uni.requireNativePlugin('animation');
export default {
mounted() {
this.container = this.getEl(this.$refs['container'])
},
methods: {
_notifyTouchChangeForItems(isTouchEnd) {
this.swiperViews && this.swiperViews.forEach(it => {
it.canClick = isTouchEnd
})
},
touchstart(e) {
if (this.isAnimated) return;
if (this.stop) return
this.isScrolling = true
this._notifyTouchChangeForItems(false)
this.stop = true
this.startTime = new Date().getTime()
const props = [{
element: this.container,
property: 'transform.translateX',
expression: uni.upx2px(this.left) + '+x'
}]
if (this.is3D) {
const deltaScale = `${this.scale}/${this.width}*x`
const currentScale = `${this.scale}-abs(x)/${this.width}*1`
const realScale = `min(${currentScale},${this.scale})`
const currentCardExp = `${realScale} < 1 ? 1 : ${realScale}`;
const leftCardExp = `${deltaScale} > 0 ? min(${this.scale},(1 + ${deltaScale})) : min(1,(1 + ${deltaScale}))`;
const rightCardExp = `${deltaScale} > 0 ? min(1,(1 - ${deltaScale})) : min(${this.scale},(1 - ${deltaScale}))`;
props.push({
element: this.getSwipteItemEl(this.position),
property: 'transform.scale',
expression: currentCardExp
})
if (this.position - 1 > -1) {
props.push({
element: this.getSwipteItemEl(this.position - 1),
property: 'transform.scale',
expression: leftCardExp
})
}
if (this.position + 1 > this._size) {
props.push({
element: this.getSwipteItemEl(this.position + 1),
property: 'transform.scale',
expression: rightCardExp
})
}
}
this.eventpan = BindingX.bind({
anchor: this.container,
eventType: 'pan',
props
}, (e) => {
// console.log(e.state);
if (e.state === 'end' ||
e.state === 'exit') {
setTimeout(() => {
this._notifyTouchChangeForItems(true)
}, 10)
const timing = new Date().getTime() - this.startTime
const velocity = Math.abs(e.deltaX / timing)
this.stop = false
this.isScrolling = false
if (this.eventpan && this.eventpan.token) {
BindingX.unbind({
token: this.eventpan.token,
eventType: 'pan'
})
}
this.moveEnd({
velocity,
deltaX: e.deltaX,
deltaY: e.deltaY
})
}
})
},
getSwipteItemEl(idx) {
return this.swiperViews[idx].$el.ref
},
/**
* 获取ref
* @param {Object} el
*/
getEl(el) {
return el.ref
}
}
}

View File

@ -0,0 +1,144 @@
var MIN_DISTANCE = 10;
function changeData(newValue, oldValue, ownerInstance, instance) {
var state = instance.getState();
if (newValue.left != undefined) {
state.left = newValue.left
}
if (newValue.bounce != undefined) {
state.bounce = newValue.bounce
}
// console.log('changeData', JSON.stringify(newValue))
}
/**
* 开始触摸操作
* @param {Object} e
* @param {Object} ins
*/
function touchstart(e, ins) {
var instance = e.instance;
// 计算滑动开始位置
stopTouchStart(e, ins)
}
/**
* 开始滑动操作
* @param {Object} e
* @param {Object} ownerInstance
*/
function touchmove(e, ownerInstance) {
var instance = e.instance;
// 是否可以滑动页面
stopTouchMove(e);
if (e.preventDefault) {
// 阻止页面滚动
e.preventDefault()
}
// var state = instance.getState();
// && state.bounce
move(instance, ownerInstance)
return false
}
/**
* 结束触摸操作
* @param {Object} e
* @param {Object} ownerInstance
*/
function touchend(e, ownerInstance) {
var instance = e.instance;
var state = instance.getState()
ownerInstance.callMethod('moveEnd', {
velocity: Math.abs(state.deltaX / state.timing),
direction: state.direction,
deltaX: state.deltaX,
deltaY: state.deltaY
})
}
/**
* 设置移动距离
* @param {Object} instance
* @param {Object} ownerInstance
*/
function move(instance, ownerInstance) {
var state = instance.getState()
var value = state.deltaX || 0
var state = instance.getState()
if (state.direction == 'horizontal') {
// instance.requestAnimationFrame(function() {
// instance.setStyle({
// transform: 'translateX(' + value + 'px)',
// '-webkit-transform': 'translateX(' + value + 'px)'
// })
// })
ownerInstance.callMethod('moveTo', {
deltaX: value,
deltaY: state.deltaY || 0,
left: state.left + value
})
}
}
/**
* 滑动中,是否禁止打开
* @param {Object} event
*/
function stopTouchMove(event) {
var instance = event.instance;
var state = instance.getState();
var touch = event.touches[0];
state.timing = getDate().getTime() - state.startTime;
state.deltaX = touch.clientX - state.startX;
state.deltaY = touch.clientY - state.startY;
state.offsetX = Math.abs(state.deltaX);
state.offsetY = Math.abs(state.deltaY);
state.direction = state.direction || getDirection(state.offsetX, state.offsetY);
}
/**
* 设置滑动开始位置
* @param {Object} event
*/
function stopTouchStart(event) {
var instance = event.instance;
var state = instance.getState();
resetTouchStatus(instance);
var touch = event.touches[0];
state.startTime = getDate().getTime();
state.startX = touch.clientX;
state.startY = touch.clientY;
}
function getDirection(x, y) {
if (x > y && x > MIN_DISTANCE) {
return 'horizontal';
}
if (y > x && y > MIN_DISTANCE) {
return 'vertical';
}
return '';
}
/**
* 重置滑动状态
* @param {Object} event
*/
function resetTouchStatus(instance) {
var state = instance.getState();
state.direction = '';
state.deltaX = 0;
state.deltaY = 0;
state.offsetX = 0;
state.offsetY = 0;
}
module.exports = {
changeData: changeData,
touchstart: touchstart,
touchmove: touchmove,
touchend: touchend
}

View File

@ -0,0 +1,62 @@
const MIN_DISTANCE = 10;
export default {
methods: {
touchstart(e) {
this._left = this.left
this.stopTouchStart(e)
},
touchmove(e) {
// 是否可以滑动页面
this.stopTouchMove(e);
if (this.direction == 'horizontal') {
this.moveTo({
deltaX: this.deltaX,
deltaY: this.deltaY || 0,
left: this._left + this.deltaX
})
}
// FIXME: 冒泡
return false
},
touchend() {
this.moveEnd({
velocity: Math.abs(this.deltaX / this.timing),
direction: this.direction,
deltaX: this.deltaX,
deltaY: this.deltaY,
})
},
stopTouchStart(event) {
this.resetTouchStatus();
const touch = event.touches[0];
this.startTime = new Date().getTime();
this.startX = touch.clientX;
this.startY = touch.clientY;
},
stopTouchMove(event) {
const touch = event.touches[0];
this.timing = new Date().getTime() - this.startTime;
this.deltaX = touch.clientX - this.startX;
this.deltaY = touch.clientY - this.startY;
this.offsetX = Math.abs(this.deltaX);
this.offsetY = Math.abs(this.deltaY);
this.direction = this.direction || this.getDirection(this.offsetX, this.offsetY);
},
getDirection(x, y) {
if (x > y && x > MIN_DISTANCE) {
return 'horizontal';
}
if (y > x && y > MIN_DISTANCE) {
return 'vertical';
}
return '';
},
resetTouchStatus() {
this.direction = '';
this.deltaX = 0;
this.deltaY = 0;
this.offsetX = 0;
this.offsetY = 0;
}
}
}

View File

@ -0,0 +1,7 @@
export default {
data() {
return {
wxsData: {}
}
}
}

15
components/utils/style.js Normal file
View File

@ -0,0 +1,15 @@
const toLine = (name) => {
return name.replace(/([A-Z])/g, '-$1').toLowerCase();
}
/**
* style对象转化为style字符串
* @return {string}
*/
export const getStyleStr = (styleObject) => {
let transfrom = '';
for (let i in styleObject) {
let line = toLine(i);
transfrom += line + ':' + styleObject[i] + ';';
}
return transfrom
}

13
config/index.js Normal file
View File

@ -0,0 +1,13 @@
// 基础请求url
const BASE_URL = {
development: 'https://diyyhdapi.qinjiu8.com',
production: 'https://diyyhdapi.qinjiu8.com', // 杭州ip
};
// 请求地址
export const baseUrl =
BASE_URL[process.env.NODE_ENV] || 'https://diyyhdapi.qinjiu8.com';
// 集数分页
export const episode = 12;
export const vx = '547845124';

20
index.html Normal file
View File

@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<script>
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
CSS.supports('top: constant(a)'))
document.write(
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
</script>
<title></title>
<!--preload-links-->
<!--app-context-->
</head>
<body>
<div id="app"><!--app-html--></div>
<script type="module" src="/main.js"></script>
</body>
</html>

18
main.js Normal file
View File

@ -0,0 +1,18 @@
import App from './App';
import uView from '@/uni_modules/uview-ui';
import Vue from 'vue';
import store from './store';
function showLoading(show) {
store.commit('showLoading', show);
}
Vue.prototype.$store = store;
Vue.prototype.$showLoading = showLoading;
Vue.use(uView);
Vue.config.productionTip = false;
App.mpType = 'app';
const app = new Vue({
...App
});
app.$mount();

91
manifest.json Normal file
View File

@ -0,0 +1,91 @@
{
"name" : "qj-playlet-app",
"appid" : "__UNI__D193E60",
"description" : "",
"versionName" : "1.0.0",
"versionCode" : "100",
"transformPx" : false,
/* 5+App */
"app-plus" : {
"usingComponents" : true,
"nvueStyleCompiler" : "uni-app",
"compilerVersion" : 3,
"splashscreen" : {
"alwaysShowBeforeRender" : true,
"waiting" : true,
"autoclose" : true,
"delay" : 0
},
/* */
"modules" : {},
/* */
"distribute" : {
/* android */
"android" : {
"permissions" : [
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
]
},
/* ios */
"ios" : {},
/* SDK */
"sdkConfigs" : {}
}
},
/* */
"quickapp" : {},
/* */
"mp-weixin" : {
"appid" : "",
"setting" : {
"urlCheck" : false
},
"usingComponents" : true
},
"mp-alipay" : {
"usingComponents" : true
},
"mp-baidu" : {
"usingComponents" : true
},
"mp-toutiao" : {
"usingComponents" : true,
"setting" : {
"postcss" : true,
"minified" : true,
"es6" : true
},
"appid" : "tt9580e33d0abf37d501"
},
"uniStatistics" : {
"enable" : false
},
"vueVersion" : "2",
"h5" : {
"devServer" : {
"port" : 8083, //
"disableHostCheck" : true,
"proxy" : {
"/api" : {
"target" : "https://diyyhdapi.qinjiu8.com", //
"changeOrigin" : true, //
"secure" : false // https
}
}
}
}
}

154
pages.json Normal file
View File

@ -0,0 +1,154 @@
{
"pages": [ //pageshttps://uniapp.dcloud.io/collocation/pages
//pageshttps://uniapp.dcloud.io/collocation/pages
{
"path": "pages/playlet/index",
"style": {
"navigationBarTitleText": "剧宝",
"enablePullDownRefresh": false,
"disableScroll": true,
"navigationBarTextStyle": "black",
"app-plus": {
"titleNView": false
},
"navigationStyle": "custom"
}
},
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "剧宝",
"enablePullDownRefresh": false,
"disableScroll": true,
"navigationBarTextStyle": "black",
"app-plus": {
"titleNView": false
},
"navigationStyle": "custom"
}
},
{
"path": "pages/my/index/index",
"style": {
"navigationBarTitleText": "剧宝",
"navigationStyle": "custom",
"disableScroll": true,
"enablePullDownRefresh": false,
"navigationBarTextStyle": "black",
"backgroundColor": "#fff"
}
},
{
"path": "pages/discover/index",
"style": {
"navigationBarTitleText": "剧宝",
"navigationStyle": "custom",
"disableScroll": true,
"enablePullDownRefresh": false,
"navigationBarTextStyle": "black",
"backgroundColor": "#fff"
}
}, {
"path": "pages/search/search",
"style": {
"navigationBarTitleText": "搜索",
"enablePullDownRefresh": false,
"disableScroll": true,
"navigationBarTextStyle": "black",
"backgroundColor": "#fff"
}
}, {
"path": "pages/pay/pay",
"style": {
"navigationBarTitleText": "充值中心",
"enablePullDownRefresh": false,
"navigationBarTextStyle": "black",
"backgroundColor": "#fff",
"navigationStyle": "custom",
"disableScroll": true
}
},
{
"path": "pages/my/history/index",
"style": {
"navigationBarTitleText": "历史观看",
"enablePullDownRefresh": false,
"navigationBarTextStyle": "black",
"backgroundColor": "#fff",
"disableScroll": true,
"navigationStyle": "custom"
}
},
{
"path": "pages/my/recharge/index",
"style": {
"navigationBarTitleText": "充值记录",
"enablePullDownRefresh": false,
"navigationBarTextStyle": "black",
"backgroundColor": "#fff",
"disableScroll": true
}
},
{
"path": "pages/video/index",
"style": {
"navigationBarTitleText": "剧宝",
"enablePullDownRefresh": false,
"navigationBarTextStyle": "black",
"backgroundColor": "#fff",
"navigationStyle": "custom",
"disableScroll": true
}
}
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "剧宝",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8"
},
"easycom": {
"autoscan": true,
"custom": {
"^G(.*)": "@/components/global/G$1.vue", // components/globalvue
"^u-(.*)": "@/uni_modules/uview-ui/components/u-$1/u-$1.vue",
"^esc-(.*)": "@/components/sn-swiper/esc-$1/index.vue"
}
},
"tabBar": {
"backgroundColor": "#FFFFFF",
"borderStyle": "#EEEEEE",
"selectedColor": "#FF779E",
"iconWidth": "22px",
"color": "#666666",
"fontSize": "10px",
"height": "68px",
"list": [{
"text": "短剧",
"pagePath": "pages/playlet/index",
"iconPath": "/static/tabbar/playlet_off.png",
"selectedIconPath": "/static/tabbar/playlet_on.png"
},
{
"text": "发现",
"pagePath": "pages/discover/index",
"iconPath": "/static/tabbar/discover_off.png",
"selectedIconPath": "/static/tabbar/discover_on.png"
},
{
"text": "我的",
"pagePath": "pages/my/index/index",
"iconPath": "/static/tabbar/my_off.png",
"selectedIconPath": "/static/tabbar/my_on.png"
}
]
},
"uniIdRouter": {}
}

297
pages/discover/index.vue Normal file
View File

@ -0,0 +1,297 @@
<template>
<view class="flex-1">
<GLoading />
<scroll-view
class="flex-1"
style="z-index: 999;"
scroll-y="true"
lower-threshold="30"
@scrolltolower="scrollLower"
>
<view style="position: relative;">
<view class="body-bg" />
<view class=" px-20 py-20">
<!-- <view class="high mb-20">
<view class="high-title mb-24">
<text class="high-title-text">
优质短剧
</text>
</view>
<view class="highContent">
<view
v-for="(item, index) in dataList.module2"
:key="index"
class="flex-row mb-20"
>
<u--image
class="highContent-img mr-20"
:fade="true"
:lazy-load="true"
height="238rpx"
width="176rpx"
:src="item.cover"
duration="450"
mode="aspectFill"
/>
<view
class="high-right"
style="justify-content: center;"
>
<text class="high-right-one text-one">
{{ item.name || '-' }}
</text>
<text class="high-right-to mt-28 mb-32 text-To">
{{ item.description || '-' }}
</text>
<view
class="high-right-three flex-row"
style="align-items: center;"
>
<u-icon
name="/static/icon/hot.png"
size="44rpx"
/>
<text class="high-right-three-text">
{{ item.num || 0 }}火力值
</text>
</view>
</view>
</view>
</view>
</view> -->
<view class="listData flex-1">
<view
v-for="(item, index) in dataList.module1"
:key="index"
class="listDataItem mb-20"
>
<image
v-if="item.recommend === 1"
src="@/static/images/recommend.png"
style="width:160rpx;height:102rpx;position: absolute;top: 20rpx;left: 20rpx;z-index: 999;"
mode="aspectFill"
/>
<u--image
class="listDataItemImg"
:fade="true"
:lazy-load="true"
height="720rpx"
width="710rpx"
:src="item.cover"
duration="450"
mode="aspectFill"
@click="listDataItemClick(item)"
/>
<image
src="@/static/images/play.png"
class="_image"
mode="aspectFill"
@click="listDataItemClick(item)"
/>
<view class="listData-remake px-20 pt-104">
<view
class="flex-row"
style="justify-content: space-between;"
>
<text class="listData-remake-title">
{{ item.name || '-' }}
</text>
<view
class="flex-row"
style="align-items: center;"
@click="chase(item)"
>
<u-icon
:name="
item.collection === 0
? '/static/icon/attention.png'
: '/static/icon/attention-on.png'
"
size="36rpx"
/>
<text class="listData-remake-text">
{{ item.num || 0 }}
</text>
</view>
</view>
<text class="listData-remarks text-To">
{{ item.description }}
</text>
</view>
<text class="listData-update">
{{ item.new || 0 }}集全
</text>
</view>
</view>
</view>
<u-loadmore :status="status" />
<!-- #ifndef H5 -->
<u-gap height="80" />
<!-- #endif -->
</view>
</scroll-view>
</view>
</template>
<script>
import { findindex, addkeep, chasingdramadel } from '@/api/index.js';
export default {
data() {
return {
dataList: {
module1: [],
module2: []
},
status: 'loadmore',
page: 1
};
},
onShow() {
this.$showLoading(true);
this.dataList.module1 = [];
console.log(this.dataList);
this.getList();
},
methods: {
getList() {
findindex({ page: this.page }).then(res => {
this.$showLoading(false);
if (res.module1.length === 0) {
this.status = 'nomore';
} else {
this.status = 'loadmore';
this.dataList.module1 =
this.dataList.module1.concat(res.module1) || [];
}
});
},
scrollLower() {
if (this.status !== 'nomore') {
this.page++;
this.status = 'loading';
this.getList();
}
},
listDataItemClick(item) {
uni.navigateTo({
url: `/pages/video/index?sid=${item.id}`
});
},
chase(item) {
let fn = null;
let params = {};
console.log(item);
if (item.collection === 0) {
fn = addkeep;
params = {
sid: item.id
};
} else {
fn = chasingdramadel;
params = {
ids: item.id
};
}
fn(params).then(() => {
item.collection = item.collection === 0 ? 1 : 0;
item.num = item.collection === 0 ? item.num - 1 : item.num + 1;
});
}
}
};
</script>
<style lang="scss">
.high {
position: relative;
padding: 40rpx 20rpx;
border-radius: 10rpx;
background-image: url('~@/static/images/hign.png');
background-size: 100% 100%;
.high-title-text {
font-size: 44rpx;
font-weight: bold;
color: #f48319;
}
.highContent-img {
width: 176rpx;
height: 238rpx;
}
.high-right-one {
font-size: 36rpx;
font-weight: bold;
color: #1a1a1a;
}
.high-right-to {
font-size: 30rpx;
font-weight: 400;
color: #666666;
}
.high-right-three-text {
font-size: 30rpx;
font-weight: 400;
color: #666666;
}
}
.listDataItem {
position: relative;
height: 958rpx;
border-radius: 10rpx;
overflow: hidden;
}
.listDataItemImg {
width: 710rpx;
height: 720rpx;
}
.listData-remake {
position: absolute;
bottom: 0;
width: 710rpx;
height: 332rpx;
background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, #ffffff 22%);
}
.listData-remake-title {
font-size: 44rpx;
font-weight: bold;
color: #1a1a1a;
}
.listData-remake-text {
font-size: 26rpx;
font-weight: 400;
color: #666666;
}
.listData-remarks {
font-size: 26rpx;
font-weight: 400;
color: #999999;
line-height: 56rpx;
margin-top: 16rpx;
}
.listData-update {
position: absolute;
bottom: 310rpx;
right: 10rpx;
font-size: 28rpx;
font-weight: 500;
color: #ffffff;
}
._image {
width: 136rpx;
height: 136rpx;
position: absolute;
top: 298rpx;
left: 288rpx;
}
.body-bg {
position: absolute;
top: 0;
width: 750rpx;
z-index: 2rpx;
height: 434rpx;
background: url('https://diyyhdapi.qinjiu8.com/backImg.png');
background-size: 100% 100%;
}
</style>

60
pages/index/index.vue Normal file
View File

@ -0,0 +1,60 @@
<template>
<list
height="100%"
width="750rpx"
class="flex-1"
>
<cell
v-for="(item, index) in urls"
:key="index"
:title="`列表长度-${index + 1}`"
class="flex-1"
style="height: 100%;width: 100%;"
>
<view class="flex-1" />
</cell>
</list>
</template>
<script>
export default {
data() {
return {
tabbarIndex: 0,
urls: [
'https://cdn.uviewui.com/uview/album/1.jpg',
'https://cdn.uviewui.com/uview/album/2.jpg',
'https://cdn.uviewui.com/uview/album/3.jpg',
'https://cdn.uviewui.com/uview/album/4.jpg',
'https://cdn.uviewui.com/uview/album/5.jpg',
'https://cdn.uviewui.com/uview/album/6.jpg',
'https://cdn.uviewui.com/uview/album/7.jpg',
'https://cdn.uviewui.com/uview/album/8.jpg',
'https://cdn.uviewui.com/uview/album/9.jpg',
'https://cdn.uviewui.com/uview/album/10.jpg',
'https://cdn.uviewui.com/uview/album/1.jpg',
'https://cdn.uviewui.com/uview/album/2.jpg',
'https://cdn.uviewui.com/uview/album/3.jpg',
'https://cdn.uviewui.com/uview/album/4.jpg',
'https://cdn.uviewui.com/uview/album/5.jpg',
'https://cdn.uviewui.com/uview/album/6.jpg',
'https://cdn.uviewui.com/uview/album/7.jpg',
'https://cdn.uviewui.com/uview/album/8.jpg',
'https://cdn.uviewui.com/uview/album/9.jpg',
'https://cdn.uviewui.com/uview/album/10.jpg',
]
};
},
};
</script>
<style lang="scss">
</style>

225
pages/my/history/index.vue Normal file
View File

@ -0,0 +1,225 @@
<template>
<view class="flex-1">
<GList class="flex-1">
<GLoading />
<view
v-if="dataList.length !== 0"
class="px-30 py-28"
>
<view
v-for="(item, index) in dataList"
:key="index"
class="history-item flex-row mb-28"
style="justify-content: space-between;"
:class="{ active: item.sace === 1 }"
>
<view
class="flex-row"
style="align-items: center;"
@click="getVideoNav(item)"
>
<image
class="history-item-img"
height="236rpx"
width="172rpx"
:src="item.cover"
mode="aspectFill"
radius="16rpx"
/>
<view
class="ml-20"
style="justify-content: center;"
>
<text class="history-title">
{{ item.name || '-' }}
</text>
<view class="flex-row my-24">
<text class="history-oder">
观看到
</text>
<text class="history-update">
{{ item.latest || 0 }}
</text>
</view>
<view class="flex-row">
<text class="history-update">
{{ item.latestid }}集全
</text>
</view>
</view>
</view>
<view
class="flex-row"
style="align-items: center;"
>
<view
class="chase flex-center flex-row"
@click="chase(item)"
>
<u-icon
v-if="item.sace === 0"
name="/static/icon/add.png"
size="22rpx"
/>
<u-icon
v-else
name="/static/icon/success.png"
color="#999999"
size="22rpx"
/>
<text class="chase-text ml-8">
追剧
</text>
</view>
<view
class="delete flex-center ml-20"
@click="delhistory(item)"
>
<u-icon
name="/static/icon/history-delete.png"
size="40rpx"
/>
</view>
</view>
</view>
</view>
<view
v-else
class="flex-1 flex-center"
style="height: 100%;background-color: #ffffff;"
>
<GNoData
image="no-history"
text="暂无历史观看~"
/>
</view>
</GList>
</view>
</template>
<script>
import { history, delhistory, addkeep, chasingdramadel } from '@/api/index.js';
export default {
data() {
return {
dataList: []
};
},
created() {
this.$showLoading(true);
this.getData();
},
methods: {
getData() {
history().then(res => {
this.dataList = res || [];
this.$showLoading(false);
});
},
getVideoNav(item) {
uni.setStorageSync('videoBackRouter', {
type:2,
url: '/pages/my/history/index'
});
uni.redirectTo({
url: `/pages/video/index?sid=${item.sid}`
});
},
delhistory(item) {
delhistory({ id: item.hid }).then(() => {
const index = this.dataList.findIndex(r=>item.hid === r.hid);
uni.showToast({
title:'删除成功',
duration:1000
});
this.dataList.splice(index,1);
});
},
chase(item) {
let fn = null;
let params = {};
if (item.sace === 0) {
fn = addkeep;
params = {
sid: item.sid
};
} else {
fn = chasingdramadel;
params = {
ids: item.sid
};
}
fn(params).then(() => {
item.sace = item.sace === 0 ? 1 : 0;
uni.showToast({
title:item.sace === 1 ?'追剧成功':'取消追剧成功',
duration:1000
});
});
},
getkActivity(){
uni.switchTab({
url:'/pages/my/index/index'
});
}
}
};
</script>
<style lang="scss">
.history-item {
.history-item-img {
width: 192rpx;
height: 236rpx;
border-radius: 16rpx;
}
.history-title {
font-size: 36rpx;
font-weight: bold;
color: #1a1a1a;
}
.history-oder {
font-size: 30rpx;
font-weight: 400;
color: #666666;
}
.history-update {
font-size: 30rpx;
font-weight: 400;
color: #333333;
}
.chase {
width: 114rpx;
height: 60rpx;
border-radius: 40rpx;
border: 1rpx solid #ff779e;
.chase-text {
font-size: 26rpx;
font-weight: 400;
color: #ff779e;
}
}
.delete {
width: 72rpx;
height: 60rpx;
border-radius: 40rpx;
border: 2rpx solid #696969;
}
&.active {
.chase {
width: 114rpx;
height: 60rpx;
border-radius: 40rpx;
border: 1rpx solid #999999;
.chase-text {
font-size: 26rpx;
font-weight: 400;
color: #999999;
}
}
}
}
</style>

378
pages/my/index/index.vue Normal file
View File

@ -0,0 +1,378 @@
<template>
<view
class="flex-1"
style="position: relative;"
>
<GLoading />
<view class="body-bg" />
<view
class="flex-1"
style="position: absolute;z-index: 9999;"
>
<view
class="px-28 flex-row pt-48 "
@click="getUserInfo"
>
<image
class="avatar"
:src="userInfo.avatar || '/static/images/avatar.png'"
mode="aspectFit"
/>
<view
class=""
style="justify-content: center;"
>
<view
class="flex-row"
style="align-items: center;"
>
<text class="nikeName">
{{ userInfo.nickname || '未登录' }}
</text>
<u-icon
v-if="userInfo.is_vip === 0"
class="ml-10"
name="/static/images/member-off.png"
size="48rpx"
/>
<u-icon
v-else
class="ml-10"
name="/static/images/member.png"
size="48rpx"
/>
</view>
<text
v-if="uid"
class="remake mt-10"
>
ID:{{ uid }}
</text>
</view>
</view>
<view class="userInfo mt-48 px-30 flex-row mb-20">
<view
class="flex-row flex-1 "
style="align-items: center;"
>
<view class="flex-row flex-1 flex-center ">
<view
class="flex-center mr-120"
@click="navPay"
>
<text class="userInfo-textOne">
{{ userInfo.egold || 0 }}
</text>
<text class="userInfo-textTo mt-14">
账户K币
</text>
</view>
<view
class="flex-center"
@click="navPay"
>
<text class="userInfo-textOne">
{{ userInfo.vip_enddate || 0 }}
</text>
<text class="userInfo-textTo mt-14">
会员天数
</text>
</view>
</view>
</view>
<view
class=" flex-center ml-90"
style="width: 212rpx;"
>
<view
v-if="platform !== 'ios' && userInfo.ispay === 1"
class="consumption flex-center"
@click="navPay"
>
<text class="consumption-text">
立即充值
</text>
</view>
<view
v-else
class="immediately flex-center"
@click="keep"
>
<text class="immediately-text">
立即追剧
</text>
</view>
</view>
</view>
<view
class="flex-1 option"
style="width: 750rpx;"
>
<view
class="flex-row"
style="align-items: center;justify-content: space-between; "
@click="seeLs"
>
<view class="flex-row">
<u-icon
class="mr-34"
name="/static/icon/history.png"
size="48rpx"
/>
<text class="option-text">
历史观看
</text>
</view>
<image
src="@/static/icon/arrowLeft.png"
mode="aspectFill"
style="width:18rpx;height: 32rpx ;"
/>
</view>
<view
v-if="historyList.length !== 0"
class="mt-28 "
>
<u-scroll-list :indicator="false">
<view
v-for="(item, index) in historyList"
:key="index"
@click="historyItem(item)"
>
<image
class="dataItem-img"
:src="item.cover"
mode="aspectFill"
/>
</view>
</u-scroll-list>
</view>
<view
class="flex-row mt-62"
style="align-items: center;justify-content: space-between; "
@click="navGetRouter('/pages/my/recharge/index')"
>
<view class="flex-row">
<u-icon
class="mr-34"
name="/static/icon/wallet.png"
size="48rpx"
/>
<text class="option-text">
充值明细
</text>
</view>
<image
src="@/static/icon/arrowLeft.png"
mode="aspectFill"
style="width:18rpx;height: 32rpx ;"
/>
</view>
<view
class="flex-row mt-62"
style="align-items: center;justify-content: space-between; "
@click="getServiceVx"
>
<view class="flex-row">
<u-icon
class="mr-34"
name="/static/icon/service.png"
size="48rpx"
/>
<text class="option-text">
联系客服
</text>
</view>
<image
src="@/static/icon/arrowLeft.png"
mode="aspectFill"
style="width:18rpx;height: 32rpx ;"
/>
</view>
</view>
</view>
</view>
</template>
<script>
import { history, getUserInfo, getkefu, renew } from '@/api/index.js';
export default {
data() {
const uid = uni.getStorageSync('uid') || '';
return {
userInfo: {},
historyList: [],
uid,
platform: ''
};
},
onShow() {
const isPopup = uni.getStorageSync('isPopup');
if(isPopup){
uni.navigateTo({
url:'/pages/pay/pay'
});
}
if(!this.userInfo.avatar){
this.$showLoading(true);
}
this.platform = uni.getSystemInfoSync().platform;
this.getData();
},
methods: {
getUserInfo() {
if (!this.userInfo.nickname && !this.userInfo.avatar) {
// #ifdef MP-TOUTIAO
tt.getUserProfile({
success: res => {
console.log(res);
const userInfo = res.userInfo;
renew({
nickname: userInfo.nickName,
avatar: userInfo.avatarUrl
}).then(res => {
this.userInfo.avatar = userInfo.avatarUrl;
this.userInfo.nickname = userInfo.nickName;
});
}
});
// #endif
}
},
historyItem(e) {
uni.navigateTo({
url: `/pages/video/index?sid=${e.sid}`
});
},
navPay() {
if (this.userInfo.ispay) {
uni.navigateTo({
url: '/pages/pay/pay'
});
}
},
seeLs(){
uni.navigateTo({
url:'/pages/my/history/index'
});
},
navGetRouter(url) {
uni.navigateTo({
url: url
});
},
getData() {
history().then(res => {
this.historyList = res;
});
getUserInfo().then(res => {
this.userInfo = res.info || {};
this.$showLoading(false);
});
},
getServiceVx() {
getkefu().then(res => {
uni.setClipboardData({
data: res.wxkf,
showToast: false,
success: function() {
uni.showToast({
title: '客服微信已复制',
duration: 2000
});
}
});
});
},
keep() {
uni.switchTab({
url: '/pages/playlet/index'
});
}
}
};
</script>
<style lang="scss">
.avatar {
width: 162rpx;
height: 162rpx;
margin-right: 20rpx;
border-radius: 50%;
}
.nikeName {
font-size: 44rpx;
font-weight: bold;
color: #1a1a1a;
}
.remake {
font-size: 28rpx;
font-weight: 400;
color: #999999;
}
.userInfo {
height: 184rpx;
width: 750rpx;
border-radius: 40rpx 40rpx 0 0;
background-color: #ffffff;
}
.userInfo-textOne {
font-size: 40rpx;
font-weight: bold;
color: #1a1a1a;
}
.userInfo-textTo {
font-size: 30rpx;
font-weight: 400;
color: #666666;
}
.consumption {
width: 212rpx;
height: 76rpx;
background: linear-gradient(89deg, #ff6c90 0%, #ff002e 100%);
border-radius: 18rpx;
.consumption-text {
font-size: 32rpx;
font-weight: bold;
color: #ffffff;
}
}
.option {
background-color: #ffffff;
padding: 48rpx 30rpx;
.option-text {
font-size: 34rpx;
font-weight: 500;
color: #1a1a1a;
}
.dataItem-img {
width: 192rpx;
height: 260rpx;
border-radius: 16rpx;
margin-right: 26rpx;
}
}
.body-bg {
position: absolute;
top: 2rpx;
width: 750rpx;
z-index: 0;
height: 434rpx;
background: url('https://diyyhdapi.qinjiu8.com/backImg.png');
background-size: 100% 100%;
}
.immediately {
width: 212rpx;
height: 76rpx;
background: linear-gradient(92deg, #ff6636 0%, #ffa236 100%);
border-radius: 50rpx;
.immediately-text {
font-size: 32rpx;
font-weight: bold;
color: #ffffff;
}
}
</style>

144
pages/my/recharge/index.vue Normal file
View File

@ -0,0 +1,144 @@
<template>
<GList
class="flex-1"
style="background: #F3F4F6;"
>
<GLoading />
<view
v-if="dataList.length !==0"
class="px-30 py-28"
>
<view
v-for="(item, index) in dataList"
:key="index"
class="pay-item mb-24"
>
<view
class="pay-item-header flex-center"
:class="{ status: item.status === 0 }"
>
<text class="pay-item-header-text">
充值{{ item.money || 0 }}{{
item.status === 1 ? '已支付' : '未支付'
}}
</text>
</view>
<view class="pay-item-bottom">
<view
class="flex-row mb-20 mt-8"
style="justify-content: space-between;"
>
<text class="pay-item-bottom-left">
订单号码
</text>
<text class="pay-item-bottom-right">
{{ item.out_trade_no }}
</text>
</view>
<view
class="flex-row"
style="justify-content: space-between;"
>
<text class="pay-item-bottom-left">
下单时间
</text>
<text class="pay-item-bottom-right">
{{ item.create_time }}
</text>
</view>
</view>
</view>
</view>
<view
v-else
class="flex-1 flex-center"
style="height: 100%;background-color: #ffffff;"
>
<GNoData
image="pay-noData"
text="暂无充值记录~"
/>
</view>
</GList>
</template>
<script>
import { rechargerecord } from '@/api/index.js';
export default {
data() {
return {
dataList: []
};
},
created() {
this.$showLoading(true);
this.getDataList();
},
methods: {
getDataList() {
rechargerecord().then(res => {
this.dataList = res || [];
this.$showLoading(false);
});
}
}
};
</script>
<style lang="scss">
.dataItem {
flex-direction: row;
justify-content: space-between;
align-items: center;
}
.pay-text {
font-size: 36rpx;
font-weight: bold;
color: #000000;
}
.pay-unit {
font-size: 30rpx;
font-weight: 400;
color: #666666;
}
.pay-status-1 {
font-size: 30rpx;
font-weight: 500;
color: #333333;
}
.pay-item {
height: 264rpx;
background-image: url('https://diyyhdapi.qinjiu8.com/payBackgrunp.png');
background-size: 100% 100%;
.pay-item-header {
height: 104rpx;
.pay-item-header-text {
font-size: 36rpx;
font-weight: bold;
color: #000000;
}
}
.pay-item-bottom {
padding: 24rpx;
justify-content: space-between;
.pay-item-bottom-left {
font-size: 30rpx;
font-weight: 400;
color: #333333;
}
.pay-item-bottom-right {
font-size: 30rpx;
font-weight: 400;
color: #333333;
}
}
&.status {
.pay-item-header-text {
color: #ce3636;
}
}
}
</style>

345
pages/pay/pay.vue Normal file
View File

@ -0,0 +1,345 @@
<template>
<view class="flex-1">
<!-- <view
class="flex-row px-24"
style="height: 88rpx;align-items: center;justify-content: space-between;background: linear-gradient(88deg, #fad2d2 0%, #fae3d2 51%, #fae3d2 100%);"
>
<view style="width: 50rpx;flex-center" @click="getkActivity">
<u-icon name="/static/icon/arrowRight.png" size="48rpx" />
</view>
<text class="title"> 充值中心 </text> <view style="width: 50rpx;" />
</view> -->
<GLoading />
<GList class="flex-1">
<view class="header flex-row">
<view class="flex-1">
<text class="balance-text"> 账户余额 </text>
<view class="flex-row mt-14" style="align-items: center;">
<view class="flex-row flex-center">
<text class="balance-num"> {{ egold || 0 }} </text>
<text class="balance-unit"> K币 </text>
</view>
<u-icon
class="ml-26"
name="/static/icon/gold.png"
size="48rpx"
/>
</view>
</view>
<image
class="header-img"
src="@/static/images/gold.png"
mode="aspectFill"
/>
</view>
<view class="money mb-20">
<view class="moneyList flex-row">
<view
v-for="(item, index) in payList"
:key="index"
:class="{
'mr-32': (index + 1) % 2 !== 0,
active: index === 0
}"
@click="payItem(item)"
class="money-item flex-center mb-40"
>
<text class="money-item-one">
{{ item.price || 0 }}
</text>
<text v-if="item.egold" class="money-item-to">
{{ item.egold || 0 }}k币
</text>
<text
class="money-item-three"
:class="{ 'mt-20': !item.egold }"
>
{{ item.title || '' }}
</text>
<view v-if="item.poster" class="tips flex-center">
<text class="tips-text"> {{ item.poster }} </text>
</view>
</view>
</view>
<view
class="payWay flex-row mt-30"
style="justify-content: space-between;align-items: center;"
>
<text class="payWay-text"> 支付方式 </text>
<view class="flex-row">
<u-icon
class="mr-20"
name="/static/icon/wx.png"
size="48rpx"
/>
<text class="payWay-wx"> 微信支付 </text>
</view>
</view>
</view>
<view class="warning">
<text class="warning-one mb-20"> 温馨提示 </text>
<text class="warning-to mb-20">
1IP和书币属于虚拟商品,一旦购买不作退换,望周知
</text>
<view style="display: inline-block;">
<span class="warning-to"
>2充值后书币到账可能有延迟15分钟内未到账请联系微信客服微信号:</span
>
<span class="warning-three"> yttfyyl, yt20216688 </span>
<span class="warning-to"
>工作时间:周一到周五9:00-17:00</span
>
</view>
</view>
<!-- #ifndef H5 -->
<u-gap height="80" />
<!-- #endif -->
</GList>
<GTopUpActivity ref="GTopUpActivity" @success="payItem" />
</view>
</template>
<script>
import { paysetting, payback, getTiktokpay } from '@/api/index.js';
export default {
data() {
return {
payList: [],
egold: 0,
backClickIndex: 0,
sid: ''
};
},
onLoad({ sid }) {
this.sid = sid;
},
onShow() {
this.backClickIndex = 0;
this.getPayList();
const isPopup = uni.getStorageSync('isPopup');
if (isPopup) {
payback().then(res => {
setTimeout(() => {
this.payList.unshift({ ...res, isback: 1 });
this.$refs.GTopUpActivity.open(res).then(() => {});
this.backClickIndex++;
}, 500);
});
} else {
uni.setStorageSync('isPopup', true);
}
},
onBackPress(e) {
return false;
},
onNavigationBarButtonTap() {
console.log(111);
},
methods: {
getPayList() {
paysetting().then(res => {
this.egold = res.egold;
this.payList = res.list;
});
},
getkActivity() {
if (this.backClickIndex === 0) {
payback().then(res => {
this.payList.unshift({ ...res, isback: 1 });
this.$refs.GTopUpActivity.open(res).then(() => {
console.log(11);
});
this.backClickIndex++;
});
} else {
if (this.sid) {
uni.redirectTo({
url: '/pages/video/index?sid=' + this.sid
});
} else {
uni.switchTab({
url: this.path || '/pages/my/index/index'
});
}
}
},
payItem(item) {
getTiktokpay({
id: item.id,
isback: item.isback === 1 ? 1 : 0
}).then(res => {
console.log(res);
const orderInfo = {
order_id: res.order_id,
order_token: res.order_token
};
tt.pay({
orderInfo,
service: 5,
success: res => {
console.log(res);
if (res.code == 0) {
uni.showToast({
title: '支付成功',
duration: 2000
});
paysetting().then(res => {
this.egold = res.egold;
uni.setStorageSync('isPopup', false);
const eventChannel = this.getOpenerEventChannel();
eventChannel.emit('paySuccess', {
egold:res.egold
});
uni.navigateBack();
});
// res.code=0
//
}
},
fail: () => {
uni.showToast({
title: '支付失败,请重新支付',
duration: 2000
});
}
});
});
}
}
};
</script>
<style lang="scss">
.header {
height: 282rpx;
background: linear-gradient(88deg, #fad2d2 0%, #fae3d2 51%, #fae3d2 100%);
padding: 40rpx 30rpx;
}
.money {
position: relative;
background: #ffffff;
border-radius: 48rpx 48rpx 0px 0px;
padding: 70rpx 30rpx;
margin-top: -56rpx;
z-index: 99;
}
.header-img {
width: 238rpx;
height: 238rpx;
}
.balance-text {
font-size: 34rpx;
font-weight: bold;
color: #1a1a1a;
}
.balance-num {
font-size: 62rpx;
color: #ff002e;
font-weight: bold;
}
.balance-unit {
font-size: 34rpx;
color: #1a1a1a;
margin-left: 10rpx;
}
.money-title {
font-size: 36rpx;
font-weight: bold;
color: #1a1a1a;
margin-bottom: 48rpx;
}
.moneyList {
flex-wrap: wrap;
}
.money-item {
position: relative;
width: 328rpx;
height: 194rpx;
border-radius: 24rpx;
border: 1rpx solid #aaaaaa;
&.active {
background: #ff7246;
border: 0;
.money-item-one {
color: #ffffff;
}
.money-item-to {
color: #ffffff;
}
.money-item-three {
color: #ffffff;
}
}
}
.tips {
position: absolute;
top: -25rpx;
left: -2rpx;
width: 140rpx;
height: 48rpx;
background: #ffbd12;
border-radius: 24rpx 0px 24rpx 0px;
}
.tips-text {
font-size: 26rpx;
font-weight: 400;
color: #1a1a1a;
}
.money-item-one {
font-size: 40rpx;
font-weight: bold;
color: #1a1a1a;
line-height: 46rpx;
}
.money-item-to {
font-size: 28rpx;
font-weight: 400;
color: #666666;
line-height: 32rpx;
margin: 8rpx 0;
}
.money-item-three {
font-size: 28rpx;
font-weight: 500;
color: #ff779e;
line-height: 32rpx;
}
.payWay-text {
font-size: 36rpx;
font-weight: bold;
color: #1a1a1a;
}
.payWay-wx {
font-size: 36rpx;
font-weight: bold;
color: #28c445;
}
.warning {
background-color: #ffffff;
padding: 52rpx 30rpx;
.warning-one {
font-size: 32rpx;
font-weight: 500;
color: #1a1a1a;
}
.warning-to {
font-size: 28rpx;
font-weight: 400;
color: #999999;
}
.warning-three {
font-size: 28rpx;
font-weight: 400;
color: #ff779e;
}
}
.title {
font-size: 40rpx;
font-weight: 500;
color: #130f26;
}
</style>

View File

@ -0,0 +1,170 @@
<template>
<GList
class="flex-1"
style=" background: #F1F2F4;;"
:scroll-top="scrollTop"
>
<view>
<view class="banner px-20 flex-center">
<image
class="flex-1"
style="width: 730rpx;"
src="@/static/images/signIn.png"
mode="aspectFit"
@click="signIn"
/>
</view>
<view class="myPursue mb-40">
<view class="header mb-28">
<text class="header-text">
我的追剧
</text>
<view
v-if="dataList.bookcase.length || isEdit"
class="flex-row flex-center"
@click="editPursue"
>
<u-icon
size="36rpx"
name="/static/icon/pursue-edit.png"
/>
<text class="header-edit">
{{ isEdit ? '完成' : '编辑' }}
</text>
</view>
</view>
<view
v-if="dataList.bookcase.length !== 0"
class="flex-row GpursueData"
>
<GpursueItem
v-for="(item, index) in dataList.bookcase"
:key="index"
:is-edit="isEdit"
:data="item"
:class="(index + 1) % 3 === 0 ? 'mb-28' : 'mb-28 mr-20'"
@del="delItem"
/>
</view>
<GNoData
v-else
text="去追剧~"
/>
</view>
<view class="myPursue mb-60">
<view class="header mb-28">
<text class="header-text">
精选推荐
</text>
</view>
<view class="flex-row GpursueData">
<GpursueItem
v-for="(item, index) in dataList.likelist"
:key="index"
:class="(index + 1) % 3 === 0 ? 'mb-28' : 'mb-28 mr-20'"
:data="item"
/>
</view>
</view>
</view>
<!-- #ifndef H5 -->
<u-gap height="80" />
<!-- #endif -->
</GList>
</template>
<script>
import { chasingdrama, signin, chasingdramadel } from '@/api/index.js';
export default {
props: {
tabIndex: {
type: Number,
default: 0
}
},
data() {
return {
dataList: {
likelist: [],
bookcase: []
},
isEdit: false,
editList: [],
scrollTop:0
};
},
watch: {
tabIndex() {
this.isEdit = false;
this.editList = [];
if(this.tabIndex === 0){
this.getList();
}
}
},
methods: {
signIn() {
signin().then(res => {
this.$emit('signIn', res);
});
},
getList() {
chasingdrama().then(res => {
this.dataList = res || { bookcase: [], likelist: [] };
});
},
editPursue() {
if (this.isEdit && this.editList.length !==0) {
const data = this.editList.join(',');
chasingdramadel({ ids: data }).then((ss) => {
this.editList = [];
});
}
this.isEdit = !this.isEdit;
},
delItem(e) {
if (this.isEdit) {
this.editList.push(e.articleid);
const index = this.dataList.bookcase.findIndex(
r => r.id === e.id
);
this.dataList.bookcase.splice(index, 1);
}
}
}
};
</script>
<style lang="scss">
.banner {
height: 190rpx;
width: 750rpx;
}
.myPursue {
padding: 40rpx 20rpx;
background: #ffffff;
border-radius: 10rpx;
margin: 0 20rpx;
.header {
flex-direction: row;
justify-content: space-between;
.header-text {
font-size: 36rpx;
font-weight: bold;
color: #1a1a1a;
}
.header-edit {
font-size: 30rpx;
font-weight: 500;
color: #1a1a1a;
margin-left: 6rpx;
}
}
.GpursueData {
flex-wrap: wrap;
}
}
</style>

View File

@ -0,0 +1,372 @@
<template>
<GList
class="flex-1"
:scroll-top="scrollTop"
@scroll="scrollGList"
>
<view style="position: relative;">
<view
v-if="dataList.history.cover"
class="television"
@click="getUserHistory"
>
<u-transition
:show="scrollTransition"
:mode="scrollTransition ? 'slide-left':'fade-left'"
duration="200"
>
<view
class="television-content"
style="align-items: center;"
>
<view
class="television-image flex-center"
:style="{background: `url(${dataList.history.cover})`, 'background-size': 'cover'}"
>
<image
src="@/static/images/play-history.png"
style="width: 66rpx;height: 66rpx;"
/>
</view>
</view>
</u-transition>
</view>
<view class="body-bg" />
<view class="banner mb-20">
<u-swiper
class=""
height="336rpx"
indicator
:list="dataList.ads"
key-name="cover"
interval="1500"
:autoplay="true"
circular
@click="bannerClick"
/>
</view>
<view class="px-20 flex-row playletItem ">
<GPlayletItem
v-for="(item, index) in dataList.module1"
:key="index"
:class="(index + 1) % 2 === 0 ? '' : 'mr-14 mb-20'"
:data="item"
/>
</view>
<view
class="card-playlet mb-24 "
style="overflow: hidden;"
>
<GSwiper
dot-mode="nav"
autoplay
:plus="2"
:circular="true"
:swiper-list="dataList.module2"
@change="GSwiperChange"
@itemClick="itemClick"
/>
<view class="mt-20">
<text class="card-playlet-title">
{{ module2Info.name || '-' }}
</text>
<text class="card-playlet-text text-three">
{{ module2Info.description || '' }}
</text>
</view>
</view>
<view class="px-20 flex-row playletItem mb-20">
<GPlayletItem
v-for="(item, index) in dataList.module3"
:key="index"
:class="(index + 1) % 2 === 0 ? '' : 'mr-14 mb-20'"
:data="item"
/>
</view>
<view class="rank mx-20 px-10">
<view class="flex-center mb-26">
<image
class="rank-title"
src="@/static/images/Group-rank.png"
mode="aspectFit"
/>
</view>
<view class="flex-row rankList">
<view
v-for="(item, index) in dataList.module4"
:key="index"
class="rankItem"
:class="(index + 1) % 3 === 0 ? 'mb-24' : 'mb-24 mr-22'"
@click="rankItem(item)"
>
<view class="rankItem-header">
<image
class="rankItem-header-img"
:src="item.cover"
mode="aspectFill"
/>
<image
class="rankItem-header-rank"
:src="rankImg[index]"
mode="aspectFill"
/>
<view class="bottom-right">
<text class="bottom-text">
{{ item.new || 0 }}集全
</text>
</view>
</view>
<view class="mt-10 ">
<text
class="fs-32 text-one"
style="color: #1A1A1A;"
>
{{ item.name }}
</text>
</view>
</view>
</view>
</view>
<view class="px-20 flex-row playletItem ">
<GPlayletItem
v-for="(item, index) in dataList.module5"
:key="index"
:class="(index + 1) % 2 === 0 ? '' : 'mr-14 mb-20'"
:data="item"
/>
</view>
<GFooter />
<!-- #ifndef H5 -->
<u-gap height="80" />
<!-- #endif -->
</view>
</GList>
</template>
<script>
import { getIndexList } from '@/api/index.js';
export default {
tabIndex: {
type: Number,
default: 0
},
data() {
return {
showLading: true,
triggered: false,
scrollTransition: true,
rankImg: [
require('@/static/images/rank_1.png'),
require('@/static/images/rank_2.png'),
require('@/static/images/rank_3.png'),
require('@/static/images/rank_4.png'),
require('@/static/images/rank_5.png'),
require('@/static/images/rank_6.png')
],
dataList: {
ads: [],
history: null,
module1: [],
module2: [],
module3: [],
module4: [],
module5: []
},
module2Index: 0,
time: null,
scrollTop:0
};
},
computed: {
module2Info() {
return this.dataList.module2[this.module2Index] || {};
}
},
methods: {
GSwiperChange(e) {
this.module2Index = e;
},
itemClick(e){
uni.navigateTo({
url: `/pages/video/index?sid=${e.id}`
});
},
getUserHistory(){
uni.navigateTo({
url: `/pages/video/index?sid=${this.dataList.history.sid}`
});
},
bannerClick(e) {
uni.navigateTo({
url: `/pages/video/index?sid=${this.dataList.ads[e].bookid}`
});
},
rankItem(e) {
uni.navigateTo({
url: `/pages/video/index?sid=${e.id}`
});
},
refresherrefreshHandler() {
this.triggered = true;
},
getList() {
getIndexList().then(res => {
this.dataList = res || {
ads: [],
history: null,
module1: [],
module2: [],
module3: [],
module4: [],
module5: []
};
});
},
scrollGList(e) {
this.scrollTransition = false;
clearTimeout(this.time);
this.time = setTimeout(() => {
this.scrollTransition = true;
}, 500);
//
const scrollTop = e;
let opacity = 1;
opacity = Math.min(1, 100 / scrollTop);
this.$emit('opacity', opacity);
}
}
};
</script>
<style lang="scss">
.header_bg {
position: fixed;
top: -6rpx;
left: 0;
width: 750rpx;
height: 614px;
z-index: 0;
}
.banner {
padding: 0 20rpx;
width: 750rpx;
height: 336rpx;
}
.playletItem {
flex-wrap: wrap;
}
.card-playlet {
margin: 0 20rpx;
padding: 24rpx 28rpx;
background: #ffffff;
border-radius: 10rpx;
.card-playlet-title {
font-size: 36rpx;
font-weight: bold;
color: #1a1a1a;
text-align: center;
margin-bottom: 8rpx;
}
.card-playlet-text {
font-size: 24rpx;
line-height: 56rpx;
font-weight: 400;
color: #666666;
text-align: center;
}
}
.rank {
background: linear-gradient(180deg, #ffecd7 0%, #ffffff 12%);
border-radius: 10rpx;
padding-top: 36rpx;
margin-bottom: 20rpx;
}
::v-deep .card-playlet .uni-swiper-slides {
width: 336rpx;
height: 452rpx;
border-radius: 10rpx;
}
.rank-title {
width: 300rpx;
height: 60rpx;
}
.rankList {
flex-wrap: wrap;
}
.rankItem {
width: 214rpx;
}
.rankItem-header {
position: relative;
height: 286rpx;
width: 214rpx;
border-radius: 10rpx;
overflow: hidden;
.rankItem-header-img {
position: absolute;
top: 2rpx;
left: 0;
height: 284rpx;
width: 214rpx;
}
.rankItem-header-rank {
position: absolute;
width: 74rpx;
height: 48rpx;
top: 0;
left: 0;
}
.bottom-right {
position: absolute;
bottom: 0;
right: 0;
padding: 20rpx 10rpx;
.bottom-text {
font-size: 24rpx;
color: #ffffff;
text-shadow: 0px 0px 4rpx rgba(0, 0, 0, 0.25);
}
}
}
.body-bg {
position: absolute;
top: -2rpx;
width: 750rpx;
z-index: 0;
height: 346rpx;
background: url('https://diyyhdapi.qinjiu8.com/backImg.png');
background-size: 100% 100%;
}
.television {
width: 158rpx;
height: 168rpx;
position: fixed;
bottom:100rpx;
left: 0rpx;
z-index: 999;
}
.television-content {
width: 198rpx;
height: 208rpx;
background: url('https://diyyhdapi.qinjiu8.com/television.png');
background-size: 100% 100%;
padding-top: 58rpx;
}
.television-image {
height: 119rpx;
width: 123rpx;
border-radius: 32rpx;
}
</style>

209
pages/playlet/index.vue Normal file
View File

@ -0,0 +1,209 @@
<template>
<view class="flex-1">
<GLoading />
<view
class="header_tabs flex-row px-20"
:style="{
background: `linear-gradient(93deg, rgba(255, 220, 230, ${
swiperIndex === 0 ? backOpacityOne : backOpacity
}) 45%, rgba(255, 238, 195, ${
swiperIndex === 0 ? backOpacityOne : backOpacity
}))`
}"
>
<view class="">
<u-tabs
:list="tabList"
:inactive-style="{
fontSize: '34rpx',
color: '#666666',
fontWeight: 500
}"
:current="swiperIndex"
:active-style="{
color: '#1A1A1A',
fontSize: '40rpx',
fontWeight: 'bold'
}"
:item-style="{
'padding-left':0,
'padding-right':'50rpx'
}"
line-height="0"
@click="tabsClick"
/>
</view>
<view
class="search"
@click="navSearch"
>
<view
class="search-view flex-row"
style="align-items: center;"
>
<u-icon
name="/static/icon/search.png"
size="24rpx"
/>
<text class="search-text">
寻找你喜欢的短剧
</text>
</view>
</view>
</view>
<swiper
class="flex-1"
:current="swiperIndex"
@change="swiperChange"
>
<swiper-item>
<Pursue
ref="Pursue"
:tab-index="swiperIndex"
@signIn="signIn"
/>
</swiper-item>
<swiper-item>
<Recommend
ref="Recommend"
:tab-index="swiperIndex"
@opacity="opacity"
/>
</swiper-item>
</swiper>
<GSignMadel ref="GSignMadel" />
</view>
</template>
<script>
import Recommend from './components/recommend.vue';
import Pursue from './components/pursue.vue';
import { reg } from '@/api/index.js';
export default {
components: { Recommend, Pursue },
data() {
return {
tabList: [
{
name: '追剧'
},
{
name: '推荐'
}
],
keyword: '',
swiperIndex:1,
backOpacity: 1,
backOpacityOne: 0,
time: null
};
},
computed: {
show() {
return this.$store.state.loading;
}
},
onShow() {
setTimeout(() => {
this.$showLoading(false);
}, 1000);
if(this.swiperIndex === 1){
setTimeout(()=>{
this.$refs.Recommend.getList();
},500);
} else {
setTimeout(()=>{
this.$refs.Pursue.getList();
},500);
}
},
onLoad() {
const uid = uni.getStorageSync('uid')|| '';
if(!uid){
uni.login({
success: function(loginRes) {
reg({
code:loginRes.code
}).then(res=>{
uni.setStorageSync('uid', res.uid );
});
}
});
}
},
methods: {
swiperChange(e) {
const index = e.detail.current;
if (this.swiperIndex !== index) {
this.swiperIndex = index;
}
},
tabsClick(e) {
const index = e.index;
if (this.swiperIndex !== index) {
this.swiperIndex = index;
}
},
navSearch() {
uni.navigateTo({
url: '/pages/search/search'
});
},
signIn(e) {
this.$refs.GSignMadel.open(e).then(() => {
this.swiperIndex = 1;
});
},
opacity(e) {
if (this.swiperIndex === 1) {
this.backOpacity = e;
}
}
}
};
</script>
<style lang="scss">
.header_bg {
position: fixed;
top: -6rpx;
left: 0;
width: 750rpx;
height: 614px;
z-index: 0;
}
.header_tabs {
z-index: 999;
height: 90rpx;
justify-content: space-between;
align-items: center;
.search {
width: 470rpx;
}
.search-view {
width: 470rpx;
height: 60rpx;
background: #ffffff;
padding: 0 28rpx;
border-radius: 60rpx;
}
.search-text {
font-size: 26rpx;
font-weight: 400;
color: #999999;
margin-left: 16rpx;
}
}
</style>

213
pages/search/search.vue Normal file
View File

@ -0,0 +1,213 @@
<template>
<view class="flex-1 px-30">
<view
class="search-content flex-row"
style="align-items: center;"
>
<view class="search-center flex-row">
<u-search
v-model="keyword"
bg-color="transparent"
class="flex-1"
:show-action="false"
height="80rpx"
placeholder="输入你想看的剧名"
@search="searchHandler"
/>
<view
class="search-btn flex-center"
@click="searchHandler"
>
<text class="search-btn-text">
搜索
</text>
</view>
</view>
</view>
<view
v-if="status === 2"
class="searchResult"
>
<text class="searchResult-title">
搜索结果
</text>
<view
v-if="searchList.length !== 0"
class="flex-row"
style="flex-wrap: wrap;"
>
<GpursueItem
v-for="(item, index) in searchList"
:key="index"
:class="{'mr-26':(index + 1) % 3 !==0}"
:data="item"
/>
</view>
<GNoData
v-else
image="no-search"
text="没有搜到相关短剧~"
/>
</view>
<view
v-else
class="search-history"
>
<view
class="search-history-title flex-row"
style="align-items: center;justify-content: space-between;"
>
<text class="search-history-title-text">
历史搜索
</text>
<u-icon
name="/static/icon/delete.png"
size="40rpx"
@click="clearHistoryList"
/>
</view>
<view
class="historyData flex-row py-20"
style="flex-wrap: wrap;"
>
<view
v-for="(item, index) in historySearch"
:key="index"
class="historyItem"
@click="navigator(item)"
>
<text class="historyItem-text">
{{ item }}
</text>
</view>
</view>
</view>
<GModal ref="modal" />
</view>
</template>
<script>
import { searchFilm } from '@/api/index.js';
export default {
data() {
return {
status: 0, // 0 1 2
keyword: '',
historySearch: [],
searchList: []
};
},
onLoad() {
this.historySearch = uni.getStorageSync('historySearch') || [];
},
methods: {
setHistorySearch(historySearch = []) {
this.historySearch = historySearch;
uni.setStorageSync('historySearch', this.historySearch);
},
clearHistoryList() {
this.$refs.modal.open('你确定要删除历史记录吗').then(() => {
this.setHistorySearch([]);
});
},
searchHandler() {
if (this.keyword.trim()) {
this.navigator(this.keyword);
} else {
uni.showToast({
title: '搜索内容不能为空',
icon: 'none'
});
}
},
navigator(item) {
const index = this.historySearch.indexOf(item);
this.keyword = item;
this.status = 2;
uni.hideKeyboard();
if (index !== -1) {
this.historySearch.splice(index, 1);
this.historySearch.unshift(item);
} else if (this.historySearch.length >= 10) {
this.historySearch.pop();
this.historySearch.unshift(item);
} else {
this.historySearch.unshift(item);
}
uni.setStorageSync('historySearch', this.historySearch);
uni.hideKeyboard();
searchFilm({ keyword: this.keyword }).then(res => {
this.searchList = res || [];
});
}
}
};
</script>
<style lang="scss">
.search-content {
height: 144rpx;
}
.search-center {
width: 690rpx;
height: 80rpx;
background: #f3f4f6;
border-radius: 52rpx;
align-items: center;
}
.search-btn {
width: 136rpx;
height: 72rpx;
background: linear-gradient(158deg, #ff8197 0%, #ff3364 100%);
border-radius: 36rpx;
.search-btn-text {
font-size: 36rpx;
font-weight: 400;
color: #ffffff;
}
}
.search-history-title-text {
font-size: 32rpx;
font-weight: bold;
color: #1a1a1a;
}
.historyItem {
padding: 8rpx 20rpx;
background: #f3f3f3;
border-radius: 58rpx;
margin-right: 20rpx;
margin-bottom: 20rpx;
}
.historyItem-text {
font-size: 28rpx;
font-weight: 400;
color: #1a1a1a;
}
.inTheSearch-img {
width: 244rpx;
height: 136rpx;
border-radius: 16rpx;
}
.inTheSearch-title {
font-size: 36rpx;
font-weight: 400;
color: #1a1a1a;
}
.inTheSearch-num {
font-size: 28rpx;
font-weight: 400;
color: #999999;
}
.searchResult-title {
font-size: 32rpx;
font-weight: bold;
color: #1a1a1a;
margin-bottom: 20rpx;
}
</style>

View File

@ -0,0 +1,291 @@
<template>
<u-popup
:show="show"
round="20"
@open="open"
@close="show=false"
>
<view class="content px-30">
<view
class="flex-row mb-40"
style="justify-content: space-between; "
>
<view style="flex-direction:row;align-items: center;">
<text class="title">
{{ watchInfo.title }}
</text>
<text class="num ml-40">
{{ listThen }}
</text>
</view>
<image
src="@/static/icon/arrowBottom.png"
mode="aspectFill"
style="width:44rpx;height: 44rpx;"
@click="close"
/>
</view>
<u-tabs
:list="list"
line-width="0"
line-height="0"
:current="tabIndex"
:inactive-style="{
width: '150rpx',
height: '64rpx',
'border-radius': '32rpx',
background: '#f8f8f8',
'text-align': 'center',
'line-height': '64rpx',
color: '#666666',
padding: 0,
marginRight: '20rpx'
}"
:active-style="{
width: '150rpx',
height: '64rpx',
'border-radius': '32rpx',
background: '#FFE5EB',
'text-align': 'center',
'line-height': '64rpx',
color: '#FF779E',
padding: 0,
marginRight: '20rpx'
}"
:item-style="{
padding: 0
}"
@click="tabClick"
/>
<view class="sidContent flex-1">
<swiper
class="flex-1"
:current="tabIndex"
style="height: 900rpx;"
@change="swiperChange"
>
<swiper-item
v-for="(each, index) in anthologyList"
:key="index"
class="flex-1"
>
<scroll-view
scroll-y="true"
style="height: 900rpx;"
class="mt-30"
:scroll-into-view="toview"
:scroll-with-animation="true"
>
<view
class="flex-row"
style="flex-wrap: wrap;padding-bottom: 60rpx;"
>
<view
v-for="(item, i) in each"
:id="`video-${index}-${i}`"
:key="i"
class="sidContent-item"
:style="
(i + 1) % 3 != 0
? 'margin-right: 30rpx;'
: ''
"
:class="
item.id == current.id ? 'check' : ''
"
@click="seeSidContent(item.id)"
>
<image
style="width: 210rpx;height: 288rpx;"
:src="watchInfo.cover"
mode="aspectFill"
/>
<view
v-if="
item.isvip == 1 ||
item.id == current.id
"
class="flex-center"
style="width: 210rpx;height: 288rpx;position: absolute;top: 0;left:0;background-color: rgba(26, 26, 26, 0.4);"
>
<u-icon
v-if="item.isvip == 1"
name="/static/images/videoLock.png"
size="64rpx"
/>
<u-icon
v-else-if="item.id == current.id"
name="/static/images/playIcon.gif"
size="100rpx"
/>
</view>
<view class="jishu flex-center">
<text class="jishu-text">
{{ item.order }}
</text>
</view>
</view>
</view>
</scroll-view>
</swiper-item>
</swiper>
</view>
</view>
</u-popup>
</template>
<script>
import {episode} from '@/config/index.js';
export default {
data() {
return {
show: false,
tabIndex: 0,
list: [
],
anthologyList: [[], [], [], []],
reject: null,
resolve: null,
current: {},
timer: null,
dataList: [],
watchInfo: {},
listThen: 0,
toview: ''
};
},
methods: {
tabClick(e) {
if (this.tabIndex !== e.index) {
this.tabIndex = e.index;
}
},
swiperChange(e) {
const index = e.detail.current;
if (this.tabIndex !== index) {
this.tabIndex = index;
}
},
open(list, index, watchInfo) {
return new Promise((resolve, reject) => {
const data = list || [];
if (data.length) {
this.listThen = data.length;
this.current = data[index];
this.watchInfo = watchInfo;
this.list = [];
let arr = [];
for (var i = 0; i < data.length; i += episode) {
arr.push(data.slice(i, i + episode));
}
arr.forEach((r, i) => {
if (i === 0) {
this.list.push({
name: `01-${(i + 1) * episode}`
});
}
if (i > 0) {
this.list.push({
name: `${i * episode + 1}-${(i + 1) * episode}`
});
}
if (arr.length === i + 1) {
this.list[i].name = `${i === 0 ? '1' : i * episode + 1}-${
data.length
}`;
}
});
this.show = true;
arr.forEach((item, index) => {
item.forEach((each, i) => {
if (each.id === this.current.id) {
this.tabIndex = index;
this.toview = `video-${index}-${i}`;
}
});
});
this.anthologyList = arr || [[]];
this.reject = reject;
this.resolve = resolve;
}
});
},
close() {
this.reject();
this.show = false;
// console.log('close');
},
seeSidContent(id) {
clearTimeout(this.timer);
this.timer = setTimeout(() => {
this.resolve(id);
this.show = false;
});
}
}
};
</script>
<style lang="scss">
.content {
width: 750rpx;
height: 1100rpx;
background: linear-gradient(180deg, #ffe2e2 0%, #ffffff 11%);
border-radius: 40rpx 40rpx 0px 0px;
box-shadow: 0px -11px 17px 0px rgba(0, 0, 0, 0.2);
padding-top: 56rpx;
.title {
font-size: 36rpx;
font-weight: bold;
color: #222222;
}
.num {
font-size: 26rpx;
font-weight: 400;
color: #222222;
}
.select {
margin-top: 60rpx;
font-size: 36rpx;
font-weight: bold;
color: #1a1a1a;
}
.sidContent {
flex-direction: row;
flex-wrap: wrap;
.sidContent-item {
width: 210rpx;
height: 288rpx;
background: #eeeeee;
border-radius: 16rpx;
color: #1a1a1a;
flex-direction: row;
align-items: center;
justify-content: center;
margin-bottom: 32rpx;
overflow: hidden;
position: relative;
}
.check {
background: #ff779e !important;
color: #ffffff;
}
}
}
.jishu {
position: absolute;
bottom: 0;
width: 210rpx;
height: 54rpx;
background-color: rgba(26, 26, 26, 0.7);
.jishu-text {
color: #ffffff;
font-size: 14px;
}
}
</style>

View File

@ -0,0 +1,186 @@
<template>
<u-popup
:show="show"
round="40rpx"
@open="open"
>
<view class="content px-30">
<view class="flex-row">
<u--image
:src="current.cover || ''"
width="212rpx"
height="300rpx"
radius="24rpx"
/>
<view
class="ml-20"
style="justify-content: center;"
>
<text
class="fs-40"
style="color: #fff;font-weight: bold;"
>
{{ current.title || '' }}
</text>
<text
class="fs-28 mt-20"
style="color: #DDDDDD;"
>
感谢您支持作者购买后继续观看
</text>
<view
class="flex-row mt-20 mb-20"
style="align-items: center;"
>
<text
class="fs-28"
style="color: #DDDDDD;"
>
我的余额:
</text><text
class="fs-28 mx-10"
style="color: #DDDDDD;"
>
{{ current.useregold }}
</text>
<text
class="fs-28"
style="color: #DDDDDD;"
>
K币
</text>
</view>
<view
class="flex-row"
style="align-items: flex-end;"
>
<text
class="fs-26"
style="color: #dddddd;"
>
专享价
</text>
<text
class="fs-48 mx-10"
style="color: #ffffff;font-weight: bold;"
>
{{ current.allprice }}
</text>
<text
class="fs-24"
style="color: #ffffff;"
>
K币
</text>
</view>
</view>
</view>
<view
class="lock flex-center mt-50"
@click="lockAll"
>
<text class="lock-text">
解锁全集
</text>
</view>
</view>
</u-popup>
</template>
<script>
import { buyall } from '@/api/index.js';
export default {
data() {
return {
show: false,
reject: null,
resolve: null,
current: {
id: '',
cover: '',
title: '',
useregold: 0,
allprice: 0
},
timer: null
};
},
methods: {
tabClick(e) {
if (this.tabIndex !== e.index) {
this.tabIndex = e.index;
}
},
open(data) {
if (data) {
this.current = data || {
cover: '',
title: '',
useregold: 0,
allprice: 0
};
this.show = true;
}
},
close() {
this.reject();
this.show = false;
},
lockAll() {
const params = {
sid: this.current.sid,
id: this.current.id,
allprice: this.current.allprice
};
buyall(params).then(res => {
if (res.status === 2) {
uni.navigateTo({
url: '/pages/pay/pay?sid=' + this.current.sid,
events: {
paySuccess: data => {
this.current.useregold = data.egold;
this.show=false;
}
}
});
} else if (res.status === 1) {
this.$emit('success');
this.show = false;
}
});
}
}
};
</script>
<style lang="scss">
.content {
width: 750rpx;
height: 594rpx;
background: #ffffff;
border-radius: 40rpx 40rpx 0px 0px;
padding-top: 50rpx;
background: linear-gradient(205deg, #b95b17 0%, #1a1922 100%);
.lock {
height: 94rpx;
background: linear-gradient(180deg, #fba676 0%, #e95e32 100%);
border-radius: 24rpx;
animation: rotate 0.7s infinite;
}
.lock-text {
font-size: 36rpx;
font-weight: bold;
color: #ffffff;
}
@keyframes rotate {
0% {
transform: scale(1);
}
20% {
transform: scale(0.95);
}
100% {
transform: scale(1);
}
}
}
</style>

453
pages/video/index.vue Normal file
View File

@ -0,0 +1,453 @@
<template>
<view
class="flex-1"
style="background-color: #000000;"
>
<GLoading :back-color="'#000'" />
<swiper
:duration="500"
vertical
class="flex-1"
:current="currentWatchIndex"
:disable-touch="true"
@change="videoChange"
>
<swiper-item
v-for="(item, index) in videoList"
:key="index"
class="flex-1"
@touchmove.stop="stopTouchMove"
>
<!-- 视频 -->
<video
v-if="Math.abs(currentWatchIndex - index) <= 1"
:id="`video_${item.id}`"
:ref="'item' + index"
:poster="item.cover"
:enable-progress-gesture="false"
style="width: 750rpx;"
class="flex-1"
:controls="watchInfo.id === item.id"
:src="item.video_url"
:play-strategy="1"
:show-fullscreen-btn="false"
@play="videoPlay"
/>
</swiper-item>
</swiper>
<view
v-if="watchInfo.order"
class="jishu1"
>
<text
style="color: #fff;"
class="fs-32"
>
{{ watchInfo.order }}
</text>
</view>
<view class="ops">
<view
class="flex-center"
@click="chaseKeep"
>
<view
class="animation"
:class="'animation-' + animation"
>
<u-icon
v-if="watchInfo.iskeep === 0"
name="/static/icon/keep-on.png"
size="68rpx"
/>
<u-icon
v-else
name="/static/icon/keep-off.png"
size="68rpx"
/>
</view>
<text
class="fs-28 mt-10"
style="color: #FFF;"
>
追剧
</text>
</view>
<view
class="flex-center mt-32"
@click="completeWorksShow"
>
<u-icon
name="/static/icon/xuanji.png"
size="68rpx"
/>
<text
class="fs-28 mt-10"
style="color: #FFF;"
>
选集
</text>
</view>
</view>
<completeWorks
ref="completeWorks"
style="position: fixed;"
/>
<Payment
ref="Payment"
style="position: fixed;"
@success="paySuccess"
/>
</view>
</template>
<script>
import completeWorks from './components/completeWorks.vue';
import Payment from './components/payment.vue';
import { batchlist, videoread, addkeep, chasingdramadel } from '@/api/index.js';
export default {
components: {
completeWorks,
Payment
},
data() {
return {
videoList: [],
currentWatchIndex: 0,
currenttimes: 0,
touchNum: 0,
ProgressBarOpacity: 0.7, //
dotWidth: 0, //
oldVideo: null,
voice: '', //🌟 setTimeout()
timeout: '', //🌟 setTimeout()
videoTimes: '', //00:30💗
changeTime: '', //💗
params: {},
watchInfo: {},
animation: '',
pageStartY: 0,
pageEndY: 0,
};
},
onLoad(ops) {
this.$showLoading(true);
this.params = ops;
},
watch: {
async currentWatchIndex(index, old_index) {
this.$showLoading(true);
const oldData = this.videoList[old_index];
const currentData = this.videoList[index];
const pData = this.videoList[index + 1];
this.params.id = currentData.id;
videoread(this.params).then(res => {
uni.createVideoContext(`video_${oldData.id}`, this).pause();
const result = res[0];
this.watchInfo = result;
if (result.isvip === 1 && result.chackpay === 3) {
this.$refs.Payment.open(result);
} else if (result.isvip === 1 && result.chackpay === 2) {
//
uni.createVideoContext(`video_${oldData.id}`, this).pause();
uni.createVideoContext(
`video_${currentData.id}`,
this
).pause();
const that = this;
uni.navigateTo({
url: '/pages/pay/pay?sid=' + result.sid,
events: {
paySuccess: () => {
console.log(index);
clearTimeout(that.timeout);
that.timeout = setTimeout(() => {
uni.createVideoContext(
`video_${oldData.id}`,
that
).pause();
}, 50);
this.init(this.params);
}
}
});
} else if (
result.isvip === 0 ||
(result.isvip === 1 && result.chackpay === 1)
) {
currentData.isvip = 0; //
oldData.state = 'pause'; //
oldData.playIng = false; //
oldData.isplay = true;
currentData.state = 'play';
console.log(`video_${currentData.id}`);
clearTimeout(this.timeout);
this.timeout = setTimeout(() => {
this.pageStartY = 0;
this.pageEndY = 0;
uni.createVideoContext(
`video_${oldData.id}`,
this
).pause();
uni.createVideoContext(
`video_${currentData.id}`,
this
).play();
}, 50);
if (pData) {
uni.createVideoContext(
`video_${pData.id}`,
this
).pause();
}
}
this.$showLoading(false);
});
}
},
onShow() {
this.init(this.params);
},
methods: {
init(ops) {
const isPopup = uni.getStorageSync('isPopup');
if (isPopup) {
const currentData = this.videoList[this.currentWatchIndex];
uni.createVideoContext(`video_${currentData.id}`, this).pause();
setTimeout(() => {
uni.navigateTo({
url: '/pages/pay/pay'
});
}, 1000);
return;
}
batchlist({ sid: ops.sid }).then(res => {
res.forEach(r => {
r.state = 'continues';
r.playIng = false;
r.isplay = false;
r.isShowimage = false;
r.isShowProgressBarTime = false;
});
this.videoList = res;
videoread(ops).then(data => {
const result = data[0];
this.watchInfo = result;
this.currentWatchIndex = 0;
const index = this.videoList.findIndex(
r => r.id === result.id
);
setTimeout(() => {
if (result.isvip === 1 && result.chackpay === 3) {
if (this.currentWatchIndex !== index) {
this.currentWatchIndex = index;
}
this.$refs.Payment.open(result);
} else if (
result.isvip === 1 &&
result.chackpay === 2
) {
//
this.currentWatchIndex = index;
} else if (
result.isvip === 0 ||
(result.isvip === 1 && result.chackpay === 1)
) {
if (this.currentWatchIndex !== index) {
this.currentWatchIndex = index;
}
setTimeout(() => {
this.videoList[index].isvip = 0; //
// bug
uni.createVideoContext(
`video_${this.videoList[index].id}`,
this
).seek(0);
uni.createVideoContext(
`video_${this.videoList[index].id}`,
this
).play();
this.videoList[index].state = 'play';
this.videoList[index].playIng = true;
this.videoList[index].isplay = true;
}, 200);
}
this.$showLoading(false);
}, 1000);
});
});
},
videoPlay() {},
stopTouchMove() {
return false;
},
//
stopChange(res) {
//
console.log(res);
return false;
},
touchStart(res) {
this.pageStartY = res.changedTouches[0].pageY;
console.log('touchStart' + this.pageStartY);
},
touchEnd(res) {
this.pageEndY = res.changedTouches[0].pageY;
console.log('touchEnd' + this.pageEndY);
let platform = uni.getSystemInfoSync().platform;
if (platform == 'android') {
if (this.pageStartY - this.pageEndY > 150) {
console.log('向上滑动:');
if (this.wrapIndex < this.videoList.length - 1) {
this.wrapIndex = this.wrapIndex + 1;
}
} else if (this.pageStartY - this.pageEndY < -150) {
console.log('向下滑动:');
if (this.wrapIndex > 1) {
this.wrapIndex = this.wrapIndex - 1;
}
}
}
},
chaseKeep() {
let fn = null;
let params = {};
if (this.watchInfo.iskeep === 0) {
fn = addkeep;
params = {
id: this.watchInfo.id,
sid: this.watchInfo.sid
};
} else {
fn = chasingdramadel;
params = {
ids: this.watchInfo.sid
};
}
fn(params).then(() => {
this.watchInfo.iskeep = this.watchInfo.iskeep === 0 ? 1 : 0;
if (this.watchInfo.iskeep === 1) {
clearTimeout(this.voice);
this.animation = 'shake';
this.voice = setTimeout(() => {
this.animation = '';
}, 100);
}
});
},
videoChange(e) {
const index = e.detail.current;
if (index !== this.currentWatchIndex) {
this.currentWatchIndex = index;
}
},
completeWorksShow() {
this.$refs.completeWorks
.open(this.videoList, this.currentWatchIndex, this.watchInfo)
.then(res => {
const index = this.videoList.findIndex(r => r.id === res);
this.currentWatchIndex = index;
});
},
paySuccess() {
const currentData = this.videoList[this.currentWatchIndex];
this.videoList.forEach(r => {
r.isvip = 0;
});
uni.createVideoContext(`video_${currentData.id}`, this).play();
},
back() {
const data = uni.getStorageSync('videoBackRouter');
if (data.type === 1) {
uni.switchTab({
url: data.url
});
} else if (data.type === 2) {
uni.reLaunch({
url: data.url
});
}
}
}
};
</script>
<style lang="scss">
.header {
padding: 0 32rpx;
height: 88rpx;
background: #000000;
justify-content: center;
.header-text {
font-size: 28rpx;
font-weight: bold;
color: #ffffff;
}
}
.bottom {
flex-direction: row;
align-items: center;
justify-content: space-between;
height: 100rpx;
padding: 0 30rpx;
background-color: #232323;
.bottom-text {
font-size: 28rpx;
font-weight: 500;
color: #ffffff;
}
}
.ops {
position: fixed;
right: 34rpx;
bottom: 300rpx;
}
.animation-shake {
animation: shake 0.3s !important;
}
@keyframes shake {
0% {
transform: scale(1);
}
20% {
transform: scale(0.95);
}
40% {
transform: scale(0.8);
}
60% {
transform: scale(0.7);
}
80% {
transform: scale(0.8);
}
100% {
transform: scale(1);
}
}
.stopTouchMove {
position: fixed;
width: 750rpx;
height: 100%;
top: 0;
z-index: 999999;
}
.videoBack {
position: fixed;
top: 20rpx;
left: 20rpx;
width: 72rpx;
height: 72rpx;
}
.jishu1 {
position: fixed;
top: 35rpx;
left: 40rpx;
}
</style>

BIN
static/icon/add.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 B

BIN
static/icon/arrowBottom.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 938 B

BIN
static/icon/arrowLeft.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 420 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 379 B

BIN
static/icon/arrowRight.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 412 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 914 B

BIN
static/icon/attention.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
static/icon/delete.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 803 B

BIN
static/icon/gold.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
static/icon/history.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
static/icon/hot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 808 B

BIN
static/icon/keep-off.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
static/icon/keep-on.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
static/icon/pursue-edit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
static/icon/pursue.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
static/icon/search.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 868 B

BIN
static/icon/service.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
static/icon/share.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
static/icon/success.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 465 B

BIN
static/icon/wallet.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
static/icon/wx.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
static/icon/xuanji.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 935 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

BIN
static/images/avatar.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
static/images/backImg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 KiB

BIN
static/images/close.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
static/images/discover.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

BIN
static/images/edit-show.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
static/images/gold.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

BIN
static/images/hign.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

BIN
static/images/loading.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

BIN
static/images/lock.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 692 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
static/images/member.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

BIN
static/images/no-data.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

BIN
static/images/no-search.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
static/images/play.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

BIN
static/images/playIcon.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
static/images/rank_1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
static/images/rank_2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

BIN
static/images/rank_3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

BIN
static/images/rank_4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
static/images/rank_5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
static/images/rank_6.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
static/images/recommend.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

BIN
static/images/signIn.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
static/images/videoBack.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 926 B

BIN
static/images/videoLock.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Some files were not shown because too many files have changed in this diff Show More