Commit b6718f83 by MichaelJier

Merge branch 'dev' of gitlab.aodianyun.com:broadcast_cloud/web-live into dev

parents 039c0477 2d28a67e
......@@ -16,4 +16,13 @@
后期可修改成 feature/alioss
4. 最新 nuxtjs 发现存在部分服务端与客户端 dom 不匹配的 bug
初步解决方案 <client-only> #content</client-only>
```html
<!-- 初步解决方案 -->
<client-only> #content</client-only>
```
5. 内部登录方法
```js
import login from '@/plugins/userAction/login'
login({token: ''})
```
......@@ -52,7 +52,7 @@ huawei:
ssr: true
folder: nuxt-dist
proxy: http://172.18.0.1:33000
server: /web\.aodiansoft\.com/
server: /web\.huaguangyun\.cn/
target:
project: Web
......
......@@ -11,7 +11,9 @@
@click="_changePlayer(item.playUrl, item.id)"
>
<div class="box">
<div class="name">{{ item.name }}</div>
<div class="name">
<div class="name-text">{{ item.name }}</div>
</div>
<img class="img" v-if="item.thumbnail" :src="item.thumbnail" alt="" />
<div class="icon" v-else></div>
</div>
......@@ -164,11 +166,17 @@ export default {
}
.name {
position: absolute;
top: 5px;
left: 5px;
top: 0;
width: 100%;
height: 100%;
z-index: 100;
font-size: 20px;
color: #fff;
&-text {
position: absolute;
top: 5px;
left: 5px;
}
}
}
&.z-active {
......
<template>
<div class="get-red">
<div class="tip">
<i class="icon"></i>
{{ info.userNick }}领取了
<em>{{ info.redFrom }}</em>
{{ info.msgType === 17 ? '红包雨' : ''}}{{ info.msgType === 20 ? '倒计时红包' : '' }}
<em>{{ info.money }}</em>
</div>
</div>
</template>
<script>
export default {
name: 'chat-red-tip',
props: {
info: {}
}
};
</script>
<style lang="less" scoped>
.get-red {
.tip {
line-height: 25px;
padding: 8px 10px;
border-radius: 8px;
font-size: 14px;
color: var(--chat-color);
background: var(--chat-bg);
.icon {
display: inline-block;
vertical-align: middle;
width: 22px;
height: 22px;
background-image: url('./img/icon-red.png');
background-repeat: no-repeat;
background-size: 20px auto;
background-position: center center;
}
em {
color: #d84e43;
font-style: normal
}
}
}
</style>
......@@ -48,6 +48,10 @@
<!--礼物打赏消息-->
<chat-reward-gift :info="info"></chat-reward-gift>
</template>
<template v-else-if="info.msgType == 17 || info.msgType == 20">
<!--领取红包雨 || 倒计时红包-->
<chat-red-tip :info="info"></chat-red-tip>
</template>
</div>
</template>
......@@ -64,6 +68,7 @@ import chatRedPasswordTip from './chatRedPasswordTip';
import chatRedAnswerTip from './chatRedAnswerTip';
import chatRedBusinessTip from './chatRedBusinessTip';
import chatRewardGift from './chatRewardGift';
import chatRedTip from './chatRedTip';
export default {
name: 'pc-chat-item',
props: {
......@@ -92,7 +97,8 @@ export default {
chatRedPasswordTip,
chatRedAnswerTip,
chatRedBusinessTip,
chatRewardGift
chatRewardGift,
chatRedTip
}
};
</script>
......@@ -45,7 +45,7 @@ export default {
},
mpsBackgroundUrl() {
const bgUrl = this.channelInfo.mpsBackgroundUrl;
return bgUrl ? `${bgUrl}?x-oss-process=style/twzb_origin` : '';
return bgUrl ? `${bgUrl}${process.env.private ? '' : '?x-oss-process=style/twzb_origin'}` : '';
},
mpsOptions() {
let options = {};
......
......@@ -36,7 +36,9 @@
/>
</div>
<div class="send-emoji" @click.stop="_toggleEmoji"></div>
<div class="send-btn" @click.stop="_sendChat">发送</div>
<div class="send-btn" @click.stop="sendCountDown === 0 && _sendChat()" :class="sendCountDown === 0 ? '' : 'unable'">
{{ sendCountDown === 0 ? '发送' : `${sendCountDown}s` }}
</div>
<keep-alive>
<emoji-box v-if="showEmoji" v-model="content"></emoji-box>
</keep-alive>
......@@ -56,6 +58,7 @@ export default {
},
data() {
return {
sendCountDown: 0,
showEmoji: false,
sendDate: 0,
content: '',
......@@ -123,13 +126,25 @@ export default {
uuid: this.uuid
});
if (res.code === 200 && res.errorCode === 0) {
this.content = '';
this._remReplay();
this._resetChat()
if (res.data.chatAuthModel === 1) {
this.$layer.msg('已提交审核,请耐心等待');
}
}
},
_resetChat() {
clearInterval(this.sendCountDownTimer)
this.sendCountDown = 3
this.sendCountDownTimer = setInterval(() => {
if (this.sendCountDown === 0) {
clearInterval(this.sendCountDownTimer)
} else if (this.sendCountDown > 0) {
this.sendCountDown--
}
}, 1000);
this._remReplay();
this.content = '';
},
_isDisabled() {
if (this.userInfo.isDisableChat === 1) {
this.$layer.msg('你已经被禁言,该功能暂时无法使用');
......@@ -290,6 +305,10 @@ export default {
border-radius: 2px;
cursor: pointer;
}
.unable {
color:#fff;
background-color: #999;
}
}
.chat-reply {
position: absolute;
......
......@@ -6,7 +6,7 @@
赠送的
<img :src="giftImg" />
{{ gift.name }}
<em>* {{ gift.num }}</em>
<em>x {{ gift.num }}</em>
</div>
</div>
</template>
......
......@@ -6,6 +6,11 @@
<div class="chat-list">
<chat-box></chat-box>
</div>
<transition name="fade">
<div class="svgaPage" v-show="showSVAG">
<canvas id="svgaBox"></canvas>
</div>
</transition>
</div>
</template>
......@@ -23,15 +28,68 @@ export default {
isShowChat: {}
},
data() {
return {};
return {
showSVAG: false
};
},
computed: {
...mapGetters({
userInfo: 'userInfo',
channelInfo: 'channelInfo'
channelInfo: 'channelInfo',
giftAni: 'giftAni'
})
},
methods: {}
mounted() {
this.$nextTick(() => {
const player = require('@gdyfe/svgaplayer-for-live')
this.SVGAPlayer = player.default({
target: '#svgaBox'
});
this.$Bus.$on('bus-playsvga', this.playsvga);
// setTimeout(() => {
// this.playsvga([{
// value: '//static-pro.guangdianyun.tv/static/svga/666/666·.svga',
// userHeadImg:'https://static-pro.guangdianyun.tv/robot-head/57f8ea050533d96616be29c52729124c.jpeg',
// userNick: 'Michael',
// filterContent: {
// img: '//static-pro.guangdianyun.tv/static/svga/666/666@2x.png',
// num: 1,
// name: '666'
// }
// }])
// }, 1000)
});
},
methods: {
playsvga(url){
if (!this.SVGAPlayer) return
this.showSVAG = true
this.SVGAPlayer.enqueue(url)
this.SVGAPlayer.$on('end',(info) => {
this.$Bus.$emit('bus-setGiftBannerInfo', null);
this.showSVAG = false
})
this.SVGAPlayer.$on('start',(info) => {
this.$Bus.$emit('bus-setGiftBannerInfo', info);
this.showSVAG = true
})
},
},
watch: {
giftAni(newVal) {
if (newVal) {
console.log('初始化svgaplayer')
const player = require('@gdyfe/svgaplayer-for-live')
this.SVGAPlayer = player.default({
target: '#svgaBox'
});
} else {
this.SVGAPlayer.destroyed()
this.SVGAPlayer = null
this.showSVAG = false
}
}
}
};
</script>
......@@ -51,5 +109,24 @@ export default {
width: 100%;
overflow: hidden;
}
.svgaPage {
position: absolute;
bottom: 0;
width: 90vw;
height: 90vw;
// background: rgba(0, 0, 0, 0.2);
z-index: 199;
padding-bottom: 0.5rem;
display: flex;
justify-content: center;
align-items: center;
.btn {
position: absolute;
}
#svgaBox {
width: 320px;
height: 320px;
}
}
}
</style>
......@@ -86,8 +86,8 @@ export default {
align-items: center;
margin-bottom: 0.1rem;
padding: 0.01rem;
height: 0.32rem;
border-radius: 0.32rem;
height: 0.35rem;
border-radius: 0.35rem;
background: rgba(0, 0, 0, 0.3);
&.gift {
.head {
......@@ -95,6 +95,7 @@ export default {
height: 0.3rem;
border-radius: 100%;
overflow: hidden;
margin-left: 0.02rem;
img {
display: block;
width: 100%;
......@@ -102,7 +103,7 @@ export default {
}
}
.info {
margin: 0 0.08rem;
margin: 0 0.08rem 0.02rem 0.08rem;
.name {
line-height: 0.2rem;
font-size: 0.11rem;
......
......@@ -21,12 +21,16 @@
<div class="icon questionnaire"></div>
<span>问卷报表</span>
</div>
<div class="item" @click="_setgift">
<div :class="`icon ${giftAni ? 'gift' : 'gift-close'}`"></div>
<span>礼物特效</span>
</div>
</div>
</transition>
</div>
</template>
<script>
import { mapGetters } from 'vuex';
import { mapGetters, mapMutations } from 'vuex';
export default {
name: 'vertical-more-box',
data() {
......@@ -39,7 +43,8 @@ export default {
channelInfo: 'channelInfo',
channelConfig: 'channelConfig',
userInfo: 'userInfo',
jumpUrls: 'jumpUrls'
jumpUrls: 'jumpUrls',
giftAni: 'giftAni'
}),
isQuestionnaire() {
const info = this.channelConfig.questionnaire || {};
......@@ -50,6 +55,17 @@ export default {
this.$Bus.$on('bus-remEnclosure', this._remEnclosure);
},
methods: {
...mapMutations({
set_giftAni: 'set_giftAni'
}),
_setgift() {
this.set_giftAni()
if (this.giftAni){
this.$layer.msg('已开启礼物特效')
} else {
this.$layer.msg('已屏蔽礼物特效')
}
},
_sendRed() {
if (!this.userInfo.id) {
this.$layer.msg('请登录');
......@@ -156,6 +172,14 @@ export default {
background: url(./img/icon-questionnaire.png) no-repeat center center;
background-size: contain;
}
&.gift {
background: url(./img/icon-gift.png) no-repeat center center;
background-size: contain;
}
&.gift-close {
background: url(./img/icon-giftclose.png) no-repeat center center;
background-size: contain;
}
}
&:first-child {
border-top: 0;
......
......@@ -25,7 +25,7 @@ export default {
}),
mpsBackgroundUrl() {
const bgUrl = this.channelInfo.channelBackground;
return bgUrl ? `${bgUrl}?x-oss-process=style/twzb_origin` : require('./img/bg.png');
return bgUrl ? `${bgUrl}${process.env.private ? '' : '?x-oss-process=style/twzb_origin'}` : require('./img/bg.png');
},
mpsOptions() {
let options = {};
......
......@@ -3,7 +3,9 @@
<div class="box">
<input type="text" v-model="content" @keyup.enter="_sendChat" ref="sendInput" v-iosfit />
</div>
<div class="btn" @click="_sendChat">发送</div>
<div class="btn" @click="sendCountDown === 0 && _sendChat()" :class="sendCountDown === 0 ? '' : 'unable'">
{{ sendCountDown === 0 ? '发送' : `${sendCountDown}s` }}
</div>
</div>
</template>
<script>
......@@ -17,7 +19,8 @@ export default {
data() {
return {
sendDate: 0,
content: ''
content: '',
sendCountDown: 0
};
},
computed: {
......@@ -49,6 +52,19 @@ export default {
_close() {
this.isShow = false;
},
_resetChat() {
clearInterval(this.sendCountDownTimer)
this.sendCountDown = 3
this.sendCountDownTimer = setInterval(() => {
if (this.sendCountDown === 0) {
clearInterval(this.sendCountDownTimer)
} else if (this.sendCountDown > 0) {
this.sendCountDown--
}
}, 1000);
this._close();
this.content = '';
},
async _sendChat() {
if (new Date().getTime() - this.sendDate <= 3000) {
this.$layer.msg('您的操作太频繁了');
......@@ -67,8 +83,7 @@ export default {
uuid: this.uuid
});
if (res.code === 200 && res.errorCode === 0) {
this.content = '';
this._close();
this._resetChat()
if (res.data.chatAuthModel === 1) {
this.$layer.msg('已提交审核,请耐心等待');
}
......@@ -113,11 +128,17 @@ export default {
margin: 0 0.1rem;
padding: 0 0.1rem;
height: 0.28rem;
width: 0.5rem;
text-align: center;
line-height: 0.28rem;
border-radius: 0.05rem;
background: #409eff;
color: #fff;
font-size: 0.12rem;
}
.unable {
color:#fff;
background-color: #999;
}
}
</style>
......@@ -50,7 +50,7 @@ import drawBox from '@/components/suspension/draw/index';
import voteBox from '@/components/suspension/vote/index';
import inviteBox from '@/components/suspension/invite/index';
import walletBox from '@/components/suspension/wallet/index';
import rewardBox from '@/components/suspension/reward/index';
import rewardBox from '@/components/suspension/reward/indexNew';
import toggleBtn from '@/components/suspension/toggle/index';
import praiseBox from '@/components/suspension/praise/index';
......
......@@ -48,6 +48,7 @@ const inviteBox = resolve => require(['@/components/modules-vertical/inviteBox']
export default {
name: 'vertical-top-box',
serverCacheKey: props => props.value,
components: {
followBox,
inviteBox
......@@ -215,9 +216,9 @@ export default {
margin-right: 0.06rem;
display: inline-block;
width: 0.48rem;
height: 0.32rem;
line-height: 0.32rem;
border-radius: 10px;
height: 0.28rem;
line-height: 0.28rem;
border-radius: 0.16rem;
background-color: rgba(0, 0, 0, 0.29);
text-align: center;
font-size: 0.11rem;
......
......@@ -7,7 +7,9 @@
:key="item.id"
@click="_changePlayer(item.playUrl, item.id)"
>
<div class="name">{{ item.name }}</div>
<div class="name">
<div class="name-text">{{ item.name }}</div>
</div>
<img class="img" v-if="item.thumbnail" :src="item.thumbnail" alt="" />
<div class="icon" v-else></div>
</div>
......@@ -74,11 +76,13 @@ export default {
margin-right: 0.06rem;
width: 0.8rem;
height: 0.45rem;
border-radius: 0.02rem;
border-radius: 0.05rem;
border: 0.01rem solid transparent;
overflow: hidden;
border: 1px solid #fff;
.img {
display: block;
border-radius: 0.05rem;
width: 100%;
height: 100%;
background-color: #333333;
......@@ -91,13 +95,21 @@ export default {
}
.name {
position: absolute;
top: 0.02rem;
left: 0.02rem;
font-size: 0.06rem;
width: 100%;
height: 100%;
font-size: 0.13rem;
color: #fff;
background: linear-gradient(180deg, rgba(0, 0, 0, .25) 0%, rgba(0, 0, 0, 0.01) 50%);
&-text {
transform: scale(0.95) translateX(-0.02rem);
position: absolute;
top: 0.02rem;
left: 0.02rem;
}
}
&.z-active {
border-color: var(--main-color);
background: var(--main-color);
}
}
}
......
<template>
<div class="wrapper">
<transition name="fade">
<div class="svgaPage" v-show="showSVAG">
<canvas id="svgaBox"></canvas>
</div>
</transition>
<div class="shop-hot-box" v-if="menuList.every(item => item.menuInfo !== 'shop' ) && caseInfo.status">
<shop-box :showHot="!!caseInfo.status" :isMarket="true"></shop-box>
</div>
<div class="swiper-container" ref="swiper">
<div class="swiper-wrapper">
<div class="swiper-slide" v-for="(item, index) in menuList" :key="index">
<template v-if="item.menuType == 'imagetext'">
<image-text :menuInfo="item.menuInfo" :menuId="item.id"></image-text>
</template>
<template v-else-if="item.menuType == 'playlists'">
<play-lists :listId="item.menuInfo"></play-lists>
</template>
<template v-else-if="item.menuType == 'share'">
<invite-box></invite-box>
</template>
<template v-else-if="item.menuType == 'shop'">
<shop-box :menuId="item.id" :showHot="!caseInfo.status" :showList="true"></shop-box>
</template>
<template v-else-if="item.menuType == 'coupon'">
<coupon-box></coupon-box>
</template>
<template v-else-if="item.menuType == 'report'">
<report-box :id="item.menuInfo"></report-box>
</template>
<template v-else-if="item.menuType == 'chat'">
<chat-box :isShowChat="isShowChat"></chat-box>
</template>
<template v-else-if="item.menuType == 'iframeLine'">
<iframe-line :menuInfo="item.menuInfo"></iframe-line>
</template>
<template v-else>
<empty404></empty404>
</template>
<!-- <div v-if="defer(index)"> -->
<template v-if="item.menuType == 'imagetext'">
<image-text :menuInfo="item.menuInfo" :menuId="item.id" v-if="defer(index)"></image-text>
</template>
<template v-else-if="item.menuType == 'playlists'">
<play-lists :listId="item.menuInfo" v-if="defer(index)"></play-lists>
</template>
<template v-else-if="item.menuType == 'share'">
<invite-box v-if="defer(index)"></invite-box>
</template>
<template v-else-if="item.menuType == 'shop'">
<shop-box :menuId="item.id" :showHot="!caseInfo.status" :showList="true" v-if="defer(index)"></shop-box>
</template>
<template v-else-if="item.menuType == 'coupon'">
<coupon-box v-if="defer(index)"></coupon-box>
</template>
<template v-else-if="item.menuType == 'report'">
<report-box :id="item.menuInfo" v-if="defer(index)"></report-box>
</template>
<template v-else-if="item.menuType == 'chat'">
<chat-box :isShowChat="isShowChat" v-if="defer(index)"></chat-box>
</template>
<template v-else-if="item.menuType == 'iframeLine'">
<iframe-line :menuInfo="item.menuInfo" v-if="defer(index)"></iframe-line>
</template>
<template v-else>
<empty404 v-if="defer(index)"></empty404>
</template>
<!-- </div> -->
</div>
</div>
</div>
......@@ -41,6 +48,7 @@
<script>
import { mapGetters } from 'vuex';
import { traffic } from '@/plugins/openTraffic';
import Defer from '@/plugins/Mixin/defer.js';
const imageText = resolve => require(['./menuClass/imageText'], resolve);
const playLists = resolve => require(['./menuClass/playLists/index'], resolve);
const inviteBox = resolve => require(['./menuClass/invite'], resolve);
......@@ -54,6 +62,7 @@ const shopHot = resolve => require(['./menuClass/shop/hot'], resolve);
export default {
name: 'menu-list',
serverCacheKey: props => props.value,
components: {
imageText,
playLists,
......@@ -68,10 +77,13 @@ export default {
props: {
value: {}
},
mixins: [Defer()],
data() {
return {
swiper: null,
active: this.value
active: this.value,
deferMenuList: [],
showSVAG: false
};
},
computed: {
......@@ -79,6 +91,7 @@ export default {
menuList: 'menuList',
drainage: 'drainage',
caseInfo: 'caseInfo',
giftAni: 'giftAni'
}),
isShowChat() {
let index = -1;
......@@ -93,10 +106,40 @@ export default {
},
mounted() {
this.$nextTick(() => {
const player = require('@gdyfe/svgaplayer-for-live')
this.SVGAPlayer = player.default({
target: '#svgaBox'
});
this.$Bus.$on('bus-playsvga', this.playsvga);
this._initSwiper();
// setTimeout(() => {
// this.playsvga([{
// value: '//static-pro.guangdianyun.tv/static/svga/666/666·.svga',
// userHeadImg:'https://static-pro.guangdianyun.tv/robot-head/57f8ea050533d96616be29c52729124c.jpeg',
// userNick: 'Michael',
// filterContent: {
// img: '//static-pro.guangdianyun.tv/static/svga/666/666@2x.png',
// num: 1,
// name: '666'
// }
// }])
// }, 1000)
});
},
methods: {
playsvga(url){
if (!this.SVGAPlayer) return
this.showSVAG = true
this.SVGAPlayer.enqueue(url)
this.SVGAPlayer.$on('end',(info) => {
this.$Bus.$emit('bus-setGiftBannerInfo', null);
this.showSVAG = false
})
this.SVGAPlayer.$on('start',(info) => {
this.$Bus.$emit('bus-setGiftBannerInfo', info);
this.showSVAG = true
})
},
_initSwiper() {
const self = this;
const option = {
......@@ -143,12 +186,27 @@ export default {
},
active(nVal) {
this.$emit('input', nVal);
},
giftAni(newVal) {
if (newVal) {
console.log('初始化svgaplayer')
const player = require('@gdyfe/svgaplayer-for-live')
this.SVGAPlayer = player.default({
target: '#svgaBox'
});
} else {
this.SVGAPlayer.destroyed()
this.SVGAPlayer = null
this.showSVAG = false
this.$Bus.$emit('bus-setGiftBannerInfo', null);
}
}
}
};
</script>
<style lang="less" scoped>
.shop-hot-box {
position: absolute;
top: 0;
......@@ -162,6 +220,27 @@ export default {
background-size: cover;
overflow: hidden;
position: relative;
.svgaPage {
position: absolute;
top: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.2);
z-index: 199;
padding-bottom: 0.5rem;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
.btn {
position: absolute;
}
#svgaBox {
width: 320px;
height: 320px;
}
}
.swiper-container {
height: 100%;
......
......@@ -23,6 +23,17 @@
<span class="close" @click="_closeReply">x</span>
</div>
</transition>
<transition name="move-left">
<div class="chat-gift" v-show="giftBannerInfo !== null"> <!-- v-show="giftBannerInfo !== null" -->
<div class="chat-gift__header" v-show="giftBannerInfo && giftBannerInfo.userHeadImg"><img :src="giftBannerInfo && giftBannerInfo.userHeadImg" alt=""></div>
<div class="chat-gift__senderName" v-show="giftBannerInfo && giftBannerInfo.userNick">{{ giftBannerInfo && giftBannerInfo.userNick || '未知' }}</div>
<strong>送出</strong>
<div class="chat-gift__giftPic" v-show="giftBannerInfo && gift.img"><img :src="giftBannerInfo && gift.img" alt=""></div>
<div class="chat-gift__num" v-show="giftBannerInfo && gift.num">
{{ giftBannerInfo && gift.name || '未知' }} x {{ giftBannerInfo && gift.num || '未知' }}
</div>
</div>
</transition >
</div>
<div class="wrapper" v-else>
<div class="list-box" ref="chatListBox">
......@@ -54,7 +65,8 @@ export default {
list: [],
redList: [],
unreadChatNum: 0,
replyChatId: ''
replyChatId: '',
giftBannerInfo: null
};
},
computed: {
......@@ -62,14 +74,21 @@ export default {
userInfo: 'userInfo',
channelInfo: 'channelInfo',
onlySeeRed: 'onlySeeRed'
})
}),
gift() {
return JSON.parse(this.giftBannerInfo.filterContent || '{}');
},
},
mounted() {
this.$Bus.$on('bus-addChat', this.addChat);
this.$Bus.$on('bus-delChat', this.delChat);
this.$Bus.$on('bus-setGiftBannerInfo', this.setGiftBannerInfo);
this.getChatList();
},
methods: {
setGiftBannerInfo(info) {
this.giftBannerInfo = info
},
getMore() {
const chatListBoxDom = this.$refs.chatListBox;
const chatListDom = this.$refs.chatList;
......@@ -290,6 +309,52 @@ export default {
color: #fff;
}
}
.chat-gift {
position: absolute;
bottom: 0.1rem;
left: 0.1rem;
z-index: 111111;
font-size: 0.13rem;
padding: 0 0.05rem;
height: 0.2rem;
display: flex;
align-items: center;
background: linear-gradient(90deg, #f37d48, rgba(0,0,0,0));
border-radius: 0.2rem;
color: #fff;
&__header {
width: 0.12rem;
height: 0.12rem;
border-radius: 50%;
overflow: hidden;
img {
width: 100%;
height: 100%;
}
}
&__senderName {
padding: 0 .03rem;
}
&__receiver {
padding: 0 .03rem;
}
&__giftPic {
width: 0.24rem;
height: 0.18rem;
overflow: hidden;
margin: .03rem 0;
img {
width: 100%;
height: 100%;
}
}
&__num {
}
strong {
font-size: 0.14rem;
}
}
.chat-reply {
position: absolute;
bottom: 0.1rem;
......
......@@ -4,7 +4,7 @@
<i class="icon"></i>
{{ info.userNick }}领取了
<em>{{ info.redFrom }}</em>
红包雨
{{ info.msgType === 17 ? '红包雨' : ''}}{{ info.msgType === 20 ? '倒计时红包' : '' }}
<em>{{ info.money }}</em>
</div>
......@@ -13,7 +13,7 @@
<script>
export default {
name: 'chat-red-business-tip',
name: 'chat-red-tip',
props: {
info: {}
}
......
......@@ -48,9 +48,9 @@
<!--礼物打赏消息-->
<chat-reward-gift :info="info"></chat-reward-gift>
</template>
<template v-else-if="info.msgType == 17">
<!--领取红包雨-->
<chat-red-rain-tip :info="info"></chat-red-rain-tip>
<template v-else-if="info.msgType == 17 || info.msgType == 20">
<!--领取红包雨 || 倒计时红包-->
<chat-red-tip :info="info"></chat-red-tip>
</template>
</div>
</template>
......@@ -68,7 +68,7 @@ import chatRedPasswordTip from './chatRedPasswordTip';
import chatRedAnswerTip from './chatRedAnswerTip';
import chatRedBusinessTip from './chatRedBusinessTip';
import chatRewardGift from './chatRewardGift';
import chatRedRainTip from './chatRedRainTip';
import chatRedTip from './chatRedTip';
export default {
name: 'chat-item',
props: {
......@@ -98,7 +98,7 @@ export default {
chatRedAnswerTip,
chatRedBusinessTip,
chatRewardGift,
chatRedRainTip
chatRedTip
}
};
</script>
......@@ -69,6 +69,10 @@ export default {
::v-deep img {
max-width: 100%;
}
.ql-editor {
background: rgba(255,255,255,.1);
// color: var(--chatBox-text-color);
}
}
.ql-container.ql-snow {
border: 0;
......
......@@ -3,16 +3,9 @@
<div class="invite__refresh">
<div class="invite__refresh-main" @click="_getInvitationList"></div>
</div>
<div class="invite__tab-box">
<div class="invite__tab-box__tab">
<!-- <div class="invite__tab-box__tab--item">
邀请榜
</div> -->
</div>
</div>
<div class="invite__list-box">
<div class="invite__list-box__list">
<div class="invite__list-box__list--topthree">
<div class="invite__list-box__list--topthree" v-if="threeList.length > 0">
<div v-for="(item, index) in threeList" :key="index" style="display: inline-block;" :class="index === 0 ? 'first-box' : index === 1 ? 'second-box': 'third-box'">
<div class="invite__list-box__list--topthree__item">
<div class="invite__list-box__list--topthree__item--head second" v-if="index === 0">
......@@ -120,8 +113,8 @@ export default {
}
.invite__refresh {
position: absolute;
right: 0.1rem;
top: 0.1rem;
right: 0.15rem;
top: 0.15rem;
padding: 0.05rem;
width: 0.3rem;
height: 0.3rem;
......@@ -158,8 +151,9 @@ export default {
}
.invite__list-box {
.invite__list-box__list {
background: rgba(255,255,255,0.1);
margin: 0 0.1rem;
background: rgba( 255, 255, 255, .1 );
margin: 0.1rem 0.1rem 0 0.1rem;
padding-bottom: 0.1rem;
border-radius: .1rem;
&--topthree {
margin-bottom: .2rem;
......@@ -262,6 +256,7 @@ export default {
overflow:hidden;
white-space:nowrap;
text-overflow:ellipsis;
text-align: center;
}
&--num {
flex: 0 0 auto;
......
......@@ -2,7 +2,7 @@
<transition name="move-right-left" mode="out-in">
<div class="shop-hot" v-if="info.id" :key="info.id">
<div class="img-box">
<img :src="`${info.real_img}?x-oss-process=style/commodity_cover`" alt="" />
<img :src="`${Array.isArray(info.real_img) ? info.real_img[0] : info.real_img}?x-oss-process=style/commodity_cover`" alt="" />
</div>
<div class="content">
<div class="name">{{ info.name }}</div>
......
......@@ -32,6 +32,7 @@ const followBox = resolve => require(['@/components/modules/followBox'], resolve
export default {
name: 'menu-tab',
serverCacheKey: props => props.value,
props: {
value: {}
},
......
......@@ -86,7 +86,7 @@ export default {
},
mpsBackgroundUrl() {
const bgUrl = this.channelInfo.mpsBackgroundUrl;
return bgUrl ? `${bgUrl}?x-oss-process=style/twzb_origin` : '';
return bgUrl ? `${bgUrl}${process.env.private ? '' : '?x-oss-process=style/twzb_origin'}` : '';
},
mpsOptions() {
let options = {};
......
......@@ -91,6 +91,8 @@ export default {
if (res.code === 200 && res.errorCode === 0) {
this.redInfo = res.data;
this._timerWait(res.data.wait);
} else {
res.errorMessage && this.$layer.msg(res.errorMessage);
}
},
async _openRed() {
......
<template>
<div class="luck-info" @click.stop>
<div class="header-box">
<div class="content">{{ luckInfo.content }}</div>
<div class="name">{{ luckInfo.userNick }}的红包</div>
</div>
<div class="num-sum-box">
{{ luckInfo.num }}
个红包共
{{ luckInfo.amount | floatNum }}
</div>
<div class="luck-list">
<ul class="list">
<li class="item" v-for="(item, index) in luckInfo.detail" :key="index">
<div class="head">
<img v-if="item.userHeadImg" :src="item.userHeadImg" />
<img v-else :src="channelInfo.defaultPhoneHeadAva" />
</div>
<div class="content">
<div class="name">{{ item.userNick }}</div>
<div class="time">{{ item.createTime }}</div>
</div>
<div class="money">
<div>{{ item.amount | floatNum }}</div>
<div class="best" v-if="bestUser == item.userId">手气最佳</div>
</div>
</li>
</ul>
</div>
</div>
</template>
<script>
export default {
name: 'red-default-luck',
props: {
luckInfo: {},
channelInfo: {}
},
data() {
return {};
},
computed: {
bestUser() {
const arr = [];
const num = this.luckInfo.num || 1;
const detail = this.luckInfo.detail || {};
for (const key in detail) {
if (detail.hasOwnProperty(key)) {
arr.push(detail[key]);
}
}
if (arr.length < num) {
return '';
} else {
arr.sort((a, b) => {
return b.amount - a.amount;
});
return arr[0].userId || '';
}
}
},
methods: {}
};
</script>
<style lang="less" scoped>
.luck-info {
position: relative;
margin: auto;
padding-top: 1.4rem;
width: 2.75rem;
height: 3.5rem;
background: url('./img/luck-bg.png') no-repeat 0 0;
background-size: 100% 100%;
.header-box {
position: absolute;
top: 0.1rem;
left: 0;
width: 100%;
text-align: center;
font-size: 0.12rem;
.content {
margin-bottom: 0.1rem;
color: #febe5c;
font-weight: 800;
font-size: 0.14rem;
}
.name {
color: #fff;
}
}
.num-sum-box {
padding: 0 0.1rem;
height: 0.2rem;
line-height: 0.2rem;
color: #febe5c;
font-size: 0.12rem;
}
.luck-list {
height: 1.9rem;
overflow: auto;
.list {
padding: 0 0.1rem;
.item {
display: flex;
align-items: center;
padding: 0.06rem 0;
.head {
flex: 0 0 auto;
width: 0.36rem;
height: 0.36rem;
border-radius: 0.04rem;
overflow: hidden;
img {
display: block;
width: 100%;
height: 100%;
}
}
.content {
flex: 1;
margin: 0 0.06rem;
.name {
margin-bottom: 0.1rem;
font-size: 0.12rem;
color: #000;
}
.time {
font-size: 0.1rem;
color: #999;
}
}
.money {
flex: 0 0 auto;
text-align: right;
font-size: 0.12rem;
color: #000;
.best {
margin-top: 0.1rem;
padding-left: 0.16rem;
color: #f4c600;
background: url('./img/icon-best.png') no-repeat 0 0;
background-size: 0.12rem 0.12rem;
}
}
}
}
}
}
</style>
<template>
<div class="default" v-show="redInfo.rid" @click="_closeRed">
<div class="default" v-if="redInfo.rid" @click="_closeRed">
<div class="box" @click.stop>
<i class="close" @click="_closeRed"></i>
<div class="red-info" v-if="!showLuck">
......@@ -75,6 +75,8 @@ export default {
this.isAjax = true;
if (res.code === 200 && res.errorCode === 0) {
this.redInfo = res.data;
} else {
res.errorMessage && this.$layer.msg(res.errorMessage);
}
},
async _openRed() {
......
......@@ -4,6 +4,7 @@
<answer-box :answerList="answerList" />
<business-box :businessList="businessList" />
<rainBox :rainInfo="rainInfo" />
<count-down-box :countDownInfo="countDownInfo"/>
</div>
<transition name="fade">
<default-box v-show="showRedInfo.type == 1 && showRedInfo.id && showRed"></default-box>
......@@ -16,7 +17,7 @@
</template>
<script>
import { getSpecialRedList, RainRedpacketInfo } from '@/plugins/API/apiRed';
import { getSpecialRedList, RainRedpacketInfo, countDownRedpacket } from '@/plugins/API/apiRed';
import { mapGetters } from 'vuex';
import defaultBox from './default/index';
import passwordBox from './password/index';
......@@ -24,6 +25,7 @@ import shareBox from './share/index';
import answerBox from './answer/index';
import businessBox from './business/index';
import rainBox from './rain/index';
import countDownBox from './countDown/index';
export default {
name: 'red-box',
......@@ -33,7 +35,8 @@ export default {
shareBox,
answerBox,
businessBox,
rainBox
rainBox,
countDownBox
},
data() {
return {
......@@ -41,6 +44,7 @@ export default {
answerList: [],
businessList: [],
rainInfo: {},
countDownInfo: {},
shareList: []
};
},
......@@ -61,26 +65,39 @@ export default {
this.$Bus.$on('bus-delShareList', this.del_shareList);
this.$Bus.$on('bus-addRain', this.add_rain);
this.$Bus.$on('bus-delRain', this.del_rain);
this.$Bus.$on('bus-getCountDown', this.get_countDown);
this._getSpecialRedList();
},
methods: {
async _getSpecialRedList() {
const res = await getSpecialRedList({
const reqInfo = {
uin: this.channelInfo.uin,
channelId: this.channelInfo.id
});
if (res.code === 200 && res.errorCode === 0) {
this.answerList = res.data.answerList;
this.businessList = res.data.businessList;
this.shareList = res.data.shareList;
}
const rain = await RainRedpacketInfo({
const redList = [
getSpecialRedList(reqInfo),
RainRedpacketInfo(reqInfo),
countDownRedpacket(reqInfo)
]
const [result1, result2, result3] = await Promise.all(redList)
if (result1.code === 200 && result1.errorCode === 0) {
this.answerList = result1.data.answerList;
this.businessList = result1.data.businessList;
this.shareList = result1.data.shareList;
}
if (result2.code === 200 && result2.errorCode === 0) {
this.rainInfo = result2.data;
}
if (result3.code === 200 && result3.errorCode === 0) {
this.countDownInfo = result3.data;
}
},
async get_countDown(obj) {
const res = await countDownRedpacket({
uin: this.channelInfo.uin,
channelId: this.channelInfo.id
})
if (res.code === 200 && res.errorCode === 0) {
this.rainInfo = rain.data;
}
this.countDownInfo = res.data;
},
_showRed(type, id) {
if (this.userInfo.id) {
......
<template>
<div class="password" v-show="redInfo.rid" @click="_closeRed">
<div class="password" v-if="redInfo.rid" @click="_closeRed">
<div class="box" @click.stop>
<i class="close" @click="_closeRed"></i>
<div class="red-info" v-if="!showLuck">
......@@ -82,6 +82,8 @@ export default {
this.isAjax = true;
if (res.code === 200 && res.errorCode === 0) {
this.redInfo = res.data;
} else {
res.errorMessage && this.$layer.msg(res.errorMessage);
}
},
async _openRed() {
......
......@@ -85,6 +85,10 @@ export default {
this.isAjax = true;
if (res.code === 200 && res.errorCode === 0) {
this.rainInfo.svSalt = res.data.svSalt || '';
return res
} else {
res.errorMessage && this.$layer.msg(res.errorMessage);
return false
}
},
async checkRainIsOpen() {
......@@ -100,7 +104,6 @@ export default {
}
},
async _openRed() {
await this._robRedpacket()
if (!this.isAjax) {
return '红包不存在';
}
......@@ -110,7 +113,6 @@ export default {
const channelId = this.channelInfo.id
const timestamp = ~~(new Date().getTime() / 1000)
const sv = this.$md5(`${this.channelInfo.uin}_${this.userInfo.id}_${this.$redSV.open}_${this.showRedInfo.id}_${this.rainInfo.svSalt || ''}`)
console.log()
const sign = sha1(channelId + '' + id + '' + sv + '' + timestamp + '' + uin + 'zf33f4248819bf94e73wx937fecfe9b8').toString()
const res = await openRedRainpacket({
id,
......@@ -120,6 +122,7 @@ export default {
timestamp,
sign
});
this.isAjax = true;
if (res.code === 200) {
if (res.errorCode === 0) {
this.isGet = true
......@@ -130,8 +133,12 @@ export default {
}
return '未抢到'
},
playGame() {
async playGame() {
if (this.userInfo.id) {
const rob = await this._robRedpacket()
if (!rob) {
return
}
const rainGame = require('./game')
this.showGame = !this.showGame
this.$nextTick(() => {
......
......@@ -34,7 +34,9 @@
</div>
<div class="emoji" @click.stop="_toggleEmoji"></div>
<div class="more" v-if="!content.trim()" @click.stop="_toggleMore"></div>
<div class="send" v-else @click.stop="_sendChat">发送</div>
<div class="send" v-else @click.stop="sendCountDown === 0 && _sendChat()" :class="sendCountDown === 0 ? '' : 'unable'">
{{ sendCountDown === 0 ? '发送' : `${sendCountDown}s` }}
</div>
</div>
<keep-alive>
<transition-group :name="showAni ? 'fade' : 'left'">
......@@ -75,7 +77,8 @@ export default {
},
count: 0,
showAni: true,
marketSrc: ''
marketSrc: '',
sendCountDown: 0
};
},
computed: {
......@@ -129,6 +132,15 @@ export default {
this.chatReplyObj = { id: '', name: '' };
},
_resetChat() {
clearInterval(this.sendCountDownTimer)
this.sendCountDown = 3
this.sendCountDownTimer = setInterval(() => {
if (this.sendCountDown === 0) {
clearInterval(this.sendCountDownTimer)
} else if (this.sendCountDown > 0) {
this.sendCountDown--
}
}, 1000);
this._remReplay();
this.content = '';
},
......@@ -376,10 +388,16 @@ export default {
height: 0.28rem;
line-height: 0.28rem;
border-radius: 0.05rem;
width: .5rem;
text-align: center;
background-color: var(--main-color);
color: var(--sebdBox-text-color);
font-size: 0.12rem;
}
.unable {
color:#fff;
background-color: #999;
}
}
}
</style>
......@@ -32,6 +32,12 @@
<div class="title">问卷报表</div>
</div>
</div>
<div class="item" >
<div class="box" @click="_setgift">
<div :class="`icon ${giftAni ? 'gift' : 'gift-close'}`"></div>
<div class="title">礼物特效</div>
</div>
</div>
</div>
</div>
</template>
......@@ -39,7 +45,7 @@
const Uploader = process.client ? require('@gdyfe/uploader') : {};
import { sendPhoto, sendPhotoByWeixin } from '@/plugins/API/apiAll';
import UserAgent from '@/plugins/UserAgent/index';
import { mapGetters } from 'vuex';
import { mapGetters, mapMutations } from 'vuex';
export default {
name: 'send-more',
data() {
......@@ -55,7 +61,8 @@ export default {
channelConfig: 'channelConfig',
userInfo: 'userInfo',
jumpUrls: 'jumpUrls',
uuid: 'uuid'
uuid: 'uuid',
giftAni: 'giftAni'
}),
isQuestionnaire() {
const info = this.channelConfig.questionnaire || {};
......@@ -66,6 +73,9 @@ export default {
},
},
methods: {
...mapMutations({
set_giftAni: 'set_giftAni'
}),
_sendRed() {
if (!this.userInfo.id) {
this.$layer.msg('请登录');
......@@ -169,6 +179,14 @@ export default {
this.$layer.msg('已提交审核,请耐心等待');
}
},
_setgift() {
this.set_giftAni()
if (this.giftAni){
this.$layer.msg('已开启礼物特效')
} else {
this.$layer.msg('已屏蔽礼物特效')
}
},
async _sendPhotoByWeixin(e) {
const res = await sendPhotoByWeixin({
uin: this.channelInfo.uin,
......@@ -195,7 +213,6 @@ export default {
<style lang="less" scoped>
.more {
padding: 0.05rem;
height: 0.9rem;
background: #fff;
.list {
display: flex;
......@@ -205,6 +222,7 @@ export default {
.item {
flex: 0 0 auto;
width: 25%;
padding: 0.1rem 0;
.box {
text-align: center;
.icon {
......@@ -231,6 +249,13 @@ export default {
&.questionnaire {
background-image: url(./img/icon-questionnaire.png);
}
&.gift {
background-image: url(./img/icon-gift.png);
}
&.gift-close {
background-image: url(./img/icon-giftclose.png);
background-size: auto 65%;
}
}
.title {
line-height: 0.2rem;
......
......@@ -60,7 +60,7 @@ import drawBox from '@/components/suspension/draw/index';
import voteBox from '@/components/suspension/vote/index';
import inviteBox from '@/components/suspension/invite/index';
import walletBox from '@/components/suspension/wallet/index';
import rewardBox from '@/components/suspension/reward/index';
import rewardBox from '@/components/suspension/reward/indexNew';
import toggleBtn from '@/components/suspension/toggle/index';
import praiseBox from '@/components/suspension/praise/index';
import seeRed from './seeRed/index';
......@@ -108,7 +108,7 @@ export default {
isReward() {
const rewardStatus = this.channelInfo.rewardStatus;
const rewardGiftStatus = this.channelInfo.rewardGiftStatus;
return rewardStatus === 1 || rewardGiftStatus === 1;
return rewardStatus === 1 || rewardGiftStatus === 1
},
isPraise() {
const info = this.channelConfig.praise;
......
<template>
<div>
<div class="case-box" v-if="caseInfo.goodsInfo.id" :style="{bottom: !(open || !isClose) ?'0.495rem' : '0.4rem'}">
<div class="case-box" v-if="caseInfo.goodsInfo.id" :style="{bottom: !(open || !isClose) ?'0.48rem' : '0.4rem'}">
<div class="goods" :style="{transform: (open && !isClose) ? 'unset' : 'translate3d(0, 120%, 0)', display: (open || !isClose) ? 'block' : 'none'}" @click="_enterMarket">
<div class="image-box">
<div class="swiper-container" ref="swiper">
<div class="swiper-wrapper">
<span class="swiper-slide" v-for="(item, index) in real_img" :key="index">
<div class="image" :style="{backgroundImage: `url(${ item })`}"/>
<span class="swiper-slide" v-for="(item, index) in real_img" :key="index" >
<div class="image" :style="{'background-color': '#fff', backgroundImage: `url(${ item })`}"/>
</span>
</div>
</div>
......@@ -24,7 +24,7 @@
<div class="name">{{ caseInfo.goodsInfo.name }}</div>
<div class="price">
<div class="small"></div>
<div style="line-height: 0.15rem;">{{ ((caseInfo.goodsInfo.price || caseInfo.goodsInfo.shop_price) + '').split('.')[0] }}</div>
<div>{{ ((caseInfo.goodsInfo.price || caseInfo.goodsInfo.shop_price) + '').split('.')[0] }}</div>
<div class="small">{{ ((caseInfo.goodsInfo.price || caseInfo.goodsInfo.shop_price) + '').split('.')[1] ? '.' + ((caseInfo.goodsInfo.price || caseInfo.goodsInfo.shop_price) + '').split('.')[1] : '' }}</div>
</div>
</div>
......@@ -85,8 +85,8 @@ export default {
_initSwiper() {
const self = this;
const option = {
loop: true,
autoplay: self.real_img.length > 1 ? { delay: 4000 } : false
effect: 'fade',
autoplay: self.real_img.length > 1 ? { delay: 2000 } : false
};
this.swiper = new this.$swiper(this.$refs.swiper, option);
},
......@@ -128,6 +128,29 @@ export default {
</script>
<style lang="less" scoped>
.swiper-wrapper {
transform: translate3d(0, 0, 0) !important;
}
.swiper-slide {
transition: all 1.5s !important;
position: absolute ;
opacity: 0 !important;
&:first-child {
position: relative;
}
}
.swiper-slide-active {
transform: scale(1) !important;
opacity: 1 !important;
}
.swiper-slide-prev {
transform: scale(1.1) !important;
}
.swiper-slide-next {
transform: scale(1.1) !important;
}
.shop-link-box,
.shop-command-box {
position: fixed;
......@@ -158,6 +181,9 @@ export default {
.underway {
color: #fff;
font-size: .12rem;
overflow:hidden;
white-space:nowrap;
text-overflow:ellipsis;
}
.icon {
width: .15rem;
......@@ -178,16 +204,16 @@ export default {
border: 1px solid rgba(0, 0, 0, 0.1);
.image-box {
position: relative;
.image {
border-radius: 5px;
overflow: hidden;
border: 1px solid #eef3ff;
position: relative;
height: 0;
padding-top: 100%;
background-position: center;
background-size: cover;
}
.image {
border-radius: 5px;
overflow: hidden;
border: 1px solid #eef3ff;
position: relative;
height: 0;
padding-top: 100%;
background-position: center;
background-size: cover;
}
.state {
position: absolute;
top: 0;
......@@ -267,7 +293,8 @@ export default {
}
.small {
transform: scale(0.8);
margin-right: -.02rem;
transform-origin: 0 100% 0;
padding-left: 0.02rem;
}
}
}
......
......@@ -12,7 +12,11 @@ export default {
name: 'suspension-draw',
props: {
info: {},
defaultIcon: require('./img/icon-draw.png')
},
data() {
return {
defaultIcon: require('./img/icon-draw.png')
}
},
computed: {
...mapGetters({
......
<template>
<div class="office" @click="_toogle">
<div class="btn">
<div class="icon" :style="{background: channelInfo && channelInfo.screenDirection === 'vertical' ? `url(${defaultIcon}) no-repeat center center` : ''}"></div>
<div class="icon" :style="{background: channelInfo && channelInfo.screenDirection === 'vertical' ? `url(${defaultIcon}) no-repeat center center` : ''}"></div>
</div>
<div class="title">文档</div>
<div class="office-box" v-transfer-dom v-show="isShow">
......@@ -27,7 +27,8 @@ export default {
},
computed: {
...mapGetters({
channelConfig: 'channelConfig'
channelConfig: 'channelConfig',
channelInfo: 'channelInfo'
})
},
methods: {
......
......@@ -6,11 +6,11 @@
<div class="title">打赏</div>
<transition name="fade">
<div class="reward-box" v-transfer-dom v-show="isShow" @click.stop="close">
<div style="background: #fff; width:100%;height: auto;border-radius: 15px 15px 0 0;overflow: hidden;">
<div style="background: linear-gradient(to bottom left, rgba(243, 207, 106, 0.2) 0%, #fff 100%); width:100%;height: auto">
<div style="width:100%;height: auto;border-radius: 15px 15px 0 0;overflow: hidden;">
<div style="background: rgba(255, 255, 255, 0.9); width:100%;height: auto"> <!-- linear-gradient(to bottom left, rgba(243, 207, 106, 0.2) 0%, #fff 100%) -->
<div class="tab-box" v-show="showTab">
<div :class="{ 'z-active': tabIndex == 0 }" @click.stop="_tabIndex(0)">
礼物打赏
礼物
</div>
<div :class="{ 'z-active': tabIndex == 1 }" @click.stop="_tabIndex(1)">
现金打赏
......
<template>
<div class="reward" @click="_toggleReward(true)">
<div class="btn">
<div class="icon" :style="{background: channelInfo && channelInfo.screenDirection === 'vertical' ? `url(${defaultIcon}) no-repeat center center` : ''}"></div>
</div>
<div class="title">打赏</div>
<reward v-model="isShow"></reward>
</div>
</template>
<script>
import { mapGetters } from 'vuex';
const reward = resolve => require(['./rewardNew'], resolve);
export default {
name: 'suspension-reward',
components: {
reward
},
data() {
return {
isShow: false,
defaultIcon: require('./img/icon-reward.png')
};
},
computed: {
...mapGetters({
channelInfo: 'channelInfo',
userInfo: 'userInfo'
}),
},
mounted() {
this.$Bus.$on('bus-showReward', this._toggleReward);
},
beforeDestroy() {
this.$Bus.$off('bus-showReward', this._toggleReward);
},
methods: {
_toggleReward(bol) {
if (!this.userInfo.id && bol) {
this.$layer.msg('请先登录');
this.$Bus.$emit('bus-showLogin', true);
return false;
}
this.isShow = bol
},
}
};
</script>
<style lang="less" scoped>
.reward {
width: 0.8rem;
height: 0.8rem;
.btn {
position: relative;
padding: 0 0.1rem;
width: 0.8rem;
height: 0.6rem;
background: var(--suspension-reward-bg) no-repeat center center;
background-size: contain;
.icon {
width: 100%;
height: 100%;
background: var(--suspension-reward-icon) no-repeat center center;
background-size: auto 50%;
}
}
.title {
margin-top: 0.04rem;
line-height: 0.18rem;
text-align: center;
white-space: nowrap;
font-size: 0.16rem;
}
}
</style>
<template>
<transition name="fade">
<div class="reward-box" v-transfer-dom v-show="value" @click.stop="close">
<div style="width:100%;height: auto;border-radius: 15px 15px 0 0;overflow: hidden;">
<div style="background: rgba(255, 255, 255, 0.9); width:100%;height: auto"> <!-- linear-gradient(to bottom left, rgba(243, 207, 106, 0.2) 0%, #fff 100%) -->
<div class="tab-box" v-show="showTab">
<div :class="{ 'z-active': tabIndex == 0 }" @click.stop="_tabIndex(0)">
礼物
</div>
<div :class="{ 'z-active': tabIndex == 1 }" @click.stop="_tabIndex(1)">
现金打赏
</div>
</div>
<div class="type-box">
<transition-group :name="showAni ? 'fadeMaxHeight' : 'hideAni'">
<rewardGift v-show="value && showRewardGift" :key="1"/>
<rewardCash v-show="value && showReward" :key="2"/>
</transition-group>
</div>
</div>
</div>
</div>
</transition>
</template>
<script>
import { mapGetters } from 'vuex';
const rewardCash = resolve => require(['./rewardCash'], resolve);
const rewardGift = resolve => require(['./rewardGift'], resolve);
export default {
name: 'suspension-reward',
components: {
rewardCash,
rewardGift
},
data() {
return {
showAni: true,
tabIndex: 0,
defaultIcon: require('./img/icon-reward.png')
};
},
props: {
value: {
type: Boolean,
default: false,
},
},
model: {
prop: 'value',
},
computed: {
...mapGetters({
channelInfo: 'channelInfo',
userInfo: 'userInfo'
}),
switchShow() {
return this.value ? (this.showRewardGift * 2 + this.showReward) : 0
},
showTab() {
return this.channelInfo.rewardGiftStatus === 1 && this.channelInfo.rewardStatus === 1;
},
showRewardGift() {
if (this.showTab && this.channelInfo.rewardGiftStatus === 1 && this.tabIndex === 0) {
return true;
} else if (!this.showTab && this.channelInfo.rewardGiftStatus === 1) {
return true;
} else {
return false;
}
},
showReward() {
if (this.showTab && this.channelInfo.rewardStatus === 1 && this.tabIndex === 1) {
return true;
} else if (!this.showTab && this.channelInfo.rewardStatus === 1) {
return true;
} else {
return false;
}
}
},
methods: {
close() {
this.$emit('input', false)
},
_tabIndex(index) {
this.tabIndex = index;
},
},
watch: {
switchShow(newVal, oldVal) {
this.showAni = (newVal === 0 || oldVal === 0)
}
}
};
</script>
<style lang="less" scoped>
.hideAni-enter,.hideAni-leave-to{
position: fixed;
z-index: -1;
bottom: 0;
}
.fadeMaxHeight-enter,.fadeMaxHeight-leave-to{
max-height: 0;
}
.fadeMaxHeight-enter-to,.fadeMaxHeight-leave{
max-height: 60vh;
}
.fadeMaxHeight-enter-active,.fadeMaxHeight-leave-active{
transition: max-height .6s cubic-bezier(0,0,0.58,1);
}
.reward-box {
position: absolute;
bottom: 0;
left: 0;
z-index: 1000;
width: 100%;
height: 100%;
display: flex;
flex-direction: column-reverse;
background-color: rgba(0, 0, 0, 0.4);
.type-box {
}
.tab-box {
padding: 0.12rem 0.1rem;
display: flex;
justify-content: space-around;
div {
display: inline-block;
margin-right: 0.1rem;
vertical-align: top;
font-size: 0.12rem;
&.z-active {
color: var(--main-color);
font-weight: 800;
position: relative;
&:after {
content: '';
position: absolute;
left: calc(50% - 0.15rem);
margin: 0.05rem auto 0;
display: block;
height: 0.02rem;
width: 0.3rem;
background-color: var(--main-color);
}
}
}
}
}
</style>
<template>
<div class="reward-cash" @click.stop>
<ul class="reward-cash__list">
<li
:class="`item ${activeIndex === index ? 'active' : ''}`"
v-for="(item, index) in channelInfo.rewardConfig"
:key="index"
@click="activeIndex === index ? (activeIndex = null) : (activeIndex = index)"
>
<div class="item__icon"></div>
<div class="item__price">
{{ item }}
<span class="item__price--yuan"></span>
</div>
</li>
</ul>
<div :class="`reward-cash__btn ${activeIndex !== null ? 'btn-active' : ''}`" @click.stop="_cashReward(channelInfo.rewardConfig[activeIndex])">确定</div>
</div>
</template>
<script>
import { reward } from '@/plugins/API/apiReward';
import { mapGetters } from 'vuex';
export default {
name: 'suspension-reward-cash',
data() {
return {
activeIndex: null
};
},
computed: {
...mapGetters({
channelInfo: 'channelInfo'
})
},
methods: {
async _cashReward(cash) {
const res = await reward({
uin: this.channelInfo.uin,
channelId: this.channelInfo.id,
money: cash,
backUrl: window.location.href,
payType: 1
});
if (res.code === 200 && res.errorCode === 0) {
const { tradeType, prepayInfo } = res.data;
const { uin } = this.channelInfo;
const DEF_SITE = process.client
? process.env.DEF_SITE + (window.location.protocol.split(':')[0] === 'https' ? process.env.HTTPS_PORT : process.env.HTTP_PORT)
: `http:${process.env.DEF_SITE + process.env.HTTP_PORT}`;
if (res.data.url) {
window.location.href = res.data.url;
} else if (tradeType === 'MWEB') {
const wxh5pay = `https:${process.env.DEF_SITE + process.env.HTTPS_PORT}/pay/wxh5pay?uin=${uin}`;
const backUrl = encodeURIComponent(window.location.href);
const transferUrl = encodeURIComponent(`${wxh5pay}&url=${backUrl}`);
const payUrl = encodeURIComponent(`${prepayInfo.mweb_url}&redirect_url=${transferUrl}`);
const url = `${wxh5pay}&url=${payUrl}`;
window.location.href = url;
} else if (tradeType === 'JSAPI') {
const data = encodeURIComponent(JSON.stringify(res.data));
const url = `${DEF_SITE}/pay/wxpay?uin=${uin}&payconfig=${data}`;
window.location.href = url;
} else {
this.$layer.msg('网络错误,请稍后重试!');
}
}
}
}
};
</script>
<style lang="less" scoped>
.reward-cash {
&__list {
padding: 0.25rem 0.1rem;
text-align: center;
display: flex;
justify-content: center;
flex-wrap: wrap;
.active {
border: 1px solid #FE5D5D !important;
}
.item {
margin: 0 0.07rem 0.15rem 0.07rem;
padding: 0.1rem;
width: 1rem;
line-height: 0.3rem;
vertical-align: top;
background: rgba(90,93,135,.3);
color: #FE5D5D;
border-radius: 0.1rem;
// font-style: italic;
font-size: 0.13rem;
font-weight: 400;
display: flex;
align-items: center;
justify-content: center;
border: 1px solid transparent;
div {
display: inline-block;
}
&__icon {
flex: 1;
width: .38rem;
height: .4rem;
background: url('./img/icon-redPacket.png') no-repeat center 55%;
background-size: auto 100%;
margin-left: .03rem;
}
&__price {
flex: 1;
white-space: nowrap;
&--yuan {
margin-left: .01rem;
}
}
}
}
&__btn {
width: calc(100% - .9rem);
margin-left: .45rem;
height: .4rem;
color: #d4d4d4;
border-radius: .45rem;;
text-align: center;
line-height: .4rem;
transition: all .3s;
margin-bottom: 0.25rem;
background: linear-gradient(180deg, #FF6868 0%, #F43D3D 100%);
opacity: 0.5;
}
.btn-active {
opacity: 1;
color: #fff;
}
}
</style>
<template>
<transition name="fadeMaxHeight">
<div class="reward-box" v-transfer-dom v-show="value" @click.stop="close">
<div style="width:100%;height: auto;border-radius: 15px 15px 0 0;overflow: hidden;">
<div style="background: rgba(0, 0, 0, 0.9); width:100%;height: auto" @click.stop>
<div class="top-box">
<div class="tab-box" v-show="swiper">
<div :class="{ 'z-active': list[tabIndex].nameKey === 'gift' }" @click.stop="_tabSwitch('0')"
v-if="list.some(item => item.nameKey === 'gift')">
礼物
</div>
<div :class="{ 'z-active': list[tabIndex].nameKey === 'cash' }" @click.stop="_tabSwitch('1')"
v-if="list.some(item => item.nameKey === 'cash')">
现金打赏
</div>
</div>
<div class="sendName-box">
<div class="text">送给</div>
<div class="header"><img :src="list.some(item => item.nameKey === 'cash') ? channelInfo.rewardPhoto : channelInfo.chatAdminAvaUrl"/></div>
<div class="name">{{ list.some(item => item.nameKey === 'cash') ? channelInfo.rewardName : (channelInfo.chatAdminName || '管理员') }}</div>
<!-- <div class="icon"></div> -->
</div>
</div>
<div class="swiper-container" ref="swiper">
<div class="swiper-wrapper">
<div class="swiper-slide" v-for="item in list" :key="item.nameKey">
<template v-if="item.nameKey === 'gift'" @click.stop>
<reward-gift :show="value" @close="close"/>
</template>
<template v-if="item.nameKey === 'cash'" @click.stop>
<reward-cash @close="close"/>
</template>
</div>
</div>
</div>
</div>
</div>
</div>
</transition>
</template>
<script>
import { mapGetters } from 'vuex';
const rewardCash = resolve => require(['./rewardCashNew'], resolve);
const rewardGift = resolve => require(['./rewardGiftNew'], resolve);
export default {
name: 'suspension-reward',
components: {
rewardCash,
rewardGift
},
data() {
return {
showAni: true,
tabIndex: 0,
defaultIcon: require('./img/icon-reward.png'),
swiper: null
};
},
props: {
value: {
type: Boolean,
default: false,
},
},
model: {
prop: 'value',
},
computed: {
...mapGetters({
channelInfo: 'channelInfo',
userInfo: 'userInfo'
}),
list() {
const list = []
if (this.channelInfo.rewardGiftStatus === 1){
list.push({name:'礼物', nameKey: 'gift'})
}
if (this.channelInfo.rewardStatus === 1) {
list.push({name:'现金打赏', nameKey: 'cash'})
}
return list
}
},
methods: {
close() {
this.$emit('input', false)
},
_tabSwitch(index) {
this.swiper.slideTo(index + '' || this.tabIndex + '');
},
_initSwiper() {
const self = this;
const option = {
touchRatio: 0.5,
on: {
slideChange() {
self.tabIndex = this.activeIndex;
}
}
};
this.swiper = new this.$swiper(this.$refs.swiper, option);
},
},
watch: {
value(newVal) {
if (newVal){
this.$nextTick(() => {
this._initSwiper();
this.$nextTick(() => {
this.swiper.slideTo(this.tabIndex)
})
});
}
}
}
};
</script>
<style lang="less" scoped>
.hideAni-enter,.hideAni-leave-to{
position: fixed;
z-index: -1;
bottom: 0;
}
.fadeMaxHeight-enter,.fadeMaxHeight-leave-to{
max-height: 0;
}
.fadeMaxHeight-enter-to,.fadeMaxHeight-leave{
max-height: 70vh;
}
.fadeMaxHeight-enter-active,.fadeMaxHeight-leave-active{
transition: max-height .5s cubic-bezier(0,0,0.38,1);
}
.reward-box {
position: absolute;
bottom: 0;
left: 0;
z-index: 1000;
width: 100%;
height: 100%;
display: flex;
color: #fff;
flex-direction: column-reverse;
.top-box {
padding: 0 .1rem;
display: flex;
height: .54rem;
justify-content: space-between;
align-items: center;
.tab-box {
width: 50%;
display: flex;
align-items: center;
div {
display: inline-block;
margin: 0.1rem;
vertical-align: top;
font-size: 0.14rem;
color: #7D7C8D;
&.z-active {
font-size: 0.15rem;
color: #FFF;
font-weight: 800;
position: relative;
&:after {
content: '';
position: absolute;
left: calc(50% - 0.05rem);
margin: 0.05rem auto 0;
display: block;
height: 0.03rem;
width: 0.1rem;
background-color: #3185F7;
border-radius: 1px;
}
}
}
}
.sendName-box {
background: rgba(90,93,135,.3);
border-radius: .32rem;
height: .32rem;
display: flex;
align-items: center;
padding: 0 .1rem;
font-size: .13rem;
div {
display: inline-block;
padding: 0 .01rem;
}
.text {
white-space: nowrap;
}
.icon {
width: .12rem;
height: .12rem;
background: url('./img/icon-right.png') no-repeat center 55%;
background-size: auto 80%;
margin-left: .03rem;
opacity: .5;
}
.header {
width: .19rem;
height: .19rem;
border-radius: 50%;
background: #fff;
overflow: hidden;
margin: 0 .07rem;
img {
width: 100%;
height: 100%;
}
}
.name {
font-size: .12rem;
color: #FFEC79;
padding-top: 2px;
white-space: nowrap;
overflow: hidden;
text-overflow:ellipsis;
}
}
}
}
</style>
......@@ -19,7 +19,6 @@
</template>
<script>
import { getWatchLoginInfo } from '@/plugins/API/apiAll';
import { watchTime } from '@/plugins/API/apiWS';
import { mapGetters, mapMutations, mapActions } from 'vuex';
import encrypt from '@/components/encrypt/index';
import white from '@/components/white/index';
......@@ -27,7 +26,7 @@ import welcome from '@/components/welcome/index';
import viewPc from './pc';
import viewMobile from './mobile';
import viewVertical from './vertical';
import websocketHeartbeat from '@/plugins/websocketHeartbeat';
export default {
name: 'view-box',
components: {
......@@ -76,24 +75,7 @@ export default {
await this.get_userInfo({ refererId: this.$route.query.refererId });
this.set_nowDate();
if (!process.env.private) {
const websocketHeartbeat = require('@/plugins/timer').default;
const userInfo = {
"userId": this.userInfo.id || 0,
// "token": this.token,
"id": this.channelInfo.id,
"type":"live",
"uin": this.channelInfo.uin,
"liveNowStatus": this.channelInfo.liveNowStatus
}
this.timer = websocketHeartbeat({
url: watchTime,
pingTimeout: 5000,
pongTimeout: 5000,
manualStart: false,
repeatLimit: 10,
userInfo,
webworker: false
}).useIt('uuid').useIt('ua')
this.timer = websocketHeartbeat.call(this)
this.set_uuid(this.timer.uuid)
// bus注册ws暂停和开始事件
this.$Bus.$on('ws-start', () => {
......
<template>
<div class="page-box view-mobile" @touchmove.stop.prevent @click="_closeAll">
<div class="live">
<div class="top-list-box m-carousel-dvertising">
<div class="top-list-box m-carousel-dvertising" v-if="defer(1)">
<advert-top v-if="isAdTop"></advert-top>
</div>
<div class="player-box">
<div class="player-box" v-if="defer(2)">
<player-box></player-box>
</div>
<div class="camera-box" @touchmove.stop>
<div class="camera-box" @touchmove.stop v-if="defer(3)">
<camera-box v-if="isCamera"></camera-box>
</div>
<div class="tab-list-box" @touchmove.stop>
<div class="tab-list-box" @touchmove.stop v-if="defer(4)">
<menu-tab v-model="menuActive"></menu-tab>
</div>
<div class="middle-list-box">
<div class="middle-list-box" v-if="defer(5)">
<extend-commodity v-if="spread"></extend-commodity>
<advert-middle v-else-if="isAdMiddle"></advert-middle>
</div>
<div class="text-box">
<div class="text-box" v-if="defer(6)">
<advert-text v-if="isAdText"></advert-text>
</div>
<div class="content-box" @touchmove.stop>
<div class="content-box" @touchmove.stop v-if="defer(7)">
<div class="menu-list-box" id="menu-list-box">
<menu-list v-model="menuActive"></menu-list>
</div>
......@@ -51,6 +51,7 @@ import playerBox from '@/components/modules/playerBox';
import menuTab from '@/components/modules/menuBox/tab';
import menuList from '@/components/modules/menuBox/list';
import Defer from '@/plugins/Mixin/defer.js';
export default {
name: 'mobile',
head() {
......@@ -72,6 +73,7 @@ export default {
extendAd,
extendCommodity
},
mixins: [Defer()],
data() {
return {
menuActive: 0,
......@@ -114,11 +116,12 @@ export default {
_closeAll() {
this.$Bus.$emit('bus-remEnclosure');
this.$Bus.$emit('bus-showReward', false);
}
},
}
};
</script>
<style lang="less" scoped>
.page-box {
height: 100%;
.live {
......
......@@ -20,7 +20,7 @@ function getEnv() {
return environment;
}
export const sentryOptions = {
dsn: `https://2fdea25b53284316bae9eadd5206164c@sentry.guangdianyun.tv/20`,
dsn: `https://61a2691f71014d5fa79d4f9aba78a109@sentry.guangdianyun.tv/8`,
version: packageEnv.version,
env: getEnv(),
name: packageEnv.name
......
module.exports = {
DEF_DOMAIM: '//cgateway.aodiansoft.com',
DEF_DOMAIM: '//cgateway.huaguangyun.cn',
DEF_OSS: '//g-resource.obs.cn-north-4.myhuaweicloud.com',
DEF_AODIANYUN: 'http://cdn.aodiansoft.com',
DEF_S_AODIANYUN: 'https://cdn.aodiansoft.com',
DEF_AODIANYUN: 'http://cdn.huaguangyun.cn',
DEF_S_AODIANYUN: 'https://cdn.huaguangyun.cn',
HTTPS_PORT: '',
HTTP_PORT: '',
X_CA_STAGE: '',
......@@ -18,5 +18,5 @@ module.exports = {
bucket: 'g-gallery',
multiFiles: true
},
DEF_SITE: '//web.aodiansoft.com',
DEF_SITE: '//web.huaguangyun.cn',
};
\ No newline at end of file
{
"name": "ssr-program-live",
"version": "1.2.0",
"version": "1.5.0",
"description": "My superb Nuxt.js project",
"author": "1006903445@qq.com",
"private": true,
......@@ -12,7 +12,7 @@
"serve:huawei": "cross-env mode=huawei.private nuxt",
"serve:pre": "cross-env mode=pre nuxt",
"serve:test": "cross-env mode=test nuxt",
"build:prod": "nuxt build",
"build:prod": "nuxt build",
"build:cm": "cross-env mode=cm.private nuxt build",
"build:vvku": "cross-env mode=vvku.private nuxt build",
"build:cbn": "cross-env mode=cbn.private nuxt build",
......@@ -40,6 +40,7 @@
},
"dependencies": {
"@gdyfe/ink-marks": "^1.1.4",
"@gdyfe/svgaplayer-for-live": "^1.0.3",
"@gdyfe/uploader": "^2.3.6",
"@nuxtjs/axios": "^5.3.6",
"@nuxtjs/component-cache": "^1.1.5",
......@@ -58,12 +59,15 @@
"hls.js": "^0.14.16",
"js-cookie": "^2.2.0",
"js-md5": "^0.7.3",
"lru-cache": "^6.0.0",
"nuxt": "^2.10.2",
"qrcode": "^1.4.4",
"quicklink": "^2.1.0",
"swiper": "4.5.1",
"vue-lazyload": "^1.3.3",
"vue-photoswipe.js": "^2.0.16",
"vue-quill-editor": "^3.0.6",
"vue-scroll-picker": "^0.7.1",
"xss": "^1.0.8"
},
"devDependencies": {
......
......@@ -140,9 +140,10 @@ const testApi = {
// getAddressForGet: '' // 防盗链接口
};
const privateApi = {
getMenuList: '/live/menu/list', // 获取菜单配置 // /go/live/menu/list // /node/live/menuList
getImagetext: '/live/menu/imagetext', // 获取富文本
getChannelInfo: '/go/live/getinfo', // 获取直播间配置
getChannelConfig: '/node/index/channelConfig', // 获取直播间配置
getMenuList: '/node/live/menuList', // 获取菜单配置
getAdvertList: '/node/live/advertList', // 获取广告配置
getChatCount: '/php/program/chat/chatCount', // 获取聊天数
getWatchNum: '/node/live/watchNum', // 获取观看人数
......
......@@ -11,12 +11,17 @@ let api = {
openAnswerRedpacket: '/Program/Redpacket/openAnswerRedpacket', // 打开竞答红包
openBusinessRedpacket: '/Program/Redpacket/openBusinessRedpacket', // 打开商家红包
openRedRainpacket: '/Program/Redpacket/CheckRedpacket', // 打开红包雨
checkRainIsOpen: '/Program/Redpacket/checkRainIsOpen' // 是否抢过红包雨
checkRainIsOpen: '/Program/Redpacket/checkRainIsOpen', // 是否抢过红包雨
countDownRedpacket: '/Program/Redpacket/CountDownRedpacket', // 查询倒计时红包
countDownPacketDetail: '/Program/redenvelope/redpacketDetail', // 获取倒计时红包领取详情
};
const prodApi = {
openRedRainpacket: 'https://1812501212048408.cn-hangzhou.fc.aliyuncs.com/2016-08-15/proxy/gdyRedPacket/gdyRed/program/redpacket/checkRedpacket', // 打开红包雨
checkRainIsOpen: 'https://1812501212048408.cn-hangzhou.fc.aliyuncs.com/2016-08-15/proxy/gdyRedPacket/gdyRed/program/redpacket/checkRainIsOpen', // 是否抢过红包雨
RainRedpacketInfo: 'https://1812501212048408.cn-hangzhou.fc.aliyuncs.com/2016-08-15/proxy/gdyRedPacket/gdyRed/program/redpacket/rainRedpacketInfo', // 获取 红包雨信息
countDownRedpacket: 'https://1812501212048408.cn-hangzhou.fc.aliyuncs.com/2016-08-15/proxy/gdyRedPacket.online/gdyRed/program/redpacket/countDownRedpacket', // 查询倒计时红包
countDownPacketDetail: 'https://1812501212048408.cn-hangzhou.fc.aliyuncs.com/2016-08-15/proxy/gdyRedPacket.online/gdyRed/program/redenvelope/redpacketDetail', // 获取倒计时红包领取详情
openRedRainpacket: 'https://1812501212048408.cn-hangzhou.fc.aliyuncs.com/2016-08-15/proxy/gdyRedPacket.online/gdyRed/program/redpacket/checkRedpacket', // 打开红包雨
checkRainIsOpen: 'https://1812501212048408.cn-hangzhou.fc.aliyuncs.com/2016-08-15/proxy/gdyRedPacket.online/gdyRed/program/redpacket/checkRainIsOpen', // 是否抢过红包雨
RainRedpacketInfo: 'https://1812501212048408.cn-hangzhou.fc.aliyuncs.com/2016-08-15/proxy/gdyRedPacket.online/gdyRed/program/redpacket/rainRedpacketInfo', // 获取 红包雨信息
getSpecialRedList:
'https://1812501212048408.cn-hangzhou.fc.aliyuncs.com/2016-08-15/proxy/gdyRedPacket.online/gdyRed/program/redenvelope/getSpecialRedList', // 获取 分享,商家,竞答红包
robRedpacket:
......@@ -35,6 +40,8 @@ const prodApi = {
'https://1812501212048408.cn-hangzhou.fc.aliyuncs.com/2016-08-15/proxy/gdyRedPacket.online/gdyRed/program/redenvelope/openBusinessRedpacket' // 打开商家红包
};
const preApi = {
countDownRedpacket: 'https://1812501212048408.cn-hangzhou.fc.aliyuncs.com/2016-08-15/proxy/gdyRedPacket/gdyRed/program/redpacket/countDownRedpacket', // 查询倒计时红包
countDownPacketDetail: 'https://1812501212048408.cn-hangzhou.fc.aliyuncs.com/2016-08-15/proxy/gdyRedPacket/gdyRed/program/redenvelope/redpacketDetail', // 获取倒计时红包领取详情
openRedRainpacket: 'https://1812501212048408.cn-hangzhou.fc.aliyuncs.com/2016-08-15/proxy/gdyRedPacket/gdyRed/program/redpacket/checkRedpacket', // 打开红包雨
checkRainIsOpen: 'https://1812501212048408.cn-hangzhou.fc.aliyuncs.com/2016-08-15/proxy/gdyRedPacket/gdyRed/program/redpacket/checkRainIsOpen', // 是否抢过红包雨
RainRedpacketInfo: 'https://1812501212048408.cn-hangzhou.fc.aliyuncs.com/2016-08-15/proxy/gdyRedPacket/gdyRed/program/redpacket/rainRedpacketInfo', // 获取 红包雨信息
......@@ -119,6 +126,13 @@ export const RainRedpacketInfo = data => {
export const checkRainIsOpen = data => {
return request.post(api['checkRainIsOpen'], data);
};
export const countDownRedpacket = data => {
return request.post(api['countDownRedpacket'], data);
};
export const countDownPacketDetail = data => {
return request.get(api['countDownPacketDetail'], data);
};
export default {
getSpecialRedList,
robRedpacket,
......@@ -132,4 +146,6 @@ export default {
openRedRainpacket,
RainRedpacketInfo,
checkRainIsOpen,
countDownRedpacket,
countDownPacketDetail
};
......@@ -9,9 +9,17 @@
import qs from 'qs';
import axios from 'axios';
import Layer from '@/plugins/Layer/index';
import md5 from 'js-md5';
import LRU from 'lru-cache'
const Cookie = process.client ? require('js-cookie') : {};
const Sentry = process.client ? require('@sentry/browser') : require('@sentry/node');
// 给api加200ms缓存
const CACHED = new LRU({
max: 1000,
maxAge: 200
})
const DEF_DOMAIM = process.client
? process.env.DEF_DOMAIM + (window.location.protocol.split(':')[0] === 'https' ? process.env.HTTPS_PORT : process.env.HTTP_PORT)
: `http:${process.env.DEF_DOMAIM + process.env.HTTP_PORT}`;
......@@ -25,12 +33,21 @@ const service = axios.create({
'X-Ca-Stage': process.env.X_CA_STAGE
}
});
// request拦截器
service.interceptors.request.use(
config => {
if (process.client) {
config.headers['token'] =
Cookie.get('token') || Cookie.get('BCC_PROGRAM_USER_LOGIN_TOKEN') || '';
} else {
// 服务端api缓存
const { params = {}, headers = {} } = config
const key = md5(config.url + JSON.stringify(params) + JSON.stringify(headers))
// 缓存命中
if (CACHED.has(key)) {
return Promise.resolve(CACHED.get(key))
}
}
const noMsg = config.headers['noMsg'] || '';
if (config.headers.hasOwnProperty('noMsg')) {
......@@ -49,6 +66,11 @@ service.interceptors.response.use(
const { status, data, config } = res;
if (status === 200) {
const { code, errorCode, errorMessage } = data;
if (!process.client) {
const { params = {}, headers = {} } = config
const key = md5(config.url + JSON.stringify(params) + JSON.stringify(headers))
CACHED.set(key, data)
}
if ((code !== 200 || errorCode !== 0) && code !== 0) {
Sentry.captureException(
new Error(`${status};${JSON.stringify(data)};${JSON.stringify(config)}`)
......
// 渐进式渲染
export default function(count = 10) {
return {
data() {
return {
displayPriority: 0
}
},
mounted() {
this.runDisplayPriority()
},
methods: {
runDisplayPriority() {
const step = () => {
requestAnimationFrame(() => {
this.displayPriority++
if (this.displayPriority < count) {
step()
}
})
}
step()
},
defer(priority) {
return this.displayPriority >= priority
}
}
}
}
/* eslint-disable complexity */
import { mapGetters, mapMutations } from 'vuex';
import {
getExplainingGoodsInfo
......@@ -15,7 +16,8 @@ const mixin = {
userInfo: 'userInfo',
menuList: 'menuList',
channelInfo: 'channelInfo',
caseInfo: 'caseInfo'
caseInfo: 'caseInfo',
giftAni: 'giftAni'
}),
reportDms() {
let dms = '';
......@@ -183,12 +185,22 @@ const mixin = {
})
return false;
}
if ((Number(data.msgType) === 18 || Number(data.msgType) === 19) && data.redpacketId) { // 发送/关闭 定时红包
this.$Bus.$emit('bus-getCountDown');
}
if (Number(data.msgType) === 16 && data.redpacketId) {
this.$Bus.$emit('bus-delRain');
return false;
}
if (Number(data.msgType) === 2 || Number(data.msgType) === 14) {
this.$Bus.$emit('bus-giftRoll', data);
if (Number(data.msgType) === 14 && !this.giftAni) {
this.$Bus.$emit('bus-setGiftBannerInfo', data);
setTimeout(() => {
this.$Bus.$emit('bus-setGiftBannerInfo', null);
}, 3000)
}
this.$Bus.$emit('bus-playsvga', data);
}
if (data.isTop) {
this.$Bus.$emit('bus-addTopChat', data);
......
export const getQueryVariable = (variable) =>{
const query = window.location.search.substring(1);
const vars = query.split("&");
for (let i = 0;i < vars.length;i++) {
const pair = vars[i].split("=");
if (pair[0] === variable){return pair[1];}
}
return (false);
}
\ No newline at end of file
......@@ -45,6 +45,12 @@ import animated from 'animate.css'
Vue.use(animated)
if (process.client) {
const quicklink = require('quicklink/dist/quicklink.umd')
quicklink.listen()
const ScrollPicker = require('vue-scroll-picker')
Vue.use(ScrollPicker)
if (!process.env.private) {
require('@/plugins/arms');
const Inkmarks = require('@gdyfe/ink-marks');
......@@ -66,3 +72,4 @@ if (process.client) {
}
});
}
// export default Vue
/**
* 登录
* @param {object} {token}
* return Pomise
*/
import { getWatchLoginInfo } from '../API/apiAll';
import store from '@/store/index'
// import Layer from '@/plugins/Layer/index'; //登陆成功
import Cookie from 'js-cookie'
import { getQueryVariable } from '../Utils/index'
export const login = async function({token} = {token: ''}) {
Cookie.set('token', token, { expires: 10 });
const { id, uin, liveNowStatus } = store().getters['channelInfo']
const res = await getWatchLoginInfo({
id, uin
});
if (res.code === 200 && res.errorCode === 0) {
const info = res.data.watchUserInfo;
store().commit('set_userInfo', info)
const referer = {refererId: getQueryVariable('refererId')}
// 邀请统计
if (referer.refererId && info.id) {
store().dispatch('invitation', referer)
}
// 数据统计相关
store().dispatch('PostInfo')
// 用户行为
const Inkmarks = require('@gdyfe/ink-marks');
Inkmarks.setUser({
id: Number(info.id) || 0,
username: info.userNick || '游客'
});
const websocketHeartbeat = require('../websocketHeartbeat').default;
websocketHeartbeat().useIt('userInfo', {
"userId": info.id || 0,
// "token": this.token,
"id": id,
"type":"live",
"uin": uin,
"liveNowStatus": liveNowStatus
})
}
return this
}
\ No newline at end of file
import { watchTime } from './API/apiWS';
export default function() {
const store = this.$store
const userInfo = store.getters['userInfo']
const channelInfo = store.getters['channelInfo']
const websocketHeartbeat = require('./timer').default;
const info = {
"userId": userInfo.id || 0,
// "token": this.token,
"id": channelInfo.id,
"type":"live",
"uin": channelInfo.uin,
"liveNowStatus": channelInfo.liveNowStatus
}
return websocketHeartbeat({
url: watchTime,
pingTimeout: 5000,
pongTimeout: 5000,
manualStart: false,
repeatLimit: 10,
userInfo: info,
webworker: false
}).useIt('uuid').useIt('ua')
}
\ No newline at end of file
......@@ -6,6 +6,9 @@ const defaultHead =
const phoneHead = require(`@/assets/img/phone-head.png`);
const getters = {
giftAni(state) {
return state.giftAni
},
nowDate(state) {
return state.nowDate;
},
......
......@@ -14,6 +14,9 @@ const mutations = {
set_caseInfo(state, info) {
state.caseInfo = info;
},
set_giftAni(state) {
state.giftAni = !state.giftAni;
},
set_drainage_state(state, info) {
state.drainage['drainage_status'] = info;
},
......
......@@ -18,6 +18,7 @@ const state = () => ({
showRed: false,
showRedInfo: { type: '', id: '' },
onlySeeRed: false,
uuid: ''
uuid: '',
giftAni: true
});
export default state;
......@@ -2135,6 +2135,13 @@
dayjs "^1.8.34"
pako "^1.0.11"
"@gdyfe/svgaplayer-for-live@^1.0.3":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@gdyfe/svgaplayer-for-live/-/svgaplayer-for-live-1.0.3.tgz#1f3b14b30ce754ace7147a4aa15b99a55c45edb9"
integrity sha512-nXpwOha6XyqF5V11hX3w1Vr3xggDq+zPncGjFTvbakuhrVJptyXKJqlRwAj5P2Ky+MK9qKOhNSddGHeq1xmsFA==
dependencies:
svga.lite "^1.5.0"
"@gdyfe/uploader@^2.3.6":
version "2.3.6"
resolved "https://registry.yarnpkg.com/@gdyfe/uploader/-/uploader-2.3.6.tgz#0117dcaa1c8bde3b08c82b8a5abf37d28a87772c"
......@@ -3394,6 +3401,18 @@ atob@^2.1.2:
resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
auto-changelog@*:
version "2.2.1"
resolved "https://registry.yarnpkg.com/auto-changelog/-/auto-changelog-2.2.1.tgz#a031fbf1dfe140dda2ec8c77a524031478a0e933"
integrity sha512-XlykJfZrXlWUAADBqGoN1elmntrRcx7oEymyYB3NRPEZxv0TfYHfivmwzejUMnwAdXKCgbQPo7GV5ULs3jwpfw==
dependencies:
commander "^5.0.0"
handlebars "^4.7.3"
lodash.uniqby "^4.7.0"
node-fetch "^2.6.0"
parse-github-url "^1.0.2"
semver "^6.3.0"
autoprefixer@^9.6.1:
version "9.8.6"
resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.6.tgz#3b73594ca1bf9266320c5acf1588d74dea74210f"
......@@ -4200,6 +4219,11 @@ commander@^4.1.1:
resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068"
integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==
commander@^5.0.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae"
integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==
commondir@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
......@@ -6102,6 +6126,18 @@ hable@^3.0.0:
resolved "https://registry.yarnpkg.com/hable/-/hable-3.0.0.tgz#6de089b2df946635cf8134b9e4859f1b62de255f"
integrity sha512-7+G0/2/COR8pwteYFqHIVYfQpuEiO2HXwJrhCBJVgrNrl9O5eaUoJVDGXUJX+0RpGncNVTuestexjk1afj01wQ==
handlebars@^4.7.3:
version "4.7.7"
resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1"
integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==
dependencies:
minimist "^1.2.5"
neo-async "^2.6.0"
source-map "^0.6.1"
wordwrap "^1.0.0"
optionalDependencies:
uglify-js "^3.1.4"
hard-source-webpack-plugin@^0.13.1:
version "0.13.1"
resolved "https://registry.yarnpkg.com/hard-source-webpack-plugin/-/hard-source-webpack-plugin-0.13.1.tgz#a99071e25b232f1438a5bc3c99f10a3869e4428e"
......@@ -7250,6 +7286,11 @@ lodash.uniq@^4.5.0:
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
lodash.uniqby@^4.7.0:
version "4.7.0"
resolved "https://registry.yarnpkg.com/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz#d99c07a669e9e6d24e1362dfe266c67616af1302"
integrity sha1-2ZwHpmnp5tJOE2Lf4mbGdhavEwI=
lodash@^4.15.0, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.5:
version "4.17.20"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52"
......@@ -8174,6 +8215,11 @@ parse-git-config@^3.0.0:
git-config-path "^2.0.0"
ini "^1.3.5"
parse-github-url@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/parse-github-url/-/parse-github-url-1.0.2.tgz#242d3b65cbcdda14bb50439e3242acf6971db395"
integrity sha512-kgBf6avCbO3Cn6+RnzRGLkUsv4ZVqv/VfAYkRsyBcgkshNvVBkRn1FEZcW0Jb+npXQWm2vHPnnOqFteZxRRGNw==
parse-json@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9"
......@@ -9238,6 +9284,14 @@ querystring@0.2.0, querystring@^0.2.0:
resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620"
integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=
quicklink@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/quicklink/-/quicklink-2.1.0.tgz#86f009b5d611db2afb798490078aa75ae9c0f464"
integrity sha512-1K4ekaequXoC1m+gbYiEZNL+nMRfZBSNF/lxqsZSgZuAMekZXN1Or5s8d+XtpY9SurnuateLv1VPZviZg5MeDw==
dependencies:
route-manifest "^1.0.0"
throttles "^1.0.0"
quill-delta@^3.6.2:
version "3.6.3"
resolved "https://registry.yarnpkg.com/quill-delta/-/quill-delta-3.6.3.tgz#b19fd2b89412301c60e1ff213d8d860eac0f1032"
......@@ -9427,6 +9481,11 @@ regexp.prototype.flags@^1.2.0:
define-properties "^1.1.3"
es-abstract "^1.17.0-next.1"
regexparam@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/regexparam/-/regexparam-1.3.0.tgz#2fe42c93e32a40eff6235d635e0ffa344b92965f"
integrity sha512-6IQpFBv6e5vz1QAqI+V4k8P2e/3gRrqfCJ9FI+O1FLQTO+Uz6RXZEZOPmTJ6hlGj7gkERzY5BRCv09whKP96/g==
regexpp@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f"
......@@ -9594,6 +9653,13 @@ ripemd160@^2.0.0, ripemd160@^2.0.1:
hash-base "^3.0.0"
inherits "^2.0.1"
route-manifest@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/route-manifest/-/route-manifest-1.0.0.tgz#0155513f3cd158c18827413845ab1a8ec2ad15e1"
integrity sha512-qn0xJr4nnF4caj0erOLLAHYiNyzqhzpUbgDQcEHrmBoG4sWCDLnIXLH7VccNSxe9cWgbP2Kw/OjME+eH3CeRSA==
dependencies:
regexparam "^1.3.0"
run-async@^2.4.0:
version "2.4.1"
resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455"
......@@ -10291,6 +10357,11 @@ svg-tags@^1.0.0:
resolved "https://registry.yarnpkg.com/svg-tags/-/svg-tags-1.0.0.tgz#58f71cee3bd519b59d4b2a843b6c7de64ac04764"
integrity sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=
svga.lite@^1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/svga.lite/-/svga.lite-1.5.0.tgz#ac1baa029b961e437f753ca70cc2a1af56fb3664"
integrity sha512-VBPWrDMy83L3Qqv8pzmVfecVaaTK469XMtshciebRVrxBIVDN6FoK5QCNQkHW8BVe897QJAoSRhyLQqb8RBYPQ==
svgo@^1.0.0:
version "1.3.2"
resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167"
......@@ -10405,6 +10476,11 @@ thread-loader@^2.1.3:
loader-utils "^1.1.0"
neo-async "^2.6.0"
throttles@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/throttles/-/throttles-1.0.1.tgz#3abdcde28df88d5eddf7e57cad8da35bd403ddd0"
integrity sha512-fab7Xg+zELr9KOv4fkaBoe/b3L0GMGLd0IBSCn16GoE/Qx6/OfCr1eGNyEcDU2pUA79qQfZ8kPQWlRuok4YwTw==
through2@^2.0.0:
version "2.0.5"
resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd"
......@@ -10574,6 +10650,11 @@ ua-parser-js@^0.7.21:
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.22.tgz#960df60a5f911ea8f1c818f3747b99c6e177eae3"
integrity sha512-YUxzMjJ5T71w6a8WWVcMGM6YWOTX27rCoIQgLXiWaxqXSx9D7DNjiGWn1aJIRSQ5qr0xuhra77bSIh6voR/46Q==
uglify-js@^3.1.4:
version "3.13.1"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.13.1.tgz#2749d4b8b5b7d67460b4a418023ff73c3fefa60a"
integrity sha512-EWhx3fHy3M9JbaeTnO+rEqzCe1wtyQClv6q3YWq0voOj4E+bMZBErVS1GAHPDiRGONYq34M1/d8KuQMgvi6Gjw==
uglify-js@^3.5.1:
version "3.10.4"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.10.4.tgz#dd680f5687bc0d7a93b14a3482d16db6eba2bfbb"
......@@ -10964,6 +11045,11 @@ vue-router@^3.4.3:
resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.4.3.tgz#fa93768616ee338aa174f160ac965167fa572ffa"
integrity sha512-BADg1mjGWX18Dpmy6bOGzGNnk7B/ZA0RxuA6qedY/YJwirMfKXIDzcccmHbQI0A6k5PzMdMloc0ElHfyOoX35A==
vue-scroll-picker@^0.7.1:
version "0.7.1"
resolved "https://registry.yarnpkg.com/vue-scroll-picker/-/vue-scroll-picker-0.7.1.tgz#31a5e73d92ea2524c14e8dc24ac80b52e2269bdf"
integrity sha512-G0TCHd3qdwmFGh+ScUpsCxHjeNPzY45bvZFHRP6xDnT66tKkuM6+QaXm4M4vO5dxyFNyzXqX9PPnH9opC+a/FA==
vue-server-renderer@^2.6.12:
version "2.6.12"
resolved "https://registry.yarnpkg.com/vue-server-renderer/-/vue-server-renderer-2.6.12.tgz#a8cb9c49439ef205293cb41c35d0d2b0541653a5"
......@@ -11194,6 +11280,11 @@ word-wrap@~1.2.3:
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
wordwrap@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=
worker-farm@^1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.7.0.tgz#26a94c5391bbca926152002f69b84a4bf772e5a8"
......
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 sign in to comment