307 lines
12 KiB
JavaScript
307 lines
12 KiB
JavaScript
/**
|
||
* 直播间混入组件
|
||
* 提供直播间相关的基本功能和数据管理
|
||
*/
|
||
const app = getApp();
|
||
import { isEmpty } from '@/common/js/common/common.js';
|
||
export default {
|
||
/**
|
||
* 组件内部数据
|
||
*/
|
||
data() {
|
||
return {
|
||
windowWidth: 0,
|
||
windowHeight: 0,
|
||
is_live_ended: false,
|
||
live_config: {}, // 直播间配置
|
||
live_data: {}, // 直播间数据
|
||
live_video_src: '',
|
||
is_loading: true,
|
||
like_show_imgs: [
|
||
'https://new.shopxo.vip/static/plugins/live/images/like/like1.png',
|
||
'https://new.shopxo.vip/static/plugins/live/images/like/like2.png',
|
||
'https://new.shopxo.vip/static/plugins/live/images/like/like3.png',
|
||
'https://new.shopxo.vip/static/plugins/live/images/like/like4.png',
|
||
'https://new.shopxo.vip/static/plugins/live/images/like/like5.png',
|
||
],
|
||
lastTapTime: 0, // 用于检测双击
|
||
lastTapPosition: { x: 0, y: 0 }, // 记录上次点击位置
|
||
lastLikeTime: 0, // 记录上次点赞时间,用于防抖
|
||
live_status: 0,
|
||
live_be_right_back_error: false,
|
||
load_timer: null, // 延时显示视频的定时器
|
||
retry_count: 0, // 重试计数器
|
||
live_room_reconnect_number: 0, // 直播间重连次数
|
||
live_room_reconnect_interval_time: 1, // 直播间重连间隔时间
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 页面加载时执行
|
||
* @param {Object} params 页面参数
|
||
*/
|
||
onLoad(params) {
|
||
// 调用公共事件方法
|
||
app.globalData.page_event_onload_handle(params);
|
||
// 设置参数
|
||
this.params = app.globalData.launch_params_handle(params);
|
||
},
|
||
|
||
/**
|
||
* 页面显示时执行
|
||
*/
|
||
onShow() {
|
||
// 调用公共事件方法
|
||
app.globalData.page_event_onshow_handle();
|
||
|
||
// 分享菜单处理
|
||
app.globalData.page_share_handle();
|
||
|
||
const data = uni.getWindowInfo();
|
||
this.windowWidth = data.windowWidth;
|
||
this.windowHeight = data.windowHeight;
|
||
|
||
this.init();
|
||
// 页面显示时,连接直播间socket, 避免用户切换到其他页面,再切换回来时,socket连接断开
|
||
if (this.$refs.liveContent) {
|
||
this.$refs.liveContent.socket_connect();
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 组件挂载完成后执行
|
||
*/
|
||
mounted() {
|
||
this.init();
|
||
},
|
||
|
||
methods: {
|
||
/**
|
||
* 初始化直播间数据
|
||
* 请求服务器获取直播间详情信息
|
||
*/
|
||
init() {
|
||
uni.showLoading({
|
||
title: '数据加载中...',
|
||
mask: true
|
||
});
|
||
uni.request({
|
||
url: app.globalData.get_request_url('detail', 'index', 'live'),
|
||
method: 'POST',
|
||
data: {
|
||
live_room_id: 1
|
||
},
|
||
dataType: 'json',
|
||
success: (res) => {
|
||
const new_data = res.data;
|
||
// 显示直播内容
|
||
this.is_loading = false;
|
||
// 判断是否有数据
|
||
if(new_data.code == 0) {
|
||
// 更新直播间数据
|
||
this.live_data = new_data.data;
|
||
// 直播间点赞图标
|
||
this.like_show_imgs = new_data.data.like_icon_list || [];
|
||
// 获取直播间视频信息
|
||
this.live_video_src = new_data.data.room_info.pull_flv_url || '';
|
||
// 直播间状态 (0离线, 1在线, 2离开, 3封禁)
|
||
this.live_status = new_data.data.room_info.status || 0;
|
||
// 直播间配置
|
||
const config = new_data.data.config || {};
|
||
this.live_config = config;
|
||
// 直播间重连次数
|
||
this.live_room_reconnect_number = config.live_room_reconnect_number || 0;
|
||
this.live_room_reconnect_interval_time = config.live_room_reconnect_interval_time || 1;
|
||
// 如果不存在拉流地址则认为直播已结束,避免因为报错导致的页面异常
|
||
// if (isEmpty(new_data.data.pull_flv_url)) {
|
||
// this.is_live_ended = true;
|
||
// }
|
||
} else if (new_data.code == -400) { // 没有登陆的跳转到登陆页
|
||
// 隐藏加载提示
|
||
uni.hideLoading();
|
||
if (app.globalData.is_login_check(res.data)) {
|
||
app.globalData.showToast(res.data.msg);
|
||
} else {
|
||
app.globalData.showToast(this.$t('common.sub_error_retry_tips'));
|
||
}
|
||
} else {
|
||
uni.showToast({
|
||
title: new_data.msg || '获取直播间信息失败',
|
||
icon: 'none'
|
||
});
|
||
this.is_live_ended = true;
|
||
// 隐藏加载提示
|
||
uni.hideLoading();
|
||
}
|
||
},
|
||
fail: (err) => {
|
||
// 隐藏加载提示
|
||
uni.hideLoading();
|
||
// 显示直播内容
|
||
this.is_loading = false;
|
||
}
|
||
});
|
||
},
|
||
|
||
/**
|
||
* 视频数据加载完成时触发
|
||
*/
|
||
loadedmetadata() {
|
||
// 隐藏加载提示
|
||
uni.hideLoading();
|
||
// 如果加载完成了,延迟2秒确定一下直播状态, 有的时候直播状态是正常的也加载成功了,但是获取不到视频流,需要确定一下没有执行error才算是真正的成功
|
||
this.load_timer = setTimeout(() => {
|
||
console.log('视频数据加载完成');
|
||
|
||
this.retry_count = 0;
|
||
// 直播状态为正常或者暂停直播了,才认为是正常的加载成功
|
||
if ([0, 1].includes(this.live_status)) {
|
||
// 如果重连的定时器还在运行中,则清除它
|
||
if (this.ended_timer) {
|
||
// 隐藏加载提示
|
||
clearTimeout(this.ended_timer);
|
||
}
|
||
this.live_be_right_back_error = false;
|
||
}
|
||
}, 2000);
|
||
},
|
||
/**
|
||
* 标记直播结束或者直播暂停
|
||
*/
|
||
ended() {
|
||
// 隐藏加载提示
|
||
uni.hideLoading();
|
||
// 如果加载定时器存在,则清除
|
||
if (this.load_timer) {
|
||
// 隐藏加载提示
|
||
clearTimeout(this.load_timer);
|
||
}
|
||
// 如果直播已结束,则返回
|
||
if (!this.is_live_ended) {
|
||
|
||
if (![1, 2].includes(this.live_status)) {
|
||
this.is_live_ended = true;
|
||
} else {
|
||
// 初始化重试计数器
|
||
if (this.retry_count === undefined) {
|
||
this.retry_count = 0;
|
||
}
|
||
// 如果历史定时器存在,则清除
|
||
if (this.ended_timer) {
|
||
// 隐藏加载提示
|
||
clearTimeout(this.ended_timer);
|
||
}
|
||
|
||
// 如果重试次数超过指定次数,则标记为真正结束
|
||
if (this.retry_count > this.live_room_reconnect_number) {
|
||
this.is_live_ended = true;
|
||
this.live_be_right_back_error = false;
|
||
// 重置计数器
|
||
this.retry_count = 0;
|
||
return;
|
||
}
|
||
|
||
// 增加重试计数
|
||
this.retry_count++;
|
||
// 暂停直播了或者继续直播了,则提示用户当前主播暂时离开
|
||
this.live_be_right_back_error = true;
|
||
// 延迟3秒后尝试重新连接
|
||
this.ended_timer = setTimeout(() => {
|
||
// 在定时结束后尝试重新连接
|
||
if (this.$refs.liveVideo) {
|
||
this.$refs.liveVideo.reload_video();
|
||
}
|
||
}, this.live_room_reconnect_interval_time * 1000);
|
||
}
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 返回上一页
|
||
*/
|
||
live_back() {
|
||
app.globalData.page_back_prev_event();
|
||
},
|
||
|
||
/**
|
||
* 处理鼠标双击事件
|
||
* @param {Event} event 鼠标事件对象
|
||
*/
|
||
handle_double_click(event) {
|
||
if (event.target.dataset.ignore) {
|
||
return;
|
||
}
|
||
// 防抖处理,200ms内只能触发一次
|
||
const currentTime = Date.now();
|
||
if (currentTime - this.lastLikeTime < 200) {
|
||
return;
|
||
}
|
||
|
||
this.lastLikeTime = currentTime;
|
||
|
||
if (this.$refs.fullScreenLikeEffect) {
|
||
this.$refs.fullScreenLikeEffect.add_like(event);
|
||
}
|
||
|
||
if (this.$refs.liveContent) {
|
||
this.$refs.liveContent.like_click(event);
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 处理触屏双击事件
|
||
* 检测用户在屏幕上的双击操作以触发点赞效果
|
||
* @param {Event} event 触摸事件对象
|
||
*/
|
||
handle_touch_end(event) {
|
||
if (event.target.dataset.ignore) {
|
||
return;
|
||
}
|
||
// 获取当前位置
|
||
let x, y;
|
||
if (event.changedTouches && event.changedTouches.length > 0) {
|
||
x = event.changedTouches[0].pageX;
|
||
y = event.changedTouches[0].pageY;
|
||
} else {
|
||
x = event.pageX || 0;
|
||
y = event.pageY || 0;
|
||
}
|
||
|
||
const currentTime = new Date().getTime();
|
||
const tapLength = currentTime - this.lastTapTime;
|
||
const distance = Math.sqrt(
|
||
Math.pow(x - this.lastTapPosition.x, 2) +
|
||
Math.pow(y - this.lastTapPosition.y, 2)
|
||
);
|
||
// 判断是否为双击 (300ms内且距离较近)
|
||
if (tapLength < 300 && tapLength > 0 && distance < 50) {
|
||
|
||
// 防抖处理,200ms内只能触发一次
|
||
if (currentTime - this.lastLikeTime < 200) {
|
||
this.lastTapTime = currentTime;
|
||
this.lastTapPosition = { x, y };
|
||
return;
|
||
}
|
||
|
||
this.lastLikeTime = currentTime;
|
||
|
||
if (this.$refs.fullScreenLikeEffect) {
|
||
this.$refs.fullScreenLikeEffect.add_like(event);
|
||
}
|
||
|
||
if (this.$refs.liveContent) {
|
||
this.$refs.liveContent.like_click(event);
|
||
}
|
||
}
|
||
this.lastTapTime = currentTime;
|
||
this.lastTapPosition = { x, y };
|
||
},
|
||
/**
|
||
* 接收直播状态
|
||
* @param {number} status 直播状态
|
||
*/
|
||
socket_live_status(status) {
|
||
this.live_status = status;
|
||
}
|
||
}
|
||
} |