第一次提交

This commit is contained in:
wangxiaowei
2025-06-11 10:21:51 +08:00
commit 52932d54b1
2341 changed files with 185283 additions and 0 deletions

View File

@ -0,0 +1,216 @@
<template>
<view class="wrap__giftPanel" v-if="popupVisible" :class="Visible?'bottom-panel open':'bottom-panel close'" @click="closePopup">
<view class="wrapgift-mask" @tap="closePopup"></view>
<view class="pop__ui_child anim-footer">
<view class="progress-bar" v-if="showSlider" @tap.stop="">
<slider :value="value" activeColor="#f72b6c" backgroundColor="#FFFFFF" block-color="#FFFFFF" @change="sliderChange"
:min="0" :max="9" show-value />
</view>
<view class="more-box" @tap.stop="">
<button class="more-list" open-type="share" @click="share(0, 'WXSceneSession')">
<text class="icon iconfont icon-weixin i-btntool more-icont">&#xe621;</text>
<text class="f28 white mt20">微信好友</text>
</button>
<button class="more-list" @click="share(0, 'WXSenceTimeline')">
<text class="icon iconfont icon-fenxiang i-btntool more-icont">&#xe617;</text>
<text class="f28 white mt20">微信朋友圈</text>
</button>
</view>
</view>
</view>
</template>
<script>
import config from '@/config.js';
export default {
data() {
return {
/*是否可见*/
popupVisible: false,
/*分享配置*/
shareConfig: {},
// logo
logo: ''
}
},
created() {
this.getData();
},
props: ['appParams'],
methods: {
show(){
this.popupVisible = true;
this.getData();
},
/*请求对象*/
getRequest(){
let self = this;
// #ifdef APP-PLUS
return getApp().globalData.vueObj;
// #endif
// #ifndef APP-PLUS
return self;
// #endif
},
getData(){
let self = this;
self.getRequest()._get(
'settings/appShare',{},
function(res) {
self.shareConfig = res.data.appshare;
self.logo = res.data.logo;
console.log(self.shareConfig)
}
);
},
/*关闭弹窗*/
closePopup(type) {
this.popupVisible = false;
},
// 分享
share: function(shareType, scene) {
let shareOPtions = {
provider: "weixin",
scene: scene, //WXSceneSession”分享到聊天界面“WXSenceTimeline”分享到朋友圈
type: shareType,
success: function (res) {
console.log("success:" + JSON.stringify(res));
},
fail: function (err) {
console.log("fail:" + JSON.stringify(err));
}
}
if(this.shareConfig.type != 2){
shareOPtions.summary = this.appParams.summary;
shareOPtions.imageUrl = this.logo;
shareOPtions.title = this.appParams.title;
// 公众号/h5
if(this.shareConfig.type == 1){
shareOPtions.href = this.shareConfig.open_site + this.appParams.path;
}else if(this.shareConfig.type == 3){
//下载页
if(this.shareConfig.bind_type == 1){
shareOPtions.href = this.shareConfig.down_url;
}else{
shareOPtions.href = config.app_url + "/index.php/api/user.useropen/invite?app_id="+ config.app_id +"&referee_id=" + uni.getStorageSync('user_id');
}
}
}else{
// 分享到小程序
shareOPtions.scene = 'WXSceneSession';
shareOPtions.type = 5;
shareOPtions.imageUrl = this.appParams.image ? this.appParams.image : this.logo;
shareOPtions.title = this.appParams.title;
shareOPtions.miniProgram = {
id: this.shareConfig.gh_id,
path: this.appParams.path,
webUrl: this.shareConfig.web_url,
type:0
};
}
uni.share(shareOPtions);
},
}
}
</script>
<style scoped>
.iconfont {
font-family: iconfont;
}
.nlv_borT {
border-color: #ebebeb;
border-style: solid;
border-top-width: 1upx;
}
.wrapgift-mask {
background-color: #000;
opacity: .1;
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 201910;
}
.pop__ui_child {
background-color: #fbfbfb;
border-top-left-radius: 12px;
border-top-right-radius: 12px;
font-size: 14px;
overflow: hidden;
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 201911;
}
.more-box {
background-color: #2a2634;
width: 750rpx;
height: 350rpx;
position: fixed;
bottom: 0;
border-top-left-radius: 16rpx;
border-top-right-radius: 16rpx;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
padding: 0 20rpx;
z-index: 9999;
}
.more-list {
display: flex;
flex-direction: column;
justify-content: center;
flex: 1;
align-items: center;
padding: 50rpx 0;
background-color: #2a2634;
border-width: 0;
}
.more-icont {
font-size: 76rpx;
}
.more-list-active {
border-width: 1rpx;
border-color: #ea4678;
border-style: solid;
border-radius: 16rpx;
}
.Progress {
background-color: rgba(0, 0, 0, 0.3);
/* opacity: 0.3; */
height: 100rpx;
width: 700rpx;
position: fixed;
bottom: 370rpx;
border-radius: 16rpx;
left: 25rpx;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
padding: 0 30rpx;
}
.progress-bar {
position: fixed;
bottom: 360rpx;
width: 750rpx;
justify-content: center;
}
.wrap__giftPanel {
z-index: 100;
}
</style>

View File

@ -0,0 +1,156 @@
<template>
<!--倒计时-->
<view class="countdown">
<template v-if="config.type == null">
<text v-if="status == 0">{{title}}</text>
<text v-if="status == 1">活动具体时间</text>
<text v-if="status == 2">活动结束时间</text>
<text class="box">{{ day }}</text>
<text class="p-0-10"></text>
<text class="box">{{ hour }}</text>
<text class="p-0-10"></text>
<text class="box">{{ minute }}</text>
<text class="p-0-10"></text>
<text class="box">{{ second }}</text>
<text class="p-0-10"></text>
</template>
<template v-if="config.type === 'text'">
{{title}}{{ parseInt(day * 24) + parseInt(hour) }}:{{ minute }}:{{ second }}
</template>
</view>
</template>
<script>
export default {
data() {
return {
/*状态*/
status: 0,
/*天*/
day: '0',
/*时*/
hour: '0',
/*分*/
minute: '0',
/*秒*/
second: '0',
/*定时器*/
timer: null,
/*剩余秒*/
totalSeconds: 0,
/*标题*/
title:'距离开始仅剩:'
};
},
props: {
config: {
type: Object,
default:function(){
return {
type: 'all',
};
}
}
},
created() {},
watch: {
config: {
deep: true,
handler: function(n, o) {
if (n != o && n.endstamp != 0) {
if(n.title&&typeof n.title!='undefined'){
this.title=n.title;
}
this.setTime();
}
},
immediate: true
}
},
methods: {
/*轮循*/
setTime() {
let self = this;
self.timer = setInterval(function() {
self.init();
}, 1000);
},
/*初始化*/
init() {
let nowseconds = Date.now() / 1000;
if (nowseconds < this.config.startstamp) {
//活动时间还没到
this.status = 1;
} else if (nowseconds > this.config.endstamp) {
//活动已过期
this.status = 2;
} else {
//活动进行中
this.totalSeconds = parseInt(this.config.endstamp - nowseconds);
this.status = 0;
this.countDown();
}
this.$emit('returnVal', this.status);
},
/*计算时分秒*/
countDown() {
let totalSeconds = this.totalSeconds;
//天数
let day = Math.floor(totalSeconds / (60 * 60 * 24));
//取模(余数)
let modulo = totalSeconds % (60 * 60 * 24);
//小时数
let hour = Math.floor(modulo / (60 * 60));
modulo = modulo % (60 * 60);
//分钟
let minute = Math.floor(modulo / 60);
//秒
let second = modulo % 60;
this.day = this.convertTwo(day);
this.hour = this.convertTwo(hour);
this.minute = this.convertTwo(minute);
this.second = this.convertTwo(second);
this.totalSeconds--;
},
/*转两位数*/
convertTwo(n) {
let str = '';
if (n < 10) {
str = '0' + n;
} else {
str = n;
}
return str;
},
/*把时间戳转普通时间*/
getLocalTime(nS) {
return new Date(parseInt(nS) * 1000).toLocaleString().replace(/:\d{1,2}$/, ' ');
}
},
destroyed() {
clearInterval(this.timer);
}
};
</script>
<style>
.countdown{
flex-direction: row;
height: 45rpx;
line-height: 45rpx;
}
.box {
display: inline-block;
width: 34rpx;
border-radius: 8rpx;
background: #fb4d70;
text-align: center;
height: 50rpx;
line-height: 45rpx;
color: #ffffff;
}
</style>

View File

@ -0,0 +1,134 @@
<template>
<view class="share-shadow" :style="'height:'+winHeight+' ;'">
<view class="share-wrap">
<view class="content ww100">
<image :src="qrcode" mode="widthFix"></image>
<button class="btn-rose-shadow mt20" type="default" @tap="savePosterImg">保存图片</button>
</view>
<view class="close-btns" @tap="hidePopupFunc(true)"><text class="icon iconfont icon-guanbi"></text></view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
/*展示类别*/
type: 0,
/*宽度*/
width: 600,
/*高度*/
/*背景颜色*/
backgroundColor: 'none',
/*阴影*/
boxShadow: 'none',
form: {},
coupon: []
};
},
props: ['qrcode','winHeight'],
created() {
},
mounted() {
/*获取弹出层内容*/
this.setData();
},
methods: {
/*获取弹出层内容*/
setData() {
console.log(this.winHeight)
},
/*关闭弹窗*/
hidePopupFunc(e) {
this.isPopup = false;
this.$emit('close');
},
//保存海报图片
savePosterImg() {
let self = this;
uni.showLoading({
title: '加载中'
});
// 下载海报图片
uni.downloadFile({
url: self.qrcode,
success(res) {
uni.hideLoading();
// 图片保存到本地
uni.saveImageToPhotosAlbum({
filePath: res.tempFilePath,
success(data) {
uni.showToast({
title: '保存成功',
icon: 'success',
duration: 2000
});
// 关闭商品海报
self.isCreatedImg = false;
},
fail(err) {
if (err.errMsg === 'saveImageToPhotosAlbum:fail auth deny') {
uni.showToast({
title: '请允许访问相册后重试',
icon: 'none',
duration: 1000
});
setTimeout(() => {
uni.openSetting();
}, 1000);
}
},
complete(res) {
console.log('complete');
}
});
}
});
},
}
};
</script>
<style scoped>
.share-shadow{
position: fixed;
top:0;
z-index: 1010;
width: 750rpx;
background-color: #00000030;
}
.share-wrap {
width: 90%;
border-radius: 20upx;
overflow: hidden;
padding-top: 130rpx;
margin: 0 auto;
}
.share-wrap .content image{
width: 100%;
}
.share-wrap .close-btns {
margin: 10rpx auto 0;
width: 60rpx;
height: 60rpx;
line-height: 60rpx;
text-align: center;
display: flex;
justify-content: center;
align-items: center;
border-radius: 50%;
background: none;
border: 2px solid #ffffff;
}
.home-push-wrap .close-btns .iconfont {
color: #ffffff;
}
</style>

