我的订单+我的
This commit is contained in:
15
components/api/ip.js
Normal file
15
components/api/ip.js
Normal file
@@ -0,0 +1,15 @@
|
||||
export function getIP (data) {
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.request({
|
||||
url: 'https://logger-data.csslcloud.net/api/detection',
|
||||
data,
|
||||
success: (res) => {
|
||||
if (res.error) {
|
||||
reject(res.data)
|
||||
} else {
|
||||
resolve(res.data)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
92
components/api/list.js
Normal file
92
components/api/list.js
Normal file
@@ -0,0 +1,92 @@
|
||||
import { baseInfo } from '../store/index.js'
|
||||
const localDataList = [{
|
||||
videoId: '7CDB7C3805062F7E753C612EB38A8D5A',
|
||||
videoTitle: '7CDB7C3805062F7E753C612EB38A8D5A',
|
||||
videoCover: 'https://4-img.bokecc.com/comimage/391E6E3340A00767/2019-05-13/2477AD327B256E5C9C33DC5901307461-1.jpg'
|
||||
|
||||
},{
|
||||
videoId: '17E1B738D75F78C63835A29B2A11961',
|
||||
videoTitle: '17E1B738D75F78C63835A29B2A11961',
|
||||
videoCover: 'https://4-img.bokecc.com/comimage/391E6E3340A00767/2019-05-13/2477AD327B256E5C9C33DC5901307461-1.jpg'
|
||||
},{
|
||||
videoId: '5D03190EE9C3F78CFC9558351D509E7C',
|
||||
videoTitle: '5D03190EE9C3F78CFC9558351D509E7C',
|
||||
videoCover: 'https://4-img.bokecc.com/comimage/391E6E3340A00767/2019-05-13/2477AD327B256E5C9C33DC5901307461-1.jpg'
|
||||
},
|
||||
{
|
||||
videoId: 'DDD7F00E720A8D8713358DE27D943A99',
|
||||
videoTitle: 'DDD7F00E720A8D8713358DE27D943A99',
|
||||
videoCover: 'https://4-img.bokecc.com/comimage/391E6E3340A00767/2019-05-13/2477AD327B256E5C9C33DC5901307461-1.jpg'
|
||||
}]
|
||||
|
||||
const listWidthUserId = [
|
||||
{
|
||||
userId: '2661F9756E5C832E',
|
||||
videoId: '67835AFD5375A87E7E6C9CEE8B422289',
|
||||
videoTitle: '数字人产品介绍视频',
|
||||
videoCover: 'http://5-img.bokecc.com/comimage/2661F9756E5C832E/2023-08-08/67835AFD5375A87E7E6C9CEE8B422289-1.jpg'
|
||||
},
|
||||
{
|
||||
userId: '2661F9756E5C832E',
|
||||
videoId: '016A4748BCF3EEF22BBA984E86119800',
|
||||
videoTitle: '3步PPT',
|
||||
videoCover: 'http://5-img.bokecc.com/comimage/2661F9756E5C832E/2023-11-24/016A4748BCF3EEF22BBA984E86119800-1.jpg'
|
||||
},
|
||||
{
|
||||
userId: '2661F9756E5C832E',
|
||||
videoId: '8D80E1FDDD31C8E52BBA984E86119800',
|
||||
videoTitle: 'ppt基础版合成-无音乐',
|
||||
videoCover: 'http://5-img.bokecc.com/comimage/2661F9756E5C832E/2024-02-27/8D80E1FDDD31C8E52BBA984E86119800-1.jpg'
|
||||
},
|
||||
{
|
||||
userId: '2661F9756E5C832E',
|
||||
videoId: '30CF0072C1E791DE63835A29B2A11961',
|
||||
videoTitle: '板书',
|
||||
videoCover: 'http://4-img.bokecc.com/comimage/2661F9756E5C832E/2023-11-24/30CF0072C1E791DE63835A29B2A11961-1.jpg'
|
||||
}
|
||||
]
|
||||
|
||||
const listWidthUserId2 = [
|
||||
{
|
||||
userId: '169A751C6B4BE3F6',
|
||||
videoId: '617B49BE28A32D61FC9558351D509E7C',
|
||||
videoTitle: '飞天·逐梦',
|
||||
videoCover: 'http://5-img.bokecc.com/comimage/169A751C6B4BE3F6/2023-11-17/617B49BE28A32D61FC9558351D509E7C-1.jpg'
|
||||
},
|
||||
{
|
||||
userId: '169A751C6B4BE3F6',
|
||||
videoId: '617B49BE28A32D610498CE5AAF1F53F5',
|
||||
videoTitle: '年度最走心广告',
|
||||
videoCover: 'http://5-img.bokecc.com/comimage/169A751C6B4BE3F6/2023-11-17/617B49BE28A32D610498CE5AAF1F53F5-1.jpg'
|
||||
},
|
||||
{
|
||||
userId: '169A751C6B4BE3F6',
|
||||
videoId: '617B49BE28A32D61B463AB73BD4C026B',
|
||||
videoTitle: '年少有为',
|
||||
videoCover: 'http://5-img.bokecc.com/comimage/169A751C6B4BE3F6/2023-11-17/617B49BE28A32D61B463AB73BD4C026B-1.jpg'
|
||||
},
|
||||
{
|
||||
userId: '169A751C6B4BE3F6',
|
||||
videoId: '8F1AF45ACE7571CBB463AB73BD4C026B',
|
||||
videoTitle: '少年-梦然',
|
||||
videoCover: 'http://5-img.bokecc.com/comimage/169A751C6B4BE3F6/2023-11-17/8F1AF45ACE7571CBB463AB73BD4C026B-1.jpg'
|
||||
}
|
||||
]
|
||||
|
||||
export function getList (callback) {
|
||||
uni.request({
|
||||
url: 'https://p.bokecc.com/demo/videoinfo.json',
|
||||
success: (res) => {
|
||||
if (res.statusCode === 200) {
|
||||
// ========== mock start ==========
|
||||
res.data = [].concat(listWidthUserId, listWidthUserId2)
|
||||
// ========== mock end ===========
|
||||
callback(res.data);
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: res.errMsg
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
16
components/api/sid copy.js
Normal file
16
components/api/sid copy.js
Normal file
@@ -0,0 +1,16 @@
|
||||
export function getSid (data) {
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.request({
|
||||
url: 'https://spark.bokecc.com/demo/app-api/sdk-sid.bo',
|
||||
data,
|
||||
success: (res) => {
|
||||
if (res.error) {
|
||||
reject(res.data)
|
||||
} else {
|
||||
console.log('request getSid', data, res)
|
||||
resolve(res.data)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
16
components/api/sid.js
Normal file
16
components/api/sid.js
Normal file
@@ -0,0 +1,16 @@
|
||||
export function getSid (data) {
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.request({
|
||||
url: 'https://spark.bokecc.com/demo/app-api/sdk-sid.bo',
|
||||
data,
|
||||
success: (res) => {
|
||||
if (res.error) {
|
||||
reject(res.data)
|
||||
} else {
|
||||
console.log('request getSid', data, res)
|
||||
resolve(res.data)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
78
components/download/downloadFooter.vue
Normal file
78
components/download/downloadFooter.vue
Normal file
@@ -0,0 +1,78 @@
|
||||
<template>
|
||||
<view
|
||||
class="button-group"
|
||||
>
|
||||
<button
|
||||
v-if="!pickMode"
|
||||
class="download-btn btn"
|
||||
type="default"
|
||||
@click="openPickMode"
|
||||
>
|
||||
<text class="text">下载</text>
|
||||
</button>
|
||||
<template
|
||||
v-else>
|
||||
<button
|
||||
class="confirm-btn btn"
|
||||
type="default"
|
||||
@click="confirm"
|
||||
>
|
||||
<text class="text">确认下载</text>
|
||||
</button>
|
||||
<button
|
||||
class="cancel-btn btn"
|
||||
type="default"
|
||||
@click="cancel"
|
||||
>
|
||||
<text class="text">取消</text>
|
||||
</button>
|
||||
</template>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
pickMode: {
|
||||
type: Boolean
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
openPickMode () {
|
||||
this.$emit('changePickMode', true);
|
||||
},
|
||||
confirm () {
|
||||
this.$emit('downloadConfirm');
|
||||
},
|
||||
cancel () {
|
||||
this.$emit('changePickMode', false);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
.button-group
|
||||
padding: 30rpx 0
|
||||
flex-direction: row
|
||||
justify-content: center
|
||||
.btn
|
||||
width: 610rpx
|
||||
height: 80rpx
|
||||
border-radius: 49rpx
|
||||
border: 2rpx solid #FF920A;
|
||||
.text
|
||||
font-size: 30rpx;
|
||||
color: #FF920A;
|
||||
&.download-btn
|
||||
width: 610rpx
|
||||
&.confirm-btn
|
||||
width: 290rpx
|
||||
&.cancel-btn
|
||||
margin-left: 30rpx
|
||||
width: 290rpx
|
||||
background: #F3F4F5
|
||||
border: 2rpx solid transparent;
|
||||
.text
|
||||
color: #333
|
||||
</style>
|
||||
77
components/list/SelectionsList.nvue
Normal file
77
components/list/SelectionsList.nvue
Normal file
@@ -0,0 +1,77 @@
|
||||
<template>
|
||||
<view class="video-list">
|
||||
<list
|
||||
class="list"
|
||||
show-scrollbar="false">
|
||||
<cell
|
||||
class="cell"
|
||||
:key="item.videoId"
|
||||
v-for="item in lists">
|
||||
<view
|
||||
class="video-item"
|
||||
@click="handleClick(item)">
|
||||
<image class="video-cover" :src="item.videoCover" mode="aspectFill"></image>
|
||||
<view class="right-view">
|
||||
<text
|
||||
class="video-title"
|
||||
:class="{active : item.definition ? item.videoId === currentVideo && item.quality == currentDefinition : item.videoId === currentVideo}"
|
||||
>{{ item.videoTitle }}</text>
|
||||
<!-- <text class="video-time">{{ item.videoTime }}</text> -->
|
||||
</view>
|
||||
</view>
|
||||
</cell>
|
||||
</list>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name:"VideoList",
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
props: {
|
||||
lists: {
|
||||
type: Array,
|
||||
default: []
|
||||
},
|
||||
currentVideo: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
currentDefinition: {
|
||||
type: Number,
|
||||
default: 20
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleClick(item) {
|
||||
this.$emit('listClick', item);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
.video-list
|
||||
flex 1
|
||||
.list
|
||||
flex 1
|
||||
padding 0 20rpx
|
||||
.video-item
|
||||
flex-direction row
|
||||
margin 15rpx 0
|
||||
.right-view
|
||||
margin-left 20rpx
|
||||
flex 1
|
||||
.video-cover
|
||||
width 160rpx
|
||||
height 90rpx
|
||||
border-radius 2rpx
|
||||
.video-title
|
||||
font-size 26rpx
|
||||
line-height 39rpx
|
||||
color #FFF
|
||||
&.active
|
||||
color #FF920A
|
||||
</style>
|
||||
118
components/list/VideoList.nvue
Normal file
118
components/list/VideoList.nvue
Normal file
@@ -0,0 +1,118 @@
|
||||
<template>
|
||||
<view class="video-list">
|
||||
<slot name="title"></slot>
|
||||
<list
|
||||
class="list"
|
||||
show-scrollbar="false">
|
||||
<cell
|
||||
class="cell"
|
||||
:key="item.videoId"
|
||||
v-for="item in lists">
|
||||
<view
|
||||
class="video-item"
|
||||
@click="handleClick(item)">
|
||||
<template
|
||||
v-if="pickMode"
|
||||
>
|
||||
<image
|
||||
v-if="!item.selected"
|
||||
class="radio-icon"
|
||||
src="@/static/download/unselected@2x.png"></image>
|
||||
<image
|
||||
v-else
|
||||
class="radio-icon"
|
||||
src="@/static/download/selected@2x.png"></image>
|
||||
</template>
|
||||
<image class="video-cover" :src="item.videoCover" mode="aspectFill"></image>
|
||||
<view class="right-view">
|
||||
<text
|
||||
class="video-title"
|
||||
:class="{active : item.videoId === currentVideo}"
|
||||
>{{ item.videoTitle }}</text>
|
||||
<text class="video-time">{{ item.videoTime }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</cell>
|
||||
</list>
|
||||
<slot name="footer"></slot>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import { mapMutations } from 'vuex'
|
||||
export default {
|
||||
name:"VideoList",
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
props: {
|
||||
lists: {
|
||||
type: Array,
|
||||
default: []
|
||||
},
|
||||
currentVideo: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
isPushing: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
pickMode: {
|
||||
type: Boolean
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapMutations(['makeDownloadList']),
|
||||
handleClick(item) {
|
||||
if (this.pickMode) {
|
||||
this.$set(item, 'selected', !item.selected);
|
||||
return;
|
||||
}
|
||||
if (this.isPushing) {
|
||||
uni.showToast({
|
||||
title: '投屏中,暂不支持切换',
|
||||
icon: 'none'
|
||||
})
|
||||
return;
|
||||
}
|
||||
this.$emit('listClick', item);
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
.video-list
|
||||
flex 1
|
||||
padding 0 30rpx
|
||||
background-color: #FFF;
|
||||
.list
|
||||
flex 1
|
||||
.video-item
|
||||
flex-direction row
|
||||
align-items: center
|
||||
margin 15rpx 0
|
||||
.right-view
|
||||
margin-left 20rpx
|
||||
flex 1
|
||||
.radio-icon
|
||||
margin-right: 20rpx
|
||||
width: 30rpx
|
||||
height: 30rpx
|
||||
.video-cover
|
||||
width 320rpx
|
||||
height 180rpx
|
||||
border-radius 10rpx
|
||||
.video-title
|
||||
font-size 28rpx
|
||||
line-height 42rpx
|
||||
color #333
|
||||
&.active
|
||||
color #FF920A
|
||||
.video-time
|
||||
margin-top 30rpx
|
||||
font-size 26rpx
|
||||
color #666
|
||||
</style>
|
||||
63
components/list/WaterFall.nvue
Normal file
63
components/list/WaterFall.nvue
Normal file
@@ -0,0 +1,63 @@
|
||||
<template>
|
||||
<view class="video-list">
|
||||
<waterfall
|
||||
class="waterfall"
|
||||
column-count="2"
|
||||
column-gap="10"
|
||||
left-gap="10"
|
||||
right-gap="10"
|
||||
>
|
||||
<cell
|
||||
class="cell"
|
||||
:key="item.videoId"
|
||||
v-for="item in lists">
|
||||
<navigator
|
||||
class="video-item"
|
||||
hover-class="navigator-hover"
|
||||
:url="`/pages/detail/detail?videoId=${item.videoId}&userId=${item.userId}`">
|
||||
<image class="video-cover" :src="item.videoCover"></image>
|
||||
<text class="video-title">{{ item.videoTitle }}</text>
|
||||
</navigator>
|
||||
</cell>
|
||||
</waterfall>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name:"VideoList",
|
||||
data() {
|
||||
return {
|
||||
|
||||
};
|
||||
},
|
||||
props: {
|
||||
lists: {
|
||||
type: Array,
|
||||
default: []
|
||||
},
|
||||
column: {
|
||||
type: Number,
|
||||
default: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
.video-list
|
||||
flex 1
|
||||
.waterfall
|
||||
flex 1
|
||||
.video-cover
|
||||
width 350rpx
|
||||
height 196rpx
|
||||
border-radius 10rpx
|
||||
.video-title
|
||||
margin 20rpx 0
|
||||
font-size 28rpx
|
||||
color #333333
|
||||
text-overflow ellipsis
|
||||
lines 1
|
||||
|
||||
</style>
|
||||
15
components/list/api/ip.js
Normal file
15
components/list/api/ip.js
Normal file
@@ -0,0 +1,15 @@
|
||||
export function getIP (data) {
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.request({
|
||||
url: 'https://logger-data.csslcloud.net/api/detection',
|
||||
data,
|
||||
success: (res) => {
|
||||
if (res.error) {
|
||||
reject(res.data)
|
||||
} else {
|
||||
resolve(res.data)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
92
components/list/api/list.js
Normal file
92
components/list/api/list.js
Normal file
@@ -0,0 +1,92 @@
|
||||
import { baseInfo } from '../store/index.js'
|
||||
const localDataList = [{
|
||||
videoId: '7CDB7C3805062F7E753C612EB38A8D5A',
|
||||
videoTitle: '7CDB7C3805062F7E753C612EB38A8D5A',
|
||||
videoCover: 'https://4-img.bokecc.com/comimage/391E6E3340A00767/2019-05-13/2477AD327B256E5C9C33DC5901307461-1.jpg'
|
||||
|
||||
},{
|
||||
videoId: '17E1B738D75F78C63835A29B2A11961',
|
||||
videoTitle: '17E1B738D75F78C63835A29B2A11961',
|
||||
videoCover: 'https://4-img.bokecc.com/comimage/391E6E3340A00767/2019-05-13/2477AD327B256E5C9C33DC5901307461-1.jpg'
|
||||
},{
|
||||
videoId: '5D03190EE9C3F78CFC9558351D509E7C',
|
||||
videoTitle: '5D03190EE9C3F78CFC9558351D509E7C',
|
||||
videoCover: 'https://4-img.bokecc.com/comimage/391E6E3340A00767/2019-05-13/2477AD327B256E5C9C33DC5901307461-1.jpg'
|
||||
},
|
||||
{
|
||||
videoId: 'DDD7F00E720A8D8713358DE27D943A99',
|
||||
videoTitle: 'DDD7F00E720A8D8713358DE27D943A99',
|
||||
videoCover: 'https://4-img.bokecc.com/comimage/391E6E3340A00767/2019-05-13/2477AD327B256E5C9C33DC5901307461-1.jpg'
|
||||
}]
|
||||
|
||||
const listWidthUserId = [
|
||||
{
|
||||
userId: '2661F9756E5C832E',
|
||||
videoId: '67835AFD5375A87E7E6C9CEE8B422289',
|
||||
videoTitle: '数字人产品介绍视频',
|
||||
videoCover: 'http://5-img.bokecc.com/comimage/2661F9756E5C832E/2023-08-08/67835AFD5375A87E7E6C9CEE8B422289-1.jpg'
|
||||
},
|
||||
{
|
||||
userId: '2661F9756E5C832E',
|
||||
videoId: '016A4748BCF3EEF22BBA984E86119800',
|
||||
videoTitle: '3步PPT',
|
||||
videoCover: 'http://5-img.bokecc.com/comimage/2661F9756E5C832E/2023-11-24/016A4748BCF3EEF22BBA984E86119800-1.jpg'
|
||||
},
|
||||
{
|
||||
userId: '2661F9756E5C832E',
|
||||
videoId: '8D80E1FDDD31C8E52BBA984E86119800',
|
||||
videoTitle: 'ppt基础版合成-无音乐',
|
||||
videoCover: 'http://5-img.bokecc.com/comimage/2661F9756E5C832E/2024-02-27/8D80E1FDDD31C8E52BBA984E86119800-1.jpg'
|
||||
},
|
||||
{
|
||||
userId: '2661F9756E5C832E',
|
||||
videoId: '30CF0072C1E791DE63835A29B2A11961',
|
||||
videoTitle: '板书',
|
||||
videoCover: 'http://4-img.bokecc.com/comimage/2661F9756E5C832E/2023-11-24/30CF0072C1E791DE63835A29B2A11961-1.jpg'
|
||||
}
|
||||
]
|
||||
|
||||
const listWidthUserId2 = [
|
||||
{
|
||||
userId: '169A751C6B4BE3F6',
|
||||
videoId: '617B49BE28A32D61FC9558351D509E7C',
|
||||
videoTitle: '飞天·逐梦',
|
||||
videoCover: 'http://5-img.bokecc.com/comimage/169A751C6B4BE3F6/2023-11-17/617B49BE28A32D61FC9558351D509E7C-1.jpg'
|
||||
},
|
||||
{
|
||||
userId: '169A751C6B4BE3F6',
|
||||
videoId: '617B49BE28A32D610498CE5AAF1F53F5',
|
||||
videoTitle: '年度最走心广告',
|
||||
videoCover: 'http://5-img.bokecc.com/comimage/169A751C6B4BE3F6/2023-11-17/617B49BE28A32D610498CE5AAF1F53F5-1.jpg'
|
||||
},
|
||||
{
|
||||
userId: '169A751C6B4BE3F6',
|
||||
videoId: '617B49BE28A32D61B463AB73BD4C026B',
|
||||
videoTitle: '年少有为',
|
||||
videoCover: 'http://5-img.bokecc.com/comimage/169A751C6B4BE3F6/2023-11-17/617B49BE28A32D61B463AB73BD4C026B-1.jpg'
|
||||
},
|
||||
{
|
||||
userId: '169A751C6B4BE3F6',
|
||||
videoId: '8F1AF45ACE7571CBB463AB73BD4C026B',
|
||||
videoTitle: '少年-梦然',
|
||||
videoCover: 'http://5-img.bokecc.com/comimage/169A751C6B4BE3F6/2023-11-17/8F1AF45ACE7571CBB463AB73BD4C026B-1.jpg'
|
||||
}
|
||||
]
|
||||
|
||||
export function getList (callback) {
|
||||
uni.request({
|
||||
url: 'https://p.bokecc.com/demo/videoinfo.json',
|
||||
success: (res) => {
|
||||
if (res.statusCode === 200) {
|
||||
// ========== mock start ==========
|
||||
res.data = [].concat(listWidthUserId, listWidthUserId2)
|
||||
// ========== mock end ===========
|
||||
callback(res.data);
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: res.errMsg
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
16
components/list/api/sid copy.js
Normal file
16
components/list/api/sid copy.js
Normal file
@@ -0,0 +1,16 @@
|
||||
export function getSid (data) {
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.request({
|
||||
url: 'https://spark.bokecc.com/demo/app-api/sdk-sid.bo',
|
||||
data,
|
||||
success: (res) => {
|
||||
if (res.error) {
|
||||
reject(res.data)
|
||||
} else {
|
||||
console.log('request getSid', data, res)
|
||||
resolve(res.data)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
16
components/list/api/sid.js
Normal file
16
components/list/api/sid.js
Normal file
@@ -0,0 +1,16 @@
|
||||
export function getSid (data) {
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.request({
|
||||
url: 'https://spark.bokecc.com/demo/app-api/sdk-sid.bo',
|
||||
data,
|
||||
success: (res) => {
|
||||
if (res.error) {
|
||||
reject(res.data)
|
||||
} else {
|
||||
console.log('request getSid', data, res)
|
||||
resolve(res.data)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
50
components/player/Brightness.nvue
Normal file
50
components/player/Brightness.nvue
Normal file
@@ -0,0 +1,50 @@
|
||||
<template>
|
||||
<view class="volume">
|
||||
<text class="text">亮度</text>
|
||||
<view class="process-bar">
|
||||
<view
|
||||
class="active-process"
|
||||
:style="{flex: precent}"
|
||||
></view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Brightness',
|
||||
props: {
|
||||
currentValue: {
|
||||
type: Number | String
|
||||
},
|
||||
totalValue: {
|
||||
type: Number | String
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
precent () {
|
||||
return this.currentValue / this.totalValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
.volume
|
||||
flex-direction row
|
||||
align-items center
|
||||
justify-content center
|
||||
padding 10rpx
|
||||
background rgba(20, 20, 20, 0.8)
|
||||
border-radius 2rpx
|
||||
.text
|
||||
color #FFFFFF
|
||||
.process-bar
|
||||
margin-left 20rpx
|
||||
width 260rpx
|
||||
height: 8rpx
|
||||
flex-direction row
|
||||
background-color rgba(153, 153, 153, 0.4)
|
||||
.active-process
|
||||
background-color #FF920A
|
||||
</style>
|
||||
307
components/player/CustomSlider.nvue
Normal file
307
components/player/CustomSlider.nvue
Normal file
@@ -0,0 +1,307 @@
|
||||
<template>
|
||||
<view class="custom-slider">
|
||||
<image
|
||||
v-if="minIcon"
|
||||
class="icon"
|
||||
:src="minIcon"></image>
|
||||
<view
|
||||
ref="slider"
|
||||
class="slider"
|
||||
@touchstart.stop="onTouchStart"
|
||||
@touchmove.stop="onTouchMove"
|
||||
@touchend.stop="onTouchEnd">
|
||||
<view class="bar">
|
||||
<slot></slot>
|
||||
</view>
|
||||
<view
|
||||
class="active-bar-wrapper">
|
||||
<view
|
||||
class="active-bar"
|
||||
:style="{flex: presentShow}"></view>
|
||||
</view>
|
||||
<view v-if="step !== 1" class="steps-wrapper">
|
||||
<template v-for="(step, index) in steps">
|
||||
<view v-if="index" class="step"></view>
|
||||
<view class="holder-bar"></view>
|
||||
</template>
|
||||
</view>
|
||||
<view
|
||||
class="dot-wrapper">
|
||||
<view
|
||||
class="holder-bar"
|
||||
:style="{flex: presentShow}"></view>
|
||||
<view class="dot"></view>
|
||||
</view>
|
||||
<view class="know-area">
|
||||
<slot name="know"></slot>
|
||||
</view>
|
||||
</view>
|
||||
<image
|
||||
v-if="maxIcon"
|
||||
class="icon"
|
||||
:src="maxIcon"></image>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
// 注意平台差异
|
||||
// #ifdef APP-NVUE
|
||||
const dom = weex.requireModule('dom')
|
||||
// #endif
|
||||
import { range, addNumber } from '@/utils/formate.js';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
dragStatus: '',
|
||||
size: {
|
||||
width: 0,
|
||||
height: 0,
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0
|
||||
},
|
||||
currentValue: 0
|
||||
}
|
||||
},
|
||||
props: {
|
||||
disabled: Boolean,
|
||||
vertical: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
barHeight: [Number, String],
|
||||
buttonSize: [Number, String],
|
||||
activeColor: String,
|
||||
inactiveColor: String,
|
||||
min: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
minIcon: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
max: {
|
||||
type: Number,
|
||||
default: 100,
|
||||
},
|
||||
maxIcon: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
step: {
|
||||
type: Number,
|
||||
default: 1,
|
||||
},
|
||||
value: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
isDOMShow: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
scope() {
|
||||
return this.max - this.min;
|
||||
},
|
||||
presentShow () {
|
||||
return (this.currentValue - this.min) / this.scope;
|
||||
},
|
||||
steps () {
|
||||
return this.scope / this.step
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
isDOMShow (value) {
|
||||
this.getSliderSize();
|
||||
},
|
||||
value (val) {
|
||||
this.currentValue = val;
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// 同步初始值
|
||||
this.currentValue = this.value;
|
||||
},
|
||||
mounted () {
|
||||
this.getSliderSize();
|
||||
},
|
||||
methods: {
|
||||
touchStart(event) {
|
||||
this.resetTouchStatus();
|
||||
this.startX = event.touches[0].screenX;
|
||||
this.startY = event.touches[0].screenY;
|
||||
},
|
||||
touchMove(event) {
|
||||
const touch = event.touches[0];
|
||||
// safari back will set clientX to negative number
|
||||
this.deltaX = touch.screenX < 0 ? 0 : touch.screenX - this.startX;
|
||||
this.deltaY = touch.screenY - this.startY;
|
||||
this.offsetX = Math.abs(this.deltaX);
|
||||
this.offsetY = Math.abs(this.deltaY);
|
||||
// lock direction when distance is greater than a certain value
|
||||
const LOCK_DIRECTION_DISTANCE = 10;
|
||||
if (
|
||||
!this.direction ||
|
||||
(this.offsetX < LOCK_DIRECTION_DISTANCE &&
|
||||
this.offsetY < LOCK_DIRECTION_DISTANCE)
|
||||
) {
|
||||
this.direction = this.getDirection(this.offsetX, this.offsetY);
|
||||
}
|
||||
},
|
||||
resetTouchStatus() {
|
||||
this.direction = '';
|
||||
this.deltaX = 0;
|
||||
this.deltaY = 0;
|
||||
this.offsetX = 0;
|
||||
this.offsetY = 0;
|
||||
},
|
||||
getDirection (x, y) {
|
||||
if (x > y) {
|
||||
return 'horizontal';
|
||||
}
|
||||
if (y > x) {
|
||||
return 'vertical';
|
||||
}
|
||||
return '';
|
||||
},
|
||||
onTouchStart(event) {
|
||||
console.log('start')
|
||||
this.touchStart(event);
|
||||
this.startValue = this.format(this.currentValue);
|
||||
this.dragStatus = 'start';
|
||||
this.$emit('dragStart');
|
||||
},
|
||||
onTouchMove(event) {
|
||||
this.touchMove(event);
|
||||
const rect = this.size;
|
||||
const delta = this.vertical ? this.deltaY : this.deltaX;
|
||||
const total = this.vertical ? rect.height : rect.width;
|
||||
const diff = (delta / total) * this.scope;
|
||||
// console.log('move', delta);
|
||||
if (delta === 0) return;
|
||||
this.dragStatus = 'draging';
|
||||
this.currentValue = this.startValue + diff;
|
||||
this.updateValue(this.currentValue, true);
|
||||
},
|
||||
onTouchEnd(event) {
|
||||
console.log('end')
|
||||
if(this.dragStatus === 'draging') {
|
||||
this.updateValue(this.currentValue, true);
|
||||
return;
|
||||
}
|
||||
if (this.dragStatus === 'start') {
|
||||
this.onClick(event);
|
||||
};
|
||||
},
|
||||
onClick(event) {
|
||||
if (this.disabled) return;
|
||||
const rect = this.size;
|
||||
const delta = this.vertical
|
||||
? event.changedTouches[0].screenY - rect.top
|
||||
: event.changedTouches[0].screenX - rect.left;
|
||||
const total = this.vertical ? rect.height : rect.width;
|
||||
let value = +this.min + (delta / total) * this.scope;
|
||||
// this.startValue = this.value;
|
||||
this.updateValue(value, true);
|
||||
},
|
||||
updateValue(value, end) {
|
||||
value = this.format(value);
|
||||
this.currentValue = value;
|
||||
this.$emit('changing', value);
|
||||
if (end) {
|
||||
this.$emit('change', value);
|
||||
}
|
||||
},
|
||||
format(value) {
|
||||
const min = +this.min;
|
||||
const max = +this.max;
|
||||
const step = +this.step;
|
||||
value = range(value, min, max);
|
||||
const diff = parseInt((value - min) / step) * step;
|
||||
return addNumber(min, diff);
|
||||
},
|
||||
isSameValue(newValue, oldValue) {
|
||||
return JSON.stringify(newValue) === JSON.stringify(oldValue);
|
||||
},
|
||||
getSliderSize () {
|
||||
setTimeout(()=> {
|
||||
const result = dom.getComponentRect(this.$refs.slider, option => {
|
||||
this.size = option.size;
|
||||
})
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
.custom-slider
|
||||
flex-direction row
|
||||
align-items center
|
||||
justify-content center
|
||||
.icon
|
||||
width 40rpx
|
||||
height 40rpx
|
||||
.slider
|
||||
position relative
|
||||
margin 0 15rpx
|
||||
height 78rpx
|
||||
flex-direction row
|
||||
align-items center
|
||||
flex 1
|
||||
.bar
|
||||
flex 1
|
||||
flex-direction row
|
||||
height 6rpx
|
||||
background-color rgba(153, 153, 153, 0.4)
|
||||
.active-bar-wrapper
|
||||
position absolute
|
||||
top 0
|
||||
right 0
|
||||
bottom 0
|
||||
left 0
|
||||
flex-direction row
|
||||
align-items center
|
||||
.active-bar
|
||||
height 6rpx
|
||||
background-color #FF920A
|
||||
.steps-wrapper
|
||||
position absolute
|
||||
top 0
|
||||
right 0
|
||||
bottom 0
|
||||
left 0
|
||||
flex-direction row
|
||||
align-items center
|
||||
.step
|
||||
width 6rpx
|
||||
height 6rpx
|
||||
background-color #FFFFFF
|
||||
.holder-bar
|
||||
flex 1
|
||||
height: 6rpx
|
||||
.dot-wrapper
|
||||
position absolute
|
||||
top 0
|
||||
right 0
|
||||
bottom 0
|
||||
left 0
|
||||
flex-direction row
|
||||
align-items center
|
||||
.holder-bar
|
||||
height 6rpx
|
||||
.dot
|
||||
width 28rpx
|
||||
height 28rpx
|
||||
background-color #FFFFFF
|
||||
border-radius 100%
|
||||
.know-area
|
||||
position absolute
|
||||
top 0
|
||||
right 0
|
||||
bottom 0
|
||||
left 0
|
||||
</style>
|
||||
215
components/player/Gesture.nvue
Normal file
215
components/player/Gesture.nvue
Normal file
@@ -0,0 +1,215 @@
|
||||
<template>
|
||||
<view
|
||||
@touchstart.stop="touchstart"
|
||||
@touchmove.stop="touchmove"
|
||||
@touchend.stop="touchend">
|
||||
<slot></slot>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
holeWidth: Number, // 屏幕宽度(物理像素)
|
||||
duration: Number, // 视频总时长
|
||||
currentTime: Number // 视频当前播放时间
|
||||
},
|
||||
computed: {
|
||||
halfWidth() {
|
||||
return parseInt(this.holeWidth / 2);
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
downLeft: false, // 是否在左区域按下手势
|
||||
swipeDir: null // 滑动方向
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.addHandler();
|
||||
},
|
||||
methods:{
|
||||
addHandler() {
|
||||
// 增加父容器左右滑动监听
|
||||
let finalTime = -1;
|
||||
// 计算左右滑动seek进度
|
||||
const countTime = (position) => {
|
||||
const { holeWidth, duration, currentTime } = this;
|
||||
const precent = Math.abs(position) / holeWidth;
|
||||
const nowTime = currentTime || 0;
|
||||
let plusTime = parseInt(Math.abs(precent * duration));
|
||||
if (position < 0) plusTime = plusTime * -1;
|
||||
finalTime = nowTime + plusTime;
|
||||
finalTime = this.limit(finalTime, 0, duration);
|
||||
return finalTime;
|
||||
};
|
||||
this.addGesture((type, position) => {
|
||||
switch (type) {
|
||||
// 下滑
|
||||
case -1:
|
||||
this.$emit('onGestureEvent', {
|
||||
type: this.downLeft ? 'LEFT_DOWN' : 'RIGHT_DOWN',
|
||||
position
|
||||
});
|
||||
break;
|
||||
// 上滑
|
||||
case -2:
|
||||
this.$emit('onGestureEvent', {
|
||||
type: this.downLeft ? 'LEFT_UP' : 'RIGHT_UP',
|
||||
position
|
||||
});
|
||||
break;
|
||||
// 左滑
|
||||
case 0:
|
||||
this.swipeDir = type;
|
||||
countTime(position);
|
||||
this.$emit('onGestureEvent', {
|
||||
type: 'SEEK_TIME_UPDATE',
|
||||
finalTime
|
||||
});
|
||||
break;
|
||||
// 右滑
|
||||
case 1:
|
||||
this.swipeDir = type;
|
||||
countTime(position);
|
||||
this.$emit('onGestureEvent', {
|
||||
type: 'SEEK_TIME_UPDATE',
|
||||
finalTime
|
||||
});
|
||||
break;
|
||||
// touchend for swipe
|
||||
case 3:
|
||||
if (this.swipeDir > -1) {
|
||||
this.$emit('onGestureEvent', {
|
||||
type: this.swipeDir ? 'SWIPE_RIGHT' : 'SWIPE_LEFT'
|
||||
});
|
||||
this.swipeDir = -1;
|
||||
}
|
||||
|
||||
if (finalTime > -1) {
|
||||
this.$emit('onGestureSeekTo', finalTime);
|
||||
finalTime = -1;
|
||||
}
|
||||
this.$emit('onGestureEvent', {
|
||||
type: 'TOUCH_END'
|
||||
});
|
||||
break;
|
||||
// doubleTap
|
||||
case 4:
|
||||
break;
|
||||
// tap
|
||||
case 5:
|
||||
this.handleClick();
|
||||
break;
|
||||
// longTap
|
||||
case 6:
|
||||
break;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
addGesture(callback) {
|
||||
const { options } = this;
|
||||
let startX, startY, moveEndX, moveEndY, X, Y, position, hasType;
|
||||
let T, lastTap, isJustTouch = true;
|
||||
|
||||
const excuteCb = (type) => {
|
||||
// type 手势类型 -2 上滑 -1 下滑 0 左滑 1 右滑 2 just touch 3 touchend 4 doubleTap 5 tap 6 longTap
|
||||
if (callback && typeof callback === 'function')
|
||||
callback(type, position);
|
||||
};
|
||||
|
||||
const isXchange = () => {
|
||||
if (Math.abs(X) > Math.abs(Y)) {
|
||||
position = X;
|
||||
hasType = 'X';
|
||||
isJustTouch = false;
|
||||
}
|
||||
if (X >= 0) excuteCb(1);
|
||||
// 左滑
|
||||
else excuteCb(0);
|
||||
};
|
||||
|
||||
const isYchange = () => {
|
||||
if (Math.abs(Y) > Math.abs(X)) {
|
||||
position = Y;
|
||||
hasType = 'Y';
|
||||
isJustTouch = false;
|
||||
}
|
||||
if (Y >= 0) excuteCb(-1);
|
||||
// 上滑
|
||||
else excuteCb(-2);
|
||||
};
|
||||
|
||||
const countDirect = () => {
|
||||
if (hasType) {
|
||||
hasType === 'X' ? isXchange() : isYchange();
|
||||
return;
|
||||
}
|
||||
if (Math.abs(X) > 5) {
|
||||
isXchange();
|
||||
return;
|
||||
}
|
||||
if (Math.abs(Y) > 5) {
|
||||
isYchange();
|
||||
}
|
||||
};
|
||||
|
||||
this.handleTouch = (type, e) => {
|
||||
switch(type) {
|
||||
case 'start':
|
||||
startX = e.touches[0].screenX;
|
||||
startY = e.touches[0].screenY;
|
||||
T = Date.now();
|
||||
hasType = '';
|
||||
isJustTouch = true;
|
||||
this.downLeft = startX < this.halfWidth ? true : false;
|
||||
break;
|
||||
case 'move':
|
||||
moveEndX = e.touches[0].screenX;
|
||||
moveEndY = e.touches[0].screenY;
|
||||
X = moveEndX - startX;
|
||||
Y = moveEndY - startY;
|
||||
// console.log('Y', Y);
|
||||
countDirect();
|
||||
break;
|
||||
case 'end':
|
||||
if (isJustTouch)
|
||||
if (lastTap && Date.now() - lastTap <= 300)
|
||||
excuteCb(4);
|
||||
else if (Date.now() - T < 1000)
|
||||
excuteCb(5);
|
||||
else
|
||||
excuteCb(6);
|
||||
else
|
||||
excuteCb(3);
|
||||
|
||||
lastTap = Date.now();
|
||||
isJustTouch = true;
|
||||
break;
|
||||
}
|
||||
};
|
||||
},
|
||||
handleClick() {
|
||||
this.$emit('onGestureClick');
|
||||
},
|
||||
touchstart(e) {
|
||||
this.handleTouch('start', e);
|
||||
},
|
||||
touchmove(e) {
|
||||
this.handleTouch('move', e);
|
||||
},
|
||||
touchend(e) {
|
||||
this.handleTouch('end', e);
|
||||
},
|
||||
limit(num, min, max) {
|
||||
if (num < min) return min;
|
||||
if (num > max) return max;
|
||||
return num;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style></style>
|
||||
|
||||
44
components/player/Process.nvue
Normal file
44
components/player/Process.nvue
Normal file
@@ -0,0 +1,44 @@
|
||||
<template>
|
||||
<view class="volume">
|
||||
<text class="text">{{ currentValue }}/{{ totalValue }}</text>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Process',
|
||||
props: {
|
||||
currentValue: {
|
||||
type: Number | String
|
||||
},
|
||||
totalValue: {
|
||||
type: Number | String
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
precent () {
|
||||
return this.currentValue / this.totalValue;
|
||||
},
|
||||
restPrecent () {
|
||||
return 1 - this.precent;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
.volume
|
||||
flex-direction row
|
||||
align-items center
|
||||
justify-content center
|
||||
padding 10rpx
|
||||
background rgba(20, 20, 20, 0.8)
|
||||
border-radius 2rpx
|
||||
.text
|
||||
color #FFFFFF
|
||||
</style>
|
||||
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
41
components/player/StatusBar.nvue
Normal file
41
components/player/StatusBar.nvue
Normal file
@@ -0,0 +1,41 @@
|
||||
<template>
|
||||
<view
|
||||
class="status-bar">
|
||||
<component
|
||||
:is="name"
|
||||
:current-value="currentValue"
|
||||
:total-value="totalValue"></component>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Volume from './Volume.nvue'
|
||||
import Brightness from'./Brightness.nvue'
|
||||
import Process from './Process.nvue'
|
||||
export default {
|
||||
components: {
|
||||
Volume,
|
||||
Brightness,
|
||||
Process
|
||||
},
|
||||
props: {
|
||||
name: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
currentValue: {
|
||||
type: Number | String
|
||||
},
|
||||
totalValue: {
|
||||
type: Number | String
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
.status-bar
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
</style>
|
||||
50
components/player/Volume.nvue
Normal file
50
components/player/Volume.nvue
Normal file
@@ -0,0 +1,50 @@
|
||||
<template>
|
||||
<view class="volume">
|
||||
<text class="text">音量</text>
|
||||
<view class="process-bar">
|
||||
<view
|
||||
class="active-process"
|
||||
:style="{flex: precent}"
|
||||
></view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Volume',
|
||||
props: {
|
||||
currentValue: {
|
||||
type: Number | String
|
||||
},
|
||||
totalValue: {
|
||||
type: Number | String
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
precent () {
|
||||
return this.currentValue / this.totalValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
.volume
|
||||
flex-direction row
|
||||
align-items center
|
||||
justify-content center
|
||||
padding 10rpx
|
||||
background rgba(20, 20, 20, 0.8)
|
||||
border-radius 2rpx
|
||||
.text
|
||||
color #FFFFFF
|
||||
.process-bar
|
||||
margin-left 20rpx
|
||||
width 260rpx
|
||||
height: 8rpx
|
||||
flex-direction row
|
||||
background-color rgba(153, 153, 153, 0.4)
|
||||
.active-process
|
||||
background-color #FF920A
|
||||
</style>
|
||||
73
components/player/player.vue
Normal file
73
components/player/player.vue
Normal file
@@ -0,0 +1,73 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
|
||||
<div id="url-player-test"></div>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
mounted() {
|
||||
// 在适合的生命周期,通过script和link标签引入播放器sdk、css
|
||||
this.loadWebPlayerSDK().then(() => {
|
||||
// 如果需要使用自定义组件,打开以下注释
|
||||
// this.loadComponent().then(() => {
|
||||
let player = new Aliplayer({
|
||||
id: "url-player-test",
|
||||
source: "//player.alicdn.com/video/aliyunmedia.mp4",
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
}, function (player) {
|
||||
});
|
||||
player.one('canplay', function () {
|
||||
console.log('canplay', player.tag);
|
||||
player.tag.play();
|
||||
});
|
||||
// }).catch((e) => { console.log("加载组件失败", e) })
|
||||
}).catch((e) => {
|
||||
console.log("加载播放器SDK失败", e);
|
||||
});
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
methods: {
|
||||
loadWebPlayerSDK() {
|
||||
return new Promise((resolve, reject) => {
|
||||
const s_tag = document.createElement('script'); // 引入播放器js
|
||||
s_tag.type = 'text/javascript';
|
||||
s_tag.src = 'https://g.alicdn.com/apsara-media-box/imp-web-player/2.20.3/aliplayer-min.js';
|
||||
s_tag.charset = 'utf-8';
|
||||
s_tag.onload = () => {
|
||||
resolve();
|
||||
}
|
||||
document.body.appendChild(s_tag);
|
||||
const l_tag = document.createElement('link'); // 引入播放器css
|
||||
l_tag.rel = 'stylesheet';
|
||||
l_tag.href = 'https://g.alicdn.com/apsara-media-box/imp-web-player/2.20.3/skins/default/aliplayer-min.css';
|
||||
document.body.appendChild(l_tag);
|
||||
});
|
||||
},
|
||||
loadComponent() {
|
||||
return new Promise((resolve, reject) => {
|
||||
const s_tag = document.createElement('script');
|
||||
s_tag.type = 'text/javascript';
|
||||
// 需要先下载组件 js 文件,放到项目 /static/ 目录下
|
||||
// 下载地址:https://github.com/aliyunvideo/AliyunPlayer_Web/blob/master/customComponents/dist/aliplayer-components/aliplayercomponents-1.0.9.min.js
|
||||
s_tag.src = './static/aliplayercomponents-1.0.9.min.js';
|
||||
s_tag.charset = 'utf-8';
|
||||
s_tag.onload = () => {
|
||||
resolve();
|
||||
}
|
||||
document.body.appendChild(s_tag);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.container {
|
||||
padding: 20px;
|
||||
font-size: 14px;
|
||||
height: 800px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,204 +1,247 @@
|
||||
<template>
|
||||
<view v-if="iosHide">
|
||||
<view class="footer_box" :class="{ footer_bg: bg }">
|
||||
<view v-for="(item, index) of navigationList" :key="index" class="footer_item">
|
||||
<view class="footer_nav_item" @click="onPageJump(item.pagePath)">
|
||||
<image v-if="item.pagePath == path" class="footer_nav_item_image footer_nav_item_image_scale"
|
||||
:src="'/' + item.selectedIconPath" mode="aspectFit"></image>
|
||||
<image v-else class="footer_nav_item_image" :src="'/' + item.iconPath" mode="aspectFit"></image>
|
||||
<text class="footer_nav_item_text"
|
||||
:class="[item.pagePath == path ? 'footer_item_text_active' : '']">{{ item.text }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="bg" class="footer_station"></view>
|
||||
</view>
|
||||
<view v-else>
|
||||
<view class="footer_box" :class="{ footer_bg: bg }">
|
||||
<view v-for="(item, index) of navigationIos" :key="index" class="footer_item">
|
||||
<view class="footer_nav_item" @click="onPageJump(item.pagePath)">
|
||||
<image v-if="item.pagePath == path" class="footer_nav_item_image footer_nav_item_image_scale"
|
||||
:src="'/' + item.selectedIconPath" mode="aspectFit"></image>
|
||||
<image v-else class="footer_nav_item_image" :src="'/' + item.iconPath" mode="aspectFit"></image>
|
||||
<text class="footer_nav_item_text"
|
||||
:class="[item.pagePath == path ? 'footer_item_text_active' : 'normal_text']">{{ item.text }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="bg" class="footer_station"></view>
|
||||
</view>
|
||||
<view v-if="iosHide">
|
||||
<view class="footer_box" :class="{ footer_bg: bg }">
|
||||
<view
|
||||
v-for="(item, index) of navigationList"
|
||||
:key="index"
|
||||
class="footer_item"
|
||||
>
|
||||
<view class="footer_nav_item" @click="onPageJump(item.pagePath)">
|
||||
<image
|
||||
v-if="item.pagePath == path"
|
||||
class="footer_nav_item_image footer_nav_item_image_scale"
|
||||
:src="'/' + item.selectedIconPath"
|
||||
mode="aspectFit"
|
||||
></image>
|
||||
<image
|
||||
v-else
|
||||
class="footer_nav_item_image"
|
||||
:src="'/' + item.iconPath"
|
||||
mode="aspectFit"
|
||||
></image>
|
||||
<text
|
||||
class="footer_nav_item_text"
|
||||
:class="[item.pagePath == path ? 'footer_item_text_active' : '']"
|
||||
>{{ item.text }}</text
|
||||
>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="bg" class="footer_station"></view>
|
||||
</view>
|
||||
<view v-else>
|
||||
<view class="footer_box" :class="{ footer_bg: bg }">
|
||||
<view
|
||||
v-for="(item, index) of navigationIos"
|
||||
:key="index"
|
||||
class="footer_item"
|
||||
>
|
||||
<view class="footer_nav_item" @click="onPageJump(item.pagePath)">
|
||||
<image
|
||||
v-if="item.pagePath == path"
|
||||
class="footer_nav_item_image footer_nav_item_image_scale"
|
||||
:src="'/' + item.selectedIconPath"
|
||||
mode="aspectFit"
|
||||
></image>
|
||||
<image
|
||||
v-else
|
||||
class="footer_nav_item_image"
|
||||
:src="'/' + item.iconPath"
|
||||
mode="aspectFit"
|
||||
></image>
|
||||
<text
|
||||
class="footer_nav_item_text"
|
||||
:class="[
|
||||
item.pagePath == path ? 'footer_item_text_active' : 'normal_text',
|
||||
]"
|
||||
>{{ item.text }}</text
|
||||
>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="bg" class="footer_station"></view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
bg: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
path: '',
|
||||
navigationList: [
|
||||
|
||||
{
|
||||
"pagePath": "pages/peanut/home",
|
||||
"iconPath": "static/tab/icon1_n.png",
|
||||
"selectedIconPath": "static/tab/icon1_y.png",
|
||||
"text": "首页"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/peanut/shopping",
|
||||
"iconPath": "static/tab/tab_nor_02.png",
|
||||
"selectedIconPath": "static/tab/tab_cur_02.png",
|
||||
"text": "购物车"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/taihu/index",
|
||||
"iconPath": "static/tab/tab_nor_03.png",
|
||||
"selectedIconPath": "static/tab/tab_cur_03.png",
|
||||
"text": "太湖公益"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/peanut/mine",
|
||||
"iconPath": "static/tab/tab_nor_04.png",
|
||||
"selectedIconPath": "static/tab/tab_cur_04.png",
|
||||
"text": "我的"
|
||||
}
|
||||
],
|
||||
navigationIos: [
|
||||
{
|
||||
"pagePath": "pages/peanut/home",
|
||||
"iconPath": "static/tab/icon1_n.png",
|
||||
"selectedIconPath": "static/tab/icon1_y.png",
|
||||
"text": "首页"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/peanut/shopping",
|
||||
"iconPath": "static/tab/tab_nor_02.png",
|
||||
"selectedIconPath": "static/tab/tab_cur_02.png",
|
||||
"text": "购物车"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/taihu/index",
|
||||
"iconPath": "static/tab/tab_nor_03.png",
|
||||
"selectedIconPath": "static/tab/tab_cur_03.png",
|
||||
"text": "太湖公益"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/peanut/mine",
|
||||
"iconPath": "static/tab/tab_nor_04.png",
|
||||
"selectedIconPath": "static/tab/tab_cur_04.png",
|
||||
"text": "我的"
|
||||
}
|
||||
],
|
||||
};
|
||||
},
|
||||
//第一次加载
|
||||
created() {
|
||||
//获取所有页面
|
||||
let currentPages = getCurrentPages();
|
||||
let page = currentPages[currentPages.length - 1];
|
||||
this.path = page.route;
|
||||
},
|
||||
//方法
|
||||
methods: {
|
||||
onPageJump(url) {
|
||||
if (this.path !== url) {
|
||||
uni.switchTab({
|
||||
url: '/' + url
|
||||
});
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
export default {
|
||||
props: {
|
||||
bg: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
path: "",
|
||||
navigationList: [
|
||||
{
|
||||
pagePath: "pages/peanut/home",
|
||||
iconPath: "static/tab/icon1_n.png",
|
||||
selectedIconPath: "static/tab/icon1_y.png",
|
||||
text: "首页",
|
||||
},
|
||||
{
|
||||
pagePath: "pages/peanut/shopping",
|
||||
iconPath: "static/tab/tab_nor_02.png",
|
||||
selectedIconPath: "static/tab/tab_cur_02.png",
|
||||
text: "购物车",
|
||||
},
|
||||
{
|
||||
pagePath: "pages/taihu/index",
|
||||
iconPath: "static/tab/tab_nor_03.png",
|
||||
selectedIconPath: "static/tab/tab_cur_03.png",
|
||||
text: "太湖公益",
|
||||
},
|
||||
{
|
||||
pagePath: "pages/bookShop/orderList",
|
||||
iconPath: "static/tab/order.png",
|
||||
selectedIconPath: "static/tab/order_active.png",
|
||||
text: "订单",
|
||||
},
|
||||
{
|
||||
pagePath: "pages/mine/mine/index",
|
||||
iconPath: "static/tab/tab_nor_04.png",
|
||||
selectedIconPath: "static/tab/tab_cur_04.png",
|
||||
text: "我的",
|
||||
},
|
||||
],
|
||||
navigationIos: [
|
||||
{
|
||||
pagePath: "pages/peanut/home",
|
||||
iconPath: "static/tab/icon1_n.png",
|
||||
selectedIconPath: "static/tab/icon1_y.png",
|
||||
text: "首页",
|
||||
},
|
||||
{
|
||||
pagePath: "pages/peanut/shopping",
|
||||
iconPath: "static/tab/tab_nor_02.png",
|
||||
selectedIconPath: "static/tab/tab_cur_02.png",
|
||||
text: "购物车",
|
||||
},
|
||||
|
||||
{
|
||||
pagePath: "pages/taihu/index",
|
||||
iconPath: "static/tab/tab_nor_03.png",
|
||||
selectedIconPath: "static/tab/tab_cur_03.png",
|
||||
text: "太湖公益",
|
||||
},
|
||||
{
|
||||
pagePath: "pages/bookShop/orderList",
|
||||
iconPath: "static/tab/order.png",
|
||||
selectedIconPath: "static/tab/order_active.png",
|
||||
text: "订单",
|
||||
},
|
||||
{
|
||||
pagePath: "pages/mine/mine/index",
|
||||
iconPath: "static/tab/tab_nor_04.png",
|
||||
selectedIconPath: "static/tab/tab_cur_04.png",
|
||||
text: "我的",
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
//第一次加载
|
||||
created() {
|
||||
//获取所有页面
|
||||
let currentPages = getCurrentPages();
|
||||
let page = currentPages[currentPages.length - 1];
|
||||
this.path = page.route;
|
||||
},
|
||||
//方法
|
||||
methods: {
|
||||
onPageJump(url) {
|
||||
if (this.path !== url) {
|
||||
uni.switchTab({
|
||||
url: "/" + url,
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
@import '@/style/mixin.scss';
|
||||
.normal_text{
|
||||
color: #FFF;
|
||||
}
|
||||
.footer_station {
|
||||
height: 110rpx;
|
||||
box-sizing: content-box;
|
||||
padding-bottom: constant(safe-area-inset-bottom);
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
}
|
||||
@import "@/style/mixin.scss";
|
||||
.normal_text {
|
||||
color: #fff;
|
||||
}
|
||||
.footer_station {
|
||||
height: 110rpx;
|
||||
box-sizing: content-box;
|
||||
padding-bottom: constant(safe-area-inset-bottom);
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
}
|
||||
|
||||
.footer_box {
|
||||
height: 110rpx;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
z-index: 502;
|
||||
box-sizing: content-box;
|
||||
padding-bottom: constant(safe-area-inset-bottom);
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
}
|
||||
.footer_box {
|
||||
height: 110rpx;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
z-index: 502;
|
||||
box-sizing: content-box;
|
||||
padding-bottom: constant(safe-area-inset-bottom);
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
}
|
||||
|
||||
.footer_bg {
|
||||
background-color: #fff;
|
||||
box-shadow: 0 0px 10px 1px #0000001a;
|
||||
}
|
||||
.footer_bg {
|
||||
background-color: #fff;
|
||||
box-shadow: 0 0px 10px 1px #0000001a;
|
||||
}
|
||||
|
||||
.footer_item {
|
||||
position: relative;
|
||||
flex: 1;
|
||||
}
|
||||
.footer_item {
|
||||
position: relative;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.footer_nav_item {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
}
|
||||
.footer_nav_item {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.footer_nav_item:active {
|
||||
background-color: rgba($color: #fff, $alpha: 0.1);
|
||||
}
|
||||
.footer_nav_item:active {
|
||||
background-color: rgba($color: #fff, $alpha: 0.1);
|
||||
}
|
||||
|
||||
.footer_nav_item_text {
|
||||
font-size: 26rpx;
|
||||
color: #7b7b7b;
|
||||
margin-top: 6rpx;
|
||||
}
|
||||
.footer_nav_item_text {
|
||||
font-size: 26rpx;
|
||||
color: #7b7b7b;
|
||||
margin-top: 6rpx;
|
||||
}
|
||||
|
||||
.footer_nav_item_text_active {
|
||||
color: #f9a633;
|
||||
}
|
||||
.footer_nav_item_text_active {
|
||||
color: #f9a633;
|
||||
}
|
||||
|
||||
.footer_nav_item_image {
|
||||
width: 50rpx;
|
||||
height: 50rpx;
|
||||
.footer_nav_item_image {
|
||||
width: 50rpx;
|
||||
height: 50rpx;
|
||||
}
|
||||
|
||||
}
|
||||
.footer_nav_item_image_scale {
|
||||
animation: mescrollUpRotate 0.6s linear 1;
|
||||
}
|
||||
|
||||
.footer_nav_item_image_scale {
|
||||
animation: mescrollUpRotate 0.6s linear 1;
|
||||
}
|
||||
@keyframes mescrollUpRotate {
|
||||
0% {
|
||||
transform: scale(1.2);
|
||||
}
|
||||
|
||||
@keyframes mescrollUpRotate {
|
||||
0% {
|
||||
transform: scale(1.2);
|
||||
}
|
||||
100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.footer_item_text_active {
|
||||
color: #3983ff;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
.footer_item_text_active {
|
||||
color: #3983ff;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user