// +---------------------------------------------------------------------- namespace App\Services\Api; use App\Models\MemberModel; use App\Models\VideoCollectModel; use App\Models\VideoModel; use App\Services\BaseService; use App\Services\ConfigService; use App\Services\RedisService; use Illuminate\Support\Facades\DB; /** * 短视频管理-服务类 * @author laravel开发员 * @since 2020/11/11 * @package App\Services\Api */ class VideoService extends BaseService { // 静态对象 protected static $instance = null; /** * 构造函数 * @author laravel开发员 * @since 2020/11/11 * GoodsService constructor. */ public function __construct() { $this->model = new VideoModel(); } /** * 静态入口 * @return static|null */ public static function make() { if (!self::$instance) { self::$instance = (new static()); } return self::$instance; } /** * 列表数据 * @param $params * @param int $pageSize * @return array */ public function getDataList($params, $pageSize = 18, $field = '', $userId=0) { $where = ['a.mark' => 1,'b.mark'=>1]; $field = $field? $field : 'lev_a.*'; $order = 'lev_a.id desc'; $list = $this->model->with(['member'])->from('videos as a') ->leftJoin('member as b', 'b.id', '=', 'a.user_id') ->where($where) ->where(function ($query) use ($params) { $type = isset($params['type']) ? $params['type'] : 0; if ($type > 0) { $query->where('a.type', $type); } $uid = isset($params['uid']) ? $params['uid'] : 0; if ($uid > 0) { $query->where('a.user_id', $uid); }else{ $query->where('a.status', 2); } }) ->where(function ($query) use ($params) { $keyword = isset($params['kw']) ? $params['kw'] : ''; if ($keyword) { $query->where('a.title', 'like', "%{$keyword}%") ->orWhere('a.tags', 'like', "%{$keyword}%") ->orWhere('a.description', 'like', "%{$keyword}%") ->orWhere('b.nickname', 'like', "%{$keyword}%"); } }) ->where(function ($query) use ($params, $userId) { $query->where(function($query) use($userId){ // 所有人可见 $query->where('a.visible_type', 1); })->orWhere(function($query) use($userId){ // 关注视频发布用户可见 $uids = $uids = MemberCollectService::make()->getCollectUsers(['user_id'=> $userId,'status'=>1,'mark'=>1],'collect_uid'); $uids = $uids? $uids : [0]; $query->where('a.visible_type', 2)->where('a.user_id', $uids); // 仅自己可见 })->orWhere(function($query) use($userId){ // 仅自己可见 $query->where('a.visible_type', 3)->where('a.user_id', $userId); // 仅自己可见 }); }) ->selectRaw($field) ->orderByRaw($order) ->paginate($pageSize > 0 ? $pageSize : 9999999); $list = $list ? $list->toArray() : []; if ($list && $list['data']) { foreach ($list['data'] as &$item) { $item['create_time'] = isset($item['create_time']) ? datetime($item['create_time'], 'Y-m-d H.i.s') : ''; $item['thumb'] = isset($item['thumb']) && $item['thumb'] ? get_image_url($item['thumb']) : ''; if(isset($item['albums'])){ $albums = $item['albums']? json_decode($item['albums'], true):[]; $item['albums'] = $albums? get_images_preview($albums) : []; } if(isset($item['file_url'])){ $item['file_url'] = $item['file_url']? get_image_url($item['file_url']) : ''; } if(isset($item['music_url'])){ $item['music_url'] = $item['music_url']? get_image_url($item['music_url']) : ''; } $member = isset($item['member'])? $item['member'] : []; if($member){ $member['avatar'] = isset($member['avatar']) && $member['avatar']? get_image_url($member['avatar']) : get_image_url('/images/member/logo.png'); } $item['tags'] = isset($item['tags']) && $item['tags']? explode(',', $item['tags']) : []; $item['like_num'] = isset($item['like_num']) && $item['like_num']? format_num($item['like_num']) : 0; $item['collect_num'] = isset($item['collect_num']) && $item['collect_num']? format_num($item['collect_num']) : 0; $item['comment_num'] = isset($item['comment_num']) && $item['comment_num']? format_num($item['comment_num']) : 0; $item['views'] = isset($item['views']) && $item['views']? format_num($item['views']) : 0; $item['member'] = $member; } } return [ 'pageSize' => $pageSize, 'total' => isset($list['total']) ? $list['total'] : 0, 'list' => isset($list['data']) ? $list['data'] : [] ]; } /** * 列表数据 * @param $params * @param int $pageSize * @return array */ public function getIndexList($params, $pageSize = 6, $field='', $userId=0) { $where = ['a.mark' => 1,'a.status'=>2,'b.mark'=>1]; $field = $field? $field : 'lev_a.*'; $order = 'rand()'; $model = $this->model->with(['member'])->from('videos as a') ->leftJoin('member as b', 'b.id', '=', 'a.user_id') ->where($where) ->where(function ($query) use ($params) { $type = isset($params['type']) ? $params['type'] : 0; if ($type > 0) { $query->where('a.type', $type); } $uid = isset($params['user_id']) ? $params['user_id'] : 0; if ($uid > 0) { $query->where('a.user_id', $uid); } }) ->where(function ($query) use ($params) { $keyword = isset($params['kw']) ? $params['kw'] : ''; if ($keyword) { $query->where('a.title', 'like', "%{$keyword}%") ->orWhere('a.tags', 'like', "%{$keyword}%") ->orWhere('a.description', 'like', "%{$keyword}%") ->orWhere('b.nickname', 'like', "%{$keyword}%"); } }) ->where(function ($query) use ($params, $userId) { $query->where(function($query) use($userId){ // 所有人可见 $query->where('a.visible_type', 1); })->orWhere(function($query) use($userId){ // 关注视频发布用户可见 $uids = $uids = MemberCollectService::make()->getCollectUsers(['user_id'=> $userId,'status'=>1,'mark'=>1],'collect_uid'); $uids = $uids? $uids : [0]; $query->where('a.visible_type', 2)->where('a.user_id', $uids); // 仅自己可见 })->orWhere(function($query) use($userId){ // 仅自己可见 $query->where('a.visible_type', 3)->where('a.user_id', $userId); // 仅自己可见 }); }); // 推荐的数据 $uids = []; $countModel = clone $model; $total = $countModel->where(function($query) use($params, $userId, &$uids){ // 推荐视频数据 $isRecommend = isset($params['is_recommend']) ? $params['is_recommend'] : 0; if ($isRecommend > 0) { $recommendData = VideoCollectService::make()->getRecommendData($userId); $uids = isset($recommendData['uids'])? $recommendData['uids'] : []; // 按用户推荐 $tags = isset($recommendData['tags'])? $recommendData['tags'] : []; // 按标签推荐 if($uids){ $query->orWhere(function($query) use($uids){ $query->whereIn('a.user_id', $uids); }); } if($tags){ $query->orWhere(function($query) use($tags){ foreach($tags as $tag){ $query->where('a.tags', 'like',"%{$tag}%") ->orWhere('a.description','like',"%{$tag}%"); } }); } } })->count('a.id'); // 随机优先匹配推送 $match = false; if($total > 3 && rand(100,999) > 300){ // 关联推荐数据 $match = true; $list = $countModel->selectRaw($field) ->orderByRaw($uids?DB::raw("FIND_IN_SET(user_id,'".implode(',', $uids)."')"):'lev_a.create_time desc') ->orderByRaw($order) ->paginate($pageSize > 0 ? $pageSize : 9999999); }else{ // 默认推荐数据 $list = $model->selectRaw($field) ->orderByRaw('lev_a.create_time desc') ->orderByRaw($order) ->paginate($pageSize > 0 ? $pageSize : 9999999); } $list = $list ? $list->toArray() : []; if ($list && $list['data']) { foreach ($list['data'] as &$item) { $item['time_text'] = isset($item['create_time']) ? dateFormat($item['create_time'], 'Y-m-d H:i') : ''; $item['thumb'] = isset($item['thumb']) && $item['thumb'] ? get_image_url($item['thumb']) : ''; if(isset($item['albums'])){ $albums = $item['albums']? json_decode($item['albums'], true):[]; $item['albums'] = $albums? get_images_preview($albums) : []; } if(isset($item['file_url'])){ $item['file_url'] = $item['file_url']? get_image_url($item['file_url']) : ''; } if(isset($item['music_url'])){ $item['music_url'] = $item['music_url']? get_image_url($item['music_url']) : ''; } $member = isset($item['member'])? $item['member'] : []; if($member){ $member['avatar'] = isset($member['avatar']) && $member['avatar']? get_image_url($member['avatar']) : get_image_url('/images/member/logo.png'); } $item['tags'] = isset($item['tags']) && $item['tags']? explode(',', $item['tags']) : []; $item['like_num'] = isset($item['like_num']) && $item['like_num']? intval($item['like_num']) : 0; $item['collect_num'] = isset($item['collect_num']) && $item['collect_num']? intval($item['collect_num']) : 0; $item['views'] = isset($item['views']) && $item['views']? intval($item['views']) : 0; $item['comment_num'] = isset($item['comment_num']) && $item['comment_num']? intval($item['comment_num']) : 0; $item['is_like'] = VideoCollectService::make()->checkCollect($userId, $item['id'], 3); $item['is_collect'] = VideoCollectService::make()->checkCollect($userId, $item['id'], 2); $item['is_follow'] = MemberCollectService::make()->checkCollect($userId, $item['user_id'], 1); $item['is_fans'] = MemberCollectService::make()->checkCollect($item['user_id'], $userId, 1); $item['is_publisher'] = $userId == $item['user_id']? 1 : 0; $item['member'] = $member; } } return [ 'pageSize' => $pageSize, "match"=> $match, 'total' => isset($list['total']) ? $list['total'] : 0, 'list' => isset($list['data']) ? $list['data'] : [] ]; } /** * 详情 * @param $id * @return array */ public function getInfo($id, $userId=0, $field=[]) { $field = $field? $field : ['a.*']; $info = $this->model->from('videos as a')->with(['member']) ->leftJoin('member as b','b.id','=','a.user_id') ->where(['a.id'=> $id,'a.mark'=>1,'b.mark'=>1]) ->select($field) ->first(); $info = $info? $info->toArray() : []; if($info){ if(isset($info['thumb'])){ $info['thumb'] = $info['thumb']? get_image_url($info['thumb']) : ''; } if(isset($info['file_url'])){ $info['file_url'] = $info['file_url']? get_image_url($info['file_url']) : ''; } if(isset($item['music_url'])){ $item['music_url'] = $item['music_url']? get_image_url($item['music_url']) : ''; } if(isset($info['albums'])){ $info['albums'] = $info['albums']? json_decode($info['albums'], true) : []; $info['albums'] = $info['albums']? get_images_preview($info['albums']) : []; } $member = isset($info['member'])? $info['member'] : []; if($member){ $member['avatar'] = isset($member['avatar']) && $member['avatar']? get_image_url($member['avatar']) : get_image_url('/images/member/logo.png'); } $info['member'] = $member; $info['tags'] = isset($info['tags']) && $info['tags']? explode(',', $info['tags']) : []; $info['like_num'] = isset($info['like_num']) && $info['like_num']? intval($info['like_num']) : 0; $info['collect_num'] = isset($info['collect_num']) && $info['collect_num']? intval($info['collect_num']) : 0; $info['views'] = isset($info['views']) && $info['views']? intval($info['views']) : 0; $info['comment_num'] = isset($info['comment_num']) && $info['comment_num']? intval($info['comment_num']) : 0; $info['is_like'] = VideoCollectService::make()->checkCollect($userId, $info['id'], 3); $info['is_collect'] = VideoCollectService::make()->checkCollect($userId, $info['id'], 2); $info['is_follow'] = MemberCollectService::make()->checkCollect($userId, $info['user_id'], 1); $info['is_fans'] = MemberCollectService::make()->checkCollect($info['user_id'], $userId, 1); $info['is_publisher'] = $userId == $info['user_id']? 1 : 0; $info['time_text'] = isset($info['create_time']) ? dateFormat($info['create_time'], 'Y-m-d H:i') : ''; // 浏览历史 if(!VideoCollectService::make()->getCollectCacheInfo($userId, $id, 1)){ $data = [ 'user_id'=> $userId, 'type'=> 1, 'collect_id'=> $id, 'collect_uid'=> isset($info['user_id'])? $info['user_id'] : 0, 'tags'=> isset($info['tags'])? $info['tags'] : '', 'create_time'=> time(), 'status'=> 1, ]; VideoCollectModel::insert($data); RedisService::set("caches:videos:collect:temp_{$userId}_{$id}_1_1", $data, rand(10,30)); RedisService::clear("caches:videos:recommend:{$userId}_1"); RedisService::clear("caches:member:fans:{$userId}_{$id}_1"); } // 浏览量 $this->updateView($userId, $id); } return $info; } /** * 更新播放浏览历史 * @param $userId 用户ID * @param $id 视频ID * @return false */ public function updatePlay($userId, $id) { // 浏览历史 if(!VideoCollectService::make()->getCollectCacheInfo($userId, $id, 1)){ $info = $this->model->from('videos as a') ->where(['a.id'=> $id,'a.mark'=>1]) ->select(['a.id','a.tags','a.user_id']) ->first(); if(empty($info)){ return false; } $data = [ 'user_id'=> $userId, 'type'=> 1, 'collect_id'=> $id, 'collect_uid'=> isset($info['user_id'])? $info['user_id'] : 0, 'tags'=> isset($info['tags'])? $info['tags'] : '', 'create_time'=> time(), 'status'=> 1, ]; VideoCollectModel::insert($data); RedisService::set("caches:videos:collect:temp_{$userId}_{$id}_1_1", $data, rand(10,30)); RedisService::clear("caches:videos:recommend:{$userId}_1"); RedisService::clear("caches:member:fans:{$userId}_{$id}_1"); } // 浏览量 $this->updateView($userId, $id); $this->error = 1010; return true; } /** * 更新浏览量 * @param $userId * @param $dynamicId * @return array|mixed */ public function updateView($userId, $id) { $cacheKey = "caches:videos:views:u{$userId}_d{$id}"; $data = RedisService::get($cacheKey); if($data){ return false; } // 浏览视频任务处理 TaskService::make()->updateTask($userId,2, $id); $data = $this->model->where(['id'=> $id])->update(['views'=>DB::raw('views + 1'),'update_time'=>time()]); RedisService::set($cacheKey, $id, rand(1,3)*3600); return $data; } /** * 发布 * @param $goodsId * @return bool */ public function publish($userId, $params, $request) { $goodsId = isset($params['goods_id'])? intval($params['goods_id']) : 0; $type = isset($params['type'])? intval($params['type']) : 2; $userInfo = MemberModel::where(['id'=> $userId,'mark'=>1]) ->select(['id','nickname','status']) ->first(); $status = isset($userInfo['status'])? $userInfo['status'] : 0; $nickname = isset($userInfo['nickname'])? $userInfo['nickname'] : ''; if(empty($userInfo) || $status != 1){ $this->error = 2017; return false; } $thumb = isset($params['thumb'])? trim($params['thumb']) : ''; if($thumb){ $result = upload_base64($thumb); $thumb = isset($result['file_path'])? $result['file_path'] : ''; if(empty($thumb)){ $this->error = 2208; return false; } } // 音乐 $musicUrl = isset($params['music_url'])? trim($params['music_url']) : ''; if($musicUrl){ $result = upload_remote_image($musicUrl,'mp3','music'); $musicUrl = isset($result['file_path'])? $result['file_path'] : ''; if(empty($musicUrl)){ $this->error = 2209; return false; } } // 视频 $fileUrl = isset($params['file_url'])? trim($params['file_url']) : ''; $albums = isset($params['album_urls'])?json_decode( $params['album_urls'],true) : []; if($type == 1) { if($fileUrl){ $result = upload_video($request,'video'); $data = isset($result['data'])? $result['data'] : []; $fileUrl = isset($data['file_path'])? $data['file_path'] : ''; if(empty($fileUrl)){ $this->error = 2212; return false; } }else{ $this->error = 2213; return false; } } // 相册 else if($type == 2){ if(empty($albums) || !is_array($albums)){ $this->error = 2211; return false; } $albums = get_format_images($albums); } $title = isset($params['title']) && $params['title']? trim($params['title']) : "{$nickname} 发布的短视频"; $description = isset($params['description']) && $params['description']? trim($params['description']) : "{$nickname} 发布的短视频"; $publishCheck = ConfigService::make()->getConfigByCode('video_publish_check',0); $publishCheck = $publishCheck>0? $publishCheck : 0; $tags = isset($params['tags']) && $params['tags']? $params['tags'] : ''; $data = [ 'user_id' => $userId, 'title' => $title, 'type' => $type, 'description' => $description, 'tags' => $tags && is_array($tags)? implode(',', $tags) : $tags, 'file_url' => $fileUrl, 'thumb' => $thumb, 'albums' => $albums? $albums : '', 'music_hash' => isset($params['music_hash'])? trim($params['music_hash']) : '', 'music_name' => isset($params['music_name'])? trim($params['music_name']) : '', 'music_url' => $musicUrl, 'goods_id' => $goodsId, 'visible_type' => isset($params['visible_type'])? intval($params['visible_type']) : 1, 'is_comment' => isset($params['is_comment'])? intval($params['is_comment']) : 1, 'status' => $publishCheck? 1 : 2, 'mark' => 1, 'publish_at' => date('Y-m-d H:i:s'), 'create_time' => time(), ]; RedisService::set('caches:videos:publish', ['params'=> $params,'data'=> $data], 600); if($id = $this->model->insertGetId($data)){ $this->error = 1023; // 发布视频任务处理 TaskService::make()->updateTask($userId,5, $id); return ['id'=> $id]; } $this->error = 1024; return false; } /** * 状态设置 * @return bool */ public function status() { $id = request()->post('id', 0); $status = request()->post('status', 1); if ($id && !$this->model->where(['id' => $id, 'mark' => 1])->value('id')) { $this->error = 2981; return false; } if($this->model->where(['id'=> $id,'mark'=>1])->update(['status'=>$status, 'update_time'=> time()])){ $this->error = 1002; return true; } $this->error = 1003; return true; } /** * 删除 * @return bool */ public function delete() { // 参数 $param = request()->all(); $id = getter($param, "id"); if (empty($id)) { $this->error = 2014; return false; } if(!$this->model->where(['id'=> $id])->value('id')){ $this->error = 1039; return false; } if($this->model->where(['id'=> $id])->update(['mark'=>0,'update_time'=>time()])){ $this->model->where(['mark'=> 0])->where('update_time','<=', time() - 3 * 86400)->delete(); $this->error = 1025; return true; }else{ $this->error = 1026; return false; } } }