|
@@ -2,15 +2,25 @@
|
|
|
|
|
|
namespace App\Services\Client;
|
|
|
|
|
|
-use App\Models\CoachApplication;
|
|
|
-use App\Models\Feedback;
|
|
|
+use App\Enums\TechnicianAuthStatus;
|
|
|
+use App\Models\CoachInfoRecord;
|
|
|
use App\Models\MemberUser;
|
|
|
-use App\Models\User;
|
|
|
use Illuminate\Support\Facades\Auth;
|
|
|
use Illuminate\Support\Facades\DB;
|
|
|
use Illuminate\Support\Facades\Log;
|
|
|
+use Illuminate\Support\Facades\Redis;
|
|
|
use SimpleSoftwareIO\QrCode\Facades\QrCode;
|
|
|
|
|
|
+/**
|
|
|
+ * 用户服务类
|
|
|
+ *
|
|
|
+ * 处理用户相关的业务逻辑,包括:
|
|
|
+ * - 用户信息的获取和更新
|
|
|
+ * - 用户注册
|
|
|
+ * - 用户反馈
|
|
|
+ * - 技师申请
|
|
|
+ * - 邀请码生成
|
|
|
+ */
|
|
|
class UserService
|
|
|
{
|
|
|
protected $marketDistTeamService;
|
|
@@ -23,21 +33,25 @@ class UserService
|
|
|
/**
|
|
|
* 获取当前用户信息
|
|
|
*
|
|
|
- * @return \Illuminate\Http\JsonResponse
|
|
|
+ * 业务逻辑:
|
|
|
+ * 1. 通过 Auth 门面获取当前登录用户信息
|
|
|
+ * 2. 返回用户基本信息
|
|
|
+ *
|
|
|
+ * @return \Illuminate\Http\JsonResponse 返回用户信息
|
|
|
+ *
|
|
|
+ * @throws \Exception 获取用户信息失败时抛出异常
|
|
|
*/
|
|
|
- public function getUserInfo()
|
|
|
+ public function getUserInfo(): MemberUser
|
|
|
{
|
|
|
try {
|
|
|
- // 获取当前登录用户
|
|
|
+ /** @var MemberUser $user */
|
|
|
+ // 通过 Auth 门面获取当前登录用户信息
|
|
|
$user = Auth::user();
|
|
|
|
|
|
- return response()->json([
|
|
|
- 'code' => 200,
|
|
|
- 'message' => '获取成功',
|
|
|
- 'data' => $user,
|
|
|
- ]);
|
|
|
+ return $user;
|
|
|
} catch (\Exception $e) {
|
|
|
- Log::error('获取用户信息失败: '.$e->getMessage());
|
|
|
+ // 记录错误日志
|
|
|
+ Log::error('获取用户信息失败', ['error' => $e->getMessage()]);
|
|
|
throw $e;
|
|
|
}
|
|
|
}
|
|
@@ -45,93 +59,85 @@ class UserService
|
|
|
/**
|
|
|
* 用户注册
|
|
|
*
|
|
|
+ * 业务逻辑:
|
|
|
+ * 1. 验证手机号是否已被注册
|
|
|
+ * 2. 验证短信验证码
|
|
|
+ * 3. 创建新用户记录
|
|
|
+ * 4. 处理邀请关系(如果有)
|
|
|
+ *
|
|
|
* @param string $mobile 手机号
|
|
|
* @param string $code 验证码
|
|
|
* @param string|null $invite_code 邀请码(选填)
|
|
|
* @param int|null $invite_id 邀请人ID(选填)
|
|
|
* @param string|null $invite_role 邀请人角色(选填)
|
|
|
- * @return \Illuminate\Http\JsonResponse
|
|
|
+ * @return \Illuminate\Http\JsonResponse 返回注册结果
|
|
|
+ *
|
|
|
+ * @throws \Exception 注册过程中出现错误时抛出异常
|
|
|
*/
|
|
|
- public function register(string $mobile, string $code, ?string $invite_code = null, ?int $invite_id = null, ?string $invite_role = null)
|
|
|
+ public function register(string $mobile, string $code, ?string $invite_code = null, ?int $invite_id = null, ?string $invite_role = null): array
|
|
|
{
|
|
|
try {
|
|
|
- // 开启事务
|
|
|
DB::beginTransaction();
|
|
|
|
|
|
// 检查手机号是否已注册
|
|
|
- if (MemberUser::where('mobile', $mobile)->exists()) {
|
|
|
- return response()->json([
|
|
|
- 'code' => 422,
|
|
|
- 'message' => '该手机号已注册',
|
|
|
- 'data' => null,
|
|
|
- ]);
|
|
|
- }
|
|
|
+ abort_if(MemberUser::where('mobile', $mobile)->exists(), 422, '该手机号已注册');
|
|
|
|
|
|
- // 验证手机验证码
|
|
|
- if (! $this->verifySmsCode($mobile, $code)) {
|
|
|
- return response()->json([
|
|
|
- 'code' => 422,
|
|
|
- 'message' => '验证码错误或已过期',
|
|
|
- 'data' => null,
|
|
|
- ]);
|
|
|
- }
|
|
|
+ // 验证短信验证码
|
|
|
+ abort_if(! $this->verifySmsCode($mobile, $code), 422, '验证码错误或已过期');
|
|
|
|
|
|
- // 创建用户数据
|
|
|
- $userData = [
|
|
|
+ // 创建用户
|
|
|
+ $user = MemberUser::create([
|
|
|
'mobile' => $mobile,
|
|
|
'password' => bcrypt(substr($mobile, -6)), // 默认密码为手机号后6位
|
|
|
'nickname' => substr_replace($mobile, '****', 3, 4), // 默认昵称为手机号(中间4位隐藏)
|
|
|
- ];
|
|
|
-
|
|
|
- // 创建用户
|
|
|
- $user = MemberUser::create($userData);
|
|
|
+ ]);
|
|
|
|
|
|
// 处理邀请关系
|
|
|
if ($invite_code && $invite_role && $invite_id) {
|
|
|
- $this->marketDistTeamService->createInviteRelation(
|
|
|
- $user,
|
|
|
- $invite_code,
|
|
|
- $invite_id,
|
|
|
- $invite_role
|
|
|
- );
|
|
|
+ $this->marketDistTeamService->createInviteRelation($user, $invite_code, $invite_id, $invite_role);
|
|
|
}
|
|
|
|
|
|
DB::commit();
|
|
|
|
|
|
- return response()->json([
|
|
|
- 'code' => 200,
|
|
|
- 'message' => '注册成功',
|
|
|
- 'data' => [
|
|
|
- 'user_id' => $user->id,
|
|
|
- 'mobile' => $mobile,
|
|
|
- 'invite_code' => $user->invite_code,
|
|
|
- ],
|
|
|
- ]);
|
|
|
-
|
|
|
+ return [
|
|
|
+ 'user_id' => $user->id,
|
|
|
+ 'mobile' => $mobile,
|
|
|
+ 'invite_code' => $user->invite_code,
|
|
|
+ ];
|
|
|
} catch (\Exception $e) {
|
|
|
DB::rollBack();
|
|
|
- Log::error('用户注册失败: '.$e->getMessage());
|
|
|
+ Log::error('用户注册失败', ['error' => $e->getMessage(), 'mobile' => $mobile]);
|
|
|
throw $e;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 验证短信验证码
|
|
|
+ *
|
|
|
+ * 业务逻辑:
|
|
|
+ * 1. 从 Redis 获取存储的验证码
|
|
|
+ * 2. 比对验证码是否匹配
|
|
|
+ * 3. 验证成功后删除缓存的验证码
|
|
|
+ *
|
|
|
+ * @param string $mobile 手机号
|
|
|
+ * @param string $code 待验证的验证码
|
|
|
+ * @return bool 返回验证结果
|
|
|
*/
|
|
|
private function verifySmsCode(string $mobile, string $code): bool
|
|
|
{
|
|
|
try {
|
|
|
- // TODO: 实现验证码验证逻辑
|
|
|
- // 可以通过Redis验证,示例:
|
|
|
- // $cacheKey = "sms_code:{$mobile}";
|
|
|
- // $cacheCode = Redis::get($cacheKey);
|
|
|
- // if (!$cacheCode || $cacheCode !== $code) {
|
|
|
- // return false;
|
|
|
- // }
|
|
|
- // Redis::del($cacheKey); // 验证成功后删除验证码
|
|
|
+ $cacheKey = "sms_code:{$mobile}";
|
|
|
+ $cacheCode = Redis::get($cacheKey);
|
|
|
+
|
|
|
+ if (! $cacheCode || $cacheCode !== $code) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ Redis::del($cacheKey); // 验证成功后删除验证码
|
|
|
+
|
|
|
return true;
|
|
|
} catch (\Exception $e) {
|
|
|
- Log::error('验证码验证失败: '.$e->getMessage());
|
|
|
+ Log::error('验证码验证失败', ['error' => $e->getMessage(), 'mobile' => $mobile]);
|
|
|
|
|
|
return false;
|
|
|
}
|
|
@@ -140,22 +146,30 @@ class UserService
|
|
|
/**
|
|
|
* 更新当前用户信息
|
|
|
*
|
|
|
- * @return \Illuminate\Http\JsonResponse
|
|
|
+ * 业务逻辑:
|
|
|
+ * 1. 获取当前登录用户
|
|
|
+ * 2. 更新用户基本信息
|
|
|
+ *
|
|
|
+ * @param array $data 待更新的用户数据
|
|
|
+ * @return \Illuminate\Http\JsonResponse 返回更新结果
|
|
|
+ *
|
|
|
+ * @throws \Exception 更新失败时抛出异常
|
|
|
*/
|
|
|
- public function updateUserInfo(array $data)
|
|
|
+ public function updateUserInfo(array $data): MemberUser
|
|
|
{
|
|
|
try {
|
|
|
+ DB::beginTransaction();
|
|
|
+
|
|
|
// 更新用户信息
|
|
|
$user = Auth::user();
|
|
|
$user->update($data);
|
|
|
|
|
|
- return response()->json([
|
|
|
- 'code' => 200,
|
|
|
- 'message' => '修改成功',
|
|
|
- 'data' => null,
|
|
|
- ]);
|
|
|
+ DB::commit();
|
|
|
+
|
|
|
+ return $user->fresh();
|
|
|
} catch (\Exception $e) {
|
|
|
- Log::error('更新用户信息失败: '.$e->getMessage());
|
|
|
+ DB::rollBack();
|
|
|
+ Log::error('更新用户信息失败', ['error' => $e->getMessage(), 'data' => $data]);
|
|
|
throw $e;
|
|
|
}
|
|
|
}
|
|
@@ -163,24 +177,37 @@ class UserService
|
|
|
/**
|
|
|
* 提交用户反馈
|
|
|
*
|
|
|
- * @return \Illuminate\Http\JsonResponse
|
|
|
+ * 业务逻辑:
|
|
|
+ * 1. 创建用户反馈记录
|
|
|
+ * 2. 保存反馈内容和图片
|
|
|
+ * 3. 记录用户联系方式(如果提供)
|
|
|
+ *
|
|
|
+ * @param string $content 反馈内容
|
|
|
+ * @param array $images 反馈图片数组
|
|
|
+ * @param string|null $contact 联系方式
|
|
|
+ * @return \Illuminate\Http\JsonResponse 返回提交结果
|
|
|
+ *
|
|
|
+ * @throws \Exception 提交反馈失败时抛出异常
|
|
|
*/
|
|
|
- public function feedback(string $content)
|
|
|
+ public function feedback(string $content, array $images = [], ?string $contact = null): void //Feedback
|
|
|
{
|
|
|
try {
|
|
|
- // 保存用户反馈
|
|
|
- // Feedback::create([
|
|
|
- // 'user_id' => Auth::id(),
|
|
|
+ DB::beginTransaction();
|
|
|
+
|
|
|
+ // 创建反馈记录
|
|
|
+ // $feedback = Feedback::create([
|
|
|
+ // 'user_id' => Auth::user()->id,
|
|
|
// 'content' => $content,
|
|
|
+ // 'images' => $images,
|
|
|
+ // 'contact' => $contact,
|
|
|
// ]);
|
|
|
|
|
|
- // return response()->json([
|
|
|
- // 'code' => 200,
|
|
|
- // 'message' => '提交成功',
|
|
|
- // 'data' => null,
|
|
|
- // ]);
|
|
|
+ DB::commit();
|
|
|
+
|
|
|
+ // return $feedback;
|
|
|
} catch (\Exception $e) {
|
|
|
- Log::error('提交反馈失败: '.$e->getMessage());
|
|
|
+ DB::rollBack();
|
|
|
+ Log::error('提交反馈失败', ['error' => $e->getMessage(), 'content' => $content]);
|
|
|
throw $e;
|
|
|
}
|
|
|
}
|
|
@@ -188,87 +215,394 @@ class UserService
|
|
|
/**
|
|
|
* 申请成为技师
|
|
|
*
|
|
|
- * @return \Illuminate\Http\JsonResponse
|
|
|
+ * 业务逻辑:
|
|
|
+ * 1. 检查用户申请资格
|
|
|
+ * - 验证用户是否已有技师身份
|
|
|
+ * - 检查是否存在未完成的申请
|
|
|
+ * 2. 创建或更新技师基础信息
|
|
|
+ * - 首次申请:创建技师记录
|
|
|
+ * - 重新申请:更新技师信息
|
|
|
+ * 3. 创建申请记录
|
|
|
+ * - 记录申请信息
|
|
|
+ * - 保存形象照片
|
|
|
+ * - 设置申请状态
|
|
|
+ *
|
|
|
+ * @param string $mobile 联系电话
|
|
|
+ * @param int $gender 性别(1:男/2:女)
|
|
|
+ * @param string $work_years 工作年限
|
|
|
+ * @param string $intention_city 意向城市
|
|
|
+ * @param array $portrait_images 形象照片数组
|
|
|
+ * @param string|null $description 个人介绍
|
|
|
+ * @return \App\Models\CoachInfoRecord 返回申请记录
|
|
|
+ *
|
|
|
+ * @throws \Exception 申请失败时抛出异常
|
|
|
*/
|
|
|
- public function applyCoach(string $mobile, string $gender, string $work_years, string $intention_city)
|
|
|
- {
|
|
|
+ public function applyCoach(
|
|
|
+ string $mobile,
|
|
|
+ int $gender,
|
|
|
+ string $work_years,
|
|
|
+ string $intention_city,
|
|
|
+ array $portrait_images,
|
|
|
+ ?string $description = null
|
|
|
+ ): CoachInfoRecord {
|
|
|
try {
|
|
|
- // 创建技师申请记录
|
|
|
- // CoachApplication::create([
|
|
|
- // 'user_id' => Auth::id(),
|
|
|
- // 'mobile' => $mobile,
|
|
|
- // 'gender' => $gender,
|
|
|
- // 'work_years' => $work_years,
|
|
|
- // 'intention_city' => $intention_city,
|
|
|
- // ]);
|
|
|
+ DB::beginTransaction();
|
|
|
|
|
|
- return response()->json([
|
|
|
- 'code' => 200,
|
|
|
- 'message' => '申请成功',
|
|
|
- 'data' => null,
|
|
|
- ]);
|
|
|
+ // 1. 获取并验证用户信息
|
|
|
+ $user = $this->getAndValidateUser();
|
|
|
+
|
|
|
+ // 2. 获取或创建技师基础信息
|
|
|
+ $coach = $this->getOrCreateCoach($user, $mobile, $gender);
|
|
|
+
|
|
|
+ // 3. 创建申请记录
|
|
|
+ $application = $this->createCoachApplication(
|
|
|
+ $coach,
|
|
|
+ $mobile,
|
|
|
+ $gender,
|
|
|
+ $work_years,
|
|
|
+ $intention_city,
|
|
|
+ $portrait_images,
|
|
|
+ $description
|
|
|
+ );
|
|
|
+
|
|
|
+ DB::commit();
|
|
|
+
|
|
|
+ // 记录成功日志
|
|
|
+ $this->logApplicationSuccess($user, $coach, $application);
|
|
|
+
|
|
|
+ return $application;
|
|
|
} catch (\Exception $e) {
|
|
|
- Log::error('申请成为技师失败: '.$e->getMessage());
|
|
|
+ DB::rollBack();
|
|
|
+ $this->logApplicationError($e, $mobile);
|
|
|
throw $e;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 获取并验证用户信息
|
|
|
+ *
|
|
|
+ * 业务逻辑:
|
|
|
+ * 1. 获取当前登录用户
|
|
|
+ * 2. 验证用户是否存在
|
|
|
+ * 3. 返回用户模型
|
|
|
+ *
|
|
|
+ * @return \App\Models\MemberUser 返回用户模型
|
|
|
+ *
|
|
|
+ * @throws \Illuminate\Http\Exceptions\HttpResponseException 用户未登录时抛出异常
|
|
|
+ */
|
|
|
+ private function getAndValidateUser(): MemberUser
|
|
|
+ {
|
|
|
+ /** @var MemberUser $user */
|
|
|
+ $user = Auth::user();
|
|
|
+
|
|
|
+ // 确保用户存在
|
|
|
+ abort_if(! $user, 401, '用户未登录');
|
|
|
+
|
|
|
+ return $user;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取或创建技师基础信息
|
|
|
+ *
|
|
|
+ * 业务逻辑:
|
|
|
+ * 1. 获取用户关联的技师信息
|
|
|
+ * 2. 如果存在技师信息:
|
|
|
+ * - 验证现有申请状态
|
|
|
+ * - 更新基础信息
|
|
|
+ * 3. 如果不存在技师信息:
|
|
|
+ * - 创建新的技师记录
|
|
|
+ *
|
|
|
+ * @param \App\Models\MemberUser $user 用户模型
|
|
|
+ * @param string $mobile 手机号
|
|
|
+ * @param int $gender 性别(1:男/2:女)
|
|
|
+ * @return \App\Models\Coach 返回技师模型
|
|
|
+ *
|
|
|
+ * @throws \Illuminate\Http\Exceptions\HttpResponseException 验证失败时抛出异常
|
|
|
+ */
|
|
|
+ private function getOrCreateCoach(MemberUser $user, string $mobile, int $gender)
|
|
|
+ {
|
|
|
+ $coach = $user->coach;
|
|
|
+
|
|
|
+ if ($coach) {
|
|
|
+ // 检查现有申请状态
|
|
|
+ $this->validateExistingApplication($coach);
|
|
|
+ // 更新基础信息
|
|
|
+ $coach->update([
|
|
|
+ 'mobile' => $mobile,
|
|
|
+ 'gender' => $gender,
|
|
|
+ ]);
|
|
|
+
|
|
|
+ return $coach->fresh();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 创建新的技师记录
|
|
|
+ return $user->coach()->create([
|
|
|
+ 'mobile' => $mobile,
|
|
|
+ 'gender' => $gender,
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 验证现有申请状态
|
|
|
+ *
|
|
|
+ * 业务逻辑:
|
|
|
+ * 1. 查询技师的申请记录
|
|
|
+ * 2. 检查是否存在审核中或已通过的申请
|
|
|
+ * 3. 根据状态返回相应的错误信息
|
|
|
+ *
|
|
|
+ * @param \App\Models\Coach $coach 技师模型
|
|
|
+ *
|
|
|
+ * @throws \Illuminate\Http\Exceptions\HttpResponseException 存在未完成申请时抛出异常
|
|
|
+ */
|
|
|
+ private function validateExistingApplication($coach): void
|
|
|
+ {
|
|
|
+ $existingApplication = CoachInfoRecord::where('coach_id', $coach->id)
|
|
|
+ ->whereIn('state', [TechnicianAuthStatus::AUDITING, TechnicianAuthStatus::PASSED])
|
|
|
+ ->first();
|
|
|
+
|
|
|
+ if ($existingApplication) {
|
|
|
+ $message = $existingApplication->state === TechnicianAuthStatus::PASSED
|
|
|
+ ? '您已是技师,无需重复申请'
|
|
|
+ : '您有正在审核的申请,请耐心等待';
|
|
|
+ abort(422, $message);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 创建技师申请记录
|
|
|
+ *
|
|
|
+ * 业务逻辑:
|
|
|
+ * 1. 准备申请记录数据
|
|
|
+ * 2. 处理形象照片数据
|
|
|
+ * 3. 创建申请记录
|
|
|
+ *
|
|
|
+ * @param \App\Models\Coach $coach 技师模型
|
|
|
+ * @param string $mobile 联系电话
|
|
|
+ * @param int $gender 性别(1:男/2:女)
|
|
|
+ * @param string $work_years 工作年限
|
|
|
+ * @param string $intention_city 意向城市
|
|
|
+ * @param array $portrait_images 形象照片数组
|
|
|
+ * @param string|null $description 个人介绍
|
|
|
+ * @return \App\Models\CoachInfoRecord 返回申请记录
|
|
|
+ */
|
|
|
+ private function createCoachApplication(
|
|
|
+ $coach,
|
|
|
+ string $mobile,
|
|
|
+ int $gender,
|
|
|
+ string $work_years,
|
|
|
+ string $intention_city,
|
|
|
+ array $portrait_images,
|
|
|
+ ?string $description
|
|
|
+ ): CoachInfoRecord {
|
|
|
+ return CoachInfoRecord::create([
|
|
|
+ 'coach_id' => $coach->id,
|
|
|
+ 'mobile' => $mobile,
|
|
|
+ 'gender' => $gender,
|
|
|
+ 'work_years' => $work_years,
|
|
|
+ 'intention_city' => $intention_city,
|
|
|
+ 'portrait_images' => json_encode($portrait_images, JSON_UNESCAPED_UNICODE),
|
|
|
+ 'description' => $description,
|
|
|
+ 'state' => TechnicianAuthStatus::AUDITING,
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 记录申请成功日志
|
|
|
+ *
|
|
|
+ * 业务逻辑:
|
|
|
+ * 1. 记录用户ID和技师ID
|
|
|
+ * 2. 记录申请记录ID和状态
|
|
|
+ * 3. 记录联系方式
|
|
|
+ *
|
|
|
+ * @param \App\Models\MemberUser $user 用户模型
|
|
|
+ * @param \App\Models\Coach $coach 技师模型
|
|
|
+ * @param \App\Models\CoachInfoRecord $application 申请记录
|
|
|
+ */
|
|
|
+ private function logApplicationSuccess(MemberUser $user, $coach, CoachInfoRecord $application): void
|
|
|
+ {
|
|
|
+ Log::info('技师申请提交成功', [
|
|
|
+ 'user_id' => $user->id,
|
|
|
+ 'coach_id' => $coach->id,
|
|
|
+ 'application_id' => $application->id,
|
|
|
+ 'mobile' => $application->mobile,
|
|
|
+ 'state' => $application->state,
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 记录申请错误日志
|
|
|
+ *
|
|
|
+ * 业务逻辑:
|
|
|
+ * 1. 记录错误信息和堆栈跟踪
|
|
|
+ * 2. 记录用户ID和联系方式
|
|
|
+ * 3. 记录错误发生的文件和行号
|
|
|
+ *
|
|
|
+ * @param \Exception $e 异常对象
|
|
|
+ * @param string $mobile 联系电话
|
|
|
+ */
|
|
|
+ private function logApplicationError(\Exception $e, string $mobile): void
|
|
|
+ {
|
|
|
+ Log::error('申请成为技师失败', [
|
|
|
+ 'error' => $e->getMessage(),
|
|
|
+ 'user_id' => Auth::id(),
|
|
|
+ 'mobile' => $mobile,
|
|
|
+ 'trace' => $e->getTraceAsString(),
|
|
|
+ 'file' => $e->getFile(),
|
|
|
+ 'line' => $e->getLine(),
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 生成用户邀请码
|
|
|
*
|
|
|
- * @return \Illuminate\Http\JsonResponse
|
|
|
+ * 业务逻辑:
|
|
|
+ * 1. 获取当前用户信息
|
|
|
+ * 2. 根据用户类型生成邀请码
|
|
|
+ * 3. 生成包含邀请参数的链接
|
|
|
+ * 4. 生成邀请二维码
|
|
|
+ * 5. 记录邀请码生成日志
|
|
|
+ *
|
|
|
+ * @param string $type 邀请码类型(user/coach)
|
|
|
+ * @return array 返回邀请码和二维码信息
|
|
|
+ *
|
|
|
+ * @throws \Exception 生成邀请码失败时抛出异常
|
|
|
*/
|
|
|
- public function generateInviteCode()
|
|
|
+ public function generateInviteCode(string $type = 'user'): array
|
|
|
{
|
|
|
try {
|
|
|
- // 获取当前用户
|
|
|
+ /** @var MemberUser $user */
|
|
|
+
|
|
|
+ // 1. 获取当前用户
|
|
|
$user = Auth::user();
|
|
|
|
|
|
- // 生成邀请码
|
|
|
- $inviteCode = strtoupper(substr(md5($user->id), 0, 6));
|
|
|
+ // 2. 根据类型获取邀请人ID和角色
|
|
|
+ $inviteInfo = $this->getInviteInfo($user, $type);
|
|
|
+ if (! $inviteInfo) {
|
|
|
+ throw new \Exception('无法生成邀请码,用户类型不匹配');
|
|
|
+ }
|
|
|
|
|
|
- // 生成带参数的网页链接
|
|
|
- $qrContent = config('app.url').'/invite?'.http_build_query([
|
|
|
- 'invite_id' => $user->id,
|
|
|
- 'invite_role' => 'user',
|
|
|
+ // 3. 生成邀请码
|
|
|
+ $inviteCode = $this->generateInviteCodeByType(
|
|
|
+ $type,
|
|
|
+ $inviteInfo['id']
|
|
|
+ );
|
|
|
+
|
|
|
+ // 4. 生成邀请链接和二维码
|
|
|
+ $inviteUrl = $this->generateInviteUrl($inviteCode);
|
|
|
+ $qrCode = $this->generateQrCode($inviteUrl);
|
|
|
+
|
|
|
+ // 5. 记录日志
|
|
|
+ Log::info('生成邀请码', [
|
|
|
+ 'user_id' => $user->id,
|
|
|
+ 'type' => $type,
|
|
|
+ 'invite_id' => $inviteInfo['id'],
|
|
|
'invite_code' => $inviteCode,
|
|
|
+ 'invite_url' => $inviteUrl,
|
|
|
]);
|
|
|
|
|
|
- // 使用QrCode库生成SVG格式的二维码
|
|
|
- $qrImage = QrCode::format('svg')
|
|
|
- ->size(200)
|
|
|
- ->margin(2)
|
|
|
- ->encoding('UTF-8')
|
|
|
- ->generate($qrContent);
|
|
|
-
|
|
|
- // 将SVG转为base64
|
|
|
- $qrBase64 = base64_encode($qrImage);
|
|
|
-
|
|
|
- // 记录生成日志
|
|
|
- Log::info('用户生成邀请码:', [
|
|
|
- 'invite_id' => $user->id,
|
|
|
- 'invite_role' => 'user',
|
|
|
+ return [
|
|
|
'invite_code' => $inviteCode,
|
|
|
- 'invite_url' => $qrContent, // 记录生成的邀请链接
|
|
|
+ 'invite_url' => $inviteUrl,
|
|
|
+ 'qr_code' => $qrCode,
|
|
|
+ ];
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ Log::error('生成邀请码失败', [
|
|
|
+ 'error' => $e->getMessage(),
|
|
|
+ 'user_id' => Auth::id(),
|
|
|
+ 'type' => $type,
|
|
|
]);
|
|
|
+ throw $e;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- return response()->json([
|
|
|
- 'code' => 200,
|
|
|
- 'message' => '生成成功',
|
|
|
- 'data' => [
|
|
|
- 'invite_code' => $inviteCode,
|
|
|
- 'invite_url' => $qrContent, // 返回邀请链接
|
|
|
- 'qr_code' => 'data:image/svg+xml;base64,'.$qrBase64,
|
|
|
- ],
|
|
|
- ]);
|
|
|
+ /**
|
|
|
+ * 获取邀请人信息
|
|
|
+ *
|
|
|
+ * 业务逻辑:
|
|
|
+ * 1. 根据类型判断邀请人身份
|
|
|
+ * 2. 用户类型:直接返回用户信息
|
|
|
+ * 3. 技师类型:
|
|
|
+ * - 验证技师状态
|
|
|
+ * - 返回技师信息
|
|
|
+ *
|
|
|
+ * @param \App\Models\MemberUser $user 当前用户
|
|
|
+ * @param string $type 邀请类型(user/coach)
|
|
|
+ * @return array|null 返回邀请人信息,无效类型返回null
|
|
|
+ */
|
|
|
+ private function getInviteInfo(MemberUser $user, string $type): ?array
|
|
|
+ {
|
|
|
+ switch ($type) {
|
|
|
+ case 'user':
|
|
|
+ return [
|
|
|
+ 'id' => $user->id,
|
|
|
+ 'role' => 'user',
|
|
|
+ ];
|
|
|
+ case 'coach':
|
|
|
+ $coach = $user->coach;
|
|
|
+ if ($coach && $coach->state === TechnicianAuthStatus::PASSED) {
|
|
|
+ return [
|
|
|
+ 'id' => $coach->id,
|
|
|
+ 'role' => 'coach',
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ return null;
|
|
|
+ default:
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- } catch (\Exception $e) {
|
|
|
- Log::error('生成邀请码失败: '.$e->getMessage());
|
|
|
+ /**
|
|
|
+ * 根据类型生成邀请码
|
|
|
+ *
|
|
|
+ * 业务逻辑:
|
|
|
+ * 1. 组合类型和ID
|
|
|
+ * 2. 生成格式化的邀请码
|
|
|
+ *
|
|
|
+ * @param string $type 邀请类型(user/coach)
|
|
|
+ * @param int $id 邀请人ID
|
|
|
+ * @return string 返回格式为 "type_id" 的邀请码
|
|
|
+ */
|
|
|
+ private function generateInviteCodeByType(string $type, int $id): string
|
|
|
+ {
|
|
|
+ return sprintf('%s_%d', $type, $id);
|
|
|
+ }
|
|
|
|
|
|
- return response()->json([
|
|
|
- 'code' => 500,
|
|
|
- 'msg' => '生成二维码失败,请稍后再试。',
|
|
|
- ]);
|
|
|
- }
|
|
|
+ /**
|
|
|
+ * 生成邀请链接
|
|
|
+ *
|
|
|
+ * 业务逻辑:
|
|
|
+ * 1. 获取应用URL
|
|
|
+ * 2. 添加邀请码参数
|
|
|
+ * 3. 生成完整的邀请链接
|
|
|
+ *
|
|
|
+ * @param string $inviteCode 邀请码
|
|
|
+ * @return string 返回完整的邀请链接
|
|
|
+ */
|
|
|
+ private function generateInviteUrl(string $inviteCode): string
|
|
|
+ {
|
|
|
+ return config('app.url').'/invite?'.http_build_query(['invite_code' => $inviteCode]);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 生成二维码
|
|
|
+ *
|
|
|
+ * 业务逻辑:
|
|
|
+ * 1. 使用 QrCode 库生成 SVG 格式二维码
|
|
|
+ * 2. 设置二维码大小和边距
|
|
|
+ * 3. 转换为 base64 编码
|
|
|
+ *
|
|
|
+ * @param string $content 二维码内容
|
|
|
+ * @return string 返回 base64 编码的二维码图片
|
|
|
+ */
|
|
|
+ private function generateQrCode(string $content): string
|
|
|
+ {
|
|
|
+ $qrImage = QrCode::format('svg')
|
|
|
+ ->size(200)
|
|
|
+ ->margin(2)
|
|
|
+ ->encoding('UTF-8')
|
|
|
+ ->generate($content);
|
|
|
+
|
|
|
+ return 'data:image/svg+xml;base64,'.base64_encode($qrImage);
|
|
|
}
|
|
|
}
|