// +---------------------------------------------------------------------- declare (strict_types=1); namespace app\common\model; use cores\BaseModel; use think\model\Collection; use think\model\relation\HasOne; use think\model\relation\HasMany; use think\model\relation\BelongsTo; use app\common\model\user\PointsLog as PointsLogModel; use think\Paginator; /** * 用户模型类 * Class User * @package app\common\model */ class User extends BaseModel { // 定义表名 protected $name = 'user'; // 定义主键 protected $pk = 'user_id'; // 性别 private $gender = [0 => '未知', 1 => '男', 2 => '女']; /** * 获取列表 * @param array $param 查询条件 * @param int $listRows 分页数量 * @return mixed * @throws \think\db\exception\DbException */ public function getList(array $param = [], int $listRows = 15) { // 筛选条件 $query = $this->getQueryFilter($param); // 排序条件 $sort = $this->setQuerySort($param); // 执行查询 $userId = isset($param['user_id'])? intval($param['user_id']) : 0; $lockedUids = $userId? UserInfo::getLockedIds($userId) : []; $list = $query->alias($this->name) ->leftJoin('user_info ui','ui.user_id='.$this->name.'.user_id') ->leftJoin('school_speciality sp','sp.speciality_id=ui.speciality') ->leftJoin('source_shools s','s.source_shools_id=ui.school_id') ->field($this->name.'.*,ui.admission_year,s.region_id,s.source_shools_name as school_name,sp.speciality_name'); if($lockedUids){ $list = $list->orderRaw("field(".$this->name.".user_id,".implode(',', $lockedUids).")"); } $list = $list->order($sort) ->paginate($listRows); // 整理列表数据并返回 return $list; } /** * 获取默认解锁用户列表 * @param array $param 查询条件 * @return mixed * @throws \think\db\exception\DbException */ public function getLockedList(array $param = []) { // 筛选条件 $query = $this->getNewQuery(); // 执行查询 $userId = isset($param['user_id'])? intval($param['user_id']) : 0; $lockedUids = $userId? UserInfo::getLockedIds($userId) : []; $list = $query->alias($this->name) ->where([$this->name.'.is_delete'=>0,$this->name.'.status'=>1]) ->where(function($query) use ($lockedUids){ if($lockedUids){ $query->where($this->name.'.user_id', $lockedUids); } }) ->leftJoin('user_info ui','ui.user_id='.$this->name.'.user_id') ->leftJoin('school_speciality sp','sp.speciality_id=ui.speciality') ->leftJoin('source_shools s','s.source_shools_id=ui.school_id') ->field($this->name.'.*,ui.admission_year,s.region_id,s.source_shools_name as school_name,sp.speciality_name') ->order($this->name.'.user_id desc') ->select(); // 整理列表数据并返回 return $list; } /** * 设置商品展示的数据 * @param Collection|Paginator $list 商品列表 * @param callable|null $callback 回调函数 * @return mixed */ protected function setListData($list, callable $callback = null) { if ($list->isEmpty()) return $list; // 遍历商品列表整理数据 foreach ($list as &$item) { $data = $this->setData($item, $callback); } return $list; } /** * 整理数据 * @param Collection|static $info * @param callable|null $callback * @return mixed */ protected function setData($info, callable $callback = null) { // 回调函数 is_callable($callback) && call_user_func($callback, $info); return $info->hidden(array_merge($this->hidden, ['albums'])); } /** * 检索查询条件 * @param array $params * @return \think\db\BaseQuery */ private function getQueryFilter(array $params) { $filter = []; // 实例化新查询对象 $query = $this->getNewQuery(); // 区 !empty($params['region_id']) && $filter[] = ['s.region_id', '=', "{$params['region_id']}"]; // 市 !empty($params['city_id']) && $filter[] = ['s.city_id', '=', "{$params['city_id']}"]; // 省 !empty($params['province_id']) && $filter[] = ['s.province_id', '=', "{$params['province_id']}"]; // 用户状态 !empty($params['status']) && $filter[] = [$this->name.'.status', '=', "{$params['status']}"]; // 审核状态 !empty($params['ui.status']) && $filter[] = ['ui.status', '=', "{$params['ui.status']}"]; // 生源学校 !empty($params['school_id']) && $filter[] = ['ui.school_id', '=', "{$params['school_id']}"]; // 用户类型 !empty($params['user_type']) && $filter[] = [$this->name.'.user_type', '=', "{$params['user_type']}"]; // 实例化新查询对象 return $query->where($filter)->where(function($query) use ($params){ // 关键词 if(!empty($params['keyword'])){ $query->where('s.source_shools_name','like', "%{$params['keyword']}%") ->whereOr('sp.speciality_name','like',"%{$params['keyword']}%"); } // 学长学姐筛选 $admissionYear = isset($params['admission_year'])? intval($params['admission_year']) : -1; if($admissionYear>0){ $query->where('ui.admission_year','<', $admissionYear)->where('ui.admission_year','>', 0); }else if(isset($params['admission_year'])){ $query->where('ui.admission_year','>', 0); } }); } /** * 检索排序条件 * @param array $param * @return array|string[] */ private function setQuerySort(array $param = []) { $params = $this->setQueryDefaultValue($param, [ 'sortType' => 'all', // 排序类型 $this->name.'.create_time' => false, // 热门排序 (true高到低 false低到高) ]); // 排序规则 $sort = []; if ($params['sortType'] === 'all') { $sort = [$this->name.'.create_time' => 'desc']; } elseif ($params['sortType'] === 'view') { $sort = [$this->name.'.id' => 'desc']; } return array_merge($sort, [$this->getPk() => 'desc']); } /** * 关联用户头像表 * @return HasOne */ public function avatar(): HasOne { return $this->hasOne('UploadFile', 'file_id', 'avatar_id') ->bind(['avatar_url' => 'preview_url']); } /** * 用户资料表 * @return HasOne */ public function info(): HasOne { return $this->hasOne("UserInfo", 'user_id', 'user_id') ->field('user_id,school_id,agent_id,position,speciality,qq,parent_name,admission_year,status'); } /** * 关联会员等级表 * @return BelongsTo */ public function grade(): BelongsTo { $module = self::getCalledModule(); return $this->belongsTo("app\\{$module}\\model\\user\\Grade", 'grade_id'); } /** * 关联收货地址表 * @return HasMany */ public function address(): HasMany { return $this->hasMany('UserAddress'); } /** * 关联收货地址表 (默认地址) * @return BelongsTo */ public function addressDefault(): BelongsTo { return $this->belongsTo('UserAddress', 'address_id'); } /** * 获取器:显示性别 * @param $value * @return string */ public function getGenderAttr($value): string { return $this->gender[$value]; } /** * 获取用户信息 * @param $where * @param array $with * @return static|array|false|null */ public static function detail($where, array $with = []) { $filter = ['is_delete' => 0]; if (is_array($where)) { $filter = array_merge($filter, $where); } else { $filter['user_id'] = (int)$where; } return static::get($filter, $with); } /** * 获取用户信息 * @param $where * @param array $with * @return static|array|false|null */ public static function cacheDetail($where, array $with = []) { $cacheKey = "caches:users:detail:".(!is_array($where)? $where.'_' : md5(json_encode($where))); $data = \think\facade\Cache::get($cacheKey); if($data){ return $data; } $filter = ['is_delete' => 0]; if (is_array($where)) { $filter = array_merge($filter, $where); } else { $filter['user_id'] = (int)$where; } $info = static::get($filter, $with); if($info){ $info['avatar'] = isset($info['avatar'])? $info['avatar'] : []; $info['info'] = isset($info['info'])? $info['info'] : []; $info['info'] = isset($info['info'])? $info['info'] : []; \think\facade\Cache::set($cacheKey, $info, rand(5, 10)); } return $info; } /** * 累积用户的实际消费金额 * @param int $userId * @param float $expendMoney * @return mixed */ public static function setIncUserExpend(int $userId, float $expendMoney) { return (new static)->setInc($userId, 'expend_money', $expendMoney); } /** * 累积用户可用余额 * @param int $userId * @param float $money * @return mixed */ public static function setIncBalance(int $userId, float $money) { return (new static)->setInc($userId, 'balance', $money); } /** * 消减用户可用余额 * @param int $userId * @param float $money * @return mixed */ public static function setDecBalance(int $userId, float $money) { return (new static)->setDec([['user_id', '=', $userId]], 'balance', $money); } /** * 指定会员等级下是否存在用户 * @param int $gradeId * @return bool */ public static function checkExistByGradeId(int $gradeId): bool { $model = new static; return (bool)$model->where('grade_id', '=', (int)$gradeId) ->where('is_delete', '=', 0) ->value($model->getPk()); } /** * 指定的手机号是否已存在 * @param string $mobile * @return bool */ public static function checkExistByMobile(string $mobile): bool { $model = new static; return (bool)$model->where('mobile', '=', $mobile) ->where('is_delete', '=', 0) ->value($model->getPk()); } /** * 累积用户总消费金额 * @param int $userId * @param float $money * @return mixed */ public static function setIncPayMoney(int $userId, float $money) { return (new static)->setInc($userId, 'pay_money', $money); } /** * 累积用户实际消费的金额 (批量) * @param array $data * @return bool */ public function onBatchIncExpendMoney(array $data): bool { foreach ($data as $userId => $expendMoney) { static::setIncUserExpend($userId, (float)$expendMoney); } return true; } /** * 累积用户的可用积分数量 (批量) * @param array $data * @return bool */ public function onBatchIncPoints(array $data): bool { foreach ($data as $userId => $value) { $this->setInc($userId, 'points', $value); } return true; } /** * 累积用户的可用积分 * @param int $userId 用户ID * @param int $points 累计的积分 * @param string $describe * @return mixed */ public static function setIncPoints(int $userId, int $points, string $describe) { // 新增积分变动明细 PointsLogModel::add([ 'user_id' => $userId, 'value' => $points, 'describe' => $describe, ]); // 更新用户可用积分 return (new static)->setInc($userId, 'points', $points); } }