View File

@ -0,0 +1,58 @@
export default [
"😀", "😁", "😃", "😄", "😅", "😆", "😉", "😊", "😋", "😎", "😍",
"😘", "😗", "😙", "😚", "☺", "😇", "😐", "😑", "😶", "😏", "😣", "😥", "😮", "😯", "😪",
"😫", "😴", "😌", "😛", "😜", "😝", "😒", "😓", "😔", "😕", "😲", "😷", "😖", "😞", "😟",
"😤", "😢", "😭", "😦", "😧", "😨", "😬", "😰", "😱", "😳", "😵", "😡", "😠",
"👦", "👧", "👨", "👩", "👴", "👵", "👶", "👱", "👮", "👲", "👳", "👷", "👸", "💂", "🎅", "👰", "👼",
"💆", "💇", "🙍", "🙎", "🙅", "🙆", "💁", "🙋", "🙇", "🙌", "🙏", "👤", "👥", "🚶", "🏃", "👯",
"💃", "👫", "👬", "👭", "💏", "💑", "👪", "💪", "👈", "👉", "☝", "👆", "👇", "✌", "✋", "👌",
"👍", "👎", "✊", "👊", "👋", "👏", "👐", "✍", "👣", "👀", "👂", "👃", "👅", "👄", "💋", "👓",
"👔", "👕", "👖", "👗","👘", "👙", "👛", "👜", "👝", "🎒", "💼", "👞", "👟", "👠", "👡", "👢", "👑",
"👒", "🎩", "🎓", "💄", "💅", "💍", "🌂", "📶", "📳", "📴", "♻", "🏧","🚮", "🚰", "♿", "🚹", "🚺",
"🚻", "🚼", "🚾", "⚠", "🚸", "⛔", "🚫", "🚳", "🚭", "🚯", "🚱", "🚷", "🔞", "💈",
"🙈", "🙉", "🙊", "🐵", "🐒", "🐶", "🐕", "🐩", "🐺", "🐱", "😺", "😸", "😹", "😻", "😼", "😽",
"🙀", "😿", "😾", "🐈", "🐯", "🐅", "🐆", "🐴", "🐎", "🐮", "🐂",
"🐃","🐄","🐷","🐖","🐗","🐽","🐏","🐑","🐐","🐪","🐫","🐘","🐭",
"🐁","🐀","🐹","🐰","🐇","🐻","🐨","🐼","🐾","🐔","🐓","🐣","🐤","🐥",
"🐦", "🐧", "🐸", "🐊", "🐢", "🐍", "🐲", "🐉", "🐳", "🐋", "🐬", "🐟", "🐠", "🐡",
"🐙", "🐚", "🐌", "🐛", "🐜", "🐝", "🐞", "🦋", "💐", "🌸", "💮", "🌹", "🌺",
"🌻", "🌼", "🌷", "🌱", "🌲", "🌳", "🌴", "🌵", "🌾", "🌿", "🍀", "🍁", "🍂", "🍃",
"🌍","🌎","🌏","🌐","🌑","🌒","🌓","🌔","🌕","🌖","🌗","🌘","🌙","🌚",
"🌛","🌜","☀","🌝","🌞","⭐","🌟","🌠","☁","⛅","☔","⚡","❄","🔥","💧","🌊",
"🍅","🍆","🌽","🍄","🌰","🍞","🍖","🍗","🍔","🍟","🍕","🍳","🍲","🍱","🍘","🍙",
"🍚", "🍛", "🍜", "🍝", "🍠", "🍢", "🍣", "🍤", "🍥", "🍡", "🍦", "🍧", "🍨", "🍩", "🍪", "🎂",
"🍰", "🍫","🍬","🍭","🍮","🍯","🍼","☕","🍵","🍶","🍷","🍸","🍹","🍺","🍻","🍴",
"🎪", "🎭", "🎨", "🎰", "🚣", "🛀", "🎫", "🏆", "⚽", "⚾",
"🏀", "🏈", "🏉", "🎾", "🎱", "🎳", "⛳", "🎣", "🎽", "🎿",
"🏂", "🏄", "🏇", "🏊", "🚴", "🚵", "🎯", "🎮", "🎲", "🎷", "🎸", "🎺", "🎻", "🎬",
"😈", "👿", "👹", "👺", "💀", "☠", "👻", "👽", "👾", "💣",
"🌋", "🗻", "🏠", "🏡", "🏢", "🏣", "🏤", "🏥", "🏦", "🏨",
"🏩", "🏪", "🏫", "🏬", "🏭", "🏯", "🏰", "💒", "🗼", "🗽", "⛪",
"⛲", "🌁", "🌃", "🌆", "🌇", "🌉", "🌌", "🎠", "🎡", "🎢", "🚂",
"🚃", "🚄", "🚅", "🚆", "🚇", "🚈", "🚉", "🚊", "🚝", "🚞", "🚋",
"🚌", "🚍", "🚎", "🚏", "🚐", "🚑", "🚒", "🚓", "🚔", "🚕", "🚖", "🚗", "🚘",
"🚚", "🚛", "🚜", "🚲", "⛽", "🚨", "🚥", "🚦", "🚧", "⚓", "⛵", "🚤", "🚢", "✈",
"💺", "🚁", "🚟", "🚠", "🚡", "🚀", "🎑", "🗿", "🛂", "🛃", "🛄", "🛅",
"💌", "💎", "🔪", "💈", "🚪", "🚽", "🚿", "🛁", "⌛", "⏳", "⌚", "⏰", "🎈", "🎉",
"🎊", "🎎", "🎏", "🎐", "🎀", "🎁", "📯", "📻", "📱", "📲", "☎", "📞", "📟", "📠", "🔋", "🔌", "💻",
"💽", "💾", "💿", "📀", "🎥", "📺", "📷", "📹", "📼", "🔍", "🔎", "🔬", "🔭", "📡", "💡", "🔦",
"🏮", "📔", "📕", "📖", "📗", "📘", "📙", "📚", "📓", "📃", "📜", "📄", "📰", "📑", "🔖",
"💰", "💴", "💵", "💶", "💷", "💸", "💳", "✉", "📧", "📨", "📩", "📤", "📥", "📦", "📫",
"📪", "📬", "📭", "📮", "✏", "✒📝", "📁", "📂", "📅", "📆", "📇", "📈", "📉", "📊", "📋",
"📌", "📍", "📎📏📐", "✂", "🔒", "🔓", "🔏", "🔐", "🔑", "🔨", "🔫", "🔧", "🔩", "🔗", "💉",
"💊", "🚬", "🔮🚩", "🎌", "💦", "💨", "♠", "♥", "♦", "♣", "🀄", "🎴", "🔇", "🔈", "🔉", "🔊", "📢", "📣",
"💤", "💢", "💬", "💭", "♨", "🌀", "🔔", "🔕", "✡", "✝", "🔯", "📛", "🔰", "🔱", "⭕", "✅",
"☑", "✔", "✖", "❌", "❎", "", "", "➗", "➰", "➿", "〽", "✳", "✴", "❇", "‼", "⁉", "❓", "❔", "❕", "❗",
"©®", "™🎦🔅", "🔆", "💯", "🔠", "🔡", "🔢", "🔣", "🔤", "🅰", "🆎", "🅱", "🆑", "🆒",
"🆓", "ℹ🆔", "Ⓜ", "🆕", "🆖", "🅾", "🆗", "🅿", "🆘", "🆙", "🆚", "🈁", "🈂", "🈷", "🈶", "🈯",
"🉐", "🈹", "🈚", "🈲", "🉑", "🈸", "🈴", "🈳", "㊗", "㊙", "🈺", "🈵", "▪", "▫", "◻", "◼◽",
"◾", "⬛", "⬜", "🔶", "🔷", "🔸", "🔹", "🔺", "🔻", "💠", "🔲", "🔳", "⚪", "⚫", "🔴", "🔵",
"♈", "♉", "♊", "♋", "♌", "♍", "♎", "♏", "♐", "♑", "♒", "♓", "⛎",
"🕛", "🕧", "🕐", "🕜", "🕑", "🕝", "🕒", "🕞", "🕓", "🕟", "🕔", "🕠", "🕕", "🕡",
"🕖", "🕢", "🕗", "🕣", "🕘", "🕤", "🕙", "🕥", "🕚", "🕦", "⏱", "⏲", "🕰",
"💘", "❤", "💓", "💔", "💕", "💖", "💗", "💙", "💚", "💛", "💜", "💝", "💞", "💟❣",
"🍇", "🍈", "🍉", "🍊", "🍋", "🍌", "🍍", "🍎", "🍏", "🍐", "🍑", "🍒", "🍓",
"⬆", "↗", "➡", "↘", "⬇", "↙", "⬅", "↖", "↕", "↔", "↩", "↪", "⤴", "⤵",
"🔃", "🔄", "🔙", "🔚", "🔛", "🔜", "🔝", "♚", "♛", "♝", "♞", "♜",
"♟", "♔", "♕", "♗", "♘", "♖",
]

View File

