FarmCropLog.php 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077
  1. <?php
  2. namespace App\Module\Farm\Models;
  3. use UCore\ModelCore;
  4. use Illuminate\Database\Eloquent\Relations\BelongsTo;
  5. use App\Module\Farm\Enums\GROWTH_STAGE;
  6. use App\Module\Farm\Enums\DISASTER_TYPE;
  7. /**
  8. * 作物事件日志模型
  9. *
  10. * @property int $id 主键ID
  11. * @property int $user_id 用户ID
  12. * @property int $land_id 土地ID
  13. * @property int $crop_id 作物ID
  14. * @property int $seed_id 种子ID
  15. * @property string $event_type 事件类型
  16. * @property array|null $event_data 事件详细数据
  17. * @property int $growth_stage 发生时的生长阶段
  18. * @property int $land_type 土地类型
  19. * @property \Carbon\Carbon $created_at 事件发生时间
  20. * @property \Carbon\Carbon $updated_at 更新时间
  21. *
  22. * @property-read FarmCrop $crop 关联的作物
  23. * @property-read FarmSeed $seed 关联的种子
  24. * @property-read FarmLand $land 关联的土地
  25. */
  26. class FarmCropLog extends ModelCore
  27. {
  28. protected $table = 'farm_crop_logs';
  29. // 事件类型常量
  30. const EVENT_FRUIT_CONFIRMED = 'fruit_confirmed'; // 确认果实种类
  31. const EVENT_OUTPUT_CALCULATED = 'output_calculated'; // 确认产出数量
  32. const EVENT_DISASTER_OCCURRED = 'disaster_occurred'; // 灾害产生
  33. const EVENT_DISASTER_CLEARED = 'disaster_cleared'; // 灾害清除
  34. const EVENT_HARVESTED = 'harvested'; // 收获
  35. const EVENT_FERTILIZED = 'fertilized'; // 施肥
  36. const EVENT_PESTICIDE_USED = 'pesticide_used'; // 使用杀虫剂
  37. const EVENT_WEEDICIDE_USED = 'weedicide_used'; // 使用除草剂
  38. const EVENT_WATERING = 'watering'; // 浇水
  39. const EVENT_REMOVED = 'removed'; // 铲除作物
  40. const EVENT_PICKED = 'picked'; // 摘取
  41. protected $fillable = [
  42. 'user_id',
  43. 'land_id',
  44. 'crop_id',
  45. 'seed_id',
  46. 'event_type',
  47. 'event_data',
  48. 'growth_stage',
  49. 'land_type',
  50. ];
  51. protected $casts = [
  52. 'event_data' => 'array',
  53. 'growth_stage' => 'integer',
  54. 'land_type' => 'integer',
  55. ];
  56. /**
  57. * 关联作物
  58. */
  59. public function crop(): BelongsTo
  60. {
  61. return $this->belongsTo(FarmCrop::class, 'crop_id');
  62. }
  63. /**
  64. * 关联种子
  65. */
  66. public function seed(): BelongsTo
  67. {
  68. return $this->belongsTo(FarmSeed::class, 'seed_id');
  69. }
  70. /**
  71. * 关联土地
  72. */
  73. public function land(): BelongsTo
  74. {
  75. return $this->belongsTo(FarmLand::class, 'land_id');
  76. }
  77. /**
  78. * 获取生长阶段名称
  79. */
  80. public function getGrowthStageNameAttribute(): string
  81. {
  82. return GROWTH_STAGE::getName($this->growth_stage);
  83. }
  84. /**
  85. * 获取事件类型名称
  86. */
  87. public function getEventTypeNameAttribute(): string
  88. {
  89. return match($this->event_type) {
  90. self::EVENT_FRUIT_CONFIRMED => '确认果实种类',
  91. self::EVENT_OUTPUT_CALCULATED => '确认产出数量',
  92. self::EVENT_DISASTER_OCCURRED => '灾害产生',
  93. self::EVENT_DISASTER_CLEARED => '灾害清除',
  94. self::EVENT_HARVESTED => '收获',
  95. self::EVENT_FERTILIZED => '施肥',
  96. self::EVENT_PESTICIDE_USED => '使用杀虫剂',
  97. self::EVENT_WEEDICIDE_USED => '使用除草剂',
  98. self::EVENT_WATERING => '浇水',
  99. self::EVENT_REMOVED => '铲除作物',
  100. self::EVENT_PICKED => '摘取',
  101. default => '未知事件'
  102. };
  103. }
  104. /**
  105. * 作用域:按事件类型筛选
  106. */
  107. public function scopeByEventType($query, string $eventType)
  108. {
  109. return $query->where('event_type', $eventType);
  110. }
  111. /**
  112. * 作用域:按作物筛选
  113. */
  114. public function scopeByCrop($query, int $cropId)
  115. {
  116. return $query->where('crop_id', $cropId);
  117. }
  118. /**
  119. * 作用域:按用户筛选
  120. */
  121. public function scopeByUser($query, int $userId)
  122. {
  123. return $query->where('user_id', $userId);
  124. }
  125. /**
  126. * 静态方法:记录确认果实种类事件
  127. */
  128. public static function logFruitConfirmed(int $userId, int $landId, int $cropId, int $seedId, array $eventData): self
  129. {
  130. return self::create([
  131. 'user_id' => $userId,
  132. 'land_id' => $landId,
  133. 'crop_id' => $cropId,
  134. 'seed_id' => $seedId,
  135. 'event_type' => self::EVENT_FRUIT_CONFIRMED,
  136. 'event_data' => $eventData,
  137. 'growth_stage' => $eventData['growth_stage'] ?? GROWTH_STAGE::SPROUT->value,
  138. 'land_type' => $eventData['land_type'] ?? 1,
  139. ]);
  140. }
  141. /**
  142. * 静态方法:记录确认产出数量事件
  143. */
  144. public static function logOutputCalculated(int $userId, int $landId, int $cropId, int $seedId, array $eventData): self
  145. {
  146. return self::create([
  147. 'user_id' => $userId,
  148. 'land_id' => $landId,
  149. 'crop_id' => $cropId,
  150. 'seed_id' => $seedId,
  151. 'event_type' => self::EVENT_OUTPUT_CALCULATED,
  152. 'event_data' => $eventData,
  153. 'growth_stage' => $eventData['growth_stage'] ?? GROWTH_STAGE::MATURE->value,
  154. 'land_type' => $eventData['land_type'] ?? 1,
  155. ]);
  156. }
  157. /**
  158. * 静态方法:记录灾害产生事件
  159. */
  160. public static function logDisasterOccurred(int $userId, int $landId, int $cropId, int $seedId, array $eventData): self
  161. {
  162. return self::create([
  163. 'user_id' => $userId,
  164. 'land_id' => $landId,
  165. 'crop_id' => $cropId,
  166. 'seed_id' => $seedId,
  167. 'event_type' => self::EVENT_DISASTER_OCCURRED,
  168. 'event_data' => $eventData,
  169. 'growth_stage' => $eventData['growth_stage'] ?? GROWTH_STAGE::GROWTH->value,
  170. 'land_type' => $eventData['land_type'] ?? 1,
  171. ]);
  172. }
  173. /**
  174. * 静态方法:记录灾害清除事件
  175. */
  176. public static function logDisasterCleared(int $userId, int $landId, int $cropId, int $seedId, array $eventData): self
  177. {
  178. return self::create([
  179. 'user_id' => $userId,
  180. 'land_id' => $landId,
  181. 'crop_id' => $cropId,
  182. 'seed_id' => $seedId,
  183. 'event_type' => self::EVENT_DISASTER_CLEARED,
  184. 'event_data' => $eventData,
  185. 'growth_stage' => $eventData['growth_stage'] ?? GROWTH_STAGE::GROWTH->value,
  186. 'land_type' => $eventData['land_type'] ?? 1,
  187. ]);
  188. }
  189. /**
  190. * 静态方法:记录收获事件
  191. */
  192. public static function logHarvested(int $userId, int $landId, int $cropId, int $seedId, array $eventData): self
  193. {
  194. return self::create([
  195. 'user_id' => $userId,
  196. 'land_id' => $landId,
  197. 'crop_id' => $cropId,
  198. 'seed_id' => $seedId,
  199. 'event_type' => self::EVENT_HARVESTED,
  200. 'event_data' => $eventData,
  201. 'growth_stage' => $eventData['growth_stage'] ?? GROWTH_STAGE::MATURE->value,
  202. 'land_type' => $eventData['land_type'] ?? 1,
  203. ]);
  204. }
  205. /**
  206. * 静态方法:记录施肥事件
  207. */
  208. public static function logFertilized(int $userId, int $landId, int $cropId, int $seedId, array $eventData): self
  209. {
  210. return self::create([
  211. 'user_id' => $userId,
  212. 'land_id' => $landId,
  213. 'crop_id' => $cropId,
  214. 'seed_id' => $seedId,
  215. 'event_type' => self::EVENT_FERTILIZED,
  216. 'event_data' => $eventData,
  217. 'growth_stage' => $eventData['growth_stage'] ?? GROWTH_STAGE::SPROUT->value,
  218. 'land_type' => $eventData['land_type'] ?? 1,
  219. ]);
  220. }
  221. /**
  222. * 静态方法:记录使用杀虫剂事件
  223. */
  224. public static function logPesticideUsed(int $userId, int $landId, int $cropId, int $seedId, array $eventData): self
  225. {
  226. return self::create([
  227. 'user_id' => $userId,
  228. 'land_id' => $landId,
  229. 'crop_id' => $cropId,
  230. 'seed_id' => $seedId,
  231. 'event_type' => self::EVENT_PESTICIDE_USED,
  232. 'event_data' => $eventData,
  233. 'growth_stage' => $eventData['growth_stage'] ?? GROWTH_STAGE::SPROUT->value,
  234. 'land_type' => $eventData['land_type'] ?? 1,
  235. ]);
  236. }
  237. /**
  238. * 静态方法:记录使用除草剂事件
  239. */
  240. public static function logWeedicideUsed(int $userId, int $landId, int $cropId, int $seedId, array $eventData): self
  241. {
  242. return self::create([
  243. 'user_id' => $userId,
  244. 'land_id' => $landId,
  245. 'crop_id' => $cropId,
  246. 'seed_id' => $seedId,
  247. 'event_type' => self::EVENT_WEEDICIDE_USED,
  248. 'event_data' => $eventData,
  249. 'growth_stage' => $eventData['growth_stage'] ?? GROWTH_STAGE::SPROUT->value,
  250. 'land_type' => $eventData['land_type'] ?? 1,
  251. ]);
  252. }
  253. /**
  254. * 静态方法:记录浇水事件
  255. */
  256. public static function logWatering(int $userId, int $landId, int $cropId, int $seedId, array $eventData): self
  257. {
  258. return self::create([
  259. 'user_id' => $userId,
  260. 'land_id' => $landId,
  261. 'crop_id' => $cropId,
  262. 'seed_id' => $seedId,
  263. 'event_type' => self::EVENT_WATERING,
  264. 'event_data' => $eventData,
  265. 'growth_stage' => $eventData['growth_stage'] ?? GROWTH_STAGE::SPROUT->value,
  266. 'land_type' => $eventData['land_type'] ?? 1,
  267. ]);
  268. }
  269. /**
  270. * 静态方法:记录摘取事件
  271. */
  272. public static function logPicked(int $userId, int $landId, int $cropId, int $seedId, array $eventData): self
  273. {
  274. return self::create([
  275. 'user_id' => $userId,
  276. 'land_id' => $landId,
  277. 'crop_id' => $cropId,
  278. 'seed_id' => $seedId,
  279. 'event_type' => self::EVENT_PICKED,
  280. 'event_data' => $eventData,
  281. 'growth_stage' => $eventData['growth_stage'] ?? GROWTH_STAGE::MATURE->value,
  282. 'land_type' => $eventData['land_type'] ?? 1,
  283. ]);
  284. }
  285. /**
  286. * 获取可读的事件数据摘要
  287. *
  288. * @return string
  289. */
  290. public function getEventDataSummaryAttribute(): string
  291. {
  292. if (empty($this->event_data)) {
  293. return '无数据';
  294. }
  295. $data = $this->event_data;
  296. return match($this->event_type) {
  297. self::EVENT_FRUIT_CONFIRMED => $this->parseFruitConfirmedData($data),
  298. self::EVENT_OUTPUT_CALCULATED => $this->parseOutputCalculatedData($data),
  299. self::EVENT_DISASTER_OCCURRED => $this->parseDisasterOccurredData($data),
  300. self::EVENT_DISASTER_CLEARED => $this->parseDisasterClearedData($data),
  301. self::EVENT_HARVESTED => $this->parseHarvestedData($data),
  302. self::EVENT_FERTILIZED => $this->parseFertilizedData($data),
  303. self::EVENT_PESTICIDE_USED => $this->parsePesticideUsedData($data),
  304. self::EVENT_WEEDICIDE_USED => $this->parseWeedicideUsedData($data),
  305. self::EVENT_WATERING => $this->parseWateringData($data),
  306. self::EVENT_REMOVED => $this->parseRemovedData($data),
  307. self::EVENT_PICKED => $this->parsePickedData($data),
  308. default => '未知事件类型'
  309. };
  310. }
  311. /**
  312. * 获取可读的详细事件数据
  313. *
  314. * @return string
  315. */
  316. public function getEventDataDetailAttribute(): string
  317. {
  318. if (empty($this->event_data)) {
  319. return '无数据';
  320. }
  321. $data = $this->event_data;
  322. return match($this->event_type) {
  323. self::EVENT_FRUIT_CONFIRMED => $this->parseFruitConfirmedDataDetail($data),
  324. self::EVENT_OUTPUT_CALCULATED => $this->parseOutputCalculatedDataDetail($data),
  325. self::EVENT_DISASTER_OCCURRED => $this->parseDisasterOccurredDataDetail($data),
  326. self::EVENT_DISASTER_CLEARED => $this->parseDisasterClearedDataDetail($data),
  327. self::EVENT_HARVESTED => $this->parseHarvestedDataDetail($data),
  328. self::EVENT_FERTILIZED => $this->parseFertilizedDataDetail($data),
  329. self::EVENT_PESTICIDE_USED => $this->parsePesticideUsedDataDetail($data),
  330. self::EVENT_WEEDICIDE_USED => $this->parseWeedicideUsedDataDetail($data),
  331. self::EVENT_WATERING => $this->parseWateringDataDetail($data),
  332. self::EVENT_PICKED => $this->parsePickedDataDetail($data),
  333. default => '<pre>' . json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) . '</pre>'
  334. };
  335. }
  336. /**
  337. * 解析确认果实种类事件数据(摘要)
  338. */
  339. private function parseFruitConfirmedData(array $data): string
  340. {
  341. $itemId = $data['final_output_item_id'] ?? '未知';
  342. $isMystery = $data['is_mystery_seed'] ?? false;
  343. $seedType = $isMystery ? '神秘种子' : '普通种子';
  344. return "确认产出物品ID: {$itemId} ({$seedType})";
  345. }
  346. /**
  347. * 解析确认果实种类事件数据(详细)
  348. */
  349. private function parseFruitConfirmedDataDetail(array $data): string
  350. {
  351. $details = [];
  352. $details[] = '<strong>确认果实种类事件详情:</strong>';
  353. $details[] = '• 最终产出物品ID: ' . ($data['final_output_item_id'] ?? '未知');
  354. $details[] = '• 生长阶段: ' . \App\Module\Farm\Enums\GROWTH_STAGE::getName($data['growth_stage'] ?? 0);
  355. $details[] = '• 土地类型: ' . ($data['land_type'] ?? '未知');
  356. $details[] = '• 是否神秘种子: ' . (($data['is_mystery_seed'] ?? false) ? '是' : '否');
  357. if (isset($data['selected_output'])) {
  358. $output = $data['selected_output'];
  359. $details[] = '• 选中产出信息:';
  360. $details[] = ' - 物品ID: ' . ($output['item_id'] ?? '未知');
  361. $details[] = ' - 最大数量: ' . ($output['max_amount'] ?? '未知');
  362. }
  363. if (isset($data['land_effect_applied'])) {
  364. $details[] = '• 土地效果已应用: ' . ($data['land_effect_applied'] ? '是' : '否');
  365. }
  366. return implode('<br>', $details);
  367. }
  368. /**
  369. * 解析确认产出数量事件数据(摘要)
  370. */
  371. private function parseOutputCalculatedData(array $data): string
  372. {
  373. $baseAmount = $data['base_amount'] ?? 0;
  374. $finalAmount = $data['final_amount'] ?? 0;
  375. $hasDisaster = $data['has_disaster'] ?? false;
  376. return "基础产量: {$baseAmount}, 最终产量: {$finalAmount}" . ($hasDisaster ? ' (有灾害)' : '');
  377. }
  378. /**
  379. * 解析确认产出数量事件数据(详细)
  380. */
  381. private function parseOutputCalculatedDataDetail(array $data): string
  382. {
  383. $details = [];
  384. $details[] = '<strong>确认产出数量事件详情:</strong>';
  385. $details[] = '• 基础产量: ' . ($data['base_amount'] ?? '未知');
  386. $details[] = '• 最终产量: ' . ($data['final_amount'] ?? '未知');
  387. $details[] = '• 土地加成: ' . ($data['land_bonus'] ?? 0) . '%';
  388. $details[] = '• 房屋加成: ' . ($data['house_bonus'] ?? 0) . '%';
  389. $details[] = '• 是否有灾害: ' . (($data['has_disaster'] ?? false) ? '是' : '否');
  390. if (isset($data['disaster_penalty'])) {
  391. $details[] = '• 灾害惩罚: ' . $data['disaster_penalty'] . '%';
  392. }
  393. $details[] = '• 是否有丰收加持: ' . (($data['has_harvest_buff'] ?? false) ? '是' : '否');
  394. $details[] = '• 灾害最大产量: ' . ($data['disaster_max_amount'] ?? '未知');
  395. $details[] = '• 全局最大产量: ' . ($data['global_max_output'] ?? '未知');
  396. $details[] = '• 最终产出物品ID: ' . ($data['final_output_item_id'] ?? '未知');
  397. return implode('<br>', $details);
  398. }
  399. /**
  400. * 解析灾害产生事件数据(摘要)
  401. */
  402. private function parseDisasterOccurredData(array $data): string
  403. {
  404. $disasterType = $data['disaster_type'] ?? $data['disaster_info']['type'] ?? 0;
  405. $disasterName = \App\Module\Farm\Enums\DISASTER_TYPE::getName($disasterType);
  406. $generatedAt = $data['generated_at'] ?? $data['disaster_info']['generated_ts'] ?? '未知时间';
  407. return "灾害类型: {$disasterName}, 发生时间: {$generatedAt}";
  408. }
  409. /**
  410. * 解析灾害产生事件数据(详细)
  411. */
  412. private function parseDisasterOccurredDataDetail(array $data): string
  413. {
  414. $details = [];
  415. $details[] = '<strong>灾害产生事件详情:</strong>';
  416. $disasterType = $data['disaster_type'] ?? $data['disaster_info']['type'] ?? 0;
  417. $details[] = '• 灾害类型: ' . \App\Module\Farm\Enums\DISASTER_TYPE::getName($disasterType);
  418. $details[] = '• 发生时间: ' . ($data['generated_at'] ?? $data['disaster_info']['generated_ts'] ?? '未知');
  419. $details[] = '• 土地类型: ' . ($data['land_type'] ?? '未知');
  420. $details[] = '• 生长阶段: ' . \App\Module\Farm\Enums\GROWTH_STAGE::getName($data['growth_stage'] ?? 0);
  421. if (isset($data['old_land_status']) && isset($data['new_land_status'])) {
  422. $details[] = '• 土地状态变化: ' . $data['old_land_status'] . ' → ' . $data['new_land_status'];
  423. }
  424. if (isset($data['disaster_info'])) {
  425. $info = $data['disaster_info'];
  426. $details[] = '• 灾害状态: ' . ($info['status'] ?? '未知');
  427. }
  428. return implode('<br>', $details);
  429. }
  430. /**
  431. * 解析灾害清除事件数据(摘要)
  432. */
  433. private function parseDisasterClearedData(array $data): string
  434. {
  435. $disasterType = $data['disaster_type'] ?? 0;
  436. $disasterName = \App\Module\Farm\Enums\DISASTER_TYPE::getName($disasterType);
  437. $itemId = $data['item_id'] ?? '未知';
  438. $successRate = $data['success_rate'] ?? 0;
  439. return "清除{$disasterName}, 使用物品ID: {$itemId}, 成功率: {$successRate}%";
  440. }
  441. /**
  442. * 解析灾害清除事件数据(详细)
  443. */
  444. private function parseDisasterClearedDataDetail(array $data): string
  445. {
  446. $details = [];
  447. $details[] = '<strong>灾害清除事件详情:</strong>';
  448. $disasterType = $data['disaster_type'] ?? 0;
  449. $details[] = '• 灾害类型: ' . \App\Module\Farm\Enums\DISASTER_TYPE::getName($disasterType);
  450. $details[] = '• 使用物品ID: ' . ($data['item_id'] ?? '未知');
  451. $details[] = '• 成功率: ' . ($data['success_rate'] ?? 0) . '%';
  452. $details[] = '• 生长阶段: ' . \App\Module\Farm\Enums\GROWTH_STAGE::getName($data['growth_stage'] ?? 0);
  453. $details[] = '• 土地类型: ' . ($data['land_type'] ?? '未知');
  454. $details[] = '• 消耗来源类型: ' . ($data['source_type'] ?? '未知');
  455. $details[] = '• 清除时间: ' . ($data['cleared_at'] ?? '未知');
  456. return implode('<br>', $details);
  457. }
  458. /**
  459. * 解析收获事件数据(摘要)
  460. */
  461. private function parseHarvestedData(array $data): string
  462. {
  463. $itemId = $data['item_id'] ?? '未知';
  464. $amount = $data['amount'] ?? 0;
  465. return "收获物品ID: {$itemId}, 数量: {$amount}";
  466. }
  467. /**
  468. * 解析收获事件数据(详细)
  469. */
  470. private function parseHarvestedDataDetail(array $data): string
  471. {
  472. $details = [];
  473. $details[] = '<strong>收获事件详情:</strong>';
  474. $details[] = '• 收获物品ID: ' . ($data['item_id'] ?? '未知');
  475. $details[] = '• 收获数量: ' . ($data['amount'] ?? '未知');
  476. $details[] = '• 收获记录ID: ' . ($data['harvest_log_id'] ?? '未知');
  477. $details[] = '• 生长阶段: ' . \App\Module\Farm\Enums\GROWTH_STAGE::getName($data['growth_stage'] ?? 0);
  478. $details[] = '• 土地类型: ' . ($data['land_type'] ?? '未知');
  479. if (isset($data['old_stage']) && isset($data['new_stage'])) {
  480. $oldStageName = \App\Module\Farm\Enums\GROWTH_STAGE::getName($data['old_stage']);
  481. $newStageName = \App\Module\Farm\Enums\GROWTH_STAGE::getName($data['new_stage']);
  482. $details[] = '• 阶段变化: ' . $oldStageName . ' → ' . $newStageName;
  483. }
  484. if (isset($data['land_status_before']) && isset($data['land_status_after'])) {
  485. $details[] = '• 土地状态变化: ' . $data['land_status_before'] . ' → ' . $data['land_status_after'];
  486. }
  487. return implode('<br>', $details);
  488. }
  489. /**
  490. * 解析施肥事件数据(摘要)
  491. */
  492. private function parseFertilizedData(array $data): string
  493. {
  494. $cropGrowthTime = $data['crop_growth_time'] ?? 0;
  495. $fertilizedAt = $data['fertilized_at'] ?? '未知时间';
  496. return "减少生长时间: {$cropGrowthTime}秒, 施肥时间: {$fertilizedAt}";
  497. }
  498. /**
  499. * 解析施肥事件数据(详细)
  500. */
  501. private function parseFertilizedDataDetail(array $data): string
  502. {
  503. $details = [];
  504. $details[] = '<strong>施肥事件详情:</strong>';
  505. $details[] = '• 生长阶段: ' . \App\Module\Farm\Enums\GROWTH_STAGE::getName($data['growth_stage'] ?? 0);
  506. $details[] = '• 土地类型: ' . ($data['land_type'] ?? '未知');
  507. $details[] = '• 减少生长时间: ' . ($data['crop_growth_time'] ?? 0) . '秒';
  508. $details[] = '• 阶段结束时间: ' . ($data['stage_end_time'] ?? '未知');
  509. $details[] = '• 施肥时间: ' . ($data['fertilized_at'] ?? '未知');
  510. return implode('<br>', $details);
  511. }
  512. /**
  513. * 解析使用杀虫剂事件数据(摘要)
  514. */
  515. private function parsePesticideUsedData(array $data): string
  516. {
  517. $itemId = $data['item_id'] ?? '未知';
  518. $successRate = $data['success_rate'] ?? 0;
  519. return "使用杀虫剂ID: {$itemId}, 成功率: {$successRate}%";
  520. }
  521. /**
  522. * 解析使用杀虫剂事件数据(详细)
  523. */
  524. private function parsePesticideUsedDataDetail(array $data): string
  525. {
  526. $details = [];
  527. $details[] = '<strong>使用杀虫剂事件详情:</strong>';
  528. $details[] = '• 生长阶段: ' . \App\Module\Farm\Enums\GROWTH_STAGE::getName($data['growth_stage'] ?? 0);
  529. $details[] = '• 土地类型: ' . ($data['land_type'] ?? '未知');
  530. $details[] = '• 使用物品ID: ' . ($data['item_id'] ?? '未知');
  531. $details[] = '• 成功率: ' . ($data['success_rate'] ?? 0) . '%';
  532. $details[] = '• 消耗来源类型: ' . ($data['source_type'] ?? '未知');
  533. $details[] = '• 使用时间: ' . ($data['cleared_at'] ?? '未知');
  534. return implode('<br>', $details);
  535. }
  536. /**
  537. * 解析使用除草剂事件数据(摘要)
  538. */
  539. private function parseWeedicideUsedData(array $data): string
  540. {
  541. $itemId = $data['item_id'] ?? '未知';
  542. $successRate = $data['success_rate'] ?? 0;
  543. return "使用除草剂ID: {$itemId}, 成功率: {$successRate}%";
  544. }
  545. /**
  546. * 解析使用除草剂事件数据(详细)
  547. */
  548. private function parseWeedicideUsedDataDetail(array $data): string
  549. {
  550. $details = [];
  551. $details[] = '<strong>使用除草剂事件详情:</strong>';
  552. $details[] = '• 生长阶段: ' . \App\Module\Farm\Enums\GROWTH_STAGE::getName($data['growth_stage'] ?? 0);
  553. $details[] = '• 土地类型: ' . ($data['land_type'] ?? '未知');
  554. $details[] = '• 使用物品ID: ' . ($data['item_id'] ?? '未知');
  555. $details[] = '• 成功率: ' . ($data['success_rate'] ?? 0) . '%';
  556. $details[] = '• 消耗来源类型: ' . ($data['source_type'] ?? '未知');
  557. $details[] = '• 使用时间: ' . ($data['cleared_at'] ?? '未知');
  558. return implode('<br>', $details);
  559. }
  560. /**
  561. * 解析浇水事件数据(摘要)
  562. */
  563. private function parseWateringData(array $data): string
  564. {
  565. $itemId = $data['item_id'] ?? '未知';
  566. $successRate = $data['success_rate'] ?? 0;
  567. return "浇水物品ID: {$itemId}, 成功率: {$successRate}%";
  568. }
  569. /**
  570. * 解析浇水事件数据(详细)
  571. */
  572. private function parseWateringDataDetail(array $data): string
  573. {
  574. $details = [];
  575. $details[] = '<strong>浇水事件详情:</strong>';
  576. $details[] = '• 生长阶段: ' . \App\Module\Farm\Enums\GROWTH_STAGE::getName($data['growth_stage'] ?? 0);
  577. $details[] = '• 土地类型: ' . ($data['land_type'] ?? '未知');
  578. $details[] = '• 使用物品ID: ' . ($data['item_id'] ?? '未知');
  579. $details[] = '• 成功率: ' . ($data['success_rate'] ?? 0) . '%';
  580. $details[] = '• 消耗来源类型: ' . ($data['source_type'] ?? '未知');
  581. $details[] = '• 浇水时间: ' . ($data['cleared_at'] ?? '未知');
  582. return implode('<br>', $details);
  583. }
  584. /**
  585. * 解析摘取事件数据(摘要)
  586. */
  587. private function parsePickedData(array $data): string
  588. {
  589. $pickerId = $data['picker_id'] ?? '未知';
  590. $pickAmount = $data['pick_amount'] ?? 0;
  591. $itemId = $data['item_id'] ?? '未知';
  592. $pickSource = $data['pick_source'] ?? '未知';
  593. return "摘取者ID: {$pickerId}, 摘取数量: {$pickAmount}, 物品ID: {$itemId}, 来源: {$pickSource}";
  594. }
  595. /**
  596. * 解析摘取事件数据(详细)
  597. */
  598. private function parsePickedDataDetail(array $data): string
  599. {
  600. $details = [];
  601. $details[] = '<strong>摘取事件详情:</strong>';
  602. $details[] = '• 摘取者ID: ' . ($data['picker_id'] ?? '未知');
  603. $details[] = '• 摘取数量: ' . ($data['pick_amount'] ?? '未知');
  604. $details[] = '• 摘取后剩余数量: ' . ($data['remaining_amount'] ?? '未知');
  605. $details[] = '• 摘取比例: ' . (($data['pick_ratio'] ?? 0) * 100) . '%';
  606. $details[] = '• 摘取来源: ' . ($data['pick_source'] ?? '未知');
  607. $details[] = '• 来源ID: ' . ($data['source_id'] ?? '无');
  608. $details[] = '• 摘取物品ID: ' . ($data['item_id'] ?? '未知');
  609. $details[] = '• 累计摘取数量: ' . ($data['total_picked'] ?? '未知');
  610. $details[] = '• 冷却结束时间: ' . ($data['cooldown_end'] ?? '未知');
  611. $details[] = '• 摘取者IP: ' . ($data['ip_address'] ?? '未知');
  612. return implode('<br>', $details);
  613. }
  614. /**
  615. * 静态方法:解析事件数据摘要
  616. *
  617. * @param string $eventType
  618. * @param array $data
  619. * @return string
  620. */
  621. public static function parseEventDataSummary(string $eventType, array $data): string
  622. {
  623. if (empty($data)) {
  624. return '无数据';
  625. }
  626. return match($eventType) {
  627. self::EVENT_FRUIT_CONFIRMED => self::parseFruitConfirmedSummary($data),
  628. self::EVENT_OUTPUT_CALCULATED => self::parseOutputCalculatedSummary($data),
  629. self::EVENT_DISASTER_OCCURRED => self::parseDisasterOccurredSummary($data),
  630. self::EVENT_DISASTER_CLEARED => self::parseDisasterClearedSummary($data),
  631. self::EVENT_HARVESTED => self::parseHarvestedSummary($data),
  632. self::EVENT_FERTILIZED => self::parseFertilizedSummary($data),
  633. self::EVENT_PESTICIDE_USED => self::parsePesticideUsedSummary($data),
  634. self::EVENT_WEEDICIDE_USED => self::parseWeedicideUsedSummary($data),
  635. self::EVENT_WATERING => self::parseWateringSummary($data),
  636. self::EVENT_REMOVED => self::parseRemovedSummary($data),
  637. self::EVENT_PICKED => self::parsePickedSummary($data),
  638. default => '未知事件类型'
  639. };
  640. }
  641. /**
  642. * 静态方法:解析事件数据详情
  643. *
  644. * @param string $eventType
  645. * @param array $data
  646. * @return string
  647. */
  648. public static function parseEventDataDetail(string $eventType, array $data): string
  649. {
  650. if (empty($data)) {
  651. return '无数据';
  652. }
  653. return match($eventType) {
  654. self::EVENT_FRUIT_CONFIRMED => self::parseFruitConfirmedDetail($data),
  655. self::EVENT_OUTPUT_CALCULATED => self::parseOutputCalculatedDetail($data),
  656. self::EVENT_DISASTER_OCCURRED => self::parseDisasterOccurredDetail($data),
  657. self::EVENT_DISASTER_CLEARED => self::parseDisasterClearedDetail($data),
  658. self::EVENT_HARVESTED => self::parseHarvestedDetail($data),
  659. self::EVENT_FERTILIZED => self::parseFertilizedDetail($data),
  660. self::EVENT_PESTICIDE_USED => self::parsePesticideUsedDetail($data),
  661. self::EVENT_WEEDICIDE_USED => self::parseWeedicideUsedDetail($data),
  662. self::EVENT_WATERING => self::parseWateringDetail($data),
  663. self::EVENT_REMOVED => self::parseRemovedDetail($data),
  664. self::EVENT_PICKED => self::parsePickedDetail($data),
  665. default => '<pre>' . json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) . '</pre>'
  666. };
  667. }
  668. // 静态解析方法 - 摘要版本
  669. private static function parseFruitConfirmedSummary(array $data): string
  670. {
  671. $itemId = $data['final_output_item_id'] ?? '未知';
  672. $isMystery = $data['is_mystery_seed'] ?? false;
  673. $seedType = $isMystery ? '神秘种子' : '普通种子';
  674. return "确认产出物品ID: {$itemId} ({$seedType})";
  675. }
  676. private static function parseOutputCalculatedSummary(array $data): string
  677. {
  678. $baseAmount = $data['base_amount'] ?? 0;
  679. $finalAmount = $data['final_amount'] ?? 0;
  680. $hasDisaster = $data['has_disaster'] ?? false;
  681. return "基础产量: {$baseAmount}, 最终产量: {$finalAmount}" . ($hasDisaster ? ' (有灾害)' : '');
  682. }
  683. private static function parseDisasterOccurredSummary(array $data): string
  684. {
  685. $disasterType = $data['disaster_type'] ?? $data['disaster_info']['type'] ?? 0;
  686. $disasterName = DISASTER_TYPE::getName($disasterType);
  687. $generatedAt = $data['generated_at'] ?? $data['disaster_info']['generated_ts'] ?? '未知时间';
  688. return "灾害类型: {$disasterName}, 发生时间: {$generatedAt}";
  689. }
  690. private static function parseDisasterClearedSummary(array $data): string
  691. {
  692. $disasterType = $data['disaster_type'] ?? 0;
  693. $disasterName = DISASTER_TYPE::getName($disasterType);
  694. $itemId = $data['item_id'] ?? '未知';
  695. $successRate = $data['success_rate'] ?? 0;
  696. return "清除{$disasterName}, 使用物品ID: {$itemId}, 成功率: {$successRate}%";
  697. }
  698. private static function parseHarvestedSummary(array $data): string
  699. {
  700. $itemId = $data['item_id'] ?? '未知';
  701. $amount = $data['amount'] ?? 0;
  702. return "收获物品ID: {$itemId}, 数量: {$amount}";
  703. }
  704. private static function parseFertilizedSummary(array $data): string
  705. {
  706. $cropGrowthTime = $data['crop_growth_time'] ?? 0;
  707. $fertilizedAt = $data['fertilized_at'] ?? '未知时间';
  708. return "减少生长时间: {$cropGrowthTime}秒, 施肥时间: {$fertilizedAt}";
  709. }
  710. private static function parsePesticideUsedSummary(array $data): string
  711. {
  712. $itemId = $data['item_id'] ?? '未知';
  713. $successRate = $data['success_rate'] ?? 0;
  714. return "使用杀虫剂ID: {$itemId}, 成功率: {$successRate}%";
  715. }
  716. private static function parseWeedicideUsedSummary(array $data): string
  717. {
  718. $itemId = $data['item_id'] ?? '未知';
  719. $successRate = $data['success_rate'] ?? 0;
  720. return "使用除草剂ID: {$itemId}, 成功率: {$successRate}%";
  721. }
  722. private static function parseWateringSummary(array $data): string
  723. {
  724. $itemId = $data['item_id'] ?? '未知';
  725. $successRate = $data['success_rate'] ?? 0;
  726. return "浇水物品ID: {$itemId}, 成功率: {$successRate}%";
  727. }
  728. private static function parseRemovedSummary(array $data): string
  729. {
  730. $toolItemId = $data['tool_item_id'] ?? 0;
  731. $removedAt = $data['removed_at'] ?? '未知时间';
  732. $toolText = $toolItemId > 0 ? "使用工具ID: {$toolItemId}" : "手动铲除";
  733. return "{$toolText}, 铲除时间: {$removedAt}";
  734. }
  735. private static function parsePickedSummary(array $data): string
  736. {
  737. $pickerId = $data['picker_id'] ?? '未知';
  738. $pickAmount = $data['pick_amount'] ?? 0;
  739. $itemId = $data['item_id'] ?? '未知';
  740. $pickSource = $data['pick_source'] ?? '未知';
  741. return "摘取者ID: {$pickerId}, 摘取数量: {$pickAmount}, 物品ID: {$itemId}, 来源: {$pickSource}";
  742. }
  743. // 静态解析方法 - 详情版本
  744. private static function parseFruitConfirmedDetail(array $data): string
  745. {
  746. $details = [];
  747. $details[] = '<strong>确认果实种类事件详情:</strong>';
  748. $details[] = '• 最终产出物品ID: ' . ($data['final_output_item_id'] ?? '未知');
  749. $details[] = '• 生长阶段: ' . GROWTH_STAGE::getName($data['growth_stage'] ?? 0);
  750. $details[] = '• 土地类型: ' . ($data['land_type'] ?? '未知');
  751. $details[] = '• 是否神秘种子: ' . (($data['is_mystery_seed'] ?? false) ? '是' : '否');
  752. if (isset($data['selected_output'])) {
  753. $output = $data['selected_output'];
  754. $details[] = '• 选中产出信息:';
  755. $details[] = ' - 物品ID: ' . ($output['item_id'] ?? '未知');
  756. $details[] = ' - 最大数量: ' . ($output['max_amount'] ?? '未知');
  757. }
  758. if (isset($data['land_effect_applied'])) {
  759. $details[] = '• 土地效果已应用: ' . ($data['land_effect_applied'] ? '是' : '否');
  760. }
  761. return implode('<br>', $details);
  762. }
  763. private static function parseOutputCalculatedDetail(array $data): string
  764. {
  765. $details = [];
  766. $details[] = '<strong>确认产出数量事件详情:</strong>';
  767. $details[] = '• 基础产量: ' . ($data['base_amount'] ?? '未知');
  768. $details[] = '• 最终产量: ' . ($data['final_amount'] ?? '未知');
  769. $details[] = '• 土地加成: ' . ($data['land_bonus'] ?? 0) . '%';
  770. $details[] = '• 房屋加成: ' . ($data['house_bonus'] ?? 0) . '%';
  771. $details[] = '• 是否有灾害: ' . (($data['has_disaster'] ?? false) ? '是' : '否');
  772. if (isset($data['disaster_penalty'])) {
  773. $details[] = '• 灾害惩罚: ' . $data['disaster_penalty'] . '%';
  774. }
  775. $details[] = '• 是否有丰收加持: ' . (($data['has_harvest_buff'] ?? false) ? '是' : '否');
  776. $details[] = '• 灾害最大产量: ' . ($data['disaster_max_amount'] ?? '未知');
  777. $details[] = '• 全局最大产量: ' . ($data['global_max_output'] ?? '未知');
  778. $details[] = '• 最终产出物品ID: ' . ($data['final_output_item_id'] ?? '未知');
  779. return implode('<br>', $details);
  780. }
  781. private static function parseDisasterOccurredDetail(array $data): string
  782. {
  783. $details = [];
  784. $details[] = '<strong>灾害产生事件详情:</strong>';
  785. $disasterType = $data['disaster_type'] ?? $data['disaster_info']['type'] ?? 0;
  786. $details[] = '• 灾害类型: ' . DISASTER_TYPE::getName($disasterType);
  787. $details[] = '• 发生时间: ' . ($data['generated_at'] ?? $data['disaster_info']['generated_ts'] ?? '未知');
  788. $details[] = '• 土地类型: ' . ($data['land_type'] ?? '未知');
  789. $details[] = '• 生长阶段: ' . GROWTH_STAGE::getName($data['growth_stage'] ?? 0);
  790. if (isset($data['old_land_status']) && isset($data['new_land_status'])) {
  791. $details[] = '• 土地状态变化: ' . $data['old_land_status'] . ' → ' . $data['new_land_status'];
  792. }
  793. if (isset($data['disaster_info'])) {
  794. $info = $data['disaster_info'];
  795. $details[] = '• 灾害状态: ' . ($info['status'] ?? '未知');
  796. }
  797. return implode('<br>', $details);
  798. }
  799. private static function parseDisasterClearedDetail(array $data): string
  800. {
  801. $details = [];
  802. $details[] = '<strong>灾害清除事件详情:</strong>';
  803. $disasterType = $data['disaster_type'] ?? 0;
  804. $details[] = '• 灾害类型: ' . DISASTER_TYPE::getName($disasterType);
  805. $details[] = '• 使用物品ID: ' . ($data['item_id'] ?? '未知');
  806. $details[] = '• 成功率: ' . ($data['success_rate'] ?? 0) . '%';
  807. $details[] = '• 生长阶段: ' . GROWTH_STAGE::getName($data['growth_stage'] ?? 0);
  808. $details[] = '• 土地类型: ' . ($data['land_type'] ?? '未知');
  809. $details[] = '• 消耗来源类型: ' . ($data['source_type'] ?? '未知');
  810. $details[] = '• 清除时间: ' . ($data['cleared_at'] ?? '未知');
  811. return implode('<br>', $details);
  812. }
  813. private static function parseHarvestedDetail(array $data): string
  814. {
  815. $details = [];
  816. $details[] = '<strong>收获事件详情:</strong>';
  817. $details[] = '• 收获物品ID: ' . ($data['item_id'] ?? '未知');
  818. $details[] = '• 收获数量: ' . ($data['amount'] ?? '未知');
  819. $details[] = '• 收获记录ID: ' . ($data['harvest_log_id'] ?? '未知');
  820. $details[] = '• 生长阶段: ' . GROWTH_STAGE::getName($data['growth_stage'] ?? 0);
  821. $details[] = '• 土地类型: ' . ($data['land_type'] ?? '未知');
  822. if (isset($data['old_stage']) && isset($data['new_stage'])) {
  823. $oldStageName = GROWTH_STAGE::getName($data['old_stage']);
  824. $newStageName = GROWTH_STAGE::getName($data['new_stage']);
  825. $details[] = '• 阶段变化: ' . $oldStageName . ' → ' . $newStageName;
  826. }
  827. if (isset($data['land_status_before']) && isset($data['land_status_after'])) {
  828. $details[] = '• 土地状态变化: ' . $data['land_status_before'] . ' → ' . $data['land_status_after'];
  829. }
  830. return implode('<br>', $details);
  831. }
  832. private static function parseFertilizedDetail(array $data): string
  833. {
  834. $details = [];
  835. $details[] = '<strong>施肥事件详情:</strong>';
  836. $details[] = '• 生长阶段: ' . GROWTH_STAGE::getName($data['growth_stage'] ?? 0);
  837. $details[] = '• 土地类型: ' . ($data['land_type'] ?? '未知');
  838. $details[] = '• 减少生长时间: ' . ($data['crop_growth_time'] ?? 0) . '秒';
  839. $details[] = '• 阶段结束时间: ' . ($data['stage_end_time'] ?? '未知');
  840. $details[] = '• 施肥时间: ' . ($data['fertilized_at'] ?? '未知');
  841. return implode('<br>', $details);
  842. }
  843. private static function parsePesticideUsedDetail(array $data): string
  844. {
  845. $details = [];
  846. $details[] = '<strong>使用杀虫剂事件详情:</strong>';
  847. $details[] = '• 生长阶段: ' . GROWTH_STAGE::getName($data['growth_stage'] ?? 0);
  848. $details[] = '• 土地类型: ' . ($data['land_type'] ?? '未知');
  849. $details[] = '• 使用物品ID: ' . ($data['item_id'] ?? '未知');
  850. $details[] = '• 成功率: ' . ($data['success_rate'] ?? 0) . '%';
  851. $details[] = '• 消耗来源类型: ' . ($data['source_type'] ?? '未知');
  852. $details[] = '• 使用时间: ' . ($data['cleared_at'] ?? '未知');
  853. return implode('<br>', $details);
  854. }
  855. private static function parseWeedicideUsedDetail(array $data): string
  856. {
  857. $details = [];
  858. $details[] = '<strong>使用除草剂事件详情:</strong>';
  859. $details[] = '• 生长阶段: ' . GROWTH_STAGE::getName($data['growth_stage'] ?? 0);
  860. $details[] = '• 土地类型: ' . ($data['land_type'] ?? '未知');
  861. $details[] = '• 使用物品ID: ' . ($data['item_id'] ?? '未知');
  862. $details[] = '• 成功率: ' . ($data['success_rate'] ?? 0) . '%';
  863. $details[] = '• 消耗来源类型: ' . ($data['source_type'] ?? '未知');
  864. $details[] = '• 使用时间: ' . ($data['cleared_at'] ?? '未知');
  865. return implode('<br>', $details);
  866. }
  867. private static function parseWateringDetail(array $data): string
  868. {
  869. $details = [];
  870. $details[] = '<strong>浇水事件详情:</strong>';
  871. $details[] = '• 生长阶段: ' . GROWTH_STAGE::getName($data['growth_stage'] ?? 0);
  872. $details[] = '• 土地类型: ' . ($data['land_type'] ?? '未知');
  873. $details[] = '• 使用物品ID: ' . ($data['item_id'] ?? '未知');
  874. $details[] = '• 成功率: ' . ($data['success_rate'] ?? 0) . '%';
  875. $details[] = '• 消耗来源类型: ' . ($data['source_type'] ?? '未知');
  876. $details[] = '• 浇水时间: ' . ($data['cleared_at'] ?? '未知');
  877. return implode('<br>', $details);
  878. }
  879. private static function parseRemovedDetail(array $data): string
  880. {
  881. $details = [];
  882. $details[] = '<strong>铲除作物事件详情:</strong>';
  883. $details[] = '• 生长阶段: ' . GROWTH_STAGE::getName($data['growth_stage'] ?? 0);
  884. $details[] = '• 土地类型: ' . ($data['land_type'] ?? '未知');
  885. $details[] = '• 使用工具ID: ' . ($data['tool_item_id'] ?? 0);
  886. $details[] = '• 铲除时间: ' . ($data['removed_at'] ?? '未知');
  887. $details[] = '• 是否软删除: ' . (($data['soft_deleted'] ?? true) ? '是' : '否');
  888. if (isset($data['old_land_status']) && isset($data['new_land_status'])) {
  889. $details[] = '• 土地状态变化: ' . $data['old_land_status'] . ' → ' . $data['new_land_status'];
  890. }
  891. if (isset($data['reason'])) {
  892. $details[] = '• 铲除原因: ' . $data['reason'];
  893. }
  894. return implode('<br>', $details);
  895. }
  896. private static function parsePickedDetail(array $data): string
  897. {
  898. $details = [];
  899. $details[] = '<strong>摘取事件详情:</strong>';
  900. $details[] = '• 摘取者ID: ' . ($data['picker_id'] ?? '未知');
  901. $details[] = '• 摘取数量: ' . ($data['pick_amount'] ?? '未知');
  902. $details[] = '• 摘取后剩余数量: ' . ($data['remaining_amount'] ?? '未知');
  903. $details[] = '• 摘取比例: ' . (($data['pick_ratio'] ?? 0) * 100) . '%';
  904. $details[] = '• 摘取来源: ' . ($data['pick_source'] ?? '未知');
  905. $details[] = '• 来源ID: ' . ($data['source_id'] ?? '无');
  906. $details[] = '• 摘取物品ID: ' . ($data['item_id'] ?? '未知');
  907. $details[] = '• 累计摘取数量: ' . ($data['total_picked'] ?? '未知');
  908. $details[] = '• 冷却结束时间: ' . ($data['cooldown_end'] ?? '未知');
  909. $details[] = '• 摘取者IP: ' . ($data['ip_address'] ?? '未知');
  910. return implode('<br>', $details);
  911. }
  912. /**
  913. * 解析铲除作物事件数据(摘要)
  914. */
  915. private function parseRemovedData(array $data): string
  916. {
  917. return self::parseRemovedSummary($data);
  918. }
  919. /**
  920. * 静态方法:记录铲除作物事件
  921. */
  922. public static function logCropRemoved(int $userId, int $landId, int $cropId, int $seedId, array $eventData): self
  923. {
  924. return self::create([
  925. 'user_id' => $userId,
  926. 'land_id' => $landId,
  927. 'crop_id' => $cropId,
  928. 'seed_id' => $seedId,
  929. 'event_type' => self::EVENT_REMOVED,
  930. 'event_data' => $eventData,
  931. 'growth_stage' => $eventData['growth_stage'] ?? GROWTH_STAGE::SPROUT->value,
  932. 'land_type' => $eventData['land_type'] ?? 1,
  933. ]);
  934. }
  935. }