StockModeController.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. <?php
  2. namespace App\Http\Controllers\Admin;
  3. use App\Http\Controllers\Controller;
  4. use Illuminate\Http\Request;
  5. use Illuminate\Support\Facades\DB;
  6. class StockModeController extends Controller
  7. {
  8. /**
  9. * 显示库存模式配置页面
  10. */
  11. public function index()
  12. {
  13. // 获取 SystemStatusInfo 中的配置
  14. $systemConfig = DB::connection('write')
  15. ->table('QPAccountsDB.dbo.SystemStatusInfo')
  16. ->whereIn('StatusName', ['StockMode2BetLevels', 'StockMode2RevenueRatio', 'StockMode2SwitchRecharge'])
  17. ->get()
  18. ->keyBy('StatusName');
  19. // 解析 StockMode2BetLevels
  20. $betLevelsString = $systemConfig['StockMode2BetLevels']->StatusString ?? '0|2|10|10000,0|0|100|1000';
  21. $betLevelsParts = explode(',', $betLevelsString);
  22. $betMaxLimits = explode('|', $betLevelsParts[0] ?? '0|2|10|10000');
  23. $rechargeMinLimits = explode('|', $betLevelsParts[1] ?? '0|0|100|1000');
  24. // 获取 RoomStockStatic2 数据
  25. $roomStocks = DB::connection('write')
  26. ->table('QPPlatformDB.dbo.RoomStockStatic2')
  27. ->where('GameID', 0)
  28. ->orderBy('SortID')
  29. ->get();
  30. return view('admin.stock_mode.index', compact(
  31. 'systemConfig',
  32. 'betMaxLimits',
  33. 'rechargeMinLimits',
  34. 'roomStocks'
  35. ));
  36. }
  37. /**
  38. * 更新系统配置参数
  39. */
  40. public function updateSystemConfig(Request $request)
  41. {
  42. try {
  43. $betMaxLimits = $request->input('bet_max_limits', []);
  44. $rechargeMinLimits = $request->input('recharge_min_limits', []);
  45. $revenueRatio = $request->input('revenue_ratio', 50);
  46. $switchRecharge = $request->input('switch_recharge', 100);
  47. // 构建 StockMode2BetLevels 的 StatusString
  48. $betMaxString = implode('|', $betMaxLimits);
  49. $rechargeMinString = implode('|', $rechargeMinLimits);
  50. $betLevelsString = $betMaxString . ',' . $rechargeMinString;
  51. // 更新 StockMode2BetLevels
  52. DB::connection('write')
  53. ->table('QPAccountsDB.dbo.SystemStatusInfo')
  54. ->where('StatusName', 'StockMode2BetLevels')
  55. ->update([
  56. 'StatusString' => $betLevelsString,
  57. 'StatusValue' => 0
  58. ]);
  59. // 更新 StockMode2RevenueRatio
  60. DB::connection('write')
  61. ->table('QPAccountsDB.dbo.SystemStatusInfo')
  62. ->where('StatusName', 'StockMode2RevenueRatio')
  63. ->update([
  64. 'StatusValue' => $revenueRatio
  65. ]);
  66. // 更新 StockMode2SwitchRecharge
  67. DB::connection('write')
  68. ->table('QPAccountsDB.dbo.SystemStatusInfo')
  69. ->where('StatusName', 'StockMode2SwitchRecharge')
  70. ->update([
  71. 'StatusValue' => $switchRecharge
  72. ]);
  73. \Log::info('库存模式系统配置更新成功', [
  74. 'bet_levels' => $betLevelsString,
  75. 'revenue_ratio' => $revenueRatio,
  76. 'switch_recharge' => $switchRecharge
  77. ]);
  78. return response()->json(['status' => 'success', 'message' => '系统配置更新成功']);
  79. } catch (\Exception $e) {
  80. \Log::error('库存模式系统配置更新失败', ['error' => $e->getMessage()]);
  81. return response()->json(['status' => 'error', 'message' => '更新失败: ' . $e->getMessage()]);
  82. }
  83. }
  84. /**
  85. * 更新房间库存配置
  86. */
  87. public function updateRoomStock(Request $request)
  88. {
  89. try {
  90. $sortId = $request->input('sort_id');
  91. $levelBase = $request->input('level_base');
  92. if (!$sortId || !is_numeric($levelBase)) {
  93. return response()->json(['status' => 'error', 'message' => '参数错误']);
  94. }
  95. // 更新 RoomStockStatic2
  96. $affected = DB::connection('write')
  97. ->table('QPPlatformDB.dbo.RoomStockStatic2')
  98. ->where('GameID', 0)
  99. ->where('SortID', $sortId)
  100. ->update([
  101. 'LevelBase' => $levelBase
  102. ]);
  103. if ($affected === 0) {
  104. // 如果没有记录,则插入新记录
  105. DB::connection('write')
  106. ->table('QPPlatformDB.dbo.RoomStockStatic2')
  107. ->insert([
  108. 'GameID' => 0,
  109. 'SortID' => $sortId,
  110. 'Stock' => 0,
  111. 'LevelBase' => $levelBase,
  112. 'Revenue' => 0,
  113. 'RevenueD' => 0
  114. ]);
  115. }
  116. \Log::info('房间库存配置更新成功', [
  117. 'sort_id' => $sortId,
  118. 'level_base' => $levelBase
  119. ]);
  120. return response()->json(['status' => 'success', 'message' => '房间库存配置更新成功']);
  121. } catch (\Exception $e) {
  122. \Log::error('房间库存配置更新失败', ['error' => $e->getMessage()]);
  123. return response()->json(['status' => 'error', 'message' => '更新失败: ' . $e->getMessage()]);
  124. }
  125. }
  126. /**
  127. * 更新库存(增减)
  128. */
  129. public function updateStock(Request $request)
  130. {
  131. try {
  132. $sortId = $request->input('sort_id');
  133. $adjustValue = $request->input('adjust_value'); // 已经是数据库值(前端已乘以100)
  134. if (!$sortId || !is_numeric($adjustValue)) {
  135. return response()->json(['status' => 'error', 'message' => '参数错误']);
  136. }
  137. // 使用 increment/decrement 方法更新库存
  138. $query = DB::connection('write')
  139. ->table('QPPlatformDB.dbo.RoomStockStatic2')
  140. ->where('GameID', 0)
  141. ->where('SortID', $sortId);
  142. if ($adjustValue > 0) {
  143. $query->increment('Stock', $adjustValue);
  144. } elseif ($adjustValue < 0) {
  145. $query->decrement('Stock', abs($adjustValue));
  146. }
  147. // 获取更新后的库存值
  148. $roomStock = DB::connection('write')
  149. ->table('QPPlatformDB.dbo.RoomStockStatic2')
  150. ->where('GameID', 0)
  151. ->where('SortID', $sortId)
  152. ->first();
  153. if (!$roomStock) {
  154. return response()->json(['status' => 'error', 'message' => '房间数据不存在']);
  155. }
  156. \Log::info('库存更新成功', [
  157. 'sort_id' => $sortId,
  158. 'adjust_value' => $adjustValue,
  159. 'new_stock' => $roomStock->Stock
  160. ]);
  161. return response()->json([
  162. 'status' => 'success',
  163. 'message' => '库存更新成功',
  164. 'new_stock' => $roomStock->Stock
  165. ]);
  166. } catch (\Exception $e) {
  167. \Log::error('库存更新失败', ['error' => $e->getMessage()]);
  168. return response()->json(['status' => 'error', 'message' => '更新失败: ' . $e->getMessage()]);
  169. }
  170. }
  171. /**
  172. * 获取房间库存统计信息
  173. */
  174. public function getRoomStockStats()
  175. {
  176. try {
  177. $roomStocks = DB::connection('write')
  178. ->table('QPPlatformDB.dbo.RoomStockStatic2')
  179. ->where('GameID', 0)
  180. ->orderBy('SortID')
  181. ->get();
  182. return response()->json(['status' => 'success', 'data' => $roomStocks]);
  183. } catch (\Exception $e) {
  184. \Log::error('获取房间库存统计失败', ['error' => $e->getMessage()]);
  185. return response()->json(['status' => 'error', 'message' => '获取失败: ' . $e->getMessage()]);
  186. }
  187. }
  188. /**
  189. * 获取库存快照历史数据
  190. */
  191. public function getSnapshotHistory(Request $request)
  192. {
  193. try {
  194. $sortId = $request->input('sort_id', 1);
  195. $minutes = $request->input('minutes', 60); // 默认1小时
  196. // 计算开始时间
  197. $startTime = date('Y-m-d H:i:s', strtotime("-{$minutes} minutes"));
  198. // 查询起始时间之前的最后一条数据(用于填充前置空白)
  199. $previousSnapshot = DB::connection('write')
  200. ->table('QPPlatformDB.dbo.RoomStockSnapshot2')
  201. ->where('GameID', 0)
  202. ->where('SortID', $sortId)
  203. ->where('CreateTime', '<', $startTime)
  204. ->orderBy('CreateTime', 'desc')
  205. ->first();
  206. // 查询时间范围内的快照数据
  207. $snapshots = DB::connection('write')
  208. ->table('QPPlatformDB.dbo.RoomStockSnapshot2')
  209. ->where('GameID', 0)
  210. ->where('SortID', $sortId)
  211. ->where('CreateTime', '>=', $startTime)
  212. ->orderBy('CreateTime', 'asc')
  213. ->get();
  214. // 处理数据
  215. $data = [];
  216. // 添加前置数据(如果存在)
  217. if ($previousSnapshot) {
  218. $stock = $previousSnapshot->Stock;
  219. $levelBase = $previousSnapshot->LevelBase;
  220. $stockRatio = $levelBase > 0 ? round($stock / $levelBase, 2) : 0;
  221. $zValue = $this->calculateZValue($stock, $levelBase);
  222. $data[] = [
  223. 'id' => $previousSnapshot->ID,
  224. 'stock' => round($stock / 100, 2),
  225. 'levelBase' => round($levelBase / 100, 2),
  226. 'revenue' => round($previousSnapshot->Revenue / 100, 2),
  227. 'revenueD' => round($previousSnapshot->RevenueD / 100, 2),
  228. 'stockChange' => round($previousSnapshot->StockChange / 100, 2),
  229. 'revenueChange' => round($previousSnapshot->RevenueChange / 100, 2),
  230. 'stockRatio' => $stockRatio,
  231. 'zValue' => $zValue,
  232. 'createTime' => $previousSnapshot->CreateTime,
  233. 'timestamp' => strtotime($previousSnapshot->CreateTime) * 1000,
  234. 'isPrevious' => true // 标记为前置数据
  235. ];
  236. }
  237. // 添加时间范围内的数据
  238. foreach ($snapshots as $snapshot) {
  239. $stock = $snapshot->Stock;
  240. $levelBase = $snapshot->LevelBase;
  241. $stockRatio = $levelBase > 0 ? round($stock / $levelBase, 2) : 0;
  242. $zValue = $this->calculateZValue($stock, $levelBase);
  243. $data[] = [
  244. 'id' => $snapshot->ID,
  245. 'stock' => round($stock / 100, 2),
  246. 'levelBase' => round($levelBase / 100, 2),
  247. 'revenue' => round($snapshot->Revenue / 100, 2),
  248. 'revenueD' => round($snapshot->RevenueD / 100, 2),
  249. 'stockChange' => round($snapshot->StockChange / 100, 2),
  250. 'revenueChange' => round($snapshot->RevenueChange / 100, 2),
  251. 'stockRatio' => $stockRatio,
  252. 'zValue' => $zValue,
  253. 'createTime' => $snapshot->CreateTime,
  254. 'timestamp' => strtotime($snapshot->CreateTime) * 1000,
  255. 'isPrevious' => false
  256. ];
  257. }
  258. return response()->json(['status' => 'success', 'data' => $data]);
  259. } catch (\Exception $e) {
  260. \Log::error('获取快照历史失败', ['error' => $e->getMessage()]);
  261. return response()->json(['status' => 'error', 'message' => '获取失败: ' . $e->getMessage()]);
  262. }
  263. }
  264. /**
  265. * 计算 Z 值(个控)
  266. */
  267. private function calculateZValue($stock, $levelBase)
  268. {
  269. if ($levelBase == 0) {
  270. return 0;
  271. }
  272. if ($stock < $levelBase * 2) {
  273. return 0;
  274. } elseif ($stock >= $levelBase * 2 && $stock < $levelBase * 4) {
  275. // 2x ~ 4x 区间:Z = FLOOR((stock - 2*base) / (2*base / 5)) + 1
  276. $stockDiff = $stock - ($levelBase * 2);
  277. $baseStep = $levelBase * 2 / 5;
  278. $zValue = floor($stockDiff / $baseStep) + 1;
  279. return min(max($zValue, 1), 5);
  280. } elseif ($stock >= $levelBase * 4 && $stock < $levelBase * 6) {
  281. // 4x ~ 6x 区间
  282. $stockDiff = $stock - ($levelBase * 4);
  283. $baseStep = $levelBase * 2 / 5;
  284. $zValue = floor($stockDiff / $baseStep) + 6;
  285. return min(max($zValue, 6), 10);
  286. } elseif ($stock >= $levelBase * 6 && $stock < $levelBase * 8) {
  287. // 6x ~ 8x 区间
  288. $stockDiff = $stock - ($levelBase * 6);
  289. $baseStep = $levelBase * 2 / 5;
  290. $zValue = floor($stockDiff / $baseStep) + 11;
  291. return min(max($zValue, 11), 15);
  292. } else {
  293. // 8x+ 区间
  294. $stockDiff = $stock - ($levelBase * 8);
  295. $baseStep = $levelBase * 4 / 5;
  296. $zValue = floor($stockDiff / $baseStep) + 16;
  297. return min(max($zValue, 16), 20);
  298. }
  299. }
  300. }