@ -0,0 +1,181 @@
<template>
<!-- <view class="content">
<view class="content_box" style="width: 74rpx;height: 74rpx"> -->
<view class="animate-wrap">
<view ref="likelist" class="aa" :class="{'bb':item.index}" v-for="(item,index) in viewList" :key="index">
<image style="width: 65rpx;height: 65rpx;" mode="widthFix" :src="item.src" :animation="item.animationData">
</image>
</view>
</view>
<!-- </view>
</view> -->
</template>
<script>
// #ifdef APP-PLUS
const animation = weex.requireModule('animation')
// #endif
export default {
data() {
return {
viewList: [],
pageDate: new Date() //全局时间用于函数节流
}
},
beforeCreate() {
// #ifdef APP-PLUS
const domModule = weex.requireModule('dom')
domModule.addRule('fontFace', {
fontFamily: "iconfont",
'src': "url('" + getApp().globalData.vueObj.font_url + "')"
});
// #endif
},
onShow() {},
methods: {
move() {
let testEl = this.$refs['likelist'];
console.log('--------------------点赞------------------------')
console.log(testEl);
let testimg = testEl[testEl.length - 1];
animation.transition(testimg, {
styles: {
color: '#FF0000',
transform: 'translate(0, -200px)',
opacity: '0',
transformOrigin: 'center center'
},
duration: 3000, //ms
timingFunction: 'ease',
delay: 0 //ms
}, function() {
console.log('animation finished.');
})
},
// 随机颜色(测试用可删除)
random() {
let r = Math.floor(Math.random() * 256),
g = Math.floor(Math.random() * 256),
b = Math.floor(Math.random() * 256);
return `rgb(${r},${g},${b})`
},
handleClick() {
let that = this;
let arr = ['-', '']
let arrImg = [
'/static/qunzi.png',
'/static/aixin.png',
'/static/yusan.png',
'/static/zan.png',
'/static/hua.png',
'/static/haixing.png'
]
let randomImg = Math.floor(Math.random() * arrImg.length)
let arrPush = {
src: arrImg[randomImg], //用于随机图标
back: this.random(), //可删除
index: false, //可删除
time: 5000, //动画时间
animationData: {}, //每个盒子独立动画不可全局
x: Math.ceil(Math.random() * 50), //方向间距
q: Math.floor(Math.random() * arr.length), //用于随机方向
lastIndex: 5, //用于删除数组
timer: null, //定时器
lastTime: 1000 //删除的倒计时
}
//函数节流限制用户频繁快速点击
let t = new Date() - this.pageDate;
console.log('--------t='+t);
if (t < 300) return //如果点击的时间小于初始时间300
this.pageDate = new Date(); //同步全局时间
//------------
this.viewList.push(arrPush)
//核心动画
this.$nextTick(function() {
// #ifdef APP-PLUS
this.move()
// #endif
this.viewList.forEach((i, o, v) => {
var animate = uni.createAnimation({
duration: i.time,
timingFunction: 'ease-out'
})
that.animation = animate
let time = arr[i.q] + i.x //随机的方向和间距
setTimeout(() => {
that.animation.translateY(-200).step()
that.animation.opacity(0).step()
that.animation.translateX(Number(time)).step()
i.animationData = that.animation.export()
//函数防抖
clearInterval(i.timer)
i.timer = setInterval(() => {
i.lastIndex-- //每个图标的倒计时到0删除
if (i.lastIndex < 0) {
v.splice(i, 1)
clearInterval(i.timer)
}
}, i.lastTime)
}, 100)
})
})
}
}
}
</script>
<style scoped>
.iconfont {
font-family: iconfont;
}
.animate-wrap {
display: inline-block;
margin-right: 10px;
position: absolute;
width: 74rpx;
height: 800rpx;
/* top: -110rpx; */
bottom: 100rpx;
right: 0;
z-index: 9998;
}
.content {
position: absolute;
right: 0;
z-index: 9999;
}
.content_box {
position: absolute;
bottom: 0;
right: 0;
}
.logo {
display: inline-block;
position: absolute;
right: 0;
width: 70rpx;
height: 70rpx;
}
.aa {
position: absolute;
bottom: 0;
font-size: 30upx;
color: white;
text-align: center;
line-height: 50upx;
width: 80upx;
transform: translateY(0);
}
.icon-31guanzhu1xuanzhong {
font-size: 40rpx;
}
</style>

View File

@ -0,0 +1,172 @@
<template>
<view v-if="popupVisible" class="popup-footer">
<view class="pop__ui_panel">
<view class="pop__ui_mask" @tap="close"></view>
<view class="pop__ui_child anim-footer" @tap.stop="">
<div>
<div class="foot-anchorinfo-wrap-anchorinfo p-0-20 tc" v-if="live_user">
<div class="foot-anchorinfo-wrap-nickName d-c-c fb f34">
<text>{{live_user.supplier.name}}</text>
</div>
<div class="d-c-c d-r mt20 gray9 f28">
<text class="p-0-10 gray6 f28">粉丝{{live_user.supplier.fav_count}}</text>
<text class="p-0-10 gray6 f28">点赞{{live_user.digg_num}}</text>
</div>
</div>
<div class="foot-anchorinfo-wrap-bottom d-b-c d-r">
<div class="foot-anchorinfo-guanzhu flex-1 d-c-c" @tap="followFunc" v-if="!is_follow">
<text class="f34 gray6">+关注</text>
</div>
<div class="foot-anchorinfo-guanzhu flex-1 d-c-c" @tap="followFunc" v-if="is_follow">
<text class="f34 gray6">已关注</text>
</div>
<div class="foot-anchorinfo-zhuye flex-1 d-c-c" @tap="gotoAnchorPage">
<text class="f34 gray6">主页</text>
</div>
</div>
</div>
<div class="foot-anchorinfo-wrap-photo-box">
<image class="foot-anchorinfo-wrap-photo" :src="live_user.supplier.logo.file_path" mode="aspectFill"></image>
</div>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
popupVisible: false,
/*主播对象*/
liveUser:{},
live_user:{},
/*是否关注*/
is_follow:false,
}
},
props: ['room_id','shop_supplier_id'],
methods: {
show() {
this.popupVisible = true;
this.getUser();
},
/*请求对象*/
getRequest(){
let self = this;
// #ifdef APP-PLUS
return getApp().globalData.vueObj;
// #endif
// #ifndef APP-PLUS
return self;
// #endif
},
/*获取主播详情*/
getUser() {
let self = this;
let data_type = self.data_type;
self.getRequest()._get(
'plus.live.room/detail',
{
room_id: self.room_id,
},
function(res) {
self.is_follow = res.data.hasFollow;
self.live_user = res.data.model
}
);
},
/*关注*/
followFunc() {
let self = this;
self.getRequest()._post(
'user.Favorite/add',
{
shop_supplier_id: self.shop_supplier_id,
pid:self.shop_supplier_id,
type:10
},
function(res) {
self.$emit('changeFollow', !self.is_follow);
self.getUser();
}
);
},
/*跳转主播个人中心*/
gotoAnchorPage(){
this.gotoPage('/pages/shop/shop?shop_supplier_id='+this.shop_supplier_id);
},
close() {
this.popupVisible = false;
},
}
}
</script>
<style scoped>
.pop__ui_mask {
background-color: #000;
opacity: .1;
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 1000;
}
.pop__ui_child {
background-color: #fbfbfb;
border-top-left-radius: 12px;
border-top-right-radius: 12px;
font-size: 14px;
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 9998;
}
.pop__ui_head {
border-style: solid;
border-color: #ebebeb;
border-bottom-width: 1upx;
font-size: 28upx;
font-weight: 700;
padding: 30upx;
text-alig: left;
}
.foot-anchorinfo-wrap-anchorinfo{
margin-top: 150rpx;
height: 120rpx;
}
.foot-anchorinfo-wrap-photo-box{
position: fixed;
bottom: 280rpx;
left: 275rpx;
width: 200rpx;
height: 200rpx;
z-index:9999;
}
.foot-anchorinfo-wrap-photo{
width: 200rpx;
height: 200rpx;
border-radius: 50%;
}
.foot-anchorinfo-wrap-nickName{
}
.foot-anchorinfo-wrap-bottom{
height: 100rpx;
background-color: #f4f4f4;
}
.foot-anchorinfo-guanzhu{
color: #e34470;
}
.foot-anchorinfo-zhuye{
color: #545454;
}
</style>

View File

