AdminLog.php 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. <?php
  2. namespace App\Module\Admin\Models;
  3. use App\Module\Admin\Enums\ADMIN_ACTION_TYPE;
  4. use UCore\ModelCore;
  5. /**
  6. * 管理员日志模型
  7. *
  8. * @property int $id
  9. * @property int|null $admin_id 管理员ID
  10. * @property string $admin_name 管理员名称
  11. * @property string $action_type 操作类型
  12. * @property string $description 操作描述
  13. * @property string|null $data 操作数据(JSON)
  14. * @property string $ip_address IP地址
  15. * @property string|null $user_agent 用户代理
  16. * @property \Carbon\Carbon $created_at 创建时间
  17. * @property \Carbon\Carbon $updated_at 更新时间
  18. */
  19. class AdminLog extends ModelCore
  20. {
  21. /**
  22. * 数据表名
  23. *
  24. * @var string
  25. */
  26. protected $table = 'admin_logs';
  27. /**
  28. * 可批量赋值的属性
  29. *
  30. * @var array
  31. */
  32. protected $fillable = [
  33. 'admin_id',
  34. 'admin_name',
  35. 'action_type',
  36. 'description',
  37. 'data',
  38. 'ip_address',
  39. 'user_agent',
  40. ];
  41. /**
  42. * 属性类型转换
  43. *
  44. * @var array
  45. */
  46. protected $casts = [
  47. 'admin_id' => 'integer',
  48. 'data' => 'array',
  49. 'created_at' => 'datetime',
  50. 'updated_at' => 'datetime',
  51. ];
  52. /**
  53. * 获取操作类型枚举
  54. *
  55. * @return ADMIN_ACTION_TYPE|null
  56. */
  57. public function getActionTypeEnumAttribute(): ?ADMIN_ACTION_TYPE
  58. {
  59. try {
  60. return ADMIN_ACTION_TYPE::from($this->action_type);
  61. } catch (\ValueError $e) {
  62. return null;
  63. }
  64. }
  65. /**
  66. * 获取操作类型标签
  67. *
  68. * @return string
  69. */
  70. public function getActionTypeLabelAttribute(): string
  71. {
  72. $enum = $this->getActionTypeEnumAttribute();
  73. return $enum ? $enum->getLabel() : $this->action_type;
  74. }
  75. /**
  76. * 获取操作类型颜色
  77. *
  78. * @return string
  79. */
  80. public function getActionTypeColorAttribute(): string
  81. {
  82. $enum = $this->getActionTypeEnumAttribute();
  83. return $enum ? $enum->getColor() : 'secondary';
  84. }
  85. /**
  86. * 获取操作类型图标
  87. *
  88. * @return string
  89. */
  90. public function getActionTypeIconAttribute(): string
  91. {
  92. $enum = $this->getActionTypeEnumAttribute();
  93. return $enum ? $enum->getIcon() : 'fa-question';
  94. }
  95. /**
  96. * 判断是否为危险操作
  97. *
  98. * @return bool
  99. */
  100. public function getIsDangerousAttribute(): bool
  101. {
  102. $enum = $this->getActionTypeEnumAttribute();
  103. return $enum ? $enum->isDangerous() : false;
  104. }
  105. /**
  106. * 获取格式化的数据
  107. *
  108. * @return string
  109. */
  110. public function getFormattedDataAttribute(): string
  111. {
  112. if (empty($this->data)) {
  113. return '';
  114. }
  115. if (is_array($this->data)) {
  116. return json_encode($this->data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
  117. }
  118. return (string) $this->data;
  119. }
  120. /**
  121. * 获取简短的用户代理
  122. *
  123. * @return string
  124. */
  125. public function getShortUserAgentAttribute(): string
  126. {
  127. if (empty($this->user_agent)) {
  128. return '';
  129. }
  130. // 提取浏览器信息
  131. if (preg_match('/Chrome\/[\d.]+/', $this->user_agent, $matches)) {
  132. return $matches[0];
  133. }
  134. if (preg_match('/Firefox\/[\d.]+/', $this->user_agent, $matches)) {
  135. return $matches[0];
  136. }
  137. if (preg_match('/Safari\/[\d.]+/', $this->user_agent, $matches)) {
  138. return $matches[0];
  139. }
  140. if (preg_match('/Edge\/[\d.]+/', $this->user_agent, $matches)) {
  141. return $matches[0];
  142. }
  143. // 如果没有匹配到,返回前50个字符
  144. return mb_substr($this->user_agent, 0, 50) . '...';
  145. }
  146. /**
  147. * 按操作类型查询
  148. *
  149. * @param \Illuminate\Database\Eloquent\Builder $query
  150. * @param string|ADMIN_ACTION_TYPE $actionType
  151. * @return \Illuminate\Database\Eloquent\Builder
  152. */
  153. public function scopeByActionType($query, $actionType)
  154. {
  155. if ($actionType instanceof ADMIN_ACTION_TYPE) {
  156. $actionType = $actionType->value;
  157. }
  158. return $query->where('action_type', $actionType);
  159. }
  160. /**
  161. * 按管理员查询
  162. *
  163. * @param \Illuminate\Database\Eloquent\Builder $query
  164. * @param int $adminId
  165. * @return \Illuminate\Database\Eloquent\Builder
  166. */
  167. public function scopeByAdmin($query, int $adminId)
  168. {
  169. return $query->where('admin_id', $adminId);
  170. }
  171. /**
  172. * 按IP地址查询
  173. *
  174. * @param \Illuminate\Database\Eloquent\Builder $query
  175. * @param string $ipAddress
  176. * @return \Illuminate\Database\Eloquent\Builder
  177. */
  178. public function scopeByIpAddress($query, string $ipAddress)
  179. {
  180. return $query->where('ip_address', $ipAddress);
  181. }
  182. /**
  183. * 按时间范围查询
  184. *
  185. * @param \Illuminate\Database\Eloquent\Builder $query
  186. * @param string $startDate
  187. * @param string $endDate
  188. * @return \Illuminate\Database\Eloquent\Builder
  189. */
  190. public function scopeByDateRange($query, string $startDate, string $endDate)
  191. {
  192. return $query->whereBetween('created_at', [$startDate, $endDate]);
  193. }
  194. /**
  195. * 查询危险操作
  196. *
  197. * @param \Illuminate\Database\Eloquent\Builder $query
  198. * @return \Illuminate\Database\Eloquent\Builder
  199. */
  200. public function scopeDangerousActions($query)
  201. {
  202. $dangerousTypes = [];
  203. foreach (ADMIN_ACTION_TYPE::cases() as $type) {
  204. if ($type->isDangerous()) {
  205. $dangerousTypes[] = $type->value;
  206. }
  207. }
  208. return $query->whereIn('action_type', $dangerousTypes);
  209. }
  210. /**
  211. * 最近的操作
  212. *
  213. * @param \Illuminate\Database\Eloquent\Builder $query
  214. * @param int $hours
  215. * @return \Illuminate\Database\Eloquent\Builder
  216. */
  217. public function scopeRecent($query, int $hours = 24)
  218. {
  219. return $query->where('created_at', '>=', now()->subHours($hours));
  220. }
  221. }