UserLog.php 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. <?php
  2. namespace App\Module\Game\Models;
  3. use App\Module\Game\Casts\UserLogSourceTypeCast;
  4. use App\Module\Game\Enums\REWARD_SOURCE_TYPE;
  5. use UCore\ModelCore;
  6. /**
  7. * 用户日志模型
  8. *
  9. * field start
  10. * @property int $id 主键ID
  11. * @property int $user_id 用户ID
  12. * @property string $message 日志消息内容
  13. * @property string $source_type 来源类型(fund, item, farm等)
  14. * @property int $source_id 来源记录ID
  15. * @property string $source_table 来源表名
  16. * @property \Carbon\Carbon $original_time 原始日志时间(业务发生时间)
  17. * @property \Carbon\Carbon $collected_at 收集时间(日志收集时间)
  18. * @property \Carbon\Carbon $created_at 创建时间(兼容字段,等同于collected_at)
  19. * field end
  20. */
  21. class UserLog extends ModelCore
  22. {
  23. /**
  24. * 与模型关联的表名
  25. *
  26. * @var string
  27. */
  28. protected $table = 'user_logs';
  29. /**
  30. * 指示模型是否应该被打上时间戳
  31. * 只需要创建时间,不需要更新时间
  32. *
  33. * @var bool
  34. */
  35. public $timestamps = true;
  36. /**
  37. * 更新时间戳字段名
  38. * 设置为null表示不使用updated_at字段
  39. *
  40. * @var string|null
  41. */
  42. const UPDATED_AT = null;
  43. // attrlist start
  44. protected $fillable = [
  45. 'id',
  46. 'user_id',
  47. 'message',
  48. 'source_type',
  49. 'source_id',
  50. 'source_table',
  51. 'original_time',
  52. 'collected_at',
  53. ];
  54. // attrlist end
  55. /**
  56. * 应该被转换为日期的属性
  57. *
  58. * @var array
  59. */
  60. protected $dates = [
  61. 'original_time',
  62. 'collected_at',
  63. 'created_at',
  64. ];
  65. /**
  66. * 应该被转换为原生类型的属性
  67. *
  68. * @var array
  69. */
  70. protected $casts = [
  71. 'user_id' => 'integer',
  72. 'source_id' => 'integer',
  73. 'source_type' => UserLogSourceTypeCast::class,
  74. 'original_time' => 'datetime',
  75. 'collected_at' => 'datetime',
  76. 'created_at' => 'datetime',
  77. ];
  78. /**
  79. * 关联用户模型
  80. *
  81. * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
  82. */
  83. public function user()
  84. {
  85. return $this->belongsTo(\App\Module\User\Models\User::class, 'user_id', 'id');
  86. }
  87. /**
  88. * 按用户ID查询日志
  89. *
  90. * @param \Illuminate\Database\Eloquent\Builder $query
  91. * @param int $userId
  92. * @return \Illuminate\Database\Eloquent\Builder
  93. */
  94. public function scopeByUser($query, int $userId)
  95. {
  96. return $query->where('user_id', $userId);
  97. }
  98. /**
  99. * 按来源类型查询日志
  100. *
  101. * @param \Illuminate\Database\Eloquent\Builder $query
  102. * @param string $sourceType
  103. * @return \Illuminate\Database\Eloquent\Builder
  104. */
  105. public function scopeBySourceType($query, string $sourceType)
  106. {
  107. return $query->where('source_type', $sourceType);
  108. }
  109. /**
  110. * 按时间范围查询日志
  111. *
  112. * @param \Illuminate\Database\Eloquent\Builder $query
  113. * @param string $startTime
  114. * @param string $endTime
  115. * @return \Illuminate\Database\Eloquent\Builder
  116. */
  117. public function scopeByTimeRange($query, string $startTime, string $endTime)
  118. {
  119. return $query->whereBetween('created_at', [$startTime, $endTime]);
  120. }
  121. /**
  122. * 最新日志优先(按原始时间排序)
  123. *
  124. * @param \Illuminate\Database\Eloquent\Builder $query
  125. * @return \Illuminate\Database\Eloquent\Builder
  126. */
  127. public function scopeLatest($query)
  128. {
  129. return $query->orderBy('original_time', 'desc');
  130. }
  131. /**
  132. * 按原始时间排序(升序)
  133. *
  134. * @param \Illuminate\Database\Eloquent\Builder $query
  135. * @return \Illuminate\Database\Eloquent\Builder
  136. */
  137. public function scopeByOriginalTime($query)
  138. {
  139. return $query->orderBy('original_time', 'asc');
  140. }
  141. /**
  142. * 按收集时间排序
  143. *
  144. * @param \Illuminate\Database\Eloquent\Builder $query
  145. * @return \Illuminate\Database\Eloquent\Builder
  146. */
  147. public function scopeByCollectedTime($query)
  148. {
  149. return $query->orderBy('collected_at', 'desc');
  150. }
  151. /**
  152. * 按原始时间范围查询
  153. *
  154. * @param \Illuminate\Database\Eloquent\Builder $query
  155. * @param string $startTime
  156. * @param string $endTime
  157. * @return \Illuminate\Database\Eloquent\Builder
  158. */
  159. public function scopeByOriginalTimeRange($query, string $startTime, string $endTime)
  160. {
  161. return $query->whereBetween('original_time', [$startTime, $endTime]);
  162. }
  163. /**
  164. * 获取格式化的创建时间
  165. *
  166. * @return string
  167. */
  168. public function getFormattedCreatedAtAttribute(): string
  169. {
  170. return $this->created_at ? $this->created_at->format('Y-m-d H:i:s') : '';
  171. }
  172. /**
  173. * 获取格式化的时间戳(使用原始时间)
  174. *
  175. * @return string
  176. */
  177. public function getTimeAttribute(): string
  178. {
  179. return $this->original_time ? $this->original_time->format('m-d H:i') : '';
  180. }
  181. /**
  182. * 获取格式化的原始时间
  183. *
  184. * @return string
  185. */
  186. public function getFormattedOriginalTimeAttribute(): string
  187. {
  188. return $this->original_time ? $this->original_time->format('Y-m-d H:i:s') : '';
  189. }
  190. /**
  191. * 获取格式化的收集时间
  192. *
  193. * @return string
  194. */
  195. public function getFormattedCollectedAtAttribute(): string
  196. {
  197. return $this->collected_at ? $this->collected_at->format('Y-m-d H:i:s') : '';
  198. }
  199. /**
  200. * 获取时间差(收集时间 - 原始时间)
  201. *
  202. * @return int 秒数
  203. */
  204. public function getCollectionDelayAttribute(): int
  205. {
  206. if (!$this->original_time || !$this->collected_at) {
  207. return 0;
  208. }
  209. return $this->collected_at->timestamp - $this->original_time->timestamp;
  210. }
  211. /**
  212. * 获取来源类型名称
  213. *
  214. * @return string
  215. */
  216. public function getSourceTypeNameAttribute(): string
  217. {
  218. if (!$this->source_type) {
  219. return '未知';
  220. }
  221. if ($this->source_type instanceof REWARD_SOURCE_TYPE) {
  222. $info = REWARD_SOURCE_TYPE::getTypeInfo($this->source_type->value);
  223. return $info['name'];
  224. }
  225. // 兼容旧数据
  226. if (is_string($this->source_type) && REWARD_SOURCE_TYPE::isValid($this->source_type)) {
  227. $info = REWARD_SOURCE_TYPE::getTypeInfo($this->source_type);
  228. return $info['name'];
  229. }
  230. return $this->source_type;
  231. }
  232. /**
  233. * 获取来源类型图标
  234. *
  235. * @return string
  236. */
  237. public function getSourceTypeIconAttribute(): string
  238. {
  239. if (!$this->source_type) {
  240. return '❓';
  241. }
  242. if ($this->source_type instanceof REWARD_SOURCE_TYPE) {
  243. $info = REWARD_SOURCE_TYPE::getTypeInfo($this->source_type->value);
  244. return $info['icon'];
  245. }
  246. // 兼容旧数据
  247. if (is_string($this->source_type) && REWARD_SOURCE_TYPE::isValid($this->source_type)) {
  248. $info = REWARD_SOURCE_TYPE::getTypeInfo($this->source_type);
  249. return $info['icon'];
  250. }
  251. return '❓';
  252. }
  253. /**
  254. * 获取来源类型分类
  255. *
  256. * @return string
  257. */
  258. public function getSourceTypeCategoryAttribute(): string
  259. {
  260. if (!$this->source_type) {
  261. return 'unknown';
  262. }
  263. if ($this->source_type instanceof REWARD_SOURCE_TYPE) {
  264. $info = REWARD_SOURCE_TYPE::getTypeInfo($this->source_type->value);
  265. return $info['category'];
  266. }
  267. // 兼容旧数据
  268. if (is_string($this->source_type) && REWARD_SOURCE_TYPE::isValid($this->source_type)) {
  269. $info = REWARD_SOURCE_TYPE::getTypeInfo($this->source_type);
  270. return $info['category'];
  271. }
  272. return 'unknown';
  273. }
  274. /**
  275. * 获取来源类型完整信息
  276. *
  277. * @return array
  278. */
  279. public function getSourceTypeInfoAttribute(): array
  280. {
  281. if (!$this->source_type) {
  282. return [
  283. 'name' => '未知',
  284. 'description' => '未知来源类型',
  285. 'category' => 'unknown',
  286. 'icon' => '❓',
  287. 'priority' => 999
  288. ];
  289. }
  290. if ($this->source_type instanceof REWARD_SOURCE_TYPE) {
  291. return REWARD_SOURCE_TYPE::getTypeInfo($this->source_type->value);
  292. }
  293. // 兼容旧数据
  294. if (is_string($this->source_type) && REWARD_SOURCE_TYPE::isValid($this->source_type)) {
  295. return REWARD_SOURCE_TYPE::getTypeInfo($this->source_type);
  296. }
  297. return [
  298. 'name' => $this->source_type,
  299. 'description' => '未知来源类型',
  300. 'category' => 'unknown',
  301. 'icon' => '❓',
  302. 'priority' => 999
  303. ];
  304. }
  305. }