@ -0,0 +1,488 @@
<template>
<view v-if="popupVisible" class="popup-footer">
<view class="pop__ui_panel">
<view class="pop__ui_mask" @tap="close"></view>
<view class="pop__ui_child anim-footer" @tap.stop="">
<div v-if="!open_addproduct">
<div class="product-head d-b-c p20 f30">
<div class="d-s-c">
<button v-if="isCaster" class="product-head-btn" @tap="addProductFunc"><text class="rose f30">添加商品</text></button>
</div>
<text class="ml10">共{{ total }}件商品</text>
<div class="d-s-c">
<button class="product-head-btn" @tap="openOrder"><text class="rose f30">订单</text></button>
</div>
</div>
<list class="add-product-list">
<cell class="add-product-item d-s-s" v-for="(item, index) in productList" :key="index">
<div class="add-product-picture">
<view>
<image class="add-product-picture-image" :src="item.image[0].file_path" mode="aspectFill"></image>
</view>
<text class="rose f28" ></text>
</div>
<div class="flex-1 ml20">
<div class="text-ellipsis-2">
<text class="f28">{{ item.product_name }}</text>
</div>
<div class="d-s-s d-r p-20-0">
<div class="d-s-s price d-r flex-1 f24">
<!--<text class="f24 rose">¥</text>-->
<text class="f34 fb rose">{{ item.product_price }}</text>
</div>
<div v-if="isCaster&&product_active != item.product_id" class="add-product-relation" @tap="setProduct(item)">
<text class="white f28">设为讲解</text>
</div>
<div v-if="product_active == item.product_id" class="add-product-relation">
<text class="white f28">讲解中</text>
</div>
<div v-if="!isCaster" class="add-product-relation" @tap="gotoProduct(item)">
<text class="white f28 m-auto">去购买</text>
</div>
</div>
</div>
</cell>
</list>
</div>
<!--添加商品-->
<div v-if="open_addproduct">
<div class="add-product-head d-b-c p20 f30">
<text class="f30">关联商品</text>
<button type="default" class="add-product-head-btn" @tap="confirmFunc(true)">
<text class="rose f28">确认</text>
</button>
</div>
<scroll-view class="add-product-list"
scroll-y="true"
@scrolltolower="loadmoreFunc">
<view class="add-product-item d-b-c" v-for="(item, index) in listData" :key="index">
<div class="add-product-picture">
<image class="add-product-picture-image" :src="item.product_image" mode="aspectFill"></image>
</div>
<div class="ml20 flex-1">
<div class="text-ellipsis-2"><text class="f30">{{ item.product_name }}</text></div>
<div class="d-s-s d-r p-20-0">
<div class="d-s-s price d-r flex-1 f24">
<text class="ml20 gray9 f28">售价:{{ item.product_price }}</text>
</div>
<div v-if="!isrelation(item)" class="add-product-relation" @tap="relationProduct(item)">
<text class="white f28">添加</text>
</div>
<div v-if="isrelation(item)" class="add-product-relation add-product-relation-hover">
<text class="white f28">已添加</text>
</div>
</div>
</div>
</view>
<!-- 没有记录 -->
<view class="d-c-c p30" v-if="listData.length == 0 && !loading">
<text class="cont">亲,暂无相关记录哦</text>
</view>
<uni-load-more v-else :loadingType="loadingType"></uni-load-more>
</scroll-view>
</div>
</view>
</view>
</view>
</template>
<script>
import uniLoadMore from '@/components/uni-load-more.vue';
export default {
components: {
uniLoadMore
},
data() {
return {
popupVisible: false,
/*当前讲解商品*/
product_active: '',
/*总条数*/
total: 0,
/*是否展示商品*/
open_products: false,
/*已关联商品id*/
relationIds: [],
/*商品列表*/
productList: [],
/*是否展开订单*/
open_order: false,
/*是否展开添加产品*/
open_addproduct: false,
/*没有更多*/
no_more: false,
/*商品列表*/
listData: [],
/*当前页面*/
page: 1,
/*一页多少条*/
list_rows: 10,
/*已选商品*/
productIds:[],
// 是否打开订单
open_Order:false,
loading: false
}
},
props: ['isCaster', 'room_id','shop_supplier_id'],
computed: {
/*加载中状态*/
loadingType() {
if (this.loading) {
return 1;
} else {
if (this.listData.length != 0 && this.no_more) {
return 2;
} else {
return 0;
}
}
}
},
methods: {
show(index) {
this.popupVisible = true;
this.getProduct();
},
/*请求对象*/
getRequest(){
let self = this;
// #ifdef APP-PLUS
return getApp().globalData.vueObj;
// #endif
// #ifndef APP-PLUS
return self;
// #endif
},
/*获取商品*/
getProduct() {
let self = this;
self.open_addproduct = false;
self.relationIds = [];
uni.showLoading({
title: '正在加载',
mask: true
})
self.getRequest()._get(
'plus.live.RoomApply/liveproduct',
{
shop_supplier_id: self.shop_supplier_id
},
function(res) {
uni.hideLoading();
if(res.data.list!=null){
self.productList = res.data.list.data;
for(let i=0;i<self.productList.length;i++) {
self.relationIds.push(self.productList[i].product_id);
}
self.total = res.data.list.total;
}
},false,function(){
uni.hideLoading();
}
);
},
/*添加商品*/
addProductFunc() {
this.open_addproduct = true;
this.productIds = [];
this.relationIds.forEach(item => {
this.productIds.push(item);
});
this.start();
},
/*开始*/
start() {
this.loading = true;
this.no_more = false;
this.listData = [];
this.page = 1;
this.list_rows = 10;
this.getData();
},
/*获取数据*/
getData() {
let self = this;
let page = self.page;
let list_rows = self.list_rows;
self.loading = true;
self.getRequest()._get(
'plus.live.RoomApply/product_list',
{
page: page || 1,
list_rows: list_rows
},
function(res) {
self.loading = false;
self.listData = self.listData.concat(res.data.list.data);
self.last_page = res.data.list.last_page;
if (res.data.list.last_page <= 1) {
self.no_more = true;
}
}
);
},
/*可滚动视图区域到底触发*/
loadmoreFunc() {
let self = this;
self.bottomRefresh = true;
self.page++;
self.loading = true;
if (self.page > self.last_page) {
self.loading = false;
self.no_more = true;
return;
}
self.getData();
},
/*判断是否关联*/
isrelation(e){
if(this.productIds.indexOf(e.product_id)!=-1){
return true;
}else{
return false;
}
},
/*设置商品*/
relationProduct(e){
let self = this;
this.productIds.push(e.product_id);
},
/*确认商品*/
confirmFunc() {
let self = this;
let e = self.productIds;
if (e.length > 0) {
for (let i = 0; i < e.length; i++) {
if (self.relationIds.indexOf(e[i]) != -1) {
e.splice(i, 1);
i--;
}
}
} else {
self.getProduct();
return;
}
if(e.length == 0){
self.getProduct();
return;
}
self.getRequest()._post(
'plus.live.RoomApply/addProduct',
{
productIds: e
},
function(res) {
self.getProduct();
}
);
},
/*设置商品*/
setProduct(item) {
let self = this;
uni.showLoading({
title: '设置中',
mask: true
});
self.getRequest()._post(
'plus.live.room/set_product',
{
room_id: self.room_id,
product_id: item.product_id
},
function(res) {
self.product_active = item.product_id;
self.$emit('setProduct', item.product_id);
self.close();
}
);
},
/*跳转商品详情*/
gotoProduct(e) {
let url = '/pages/product/detail/detail?product_id=' + e.product_id + '&room_id=' + this.room_id;
this.getRequest().gotoPage(url);
},
openOrder(){
this.popupVisible = false;
this.$emit('openOrder');
},
close() {
if(this.open_addproduct){
this.open_addproduct = false;
}else{
this.popupVisible = false;
}
},
}
}
</script>
<style scoped>
.m-auto{
margin: 0 auto;
}
.pop__ui_mask {
background-color: #000;
opacity: .1;
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 1000;
}
.pop__ui_child {
background-color: #fbfbfb;
border-top-left-radius: 12px;
border-top-right-radius: 12px;
font-size: 14px;
overflow: hidden;
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 1001;
}
.pop__ui_head {
border-style: solid;
border-color: #ebebeb;
border-bottom-width: 1upx;
font-size: 28upx;
font-weight: 700;
padding: 30upx;
text-align: left;
}
.wrap_carts {
height: 650upx;
}
.item {
flex-direction: row;
align-items: center;
padding: 30upx;
position: relative;
}
.gpic {
margin-right: 30upx;
height: 50px;
width: 50px;
}
.ginfo {
flex: 1;
}
.name {
font-size: 28upx;
}
.price {
color: #ff0f33;
font-size: 28upx;
margin-top: 15upx;
}
.gbtn {
background-image: linear-gradient(to right, #ff540a, #ff0f33);
border-radius: 5upx;
color: #fff;
font-size: 28upx;
padding: 12upx 25upx;
}
.product-head {
flex-direction: row;
}
.product-head-btn,.add-product-head-btn {
height: 60rpx;
line-height: 60rpx;
background-color: #fff;
border-color: #f72b6c;
}
.add-product-list{
width: 750rpx;
height: 700rpx;
}
.add-product-head {
flex-direction: row;
}
.add-product-item{
flex-direction: row;
padding: 20rpx;
}
.add-product-picture{
width: 160rpx;
height: 160rpx;
}
.add-product-picture-image{
width: 160rpx;
height: 160rpx;
}
.text-ellipsis-2{ height: 70rpx;}
.add-product-relation{
background-color: #51a938;
color: #fff;
border-color: #51a938;
font-size: 12px;
display: flex;
align-items: center;
border-radius: 6rpx;
width: 120rpx;
padding: 10rpx 0;
}
.add-product-relation text{
/* display: flex;
height: 60rpx;
line-height: 60rpx; */
}
.add-product-relation-hover{
background-color: #abd7a2;
border-color: #abd7a2;
}
.add-product-order{
position: absolute;
width: 750rpx;
height: 900rpx;
right: 0;
bottom: 0;
left: 0;
border-radius: 16rpx 16rpx 0 0;
background-color:#fff;
transition: transform 0.2s ease;
transform: translate(0, 0);
}
.add-product-order-close {
transition: transform 0s ease;
transform: translate(0, 100%);
}
.order-close{
width: 40rpx;
height: 40rpx;
}
.add-order-head{
background-color:#eeeeee;
flex-direction: row;
}
.order-num{
font-size: 28px;
color: #ababab;
margin-bottom: 10rpx;
}
.order-title{
text-overflow: ellipsis;
overflow:hidden;
}
.order-money{margin-top: 20rpx;}
</style>

View File

@ -0,0 +1,266 @@
<template>
<view class="wrap__giftPanel" v-if="showGiftView">
<view class="wrapgift-mask" @tap="close"></view>
<view class="pop__ui_child anim-footer" @tap.stop="">
<scroll-view class="wrapgift-body">
<view class="wrap_giftlist">
<view class="gift-head">
<view class="gift-menu"><text class="gm-item gm-item-on">礼物</text></view>
<view class="gift-coins"><text class="gc-coin">{{giftName}}</text><text class="gc-num">{{userInfo.gift_money}}</text><text class="gc-recharge" @tap="PlanFunc">充值</text></view>
</view>
<swiper class="gift-swiper" :indicator-dots="true" :duration="200" indicator-color="#dbdbdb" indicator-active-color="#999">
<swiper-item v-for="(group, num) in giftList" :key="num">
<view class="gift__cells">
<block v-for="(item, index) in group" :key="index">
<view v-if="item.gift_id!=isGift" class="giftitem" @tap="chooseGift(item)">
<view class="giftitem-rect">
<image class="giftimg" :src="item.file_path" mode="aspectFill" />
</view><text class="giftname">{{item.gift_name}}</text><text class="giftcoin">{{item.price}}{{giftName}}</text>
</view>
<view class="giftitem" v-if="item.gift_id==isGift">
<view class="giftitem_active">
<view class="giftitem-rect">
<image class="giftimg_active" :src="item.file_path" mode="aspectFill" />
</view>
<text class="giftcoin">{{item.price}}{{giftName}}</text>
<text class="btntext" @tap="sendGift(item)">发送</text>
</view>
</view>
</block>
</view>
</swiper-item>
</swiper>
</view>
</scroll-view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
showGiftView: false,
/*是否打开充值*/
open_plan: false,
/*个人信息*/
userInfo:{},
isGift:0
}
},
props: ['giftName', 'giftList','room_id'],
methods: {
show() {
this.showGiftView = true;
this.getUser();
},
/*请求对象*/
getRequest(){
let self = this;
// #ifdef APP-PLUS
return getApp().globalData.vueObj;
// #endif
// #ifndef APP-PLUS
return self;
// #endif
},
/*获取用户信息*/
getUser() {
let self = this;
self.getRequest()._get('user.user/detail', {
}, function(res) {
self.userInfo=res.data.userInfo;
});
},
chooseGift(item){
this.isGift=item.gift_id
},
sendGift(item) {
let self = this;
console.log('发送礼物')
self.getRequest()._post(
'plus.live.room/send_gift',
{
room_id: self.room_id,
gift_id: item.gift_id
},
function(res) {
console.log(res)
uni.showToast({
title:res.msg
});
self.userInfo.gift_money = res.data.gift_money;
self.$emit('sendGift', item.gift_id + "," + res.data.gift_num);
}
);
},
PlanFunc(){
this.showGiftView = false;
this.$emit('openPlan');
},
close() {
this.showGiftView = false;
},
}
}
</script>
<style scoped>
.nlv_borT {
border-color: #ebebeb;
border-style: solid;
border-top-width: 1upx;
}
.wrapgift-mask {
background-color: #000;
opacity: .1;
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 201910;
}
.wrapgift-body {
overflow: hidden;
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 201911;
}
.gift-head {
border-color: rgba(255, 255, 255, .3);
border-style: solid;
border-bottom-width: 1upx;
flex-direction: row;
align-items: center;
height: 100upx;
}
.gift-menu {
flex: 1;
flex-direction: row;
}
.gm-item {
color: #999;
font-size: 32upx;
margin-left: 40upx;
line-height: 100upx;
}
.gm-item-on {
color: #fff;
border-color: #ff0f33;
border-style: solid;
border-bottom-width: 2px;
}
.gift-coins {
color: #fff;
font-size: 28upx;
flex-direction: row;
align-items: center;
padding-right: 30upx;
}
.gc-coin {
color: #ffffff;
font-size: 25rpx;
}
.gc-num {
color: #feb719;
font-size: 12px;
}
.gc-recharge {
color: #ff0f33;
font-size: 12px;
margin-left: 30upx;
}
.wrap_giftlist {
background-color: rgba(31, 37, 62, 1);
border-top-left-radius: 12px;
border-top-right-radius: 12px;
height: 700upx;
position: relative;
}
.gift-swiper {
flex: 1;
}
.gift__cells {
flex-direction: row;
flex-wrap: wrap;
}
.giftitem {
flex-direction: column;
align-items: center;
justify-content: center;
margin-top: 20upx;
width: 186upx;
}
.giftitem-rect {
align-items: center;
justify-content: center;
height: 150upx;
width: 150upx;
position: relative;
}
.giftimg {
height: 100rpx;
width: 100rpx;
}
.giftimg_active{
height: 100rpx;
width: 100rpx;
transform: scale(1.2);
}
.giftname {
color: #fff;
font-size: 30upx;
}
.giftcoin {
color: rgba(255, 255, 255, .3);
font-size: 22upx;
margin-top: 2px;
}
.sendbtn{
}
.btntext{
width: 150rpx;
height: 40rpx;
background-color: red;
border-radius: 20rpx;
text-align: center;
padding: 0;
border-width: 0;
font-size: 22rpx;
color: #FFFFFF;
line-height: 40rpx;
}
.giftitem_active{
flex-direction: column;
align-items: center;
justify-content: center;
background-image: linear-gradient(to bottom, rgba(255,255,255,0), rgba(255,255,255,0.3));
border-radius: 20rpx;
}
.giftitem_active .giftcoin{
margin-top: -6rpx;
margin-bottom: 6rpx;
}
</style>

