// +---------------------------------------------------------------------- declare (strict_types=1); namespace app\store\model\wxapp; use app\store\model\wxapp\Setting as WxappSettingModel; use app\common\model\wxapp\LiveRoom as LiveRoomModel; use app\common\library\wechat\live\Room as LiveRoomApi; use cores\exception\BaseException; /** * 微信小程序直播间模型 * Class LiveRoom * @package app\store\model\wxapp */ class LiveRoom extends LiveRoomModel { /** * 获取直播间列表 * @param string $search * @return \think\Paginator * @throws \think\db\exception\DbException */ public function getList(string $search = ''): \think\Paginator { // 查询对象 $query = $this->getNewQuery(); // 检索查询条件 !empty($search) && $query->where('room_name|anchor_name', 'like', "%{$search}%"); // 查询直播间列表 return $query->where('is_delete', '=', 0) ->order(['is_top' => 'desc', 'live_status' => 'asc', 'create_time' => 'desc']) ->paginate(15); } /** * 设置直播间置顶状态 * @param int $isTop * @return bool|false */ public function setIsTop(int $isTop): bool { return $this->save(['is_top' => $isTop]); } /** * 刷新直播间列表(同步微信api) * 每次拉取上限100条数据 * @return bool * @throws BaseException * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ public function refreshLiveList(): bool { // 获取微信api最新直播间列表信息 $originRoomList = $this->getOriginRoomList(); // 获取微信直播间的房间id集 $originRoomIds = $this->getOriginRoomIds($originRoomList); // 已存储的所有房间id集 $localRoomIds = $this->getLocalRoomIds(); // 同步新增直播间 $this->refreshLiveNew($localRoomIds, $originRoomIds, $originRoomList); // 同步删除直播间 $this->refreshLiveRemove($localRoomIds, $originRoomIds); // 同步更新直播间 $this->refreshLiveUpdate($localRoomIds, $originRoomIds, $originRoomList); return true; } /** * 获取微信api最新直播间列表信息 * @return array * @throws BaseException * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ private function getOriginRoomList(): array { // 小程序配置信息 $wxConfig = WxappSettingModel::getConfigBasic(); // 请求api数据 $LiveRoomApi = new LiveRoomApi($wxConfig['app_id'], $wxConfig['app_secret']); $response = $LiveRoomApi->getLiveRoomList(); empty($response) && throwError('直播房间列表API请求失败:' . $LiveRoomApi->getError()); // 格式化返回的列表数据 $originRoomList = []; foreach ($response['room_info'] as $item) { $originRoomList[$item['roomid']] = $item; } return $originRoomList; } /** * 获取微信直播间的房间id集 * @param array $originRoomList * @return array */ private function getOriginRoomIds(array $originRoomList): array { $originRoomIds = []; foreach ($originRoomList as $item) { $originRoomIds[] = $item['roomid']; } return $originRoomIds; } /** * 获取数据库中已存在的roomid * @return array */ private function getLocalRoomIds(): array { return $this->where('is_delete', '=', 0)->column('room_id', 'id'); } /** * 同步新增直播间 * @param array $localRoomIds 本地直播间id集 * @param array $originRoomIds 最新直播间id集 * @param array $originRoomList 最新直播间列表 * @return void */ private function refreshLiveNew(array $localRoomIds, array $originRoomIds, array $originRoomList): void { // 需要新增的直播间ID $newLiveRoomIds = array_values(array_diff($originRoomIds, $localRoomIds)); if (empty($newLiveRoomIds)) { return; } // 整理新增数据 $saveData = []; foreach ($newLiveRoomIds as $roomId) { $item = $originRoomList[$roomId]; $saveData[] = [ 'room_id' => $roomId, 'room_name' => $item['name'], 'cover_img' => $item['cover_img'], 'share_img' => $item['share_img'], 'anchor_name' => $item['anchor_name'], 'start_time' => $item['start_time'], 'end_time' => $item['end_time'], 'live_status' => $item['live_status'], 'store_id' => self::$storeId, ]; } // 批量新增直播间 $this->addAll($saveData) !== false; } /** * 同步更新直播间 * @param array $localRoomIds 本地直播间id集 * @param array $originRoomIds 最新直播间id集 * @param array $originRoomList 最新直播间列表 * @return void */ private function refreshLiveUpdate(array $localRoomIds, array $originRoomIds, array $originRoomList): void { // 需要新增的直播间ID $updatedLiveRoomIds = array_values(array_intersect($originRoomIds, $localRoomIds)); if (empty($updatedLiveRoomIds)) { return; } // 根据直播间id获取主键id $idArr = $this->getLocalIdsByRoomIds($localRoomIds); // 整理更新的数据 $saveData = []; foreach ($updatedLiveRoomIds as $roomId) { $item = $originRoomList[$roomId]; $saveData[] = [ 'where' => ['id' => $idArr[$roomId]], 'data' => [ 'room_id' => $roomId, 'room_name' => $item['name'], 'cover_img' => $item['cover_img'], 'share_img' => $item['share_img'], 'anchor_name' => $item['anchor_name'], 'start_time' => $item['start_time'], 'end_time' => $item['end_time'], 'live_status' => $item['live_status'], 'store_id' => self::$storeId, ] ]; } // 批量更新直播间 $this->updateAll($saveData); } /** * 同步删除直播间 * @param array $localRoomIds 本地直播间id集 * @param array $originRoomIds 最新直播间id集 * @return void */ private function refreshLiveRemove(array $localRoomIds, array $originRoomIds): void { // 需要删除的直播间ID $removedLiveRoomIds = array_values(array_diff($localRoomIds, $originRoomIds)); if (empty($removedLiveRoomIds)) { return; } // 根据直播间id获取主键id $removedIds = $this->getLocalIdsByRoomIds($localRoomIds, $removedLiveRoomIds); // 批量删除直播间 self::destroy(array_values($removedIds)); } /** * 根据直播间ID获取主键ID * @param array $localRoomIds * @param array $searchRoomIds * @return array */ private function getLocalIdsByRoomIds(array $localRoomIds, array $searchRoomIds = []): array { $data = []; foreach ($localRoomIds as $id => $roomId) { if (empty($searchRoomIds) || in_array($roomId, $searchRoomIds)) { $data[$roomId] = $id; } } return $data; } }