ChatUserRelation.php 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. <?php
  2. declare (strict_types = 1);
  3. namespace app\model\api;
  4. use library\basic\BaseModel;
  5. use library\traits\ModelTrait;
  6. use think\Model;
  7. /**
  8. * 用户会话关系模型
  9. * @mixin \think\Model
  10. */
  11. class ChatUserRelation extends BaseModel
  12. {
  13. use ModelTrait;
  14. protected $name = 'chat_user_relation';
  15. // 未扣次数
  16. const NOT_DEDUCT = 0;
  17. // 已扣次数
  18. const IS_DEDUCT = 1;
  19. /**
  20. * 获取或创建会话关系
  21. * @param int $userId 用户ID
  22. * @param int $toUserId 对方用户ID
  23. * @return self|null
  24. */
  25. public static function getOrCreate(int $userId, int $toUserId): ?self
  26. {
  27. // 确保 userId < toUserId,保持一致性
  28. if ($userId > $toUserId) {
  29. [$userId, $toUserId] = [$toUserId, $userId];
  30. }
  31. $relation = self::where('user_id', $userId)
  32. ->where('to_user_id', $toUserId)
  33. ->find();
  34. if (!$relation) {
  35. $relation = self::create([
  36. 'user_id' => $userId,
  37. 'to_user_id' => $toUserId,
  38. 'is_deduct' => self::NOT_DEDUCT,
  39. 'create_time' => time(),
  40. 'update_time' => time(),
  41. ]);
  42. }
  43. return $relation;
  44. }
  45. /**
  46. * 检查是否已扣次数
  47. * @param int $userId 用户ID
  48. * @param int $toUserId 对方用户ID
  49. * @return bool
  50. */
  51. public static function isDeducted(int $userId, int $toUserId): bool
  52. {
  53. // 确保 userId < toUserId
  54. if ($userId > $toUserId) {
  55. [$userId, $toUserId] = [$toUserId, $userId];
  56. }
  57. $relation = self::where('user_id', $userId)
  58. ->where('to_user_id', $toUserId)
  59. ->find();
  60. return $relation && $relation->is_deduct == self::IS_DEDUCT;
  61. }
  62. /**
  63. * 标记已扣次数
  64. * @param int $userId 用户ID
  65. * @param int $toUserId 对方用户ID
  66. * @return bool
  67. */
  68. public static function markDeducted(int $userId, int $toUserId): bool
  69. {
  70. // 确保 userId < toUserId
  71. if ($userId > $toUserId) {
  72. [$userId, $toUserId] = [$toUserId, $userId];
  73. }
  74. return self::where('user_id', $userId)
  75. ->where('to_user_id', $toUserId)
  76. ->update([
  77. 'is_deduct' => self::IS_DEDUCT,
  78. 'update_time' => time(),
  79. ]) !== false;
  80. }
  81. /**
  82. * 获取用户的所有会话列表
  83. * @param int $userId 用户ID
  84. * @return array
  85. */
  86. public static function getUserSessions(int $userId): array
  87. {
  88. $relations = self::where('user_id', $userId)
  89. ->whereOr('to_user_id', $userId)
  90. ->order('update_time desc')
  91. ->select();
  92. $sessions = [];
  93. foreach ($relations ?: [] as $relation) {
  94. // 确定对方用户ID
  95. $otherUserId = $relation->user_id == $userId ? $relation->to_user_id : $relation->user_id;
  96. // 获取对方用户信息
  97. $user = User::find($otherUserId);
  98. if (!$user) continue;
  99. // 获取最新一条聊天记录
  100. $lastRecord = self::getLastRecord($userId, $otherUserId);
  101. // 获取未读消息数
  102. $unreadCount = ChatRecord::getUnreadCount($userId, $otherUserId);
  103. $sessions[] = [
  104. 'id' => $relation->id,
  105. 'user_id' => $otherUserId,
  106. 'nickname' => $user->nickname ?? '',
  107. 'avatar' => $user->avatar ?? '',
  108. 'last_message' => $lastRecord['content'] ?? '',
  109. 'last_message_time' => $lastRecord['create_time'] ?? $relation->update_time,
  110. 'unread_count' => $unreadCount,
  111. 'is_deduct' => $relation->is_deduct,
  112. ];
  113. }
  114. return $sessions;
  115. }
  116. /**
  117. * 获取最新聊天记录
  118. * @param int $userId 用户ID
  119. * @param int $toUserId 对方用户ID
  120. * @return array|null
  121. */
  122. protected static function getLastRecord(int $userId, int $toUserId): ?array
  123. {
  124. $record = ChatRecord::where(function ($query) use ($userId, $toUserId) {
  125. $query->where(function ($q) use ($userId, $toUserId) {
  126. $q->where('user_id', $userId)->where('to_user_id', $toUserId);
  127. })->whereOr(function ($q) use ($userId, $toUserId) {
  128. $q->where('user_id', $toUserId)->where('to_user_id', $userId);
  129. });
  130. })
  131. ->order('create_time desc')
  132. ->find();
  133. return $record ? $record->toArray() : null;
  134. }
  135. /**
  136. * 删除会话关系
  137. * @param int $userId 用户ID
  138. * @param int $toUserId 对方用户ID
  139. * @return bool
  140. */
  141. public static function deleteSession(int $userId, int $toUserId): bool
  142. {
  143. // 确保 userId < toUserId
  144. if ($userId > $toUserId) {
  145. [$userId, $toUserId] = [$toUserId, $userId];
  146. }
  147. return self::where('user_id', $userId)
  148. ->where('to_user_id', $toUserId)
  149. ->delete() !== false;
  150. }
  151. }