View File

@ -0,0 +1,217 @@
<template>
<view class="wrap__giftPanel" v-if="popupVisible">
<view class="wrapgift-mask" @tap="close"></view>
<view class="pop__ui_child anim-footer">
<div class="progress-bar" v-if="showSlider" @tap.stop="">
<slider :value="value" activeColor="#f72b6c" backgroundColor="#FFFFFF" block-color="#FFFFFF" @change="sliderChange"
:min="0" :max="9" show-value />
</div>
<div class="more-box" @tap.stop="">
<div class="more-list" :class="{'more-list-active': activeIndex == 0}" @tap="setBeauty">
<!-- #ifndef APP-PLUS -->
<text class="icon iconfont icon-meiyan i-btntool more-icont"></text>
<!-- #endif -->
<!-- #ifdef APP-PLUS -->
<text class="icon iconfont icon-meiyan i-btntool more-icont">&#58972;</text>
<!-- #endif -->
<text class="f28 white mt20">美颜</text>
</div>
<div class="more-list" :class="{'more-list-active': activeIndex == 1}" @tap="setWhiteness">
<!-- #ifndef APP-PLUS -->
<text class="icon iconfont icon-meibai i-btntool more-icont"></text>
<!-- #endif -->
<!-- #ifdef APP-PLUS -->
<text class="icon iconfont icon-meibai i-btntool more-icont">&#58938;</text>
<!-- #endif -->
<text class="f28 white mt20">美白</text>
</div>
<div class="more-list" :class="{'more-list-active': activeIndex == 2}" @tap="setDevice">
<!-- #ifndef APP-PLUS -->
<text class="icon iconfont icon-iconset0243 i-btntool more-icont"></text>
<!-- #endif -->
<!-- #ifdef APP-PLUS -->
<text class="icon iconfont icon-iconset0243 i-btntool more-icont">&#59022;</text>
<!-- #endif -->
<text class="f28 white mt20">相机切换</text>
</div>
</div>
</view>
</view>
</template>
<script>
export default {
data() {
return {
popupVisible: false,
activeIndex: -1,
// 进度条
max: 5,
min: 0,
progressVal: 0,
beauty: 9,
whiteness: 9,
device_position: 'front',
value: 9,
showSlider: false
}
},
beforeCreate() {
// #ifdef APP-PLUS
const domModule = weex.requireModule('dom')
domModule.addRule('fontFace', {
fontFamily: "iconfont",
'src': "url('"+getApp().globalData.vueObj.font_url+"')"
});
// #endif
},
methods: {
show() {
this.popupVisible = true;
},
/*改变*/
sliderChange(e) {
console.log(e);
this.value = e.detail.value;
if (this.activeIndex == 0) {
uni.setStorageSync('beauty', this.value);
this.$emit('liveSet', {
type: 'beauty',
value: this.value
});
} else {
uni.setStorageSync('whiteness', this.value);
this.$emit('liveSet', {
type: 'whiteness',
value: this.value
});
}
},
setBeauty() {
this.activeIndex = 0;
let beauty = uni.getStorageSync('beauty');
if (beauty) {
this.value = beauty;
} else {
this.value = this.beauty;
}
this.showSlider = true;
},
setWhiteness() {
this.activeIndex = 1;
let whiteness = uni.getStorageSync('whiteness');
if (whiteness) {
this.value = whiteness;
} else {
this.value = this.whiteness;
}
this.showSlider = true;
},
setDevice() {
this.$emit('switchCamera');
},
close() {
this.popupVisible = false;
},
}
}
</script>
<style scoped>
.iconfont {
font-family: iconfont;
}
.nlv_borT {
border-color: #ebebeb;
border-style: solid;
border-top-width: 1upx;
}
.wrapgift-mask {
background-color: #000;
opacity: .1;
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 201910;
}
.pop__ui_child {
background-color: #fbfbfb;
border-top-left-radius: 12px;
border-top-right-radius: 12px;
font-size: 14px;
overflow: hidden;
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 201911;
}
.more-box {
background-color: #2a2634;
width: 750rpx;
height: 350rpx;
position: fixed;
bottom: 0;
border-top-left-radius: 16rpx;
border-top-right-radius: 16rpx;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
padding: 0 20rpx;
z-index: 9999;
}
.more-list {
display: flex;
flex-direction: column;
justify-content: center;
flex: 1;
align-items: center;
padding: 50rpx 0;
}
.more-icont {
font-size: 76rpx;
}
.more-list-active {
border-width: 1rpx;
border-color: #ea4678;
border-style: solid;
border-radius: 16rpx;
}
.Progress {
background-color: rgba(0, 0, 0, 0.3);
/* opacity: 0.3; */
height: 100rpx;
width: 700rpx;
position: fixed;
bottom: 370rpx;
border-radius: 16rpx;
left: 25rpx;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
padding: 0 30rpx;
}
.progress-bar {
position: fixed;
bottom: 360rpx;
width: 750rpx;
justify-content: center;
}
.wrap__giftPanel {
z-index: 100;
}
</style>

View File

@ -0,0 +1,198 @@
<template>
<view v-if="popupVisible" class="popup-footer">
<view class="pop__ui_panel">
<view class="pop__ui_mask" @tap="close"></view>
<view class="pop__ui_child anim-footer" @tap.stop="">
<view class="pop__ui_body">
<view class="wrap_commentPanel">
<view class="wrap_cmtFoot" :style="'bottom:' +inputBottom+'px;'">
<view class="wrap__editorPanel uni_borT uni__editorPanel">
<view class="wrap_editor uni_editor">
<input class="editor" auto-focus="true" value="" v-model="content" :adjust-position="false" confirm-type="send"
@confirm="sendTextMsg()" placeholder="说点什么..." @focus="inputFocus" @blur="inputBlur" />
</view>
<view class="uni_editor_btn" @tap="emojiShow=!emojiShow;">
<text class="icon iconfont icon-biaoqing"></text>
</view>
<view class="uni_editor_btn btn_submit uni__btn-primary bg_linear2" @tap="sendTextMsg">
<text class="icon iconfont icon-fasong"></text>
</view>
</view>
<view class="bc-white" v-show="emojiShow">
<swiper class="slider">
<swiper-item v-for="(item, key) in emojiData" :key="key" class="slider-emoji" :class="[key==emojiData.length-1?'lastbox':'']">
<text v-for="(emoji, index) in item" :key="index" @click="selemoji(emoji)" class="slider-emoji-icon">{{ emoji }}</text>
</swiper-item>
</swiper>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
const emoji = require('./emoji.js');
import uniLoadMore from '@/components/uni-load-more.vue';
import utils from '@/common/utils.js'
export default {
components: {
uniLoadMore
},
data() {
return {
popupVisible: false,
emojiShow:false,
inputBottom: 0,
inputheight:0,
content:''
}
},
beforeCreate() {
// #ifdef APP-PLUS
const domModule = weex.requireModule('dom')
domModule.addRule('fontFace', {
fontFamily: "nvueIcon",
'src': "url('../../../static/fonts/iconfont.ttf')"
});
// #endif
},
props:['emojiData'],
methods: {
selemoji(m) {
console.log(m);
this.content+=m;
},
show() {
this.popupVisible = true;
},
close() {
this.popupVisible = false;
},
/*评论*/
sendTextMsg() {
uni.hideKeyboard();
this.$emit('closeMsg', this.content);
this.content = '';
this.emojiShow=false;
this.popupVisible = false;
},
inputFocus(e) {
this.inputBottom= e.detail.height;
this.emojiShow=false;
console.log(e)
},
inputBlur() {
this.inputBottom = 0;
},
}
}
</script>
<style lang="scss" scoped>
.pop__ui_mask {
background-color: #000;
opacity: .1;
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 1000;
}
.pop__ui_child {
background-color: #fbfbfb;
border-top-left-radius: 12px;
border-top-right-radius: 12px;
font-size: 14px;
overflow: hidden;
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 1001;
}
.pop__ui_head {
border-style: solid;
border-color: #ebebeb;
border-bottom-width: 1upx;
font-size: 28upx;
font-weight: 700;
padding: 30upx;
text-align: center;
}
.iconfont {
font-family: nvueIcon;
}
.wrap_commentPanel {
flex-direction: column;
height: 11upx;
}
.uni_borT {
border-color: #dbdbdb;
border-style: solid;
border-top-width: 1upx;
}
.wrap__editorPanel {
flex-direction: row;
align-items: flex-end;
background-color: #fff;
padding: 20upx 30upx;
}
.wrap_editor {
flex: 1;
overflow: hidden;
}
.editor {
font-size: 14px;
line-height: 1.2;
}
.wrap_cmtFoot {
position: fixed;
left: 0;
right: 0;
z-index: 201911;
}
.uni__editorPanel .uni_editor {box-sizing: border-box; overflow: hidden;}
.uni_editor .editor {caret-color: #41a863; font-size: 28rpx; max-height: 200rpx; max-width: 100%; line-height: 1.2;}
.uni__editorPanel .uni_editor_btn {align-self: flex-end; justify-content: center; padding: 0 8rpx; height: 56rpx;}
.uni__editorPanel .uni_editor_btn .iconfont {color: #999; font-size: 50rpx;}
.uni__editorPanel .btn_submit {border-radius: 40rpx; font-size: 28rpx; margin-left: 10rpx; padding: 0 24rpx; line-height: 56rpx;}
.uni__editorPanel .btn_submit .iconfont {color: #999; font-size: 48rpx;}
.bc-white{
background-color: #FFFFFF;
}
.slider {
width: 750rpx;
height: 256rpx;
}
.slider-emoji {
width: 750rpx;
direction:ltr;
flex-direction: row;
flex-wrap: wrap;
justify-content:center;
align-content: flex-start;
align-items: stretch;
}
.slider-emoji-icon {
width: 105rpx;
text-align: center;
padding: 21rpx 0;
}
.lastbox{
justify-content: flex-start;
}
</style>

View File

@ -0,0 +1,251 @@
<template>
<view v-if="popupVisible" class="popup-footer">
<view class="pop__ui_panel">
<view class="pop__ui_mask" @tap="close"></view>
<view class="pop__ui_child anim-footer" @tap.stop="">
<div>
<div class="add-order-head d-b-c p20 f30">
<text class="f30">我的订单</text>
<image class="order-close" src="/static/live/close.png" mode="" @tap="close"></image>
</div>
<list class="add-product-list">
<cell class="add-product-item d-s-s" v-for="(item, index) in listData" :key="index">
<div class="add-product-picture">
<image class="add-product-picture-image" :src="item.product[0].image.file_path" mode="aspectFill"></image>
</div>
<div class="flex-1 ml20">
<div class="order-num">
<text class="f28 gray9">订单号:{{item.order_no}}</text>
</div>
<div class="order-title">
<div class="text-ellipsis-2">
<text class="f28">{{ item.product[0].product_name }}</text>
</div>
</div>
<div class="order-money">
<text class="rose f28" style="font-weight: 700;">¥{{item.product[0].product_price}}</text>
</div>
</div>
<div class="order-statu">
<text class="rose f28" v-if="item.is_settled==1">已结算</text>
<text class="rose f28" v-if="item.is_settled==0">未结算</text>
</div>
</cell>
</list>
</div>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
popupVisible: false,
/*总条数*/
total: 0,
/*没有更多*/
no_more: false,
/*商品列表*/
listData: [],
/*当前页面*/
page: 1,
/*一页多少条*/
list_rows: 10,
}
},
props: ['shop_supplier_id','room_id'],
methods: {
show() {
this.popupVisible = true;
this.start();
},
/*开始*/
start() {
this.loading = true;
this.no_more = false;
this.listData = [];
this.page = 1;
this.list_rows = 10;
this.getData();
},
/*获取数据*/
getData() {
let self = this;
let page = self.page;
let list_rows = self.list_rows;
self.loading = true;
getApp()._get(
'plus.live.RoomApply/orderList', {
page: page || 1,
list_rows: list_rows,
shop_supplier_id: self.shop_supplier_id,
room_id:self.room_id,
pay_status:20
},
function(res) {
self.loading = false;
self.listData = self.listData.concat(res.data.list.data);
self.last_page = res.data.list.last_page;
if (res.data.list.last_page <= 1) {
self.no_more = true;
}
}
);
},
/*可滚动视图区域到底触发*/
loadmoreFunc() {
let self = this;
self.bottomRefresh = true;
self.page++;
self.loading = true;
if (self.page > self.last_page) {
self.loading = false;
self.no_more = true;
return;
}
self.getData();
},
close() {
this.popupVisible = false;
this.$emit('closeOrder');
},
}
}
</script>
<style scoped>
.pop__ui_mask {
background-color: #000;
opacity: .1;
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 1000;
}
.pop__ui_child {
background-color: #fbfbfb;
border-top-left-radius: 12px;
border-top-right-radius: 12px;
font-size: 14px;
overflow: hidden;
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 1001;
}
.pop__ui_head {
border-style: solid;
border-color: #ebebeb;
border-bottom-width: 1upx;
font-size: 28upx;
font-weight: 700;
padding: 30upx;
text-align: left;
}
.product-head {
flex-direction: row;
}
.product-head-btn,
.add-product-head-btn {
height: 60rpx;
line-height: 60rpx;
background-color: #fff;
border-color: #f72b6c;
}
.add-product-list {
width: 750rpx;
height: 700rpx;
}
.add-product-container {
position: absolute;
width: 750rpx;
height: 900rpx;
right: 0;
bottom: 0;
left: 0;
border-radius: 16rpx 16rpx 0 0;
background-color: #FFFFFF;
transition: transform 0.2s ease;
transform: translate(0, 0);
}
.add-product-container-close {
transition: transform 0s ease;
transform: translate(0, 100%);
}
.add-product-head {
flex-direction: row;
}
.add-product-item {
flex-direction: row;
padding: 20rpx;
}
.add-product-picture {
width: 160rpx;
height: 160rpx;
}
.text-ellipsis-2 {
height: 70rpx;
}
.add-product-relation {
height: 60rpx;
line-height: 60rpx;
background-color: #51a938;
color: #fff;
border-color: #51a938;
font-size: 12px;
}
.add-product-relation-hover {
background-color: #abd7a2;
border-color: #abd7a2;
}
.order-close {
width: 40rpx;
height: 40rpx;
}
.add-order-head {
background-color: #eeeeee;
flex-direction: row;
}
.order-num {
font-size: 28px;
color: #ababab;
margin-bottom: 10rpx;
}
.order-title {
text-overflow: ellipsis;
overflow: hidden;
}
.order-money {
margin-top: 20rpx;
}
.add-product-picture-image {
width: 160rpx;
height: 160rpx;
}
</style>

