Commit 806ff668 by 程默

fix 11

parent a234435d
.DS_Store .DS_Store
node_modules/ node_modules/
dist/ dist/
.history/
npm-debug.log* npm-debug.log*
yarn-debug.log* yarn-debug.log*
yarn-error.log* yarn-error.log*
......
module.exports = { module.exports = {
SHOP_MIXID:"'zjgyl'", SHOP_MIXID:"'songsong'",
NODE_ENV: '"production"', NODE_ENV: '"production"',
BASE_URL:"'https://shop.mayi888.com'", BASE_URL:"'https://shop.mayi888.com'",
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
}, },
"miniprogramRoot": "dist/wx/", "miniprogramRoot": "dist/wx/",
"compileType": "miniprogram", "compileType": "miniprogram",
"appid": "wxdec983ee91e2422a", "appid": "wxae95a07ffdf11548",
"projectname": "mayi-mp-shop", "projectname": "mayi-mp-shop",
"simulatorType": "wechat", "simulatorType": "wechat",
"simulatorPluginLibVersion": {}, "simulatorPluginLibVersion": {},
......
{ {
"pages": [ "pages": [
"pages/index/main", "pages/index/main",
"pages/livedPoster/main",
"pages/lived/main",
"pages/login/main", "pages/login/main",
"pages/wxPay/main", "pages/wxPay/main",
"pages/counter/main", "pages/counter/main",
"pages/address/main", "pages/address/main",
"pages/contact/main", "pages/contact/main"
"pages/liveList/main",
"pages/historyLive/main",
"pages/liveOver/main",
"pages/live/main"
], ],
"window": { "window": {
"backgroundTextStyle": "light", "backgroundTextStyle": "light",
......
<template>
<div class="container" :style="{'padding-top':navHeight +'px'}">
<div class="navbar" :style="{'height' : navHeight + 'px','padding-top':navTop+'px'}">
<div @click="toLiveList" class="history-btn">
<span class="iconfont iconzuo"></span>
</div>
<div class="navbar-title">直播计划</div>
</div>
<div class="uprefresh" v-if="isUprefresh">正在刷新...</div>
<div class="history-list">
<div class="list-item" v-for="(item,index) in list" :key="index" @click="liveDetail(item)">
<div class="item-top">
<div class="top-img">
<img :src="item.logoUrl" alt="">
</div>
<div class="top-name">{{item.shopName}}</div>
</div>
<div class="item-info">
<div class="info-poster">
<image :src="item.coverUrl" mode="aspectFill" alt=""></image>
</div>
<div class="info-detail">
<div class="detail-name">{{item.title}}</div>
<div class="detail-time">开播时间:{{item.startTime}}</div>
<div class="detail-data">
<div class="look data-icon">
<span class="iconfont iconyanjing"></span>
{{item.watchNum}}
</div>
<div class="thumbs data-icon">
<span class="iconfont iconicon_huabanfuben"></span>
{{item.likeNum}}
</div>
<div class="comment data-icon">
<span class="iconfont iconpinglun"></span>
{{item.guestBookNum}}
</div>
</div>
</div>
</div>
</div>
</div>
<van-divider
class="no-more"
v-if="isNoMore"
contentPosition="center"
customStyle="border-color: #ccc;"
>
已经到底了
</van-divider>
</div>
</template>
<script>
import liveApi from '@/api/liveing'
import { DFSImg,getNavbarInfo } from '../../utils/common.js'
export default {
data(){
return{
list:[],
currentPage : 1,
pageSize : 5,
pages : 0,
navTop : '',
navHeight : '',
isUprefresh :false,
isNoMore : false,
}
},
methods:{
getLiveHandler(type){
if(type == 'init'){
wx.showLoading({
title : '加载中'
})
}
liveApi.queryCompleteLive({
pageSize : this.pageSize,
currentPage : this.currentPage
}).then(res => {
if(res.data.code == '200'){
wx.hideLoading()
this.pages = res.data.pages;
if(type == 'refresh'){
wx.hideNavigationBarLoading();
this.isUprefresh = false;
// 停止下拉动作
wx.stopPullDownRefresh();
res.data.data.forEach(item => {
item.coverUrl = DFSImg(item.coverUrl)
item.logoUrl = DFSImg(item.logoUrl)
item.startTime = `${item.startTime.split(' ')[0]} ${item.startTimeByWeek} ${item.startTime.split(' ')[1].substr(0,5)}`
})
this.list = res.data.data;
}else if(type == 'more'){
res.data.data.forEach(item => {
item.coverUrl = DFSImg(item.coverUrl)
item.logoUrl = DFSImg(item.logoUrl)
item.startTime = `${item.startTime.split(' ')[0]} ${item.startTimeByWeek} ${item.startTime.split(' ')[1].substr(0,5)}`
this.list.push(item)
})
if(res.data.current == res.data.pages){
this.isNoMore = true;
}
}else{
res.data.data.forEach(item => {
item.coverUrl = DFSImg(item.coverUrl)
item.logoUrl = DFSImg(item.logoUrl)
item.startTime = `${item.startTime.split(' ')[0]} ${item.startTimeByWeek} ${item.startTime.split(' ')[1].substr(0,5)}`
})
this.list = res.data.data;
}
}
}).catch(error => {
wx.showToast({ title: error, icon: "none" });
wx.hideLoading()
})
},
liveDetail(item){
wx.navigateTo({url:`../liveOver/main?id=${item.id}&type=3&liveInfo=${JSON.stringify(item)}`})
},
toLiveList(){
wx.reLaunch({url:`../liveList/main`})
}
},
onShow(){
this.isUprefresh = false;
this.isNoMore = false;
this.currentPage = 1;
this.getLiveHandler('init')
},
created(){
//获取导航栏信息
getNavbarInfo((res) => {
this.navTop = res.navTop
this.navHeight = res.navHeight
})
},
onPullDownRefresh(){
this.isUprefresh = true;
this.currentPage = 1;
this.getLiveHandler('refresh');
wx.showNavigationBarLoading();
},
onReachBottom(){
if(this.currentPage < this.pages){
++this.currentPage;
this.getLiveHandler('more');
}
},
}
</script>
<style scoped lang="scss">
img{
width: 100%;
height: 100%;
}
.container{
min-height: 100vh;
background-color: #efefef;
padding-bottom: 24px;
}
.navbar{
box-sizing: border-box;
display: flex;
justify-content: center;
align-items: center;
position: relative;
background-color: white;
width: 100%;
position: fixed;
left: 0;
top: 0;
z-index: 10;
.history-btn{
width: 24px;
height: 24px;
position: absolute;
left: 16px;
.iconfont{
font-size: 15px;
color: #323232;
}
}
.navbar-title{
font-size: 14px;
color: #000;
text-align: center;
}
}
.uprefresh{
line-height: 30px;
font-size: 16px;
color: #999;
text-align: center;
}
.history-list{
width: 100%;
box-sizing: border-box;
padding: 12px 12px 0 12px;
.list-item{
width: 100%;
background-color: white;
border-radius: 4px;
padding: 0 12px 16px;
margin-bottom: 12px;
box-sizing: border-box;
.item-top{
display: flex;
justify-content: flex-start;
align-items: center;
height: 42px;
margin-bottom: 4px;
.top-img{
width: 27px;
height: 27px;
border-radius: 50%;
overflow: hidden;
background-color: #B5B5B5;
margin-right: 6px;
}
.top-name{
font-size: 15px;
color: #333333;
}
}
.item-info{
width: 100%;
display: flex;
justify-content: flex-start;
justify-items: center;
.info-poster{
width: 90px;
height: 90px;
border-radius: 3px;
background-color: #B5B5B5;
margin-right: 16px;
overflow: hidden;
image{
width: 100%;
height: 100%;
}
}
.info-detail{
.detail-name{
font-size: 15px;
color: #333333;
}
.detail-time{
font-size: 13px;
color: #999999;
line-height: 34px;
}
}
.detail-data{
color: #999;
font-size: 13px;
display: flex;
justify-content: flex-start;
align-items: center;
margin-top: 14px;
.data-icon{
margin-right: 16px;
font-size: 13px;
}
}
}
}
}
.no-more{
width: 90%;
line-height: 30px;
font-size: 16px;
color: #999;
text-align: center;
}
</style>
\ No newline at end of file
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
{
"navigationBarTitleText":"直播计划",
"enablePullDownRefresh":true,
"navigationStyle":"custom",
"usingComponents": {
"van-divider": "/static/vant/divider/index"
}
}
\ No newline at end of file
<template>
<div class="container" :style="{'padding-top':navHeight +'px'}">
<div class="masker"></div>
<live-pusher
id="pusher"
:url="tuiStream"
:mode="clear"
bindstatechange="statechange"
:beauty="beauty"
:enable-camera="enableCamera"
:whiteness="whiteness"
:device-position="devicePosition"
:enable-mic="enableMic"
:remote-mirror="remoteMirror"
:local-mirror="remoteMirror"
:mirror="mirror"
style="width: 100%; height: 100vh;position:fixed;top:0;left:0;z-index:-1"
@statechange="statechange"
@error="binderror"
@netstatus="bindnetstatus"
/>
<image class="bg-img" v-if="isBgImg" :src="liveInfo.coverUrl" mode="aspectFill" alt=""></image>
<div class="content" :style="{'padding-top':navHeight +'px'}">
<navBar
:navTop="navTop"
:navHeight="navHeight"
:isSetBeauty="isSetBeauty"
:isLive="isLive"
:type="1"
:id="liveId"
:pusher="pusher"
:liveInfo="liveInfo"
:realStartTime="realStartTime"
@closeSetBeauty="closeSetBeauty"
@clearAllInterval="clearAllInterval"
@changeOver="changeOver"
>
</navBar>
<div class="live-active" v-if="!isSetBeauty">
<span>{{look}} 观看</span>
<span>{{praise}}</span>
<span>{{online}} 在线</span>
</div>
<!-- 开播倒计时 -->
<div class="countdown" v-show="isCountDown">
{{liveCountDown}}
</div>
<!-- 还没开始直播 -->
<div class="wait-start" v-show="noStartLive">
<div class="title">{{liveInfo.title}}</div>
<div class="open-live-title">{{!liveTimeStatus ? '开播倒计时' : '已超时,请尽快开始'}}</div>
<div class="wait-time">{{liveTime}}</div>
<div class="start-btn" @click="toSetBeauty('start')">开始直播</div>
</div>
<!-- 直播异常 -->
<div class="unusual-wrap" v-show="recoverLive">
<div class="title">{{liveInfo.title}}</div>
<div class="unusual-text">直播异常中断</div>
<div class="recover-btn" @click="checkLiveEnv('recover')">恢复直播</div>
</div>
<!-- 公告 -->
<div class="notice" v-show="!isSetBeauty">
公告:{{liveInfo.liveNotice}}
</div>
<!-- 设置 -->
<div class="setting-wrap" @click="setBeauty" v-show="!isSetBeauty && !isCountDown">
<img class="set-img" src="../../../static/images/shezhi.png" alt="">
</div>
<!-- 商品 -->
<div class="product-wrap" v-show="!isSetBeauty && liveInfo.liveBroadcastSales == 0" @click="showPopup">
<div class="product-num">{{productList.length}}</div>
<img class="product-img" src="../../../static/images/shangpin.png" alt="">
</div>
<!-- 商品弹窗 -->
<product
:productList="productList"
:productDialogStatus="productDialogStatus"
@hideProductPopup="hideProductPopup"
@changeProduct="changeProduct"
>
</product>
<!-- 讲解商品列表 -->
<div class="speak-product" v-show="!isSetBeauty && isLive">
<!-- <div class="speak-product"> -->
<div class="speak-item" v-for="(item,index) in speakProductList" :key="index">
<div class="item-status">
讲解中
</div>
<div class="item-top">
<img :src="item.productImgUrl" alt="">
</div>
<div class="item-bottom">
{{item.minPrice}}
</div>
</div>
</div>
<!-- 设置 -->
<setting
:pusher="pusher"
:beauty="beauty"
:whiteness="whiteness"
:clear="clear"
:devicePosition="devicePosition"
:enableMic="enableMic"
:remoteMirror="remoteMirror"
:isLive="isLive"
:liveInfo="liveInfo"
@updateBeauty="updateBeauty"
@updateWhiteness="updateWhiteness"
@updateClear="updateClear"
@updateDevicePosition="updateDevicePosition"
@updateRemoteMirror="updateRemoteMirror"
@updateEnableMic="updateEnableMic"
v-if="isSetBeauty"
@setBeautyStart="startLive"
>
</setting>
<!-- 评论 -->
<comments v-if="!isSetBeauty" :updateVal="updateVal" :id="liveId" :commentsList="commentsList"></comments>
<!-- 用户进入通知 -->
<div class="userComing userComingAni" v-if="userComing && !isSetBeauty">
<span>{{entryNoticeText}}</span>
<span>来了</span>
</div>
</div>
</div>
</template>
<script>
import navBar from '@/components/common/navbar.vue'
import product from '@/components/product'
import setting from '@/components/setting'
import comments from '@/components/comments'
import { getNavbarInfo,DFSImg } from '../../utils/common.js'
import liveApi from '@/api/liveing'
export default {
data(){
return{
navTop : '',
navHeight : '',
isSetBeauty : false, //是否点击了设置
isUsual : false, //直播异常
productDialogStatus : false, //商品弹出框状态
isLive : false, //是否在直播
enableCamera : false, //是否开启摄像头
isPruductUp : false,
speakProductList : [],
pusher:null,
beauty:5, //美颜
whiteness:5,//美白
clear:'HD',
devicePosition : 'front', //前置或者后置 back => 后置
enableMic: true, //麦克风是否开启
remoteMirror:'enable', //镜像
userInfo : null,
liveInfo : {}, //直播信息
liveTime :'', //开播时间
liveTimeStatus : false , //是否超时
liveCountDown : 3, //开播倒计时
isCountDown : false, //是否显示倒计时
liveId : '', //直播间id
userComing: false,
entryNoticeText : '', //进入通知
online : 0, //在线
look : 0, //观看
praise:0, //点赞
commentsList : [], //评论
noStartLive : false,//还没开始直播,
recoverLive : false,//恢复直播
openLiveTimer : null, //开播时间定时器
tuiStream : '', //推流
productList : [], //商品列表
realStartTime : 0, //直播时间
liveDetailTimer : null, //获取直播评论等数据的定时器
getProductTimer : null, //刷新商品定时器
isBgImg : true, //是否展示背景图片
openRecordSet : false, //控制录音授权
openCameraSet : false, //控制相机授权
isChangeProduct : true, //是否可以上下屏,防止多次点击上下屏
isTimeLock : true, //时间锁
isTimeFirstReq : true, //第一次数据请求
isDetailLock : true, //查看详情锁
updateVal : 0,
overOrStop : 1, //是暂停还是结束
isDetailControlLock : true,
mirror : true,
}
},
watch:{
//用户通知
entryNoticeText(){
if(this.entryNoticeText){
this.userComing=true;
setTimeout(() => {
this.userComing=false;
}, 4600);
}else{
this.userComing=false;
}
},
//开关摄像头
enableCamera(){
if(this.isLive){
this.enableCamera = true
this.isBgImg = false;
}
},
// tuiStream(oldval,newval){
// if(newval){
// console.log('tuiStream',newval)
// this.tuiStream = newval
// }
// }
},
components:{
navBar,
product,
setting,
comments
},
created(){
//获取导航栏信息
getNavbarInfo((res) => {
this.navTop = res.navTop
this.navHeight = res.navHeight
})
},
onLoad(options){
this.isLive = false;
this.enableCamera = false;
this.isSetBeauty = false;
this.noStartLive = false;
this.recoverLive = false;
this.realStartTime = 0;
this.isBgImg = true;
this.isTimeLock = true;
this.isTimeFirstReq = true;
this.overOrStop = 1;
this.isDetailLock = true;
this.online = 0 //在线
this.look = 0 //观看
this.praise = 0 //点赞
this.liveInfo = {}
this.liveTime = '';
this.liveId = options.id;
this.getLiveDetail(options.id);
this.openLiveTimer = setInterval(() => {
this.getLiveDetail(options.id); //传入直播间id
},5000)
this.getServerTimeNow(); //获取服务器时间戳
},
onReady(){
this.userInfo = this.$store.state.userInfo;
this.pusher = wx.createLivePusherContext('pusher')
},
onShow(){
wx.setKeepScreenOn({
keepScreenOn: true
})
if(this.openRecordSet){
this.openRecordSet = false;
this.getAuthSet('record')
}
if(this.openCameraSet){
this.openCameraSet = false;
this.getAuthSet('camera');
}
},
onHide(){
this.commentsList = []
this.clearAllInterval()
console.log('onHide',this.overOrStop)
if(this.overOrStop){
if(this.liveInfo.liveBroadcastState == 1){
this.changeLiveStatus(3)
this.isSetBeauty = false;
}
}
},
onUnload(){
this.commentsList = []
this.clearAllInterval()
this.changeLiveStatus(3)
},
methods:{
getAuthSet(type){
wx.getSetting({
success :(res) => {
if(type == 'record'){
if (!res.authSetting["scope.record"]) {
this.openConfirm(type);
}
}else if(type == 'camera'){
if (!res.authSetting["scope.camera"]) {
this.openConfirm(type);
}else{
this.enableCamera = true;
}
}
},
fail(res) {
console.log("调用失败");
}
});
},
openConfirm(type){
let contentText = '';
if(type == 'record'){
contentText = '检测到您没打开麦克风的权限,是否去设置打开?'
}else if(type == 'camera'){
this.enableCamera = false;
contentText = '检测到您没打开摄像头的权限,是否去设置打开?'
}
wx.showModal({
content: contentText,
confirmText : '确认',
confirmColor : '#07c160',
success : (res) => {
if (res.confirm) {
wx.openSetting({
success : (res1) => {
if(type == 'record'){
this.openRecordSet = true;
}else if(type == 'camera'){
this.openCameraSet = true;
}
}
});
} else if (res.cancel) {
wx.reLaunch({url:`../liveList/main`})
}
}
})
},
//点击设置美颜
setBeauty(){
this.enableCamera = true;
this.noStartLive = false;
this.recoverLive = false
this.isBgImg = false;
this.isSetBeauty = true;
this.isDetailControlLock = false;
this.pusher.startPreview()
},
showPopup(){
this.productDialogStatus = true
this.getProductList()
},
hideProductPopup(){
this.productDialogStatus = false
},
//设置美颜
updateBeauty(val){
this.beauty = val;
},
//设置美白
updateWhiteness(val){
this.whiteness = val;
},
//设置清晰度
updateClear(val){
this.clear = val
},
//镜像
updateRemoteMirror(val){
this.remoteMirror = val;
this.mirror = val == 'enable' ? true : false
},
//麦克风
updateEnableMic(val){
this.enableMic = val;
},
//获取直播间详情
getLiveDetail(id){
console.log('获取',this.recoverLive)
if(this.isDetailLock && this.isDetailControlLock){
this.isDetailLock = false;
liveApi.queryLiveDetail({id}).then(res => {
this.isDetailLock = true;
if(res.data.code == '200'){
let result = res.data.data
if(result){
result.coverUrl = DFSImg(result.coverUrl)
result.logoUrl = DFSImg(result.logoUrl)
this.liveInfo = result;
this.tuiStream = result.tuiStream
if(result.liveBroadcastState == 0){
this.isLive = false
this.isBgImg = true;
this.noStartLive = true;
}else if(result.liveBroadcastState == 1){
this.enableCamera = true
this.isLive = true
this.isBgImg = false;
}else if(result.liveBroadcastState == 3){
console.log('llll')
this.recoverLive = true;
this.isUsual = true;
this.isBgImg = true;
}
if(result.realStartTime){
this.realStartTime = Math.floor((new Date().getTime() - new Date(result.realStartTime.replace(/-/g, '/').replace(/-/g, '/')).getTime())/1000)
}else{
this.realStartTime = 0
}
this.getLiveTimeHandler(result.startTime)
this.getProductList(); //获取商品列表
}else{
wx.showModal({
title: '提示',
content: '直播已关闭',
success (res3) {
if (res3.confirm) {
wx.reLaunch({url:`../liveList/main`})
} else if (res3.cancel) {
console.log('用户点击取消')
}
}
})
}
}else if(res.data.code == '-1'){
wx.showModal({
title: '提示',
content: '直播已关闭',
success (res3) {
if (res3.confirm) {
wx.reLaunch({url:`../liveList/main`})
} else if (res3.cancel) {
console.log('用户点击取消')
}
}
})
}
})
}
},
//获取开播时间
getLiveTimeHandler(time){
let getTime = new Date(time.replace(/-/g, '/')).getTime() - new Date().getTime();
let getTimeAbs = Math.abs(getTime)
let hours = '';
let minute = '';
let day = '';
if(getTime > 0){
this.liveTimeStatus = false
}else{
this.liveTimeStatus = true
}
day = Math.floor(getTimeAbs / (3600*1000*24))
hours = Math.floor((getTimeAbs%(24*3600*1000))/(3600*1000));
minute = Math.floor((getTimeAbs%(24*3600*1000)%(3600*1000) )/(60*1000))
if(getTime > 0){
if(day > 0){
this.liveTime = `${day >= 10 ? day : '0' + day}${hours >= 10 ? hours : '0' + hours}小时${minute >= 10 ? minute : '0' + minute}分`
}else if(day <= 0 && hours > 0){
this.liveTime = `${hours >= 10 ? hours : '0' + hours}小时${minute >= 10 ? minute : '0' + minute}分`
}else if(day <= 0 && hours <= 0 && minute >= 0){
this.liveTime = `${minute >= 10 ? minute : '0' + minute}分`
}
}else{
this.liveTime = `${15 - minute}分钟后关闭`
}
},
//开始直播去设置美颜
toSetBeauty(type){
this.noStartLive = false;
this.isSetBeauty = true;
this.enableCamera = true;
this.isDetailControlLock = false;
this.isBgImg = false;
this.pusher.startPreview()
},
//检测直播环境
checkLiveEnv(type){
wx.getNetworkType({
success :(res) => {
if(res.errMsg == 'getNetworkType:ok'){
if(res.networkType != 'wifi'){
wx.showModal({
title: '流量提醒',
content: '你目前处于非WIFI环境,是否继续',
confirmText : '继续',
confirmColor : '#07c160',
success :(res1) => {
if (res1.confirm) {
liveApi.queryLiveDetail({id : this.liveId}).then(res2 => {
if(res2.data.code == '200'){
if(res2.data.data.liveBroadcastState == 4 || res2.data.data.liveBroadcastState == 2){
wx.showModal({
title: '提示',
content: '直播已关闭',
success (res3) {
if (res3.confirm) {
wx.reLaunch({url:`../liveList/main`})
} else if (res3.cancel) {
console.log('用户点击取消')
}
}
})
}else{
this.startLive(type);
}
}
})
} else if (res1.cancel) {
// console.log('用户点击取消')
}
}
})
}else{
this.startLive(type);
}
}
}
})
},
//开始直播
startLive(type){
this.isDetailControlLock = false;
if(type == 'recover'){
this.recoverLive = false;
this.isUsual = false;
}else if(type == 'start'){
this.noStartLive = false;
}
this.isPruductUp = true;
this.liveCountDown = 3;
this.isCountDown = true;
let timer = setInterval(() => {
--this.liveCountDown;
if(this.liveCountDown == 0){
console.log('开始直播')
this.pusher.start(); //开始推流
this.isCountDown = false;
this.isSetBeauty = false;
clearInterval(timer)
this.changeLiveStatus(1);
}
},1000)
},
//改变直播状态
changeLiveStatus(val){
liveApi.updateLiveStatus({
id : this.liveId,
liveBroadcastState : val
}).then(res => {
if(res.data.code == '200'){
if(val == 1){
this.isLive = true;
this.enableCamera = true;
this.isBgImg = false;
this.pusher.resume();
}else if(val == 3){
this.isLive = false;
console.log('222222')
this.recoverLive = true;
this.isBgImg = true;
this.enableCamera = false;
this.pusher.pause();
}
this.isDetailControlLock = true;
this.$set(this.liveInfo,'liveBroadcastState',val)
// this.pusher.resume();
}
})
},
//设置点击右上角返回
closeSetBeauty(val){
this.isSetBeauty = val;
this.isBgImg = true;
this.enableCamera = false;
this.isDetailControlLock = true;
if(this.liveInfo.liveBroadcastState == 0){
this.noStartLive = true;
}else if(this.liveInfo.liveBroadcastState == 1){
this.noStartLive = false;
this.recoverLive = false;
}else if(this.liveInfo.liveBroadcastState ==3){
this.recoverLive = true;
}
},
//定时查询数据
timeGetInfo(serverTime){
let newCommentsTime = serverTime
let userActivebeginTime = serverTime
clearInterval(this.liveDetailTimer)
this.liveDetailTimer = setInterval(() => {
if(this.isTimeLock){
//第一次请求用服务器的时间减去2秒
this.isTimeLock = false;
let dataTime = this.isTimeFirstReq ? serverTime - 2000 : newCommentsTime
let userTime = this.isTimeFirstReq ? serverTime - 2000 : userActivebeginTime
liveApi.queryLiveComments({
id: Number(this.liveId),
beginTime: dataTime, //评论时间
userActivebeginTime : userTime, //用户进入时间
}).then(res => {
this.isTimeLock = true;
if(res.data.code == '200'){
this.isTimeFirstReq = false;
let result = res.data.data;
// if(result.liveState == 'IN_LIVE' || result.liveState == 'SUSPEND_LIVE' || result.liveState == 'NO_LIVE' || result.liveState == 'PAUSE_LIVE'){
//用户通知
this.entryNoticeText = "";
if (result.entryNoticeList.length > 0) {
if (result.entryNoticeList.length == 1) {
this.entryNoticeText = `${result.entryNoticeList[0].userName}`;//用户进入
} else {
this.entryNoticeText = `${
result.entryNoticeList[0].userName
}${result.entryNoticeList.length}人`;//用户进入
}
}
//观看
this.look = result.historyWatchNum;
//在线
this.online = result.watchNum
//点赞
this.praise = result.likeInfo.likeNum
//评论
result.guestBookList.forEach(item => {
this.commentsList.push(item)
})
if(result.guestBookList && result.guestBookList.length){
newCommentsTime = result.guestBookList[result.guestBookList.length - 1].createTimeStamp
}
if(result.entryNoticeList && result.entryNoticeList.length){
userActivebeginTime = result.entryNoticeList[result.entryNoticeList.length - 1].createTimeStamp
}
this.updateVal = new Date().getTime(); //监听使用数据
// }
}
})
}else{
console.log('上次请求未结束,进行了下一次请求')
}
},2000)
},
//服务器时间戳
getServerTimeNow(){
liveApi.queryServerTimeNow().then(res => {
if(res.data.code == 200){
//定时查询数据
this.timeGetInfo(res.data.data);
}
})
},
//推流状态
statechange(e){
console.log('statechange',e.mp.detail)
if(e.mp.detail.code == -1307){
this.isLive = false;
this.clearAllInterval()
wx.showToast({ title: e.mp.detail.message, icon: "none" });
}
},
binderror(e){
console.log('binderror',e.mp.detail)
if(e.mp.detail.errCode == 10002){ //禁用麦克风
this.getAuthSet('record')
}
if(e.mp.detail.errCode == 10001){ //禁用摄像头
this.getAuthSet('camera')
}
},
bindnetstatus(e){
console.log('binderror',e.mp.detail)
},
//获取商品列表
getProductList(){
liveApi.queryProductList({id : this.liveId,pageNum : 0,pageSize:0}).then(res => {
if(res.data.code == '200'){
let productIdArr = []
let productIdArr1 = []
this.productList.forEach(item2 => {
productIdArr.push(item2.productId)
})
res.data.data.forEach(item1 => {
productIdArr1.push(item1.productId)
})
if(JSON.stringify(productIdArr) != JSON.stringify(productIdArr1)){
this.speakProductList = [];
res.data.data.forEach(item => {
item.productImgUrl = DFSImg(item.productImgUrl)
item.minPrice = Number(item.minPrice).toFixed(2)
if(item.upperScreenState == '1'){
this.speakProductList.push(item)
}
})
this.productList = res.data.data
}
}
})
},
//商品上下屏
changeProduct(type,id,item){
if(this.isChangeProduct){
this.isChangeProduct = false;
liveApi.queryProductUpDown({
productId : id,
liveBroadcastId : this.liveId,
upperScreenState : type
}).then(res => {
this.isChangeProduct = true;
if(res.data.code == '200'){
console.log('上下屏')
if(type == 1){
if(this.speakProductList.length == 1){
if(Number(item.number) < Number(this.speakProductList[0].number)){
this.speakProductList.unshift(item)
}else{
this.speakProductList.push(item)
}
}else{
this.speakProductList.push(item)
}
this.productList.forEach((productItem,productIndex) => {
if(productItem.productId == id){
this.$set(this.productList[productIndex],'upperScreenState',1)
}
})
}else{
this.speakProductList.forEach((i,index) => {
if(i.productId == id){
this.speakProductList.splice(index,1)
}
})
this.productList.forEach((productItem,productIndex) => {
if(productItem.productId == id){
this.$set(this.productList[productIndex],'upperScreenState',0)
}
})
}
console.log(this.productList)
}else{
wx.showModal({
title: '提示',
content: res.data.msg,
success (res) {
if (res.confirm) {
console.log('用户点击确定')
} else if (res.cancel) {
console.log('用户点击取消')
}
}
})
}
})
}
},
//结束直播清除相关定时器
clearAllInterval(){
clearInterval(this.openLiveTimer)
clearInterval(this.getProductTimer)
clearInterval(this.liveDetailTimer)
},
changeOver(val){
this.overOrStop = 0;
}
}
}
</script>
<style scoped lang="scss">
@mixin btn {
width: 148px;
height: 40px;
text-align: center;
line-height: 40px;
font-size: 16px;
color: white;
border-radius: 8px;
background-image:-webkit-linear-gradient(to right,#FF877D, #FB566D);
background-image:-moz-linear-gradient(to right,#FF877D, #FB566D);
background-image:-o-linear-gradient(to right,#FF877D, #FB566D);
background-image: linear-gradient(to right,#FF877D, #FB566D);
}
.container{
width: 100%;
height: 100vh;
position: fixed;
top: 0;
left: 0;
box-sizing: border-box;
}
.masker{
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100vh;
background-color: rgba(102,102,102,0.38);
}
.bg-img{
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
z-index: -1;
}
.content{
width: 100%;
height: 100vh;
z-index: 10;
position: fixed;
top: 0;
left: 0;
z-index: 10;
}
.live-active{
width: 155px;
height: 17px;
background-color: rgba(0,0,0,.6);
margin-left: 36px;
border-radius: 17px;
font-size: 10px;
color: white;
display: flex;
align-items: center;
justify-content: space-around;
}
.wait-start{
text-align: center;
margin-top: 20vh;
.title{
font-size: 18px;
color: white;
font-weight: bold;
}
.open-live-title{
font-size: 15px;
color: #EEEEED;
line-height: 50px;
}
.wait-time{
font-size: 36px;
color: white;
font-weight: bold;
}
.start-btn{
@include btn;
margin: 23px auto 0;
}
}
.countdown{
width: 100%;
height: 100vh;
position: absolute;
top: 0;
left: 0;
background-color: rgba(0,0,0,.38);
padding-top: 35vh;
color: white;
font-size: 40px;
text-align: center;
z-index: 120;
}
.unusual-wrap{
text-align: center;
margin-top: 20vh;
color: white;
.title{
font-size: 18px;
font-weight: bold;
}
.unusual-text{
font-size: 36px;
line-height: 80px;
font-weight: bold;
}
.recover-btn{
@include btn;
margin: 20px auto 0;
}
}
.notice{
position: fixed;
left: 16px;
bottom: 60px;
width: 195px;
background-color: rgba(0,0,0,.4);
border-radius: 14px;
box-sizing: border-box;
padding: 10px 7px 7px 10px;
font-size: 12px;
color: white;
line-height: 18px;
}
.product-wrap{
position: fixed;
left: 19px;
bottom: 14px;
width: 31px;
height: 29px;
.product-num{
font-size:12px;
color: white;
width: 100%;
text-align: center;
position: absolute;
bottom: 4px;
}
.product-img{
width: 100%;
height: 100%;
}
}
.setting-wrap{
position: fixed;
right: 13px;
bottom: 14px;
width: 37px;
height: 37px;
.set-img{
width: 100%;
height: 100%;
}
}
.speak-product{
position: fixed;
left: 8px;
top:20vh;
.speak-item{
width: 78px;
margin-bottom: 15px;
border-radius: 2px;
overflow: hidden;
position: relative;
.item-status{
position: absolute;
top: 0;
left: 0;
width: 39px;
height: 12px;
color: white;
background-color: #FF4240;
border-bottom-right-radius: 2px;
font-size: 11px;
text-align: center;
line-height: 12px;
}
.item-top{
height: 78px;
background-color: #B1B1B1;
img{
width: 100%;
height: 100%;
}
}
.item-bottom{
height: 23px;
background-color: white;
text-align: center;
line-height: 23px;
font-size: 14px;
color: #FA7018;
}
}
}
.userComing {
margin-bottom: 10px;
background: rgba(#000, 0.4);
color: #fff;
font-size: 16px;
height: 26px;
line-height: 26px;
border-radius: 26px;
padding: 0 8px;
display: inline-block;
position: fixed;
bottom: 30vh;
}
.userComingAni {
animation: userComingAni 4.7s linear;
}
@keyframes userComingAni {
0% {
transform: translateX(150vw);
opacity: 0.3;
}
30% {
transform: translateX(24px);
opacity: 1;
}
80% {
transform: translateX(24px);
opacity: 1;
}
100% {
transform: translateX(-150vw);
opacity: 0;
}
}
</style>
\ No newline at end of file
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
{
"navigationStyle":"custom",
"usingComponents": {
"van-popup": "/static/vant/popup/index",
"van-divider": "/static/vant/divider/index"
}
}
\ No newline at end of file
<template>
<div class="container1" :style="{'padding-top':navHeight +'px'}">
<div class="navbar" :style="{'height' : navHeight + 'px','padding-top':navTop+'px'}">
<div @click="toIndex" class="history-btn">
<span class="iconfont iconzuo"></span>
</div>
<div class="navbar-title">直播计划</div>
</div>
<div class="history-wrap">
<div class="history-box" @click="toHistory">
<img class="history-img" src="../../../static/images/lishi.png" alt="">
<span class="history-text">直播历史</span>
</div>
</div>
<div class="live-list" v-if="isLogin">
<div class="live-item" @click="toLive(item.id)" v-for="(item,index) in liveList" :key="index">
<div class="live-item-top">
<div class="top-img">
<img :src="item.logoUrl" alt="">
</div>
<div class="top-name">{{item.shopName}}</div>
</div>
<div class="live-posters">
<div class="posters-img">
<image :src="item.coverUrl" mode="aspectFill" alt=""></image>
<div class="masker"></div>
</div>
<div class="live-status">
<span class="status-text" v-show="item.liveBroadcastState == 0">
未开始
</span>
<span class="status-text" v-show="item.liveBroadcastState == 1">
直播中
</span>
<span class="status-text" v-show="item.liveBroadcastState == 2">
直播完成
</span>
<span class="status-text" v-show="item.liveBroadcastState == 3">
暂停直播
</span>
</div>
</div>
<div class="live-info">
{{item.title}}
</div>
<div class="live-time">开播时间: {{item.startTime}}</div>
</div>
</div>
<!-- 未登陆 -->
<div class="no-login-wrap" v-else>
<div class="no-info">
<div class="info-row1">暂无计划</div>
<div class="info-row2">授权登陆后查看</div>
</div>
<button class="login-btn" lang="zh_CN" open-type="getUserInfo" @getuserinfo="getUserInfo">立即登陆</button>
</div>
<div class="no-list" v-if="!liveList.length && isLogin">
暂无直播
</div>
<!-- 绑定手机号 -->
<div class="toCLogin1" v-if="isShowPhone">
<div class="btn_info1">
<h1>绑定手机号</h1>
<span class="hint">检测到您的账号还未绑定手机号,请绑定手机号</span>
<button class="btn" open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">绑定手机号一键绑定</button>
<!-- <div class="btn2" @click="handbindHandle">手动绑定手机号</div> -->
</div>
<div class="layer" @click="isShowPhone=false"></div>
</div>
</div>
</template>
<script>
import { getNavbarInfo,DFSImg } from '../../utils/common.js'
import { wx_decode } from "@/utils/wxIndex.js";
import login from "@/api/login";
import indexApi from '@/api/liveing'
import liveApi from '@/api/liveing'
export default {
data(){
return{
navTop : '',
navHeight : '',
//直播计划列表
liveList : [],
//登录状态
isLogin : false,
isHaveUnion : '',
appid : '',
session_key: "",
openid : '',
unionId: "",
userInfo : '',
phoneNumber : '',
isShowPhone : false,//绑定手机号码状态
code : '',
shopId: process.env.SHOP_MIXID,
baseUrl: process.env.BASE_URL,
}
},
created(){
//获取导航栏信息
getNavbarInfo((res) => {
this.navTop = res.navTop
this.navHeight = res.navHeight
})
},
onShow(){
wx.setKeepScreenOn({
keepScreenOn: false
})
this.checkIsLogin();//检测登录状态
wx.checkSession({
success : () => {
//session_key 未过期,并且在本生命周期一直有效
wx.login({
success: res => {
this.code = res.code;
},
fail: err => {
reject(err);
}
}) //重新登录
},
fail : () => {
// session_key 已经失效,需要重新执行登录流程
wx.login({
success: res => {
this.code = res.code;
},
fail: err => {
reject(err);
}
}) //重新登录
}
})
},
onLoad(){
},
methods:{
//去商城首页
toIndex(){
let backPath = `/`;
let query = {
sessionid : wx.getStorageSync('sessionid') || '',
}
wx.reLaunch({
url: `../index/main?from=liveList&backpath=${
backPath
}&params=${JSON.stringify(query)}`
});
},
toHistory(){
wx.navigateTo({url:'../historyLive/main'})
},
//去直播间
toLive(id){
liveApi.queryLiveDetail({id}).then(res => {
console.log(res.data)
if(res.data.code == '200'){
if(res.data.data){
let openId = '';
this.liveList.forEach(item => {
if(item.liveBroadcastState == 3 || item.liveBroadcastState == 1){
openId = item.id
}
})
if(openId){
if(openId == id){
wx.navigateTo({url:'../live/main?id=' + id})
}else{
wx.showToast({ title: '同时只能开播一个直播间', icon: "none" });
}
}else{
wx.navigateTo({url:'../live/main?id=' + id})
}
}else{
wx.showModal({
title: '提示',
content: '直播已关闭',
success : (res3) => {
if (res3.confirm) {
this.getLiveList()
} else if (res3.cancel) {
console.log('用户点击取消')
}
}
})
}
}else{
wx.showModal({
title: '提示',
content: '直播已关闭',
success : (res3) => {
if (res3.confirm) {
this.getLiveList()
} else if (res3.cancel) {
console.log('用户点击取消')
}
}
})
}
})
},
getUserInfo(e){
wx.showLoading({
title: "加载中"
});
if(e.target.errMsg == "getUserInfo:ok"){
this.init().then(res => {
//存入openid
wx.setStorage({
key: "openid",
data: res.data.data.openid
});
if (res.data.data.isHaveUnion == "true") {
wx.setStorage({
key: "sessionid",
data: res.data.data.sessionId
});
this.isHaveUnion = true;
}else {
//需要绑定
this.isHaveUnion = false;
}
this.appid = res.data.data.appid;
this.session_key = res.data.data.session_key;
this.openid = res.data.data.openid;
this.checkLogin(e);
}).catch(error => {
wx.hideLoading();
wx.showToast({ title: error, icon: "none" });
})
}else{
wx.hideLoading();
wx.showToast({ title: "获取用户信息失败", icon: "none" });
}
},
init(){
return new Promise((resolve, reject) => {
login.miniLogin({ code: this.code}).then(res1 => {
if (res1.data.code == 200) {
resolve(res1);
} else {
reject(res1.data.msg);
}
})
.catch(err => {
reject(err);
});
});
},
checkLogin(e) {
if (this.isHaveUnion) {
wx.hideLoading();
var data = wx_decode(
this.appid,
this.session_key,
e.mp.detail.encryptedData,
e.mp.detail.iv
);
this.userInfo = JSON.parse(e.target.rawData);
this.$store.commit('setUserInfo',this.userInfo)
console.log(this.userInfo)
//是会员 直接登录
this.$store.commit('setLoginStatus',1)
this.isLogin = true;
this.isShowPhone = false;
this.getLiveList()
} else {
var data = wx_decode(
this.appid,
this.session_key,
e.mp.detail.encryptedData,
e.mp.detail.iv
);
this.unionId = data.unionId || "";
this.userInfo = JSON.parse(e.target.rawData);
this.$store.commit('setUserInfo',this.userInfo)
if (this.unionId) {
wx.hideLoading();
login.checkUnionid({ unionId: this.unionId, openId: this.openid })
.then(res => {
if (res.data.code == 200) {
if (res.data.data.isHaveUnion == "true") {
console.log('true===========')
wx.setStorage({
key: "sessionid",
data: res.data.data.sessionId
});
this.isLogin = true
this.$store.commit('setLoginStatus',1)
this.isShowPhone = false;
this.getLiveList()
} else {
//不是会员需要绑定手机号
this.isShowPhone = true;
}
}else{
this.isShowPhone = true;
}
})
.catch(err => {
wx.showToast({ title: err, icon: "none" });
wx.hideLoading();
});
}
else {
wx.hideLoading();
//不是会员需要绑定手机号
this.isShowPhone = true;
}
}
},
getPhoneNumber(e){
wx.checkSession({
success: () => {
//session_key 未过期,并且在本生命周期一直有效
if (e.target.errMsg == "getPhoneNumber:ok") {
// this.isShowPhone = false;
this.phoneNumber = wx_decode(
this.appid,
this.session_key,
e.mp.detail.encryptedData,
e.mp.detail.iv + ""
).phoneNumber;
this.bindUser();
}
},
fail: () => {
// session_key 已经失效,需要重新执行登录流程
// wx.login() //重新登录
}
});
},
bindUser() {
let query = {
openId: this.openid,
phoneNumber: this.phoneNumber,
unionId: this.unionId,
headImgUrl: this.userInfo.avatarUrl,
gender: this.userInfo.gender,
nickname: this.userInfo.nickName,
country: this.userInfo.country,
province: this.userInfo.province,
city: this.userInfo.city,
otherPhone: 0
};
login.bindUser(query).then(res => {
//绑定成功
if (res.data.code == 200) {
wx.setStorage({
key: "sessionid",
data: res.data.data.sessionId
});
this.isShowPhone = false;
wx.hideLoading();
this.$store.commit('setLoginStatus',1)
this.isLogin = true;
this.getLiveList()
}else{
wx.showToast({ title: res.data.msg, icon: "none" });
this.isShowPhone = false;
}
})
.catch(err => {
wx.showToast({ title: res.data.msg, icon: "none" });
console.log(err, "bindusererr");
});
},
checkIsLogin(){
let getOpenid = wx.getStorageSync("openid");
let getSessionid = wx.getStorageSync("sessionid");
if (getOpenid == "" || getSessionid == "") {
this.isLogin = false;
}
if(getOpenid && getSessionid){
this.$store.commit('setLoginStatus',1)
console.log('getOpenid2',getOpenid)
this.isLogin = true
this.getLiveList(); //获取直播计划列表
}
},
//获取直播计划列表
getLiveList(type){
wx.showLoading({
title : '加载中'
})
indexApi.queryLiveList().then(res => {
if(res.data.code == "200"){
wx.hideLoading()
if(type == 'refresh'){ //下拉刷新
wx.hideNavigationBarLoading();
// 停止下拉动作
wx.stopPullDownRefresh();
}
res.data.data.forEach(item => {
item.coverUrl = DFSImg(item.coverUrl)
item.logoUrl = DFSImg(item.logoUrl)
item.startTime = `${item.startTime.split(' ')[0]} ${item.startTimeByWeek} ${item.startTime.split(' ')[1].substr(0,5)}`
})
this.liveList = res.data.data;
}
}).catch(error => {
wx.showToast({ title: error, icon: "none" });
wx.hideLoading()
})
},
},
onPullDownRefresh(){
// wx.showLoading({
// title : '加载中'
// })
this.getLiveList('refresh')
}
}
</script>
<style scoped lang="scss">
@mixin btn {
width: 148px;
height: 40px;
text-align: center;
line-height: 40px;
font-size: 16px;
color: white;
border-radius: 8px;
background-image:-webkit-linear-gradient(to right,#FF877D, #FB566D);
background-image:-moz-linear-gradient(to right,#FF877D, #FB566D);
background-image:-o-linear-gradient(to right,#FF877D, #FB566D);
background-image: linear-gradient(to right,#FF877D, #FB566D);
}
img{
width: 100%;
height: 100%;
}
.container1{
min-height: 100vh;
height: 50vh;
padding-bottom: 12px;
background-color: #efefef;
}
.history-wrap{
width: 100%;
height: 50px;
background-color: white;
display: flex;
justify-content: flex-end;
border-top: 1rpx solid #efefef;
box-sizing: border-box;
.history-box{
width: 40%;
height: 50px;
box-sizing: border-box;
padding-right: 10px;
display: flex;
justify-content: flex-end;
align-items: center;
.history-img{
width: 16px;
height: 16px;
margin-right: 4.5px;
}
.history-text{
font-size: 15px;
color: #333333;
}
}
}
.navbar{
box-sizing: border-box;
display: flex;
justify-content: center;
align-items: center;
position: relative;
background-color: white;
width: 100%;
position: fixed;
left: 0;
top: 0;
z-index: 10;
.history-btn{
width: 21px;
height: 21px;
position: absolute;
left: 16px;
.btn-img{
width: 100%;
height: 100%;
}
}
.navbar-title{
font-size: 14px;
color: #000;
text-align: center;
}
}
.live-list{
box-sizing: border-box;
padding: 12px 12px 0 12px;
.live-item{
width: 100%;
background-color: white;
border-radius: 4px;
padding: 0 12px 16px;
box-sizing: border-box;
margin-bottom: 12px;
.live-item-top{
display: flex;
justify-content: flex-start;
align-items: center;
height: 42px;
.top-img{
object-fit: fill;
width: 27px;
height: 27px;
border-radius: 50%;
overflow: hidden;
background-color: #B5B5B5;
margin-right: 6px;
}
.top-name{
font-size: 15px;
color: #333333;
}
}
.live-posters{
width: 100%;
height: 184px;
background-color: #B5B5B5;
border-radius: 4px;
position: relative;
overflow: hidden;
.posters-img{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: 4px;
overflow: hidden;
.masker{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 2;
background-color: rgba(102,102,102,.38);
}
image{
width: 100%;
height: 100%;
}
}
.live-status{
padding: 0 9px;
height: 20px;
border-radius: 2px;
background-color: rgba(0, 0, 0, 0.8);
color: #FEFEFE;
font-size: 12px;
position: absolute;
bottom: 5px;
left: 5px;
line-height: 20px;
box-sizing: border-box;
padding-left: 22px;
z-index: 3;
.status-text{
&::before{
content: "";
position: absolute;
width: 5px;
height: 5px;
border-radius: 50%;
background-color: white;
top:8px;
left: 10px;
}
}
}
}
.live-info{
font-size: 15px;
color: #333333;
line-height: 34px;
}
.live-time{
font-size: 13px;
color: #999999;
}
}
}
.no-login-wrap{
text-align: center;
padding-top: 20vh;
.no-info{
.info-row1{
font-size: 30px;
color: #999999;
}
.info-row2{
font-size: 15px;
line-height: 30px;
color: #999999;
}
}
.login-btn{
@include btn;
margin: 45px auto 0;
}
}
.no-list{
text-align: center;
padding-top: 20vh;
font-size: 30px;
color: #999999;
}
.toCLogin1 {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100vh;
z-index: 10;
.btn_info1 {
position: absolute;
top: 30vh;
box-sizing: border-box;
left: 10%;
width: 80%;
color: #000;
align-items: center;
justify-content: space-around;
border: 1px solid #000;
border-radius: 5px;
padding: 15px;
z-index: 10;
background-color: #fff;
h1 {
text-align: center;
font-size: 22px;
margin: 10px 15px;
font-weight: 700;
}
.btn {
margin-top: 25px;
background-color: #01d10c;
color: #fff;
height: 45px;
line-height: 45px;
border-radius:5px;
font-size: 16px;
}
}
.layer {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.4);
z-index: 1;
}
}
</style>
\ No newline at end of file
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
{
"enablePullDownRefresh":true,
"navigationStyle":"custom",
"navigationBarTitleText":"直播计划",
"usingComponents": {
"van-divider": "/static/vant/divider/index"
}
}
\ No newline at end of file
<template>
<div class="container" :style="{'padding-top':navHeight +'px'}">
<div class="masker"></div>
<image class="bg-img" :src="overInfo.coverUrl" mode="aspectFill" alt=""></image>
<div class="conbox">
<div class="live-over">
<div class="over-text">直播已结束</div>
<div class="live-time">直播时长:{{overInfo.liveTime}}</div>
</div>
<div class="live-info">
<div class="info-row item-row-one">
<div class="info-item">
<div class="item-num">{{overInfo.watchNum}}</div>
<div class="item-text">观看</div>
</div>
<div class="info-item">
<div class="item-num">{{overInfo.goodsClickNum}}</div>
<div class="item-text">商品点击</div>
</div>
</div>
<div class="info-row">
<div class="info-item">
<div class="item-num">{{overInfo.shareNum}}</div>
<div class="item-text">分享</div>
</div>
<div class="info-item">
<div class="item-num">{{overInfo.guestBookNum}}</div>
<div class="item-text">评论</div>
</div>
<div class="info-item">
<div class="item-num">{{overInfo.likeNum}}</div>
<div class="item-text"></div>
</div>
</div>
</div>
</div>
<navBar :navTop="navTop" :liveInfo="liveInfo" :navHeight="navHeight" :type="type"></navBar>
</div>
</template>
<script>
import navBar from '@/components/common/navbar.vue'
import { getNavbarInfo,DFSImg } from '../../utils/common.js'
import liveApi from '@/api/liveing'
export default {
data(){
return{
navTop : '',
navHeight : '',
type : 2,
overInfo : {},
liveInfo : {}
}
},
components:{
navBar
},
created(){
//获取导航栏信息
getNavbarInfo((res) => {
this.navTop = res.navTop
this.navHeight = res.navHeight
})
},
onShow(){
// this.overInfo = {}
},
onLoad(options){
this.overInfo = {}
if(options.type){
this.type = options.type;
}
this.liveInfo = JSON.parse(options.liveInfo)
this.getOverInfo(options.id)
},
methods:{
getOverInfo(id){
liveApi.queryCompleteDetail({
id : id
}).then(res => {
// console.log(res.data.code == 200)
if(res.data.code == 200){
// console.log(res.data.data)
res.data.data.coverUrl = DFSImg(res.data.data.coverUrl)
this.overInfo = res.data.data
console.log(this.overInfo)
}
})
}
},
}
</script>
<style scoped lang="scss">
.container{
width: 100%;
height: 100vh;
box-sizing: border-box;
background-color: rgba(102,102,102,.38);
overflow: hidden;
position: fixed;
top: 0;
left: 0;
.conbox{
width: 100%;
height: 100vh;
position: fixed;
top: 0;
left: 0;
z-index: 10;
}
.masker{
width: 100%;
height: 100vh;
position: fixed;
top: 0;
left: 0;
z-index: 1;
background-color: rgba(102,102,102,.38);
}
.bg-img{
width: 100%;
height: 100vh;
position: fixed;
top: 0;
left: 0;
background-color: rgba(102,102,102,.38);
}
.live-over{
color: white;
text-align: center;
padding-top: 25vh;
.over-text{
font-size: 36px;
color: #FFFFFF;
font-weight: bold;
}
.live-time{
font-size: 15px;
line-height: 30px;
}
}
.live-info{
font-size: 18px;
color: white;
margin-top: 10vh;
width: 100%;
.info-row{
display: flex;
justify-content: space-around;
align-items: center;
margin-bottom: 40px;
font-weight: bold;
.info-item{
text-align: center;
}
}
.item-row-one{
width: 100%;
padding: 0 60px;
box-sizing: border-box;
.info-item{
width: 50%;
}
}
}
}
</style>
\ No newline at end of file
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
{
"navigationStyle":"custom"
}
\ No newline at end of file
<template>
<div class="lived">
<!-- 背景(未开始&&已结束) -->
<div class="bgImg" v-if="liveNoticeInfo.coverUrl&&liveNoticeInfo.liveBroadcastState!=1">
<!-- <img :src="liveNoticeInfo.coverUrl" alt /> -->
<image :src="liveNoticeInfo.coverUrl" mode="aspectFill" alt=""></image>
</div>
<!-- 直播展示层 -->
<div class="liveModel" v-if="liveNoticeInfo.liveBroadcastState>-1">
<!-- 自定义返回按钮 -->
<!-- ,'height':(navHeight*2-2)+'rpx' -->
<div class="customBack flex" :style="{'top':(navHeight)+'rpx'}">
<div class="backIcon">
<img
@click="back"
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAACWklEQVR4Xu3by2rVUBSH8fVXRCmiiCIWUbwi3tpSFRFFFBEviOKF4hv4BM51rO8htoPOfQZBHDgUBX0Gp58EVsGB5hx3drLXTk+mhxPy/bKSQC6yTb5ok/fbDGA2AYEFgDdm9sw38YOkF7k3N+QhAGwxs/d/xG90v5b0KidCOABgq8c//UfoUUnfcyGEAgC2efzjlsBlSZ9GBwBs9/hHLXFfzWxB0q9RAQA7PP7hhLAnktZzxTfrKX4IAHMe/2BC2IqktZzxxQGAnR5/v0R8UQBgl8ffLRVfDADY7fF3SsYXAQD2ePzt0vGDAwB7Pf5WhPhBAYB9ZrZqZjejxA8GAOz3PX8jUvwgAMABj78eLb53AGDex/5axPheAYCDvuevRo3vDQA45PFXIsf3AgAc9rG/HD0+OwBwxOMv1RCfFQA45mN/sZb4bADACY9frik+CwBw0sd+qbb4zgDAKd/zizXGdwIATnv8+VrjkwGAMz72Z2uO7wLwzsye1x6fBODX+m9jiE8FWDCzzy0Aa5JWJgCF+Tnptjjw0cwujAEhFeCemTVPbttOglVMQhJAs+envBKER0gGGAtCJ4AxIHQGqB0hC0DNCNkAakXIClAjQnaA2hB6AagJoTeAWhB6BagBoXeA6AiDAERGGAwgKsKgABERBgeIhlAEIBJCMYAoCEUBIiAUByiNEALgPxDeSnqZ8556GIApEX5Kal6/ybaEApgC4Yukc9nqI3wv8LeYllvu4/9oagMEOO4PX5r3in+YWRM/rg8mco5y6rrCnQNSQ1L/NwNIlRvL/34D8BMaUGntkTQAAAAASUVORK5CYII="
alt
/>
</div>
<div class="shopName flex">
<div class="img" v-if="shopLogo">
<img :src="shopLogo" alt />
</div>
<div class="info">
<p class="name line-clamp1" v-if="shopName">{{shopName}}</p>
<p class="num" v-if="liveNoticeInfo.historyWatchNum>0">
<span>{{liveNoticeInfo.historyWatchNum}}</span>
<span style="margin-left:6px;">观看</span>
</p>
</div>
<div class="toShop" @click="toShop">进店</div>
</div>
</div>
<!-- 未开始展示 -->
<notStarted v-if="liveNoticeInfo.liveBroadcastState==0" :info="liveNoticeInfo"></notStarted>
<!-- 直播暂停展示 -->
<isPauseShow v-if="liveNoticeInfo.liveBroadcastState==3" :info="liveNoticeInfo"></isPauseShow>
<!-- 结束展示 -->
<livedIsEnded
v-if="liveNoticeInfo.liveBroadcastState==2"
:updateGoods="updateGoods"
:endInfo="endInfo"
:goodsList="goodsList"
></livedIsEnded>
<!-- 控件层 -->
<livedControls
v-if="liveNoticeInfo&&liveNoticeInfo.liveBroadcastState!=2"
:info="liveNoticeInfo"
:entryNoticeText="entryNoticeText"
:guestBookList="guestBookList"
:updateVal="updateVal"
:updateGoods="updateGoods"
:likeInfo="likeInfo"
:goodsList="goodsList"
@toSendMsg="toSendMsg"
></livedControls>
</div>
<!-- 直播 -->
<live-player
v-if="liveNoticeInfo.liveBroadcastState==1&&liveNoticeInfo.boStreamRTMP"
class="livePlayer"
id="liveDemo"
:src="liveNoticeInfo.boStreamRTMP"
mode="live"
:picture-in-picture-mode="['push','pop']"
autoplay
object-fit="fillCrop"
orientation="vertical"
auto-pause-if-open-native="true"
auto-pause-if-navigate="true"
@error="error"
@statechange="changes"
/>
<!-- object-fit="fillCrop" -->
<!-- orientation="horizontal" -->
</div>
</template>
<script type="text/ecmascript-6">
import {
serialize,
getQueryVariable,
DFSImg,
getNavbarInfo
} from "@/utils/index";
import live from "@/api/live";
import notStarted from "@/components/livedModel/notStarted";
import livedControls from "@/components/livedModel/livedControls";
import livedIsEnded from "@/components/livedModel/livedIsEnded";
import isPauseShow from "@/components/livedModel/isPauseShow";
import spokesman from "@/api/spokesman";
import shop from "@/api/shop";
export default {
name: "",
data() {
return {
liveId: "", //直播间id
livedUrl: "rtmp://58.200.131.2:1935/livetv/hunantv",
shopName: "",
shopLogo: "",
backPath: "",
isLoading: false,
status: 0, // 0:未开始 1:直播中 2:已结束
// 总数据
liveNoticeInfo: {}, //详情
entryNoticeText: "", //用户通知
guestBookList: [], // 定时查评论
goodsList: [], //商品列表
updateVal: 0, //子组件监听此数据进行数据赋值
updateGoods: 0, //商品相关组件监听
likeInfo: {}, //点赞
isVideo: false, //是否有直播或回放链接
liveTime: null, //定时器
isWifi: true, //提示网络环境
infoTiming: null, //全局定时器
goodTiming: null, //商品定时器
endInfo: {}, //直播结束详情
firstComing: true, // 首次进入
params: {},
userId: "",
hasInvitationStatus: 0, // 邀请资格:0-不能够邀请下级,1-能够邀请下级
spokesmanObj: {}, //分销员信息
navTop: 0,
navHeight: 0,
isTimeLock: true, //时间锁
isTimeFirstReq: true, //第一次数据请求
newCommentsTime: 0,
userActivebeginTime: 0
};
},
components: {
notStarted,
livedControls,
livedIsEnded,
isPauseShow
},
computed: {},
onLoad(options) {
console.log("onLoad");
this.isTimeLock = true;
this.isTimeFirstReq = true;
this.newCommentsTime = 0;
wx.setKeepScreenOn({
keepScreenOn: true
});
getNavbarInfo(res => {
console.log(res, "--------------------125");
this.navTop = res.navTop;
this.navHeight = res.navHeight;
});
wx.getNetworkType({
success: function(res) {
if (res.networkType != "wifi") {
wx.showModal({
content: "您当前处于非wifi网络环境下",
confirmColor: "#ff877d",
success: function(res) {
if (res.confirm) {
} else if (res.cancel) {
}
}
});
}
}
});
this.params = JSON.parse(options.params);
console.log(this.params, "-----------------133");
this.$store.commit("setOfflineShopCode", this.params.offlineShopCode);
this.liveId = this.params.liveId;
this.shopName = this.params.shopName;
this.backPath = this.params.fromPagePath || "/";
this.shopLogo = DFSImg(this.params.shopLogo, 40, 40);
// 是否有分销员信息
if (this.params.spokesmanGroupId) {
this.$store.commit("setSpokesman", {
spokesmanGroupId: this.params.spokesmanGroupId,
spokesmanShopId: this.params.spokesmanShopId,
spokesmanRelId: this.params.spokesmanRelId
});
}
this.init();
// this.userEntry("IN");
// 通过分享进入直播间重新查询订阅消息配置
this.getMsgConfig();
this.isLogin();
this.getServerTimeNow();
},
onShareAppMessage(options) {
let query = {
liveBroadcastId: this.liveId,
shareType: "WX"
};
live.addShareRecord(query).then();
let _this = this;
if (this.hasInvitationStatus == 1) {
Object.assign(this.params, this.params, this.spokesmanObj);
}
console.log(this.params, "--------------161");
let shareObj = {
title: this.liveNoticeInfo.title,
path: `/pages/lived/main?params=${JSON.stringify(this.params)}`,
imageUrl: this.liveNoticeInfo.shareUrl,
success: function(res) {
console.log("-----------success");
// 转发成功之后的回调
if (res.errMsg == "shareAppMessage:ok") {
console.log(res, "分享成功");
}
},
fail: function(res) {
console.log("-----------fail");
// 转发失败之后的回调
if (res.errMsg == "shareAppMessage:fail cancel") {
console.log(res, "取消转发");
} else if (res.errMsg == "shareAppMessage:fail") {
console.log(res, "转发失败");
}
}
};
console.log(shareObj, "----------------168");
return shareObj;
},
onHide() {
this.userEntry("OUT");
},
onShow() {
console.log("onShow");
this.userEntry("IN");
},
onUnload() {
this.liveNoticeInfo.liveBroadcastState = -1;
this.liveNoticeInfo = {};
this.liveNoticeInfo.boStreamRTMP = "";
let videoContext = wx.createLivePlayerContext("liveDemo");
videoContext.stop();
this.userEntry("OUT");
this.firstComing = true;
if (this.infoTiming) {
clearInterval(this.infoTiming);
this.infoTiming = null;
}
if (this.goodTiming) {
clearInterval(this.goodTiming);
this.goodTiming = null;
}
},
mounted() {},
methods: {
// 初始化数据
init() {
let liveBroadcastId = this.liveId;
live.getLiveInfo(liveBroadcastId).then(res => {
if (res.data.code == 200) {
console.log(res.data.data, "------73");
this.liveNoticeInfo = res.data.data;
this.liveNoticeInfo.coverUrl = this.liveNoticeInfo.coverUrl
? DFSImg(this.liveNoticeInfo.coverUrl)
: "";
this.liveNoticeInfo.shareUrl = this.liveNoticeInfo.coverUrl
? DFSImg(this.liveNoticeInfo.coverUrl, 500, 400)
: "";
this.getGoodsList();
if (this.liveNoticeInfo.liveBroadcastState == 2) {
// 调直播结束
this.endLived();
} else {
console.log("这里");
this.timingGetInfo();
}
if (this.liveNoticeInfo.liveBroadcastState != 2 && !this.goodTiming) {
this.goodTiming = setInterval(() => {
console.log("--------获取商品接口");
this.getGoodsList();
}, 5000);
} else if (
this.liveNoticeInfo.liveBroadcastState == 2 &&
this.goodTiming
) {
clearInterval(this.goodTiming);
}
}
});
},
back() {
let query = {
sessionid: wx.getStorageSync("sessionid") || ""
};
// 返回商城
wx.reLaunch({
url: `../index/main?from=livedBackShop&backpath=${
this.backPath
}&params=${JSON.stringify(query)}`
});
},
// 是否登录
isLogin() {
let _this = this;
wx.getStorage({
key: "sessionid",
success(res) {
// 查询分销员信息
_this.getSpokesman();
},
fail(res) {}
});
},
getMsgConfig() {
if (!this.$store.state.subscribeMessageObj) {
shop.getWxMiniSubscribeMessageConfig().then(res => {
if (res.data.code == 200) {
const data = res.data.data;
console.log("wx mini subscribe message data: ", data);
if (data != null) {
const subscribeMessageObj = {};
for (var key in data) {
if (data[key] && data[key].template_id) {
subscribeMessageObj[key] = data[key].template_id;
}
}
this.$store.commit("setSubscribeMessageObj", subscribeMessageObj);
}
}
});
}
},
getSpokesman() {
spokesman.getSpokesmanidByShare().then(res => {
if (res.data.code == 200) {
if (res.data.data.hasInvitationStatus == 1) {
this.hasInvitationStatus = 1;
this.spokesmanObj = {
spokesmanGroupId: res.data.data.groupId,
spokesmanShopId: res.data.data.shopId,
spokesmanRelId: res.data.data.spokesmanId
};
}
}
});
},
toShop() {
// 到商城首页
this.backPath = "/";
wx.reLaunch({
url: `../index/main?from=livedToIndex&backpath=${this.backPath}`
});
},
// 定时查询直播数据
timingGetInfo(serverTime) {
if (this.isTimeLock) {
this.isTimeLock = false;
let dataTime = this.isTimeFirstReq
? serverTime - 2000
: this.newCommentsTime;
let userTime = this.isTimeFirstReq
? serverTime - 2000
: this.userActivebeginTime;
// 前五秒
let query = {
id: Number(this.liveId),
beginTime: dataTime,
userActivebeginTime: userTime //用户进入时间
};
live.getLiveStateById(query).then(res => {
this.isTimeFirstReq = false;
this.isTimeLock = true;
if (res.data.code == 200) {
let resData = res.data.data;
// 1、判断状态如果发生改变才init();
// 2、直播中给用户进入通知、评论、点赞数赋值
if (
this.liveNoticeInfo.liveBroadcastState == 0 &&
resData.liveState == "NO_LIVE"
) {
// 未开始且接口也未开始不作操作
} else if (
this.liveNoticeInfo.liveBroadcastState == 1 &&
resData.liveState == "IN_LIVE"
) {
} else if (
this.liveNoticeInfo.liveBroadcastState == 0 &&
resData.liveState == "IN_LIVE"
) {
console.log("未开始----直播中");
// 未开始且接口直播中/直播中且接口已结束
this.init();
} else if (
(this.liveNoticeInfo.liveBroadcastState == 2 &&
resData.liveState == "END_LIVE") ||
(this.liveNoticeInfo.liveBroadcastState == 1 &&
resData.liveState == "END_LIVE")
) {
console.log(
this.liveNoticeInfo.liveBroadcastState,
resData.liveState,
this.firstComing,
"直播中----结束",
"结束----结束"
);
//直播结束且接口已结束
if (this.firstComing) {
this.firstComing = false;
this.init();
}
} else if (
this.liveNoticeInfo.liveBroadcastState == 1 &&
resData.liveState == "PAUSE_LIVE"
) {
this.liveNoticeInfo.liveBroadcastState = 3;
} else if (
this.liveNoticeInfo.liveBroadcastState == 3 &&
resData.liveState == "IN_LIVE"
) {
this.liveNoticeInfo.liveBroadcastState = 1;
}
// console.log("resData.guestBookList---》", resData.guestBookList)
this.guestBookList = resData.guestBookList; //评论列表
if (resData.guestBookList && resData.guestBookList.length) {
this.newCommentsTime =
resData.guestBookList[
resData.guestBookList.length - 1
].createTimeStamp;
}
if (resData.entryNoticeList && resData.entryNoticeList.length) {
this.userActivebeginTime =
resData.entryNoticeList[
resData.entryNoticeList.length - 1
].createTimeStamp;
}
this.likeInfo = resData.likeInfo; //点赞信息
// 直播中且接口直播中---主要操作
// 数据初始化
this.entryNoticeText = "";
this.liveNoticeInfo.historyWatchNum = resData.historyWatchNum; //观看人数
if (resData.entryNoticeList.length > 0) {
if (resData.entryNoticeList.length == 1) {
this.entryNoticeText = `${resData.entryNoticeList[0].userName}`; //用户进入
} else {
this.entryNoticeText = `${
resData.entryNoticeList[0].userName
}${resData.entryNoticeList.length}人`; //用户进入
}
}
this.updateVal = new Date().getTime(); //监听使用数据
} else {
// if (this.infoTiming) {
// clearInterval(this.infoTiming);
// }
}
});
} else {
console.log("上次请求未结束,进行了下一次请求");
}
},
// 获取商品列表
getGoodsList() {
let id = this.liveId;
live.getListByLiveBroadcastId(id).then(res => {
if (res.data.code == 200) {
this.goodsList = [];
let arr = [];
if (res.data.data.length > 0) {
this.goodsList = res.data.data.forEach((item, index) => {
if (item.productImgUrl) {
item.productImgUrl = DFSImg(item.productImgUrl);
item.minPrice = Number(item.minPrice);
}
arr.push(item);
});
this.goodsList = arr;
this.updateGoods = Math.random();
}
}
});
},
// 直播结束数据
endLived() {
let query = {
id: Number(this.liveId)
};
live.getLiveStatisticsById(query).then(res => {
if (res.data.code == 200) {
this.endInfo = res.data.data;
}
});
},
userEntry(type) {
let query = {
liveBroadcastId: Number(this.liveId),
activityType: type
};
live.userEntryOrExitsLiveRoom(query).then(res => {});
},
toSendMsg(val) {
live.addGuestbook(val).then(res => {
if (res.data.code == 200) {
} else {
wx.showToast({
title: res.data.msg,
icon: "none"
});
}
});
},
//服务器时间戳
getServerTimeNow() {
live.queryServerTimeNow().then(res => {
if (res.data.code == 200) {
//定时查询数据
// this.timingGetInfo(res.data.data);
this.newCommentsTime = res.data.data;
this.userActivebeginTime = res.data.data;
console.log("newCommentsTime", this.newCommentsTime);
// setTimeout(() => {
this.infoTiming = setInterval(() => {
this.timingGetInfo(res.data.data);
}, 2000);
// }, 2000);
}
});
},
error(res) {
console.log(res, "------------------237");
},
changes(res) {
console.log(res, "---------------241");
}
}
};
</script>
<style lang="scss" scoped>
img {
display: block;
}
.flex {
display: flex;
}
/*清除浮动*/
.clearfix {
zoom: 1;
}
.clearfix:after {
clear: both;
content: ".";
display: block;
width: 0;
height: 0;
visibility: hidden;
}
/* 一行否则出现省略号 */
.line-clamp1 {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
}
.line-clamp2 {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
line-height: 22px;
}
.lived {
width: 100vw;
height: 100vh;
position: relative;
overflow: hidden;
.bgImg {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
z-index: -1;
image {
width: 100%;
height: 100%;
object-fit: cover;
// 亮度
filter: brightness(0.8);
}
}
.liveModel {
width: 100vw;
height: 100vh;
position: absolute;
top: 0;
left: 0;
z-index: 1;
.customBack {
position: absolute;
left: 12px;
width: 70%;
z-index: 2;
align-items: center;
.backIcon {
img {
width: 18px;
height: 18px;
}
}
.shopName {
margin-left: 20px;
background: rgba(0, 0, 0, 0.6);
border-radius: 30px;
align-items: center;
padding-right: 10px;
.img {
width: 30px;
height: 30px;
border-radius: 50%;
overflow: hidden;
margin-left: 4px;
img {
width: 100%;
height: 100%;
}
}
.info {
margin: 0 8px;
color: #fff;
flex: 1;
font-size: 14px;
padding: 2px 0;
.num {
font-size: 12px;
}
}
.toShop {
background: linear-gradient(
90deg,
rgba(255, 135, 125, 1),
rgba(251, 86, 109, 1)
);
padding: 0 8px;
color: #fff;
font-size: 14px;
display: inline-block;
border-radius: 10px;
height: 20px;
line-height: 20px;
}
}
}
}
.livePlayer {
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
width: 100vw;
height: 100vh;
z-index: -1;
}
}
</style>
\ No newline at end of file
import Vue from 'vue'
import App from './index'
// add this to handle exception
Vue.config.errorHandler = function (err) {
if (console && console.error) {
console.error(err)
}
}
const app = new Vue(App)
app.$mount()
{
"navigationStyle":"custom",
"navigationBarTextStyle": "white",
"disableScroll": true,
"usingComponents": {
"van-button": "/static/vant/button/index",
"van-icon": "/static/vant/icon/index",
"van-popup": "/static/vant/popup/index",
"van-stepper": "/static/vant/stepper/index"
}
}
\ No newline at end of file
<template>
<div class="livedPoster">
<div class="posterWrap">
<canvas canvas-id="posterCanvas" class="myCanvas" @click="getImg"></canvas>
</div>
</div>
</template>
<script type="text/ecmascript-6">
import { serialize, getQueryVariable, DFSImg } from "@/utils/index";
import live from "@/api/live";
export default {
name: "",
data() {
return {
InfoSync: {},
liveId: 0,
params: {},
// 海报中信息
info: {
coverUrl: "",
livedStatus: 1, //直播状态 0未开播 1一开播
livedTime: "3月21日 20:20",
livedTitle: "",
nickName: "",
avatarUrl: "",
miniCode: ""
}
};
},
onLoad(options) {
this.params = JSON.parse(options.params);
this.liveId = this.params.liveId;
Object.assign(this.info,this.info,this.params);
console.log(this.info,'--------------------35');
this.init();
},
onUnload() {},
methods: {
back() {
wx.navigateBack({
delta: 1
});
},
init() {
wx.showLoading({title: '加载中…'})
let liveBroadcastId = this.liveId;
let _this = this;
wx.getUserInfo({
//获取微信用户信息
success: function(res) {
(_this.info.nickName = res.userInfo.nickName),
(_this.info.avatarUrl = res.userInfo.avatarUrl),
_this.initPoster(_this.info);
},
fail: function(res) {
_this.initPoster(_this.info);
}
});
// live.getLiveInfo(liveBroadcastId).then(res => {
// if (res.data.code == 200) {
// let resData = res.data.data;
// this.info.livedTitle = resData.title;
// this.info.livedStatus = resData.liveBroadcastState;
// let cImg = DFSImg(resData.coverUrl);
// if (cImg.indexOf("https") == -1) {
// this.info.coverUrl = cImg.replace("http", "https");
// }
// let newTime = new Date(resData.startTime.replace(/-/g, "/"));
// this.info.livedTime = `${newTime.getMonth() +
// 1}月${newTime.getDate() -
// 1}日 ${newTime.getHours()}:${newTime.getMinutes()}`;
// }
// });
},
initPoster(info) {
console.log(info, "---------------------71");
const InfoSync = wx.getSystemInfoSync();
this.InfoSync = InfoSync;
let bili = InfoSync.windowWidth / 375 * 1;
const ctx = wx.createCanvasContext("posterCanvas");
ctx.setFillStyle("#fff");
ctx.fillRect(0, 0, 310 * bili, 520 * bili);
//封面
this.saveThe(info.coverUrl, path => {
ctx.drawImage(path, 0, 0, 310 * bili, 370 * bili);
ctx.save();
// 微信昵称
ctx.setTextAlign("left");
ctx.setFillStyle("#3F2F00");
ctx.setFontSize(15);
ctx.fillText(info.nickName, 80 * bili, 420 * bili);
ctx.setTextAlign("left");
ctx.setFillStyle("#3F2F00");
ctx.setFontSize(14);
ctx.fillText("邀你一起看直播", 10 * bili, 460 * bili);
// 直播名
ctx.setTextAlign("left");
ctx.setFillStyle("#3F2F00");
ctx.setFontSize(18);
ctx.fillText(info.livedTitle, 10 * bili, 500 * bili);
//圆形头像框
ctx.setStrokeStyle("rgba(0,0,0,0)");
ctx.arc(40 * bili, 410 * bili, 30 * bili, 0, 2 * Math.PI);
ctx.fill();
//头像
this.saveThe(info.avatarUrl, path => {
ctx.clip();
ctx.drawImage(path, 10 * bili, 380 * bili, 70 * bili, 70 * bili);
ctx.save();
ctx.stroke();
ctx.draw();
});
wx.hideLoading();
});
},
// 小程序需要将图片下载下来,然后才能绘制到画布上
saveThe(url, callback) {
wx.getImageInfo({
src: url, //服务器返回的图片地址
success: res => {
callback(res.path);
},
fail: function(res) {}
});
},
getImg() {
this.handleSave();
},
// 点击保存时,将画布生成海报
handleSave() {
var that = this;
wx.showLoading({
title: "正在保存...",
mask: true
});
wx.getSetting({
success(res) {
if (res.authSetting["scope.writePhotosAlbum"]) {
that.saveImg();
} else if (res.authSetting["scope.writePhotosAlbum"] === undefined) {
wx.authorize({
scope: "scope.writePhotosAlbum",
success() {
that.saveImg();
},
fail() {
wx.hideLoading();
wx.showToast({
title: "您没有授权,无法保存到相册",
icon: "none"
});
}
});
} else {
wx.openSetting({
success(res) {
if (res.authSetting["scope.writePhotosAlbum"]) {
that.saveImg();
} else {
wx.showToast({
title: "您没有授权,无法保存到相册",
icon: "none"
});
}
}
});
}
},
fail: err => {
wx.hideLoading();
wx.showToast({
title: "出现了错误,请稍后再试",
icon: "none"
});
}
});
},
saveImg() {
// 按照设备比例去计算图片和画布尺寸
let bili = this.InfoSync.windowWidth / 375 * 1;
wx.canvasToTempFilePath({
x: 0,
y: 0,
width: 310 * bili,
height: 520 * bili,
destWidth: 310 * bili * this.InfoSync.pixelRatio,
destHeight: 520 * bili * this.InfoSync.pixelRatio,
fileType: "png",
quality: 1,
canvasId: "posterCanvas",
success: function(res) {
wx.hideLoading();
var tempFilePath = res.tempFilePath;
// 需要权限
wx.saveImageToPhotosAlbum({
filePath: tempFilePath,
success(res) {
wx.showModal({
content: "图片已保存到相册,赶紧晒一下吧~",
showCancel: false,
confirmText: "好的",
confirmColor: "#333"
});
},
fail: function(res) {
wx.hideLoading();
wx.showToast({
title: "没有相册权限",
icon: "none",
duration: 2000
});
}
});
},
fail: err => {
wx.hideLoading();
wx.showToast({
title: "出现了错误,请稍后再试",
icon: "none"
});
}
});
},
// 发送给朋友,以图片的方式,先生成临时图片地址,然后调用微信api显示转发
handleShowImg() {
let bili = this.InfoSync.windowWidth / 375 * 1;
wx.canvasToTempFilePath({
x: 0,
y: 0,
width: 310 * bili,
height: 520 * bili,
destWidth: 310 * bili * this.InfoSync.pixelRatio,
destHeight: 520 * bili * this.InfoSync.pixelRatio,
fileType: "png",
quality: 1,
canvasId: "posterCanvas",
success: function(res) {
wx.hideLoading();
wx.previewImage({
urls: [res.tempFilePath],
current: res.tempFilePath
});
},
fail: err => {
wx.hideLoading();
wx.showToast({
title: "出现了错误,请稍后再试",
icon: "none"
});
}
});
}
}
};
</script>
<style scoped lang="scss">
.livedPoster {
position: relative;
}
.posterWrap {
min-height: calc(100vh - 20px);
padding-top: 20px;
background-color: #f1f1f1;
}
.myCanvas {
width: 310px;
height: 520px;
margin: 0 auto;
background: #fff;
}
</style>
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()
\ No newline at end of file
{
"navigationBarTitleText": "点击保存图片"
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment