Request.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. <?php
  2. namespace App\Module\Friend\Logics;
  3. use App\Module\Friend\Enums\ERROR_CODE;
  4. use App\Module\Friend\Enums\READ_STATUS;
  5. use App\Module\Friend\Enums\REQUEST_STATUS;
  6. use App\Module\Friend\Models\FriendRequest;
  7. use App\Module\User\Models\User;
  8. use Carbon\Carbon;
  9. use Illuminate\Support\Facades\DB;
  10. use Illuminate\Support\Facades\Log;
  11. /**
  12. * 好友申请逻辑类
  13. *
  14. * 实现好友申请的核心业务逻辑,包括申请发送、处理等功能。
  15. * 该类仅供内部使用,不对外提供服务。
  16. */
  17. class Request
  18. {
  19. /**
  20. * 申请有效期(天)
  21. *
  22. * @var int
  23. */
  24. protected $requestExpireDays = 30;
  25. /**
  26. * 发送好友申请
  27. *
  28. * @param int $senderId 发送者ID
  29. * @param int $receiverId 接收者ID
  30. * @param string|null $message 申请消息
  31. * @return array 操作结果
  32. */
  33. public function sendFriendRequest(int $senderId, int $receiverId, ?string $message = null): array
  34. {
  35. try {
  36. // 检查接收者是否存在
  37. $receiver = User::find($receiverId);
  38. if (!$receiver) {
  39. return [
  40. 'success' => false,
  41. 'code' => ERROR_CODE::USER_NOT_EXIST,
  42. 'message' => '用户不存在'
  43. ];
  44. }
  45. // 检查是否已经是好友
  46. $isFriend = DB::table('friend_relations')
  47. ->where('user_id', $senderId)
  48. ->where('friend_id', $receiverId)
  49. ->exists();
  50. if ($isFriend) {
  51. return [
  52. 'success' => false,
  53. 'code' => ERROR_CODE::ALREADY_FRIEND,
  54. 'message' => '已经是好友关系'
  55. ];
  56. }
  57. // 检查是否已经发送过申请且未处理
  58. $existingRequest = FriendRequest::where('sender_id', $senderId)
  59. ->where('receiver_id', $receiverId)
  60. ->where('status', REQUEST_STATUS::PENDING)
  61. ->first();
  62. if ($existingRequest) {
  63. return [
  64. 'success' => false,
  65. 'code' => ERROR_CODE::REQUEST_ALREADY_SENT,
  66. 'message' => '已发送过申请,请等待对方处理'
  67. ];
  68. }
  69. // 创建新的申请
  70. $request = FriendRequest::create([
  71. 'sender_id' => $senderId,
  72. 'receiver_id' => $receiverId,
  73. 'message' => $message,
  74. 'status' => REQUEST_STATUS::PENDING,
  75. 'read_status' => READ_STATUS::UNREAD,
  76. 'expired_at' => Carbon::now()->addDays($this->requestExpireDays),
  77. ]);
  78. // TODO: 发送通知给接收者
  79. return [
  80. 'success' => true,
  81. 'data' => $request
  82. ];
  83. } catch (\Exception $e) {
  84. Log::error('发送好友申请失败: ' . $e->getMessage());
  85. return [
  86. 'success' => false,
  87. 'code' => ERROR_CODE::PARAM_ERROR,
  88. 'message' => '发送好友申请失败'
  89. ];
  90. }
  91. }
  92. /**
  93. * 获取收到的好友申请列表
  94. *
  95. * @param int $userId 用户ID
  96. * @param int $page 页码
  97. * @param int $limit 每页数量
  98. * @return array 申请列表数据
  99. */
  100. public function getReceivedRequests(int $userId, int $page = 1, int $limit = 20): array
  101. {
  102. // 查询收到的申请
  103. $requests = FriendRequest::where('receiver_id', $userId)
  104. ->where('status', REQUEST_STATUS::PENDING)
  105. ->where('expired_at', '>', Carbon::now())
  106. ->with('sender')
  107. ->orderBy('id', 'desc')
  108. ->paginate($limit, ['*'], 'page', $page);
  109. // 更新为已读状态
  110. FriendRequest::where('receiver_id', $userId)
  111. ->where('read_status', READ_STATUS::UNREAD)
  112. ->update(['read_status' => READ_STATUS::READ]);
  113. // 格式化数据
  114. $items = [];
  115. foreach ($requests as $request) {
  116. if (!$request->sender) {
  117. continue;
  118. }
  119. $items[] = [
  120. 'id' => $request->id,
  121. 'sender_id' => $request->sender_id,
  122. 'nickname' => $request->sender->nickname ?? '',
  123. 'avatar' => $request->sender->avatar ?? '',
  124. 'level' => $request->sender->level ?? 1,
  125. 'message' => $request->message,
  126. 'apply_time' => $request->created_at->timestamp,
  127. ];
  128. }
  129. return [
  130. 'total' => $requests->total(),
  131. 'per_page' => $requests->perPage(),
  132. 'current_page' => $requests->currentPage(),
  133. 'last_page' => $requests->lastPage(),
  134. 'items' => $items
  135. ];
  136. }
  137. /**
  138. * 获取发送的好友申请列表
  139. *
  140. * @param int $userId 用户ID
  141. * @param int $page 页码
  142. * @param int $limit 每页数量
  143. * @return array 申请列表数据
  144. */
  145. public function getSentRequests(int $userId, int $page = 1, int $limit = 20): array
  146. {
  147. // 查询发送的申请
  148. $requests = FriendRequest::where('sender_id', $userId)
  149. ->where(function($query) {
  150. $query->where('status', REQUEST_STATUS::PENDING)
  151. ->orWhere('created_at', '>', Carbon::now()->subDays(7));
  152. })
  153. ->with('receiver')
  154. ->orderBy('id', 'desc')
  155. ->paginate($limit, ['*'], 'page', $page);
  156. // 格式化数据
  157. $items = [];
  158. foreach ($requests as $request) {
  159. if (!$request->receiver) {
  160. continue;
  161. }
  162. $items[] = [
  163. 'id' => $request->id,
  164. 'receiver_id' => $request->receiver_id,
  165. 'nickname' => $request->receiver->nickname ?? '',
  166. 'avatar' => $request->receiver->avatar ?? '',
  167. 'level' => $request->receiver->level ?? 1,
  168. 'message' => $request->message,
  169. 'status' => $request->status,
  170. 'apply_time' => $request->created_at->timestamp,
  171. ];
  172. }
  173. return [
  174. 'total' => $requests->total(),
  175. 'per_page' => $requests->perPage(),
  176. 'current_page' => $requests->currentPage(),
  177. 'last_page' => $requests->lastPage(),
  178. 'items' => $items
  179. ];
  180. }
  181. /**
  182. * 获取已发送申请的用户ID列表
  183. *
  184. * @param int $userId 用户ID
  185. * @return array 用户ID数组
  186. */
  187. public function getSentRequestUserIds(int $userId): array
  188. {
  189. return FriendRequest::where('sender_id', $userId)
  190. ->where('status', REQUEST_STATUS::PENDING)
  191. ->where('expired_at', '>', Carbon::now())
  192. ->pluck('receiver_id')
  193. ->toArray();
  194. }
  195. /**
  196. * 同意好友申请
  197. *
  198. * @param int $userId 当前用户ID
  199. * @param int $requestId 申请ID
  200. * @return array 操作结果
  201. */
  202. public function acceptFriendRequest(int $userId, int $requestId): array
  203. {
  204. try {
  205. // 查询申请记录
  206. $request = FriendRequest::where('id', $requestId)
  207. ->where('receiver_id', $userId)
  208. ->where('status', REQUEST_STATUS::PENDING)
  209. ->where('expired_at', '>', Carbon::now())
  210. ->first();
  211. if (!$request) {
  212. return [
  213. 'success' => false,
  214. 'code' => ERROR_CODE::REQUEST_NOT_EXIST,
  215. 'message' => '申请不存在或已过期'
  216. ];
  217. }
  218. // 开启事务
  219. DB::beginTransaction();
  220. // 更新申请状态
  221. $request->status = REQUEST_STATUS::ACCEPTED;
  222. $request->save();
  223. // 创建好友关系
  224. $friendLogic = new Friend();
  225. $result = $friendLogic->createFriendRelation($userId, $request->sender_id);
  226. if (!$result['success']) {
  227. DB::rollBack();
  228. return $result;
  229. }
  230. // 提交事务
  231. DB::commit();
  232. // 获取好友信息
  233. $friend = User::find($request->sender_id);
  234. $friendData = null;
  235. if ($friend) {
  236. $friendData = [
  237. 'user_id' => $friend->id,
  238. 'nickname' => $friend->nickname ?? '',
  239. 'avatar' => $friend->avatar ?? '',
  240. 'level' => $friend->level ?? 1,
  241. 'status' => 2, // 默认离线
  242. 'last_login' => $friend->last_login_at ?? 0,
  243. 'remark' => null,
  244. 'intimacy' => 0,
  245. ];
  246. }
  247. // TODO: 发送通知给申请者
  248. return [
  249. 'success' => true,
  250. 'data' => $friendData
  251. ];
  252. } catch (\Exception $e) {
  253. DB::rollBack();
  254. Log::error('同意好友申请失败: ' . $e->getMessage());
  255. return [
  256. 'success' => false,
  257. 'code' => ERROR_CODE::PARAM_ERROR,
  258. 'message' => '同意好友申请失败'
  259. ];
  260. }
  261. }
  262. /**
  263. * 拒绝好友申请
  264. *
  265. * @param int $userId 当前用户ID
  266. * @param int $requestId 申请ID
  267. * @return array 操作结果
  268. */
  269. public function rejectFriendRequest(int $userId, int $requestId): array
  270. {
  271. try {
  272. // 查询申请记录
  273. $request = FriendRequest::where('id', $requestId)
  274. ->where('receiver_id', $userId)
  275. ->where('status', REQUEST_STATUS::PENDING)
  276. ->first();
  277. if (!$request) {
  278. return [
  279. 'success' => false,
  280. 'code' => ERROR_CODE::REQUEST_NOT_EXIST,
  281. 'message' => '申请不存在或已处理'
  282. ];
  283. }
  284. // 更新申请状态
  285. $request->status = REQUEST_STATUS::REJECTED;
  286. $request->save();
  287. // TODO: 发送通知给申请者
  288. return [
  289. 'success' => true
  290. ];
  291. } catch (\Exception $e) {
  292. Log::error('拒绝好友申请失败: ' . $e->getMessage());
  293. return [
  294. 'success' => false,
  295. 'code' => ERROR_CODE::PARAM_ERROR,
  296. 'message' => '拒绝好友申请失败'
  297. ];
  298. }
  299. }
  300. }