View File

@ -0,0 +1,362 @@
<template>
<view class="wrap__giftPanel" v-if="showPlanView">
<view class="wrapgift-mask" @tap="close"></view>
<scroll-view class="wrapgift-body">
<div>
<div class="plan-box">
<div class="gift-container-head plan-box-head">
<text class="f30">{{giftName}}</text>
<text class="f30 yellow">{{userInfo.gift_money}}</text>
</div>
<div class="plan-cells">
<div :class="choose_id==item.plan_id?'active_border':'plan-cell-list'"
v-for="(item,index) in planList" :key="index" @tap="chooseplan(item)">
<div class="plan-list-title">
<text class="rose f30">{{item.real_money}}</text><text class="f28">{{giftName}}</text>
</div>
<div class="plan-list-rmb"><text class="f30 gray9">{{item.money}}元</text></div>
</div>
</div>
<div class="w100">
<button class="pan_btn" @click="submit"><text class="white">立即充值</text></button>
</div>
<div class="plan-xieyi">
<!-- <text class="f28">充值代表已阅读并同意</text> <text class="f28 yellow">《用户充值协议》</text> -->
</div>
</div>
</div>
</scroll-view>
</view>
</template>
<script>
import {
pay
} from '@/common/pay.js';
export default {
data() {
return {
showPlanView: false,
/*是否打开充值*/
open_plan: false,
/*个人信息*/
userInfo: {},
/*礼物币名称*/
planList: [],
/*10余额20微信支付*/
payType: 20,
choose_id: 0
}
},
props: ['giftName'],
beforeCreate() {
// #ifdef APP-PLUS
const domModule = weex.requireModule('dom')
domModule.addRule('fontFace', {
fontFamily: "iconfont",
'src': "url('" + getApp().globalData.vueObj.font_url + "')"
});
console.log(getApp().globalData.vueObj.font_url);
// #endif
},
methods: {
show() {
this.showPlanView = true;
this.getUser();
this.getPlan();
},
/*请求对象*/
getRequest() {
let self = this;
// #ifdef APP-PLUS
return getApp().globalData.vueObj;
// #endif
// #ifndef APP-PLUS
return self;
// #endif
},
/*获取用户信息*/
getUser() {
let self = this;
self.getRequest()._get('user.user/detail', {}, function(res) {
self.userInfo = res.data.userInfo;
});
},
/*获取礼物类别*/
getPlan() {
let self = this;
self.getRequest()._get('plus.live.plan/lists', {}, function(res) {
self.planList = res.data.list;
});
},
chooseplan(item) {
this.choose_id = item.plan_id;
},
/*充值*/
submit() {
let self = this;
uni.showLoading({
title: '加载中'
});
self.getRequest()._post('plus.live.plan/submit', {
plan_id: self.choose_id
}, function(result) {
getApp().gotoPage('/pages/order/cashier?order_id=' + result.data.order_id+ '&order_type=30');
});
},
/**
* 显示失败提示框
*/
showError(msg, callback) {
uni.showModal({
title: '友情提示',
content: msg,
showCancel: false,
success: function(res) {
callback && callback();
}
});
},
/**
* 显示失败提示框
*/
showSuccess(msg, callback) {
uni.showModal({
title: '友情提示',
content: msg,
showCancel: false,
success: function(res) {
callback && callback();
}
});
},
changeType(type) {
this.payType = type;
},
close() {
this.showPlanView = false;
this.$emit('closePlan');
},
}
}
</script>
<style scoped>
.iconfont {
font-family: iconfont;
}
.nlv_borT {
border-color: #ebebeb;
border-style: solid;
border-top-width: 1upx;
}
.wrapgift-mask {
background-color: #000;
opacity: .1;
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 1000;
}
.wrapgift-body {
overflow: hidden;
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 1001;
}
.gift-container-head {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
padding: 20rpx;
}
.chongzhi {
height: 70rpx;
line-height: 70rpx;
}
.plan-box {
background-color: #FFFFFF;
border-top-left-radius: 20rpx;
border-top-right-radius: 20rpx;
/* height: 720rpx; */
}
.plan-cells {
width: 750rpx;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-start;
padding-top: 0;
}
.plan-cell-list {
display: flex;
flex-direction: column;
width: 225rpx;
margin: 0 10rpx 20rpx;
align-items: center;
justify-content: center;
background-color: #efefef;
padding: 30rpx 0;
border-color: #FFFFFF;
border-style: solid;
border-width: 1px;
border-radius: 5rpx;
}
.plan-list-title {
display: flex;
flex-direction: row;
align-items: center;
}
.plan-list-rmb {
margin-top: 10rpx;
}
.plan-box-head {
display: flex;
flex-direction: row;
justify-content: flex-start;
}
.plan-head-title {
margin-left: 200rpx;
padding: 10rpx 0;
}
.plan-xieyi {
text-align: center;
padding: 30rpx 0;
display: flex;
flex-direction: row;
justify-content: center;
}
.plan-xieyi {
text-align: center;
padding: 30rpx 0;
display: flex;
flex-direction: row;
justify-content: center;
}
.paypop {
position: absolute;
top: 0;
z-index: 1002;
width: 750rpx;
height: 600rpx;
right: 0;
left: 0;
display: flex;
align-items: center;
justify-content: center;
}
.paypop-cont {
background-color: #FFFFFF;
border-radius: 16rpx;
display: flex;
align-items: flex-start;
justify-content: flex-start;
flex-direction: column;
width: 750rpx;
padding-bottom: 20rpx;
}
.paypop-list {
width: 750rpx;
padding: 30rpx;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
border-bottom: 1px solid #f6f6f6;
box-sizing: border-box;
}
.pay-body {
display: flex;
flex: 1;
flex-direction: row;
justify-content: flex-start;
}
.icon-weixin {
color: #04BE01;
}
.icon-yue1 {
color: #edde89;
}
.icon-icon_xianshi-xian:before {
content: "\e658";
}
.icon-danxuanxuanzhong:before {
content: '\e623';
}
.icon-xuanze-active {
color: #55bb36;
}
.w100 {
width: 750rpx;
}
.pan_btn {
width: 695rpx;
height: 85rpx;
line-height: 85rpx;
color: #FFFFFF;
font-size: 28rpx;
text-align: center;
background-color: #fc3e5a;
border-radius: 5rpx;
overflow: hidden;
cursor: pointer;
text-decoration: none;
position: relative;
display: block;
border-width: 0;
margin-top: 0;
margin-bottom: 0;
margin-left: 27.5rpx;
margin-right: auto;
padding-left: 14px;
padding-right: 14px;
box-sizing: border-box;
}
.active_border {
display: flex;
flex-direction: column;
width: 225rpx;
margin: 0 10rpx 20rpx;
align-items: center;
justify-content: center;
background-color: #efefef;
padding: 30rpx 0;
border-color: #fc3e5a;
border-style: solid;
border-width: 1px;
border-radius: 5rpx;
}
</style>

