PetActiveSkill.php 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. <?php
  2. namespace App\Module\Pet\Models;
  3. use UCore\ModelCore;
  4. use Illuminate\Database\Eloquent\Relations\BelongsTo;
  5. /**
  6. * 宠物激活技能模型
  7. *
  8. * 用于记录宠物当前激活的技能状态,支持定时任务自动处理
  9. *
  10. * @property int $id 主键ID
  11. * @property int $pet_id 宠物ID
  12. * @property int $skill_id 技能ID
  13. * @property string $skill_name 技能名称
  14. * @property \Carbon\Carbon $start_time 开始时间
  15. * @property \Carbon\Carbon $end_time 结束时间
  16. * @property string $status 状态:active-生效中,expired-已过期,cancelled-已取消
  17. * @property array $config 技能配置信息
  18. * @property \Carbon\Carbon $created_at 创建时间
  19. * @property \Carbon\Carbon $updated_at 更新时间
  20. */
  21. class PetActiveSkill extends ModelCore
  22. {
  23. /**
  24. * 数据表名
  25. *
  26. * @var string
  27. */
  28. protected $table = 'pet_active_skills';
  29. /**
  30. * 可批量赋值的属性
  31. *
  32. * @var array<int, string>
  33. */
  34. protected $fillable = [
  35. 'pet_id',
  36. 'skill_id',
  37. 'skill_name',
  38. 'start_time',
  39. 'end_time',
  40. 'status',
  41. 'config',
  42. ];
  43. /**
  44. * 属性类型转换
  45. *
  46. * @var array<string, string>
  47. */
  48. protected $casts = [
  49. 'start_time' => 'datetime',
  50. 'end_time' => 'datetime',
  51. 'config' => 'array',
  52. 'created_at' => 'datetime',
  53. 'updated_at' => 'datetime',
  54. ];
  55. /**
  56. * 技能状态常量
  57. */
  58. const STATUS_ACTIVE = 'active'; // 生效中
  59. const STATUS_EXPIRED = 'expired'; // 已过期
  60. const STATUS_CANCELLED = 'cancelled'; // 已取消
  61. /**
  62. * 关联宠物
  63. *
  64. * @return BelongsTo
  65. */
  66. public function pet(): BelongsTo
  67. {
  68. return $this->belongsTo(PetUser::class, 'pet_id');
  69. }
  70. /**
  71. * 关联技能配置
  72. *
  73. * @return BelongsTo
  74. */
  75. public function skill(): BelongsTo
  76. {
  77. return $this->belongsTo(PetSkill::class, 'skill_id');
  78. }
  79. /**
  80. * 检查技能是否仍然有效
  81. *
  82. * @return bool
  83. */
  84. public function isActive(): bool
  85. {
  86. return $this->status === self::STATUS_ACTIVE && $this->end_time > now();
  87. }
  88. /**
  89. * 检查技能是否已过期
  90. *
  91. * @return bool
  92. */
  93. public function isExpired(): bool
  94. {
  95. return $this->end_time <= now();
  96. }
  97. /**
  98. * 获取剩余时间(秒)
  99. *
  100. * @return int
  101. */
  102. public function getRemainingSeconds(): int
  103. {
  104. if ($this->isExpired()) {
  105. return 0;
  106. }
  107. return now()->diffInSeconds($this->end_time);
  108. }
  109. /**
  110. * 标记技能为已过期
  111. *
  112. * @return bool
  113. */
  114. public function markAsExpired(): bool
  115. {
  116. $this->status = self::STATUS_EXPIRED;
  117. return $this->save();
  118. }
  119. /**
  120. * 取消技能
  121. *
  122. * @return bool
  123. */
  124. public function cancel(): bool
  125. {
  126. $this->status = self::STATUS_CANCELLED;
  127. return $this->save();
  128. }
  129. /**
  130. * 更新最后检查时间
  131. *
  132. * @return bool
  133. */
  134. public function updateLastCheckTime(): bool
  135. {
  136. $config = $this->config;
  137. // 确保config是数组类型
  138. if (!is_array($config)) {
  139. // 如果是字符串,尝试解析JSON
  140. if (is_string($config)) {
  141. $config = json_decode($config, true);
  142. if (json_last_error() !== JSON_ERROR_NONE) {
  143. $config = [];
  144. }
  145. } else {
  146. $config = [];
  147. }
  148. }
  149. $config['last_check_time'] = now()->toDateTimeString();
  150. $this->config = $config;
  151. return $this->save();
  152. }
  153. /**
  154. * 获取最后检查时间
  155. *
  156. * @return \Carbon\Carbon|null
  157. */
  158. public function getLastCheckTime(): ?\Carbon\Carbon
  159. {
  160. $config = $this->config;
  161. // 确保config是数组类型
  162. if (!is_array($config)) {
  163. if (is_string($config)) {
  164. $config = json_decode($config, true);
  165. if (json_last_error() !== JSON_ERROR_NONE) {
  166. return null;
  167. }
  168. } else {
  169. return null;
  170. }
  171. }
  172. $lastCheckTime = $config['last_check_time'] ?? null;
  173. return $lastCheckTime ? \Carbon\Carbon::parse($lastCheckTime) : null;
  174. }
  175. /**
  176. * 检查是否需要执行检查
  177. *
  178. * @return bool
  179. */
  180. public function shouldCheck(): bool
  181. {
  182. if (!$this->isActive()) {
  183. return false;
  184. }
  185. return true; // 无间隔检查
  186. $lastCheckTime = $this->getLastCheckTime();
  187. if (!$lastCheckTime) {
  188. return true;
  189. }
  190. $config = $this->config;
  191. // 确保config是数组类型
  192. if (!is_array($config)) {
  193. if (is_string($config)) {
  194. $config = json_decode($config, true);
  195. if (json_last_error() !== JSON_ERROR_NONE) {
  196. $config = [];
  197. }
  198. } else {
  199. $config = [];
  200. }
  201. }
  202. $checkInterval = $config['check_interval'] ?? 60; // 默认60秒
  203. return now()->diffInSeconds($lastCheckTime) >= $checkInterval;
  204. }
  205. /**
  206. * 获取技能配置中的特定值
  207. *
  208. * @param string $key 配置键名
  209. * @param mixed $default 默认值
  210. * @return mixed
  211. */
  212. public function getConfigValue(string $key, $default = null)
  213. {
  214. $config = $this->config;
  215. // 确保config是数组类型
  216. if (!is_array($config)) {
  217. if (is_string($config)) {
  218. $config = json_decode($config, true);
  219. if (json_last_error() !== JSON_ERROR_NONE) {
  220. return $default;
  221. }
  222. } else {
  223. return $default;
  224. }
  225. }
  226. return $config[$key] ?? $default;
  227. }
  228. /**
  229. * 设置技能配置中的特定值
  230. *
  231. * @param string $key 配置键名
  232. * @param mixed $value 配置值
  233. * @return bool
  234. */
  235. public function setConfigValue(string $key, $value): bool
  236. {
  237. $config = $this->config;
  238. // 确保config是数组类型
  239. if (!is_array($config)) {
  240. if (is_string($config)) {
  241. $config = json_decode($config, true);
  242. if (json_last_error() !== JSON_ERROR_NONE) {
  243. $config = [];
  244. }
  245. } else {
  246. $config = [];
  247. }
  248. }
  249. $config[$key] = $value;
  250. $this->config = $config;
  251. return $this->save();
  252. }
  253. /**
  254. * 查询生效中的技能
  255. *
  256. * @param \Illuminate\Database\Eloquent\Builder $query
  257. * @return \Illuminate\Database\Eloquent\Builder
  258. */
  259. public function scopeActive($query)
  260. {
  261. return $query->where('status', self::STATUS_ACTIVE)
  262. ->where('end_time', '>', now());
  263. }
  264. /**
  265. * 查询已过期的技能
  266. *
  267. * @param \Illuminate\Database\Eloquent\Builder $query
  268. * @return \Illuminate\Database\Eloquent\Builder
  269. */
  270. public function scopeExpired($query)
  271. {
  272. return $query->where('end_time', '<=', now());
  273. }
  274. /**
  275. * 查询特定技能类型
  276. *
  277. * @param \Illuminate\Database\Eloquent\Builder $query
  278. * @param string $skillName 技能名称
  279. * @return \Illuminate\Database\Eloquent\Builder
  280. */
  281. public function scopeBySkillName($query, string $skillName)
  282. {
  283. return $query->where('skill_name', $skillName);
  284. }
  285. /**
  286. * 查询特定宠物的技能
  287. *
  288. * @param \Illuminate\Database\Eloquent\Builder $query
  289. * @param int $petId 宠物ID
  290. * @return \Illuminate\Database\Eloquent\Builder
  291. */
  292. public function scopeByPet($query, int $petId)
  293. {
  294. return $query->where('pet_id', $petId);
  295. }
  296. }