ChatRecord.php 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  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 ChatRecord extends BaseModel
  12. {
  13. use ModelTrait;
  14. protected $name = 'chat_record';
  15. // 消息类型
  16. const TYPE_TEXT = 1; // 文字
  17. const TYPE_VOICE = 2; // 语音
  18. const TYPE_IMAGE = 3; // 图片
  19. // 未读
  20. const UNREAD = 0;
  21. // 已读
  22. const READ = 1;
  23. // 来源类型
  24. const FROM_PC = 0; // PC端
  25. const FROM_WECHAT = 1; // 微信
  26. const FROM_MINIAPP = 2; // 小程序
  27. const FROM_H5 = 3; // H5
  28. /**
  29. * 保存聊天记录
  30. * @param int $userId 发送者ID
  31. * @param int $toUserId 接收者ID
  32. * @param string $content 消息内容
  33. * @param int $type 消息类型
  34. * @param int $formType 来源类型 0=PC, 1=微信, 2=小程序, 3=H5
  35. * @return self
  36. */
  37. public static function saveRecord(int $userId, int $toUserId, string $content, int $type = self::TYPE_TEXT, int $formType = self::FROM_PC): self
  38. {
  39. return self::create([
  40. 'user_id' => $userId,
  41. 'to_user_id' => $toUserId,
  42. 'content' => $content,
  43. 'type' => $type,
  44. 'form_type' => $formType,
  45. 'is_read' => self::UNREAD,
  46. 'create_time' => time(),
  47. ]);
  48. }
  49. /**
  50. * 获取与某用户的聊天记录
  51. * @param int $userId 当前用户ID
  52. * @param int $toUserId 对方用户ID
  53. * @param int $page 页码
  54. * @param int $limit 每页数量
  55. * @return array
  56. */
  57. public static function getChatRecords(int $userId, int $toUserId, int $page = 1, int $limit = 20): array
  58. {
  59. $where = function ($query) use ($userId, $toUserId) {
  60. $query->where(function ($q) use ($userId, $toUserId) {
  61. $q->where('user_id', $userId)->where('to_user_id', $toUserId);
  62. })->whereOr(function ($q) use ($userId, $toUserId) {
  63. $q->where('user_id', $toUserId)->where('to_user_id', $userId);
  64. });
  65. };
  66. $data = self::where($where)
  67. ->order('create_time desc')
  68. ->page($page, $limit)
  69. ->select();
  70. $total = self::where($where)->count();
  71. // 标记为已读
  72. self::markAsRead($userId, $toUserId);
  73. return [
  74. 'list' => $data ? array_reverse($data->toArray()) : [],
  75. 'total' => $total,
  76. 'page' => $page,
  77. 'limit' => $limit,
  78. ];
  79. }
  80. /**
  81. * 标记消息为已读
  82. * @param int $userId 当前用户ID
  83. * @param int $fromUserId 发送者ID
  84. * @return bool
  85. */
  86. public static function markAsRead(int $userId, int $fromUserId): bool
  87. {
  88. $affected = \think\facade\Db::name('chat_record')
  89. ->where('user_id', $fromUserId)
  90. ->where('to_user_id', $userId)
  91. ->where('is_read', self::UNREAD)
  92. ->update(['is_read' => self::READ]);
  93. // 调试:记录执行的SQL和影响行数
  94. $sql = \think\facade\Db::name('chat_record')->getLastSql();
  95. trace('【markAsRead】SQL: ' . $sql . ' | 影响行数: ' . $affected, 'chat_debug');
  96. return $affected > 0;
  97. }
  98. /**
  99. * 获取未读消息数
  100. * @param int $userId 用户ID
  101. * @param int|null $fromUserId 指定发送者(可选)
  102. * @return int
  103. */
  104. public static function getUnreadCount(int $userId, ?int $fromUserId = null): int
  105. {
  106. $query = \think\facade\Db::name('chat_record')
  107. ->where('to_user_id', $userId)
  108. ->where('is_read', self::UNREAD);
  109. if ($fromUserId !== null && $fromUserId > 0) {
  110. $query->where('user_id', $fromUserId);
  111. }
  112. $count = $query->count();
  113. // 调试:记录执行的SQL和结果
  114. $sql = \think\facade\Db::name('chat_record')->getLastSql();
  115. trace('【getUnreadCount】SQL: ' . $sql . ' | 结果: ' . $count, 'chat_debug');
  116. return $count;
  117. }
  118. /**
  119. * 获取所有未读消息数
  120. * @param int $userId 用户ID
  121. * @return int
  122. */
  123. public static function getTotalUnreadCount(int $userId): int
  124. {
  125. $count = \think\facade\Db::name('chat_record')
  126. ->where('to_user_id', $userId)
  127. ->where('is_read', self::UNREAD)
  128. ->count();
  129. // 调试:记录执行的SQL和结果
  130. $sql = \think\facade\Db::name('chat_record')->getLastSql();
  131. trace('【getTotalUnreadCount】SQL: ' . $sql . ' | 结果: ' . $count, 'chat_debug');
  132. return $count;
  133. }
  134. /**
  135. * 获取消息类型文本
  136. * @param int $type 类型
  137. * @return string
  138. */
  139. public static function getTypeText(int $type): string
  140. {
  141. $typeMap = [
  142. self::TYPE_TEXT => '文字',
  143. self::TYPE_VOICE => '语音',
  144. self::TYPE_IMAGE => '图片',
  145. ];
  146. return $typeMap[$type] ?? '未知';
  147. }
  148. /**
  149. * 获取来源类型文本
  150. * @param int $formType 来源类型
  151. * @return string
  152. */
  153. public static function getFormTypeText(int $formType): string
  154. {
  155. $formTypeMap = [
  156. self::FROM_PC => 'PC端',
  157. self::FROM_WECHAT => '微信',
  158. self::FROM_MINIAPP => '小程序',
  159. self::FROM_H5 => 'H5',
  160. ];
  161. return $formTypeMap[$formType] ?? '未知';
  162. }
  163. }