GameRecordModel.php 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. <?php
  2. declare (strict_types = 1);
  3. namespace app\model;
  4. use think\Model;
  5. use think\facade\Db;
  6. /**
  7. * 游戏记录模型
  8. */
  9. class GameRecordModel extends Model
  10. {
  11. protected $name = 'game_lottery_prizes';
  12. protected $connection = 'fortune_tiger';
  13. protected $pk = 'id';
  14. // 动作类型常量
  15. const ACTION_TYPE_BET = 1; // 下注
  16. const ACTION_TYPE_WIN = 2; // 中奖
  17. const ACTION_TYPE_RETURN = 3; // 退还
  18. // 状态常量
  19. const STATUS_PENDING = 0; // 待处理
  20. const STATUS_SUCCESS = 1; // 成功
  21. const STATUS_FAILED = 2; // 失败
  22. /**
  23. * 获取游戏记录列表
  24. */
  25. public static function getGameRecords($appId, $page = 1, $limit = 20, $filters = [])
  26. {
  27. $where = [
  28. ['app_id', '=', $appId],
  29. ['action_type', '=', 1],
  30. ];
  31. // 时间筛选
  32. if (!empty($filters['start_time'])) {
  33. $startTime = strtotime($filters['start_time'] . ' 00:00:00');
  34. $where[] = ['create_time', '>=', $startTime];
  35. }
  36. if (!empty($filters['end_time'])) {
  37. $endTime = strtotime($filters['end_time'] . ' 23:59:59');
  38. $where[] = ['create_time', '<=', $endTime];
  39. }
  40. // 平台ID筛选
  41. if (!empty($filters['platform_id'])) {
  42. $where[] = ['user_id', '=', $filters['platform_id']];
  43. }
  44. // 游戏筛选
  45. if (!empty($filters['game_id'])) {
  46. $where[] = ['game_id', '=', $filters['game_id']];
  47. }
  48. // 玩家状态筛选
  49. if ($filters['play_status'] !== '') {
  50. $where[] = ['status', '=', $filters['play_status']];
  51. }
  52. // 玩法筛选
  53. if (!empty($filters['play_method'])) {
  54. $where[] = ['bet_game_play_type', '=', $filters['play_method']];
  55. }
  56. // 触发方式筛选
  57. if (!empty($filters['trigger_method'])) {
  58. $where[] = ['action_type', '=', $filters['trigger_method']];
  59. }
  60. // 牌局编号筛选
  61. if (!empty($filters['round_number'])) {
  62. $where[] = ['third_round_id', 'like', '%' . $filters['round_number'] . '%'];
  63. }
  64. $query = self::where($where);
  65. // 统计总数
  66. $total = $query->count();
  67. // 获取列表数据
  68. $list = $query->field([
  69. 'id', 'user_id', 'uname', 'nickname', 'third_gid', 'third_round_id',
  70. 'game_id', 'game_type', 'bet_game_play_type', 'amount', 'bet_amount',
  71. 'prev_amount', 'next_amount', 'balance_amount', 'action_type', 'status',
  72. 'ip', 'create_time'
  73. ])
  74. ->order('create_time', 'desc')
  75. ->page($page, $limit)
  76. ->select()
  77. ->toArray();
  78. // 格式化数据
  79. foreach ($list as &$item) {
  80. // 格式化金额(除以10000)
  81. $item['amount'] = bcdiv((string)$item['amount'], '10000', 2);
  82. $item['bet_amount'] = bcdiv((string)$item['bet_amount'], '10000', 2);
  83. $item['prev_amount'] = bcdiv((string)$item['prev_amount'], '10000', 2);
  84. $item['next_amount'] = bcdiv((string)$item['next_amount'], '10000', 2);
  85. $item['balance_amount'] = bcdiv((string)$item['balance_amount'], '10000', 2);
  86. // 状态文本
  87. $item['status_text'] = self::getStatusText($item['status']);
  88. // 动作类型文本
  89. $item['action_type_text'] = self::getActionTypeText($item['action_type']);
  90. }
  91. return [
  92. 'list' => $list,
  93. 'total' => $total,
  94. 'page' => $page,
  95. 'limit' => $limit
  96. ];
  97. }
  98. /**
  99. * 获取游戏记录详情
  100. */
  101. public static function getGameRecordDetail($id, $appId)
  102. {
  103. $record = self::where('id', $id)
  104. ->where('app_id', $appId)
  105. ->find();
  106. if (!$record) {
  107. return null;
  108. }
  109. $record = $record->toArray();
  110. // 格式化数据
  111. $record['create_time_text'] = date('Y-m-d H:i:s', $record['create_time']);
  112. $record['update_time_text'] = date('Y-m-d H:i:s', $record['update_time']);
  113. // 格式化金额
  114. $record['amount_yuan'] = bcdiv((string)$record['amount'], '10000', 2);
  115. $record['bet_amount_yuan'] = bcdiv((string)$record['bet_amount'], '10000', 2);
  116. $record['prev_amount_yuan'] = bcdiv((string)$record['prev_amount'], '10000', 2);
  117. $record['next_amount_yuan'] = bcdiv((string)$record['next_amount'], '10000', 2);
  118. $record['balance_amount_yuan'] = bcdiv((string)$record['balance_amount'], '10000', 2);
  119. // 状态文本
  120. $record['status_text'] = self::getStatusText($record['status']);
  121. // 动作类型文本
  122. $record['action_type_text'] = self::getActionTypeText($record['action_type']);
  123. // 解析开奖结果
  124. $record['result_data'] = !empty($record['result']) ? json_decode($record['result'], true) : [];
  125. return $record;
  126. }
  127. /**
  128. * 获取游戏统计信息
  129. */
  130. public static function getGameStatistics($appId, $filters = [])
  131. {
  132. $where = [
  133. ['app_id', '=', $appId]
  134. ];
  135. // 时间筛选
  136. if (!empty($filters['start_time'])) {
  137. $startTime = strtotime($filters['start_time'] . ' 00:00:00');
  138. $where[] = ['create_time', '>=', $startTime];
  139. }
  140. if (!empty($filters['end_time'])) {
  141. $endTime = strtotime($filters['end_time'] . ' 23:59:59');
  142. $where[] = ['create_time', '<=', $endTime];
  143. }
  144. $statistics = self::where($where)
  145. ->field([
  146. 'COUNT(*) as total_records',
  147. 'COUNT(DISTINCT uname) as total_players',
  148. 'SUM(CASE WHEN action_type = 1 THEN bet_amount ELSE 0 END) as total_bet_amount',
  149. 'SUM(CASE WHEN action_type = 2 THEN amount ELSE 0 END) as total_win_amount',
  150. 'SUM(CASE WHEN status = 1 THEN 1 ELSE 0 END) as success_records',
  151. 'SUM(CASE WHEN status = 2 THEN 1 ELSE 0 END) as failed_records'
  152. ])
  153. ->find()
  154. ->toArray();
  155. // 格式化金额
  156. $statistics['total_bet_amount_yuan'] = bcdiv((string)$statistics['total_bet_amount'], '10000', 2);
  157. $statistics['total_win_amount_yuan'] = bcdiv((string)$statistics['total_win_amount'], '10000', 2);
  158. $net_amount = bcsub((string)$statistics['total_bet_amount'], (string)$statistics['total_win_amount']);
  159. $statistics['net_amount_yuan'] = bcdiv($net_amount, '10000', 2);
  160. // 计算成功率
  161. if ($statistics['total_records'] > 0) {
  162. $rate = bcdiv((string)$statistics['success_records'], (string)$statistics['total_records'], 4);
  163. $statistics['success_rate'] = bcmul($rate, '100', 2);
  164. } else {
  165. $statistics['success_rate'] = '0.00';
  166. }
  167. return $statistics;
  168. }
  169. /**
  170. * 获取所有游戏ID列表
  171. */
  172. public static function getAllGameIds($appId)
  173. {
  174. return self::where('app_id', $appId)
  175. ->distinct(true)
  176. ->column('game_id');
  177. }
  178. /**
  179. * 获取所有游戏玩法列表
  180. */
  181. public static function getAllPlayMethods($appId)
  182. {
  183. return self::where('app_id', $appId)
  184. ->distinct(true)
  185. ->column('bet_game_play_type');
  186. }
  187. /**
  188. * 获取状态文本
  189. */
  190. public static function getStatusText($status)
  191. {
  192. $statusMap = [
  193. self::STATUS_PENDING => '待处理',
  194. self::STATUS_SUCCESS => '成功',
  195. self::STATUS_FAILED => '失败'
  196. ];
  197. return $statusMap[$status] ?? '未知';
  198. }
  199. /**
  200. * 获取动作类型文本
  201. */
  202. public static function getActionTypeText($actionType)
  203. {
  204. $actionTypeMap = [
  205. self::ACTION_TYPE_BET => '下注',
  206. self::ACTION_TYPE_WIN => '中奖',
  207. self::ACTION_TYPE_RETURN => '退还'
  208. ];
  209. return $actionTypeMap[$actionType] ?? '其他';
  210. }
  211. }