|
@@ -3,14 +3,17 @@
|
|
|
namespace App\Services\Client;
|
|
|
|
|
|
// 引入所需的类和枚举
|
|
|
-use App\Enums\UserStatus; // 用户状态枚举
|
|
|
-use App\Exceptions\BusinessException; // 业务异常类
|
|
|
-use App\Models\MemberSocialAccount; // 社交账号模型
|
|
|
-use App\Models\MemberUser; // 用户模型
|
|
|
-use App\Services\SmsService; // 短信服务
|
|
|
-use Illuminate\Support\Facades\Auth; // 认证门面
|
|
|
-use Illuminate\Support\Facades\Cache; // 缓存门面
|
|
|
-use Illuminate\Support\Facades\DB; // 数据库门面
|
|
|
+use App\Enums\UserStatus;
|
|
|
+use App\Exceptions\BusinessException;
|
|
|
+use App\Models\CoachUser;
|
|
|
+use App\Models\MarketDistTeam;
|
|
|
+use App\Models\MemberSocialAccount;
|
|
|
+use App\Models\MemberUser;
|
|
|
+use App\Services\SmsService;
|
|
|
+use Illuminate\Support\Facades\Auth;
|
|
|
+use Illuminate\Support\Facades\Cache;
|
|
|
+use Illuminate\Support\Facades\DB;
|
|
|
+use Illuminate\Support\Facades\Log;
|
|
|
|
|
|
class AccountService
|
|
|
{
|
|
@@ -28,7 +31,6 @@ class AccountService
|
|
|
|
|
|
/**
|
|
|
* 发送验证码
|
|
|
- *
|
|
|
* 业务逻辑:
|
|
|
* 1. 生成6位随机数字验证码
|
|
|
* 2. 将验证码保存到缓存中,有效期5分钟
|
|
@@ -36,22 +38,20 @@ class AccountService
|
|
|
* 4. 返回发送成功消息和验证码
|
|
|
*
|
|
|
* @param string $mobile 手机号
|
|
|
- * @return array{message: string, code: int} 发送结果
|
|
|
- *
|
|
|
- * @throws \Exception 短信发送失败时抛出异常
|
|
|
+ * @return array 包含消息和验证码
|
|
|
*/
|
|
|
public function sendVerifyCode(string $mobile): array
|
|
|
{
|
|
|
- // 生成6位随机验证码
|
|
|
+ // 调用私有方法生成6位随机验证码
|
|
|
$code = $this->generateVerifyCode();
|
|
|
|
|
|
- // 将验证码保存到缓存中,设置过期时间
|
|
|
+ // 将验证码存入缓存,设置5分钟过期时间
|
|
|
$this->storeVerifyCode($mobile, $code);
|
|
|
|
|
|
- // 调用短信服务发送验证码
|
|
|
+ // 调用短信服务发送验证码到用户手机
|
|
|
$this->sendSmsVerifyCode($mobile, $code);
|
|
|
|
|
|
- // 返回发送结果
|
|
|
+ // 返回成功消息和验证码(用于测试环境)
|
|
|
return [
|
|
|
'message' => '验证码发送成功',
|
|
|
'code' => $code,
|
|
@@ -60,39 +60,36 @@ class AccountService
|
|
|
|
|
|
/**
|
|
|
* 用户登录
|
|
|
- *
|
|
|
* 业务逻辑:
|
|
|
* 1. 验证用户输入的验证码是否与缓存中的一致
|
|
|
* 2. 根据手机号查找用户,不存在则创建新用户
|
|
|
* 3. 新用户默认状态为开启,记录注册区域
|
|
|
- * 4. 处理邀请关系(如果有邀请码)
|
|
|
- * 5. 生成用户认证token
|
|
|
- * 6. 返回token和用户信息
|
|
|
+ * 4. 生成用户认证token
|
|
|
+ * 5. 返回token和用户信息
|
|
|
*
|
|
|
* @param string $mobile 手机号
|
|
|
* @param string $code 验证码
|
|
|
- * @param string|null $inviteCode 邀请码 (格式: type_id, 如 user_1, coach_1)
|
|
|
- * @return array{token: string, user: \App\Models\MemberUser} 登录结果
|
|
|
+ * @return array 包含token和用户信息
|
|
|
*
|
|
|
* @throws \Exception 验证码错误时抛出异常
|
|
|
*/
|
|
|
public function login(string $mobile, string $code, ?string $inviteCode = null): array
|
|
|
{
|
|
|
- // 验证用户输入的验证码
|
|
|
+ // 验证用户输入的验证码是否正确
|
|
|
$this->verifyCode($mobile, $code);
|
|
|
|
|
|
- // 查找或创建用户记录
|
|
|
+ // 根据手机号查找用户,不存在则创建新用户
|
|
|
$user = $this->findOrCreateUser($mobile);
|
|
|
|
|
|
- // 如果提供了邀请码,处理邀请关系
|
|
|
+ // 如果提供了邀请码,处理用户的邀请关系
|
|
|
if ($inviteCode) {
|
|
|
$this->handleInviteRelation($user, $inviteCode);
|
|
|
}
|
|
|
|
|
|
- // 生成用户认证令牌
|
|
|
+ // 为用户生成新的认证令牌
|
|
|
$token = $this->createAuthToken($user);
|
|
|
|
|
|
- // 返回登录结果
|
|
|
+ // 返回令牌和用户信息
|
|
|
return [
|
|
|
'token' => $token,
|
|
|
'user' => $user,
|
|
@@ -101,62 +98,77 @@ class AccountService
|
|
|
|
|
|
/**
|
|
|
* 微信登录
|
|
|
- *
|
|
|
* 业务逻辑:
|
|
|
* 1. 根据openid查找或创建社交账号记录
|
|
|
* 2. 检查社交账号是否已关联用户
|
|
|
* 3. 未关联则创建新用户并建立关联
|
|
|
- * 4. 处理邀请关系(如果有)
|
|
|
- * 5. 生成用户认证token
|
|
|
- * 6. 返回token和用户信息
|
|
|
+ * 4. 更新用户微信相关信息(昵称、头像、性别)
|
|
|
+ * 5. 处理邀请关系(如果是新用户且有邀请码)
|
|
|
+ * 6. 生成用户认证token
|
|
|
+ * 7. 返回token和用户信息
|
|
|
*
|
|
|
* @param string $openid 微信openid
|
|
|
- * @param array{
|
|
|
- * nickname?: string,
|
|
|
- * avatar?: string,
|
|
|
- * gender?: int,
|
|
|
- * invite_code?: string
|
|
|
- * } $userInfo 微信用户信息
|
|
|
- * @return array{token: string, user: \App\Models\MemberUser} 登录结果
|
|
|
+ * @param array $userInfo 用户信息,包含 nickname, avatar, gender, invite_code(可选)
|
|
|
+ * @return array 包含token和用户信息
|
|
|
*
|
|
|
* @throws BusinessException 业务异常
|
|
|
*/
|
|
|
public function wxLogin(string $openid, array $userInfo = []): array
|
|
|
{
|
|
|
- return DB::transaction(function () {
|
|
|
- // ... 行内注释保持不变
|
|
|
+ // 使用事务确保数据一致性
|
|
|
+ return DB::transaction(function () use ($openid, $userInfo) {
|
|
|
+ // 查找或创建微信社交账号记录
|
|
|
+ $socialAccount = $this->findOrCreateSocialAccount($openid);
|
|
|
+
|
|
|
+ // 获取关联的用户,如果没有则创建新用户
|
|
|
+ $user = $socialAccount->user ?? $this->createUserFromWechat($userInfo);
|
|
|
+
|
|
|
+ // 如果社交账号未关联用户,建立关联关系
|
|
|
+ if (! $socialAccount->user_id) {
|
|
|
+ $this->linkSocialAccount($socialAccount, $user);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理邀请关系(如果提供了邀请码)
|
|
|
+ if (! empty($userInfo['invite_code'])) {
|
|
|
+ $this->handleInviteRelation($user, $userInfo['invite_code']);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 生成用户认证令牌
|
|
|
+ $token = $this->createAuthToken($user);
|
|
|
+
|
|
|
+ // 返回令牌和刷新后的用户信息
|
|
|
+ return [
|
|
|
+ 'token' => $token,
|
|
|
+ 'user' => $user->fresh(), // 重新获取用户信息,确保数据最新
|
|
|
+ ];
|
|
|
});
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 用户退出
|
|
|
- *
|
|
|
* 业务逻辑:
|
|
|
* 1. 根据用户ID查找用户
|
|
|
- * 2. 验证用户是否存在
|
|
|
+ * 2. 验证用户是否存在,不存在则中断请求
|
|
|
* 3. 删除用户所有token
|
|
|
* 4. 返回退出成功消息
|
|
|
*
|
|
|
* @param int $userId 用户ID
|
|
|
- * @return array{message: string} 退出结果
|
|
|
- *
|
|
|
- * @throws \Illuminate\Http\Exceptions\HttpResponseException 用户不存在时抛出异常
|
|
|
+ * @return array 退出结果消息
|
|
|
*/
|
|
|
public function logout(int $userId): array
|
|
|
{
|
|
|
- // 查找用户
|
|
|
+ // 查找并验证用户是否存在
|
|
|
$user = $this->findUser($userId);
|
|
|
|
|
|
- // 删除用户所有token
|
|
|
+ // 删除用户的所有认证令牌
|
|
|
$this->revokeTokens($user);
|
|
|
|
|
|
- // 返回退出成功消息
|
|
|
+ // 返回退出成功的消息
|
|
|
return ['message' => '退出成功'];
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 用户注销
|
|
|
- *
|
|
|
* 业务逻辑:
|
|
|
* 1. 获取当前认证用户
|
|
|
* 2. 验证用户存在且状态为启用
|
|
@@ -165,25 +177,25 @@ class AccountService
|
|
|
* 5. 删除用户所有token
|
|
|
* 6. 返回注销成功消息
|
|
|
*
|
|
|
- * @return array{message: string} 注销结果
|
|
|
+ * @return array 注销结果消息
|
|
|
*
|
|
|
* @throws \Exception 用户状态异常时抛出异常
|
|
|
*/
|
|
|
public function deleteAccount(): array
|
|
|
{
|
|
|
- // 获取当前用户
|
|
|
+ // 获取并验证当前登录用户
|
|
|
$user = $this->getCurrentUser();
|
|
|
|
|
|
- // 确保用户可以被删除
|
|
|
+ // 验证用户是否可以被注销
|
|
|
$this->ensureUserCanBeDeleted($user);
|
|
|
|
|
|
- // 停用用户账号
|
|
|
+ // 停用用户账号并软删除
|
|
|
$this->deactivateUser($user);
|
|
|
|
|
|
- // 删除用户令牌
|
|
|
+ // 删除用户的所有认证令牌
|
|
|
$this->revokeTokens($user);
|
|
|
|
|
|
- // 返回注销成功消息
|
|
|
+ // 返回注销成功的消息
|
|
|
return ['message' => '账号已注销'];
|
|
|
}
|
|
|
|
|
@@ -198,38 +210,39 @@ class AccountService
|
|
|
*/
|
|
|
private function generateVerifyCode(): int
|
|
|
{
|
|
|
- // 生成指定长度的随机数字验证码
|
|
|
- return mt_rand(
|
|
|
- 10 ** (self::VERIFY_CODE_LENGTH - 1), // 最小值:100000
|
|
|
- (10 ** self::VERIFY_CODE_LENGTH) - 1 // 最大值:999999
|
|
|
- );
|
|
|
+ // 计算最小值(例如: 6位数的最小值为100000)
|
|
|
+ $min = 10 ** (self::VERIFY_CODE_LENGTH - 1);
|
|
|
+
|
|
|
+ // 计算最大值(例如: 6位数的最大值为999999)
|
|
|
+ $max = (10 ** self::VERIFY_CODE_LENGTH) - 1;
|
|
|
+
|
|
|
+ // 生成指定范围内的随机数作为验证码
|
|
|
+ return mt_rand($min, $max);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 保存验证码到缓存
|
|
|
*
|
|
|
- * 业务逻辑:
|
|
|
- * 1. 使用手机号和前缀生成缓存键
|
|
|
- * 2. 将验证码保存到缓存
|
|
|
- * 3. 设置验证码过期时间
|
|
|
+ * 逻辑描述:
|
|
|
+ * 1. 使用手机号作为缓存key
|
|
|
+ * 2. 设置验证码的过期时间
|
|
|
*
|
|
|
* @param string $mobile 手机号
|
|
|
* @param int $code 验证码
|
|
|
*/
|
|
|
private function storeVerifyCode(string $mobile, int $code): void
|
|
|
{
|
|
|
- // 将验证码保存到缓存,使用手机号作为键名
|
|
|
- Cache::put(
|
|
|
- self::VERIFY_CODE_PREFIX.$mobile, // 缓存键:verify_code:手机号
|
|
|
- $code, // 缓存值:验证码
|
|
|
- self::VERIFY_CODE_EXPIRE // 过期时间:5分钟
|
|
|
- );
|
|
|
+ // 构建缓存键名(verify_code:手机号)
|
|
|
+ $key = self::VERIFY_CODE_PREFIX.$mobile;
|
|
|
+
|
|
|
+ // 将验证码存入缓存,并设置过期时间
|
|
|
+ Cache::put($key, $code, self::VERIFY_CODE_EXPIRE);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 发送验证码短信
|
|
|
*
|
|
|
- * 业务逻辑:
|
|
|
+ * 逻辑描述:
|
|
|
* 1. 调用短信服务发送验证码
|
|
|
*
|
|
|
* @param string $mobile 手机号
|
|
@@ -239,16 +252,29 @@ class AccountService
|
|
|
*/
|
|
|
private function sendSmsVerifyCode(string $mobile, int $code): void
|
|
|
{
|
|
|
- // 调用短信服务发送验证码
|
|
|
- $this->smsService->sendVerifyCode($mobile, $code);
|
|
|
+ try {
|
|
|
+ // 调用短信服务发送验证码短信
|
|
|
+ $this->smsService->sendVerifyCode($mobile, $code);
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ // 记录发送失败的日志
|
|
|
+ Log::error('发送验证码失败', [
|
|
|
+ 'mobile' => $mobile,
|
|
|
+ 'code' => $code,
|
|
|
+ 'error' => $e->getMessage(),
|
|
|
+ ]);
|
|
|
+
|
|
|
+ // 重新抛出异常
|
|
|
+ throw $e;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 验证验证码
|
|
|
*
|
|
|
- * 业务逻辑:
|
|
|
+ * 逻辑描述:
|
|
|
* 1. 从缓存中获取验证码
|
|
|
- * 2. 验证码不存在或不匹配则抛出异常
|
|
|
+ * 2. 比对验证码是否匹配
|
|
|
+ * 3. 验证失败则抛出异常
|
|
|
*
|
|
|
* @param string $mobile 手机号
|
|
|
* @param string $code 验证码
|
|
@@ -257,10 +283,10 @@ class AccountService
|
|
|
*/
|
|
|
private function verifyCode(string $mobile, string $code): void
|
|
|
{
|
|
|
- // 从缓存中获取验证码
|
|
|
+ // 使用手机号和前缀构建缓存键,获取存储的验证码
|
|
|
$cacheCode = Cache::get(self::VERIFY_CODE_PREFIX.$mobile);
|
|
|
|
|
|
- // 比对验证码是否匹配
|
|
|
+ // 验证码不存在或不匹配则抛出业务异常
|
|
|
if (! $cacheCode || $cacheCode != $code) {
|
|
|
throw new BusinessException('验证码错误');
|
|
|
}
|
|
@@ -269,21 +295,23 @@ class AccountService
|
|
|
/**
|
|
|
* 查找或创建用户
|
|
|
*
|
|
|
- * 业务逻辑:
|
|
|
+ * 逻辑描述:
|
|
|
* 1. 根据手机号查找用户
|
|
|
- * 2. 用户不存在则创建新用户
|
|
|
+ * 2. 不存在则创建新用户
|
|
|
* 3. 设置用户状态和注册区域
|
|
|
*
|
|
|
* @param string $mobile 手机号
|
|
|
*/
|
|
|
private function findOrCreateUser(string $mobile): MemberUser
|
|
|
{
|
|
|
- // 根据手机号查找用户
|
|
|
+ // 使用 firstOrCreate 方法查找或创建用户
|
|
|
return MemberUser::firstOrCreate(
|
|
|
+ // 查询条件:根据手机号查找
|
|
|
['mobile' => $mobile],
|
|
|
+ // 创建数据:设置用户状态和注册区域
|
|
|
[
|
|
|
- 'state' => UserStatus::OPEN->value,
|
|
|
- 'register_area' => request()->header('area_code'),
|
|
|
+ 'state' => UserStatus::OPEN->value, // 设置用户状态为开启
|
|
|
+ 'register_area' => request()->header('area_code'), // 从请求头获取注册区域
|
|
|
]
|
|
|
);
|
|
|
}
|
|
@@ -291,19 +319,20 @@ class AccountService
|
|
|
/**
|
|
|
* 查找或创建社交账号
|
|
|
*
|
|
|
- * 业务逻辑:
|
|
|
- * 1. 根据openid查找微信社交账号
|
|
|
- * 2. 不存在则创建新的社交账号记录
|
|
|
+ * 逻辑描述:
|
|
|
+ * 1. 根据openid查找社交账号
|
|
|
+ * 2. 不存在则创建新记录
|
|
|
*
|
|
|
* @param string $openid 微信openid
|
|
|
*/
|
|
|
private function findOrCreateSocialAccount(string $openid): MemberSocialAccount
|
|
|
{
|
|
|
- // 根据openid查找社交账号
|
|
|
+ // 使用 firstOrCreate 方法查找或创建社交账号记录
|
|
|
return MemberSocialAccount::firstOrCreate(
|
|
|
+ // 查询条件:平台类型和社交ID
|
|
|
[
|
|
|
- 'platform' => 'WECHAT',
|
|
|
- 'social_id' => $openid,
|
|
|
+ 'platform' => 'WECHAT', // 设置平台为微信
|
|
|
+ 'social_id' => $openid, // 设置微信openid
|
|
|
]
|
|
|
);
|
|
|
}
|
|
@@ -311,7 +340,7 @@ class AccountService
|
|
|
/**
|
|
|
* 创建微信用户
|
|
|
*
|
|
|
- * 业务逻辑:
|
|
|
+ * 逻辑描述:
|
|
|
* 1. 创建新用户记录
|
|
|
* 2. 设置用户基本信息
|
|
|
* 3. 设置微信相关信息
|
|
@@ -320,20 +349,21 @@ class AccountService
|
|
|
*/
|
|
|
private function createUserFromWechat(array $userInfo): MemberUser
|
|
|
{
|
|
|
- // 创建新用户记录
|
|
|
+ // 创建新的用户记录
|
|
|
return MemberUser::create([
|
|
|
- 'state' => UserStatus::OPEN->value,
|
|
|
- 'register_area' => request()->header('area_code'),
|
|
|
- 'nickname' => $userInfo['nickname'] ?? null,
|
|
|
- 'avatar' => $userInfo['avatar'] ?? null,
|
|
|
- 'gender' => $userInfo['gender'] ?? null,
|
|
|
+ 'state' => UserStatus::OPEN->value, // 设置用户状态为开启
|
|
|
+ 'register_area' => request()->header('area_code'), // 从请求头获取注册区域
|
|
|
+ 'nickname' => $userInfo['nickname'] ?? null, // 设置微信昵称,可选
|
|
|
+ 'avatar' => $userInfo['avatar'] ?? null, // 设置微信头像,可选
|
|
|
+ 'gender' => $userInfo['gender'] ?? null, // 设置性别,可选
|
|
|
]);
|
|
|
+
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 关联社交账号和用户
|
|
|
*
|
|
|
- * 业务逻辑:
|
|
|
+ * 逻辑描述:
|
|
|
* 1. 更新社交账号的用户ID
|
|
|
*
|
|
|
* @param \App\Models\MemberSocialAccount $account 社交账号
|
|
@@ -341,32 +371,34 @@ class AccountService
|
|
|
*/
|
|
|
private function linkSocialAccount(MemberSocialAccount $account, MemberUser $user): void
|
|
|
{
|
|
|
- // 更新社交账号的用户ID
|
|
|
- $account->update(['user_id' => $user->id]);
|
|
|
+ // 更新社交账号记录,建立与用户的关联关系
|
|
|
+ $account->update([
|
|
|
+ 'user_id' => $user->id, // 设置关联的用户ID
|
|
|
+ ]);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 生成用户认证令牌
|
|
|
+ * 生成认证令牌
|
|
|
*
|
|
|
- * 业务逻辑:
|
|
|
- * 1. 创建新的认证令牌
|
|
|
- * 2. 返回令牌字符串
|
|
|
+ * 逻辑描述:
|
|
|
+ * 1. 为用户创建新的认证令牌
|
|
|
*
|
|
|
* @param \App\Models\MemberUser $user 用户
|
|
|
- * @return string 认证令牌
|
|
|
+ * @return string 令牌字符串
|
|
|
*/
|
|
|
private function createAuthToken(MemberUser $user): string
|
|
|
{
|
|
|
- // 为用户创建新的认证令牌
|
|
|
- return $user->createToken('auth-token')->plainTextToken;
|
|
|
+ // 使用 Sanctum 为用户创建新的认证令牌
|
|
|
+ return $user->createToken('auth-token') // 创建名为 auth-token 的令牌
|
|
|
+ ->plainTextToken; // 返回令牌的明文字符串
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 查找用户
|
|
|
*
|
|
|
- * 业务逻辑:
|
|
|
+ * 逻辑描述:
|
|
|
* 1. 根据ID查找用户
|
|
|
- * 2. 用户不存在则抛出404异常
|
|
|
+ * 2. 用户不存在则抛出异常
|
|
|
*
|
|
|
* @param int $userId 用户ID
|
|
|
*
|
|
@@ -374,17 +406,20 @@ class AccountService
|
|
|
*/
|
|
|
private function findUser(int $userId): MemberUser
|
|
|
{
|
|
|
- // 根据ID查找用户
|
|
|
+ // 根据用户ID查找用户记录
|
|
|
$user = MemberUser::find($userId);
|
|
|
+
|
|
|
+ // 用户不存在则抛出404异常
|
|
|
abort_if(! $user, 404, '用户不存在');
|
|
|
|
|
|
+ // 返回找到的用户
|
|
|
return $user;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 获取当前认证用户
|
|
|
+ * 获取当前用户
|
|
|
*
|
|
|
- * 业务逻辑:
|
|
|
+ * 逻辑描述:
|
|
|
* 1. 获取当前认证用户
|
|
|
* 2. 用户未登录则抛出异常
|
|
|
*
|
|
@@ -393,20 +428,24 @@ class AccountService
|
|
|
private function getCurrentUser(): MemberUser
|
|
|
{
|
|
|
/** @var MemberUser $user */
|
|
|
+ // 从认证系统获取当前登录用户
|
|
|
$user = Auth::user();
|
|
|
+
|
|
|
+ // 用户未登录则抛出业务异常
|
|
|
if (! $user) {
|
|
|
throw new BusinessException('用户未登录');
|
|
|
}
|
|
|
|
|
|
+ // 返回当前用户
|
|
|
return $user;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 确保用户可以被删除
|
|
|
*
|
|
|
- * 业务逻辑:
|
|
|
+ * 逻辑描述:
|
|
|
* 1. 检查用户状态是否为开启状态
|
|
|
- * 2. 状态异常则抛出异常
|
|
|
+ * 2. 状态异常则抛出业务异常
|
|
|
*
|
|
|
* @param \App\Models\MemberUser $user 用户
|
|
|
*
|
|
@@ -414,41 +453,127 @@ class AccountService
|
|
|
*/
|
|
|
private function ensureUserCanBeDeleted(MemberUser $user): void
|
|
|
{
|
|
|
- // 检查用户状态是否正常
|
|
|
+ // 检查用户状态是否为开启状态
|
|
|
if ($user->state !== UserStatus::OPEN->value) {
|
|
|
+ // 状态异常则抛出业务异常
|
|
|
throw new BusinessException('用户状态异常');
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 停用用户账号
|
|
|
+ * 停用用户
|
|
|
*
|
|
|
- * 业务逻辑:
|
|
|
- * 1. 更新用户状态为关闭
|
|
|
- * 2. 保存用户状态
|
|
|
- * 3. 软删除用户记录
|
|
|
+ * 逻辑描述:
|
|
|
+ * 1. 更新用户状态为关闭状态
|
|
|
+ * 2. 保存用户状态更新
|
|
|
+ * 3. 软删除用户记录(不会真正删除数据)
|
|
|
*
|
|
|
* @param \App\Models\MemberUser $user 用户
|
|
|
*/
|
|
|
private function deactivateUser(MemberUser $user): void
|
|
|
{
|
|
|
- // 更新用户状态为关闭
|
|
|
+ // 更新用户状态为关闭状态
|
|
|
$user->state = UserStatus::CLOSE->value;
|
|
|
+
|
|
|
+ // 保存用户状态更新
|
|
|
$user->save();
|
|
|
+
|
|
|
+ // 软删除用户记录(不会真正删除数据)
|
|
|
$user->delete();
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 撤销用户令牌
|
|
|
*
|
|
|
- * 业务逻辑:
|
|
|
- * 1. 删除用户所有认证令牌
|
|
|
+ * 逻辑描述:
|
|
|
+ * 1. 删除用户所有的认证令牌记录
|
|
|
*
|
|
|
* @param \App\Models\MemberUser $user 用户
|
|
|
*/
|
|
|
private function revokeTokens(MemberUser $user): void
|
|
|
{
|
|
|
- // 删除用户所有认证令牌
|
|
|
+ // 删除用户所有的认证令牌记录
|
|
|
$user->tokens()->delete();
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理邀请关系
|
|
|
+ *
|
|
|
+ * 逻辑描述:
|
|
|
+ * 1. 解析邀请码格式(格式为: type_id)
|
|
|
+ * 2. 验证邀请码格式是否正确
|
|
|
+ * 3. 分解邀请码获取类型和ID
|
|
|
+ * 4. 根据类型查找邀请人
|
|
|
+ * 5. 邀请人不存在则记录日志并返回
|
|
|
+ * 6. 检查用户是否已在营销团队中
|
|
|
+ * 7. 使用事务创建团队关系
|
|
|
+ *
|
|
|
+ * @param \App\Models\MemberUser $user 用户
|
|
|
+ * @param string $inviteCode 邀请码
|
|
|
+ */
|
|
|
+ private function handleInviteRelation(MemberUser $user, string $inviteCode): void
|
|
|
+ {
|
|
|
+ try {
|
|
|
+ // 解析邀请码格式(格式为: type_id)
|
|
|
+ $parts = explode('_', $inviteCode);
|
|
|
+
|
|
|
+ // 验证邀请码格式是否正确
|
|
|
+ if (count($parts) !== 2) {
|
|
|
+ // 记录无效邀请码的警告日志
|
|
|
+ Log::warning('Invalid invite code format', ['invite_code' => $inviteCode]);
|
|
|
+
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 分解邀请码获取类型和ID
|
|
|
+ [$type, $id] = $parts;
|
|
|
+
|
|
|
+ // 根据类型查找邀请人
|
|
|
+ $inviter = match ($type) {
|
|
|
+ 'user' => MemberUser::find($id), // 用户邀请
|
|
|
+ 'coach' => CoachUser::find($id), // 技师邀请
|
|
|
+ default => null
|
|
|
+ };
|
|
|
+
|
|
|
+ // 邀请人不存在则记录日志并返回
|
|
|
+ if (! $inviter) {
|
|
|
+ Log::warning('Inviter not found', [
|
|
|
+ 'type' => $type,
|
|
|
+ 'id' => $id,
|
|
|
+ 'invite_code' => $inviteCode,
|
|
|
+ ]);
|
|
|
+
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查用户是否已在营销团队中
|
|
|
+ $existingTeam = MarketDistTeam::where('user_id', $user->id)->exists();
|
|
|
+ if ($existingTeam) {
|
|
|
+ // 记录用户已在团队中的信息日志
|
|
|
+ Log::info('User already in marketing team', ['user_id' => $user->id]);
|
|
|
+
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 使用事务创建团队关系
|
|
|
+ DB::transaction(function () use ($user, $inviter) {
|
|
|
+ // 创建营销团队成员记录
|
|
|
+ MarketDistTeam::create([
|
|
|
+ 'user_id' => $user->id, // 被邀请用户ID
|
|
|
+ 'owner_id' => $inviter->id, // 邀请人ID
|
|
|
+ 'owner_type' => $inviter::class, // 邀请人类型(用户/技师)
|
|
|
+ 'level' => 1, // 设置团队层级为1
|
|
|
+ 'status' => 1, // 设置状态为有效
|
|
|
+ ]);
|
|
|
+ });
|
|
|
+
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ // 记录处理邀请关系时的错误日志
|
|
|
+ Log::error('Failed to handle invite relation', [
|
|
|
+ 'user_id' => $user->id,
|
|
|
+ 'invite_code' => $inviteCode,
|
|
|
+ 'error' => $e->getMessage(),
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|