MemberDevice.php 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. <?php
  2. namespace app\api\library;
  3. use think\Db;
  4. /**
  5. * 玩家常用设备管理
  6. * 维护玩家最近登录的3个常用设备,用于设备切换验证判断
  7. */
  8. class MemberDevice
  9. {
  10. // 最大常用设备数量
  11. const MAX_RECENT_DEVICES = 3;
  12. /**
  13. * 添加/更新常用设备
  14. * 登录时调用,将设备记录存储到 recent_devices 字段
  15. *
  16. * @param int $memberId 玩家ID
  17. * @param int $gameId 游戏ID
  18. * @param string $imei 设备IMEI
  19. * @param int $deviceType 设备类型:1=PC,2=安卓,3=苹果
  20. * @param bool $forceReplace 列表已满时是否强制替换最旧设备(验证通过后传true)
  21. * @param bool $onlyUpdateExisting 是否仅更新已存在的设备(登录时传true,不添加新设备)
  22. * @return bool
  23. */
  24. public function addDevice($memberId, $gameId, $imei, $deviceType = 0, $forceReplace = false, $onlyUpdateExisting = false)
  25. {
  26. if (empty($memberId) || empty($gameId) || empty($imei)) {
  27. return false;
  28. }
  29. // 查询当前常用设备列表
  30. $subInfo = Db::name('nw_subaccount')
  31. ->where('member_id', $memberId)
  32. ->where('game_id', $gameId)
  33. ->field('id, recent_devices')
  34. ->find();
  35. if (empty($subInfo)) {
  36. return false;
  37. }
  38. // 解析现有设备列表
  39. $recentDevices = [];
  40. if (!empty($subInfo['recent_devices'])) {
  41. $recentDevices = json_decode($subInfo['recent_devices'], true);
  42. if (!is_array($recentDevices)) {
  43. $recentDevices = [];
  44. }
  45. }
  46. // 检查设备是否已存在
  47. $existsIndex = $this->findDeviceIndex($recentDevices, $imei);
  48. $now = time();
  49. if ($existsIndex !== false) {
  50. // 设备已存在,更新最后登录时间
  51. $recentDevices[$existsIndex]['last_login'] = $now;
  52. } else {
  53. // 设备不存在
  54. // 仅更新模式:不添加新设备
  55. if ($onlyUpdateExisting) {
  56. return false;
  57. }
  58. // 判断是否需要添加
  59. if (count($recentDevices) >= self::MAX_RECENT_DEVICES) {
  60. // 列表已满,且未强制替换,不处理
  61. if (!$forceReplace) {
  62. return false;
  63. }
  64. // 强制替换:移除最旧的设备
  65. $oldestIndex = $this->findOldestDeviceIndex($recentDevices);
  66. if ($oldestIndex !== false) {
  67. unset($recentDevices[$oldestIndex]);
  68. $recentDevices = array_values($recentDevices);
  69. }
  70. }
  71. // 添加新设备
  72. $recentDevices[] = [
  73. 'imei' => $imei,
  74. 'device_type' => (int)$deviceType,
  75. 'last_login' => $now,
  76. ];
  77. }
  78. // 更新数据库
  79. $result = Db::name('nw_subaccount')
  80. ->where('id', $subInfo['id'])
  81. ->update([
  82. 'recent_devices' => json_encode($recentDevices),
  83. 'update_time' => $now,
  84. ]);
  85. return $result !== false;
  86. }
  87. /**
  88. * 判断是否为最近登录的设备
  89. *
  90. * @param int $memberId 玩家ID
  91. * @param int $gameId 游戏ID
  92. * @param string $imei 设备IMEI
  93. * @return bool true=是常用设备,false=不是常用设备
  94. */
  95. public function isRecentDevice($memberId, $gameId, $imei)
  96. {
  97. if (empty($memberId) || empty($gameId) || empty($imei)) {
  98. return false;
  99. }
  100. // 查询当前常用设备列表
  101. $subInfo = Db::name('nw_subaccount')
  102. ->where('member_id', $memberId)
  103. ->where('game_id', $gameId)
  104. ->field('recent_devices')
  105. ->find();
  106. if (empty($subInfo) || empty($subInfo['recent_devices'])) {
  107. return false;
  108. }
  109. // 解析设备列表
  110. $recentDevices = json_decode($subInfo['recent_devices'], true);
  111. if (!is_array($recentDevices) || empty($recentDevices)) {
  112. return false;
  113. }
  114. // 查找设备
  115. return $this->findDeviceIndex($recentDevices, $imei) !== false;
  116. }
  117. /**
  118. * 查找设备在列表中的索引
  119. *
  120. * @param array $devices 设备列表
  121. * @param string $imei 设备IMEI
  122. * @return int|false 找到返回索引,未找到返回false
  123. */
  124. private function findDeviceIndex($devices, $imei)
  125. {
  126. foreach ($devices as $index => $device) {
  127. if (isset($device['imei']) && $device['imei'] === $imei) {
  128. return $index;
  129. }
  130. }
  131. return false;
  132. }
  133. /**
  134. * 查找最旧设备的索引
  135. *
  136. * @param array $devices 设备列表
  137. * @return int|false
  138. */
  139. private function findOldestDeviceIndex($devices)
  140. {
  141. if (empty($devices)) {
  142. return false;
  143. }
  144. $oldestIndex = 0;
  145. $oldestTime = PHP_INT_MAX;
  146. foreach ($devices as $index => $device) {
  147. if (isset($device['last_login']) && $device['last_login'] < $oldestTime) {
  148. $oldestTime = $device['last_login'];
  149. $oldestIndex = $index;
  150. }
  151. }
  152. return $oldestIndex;
  153. }
  154. }