View File

@ -0,0 +1,221 @@
<template>
<view v-if="popupVisible" class="popup-footer">
<view class="pop__ui_panel">
<view class="pop__ui_mask" @tap="close"></view>
<view class="pop__ui_child anim-footer" @tap.stop="">
<div>
<div class="add-product-head p20 f30">
<text class="f30">礼物排行</text>
</div>
<scroll-view scroll-y="true" style="height: 700rpx;">
<list class="add-product-list" :loadmoreoffset="10"
@loadmore="loadmoreFunc" v-if="listData.length > 0">
<cell class="add-product-item d-s-s" v-for="(item, index) in listData" :key="index">
<text class="gift-num ml20 white f26 fir" v-if="index==0">{{index+1}}</text>
<text class="gift-num ml20 white f26 sec" v-if="index==1">{{index+1}}</text>
<text class="gift-num ml20 white f26 thr" v-if="index==2">{{index+1}}</text>
<text class="gift-num ml20 white f26" v-if="index!=0&&index!=1&&index!=2">{{index+1}}</text>
<view>
<image class="add-product-picture-image ml20" :src="item.user.avatarUrl" mode="aspectFill"></image>
</view>
<text class="user-name f30 ml20">{{ item.user.nickName }}</text>
<text class="rose f30 f-w mr20 red mt30">+{{item.gift_num}}</text>
</cell>
</list>
<div class="gift-null" v-if="listData.length <= 0 &&listData!=''">
<text class="f32">暂无记录</text>
</div>
</scroll-view>
</div>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
popupVisible: false,
/*底部加载*/
loading: true,
/*没有更多*/
no_more: false,
/*商品列表*/
listData: [],
/*当前页面*/
page: 1,
/*一页多少条*/
list_rows: 10,
}
},
props: ['room_id'],
methods: {
/*请求对象*/
getRequest(){
let self = this;
// #ifdef APP-PLUS
return getApp().globalData.vueObj;
// #endif
// #ifndef APP-PLUS
return self;
// #endif
},
show() {
this.popupVisible = true;
this.getRank();
},
/*开始*/
getRank() {
this.loading = true;
this.no_more = false;
this.listData = [];
this.page = 1;
this.list_rows = 10;
this.getData();
},
/*获取数据*/
getData() {
let self = this;
let page = self.page;
let list_rows = self.list_rows;
console.log(self.room_id);
self.getRequest()._get(
'plus.live.room/user_gift',
{
page: page || 1,
list_rows: list_rows,
room_id:self.room_id
},
function(res) {
self.loading = false;
self.listData = self.listData.concat(res.data.list.data);
self.last_page = res.data.list.last_page;
if (res.data.list.last_page <= 1) {
self.no_more = true;
}
}
);
},
/*可滚动视图区域到底触发*/
loadmoreFunc() {
let self = this;
self.bottomRefresh = true;
self.page++;
self.loading = true;
if (self.page > self.last_page) {
self.loading = false;
self.no_more = true;
return;
}
self.getData();
},
close() {
this.popupVisible = false;
},
}
}
</script>
<style scoped>
.pop__ui_mask {
background-color: #000;
opacity: .1;
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 1000;
}
.pop__ui_child {
background-color: #fbfbfb;
border-top-left-radius: 12px;
border-top-right-radius: 12px;
font-size: 14px;
overflow: hidden;
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 9999;
}
.pop__ui_head {
border-style: solid;
border-color: #ebebeb;
border-bottom-width: 1upx;
font-size: 28upx;
font-weight: 700;
padding: 30upx;
text-align: left;
}
.add-product-head {
background-color: #eeeeee;
flex-direction: row;
}
.add-product-list {
width: 750rpx;
height: 700rpx;
}
.add-product-item {
display: flex;
flex-direction: row;
align-items: center;
border-bottom-width: 1px;
border-bottom-color: #F6F6F6;
border-bottom-style: solid;
padding: 15rpx 0;
}
.gift-num {
width: 50rpx;
height: 50rpx;
display: flex;
justify-content: center;
align-items: center;
border-radius: 50rpx;
background-color: #e3416d;
text-align: center;
line-height: 50rpx;
margin-top: 10rpx;
}
.add-product-picture-image {
width: 100rpx;
height: 100rpx;
border-radius: 50%;
}
.user-name {
display: flex;
flex: 1;
margin-top: 30rpx;
}
.gift-null {
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 600rpx;
}
.fir{
background-color: #df372a;
}
.sec{
background-color: #ff721b;
}
.thr{
background-color: #e4a347;
}
</style>

View File

