store_id)) { $this->store_id = get_store_id(); } } public static function roomTimeoutClose($room_id, $addQueue = 1) { $room = LiveRoom::findOne($room_id); if($room->is_close == 1){ return; } if($room->off_time == 0){ return; } $store_id = $room->store_id; $self = new self(['store_id' => $store_id]); $timeout_off = $self->storeConf('timeout_off'); if($timeout_off){ if($addQueue){ queue_push(new \app\jobs\live\LivePublishDoneJob([ 'id' => $room_id, ]), $timeout_off * 60); }else{ if(time() - $room->off_time >= $timeout_off * 60){ $self->roomSaveKey($room_id, 'is_close', 1); } } } return [ 'code' => 0, 'msg' => '操作成功。', ]; } public static function roomNoticeBegin($user_id, $room_id, $addQueue = 1) { $room = LiveRoom::findOne($room_id); if($room->is_close == 1 || $room->is_delete == 1){ return; } if($room->start_time <= 0){ return; } $store_id = $room->store_id; $self = new self(['store_id' => $store_id]); $delay = $room->start_time - time() > 0 ? $room->start_time - time() : 0; if($addQueue){ $queueId = queue_push(new \app\jobs\live\LiveBeginJob([ 'room_id' => $room_id, 'user_id' => $user_id, ]), $delay); }else{ $anchor = LiveAnchor::findOne($room->anchor_id); NoticeSend::LiveBegin($user_id, $anchor, $room); } return [ 'code' => 0, 'msg' => '操作成功。', 'queueId' => $queueId, ]; } public static function roomRecordAdd($room_id, $uri) { $room = LiveRoom::findOne($room_id); if ($room) { if (empty($room->record)) { $room->record = json_encode([$uri]); } else { $record = json_decode($room->record, true); $record[] = $uri; $room->record = json_encode($record); } $room->save(); } return [ 'code' => 0, 'msg' => '操作成功。', ]; } public static function encodePath($anchor_id, $anchor_user_id, $room_id) { $path = '/' . $anchor_id . '_' . $anchor_user_id . '/' . $room_id . '_' . $anchor_id; return $path; } /** * @return array [room_id,anchor_id,anchor_user_id] */ public static function decodePath($appname, $stream) { list($anchor_id, $anchor_user_id) = explode('_', $appname); list($room_id) = explode('_', $stream); return [ 'room_id' => $room_id, 'anchor_id' => $anchor_id, 'anchor_user_id' => $anchor_user_id, ]; } /** * 播流地址 */ public function getPlayStream($anchor_id, $anchor_user_id, $room_id) { $config = $this->storeConf(); $filename = self::encodePath($anchor_id, $anchor_user_id, $room_id); $rtmp = $this->PrivateKeyA(time() + 600, 'rtmp://' . $config['domain_name'], $filename, $config['auth_main_key']); $m3u8 = $this->PrivateKeyA(time() + 600, 'http://' . $config['domain_name'], $filename . '.m3u8', $config['auth_main_key']); $flv = $this->PrivateKeyA(time() + 600, 'http://' . $config['domain_name'], $filename, $config['auth_main_key']) . '.flv'; return ['rtmp' => $rtmp, 'm3u8' => $m3u8, 'flv' => $flv]; } /** * 推流地址 */ public function getPushStream($anchor, $room) { $config = $this->storeConf(); $filename = self::encodePath($anchor['id'], $anchor['user_id'], $room['id']); $pushURl = $this->PrivateKeyA(time() + 600, 'rtmp://' . $config['push_flow'], $filename, $config['auth_main_key'], $config['push_flow_ext']); return $pushURl; } public function PrivateKeyA($time, $domain, $filename, $key, $ext = '') { $sstring = $filename . "-" . $time . "-0-0-" . $key; $md5 = md5($sstring); $auth_key = "auth_key=" . $time . "-0-0-" . $md5; if ($ext) { $url = $domain . $filename . "?" . $ext . '&' . $auth_key; } else { $url = $domain . $filename . "?" . $auth_key; } return $url; } public function storeConf($key = null) { $def = new LiveConfig(); $def->loadDefaultValues(); $attributes = $def->attributes; unset($attributes['store_id']); unset($attributes['id']); $conf = LiveConfig::findOne(['store_id' => $this->store_id]); return $conf ? ($key ? $conf[$key] : $conf) : $attributes; } public function storeConfSave($params = []) { $conf = LiveConfig::findOne(['store_id' => $this->store_id]); if (!$conf) { $conf = new LiveConfig(); } $conf->setAttributes($params, false); $conf->store_id = $this->store_id; if (!$conf->save()) { return [ 'code' => 1, 'msg' => '操作失败!' . array_shift($conf->getFirstErrors()), ]; } return [ 'code' => 0, 'msg' => '操作成功。', 'data' => $conf, ]; } public function anchorInfo($id) { $info = LiveAnchor::findOne($id); return [ 'code' => 0, 'data' => $info, ]; } public function anchorInfoByUserid($user_id) { $anchor = LiveAnchor::findOne(['user_id' => $user_id, 'is_delete' => 0, 'status' => 1]); if(!$anchor){ return [ 'code' => 1, 'msg' => '不是主播或状态异常', ]; } return [ 'code' => 0, 'data' => $anchor, ]; } public function anchorHome($user_id) { try { $anchor = $this->anchorInfoByUserid($user_id); if ($anchor['code']) { throw new \Exception($anchor['msg']); } return [ 'code' => 0, 'data' => $anchor['data'], ]; } catch (\Exception $e) { \Yii::error($e); return [ 'code' => 1, 'msg' => $e->getMessage() ]; } } public function anchorList($params = []) { try { $query = LiveAnchor::find()->where(['is_delete' => 0, 'store_id' => $this->store_id]); if (!empty($params['id'])) { $query->andWhere(['id' => $params['id']]); } if (!empty($params['is_push'])) { $query->andWhere(['is_push' => $params['is_push']]); } if (!empty($params['is_open'])) { $query->andWhere(['is_open' => $params['is_open']]); } if (!empty($params['is_recommen'])) { $query->andWhere(['is_recommen' => $params['is_recommen']]); } if (!empty($params['name'])) { $query->andWhere(['like', 'name', trim($params['name'])]); } if (!empty($params['cat_id'])) { $query->andWhere(['cat_id' => $params['cat_id']]); } if ($params['realname']) { $query->andWhere(['like', 'realname', $params['realname']]); } if ($params['mobile']) { $query->andWhere(['like', 'mobile', $params['mobile']]); } if (!empty($params['start_time'])) { $query->andWhere(['>=', 'created_at', strtotime($params['start_time'])]); } if (!empty($params['end_time'])) { $query->andWhere(['<=', 'created_at', strtotime($params['end_time']) + 86400]); } if ($params['user_mobile']) { $query->andWhere(['user_id' => User::find()->select('id')->where(['like', 'binding', $params['user_mobile']]) ]); } if ($params['user_name']) { $query->andWhere(['user_id' => User::find()->alias('u') ->leftJoin(['su' => SaasUser::tableName()], 'u.binding = su.mobile') ->select('u.id') ->where(['like', 'su.name', $params['user_name']]) ]); } $query->addOrderBy('id DESC'); $pagination = pagination_make($query); $cats = LiveCat::find()->where(['store_id' => $this->store_id])->indexBy('id')->all(); foreach ($pagination['list'] as &$item) { $item['cat_name'] = $cats[$item['cat_id']] ? $cats[$item['cat_id']]['name'] : '-'; $user = User::findOne($item['user_id']); $saasUser = SaasUser::findOne(['mobile' => $user['binding']]); // 做兼容 前端展示的saas_user的信息 将saas_user的头像昵称电话修改为user表的信息 $saasUser['avatar'] = $user['avatar_url']; $saasUser['name'] = $user['nickname']; $saasUser['mobile'] = $user['binding']; $item['user'] = $user; $item['saasUser'] = $saasUser; } return [ 'code' => 0, 'msg' => '操作成功', 'data' => $pagination, 'q' => $query->createCommand()->getRawSql(), ]; } catch (\Exception $e) { \Yii::error($e); return [ 'code' => 1, 'msg' => $e->getMessage() ]; } } public function anchorSave($params) { $t = \Yii::$app->db->beginTransaction(); try { $liveAnchor = $params['id'] ? LiveAnchor::findOne(['id' => $params['id'], 'store_id' => $this->store_id]) : new LiveAnchor(); if (empty($liveAnchor)) { throw new \Exception('参数错误' . $params['id']); } if (isset($this->store_id)) { $liveAnchor->store_id = $this->store_id; } if (isset($params['user_id'])) { $user = User::findOne($params['user_id']); if (empty($user)) { throw new \Exception('用户id错误。' . $params['user_id']); } $liveAnchor->user_id = $params['user_id']; } if (isset($params['name'])) { $liveAnchor->name = $params['name']; } if (isset($params['desc'])) { $liveAnchor->desc = $params['desc']; } $liveAnchor->status = isset($params['status']) ? int($params['status']) : 1; if (isset($params['cat_id'])) { $liveAnchor->cat_id = $params['cat_id']; } if (isset($params['realname'])) { $liveAnchor->realname = $params['realname']; } if (isset($params['mobile'])) { $liveAnchor->mobile = trim($params['mobile']); } if (isset($params['status_desc'])) { $liveAnchor->status_desc = trim($params['status_desc']); } if (!$liveAnchor->save()) { \Yii::error([__METHOD__, $liveAnchor->attributes]); throw new \Exception('保存失败。' . array_shift($liveAnchor->getFirstErrors())); } $t->commit(); return [ 'code' => 0, 'msg' => '操作成功!', 'data' => $liveAnchor, ]; } catch (\Exception $e) { \Yii::error($e); $t->rollBack(); return [ 'code' => 1, 'msg' => $e->getMessage() ]; } } /** * 修改字段(包括删除is_delete) * @param type $id * @param type $key * @param type $val * @return type * @throws \Exception */ public function anchorSaveKey($id, $key, $val) { try { if (!is_array($id)) { $id = explode(',', $id); } foreach ($id as $item) { $model = LiveAnchor::findOne($item); if (!$model) { throw new \Exception('参数错误' . $item); } $model->$key = $val; if (!$model->save()) { throw new \Exception('操作失败。' . $item . array_shift($model->getFirstErrors())); } } return [ 'code' => 0, 'msg' => '操作成功', ]; } catch (\Exception $e) { \Yii::error($e); return [ 'code' => 1, 'msg' => $e->getMessage() ]; } } public function catList($params = []) { try { $is_delete = 0; if ($params['is_delete'] == 1) { $is_delete = 1; } $query = LiveCat::find()->where(['is_delete' => $is_delete, 'store_id' => $this->store_id]); if (!empty($params['id'])) { $query->andWhere(['id' => $params['id']]); } if (!is_null($params['is_show']) && $params['is_show'] > -1) { $query->andWhere(['is_show' => $params['is_show']]); } if (!empty($params['name'])) { $query->andWhere(['like', 'name', trim($params['name'])]); } $query->orderBy('sort DESC, id DESC'); $pagination = pagination_make($query); return [ 'code' => 0, 'msg' => '操作成功', 'data' => $pagination, // 'q' => $query->createCommand()->getRawSql(), ]; } catch (\Exception $e) { \Yii::error($e); return [ 'code' => 1, 'msg' => $e->getMessage() ]; } } public function catSelectList($indexBy = 1) { $query = LiveCat::find()->where(['store_id' => $this->store_id]) ->select('id,name,is_show'); if ($indexBy) { $query->indexBy('id'); } $list = $query->orderBy('sort DESC, id DESC')->asArray()->all(); foreach ($list as &$item) { if (!$item['is_show']) { $item['name'] .= '(已隐藏)'; } } return [ 'code' => 0, 'msg' => '操作成功', 'data' => $list, ]; } public function catSave($params = []) { try { $model = $params['id'] ? LiveCat::findOne(['id' => $params['id'], 'store_id' => $this->store_id]) : new LiveCat(); if (empty($model)) { throw new \Exception('参数错误' . $params['id']); } $model->name = $params['name']; $model->sort = $params['sort'] ?: 0; $model->is_show = $params['is_show']; $model->store_id = $this->store_id; isset($params['pic_url']) && $model->pic_url = $params['pic_url']; if (!$model->save()) { \Yii::error([__METHOD__, $model->attributes]); throw new \Exception('保存失败。' . array_shift($model->getFirstErrors())); } return [ 'code' => 0, 'msg' => '操作成功!' ]; } catch (\Exception $e) { \Yii::error($e); return [ 'code' => 1, 'msg' => $e->getMessage() ]; } } /** * 修改字段(包括删除is_delete) * @param type $id * @param type $key * @param type $val * @return type * @throws \Exception */ public function catSaveKey($id, $key, $val) { try { if (!is_array($id)) { $id = explode(',', $id); } foreach ($id as $item) { $model = LiveCat::findOne($item); if (!$model) { throw new \Exception('参数错误' . $item); } $model->$key = $val; if (!$model->save()) { throw new \Exception('操作失败。' . $item . array_shift($model->getFirstErrors())); } } return [ 'code' => 0, 'msg' => '操作成功', ]; } catch (\Exception $e) { \Yii::error($e); return [ 'code' => 1, 'msg' => $e->getMessage() ]; } } public function goodsExtList($params = []) { try { $params['liveGoodsExt'] = 1; $params['mch'] = -1; return Goods::getList($params); } catch (\Exception $e) { \Yii::error($e); return [ 'code' => 1, 'msg' => $e->getMessage() ]; } } public function goodsExtSave($params = []) { try { if (!isset($params['id'])) { if (!empty($params['goods_id'])) { $goods_id = explode(',', $params['goods_id']); foreach ($goods_id as $goods_id_item) { $liveGoodsExtItem = LiveGoodsExt::findOne(['goods_id' => $goods_id_item, 'store_id' => $this->store_id, 'is_delete' => 0]) ?: new LiveGoodsExt(); $liveGoodsExtItem->store_id = $this->store_id; $liveGoodsExtItem->goods_id = $goods_id_item; if (!$liveGoodsExtItem->save()) { throw new \Exception('保存失败。' . array_shift($liveGoodsExtItem->getFirstErrors())); } } } } else { $model = LiveGoodsExt::findOne(['id' => $params['id'], 'store_id' => $this->store_id]); if (empty($model)) { throw new \Exception('参数错误' . $params['id']); } $model->store_id = $this->store_id; $model->goods_id = $params['goods_id']; if (!$model->save()) { \Yii::error([__METHOD__, $model->attributes]); throw new \Exception('保存失败。' . array_shift($model->getFirstErrors())); } } return [ 'code' => 0, 'msg' => '操作成功!' ]; } catch (\Exception $e) { \Yii::error($e); return [ 'code' => 1, 'msg' => $e->getMessage() ]; } } /** * 修改字段(包括删除is_delete) * @param type $id * @param type $key * @param type $val * @return type * @throws \Exception */ public function goodsExtSaveKey($id, $key, $val) { try { if (!is_array($id)) { $id = explode(',', $id); } foreach ($id as $item) { $model = LiveGoodsExt::findOne($item); if (!$model) { throw new \Exception('参数错误' . $item); } $model->$key = $val; if (!$model->save()) { throw new \Exception('操作失败。' . $item . array_shift($model->getFirstErrors())); } } return [ 'code' => 0, 'msg' => '操作成功', ]; } catch (\Exception $e) { \Yii::error($e); return [ 'code' => 1, 'msg' => $e->getMessage() ]; } } public function roomList($params = []) { try { $is_delete = 0; if ($params['is_delete'] == 1) { $is_delete = 1; } $query = LiveRoom::find()->where(['is_delete' => $is_delete, 'store_id' => $this->store_id]); if ($params['id']) { $query->andWhere(['id' => $params['id']]); } if (isset($params['has_record']) && $params['has_record'] > -1) { if($params['has_record']){ $query->andWhere(['!=', 'record', '']); }else{ $query->andWhere(['or', ['record' => null], ['record' => '']]); } } if (!empty($params['name'])) { $query->andWhere(['like', 'name', trim($params['name'])]); } if (isset($params['is_close']) && $params['is_close'] > -1) { $query->andWhere(['is_close' => $params['is_close']]); } if (!empty($params['pre_play_time'])) { $query->andWhere(['>', 'pre_play_time', 0]); } if ($params['anchor_is_recommen']) { $query->andWhere(['anchor_id' => LiveAnchor::find()->select('id')->where(['is_recommen' => 1])]); } if ($params['anchor_is_follow'] && $params['user_id']) { $query->andWhere(['anchor_id' => LiveFollow::find()->select('anchor_id')->where(['user_id' => $params['user_id']])]); } if ($params['anchor_id']) { $query->andWhere(['anchor_id' => $params['anchor_id']]); } if ($params['anchor_name']) { $query->andWhere(['anchor_id' => LiveAnchor::find()->select('id')->where(['like', 'name', $params['anchor_name']])]); } if ($params['anchor_realname']) { $query->andWhere(['anchor_id' => LiveAnchor::find()->select('id')->where(['like', 'realname', $params['anchor_realname']])]); } if ($params['anchor_mobile']) { $query->andWhere(['anchor_id' => LiveAnchor::find()->select('id')->where(['like', 'mobile', $params['anchor_mobile']])]); } if ($params['user_mobile']) { $query->andWhere(['anchor_id' => LiveAnchor::find()->alias('a') ->leftJoin(['u' => User::tableName()], 'a.user_id = u.id') ->select('a.id') ->where(['like', 'u.binding', $params['user_mobile']]) ]); } if ($params['user_name']) { $query->andWhere(['anchor_id' => LiveAnchor::find()->alias('a') ->leftJoin(['u' => User::tableName()], 'a.user_id = u.id') ->leftJoin(['su' => SaasUser::tableName()], 'u.binding = su.mobile') ->select('a.id') ->where(['like', 'su.name', $params['user_name']]) ]); } if ($params['cat_id']) { $query->andWhere(['anchor_id' => LiveAnchor::find()->select('id')->where(['cat_id' => $params['cat_id']])]); } $query->orderBy('id DESC'); $pagination = pagination_make($query); $cats = $this->catSelectList()['data']; $conf = $this->storeConf(); foreach ($pagination['list'] as &$item) { $item['count_comment'] = (int)LiveComment::find()->where(['room_id' => $item['id'], 'type' => 0])->count(); $item['anchor'] = LiveAnchor::findOne($item['anchor_id']); $item['user'] = User::findOne($item['anchor']['user_id']); $item['saasUser'] = SaasUser::findOne(['mobile' => $item['user']['binding']]); $item['cat_name'] = $cats[$item['anchor']['cat_id']]['name']; $item['push_url'] = $this->getPushStream($item['anchor'], $item); $item['play_url'] = $this->getPlayStream($item['anchor']['id'], $item['anchor']['user_id'], $item['id']); $item['record_url'] = []; if($item['record']){ $record = json_decode($item['record'], true); foreach($record as $_rec){ $item['record_url'][] = (stripos($conf['oss_endpoint'], 'http') === false ? 'https://' : '') . implode('/', [$conf['oss_endpoint'], $_rec]); } } } $template_id = \app\utils\Notice\NoticeAction::getSendTamplateId(['live_begin'], is_h5() ? 'wxaapi' : 'miapp'); return [ 'code' => 0, 'msg' => '操作成功', 'data' => $pagination, 'template_id' => $template_id, 'q' => $query->createCommand()->getRawSql(), ]; } catch (\Exception $e) { \Yii::error($e); return [ 'code' => 1, 'msg' => $e->getMessage() ]; } } //主播进入直播间 public function roomAnchorEnter($user_id = 0, $anchor_id = 0, $params = []) { try { $anchor = LiveAnchor::findOne($anchor_id); if($anchor['user_id'] != $user_id){ \Yii::error([__METHOD__, $user_id, $anchor_id]); throw new \Exception('参数错误。'); } if(!$anchor['is_open']){ \Yii::error([__METHOD__, $user_id, $anchor_id]); throw new \Exception('未开通直播。'); } $room = LiveRoom::find()->where(['anchor_id' => $anchor_id, 'is_close' => 0, 'store_id' => $this->store_id])->orderBy('id DESC')->limit(1)->one(); if (empty($room) && $params['create_new_live']) { $room = new LiveRoom(); $room->anchor_id = $anchor_id; $room->store_id = $this->store_id; $room->start_time = time(); $room->end_time = 0; isset($params['start_time']) && $room->pre_play_time = time(); isset($params['start_time']) && $room->start_time = $params['start_time']; isset($params['end_time']) && $room->end_time = $params['end_time']; isset($params['open_comment']) && $room->open_comment = $params['open_comment']; isset($params['open_good']) && $room->open_good = $params['open_good']; isset($params['open_share']) && $room->open_share = $params['open_share']; $room->name = $params['name'] ?? $anchor->name; $room->pic_url = $params['pic_url'] ?: \Yii::$app->request->hostInfo . \Yii::$app->request->baseUrl . '/web/v1/statics/clientImg/live/live_bg.png'; isset($params['desc']) && $room->desc = $params['desc']; isset($params['address']) && $room->address = $params['address']; if($room->start_time && $room->pre_play_time && $room->start_time - $room->pre_play_time > 86400 * 7){ \Yii::error([__METHOD__, $room->attributes]); throw new \Exception('开播时间距离预播时间超过7天。'); } if (!$room->save()) { \Yii::error([__METHOD__, $room->attributes]); throw new \Exception('保存失败。' . array_shift($room->getFirstErrors())); } // $room->push_url = $this->getPushStream($anchor, $room); // $room->save(); } return [ 'code' => 0, 'msg' => '操作成功!', 'data' => $room, 'push_url' => $this->getPushStream($anchor, $room), 'anchor' => $anchor, ]; } catch (\Exception $e) { \Yii::error($e); return [ 'code' => 1, 'msg' => $e->getMessage() ]; } } public function roomAnchorClose($room_id) { // return [ // 'code' => 0, // 'msg' => '操作成功!', // ]; return $this->roomSaveKey($room_id, 'is_close', 1); } //直播间添加商品 public function roomGoodsAdd($room_id, $goods_id = []) { if (!is_array($goods_id)) { $goods_id = explode(',', $goods_id); } $goods_id = trim(implode(',', $goods_id), ','); $model = LiveRoom::findOne($room_id); $model->goods_id = $goods_id; if (!$model->save()) { return [ 'code' => 1, 'msg' => '操作失败!' . array_shift($model->getFirstErrors()), ]; } return [ 'code' => 0, 'msg' => '操作成功', ]; } public function roomInfo($room_id = 0) { $room = LiveRoom::findOne($room_id); $anchor = LiveAnchor::findOne($room->anchor_id); $anchor_user = User::findOne($anchor['user_id']); $anchor_saasUser = SaasUser::findOne(['mobile' => $anchor_user['binding']]); $newRoom = null; if($room->is_close){ $newRoom = LiveRoom::find()->where(['anchor_id' => $anchor->id, 'is_close' => 0])->orderBy('id DESC')->limit(1)->one(); if($newRoom && $newRoom->id == $room->id){ unset($newRoom); } } return [ 'code' => 0, 'msg' => '操作成功', 'data' => $room, 'newRoom' => $newRoom, 'anchor' => $anchor, 'anchor_user' => $anchor_user, 'anchor_saasUser' => $anchor_saasUser, 'playStream' => $this->getPlayStream($anchor->id, $anchor->user_id, $room['id']), ]; } //用户进入直播间 public function roomUserEnter($room_id = 0, $user_id = 0) { $key = ['roomUserEnter', $room_id, $user_id]; if (!cache_lock($key, 3600)) { LiveRoom::updateAllCounters(['look_num' => 1], ['id' => $room_id]); } $user = User::findOne($user_id); $saasUser = SaasUser::findOne(['mobile' => $user['binding']]); $content = $saasUser['name'] . ' 进来了'; $this->commentAdd($room_id, $user_id, $content, LiveComment::TYPE_INFO); $template_id = \app\utils\Notice\NoticeAction::getSendTamplateId(['live_begin'], is_h5() ? 'wxaapi' : 'miapp'); $roomUserSubscribe = cache()->get(implode('_', ['roomUserSubscribe', $room_id, $user_id])) ? 1 : 0; return [ 'code' => 0, 'msg' => '操作成功', 'template_id' => $template_id, 'roomUserSubscribe' => $roomUserSubscribe, ]; } //点赞 public function roomUserGood($room_id, $user_id = 0) { $key = ['roomUserGood', $room_id, $user_id]; if (!cache_lock($key, 60)) { LiveRoom::updateAllCounters(['good_num' => 1], ['id' => $room_id]); $user = User::findOne($user_id); $saasUser = SaasUser::findOne(['mobile' => $user['binding']]); $content = $saasUser['name'] . ' 点赞了'; $this->commentAdd($room_id, $user_id, $content, LiveComment::TYPE_INFO); return [ 'code' => 0, 'msg' => '操作成功!', ]; } return [ 'code' => 1, 'msg' => '限制每分钟点赞一次!', ]; } //订阅 public function roomUserSubscribe($room_id, $user_id = 0) { $room = LiveRoom::findOne($room_id); $time = $room->start_time - time() > 0 ? $room->start_time - time() : 0; if (!cache_lock(implode('_', ['roomUserSubscribe', $room_id, $user_id]), $time + 3600) || !$time) { $sub = self::roomNoticeBegin($user_id, $room_id); \Yii::error([__METHOD__, $sub, $room_id, $user_id]); } return [ 'code' => 0, 'msg' => '操作成功!', ]; } /** * 修改字段(包括删除is_delete) * @param type $id * @param type $key * @param type $val * @return type * @throws \Exception */ public function roomSaveKey($id, $key, $val) { try { if (!is_array($id)) { $id = explode(',', $id); } foreach ($id as $item) { $model = LiveRoom::findOne($item); if (!$model) { throw new \Exception('参数错误' . $item); } $model->$key = $val; if (!$model->save()) { throw new \Exception('操作失败。' . $item . array_shift($model->getFirstErrors())); } } return [ 'code' => 0, 'msg' => '操作成功', ]; } catch (\Exception $e) { \Yii::error($e); return [ 'code' => 1, 'msg' => $e->getMessage() ]; } } public function roomDel($id) { try { $model = LiveRoom::findOne($id); if (!$model) { throw new \Exception('参数错误' . $id); } $model->is_close = 1; $model->is_delete = 1; if (!$model->save()) { throw new \Exception('操作失败。' . $id . array_shift($model->getFirstErrors())); } return [ 'code' => 0, 'msg' => '操作成功', ]; } catch (\Exception $e) { \Yii::error($e); return [ 'code' => 1, 'msg' => $e->getMessage() ]; } } //心跳请求 public function roomUserHeartBeat($room_id = 0, $user = null, $comment_last_id = 0) { $roomInfo = $this->roomInfo($room_id); $follow = LiveFollow::findOne(['anchor_id' => $roomInfo['data']['anchor_id'], 'user_id' => $user['id']]); $roomInfo['is_follow'] = $follow ? 1 : 0; $query = LiveComment::find()->alias('lc') ->leftJoin(['u' => User::tableName()], 'u.id = lc.user_id') ->leftJoin(['su' => SaasUser::tableName()], 'su.mobile = u.binding') ->where([ 'lc.store_id' => $this->store_id, 'lc.room_id' => $room_id, ]); if ($comment_last_id > 0) { $query->andWhere(['>', 'lc.id', $comment_last_id]); } $query->select('su.name, su.avatar, lc.*'); $query->limit(50); $query->orderBy('lc.id DESC'); $listComment = $query->asArray()->all(); $roomInfo['comment'] = $listComment; $roomInfo['tips'] = null; if($comment_last_id == 0){ $tips = $this->storeConf('tips'); if($tips){ $roomInfo['tips'] = $tips; } } return $roomInfo; } public function roomQrcode($room_id = 0, $user_id = 0) { $user = User::findOne($user_id); $saasUser = SaasUser::findOne(['mobile' => $user['binding']]); $content = $saasUser['name'] . ' 分享了直播间'; $this->commentAdd($room_id, $user_id, $content, LiveComment::TYPE_INFO); $form = new ShareQrcodeForm(); $form->id = $room_id; $form->store_id = $this->store_id; $form->type = \app\models\Qrcode::TYPE_LIVE; $form->user = $user; $form->user_id = $user['id']; return $form->search(); } public function commentList($params = []) { try { $query = LiveComment::find()->where(['store_id' => $this->store_id]); if (isset($params['type']) && $params['type'] > -1) { $query->andWhere(['type' => $params['type']]); } if ($params['room_id']) { $query->andWhere(['room_id' => $params['room_id']]); } if ($params['room_name']) { $query->andWhere(['room_id' => LiveRoom::find()->select('id')->where(['like', 'name', $params['room_name']])]); } if ($params['anchor_id']) { $query->andWhere(['anchor_id' => $params['anchor_id']]); } if ($params['anchor_name']) { $query->andWhere(['anchor_id' => LiveAnchor::find()->select('id')->where(['like', 'name', $params['anchor_name']])]); } if (!empty($params['content'])) { $query->andWhere(['like', 'content', trim($params['content'])]); } $query->orderBy('id DESC'); $pagination = pagination_make($query); return [ 'code' => 0, 'msg' => '操作成功', 'data' => $pagination, // 'q' => $query->createCommand()->getRawSql(), ]; } catch (\Exception $e) { \Yii::error($e); return [ 'code' => 1, 'msg' => $e->getMessage() ]; } } public function commentAdd($room_id, $user_id = 0, $content = '', $type = LiveComment::TYPE_DEFAULT) { $room = LiveRoom::findOne($room_id); $model = new LiveComment(); $model->store_id = $room->store_id; $model->content = $content; $model->room_id = $room_id; $model->user_id = $user_id; $model->type = $type; if (!$model->save()) { return [ 'code' => 1, 'msg' => '操作失败!' . array_shift($model->getFirstErrors()), ]; } return [ 'code' => 0, 'msg' => '操作成功', ]; } public function commentDel($id) { LiveComment::deleteAll(['id' => $id]); return [ 'code' => 0, 'msg' => '操作成功', ]; } public function followAdd($anchor_id, $user_id = 0) { $follow = LiveFollow::findOne(['anchor_id' => $anchor_id, 'user_id' => $user_id]); if (!$follow) { $model = new LiveFollow(); $model->store_id = $this->store_id; $model->anchor_id = $anchor_id; $model->user_id = $user_id; if (!$model->save()) { return [ 'code' => 1, 'msg' => '操作失败!' . array_shift($model->getFirstErrors()), ]; } LiveAnchor::updateAllCounters(['follow_num' => 1], ['id' => $anchor_id]); } return [ 'code' => 0, 'msg' => '操作成功', ]; } public function followDel($anchor_id, $user_id = 0) { $up = LiveFollow::deleteAll(['anchor_id' => $anchor_id, 'user_id' => $user_id]); if ($up) { try { LiveAnchor::updateAllCounters(['follow_num' => -1], ['id' => $anchor_id]); } catch (\Exception $e) { } } return [ 'code' => 0, 'msg' => '操作成功', ]; } public function goodsList($params = []) { try { $is_delete = 0; if ($params['is_delete'] == 1) { $is_delete = 1; } $query = LiveGoods::find()->where(['is_delete' => $is_delete, 'store_id' => $this->store_id]); if (isset($params['status']) && $params['status'] > -1) { $query->andWhere(['status' => $params['status']]); } if ($params['anchor_id']) { $query->andWhere(['anchor_id' => $params['anchor_id']]); } if ($params['anchor_name']) { $query->andWhere(['anchor_id' => LiveAnchor::find()->select('id')->where(['like', 'name', $params['anchor_name']])]); } if ($params['goods_id']) { $query->andWhere(['goods_id' => $params['goods_id']]); } if ($params['goods_name']) { $query->andWhere(['goods_id' => Goods::find()->select('id')->where(['like', 'name', $params['goods_name']])]); } $query->orderBy('id DESC'); $pagination = pagination_make($query); $goods = []; $anchor = []; foreach ($pagination['list'] as &$item) { $item['goods'] = $goods[$item['goods_id']] = $goods[$item['goods_id']] ?? Goods::findOne($item['goods_id']); $item['anchor'] = $anchor[$item['anchor_id']] = $anchor[$item['anchor_id']] ?? LiveAnchor::findOne($item['anchor_id']); } return [ 'code' => 0, 'msg' => '操作成功', 'data' => $pagination, // 'q' => $query->createCommand()->getRawSql(), ]; } catch (\Exception $e) { \Yii::error($e); return [ 'code' => 1, 'msg' => $e->getMessage() ]; } } public function goodsAdd($anchor_id, $goods_id = []) { if (!is_array($goods_id)) { $goods_id = explode(',', $goods_id); } foreach ($goods_id as $item) { if ($item <= 0) { continue; } $model = LiveGoods::findOne(['anchor_id' => $anchor_id, 'goods_id' => $item]); if (!$model) { $model = new LiveGoods(); $model->store_id = $this->store_id; $model->anchor_id = $anchor_id; $model->goods_id = $item; } $model->status = 1; $model->is_delete = 0; if (!$model->save()) { return [ 'code' => 1, 'msg' => '操作失败!' . array_shift($model->getFirstErrors()), ]; } } return [ 'code' => 0, 'msg' => '操作成功', ]; } /** * 修改字段(包括删除is_delete) * @param type $id * @param type $key * @param type $val * @return type * @throws \Exception */ public function goodsSaveKey($id, $key, $val) { try { if (!is_array($id)) { $id = explode(',', $id); } foreach ($id as $item) { $model = LiveGoods::findOne($item); if (!$model) { throw new \Exception('参数错误' . $item); } $model->$key = $val; if (!$model->save()) { throw new \Exception('操作失败。' . $item . array_shift($model->getFirstErrors())); } } return [ 'code' => 0, 'msg' => '操作成功', ]; } catch (\Exception $e) { \Yii::error($e); return [ 'code' => 1, 'msg' => $e->getMessage() ]; } } }