ChatRecord.php 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  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. return self::where('user_id', $fromUserId)
  89. ->where('to_user_id', $userId)
  90. ->where('is_read', self::UNREAD)
  91. ->update(['is_read' => self::READ]) !== false;
  92. }
  93. /**
  94. * 获取未读消息数
  95. * @param int $userId 用户ID
  96. * @param int|null $fromUserId 指定发送者(可选)
  97. * @return int
  98. */
  99. public static function getUnreadCount(int $userId, ?int $fromUserId = null): int
  100. {
  101. $where = [
  102. 'to_user_id' => $userId,
  103. 'is_read' => self::UNREAD,
  104. ];
  105. if ($fromUserId !== null) {
  106. $where['user_id'] = $fromUserId;
  107. }
  108. return self::where($where)->count();
  109. }
  110. /**
  111. * 获取所有未读消息数
  112. * @param int $userId 用户ID
  113. * @return int
  114. */
  115. public static function getTotalUnreadCount(int $userId): int
  116. {
  117. return self::where('to_user_id', $userId)
  118. ->where('is_read', self::UNREAD)
  119. ->count();
  120. }
  121. /**
  122. * 获取消息类型文本
  123. * @param int $type 类型
  124. * @return string
  125. */
  126. public static function getTypeText(int $type): string
  127. {
  128. $typeMap = [
  129. self::TYPE_TEXT => '文字',
  130. self::TYPE_VOICE => '语音',
  131. self::TYPE_IMAGE => '图片',
  132. ];
  133. return $typeMap[$type] ?? '未知';
  134. }
  135. /**
  136. * 获取来源类型文本
  137. * @param int $formType 来源类型
  138. * @return string
  139. */
  140. public static function getFormTypeText(int $formType): string
  141. {
  142. $formTypeMap = [
  143. self::FROM_PC => 'PC端',
  144. self::FROM_WECHAT => '微信',
  145. self::FROM_MINIAPP => '小程序',
  146. self::FROM_H5 => 'H5',
  147. ];
  148. return $formTypeMap[$formType] ?? '未知';
  149. }
  150. }