@ -0,0 +1,550 @@
<template>
<view>
<block v-if="is_replay">
<view class="video-detail">
<video id="myVideo" :src="replay_url" :autoplay="true" :loop="true" :controls="false" :show-fullscreen-btn="false"
:show-play-btn="false" :show-center-play-btn="false" object-fit="cover" :style="{height: winHeight, width: winWidth}"
@error="videoErrorCallback"></video>
</view>
</block>
<!-- #ifdef APP-PLUS -->
<block v-if="role == 'audience' && player_url != ''">
<video
id="myVideo"
:src="player_url"
:autoplay="true"
:loop="true"
:controls="false"
:show-fullscreen-btn="false"
:show-play-btn="false"
:show-center-play-btn="false"
:auto-pause-if-navigate="false"
:auto-pause-if-open-native="false"
object-fit="cover"
:style="{height: winHeight, width: winWidth}"
></video>
</block>
<!-- #endif -->
<!-- #ifndef APP-PLUS -->
<block v-if="role == 'audience' && player_url != ''">
<live-player id="livePlayer" :picture-in-picture-mode="picture_mode" :src="player_url" autoplay="true" mode="RTC" object-fit="fillCrop" :style="{height: winHeight, width: winWidth}"
></live-player>
</block>
<!-- #endif -->
<block v-if="role == 'broadcaster'">
<live-pusher id="livePusher1" ref="livePusher1" class="livePusher" :url="mainPusherInfo_url" mode="RTC"
enable-camera="true" enable-mic="true" auto-focus="true" aspect="9:16" objectFit="fill"
max-bitrate="500" min-bitrate="200" waiting-image="../../../static/temporarily.jpg" :beauty="beauty" :whiteness="whiteness"
:style="{height: winHeight, width: winWidth}" @statechange="recorderStateChange" @netstatus="recorderNetChange"></live-pusher>
</block>
</view>
</template>
<script>
const AgoraMiniappSDK = require("../../lib/mini-app-sdk-production.js");
const RTMClient = require('../../lib/agora-rtm.js');
export default {
data() {
return {
RTMClient: null,
/*加载中*/
loading_login: false,
/*推流对象*/
pusherContext: null,
/*拉流对象*/
playerContext: null,
player_url: '',
mainPusherInfo_url: '',
room_id: '',
/*发送消息*/
TextMsg: '',
/*是否打开礼物*/
open_gift: false,
/*评论*/
commentsList: [],
/*礼物*/
giftList: [],
/*是否打开商品列表*/
open_products: false,
/*当前讲解商品ID*/
explain_product_id: '',
/*当前讲解商品*/
explain_product: null,
/*是否显示更多功能*/
open_more: false,
/*是否美颜*/
beauty: 5,
/*美白*/
whiteness: 5,
/*前置后置*/
device_position: 'front',
/*打开分享*/
open_share: false,
/*分享参数*/
param_share: {},
/*分享图片*/
qrcode: null,
/*获取观看人数*/
showNumTimer: null,
/*是否点赞*/
is_click_digg: false,
// 房间详情
roomDetail: {},
// 用户信息
userInfo: {},
// RTC房间频道
channel: '',
// 应用appid
appId: '',
// rtm客户端
rtm_client: null,
reconnectTimer: null,
// 0 - loading, 1 - ok, 2 - error
push_status: 'loading',
picture_mode: ["push", "pop"],
isCaster: false
};
},
props: ['winHeight', 'winWidth', 'role', 'is_replay', 'replay_url'],
methods: {
show(){
if(this.playerContext!=null){
this.playerContext.play();
}
if(this.pusherContext){
this.reconnect();
}
},
/*请求对象*/
getRequest(){
let self = this;
// #ifdef APP-PLUS
return getApp().globalData.vueObj;
// #endif
// #ifndef APP-PLUS
return self;
// #endif
},
start(roomDetail, userInfo) {
let self = this;
self.roomDetail = roomDetail;
self.userInfo = userInfo;
self.channel = 'channel_' + roomDetail.shop_supplier_id;
self.isCaster = self.role == 'broadcaster';
if (self.isCaster) {
let whiteness = uni.getStorageSync('whiteness');
if (whiteness) {
self.whiteness = whiteness;
}
let beauty = uni.getStorageSync('beauty');
if (beauty) {
self.beauty = beauty;
}
} else {
//观众
console.log('观众进入');
}
self.loginRoom();
},
/*直播间登录*/
loginRoom() {
let self = this;
uni.showLoading({
title: '正在进入'
});
self.getRequest()._get('plus.live.agora.api/login', {
room_id: self.roomDetail.room_id,
channel: self.channel,
isCaster: self.isCaster
}, function(res) {
self.appId = res.data.appId;
self.initAgoraChannel(res.data.userSign).then(url => {
console.log(`pushing ${url}`);
let ts = new Date().getTime();
self.mainPusherInfo_url = url;
if (self.isCaster) {
self.pusherContext = uni.createLivePusherContext('livePusher1', self);
setTimeout(function() {
console.log('创建 pusherContext app', self.pusherContext);
self.pusherContext.start();
self.loginIM();
}, 500);
// 同步数据
self.showNumTimer = setInterval(() => {
self.synRoomInfo();
}, 15000)
}
}).catch(e => {
console.log(`init agora client failed: ${e}`);
console.log(JSON.stringify(e));
uni.showToast({
title: `客户端初始化失败`,
icon: 'none',
duration: 5000
});
});
});
},
/**
* 初始化sdk推流
*/
initAgoraChannel: function(token) {
let self = this;
return new Promise((resolve, reject) => {
let client = new AgoraMiniappSDK.Client();
//subscribe stream events
self.subscribeEvents(client);
AgoraMiniappSDK.LOG.onLog = (text) => {
// callback to expose sdk logs
console.log(text);
};
// info:1 WARNING:2 ERROR:3 DEBUG:0
AgoraMiniappSDK.LOG.setLogLevel(1);
self.client = client;
client.setRole(self.role);
client.init(self.appId, () => {
console.log(`client init success`);
// pass key instead of undefined if certificate is enabled
client.join(token, self.channel, self.getRequest().getUserId(), () => {
console.log(`client join channel success`);
//and get my stream publish url
if (self.isCaster) {
client.publish(url => {
console.log(`client publish success`);
console.log('url=' + url);
resolve(url);
}, e => {
console.log(`client publish failed: ${e.code} ${e.reason}`);
reject(e)
});
} else {
resolve();
}
}, e => {
console.log(`: ${e.code} ${e.reason}`);
reject(e)
})
}, e => {
console.log(`client init failed: ${e} ${e.code} ${e.reason}`);
reject(e);
});
});
},
loginIM() {
let self = this;
self.getRequest()._get('plus.live.agora.api/rtmToken', {
channel: self.channel
}, function(res) {
self.rtm_client = new RTMClient(self.appId);
self.onChannelEvent();
// sdk连接状态
self.rtm_client.on('ConnectionStateChanged', (newState, reason) => {
console.log('The connection status', newState)
console.log('The reason for the state change', reason)
});
// 登录 RTM 系统
self.rtm_client.login(res.data.userSign, '' + self.getRequest().getUserId()).then(() => {
console.log('AgoraRTM client login success');
self.rtm_client.joinChannel(self.channel).then(() => {
console.log('join channel success');
// 发送通知
let msg = {
type: 'enter',
nickName: self.userInfo.nickName
};
self.sendMsg(JSON.stringify(msg));
if(self.isCaster){
// 直播开始
self.getRequest()._post(
'plus.live.room/set_status', {
room_id: self.roomDetail.room_id,
status: 101
},
function(res) {
// 开始录制
self.startRecord();
}
);
}
}).catch((err) => {
console.log('join channel failed', err)
});
}).catch(err => {
console.log('AgoraRTM client login failure', err);
});
});
},
/*获取直播间信息*/
synRoomInfo(e){
let self = this;
self.getRequest()._post(
'plus.live.room/syn_room',
{
room_id: self.roomDetail.room_id,
},
function(res) {
// 发送通知
let msg = {
type: 'views',
views: res.data.model.views,
digg_num: res.data.model.digg_num,
};
self.sendMsg(JSON.stringify(msg));
}
);
},
/**
* 注册stream事件
*/
subscribeEvents: function(client) {
let self = this;
/**
* sometimes the video could be rotated
* this event will be fired with ratotion
* angle so that we can rotate the video
* NOTE video only supportes vertical or horizontal
* in case of 270 degrees, the video could be
* up side down
*/
client.on("video-rotation", (e) => {
console.log(`video rotated: ${e.rotation} ${e.uid}`);
});
/**
* fired when new stream join the channel
*/
client.on("stream-added", e => {
let uid = e.uid;
console.log(`stream ${uid} added`);
/**
* subscribe to get corresponding url
*/
client.subscribe(uid, (url, rotation) => {
console.log(`stream ${uid} subscribed successful`);
console.log(url);
self.player_url = url;
self.loginIM();
}, e => {
console.log(`stream subscribed failed ${e} ${e.code} ${e.reason}`);
});
});
/**
* remove stream when it leaves the channel
*/
client.on("stream-removed", e => {
let uid = e.uid;
console.log(`stream ${uid} removed`);
});
/**
* when bad thing happens - we recommend you to do a
* full reconnect when meeting such error
* it's also recommended to wait for few seconds before
* reconnect attempt
*/
client.on("error", err => {
let errObj = err || {};
let code = errObj.code || 0;
let reason = errObj.reason || "";
console.log(`error: ${code}, reason: ${reason}`);
if (code === 501 || code === 904) {
self.reconnect();
}
});
/**
* there are cases when server require you to update
* player url, when receiving such event, update url into
* corresponding live-player, REMEMBER to update key property
* so that live-player is properly refreshed
* NOTE you can ignore such event if it's for pusher or happens before
* stream-added
*/
client.on('update-url', e => {
console.log(`update-url: ${JSON.stringify(e)}`);
});
},
onChannelEvent: function() {
let self = this;
// 频道消息
self.rtm_client.on('ChannelMessage', (message, memberId) => {
let object = {
uid: memberId,
message: message.text
}
console.log('message -----');
console.log(message);
if (memberId != self.getRequest().getUserId()) {
self.$emit('showMsg', message.text);
}
})
//频道成员进出通知
self.rtm_client.on('MemberJoined', (memberId) => {
console.log('memberId: ', memberId);
})
self.rtm_client.on('MemberLeft', (memberId) => {
console.log('memberId: ', memberId);
})
},
/** type消息类型 文本text,礼物gift,进入房间enter 观看人数views 点赞: digg
结束over 讲解: explain
*/
sendMsg(msg) {
let self = this;
self.rtm_client.sendChannel(msg).then(() => {
self.$emit('showMsg', msg);
}).catch(error => {
// 频道消息发送失败的处理逻辑
console.log('频道消息发送失败的处理逻辑');
console.log(error);
});
},
/*直播设置*/
liveSet(e) {
switch (e.type) {
case 'beauty':
this.beauty = e.value;
break;
case 'whiteness':
this.whiteness = e.value;
break;
case 'device_position':
this.device_position = e.value;
if (this.pusherContext != null) {
this.pusherContext.switchCamera({
type: e.value,
success: function(res) {
console.log('切换成功');
},
fail: function(err) {
console.log(err);
}
});
}
break;
}
},
/**
* reconnect when bad things happens...
*/
reconnect: function() {
let self = this;
uni.showToast({
title: '尝试恢复链接...',
icon: 'none',
duration: 5000
});
// always destroy client first
// *important* miniapp supports 2 websockets maximum at same time
// do remember to destroy old client first before creating new ones
self.client && self.client.destroy();
self.reconnectTimer = setTimeout(() => {
self.loginRoom();
}, 1 * 1000);
},
/**
* 推流状态更新回调
*/
recorderStateChange: function (e) {
console.log('live-pusher code: ' , e)
if (e.detail.code === -1307) {
//re-push
console.log('live-pusher stopped ---- error');
this.push_status = 'error';
}
if (e.detail.code === 1008) {
//started
console.log('live-pusher started');
if(this.push_status === "loading") {
this.push_status = 'ok';
}
}
},
recorderNetChange: function(e) {
//console.log('netstatus:' + JSON.stringify(e));
},
onMainError: function(e) {
var self = this;
console.log('onMainError called: ', e);
},
/*退出 type: auto:主动 over结束*/
exit: function(type) {
let self = this;
let url = '/pagesLive/live/index';
if (self.role == 'broadcaster') {
type = 'over';
// 通知其他人
let msg = {
type: 'over'
};
self.sendMsg(JSON.stringify(msg));
}
if(type == 'over'){
//直播结束页
url = '/pagesLive/live/live-over?room_id=' + self.roomDetail.room_id;
}
self.clear();
uni.redirectTo({
url: url
});
},
startRecord:function(){
let self = this;
// 请求开始录制
if(self.isCaster){
self.getRequest()._post('plus.live.agora.api/record_acquire', {
room_id: self.roomDetail.room_id
}, function(res) {
self.getRequest()._post('plus.live.agora.api/record_start', {
room_id: self.roomDetail.room_id
}, function(res) {
self.getRequest()._post('plus.live.agora.api/record_query', {
room_id: self.roomDetail.room_id
}, function(res) {
});
});
});
}
},
/*销毁*/
clear: function() {
let self = this;
try {
if (self.showNumTimer) {
clearInterval(self.showNumTimer);
self.showNumTimer = null;
}
if (self.playerContext) {
self.playerContext.stop();
self.playerContext = null;
}
if (self.pusherContext) {
self.pusherContext.stop();
self.pusherContext = null;
}
clearTimeout(this.reconnectTimer);
self.reconnectTimer = null;
if (self.isCaster) {
try {
self.client && self.client.unpublish();
} catch (e) {
console.log(`unpublish failed`);
console.log(e);
}
}
// rtm退出
self.client && self.client.leave();
// rtm退出
self.rtm_client && self.rtm_client.logout();
} catch (e) {
console.log(e);
}
}
}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,156 @@
<template>
<view class="wrap__giftPanel" v-if="popupVisible">
<view class="wrapgift-mask" @tap="close"></view>
<view class="pop__ui_child anim-footer">
<div class="more-box" @tap.stop="">
<div class="more-list" @tap="share">
<button class="icon iconfont icon-weixin i-btntool more-icont" open-type="share"></button>
<text class="f28 white mt20">分享微信好友</text>
</div>
<div class="more-list" @tap="getPoster">
<button class="icon iconfont icon-jingmeihaibao i-btntool more-icont"></button>
<text class="f28 white mt20">生成海报</text>
</div>
</div>
</view>
</view>
</template>
<script>
export default {
data() {
return {
popupVisible: false,
}
},
beforeCreate() {
// #ifdef APP-PLUS
const domModule = weex.requireModule('dom')
domModule.addRule('fontFace', {
fontFamily: "nvueIcon",
'src': "url('../../../static/fonts/iconfont.ttf')"
});
// #endif
},
methods: {
show() {
this.popupVisible = true;
},
getPoster(){
this.$emit('livePoster');
},
close() {
this.popupVisible = false;
},
share(){
},
}
}
</script>
<style scoped>
.iconfont {
font-family: nvueIcon;
}
.nlv_borT {
border-color: #ebebeb;
border-style: solid;
border-top-width: 1upx;
}
.wrapgift-mask {
background-color: #000;
opacity: .1;
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 201910;
}
.pop__ui_child {
background-color: #fbfbfb;
border-top-left-radius: 12px;
border-top-right-radius: 12px;
font-size: 14px;
overflow: hidden;
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 201911;
}
.more-box {
background-color: #2a2634;
width: 750rpx;
height: 350rpx;
position: fixed;
bottom: 0;
border-top-left-radius: 16rpx;
border-top-right-radius: 16rpx;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
padding: 0 20rpx;
z-index: 9999;
}
.more-list {
display: flex;
flex-direction: column;
justify-content: center;
flex: 1;
align-items: center;
padding: 50rpx 0;
}
.more-icont {
font-size: 76rpx;
}
.more-list-active {
border-width: 1rpx;
border-color: #ea4678;
border-style: solid;
border-radius: 16rpx;
}
.Progress {
background-color: rgba(0, 0, 0, 0.3);
/* opacity: 0.3; */
height: 100rpx;
width: 700rpx;
position: fixed;
bottom: 370rpx;
border-radius: 16rpx;
left: 25rpx;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
padding: 0 30rpx;
}
.progress-bar {
position: fixed;
bottom: 360rpx;
width: 750rpx;
justify-content: center;
}
.wrap__giftPanel {
z-index: 100;
}
.icon-weixin{
color: #04BE01;
background: none;
}
.icon-jingmeihaibao{
background: none;
}
</style>