// +---------------------------------------------------------------------- declare (strict_types=1); namespace app\api\model; use app\api\validate\user\Dynamic; use app\common\model\UserDynamic as UserDynamicModel; use think\facade\Cache; /** * 用户动态模型类 * Class UserDynamic * @package app\api\model */ class UserDynamic extends UserDynamicModel { protected $globalScope = ['']; /** * 隐藏字段 * @var array */ protected $hidden = [ 'update_time' ]; /** * 获取列表 * @param array $param * @param int $listRows * @return mixed * @throws \think\db\exception\DbException */ public function getList(array $param = [], int $listRows = 15) { // 整理查询参数 $params = array_merge($param, ['status' => 1]); // 获取商品列表 $list = parent::getList($params, $listRows); if ($list->isEmpty()) { return $list; } // 隐藏冗余的字段 $list->hidden(array_merge($this->hidden, ['status'])); // 整理列表数据并返回 return $this->setListDataFromApi($list, $param); } /** * 获取列表 * @param array $param * @param int $listRows * @return mixed * @throws \think\db\exception\DbException */ public function getIndexList(int $userId, array $param = [], int $listRows = 15) { // 排序 $sort = "views desc,like_num desc,collect_num desc"; if($this->getNewCount($userId)){ $sort = "create_time desc,views desc, id desc"; } // 获取商品列表 $list = parent::alias($this->name) ->leftJoin('user u','u.user_id='.$this->name.'.user_id') ->leftJoin('user_info ui','ui.user_id='.$this->name.'.user_id') ->where([$this->name.'.status'=> 1]) ->where(function($query) use($userId){ // 访问权限 if($userId>0){ // 获取粉丝用户ID,并验证 $query->where(function($query) use($userId){ // 粉丝只能看公开或好友可看 $query->whereIn($this->name.'.user_id', \app\api\model\UserFans::getFansUid($userId)) ->whereIn($this->name.'.look_type',[1,2]); })->whereOr(function($query) use ($userId){ // 用户自己所有 $query->where([$this->name.'.user_id'=> $userId]); })->whereOr(function($query){ // 公开对所有 $query->where([$this->name.'.look_type'=> 1]); }); } }) ->where(function($query) use($param){ if(!empty($param['keyword'])){ $query->where(function($query) use($param){ $query->where($this->name.'.content','like',"%{$param['keyword']}%") ->whereOr('u.nick_name','like', "%{$param['keyword']}%"); }); } if(!empty($param['school_id'])){ $query->where('ui.school_id','=', intval($param['school_id'])); } }) ->field($this->name.'.*,u.user_type,u.avatar_id,u.nick_name,u.user_type,ui.school_id,ui.admission_year') ->order($sort) ->paginate($listRows); if ($list->isEmpty()) { return $list; } // 隐藏冗余的字段 $list->hidden(array_merge($this->hidden, ['status'])); // 整理列表数据并返回 $param['access_user_id'] = $userId; return $this->setListDataFromApi($list, $param); } /** * 验证是否最新发布有动态,以便于优先推送 * @param $userId * @return int|mixed */ private function getNewCount($userId) { if($userId<=0){ return false; } $cacheKey = "caches:dynamic:news:{$userId}"; if($data = Cache::get($cacheKey)){ return $data; } $data = $this->where(['user_id'=> $userId,'status'=> 1]) ->where('create_time','>=', time() - 60) ->order('create_time desc, id desc') ->count('id'); if($data){ Cache::set($cacheKey, ['user_id'=> $userId,'count'=> $data], rand(30, 60)); } return $data; } /** * 设置展示的数据 api模块 * @param $info * @return mixed */ private function setListDataFromApi($info, $params = []) { return $this->setListData($info, function ($data) use($params){ // 访问用户粉丝状态 $userId = isset($params['access_user_id'])? $params['access_user_id'] : 0; if($userId>0){ $data['fans_status'] = UserFans::checkFans($data['user_id'], $userId); } // 整理数据 api模块 $this->setDataFromApi($data); $this->hidden(['update_time','avatar_id']); }); } /** * 整理数据 api模块 * @param $info * @return mixed */ private function setDataFromApi($info) { return $this->setData($info, function ($data) { // logo封面 $data['image'] = $data['image']? getPreview($data['image']) : ''; $data['file_url'] = $data['file_url']? getPreview($data['file_url']) : ''; $data['create_time_text'] = $data['create_time']? getTimeText(strtotime($data['create_time'])) : ''; if(isset($data['avatar_id'])){ $uploadData = $data['avatar_id']? UploadFile::detail($data['avatar_id']) : []; $data['avatar_url'] = isset($uploadData['preview_url'])? $uploadData['preview_url'] : ''; } // 学校名称 if(isset($data['user_type'])){ $userType = intval($data['user_type']); $admissionYear = isset($data['admission_year'])? $data['admission_year'] : ''; $position = isset($data['position'])? $data['position'] : ''; $data['school_name'] = ''; $data['user_type_text'] = $userType==3? ($position==1? '科任老师' :'招生老师') : ($admissionYear? $admissionYear.'级' :'学生'); if($userType == 3){ $data['school_name'] = $data['school_id']? School::getSchoolField($data['school_id']) : ''; }else{ $data['school_name'] = $data['school_id']? SourceShool::getSchoolField($data['school_id']) : ''; } } // 点赞喜欢数 if(!is_null($data['like_num'])){ $data['like_num'] = $data['like_num']? ($data['like_num']<10000? "{$data['like_num']}" : round($data['like_num']/10000,1).'w') :''; } // 收藏数 if(!is_null($data['collect_num'])){ $data['collect_num'] = $data['collect_num']? ($data['collect_num']<10000? "{$data['collect_num']}" : round($data['collect_num']/10000,1).'w') :''; } // 浏览数 if(!is_null($data['views'])){ $data['views'] = $data['views']? ($data['views']<10000? "{$data['views']}" : round($data['views']/10000,1).'w') :''; } }); } /** * 获取详情信息 * @param $where * @param array $with * @return static|array|false|null */ public static function detail($where, array $with = []) { $filter = []; if (is_array($where)) { $filter = array_merge($filter, $where); } else { $filter['id'] = (int)$where; } return static::get($filter, $with); } /** * 获取学校动态列表 * @param int $schoolId * @param array $param * @param int $listRows * @return mixed */ public function getListBySchool(int $schoolId,int $userId = 0, array $param = [], int $listRows = 15) { // 整理查询参数 $params = array_merge($param, [$this->name.'.status' => 1, 'ui.school_id'=> $schoolId]); // 获取商品列表 $list = parent::getListBySchool($schoolId, $userId, $params, $listRows); if ($list->isEmpty()) { return $list; } // 隐藏冗余的字段 $list->hidden(array_merge($this->hidden, ['status'])); // 整理列表数据并返回 return $this->setListDataFromApi($list); } /** * 发布动态 * @param $params * @return bool * @throws \cores\exception\BaseException */ public function publish($params) { // 表单参数验证 $validate = new Dynamic(); if(!$validate->check($params)){ throwError($validate->getError()); } $userInfo = \app\api\service\User::getCurrentLoginUser(true); if($userInfo['status'] != 1){ $this->error = '用户已冻结'; return false; } $data = [ 'user_id'=> $userInfo['user_id'], 'name'=> isset($params['name'])? $params['name'] : '用户动态', 'content'=> isset($params['content'])? $params['content'] : '', 'image'=> isset($params['image'])? $params['image'] : '', 'type'=> isset($params['type'])? $params['type'] : 1, 'file_url'=> isset($params['file_url'])? $params['file_url'] : '', 'look_type'=> isset($params['look_type'])? intval($params['look_type']) : 1, 'latitude'=> isset($params['latitude'])? $params['latitude'] : 0, 'longitude'=> isset($params['longitude'])? $params['longitude'] : 0, 'address'=> isset($params['address'])? $params['address'] : '', 'create_time'=> time(), 'update_time'=> time(), 'status'=> 1, ]; return $this->save($data); } /** * 获取详情信息 * @param $where * @param array $with * @return static|array|false|null */ public static function getDetail($id, array $with = []) { $data = static::alias('a') ->leftJoin('user u','u.user_id=a.user_id') ->leftJoin('user_info ui','ui.user_id=a.user_id') ->where(['a.status'=> 1,'a.id'=> $id]) ->field('a.*,u.user_type,u.avatar_id,u.nick_name,u.user_type,ui.school_id,ui.admission_year,ui.position') ->find(); if(empty($data)){ throwError('动态信息不存在或已删除'); } // 权限验证 $userInfo = \app\api\service\User::getCurrentLoginUser(true); if($data['look_type']==3 && $userInfo['user_id'] != $data['user_id']){ throwError('该作品已被设置为仅作者可看'); } // 好友作品,我是对方粉丝时可看 if($data['look_type']==2 && UserFans::checkFans($data['user_id'], $userInfo['user_id'])){ throwError('该作品已被设置为仅好友可看'); } // 粉丝状态 $data['fans_status'] = UserFans::checkFans($data['user_id'], $userInfo['user_id']); // 访问量 $cacheKey = "caches:dynamic:views:{$userInfo['user_id']}_{$data['id']}"; if(!Cache::get($cacheKey)){ self::setIncViews($id); // 半年内同用户只记一次 Cache::set($cacheKey, ['id'=> $id, 'user_id'=> $userInfo['user_id'],'date'=>date('Y-m-d H:i:s')], rand(3*30*24*3600,6*30*24*3600)); } return (new static())->setDataFromApi($data); } /** * 访问量 * @param $id */ public static function setIncViews($id){ (new static())->setInc(['id'=> $id], 'views', 1); } /** * 统计综合数量 * @param $userId * @return array */ public static function getCountsByUser($userId) { return [ 'public'=> (int)static::where(['user_id'=> $userId, 'status'=> 1])->whereIn('look_type',[1,2])->count('id'), 'private'=> (int)static::where(['user_id'=> $userId, 'status'=> 1,'look_type'=> 3])->count('id'), 'collect'=> (int)UserDynamicCollect::getCountsByType($userId, 1), 'liked'=> (int)UserDynamicCollect::getCountsByType($userId, 2), ]; } }