identityMiddle->count() >= 1) { //续费 if ($this->hasIdentity($identity_id)) { $this->renewIdentity($identity_id); } else { //升级 self::updateIdentity($identity_id, $channel, $source); } } else { $identity = Identity::find($identity_id); if ($identity) { //未开通此身份 if ($this->hasIdentity($identity_id) == false) { $remark = Arr::get($source, 'remark', '加入身份'); $res = self::identityLog(0, $identity_id, $channel, $remark, $source); if ($res) { $serial = $source['serial'] ?? ''; if ($identity->serial_open && empty($serial)) { $serial = self::getNewSerial($identity->serial_places); } $value = []; if ($identity->years) { $value = [ 'started_at' => now(), 'ended_at' => now()->addMonths($identity->years), ]; } $this->identityMiddle() ->updateOrCreate([ 'identity_id' => $identity_id, 'serial' => $serial, ], $value); event(new UserJoinIdentity($this, $identity)); } else { throw new Exception('添加日志失败'); } } else { //已开通此身份 $this->renewIdentity($identity_id); } } else { throw new Exception('身份信息不存在'); } } } /** * Notes: 续费 * * @Author: 玄尘 * @Date : 2021/6/8 9:49 * @param int $identity_id */ public function renewIdentity(int $identity_id) { $identity = Identity::find($identity_id); $before = $this->identityMiddle()->where('identity_id', $identity_id)->first(); //vip if ($identity->years) { IdentityMiddle::where('user_id', $this->id) ->where('identity_id', $identity_id) ->update([ 'ended_at' => Carbon::parse($before->ended_at)->addMonths($identity->years), ]); } else { IdentityMiddle::where('user_id', $this->id) ->where('identity_id', $identity_id) ->update([ 'started_at' => null, 'ended_at' => null, ]); } event(new UserJoinIdentity($this, $before->identity)); } /** * 用户身份调整,当多身份关闭时由join触发 * * @param int $identity_id * @param string $channel * @param array $source * @throws Exception */ public function updateIdentity( int $identity_id = 0, string $channel = IdentityLog::CHANNEL_AUTO, array $source = [] ) { $before = $this->identityMiddle()->first(); if ($this->identityMiddle()->count() > 1) { $this->identityMiddle()->where('identity_id', '!=', $before->identity_id)->delete(); } $identity = Identity::find($identity_id); if ($identity) { $remark = Arr::get($source, 'remark', '身份变更'); $res = self::identityLog($before->identity_id, $identity_id, $channel, $remark, $source); if ($res) { $serial = $source['serial'] ?? ''; if ($identity->serial_open && empty($serial)) { $serial = self::getNewSerial($identity->serial_places); } $data = [ 'identity_id' => $identity_id, 'serial' => $serial, 'started_at' => null, 'ended_at' => null, ]; if ($identity->years) { $data['started_at'] = now(); $data['ended_at'] = now()->addMonths($identity->years); } IdentityMiddle::where('user_id', $this->id) ->where('identity_id', $before->identity_id) ->update($data); event(new UserUpdateIdentity($this, $before->identity, $identity)); } else { throw new Exception('调整身份'); } } else { throw new Exception('身份信息不存在'); } } /** * 判断用户是否参与身份 * * @param int $identity_id * @return bool */ public function hasIdentity(int $identity_id = 0): bool { if ($identity_id) { $res = $this->identityMiddle()->where('identity_id', $identity_id)->first(); return (bool) $res; } else { return true; } } /** * 用户移除身份 * * @param int $identity_id 身份ID * @param string $channel 移除渠道 * @param array $source 其他溯源信息 * @throws Exception */ public function removeIdentity( int $identity_id = 0, string $channel = IdentityLog::CHANNEL_AUTO, array $source = [] ) { if ($this->identityMiddle()->where('identity_id', $identity_id)->first()) { $remark = Arr::get($source, 'remark', '身份移除'); $res = self::identityLog($identity_id, 0, $channel, $remark, $source); if ($res) { $this->identityMiddle()->where('identity_id', $identity_id)->delete(); event(new UserRemoveIdentity($this, Identity::find($identity_id))); } else { throw new Exception('移除记录失败'); } } else { throw new Exception('用户不在身份组中'); } } /** * 生成数据库中部存在的号码 * * @return int */ public function getNewSerial($places = 8) { try { $min = pow(10, $places - 1); $max = 9 * $min; $query = 'SELECT code FROM (SELECT CEILING(RAND()*'.$max.'+'.$min.') AS code FROM user_identity UNION SELECT CEILING(RAND()*'.$max.'+'.$min.') AS code) AS ss WHERE "code" NOT IN (SELECT serial FROM user_identity where serial !=null) LIMIT 1'; $res = DB::select($query); return (int) $res[0]->code; } catch (Exception $e) { return ''; } } public function identityLog( $before = 0, $after = 0, $channel = '', $remark = '', $source = [] ): Model { return $this->identity_logs()->create([ 'before' => $before, 'after' => $after, 'channel' => $channel, 'remark' => $remark, 'source' => $source, ]); } }