Chat.php 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. <?php
  2. namespace App\Models;
  3. use Illuminate\Database\Eloquent\Factories\HasFactory;
  4. use Illuminate\Database\Eloquent\Model;
  5. use Illuminate\Support\Str;
  6. class Chat extends Model
  7. {
  8. use HasFactory;
  9. protected $fillable = [
  10. 'uid',
  11. 'title',
  12. 'user_id'
  13. ];
  14. protected $casts = [
  15. 'id' => 'string',
  16. 'uid' => 'string',
  17. 'created_at' => 'datetime',
  18. 'updated_at' => 'datetime',
  19. 'deleted_at' => 'datetime',
  20. ];
  21. protected $primaryKey = 'uid';
  22. protected static function boot()
  23. {
  24. parent::boot();
  25. static::creating(function ($model) {
  26. if (empty($model->uid)) {
  27. $model->uid = (string) Str::uuid();
  28. }
  29. });
  30. // 级联软删除:删除Chat时同时软删除所有相关消息
  31. static::deleting(function ($chat) {
  32. if ($chat->isForceDeleting()) {
  33. // 强制删除时,物理删除所有消息
  34. $chat->messages()->forceDelete();
  35. } else {
  36. // 软删除时,级联软删除所有消息
  37. $chat->messages()->delete();
  38. }
  39. });
  40. // 恢复Chat时同时恢复所有相关消息
  41. static::restoring(function ($chat) {
  42. $chat->messages()->withTrashed()->restore();
  43. });
  44. }
  45. // 使用 uid 作为路由键
  46. public function messages()
  47. {
  48. return $this->hasMany(ChatMessage::class);
  49. }
  50. public function getRouteKeyName()
  51. {
  52. return 'uid';
  53. }
  54. /**
  55. * 获取根消息(没有parent_id的消息)
  56. */
  57. public function rootMessages()
  58. {
  59. return $this->hasMany(ChatMessage::class, 'chat_id', 'uid')
  60. ->whereNull('parent_id')
  61. ->where('is_active', true);
  62. }
  63. /**
  64. * 获取token使用统计
  65. */
  66. public function getTokenStats()
  67. {
  68. return $this->messages()
  69. ->where('role', 'assistant')
  70. ->whereNotNull('metadata')
  71. ->selectRaw('
  72. SUM(JSON_EXTRACT(metadata, "$.token_usage.total_tokens")) as total_tokens,
  73. SUM(JSON_EXTRACT(metadata, "$.token_usage.prompt_tokens")) as prompt_tokens,
  74. SUM(JSON_EXTRACT(metadata, "$.token_usage.completion_tokens")) as completion_tokens,
  75. AVG(JSON_EXTRACT(metadata, "$.performance.response_time_ms")) as avg_response_time
  76. ')
  77. ->first();
  78. }
  79. /**
  80. * 批量软删除多个聊天
  81. */
  82. public static function batchSoftDelete(array $chatIds): int
  83. {
  84. return static::whereIn('uid', $chatIds)->delete();
  85. }
  86. /**
  87. * 批量恢复多个聊天
  88. */
  89. public static function batchRestore(array $chatIds): int
  90. {
  91. return static::withTrashed()->whereIn('uid', $chatIds)->restore();
  92. }
  93. }