index.blade.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. @extends('base.base')
  2. @section('base')
  3. <div class="main-panel">
  4. <div class="content-wrapper">
  5. <div class="row">
  6. <div class="col-12 grid-margin stretch-card">
  7. <div class="card">
  8. <div class="card-body">
  9. <h4 class="card-title">个控回报配置</h4>
  10. <p class="card-description">配置不同个控区间和倍率的权重调节</p>
  11. <div class="row" style="margin-bottom: 20px;">
  12. <!-- 游戏选择 -->
  13. <div class="col-md-6 form-group">
  14. <label for="game_select" style="font-weight: bold; margin-right: 10px;">选择游戏:</label>
  15. <select id="game_select" class="form-control" style="width: 300px; display: inline-block;" onchange="switchGame(this.value)">
  16. @foreach($games as $id => $name)
  17. <option value="{{ $id }}" {{ $id == $gameId ? 'selected' : '' }}>
  18. {{ $name }} (GameID: {{ $id }})
  19. </option>
  20. @endforeach
  21. </select>
  22. </div>
  23. <!-- 库存模式切换 -->
  24. <div class="col-md-6 form-group">
  25. <label style="font-weight: bold; margin-right: 10px;">库存模式:</label>
  26. <div class="btn-group btn-group-toggle" data-toggle="buttons">
  27. <label class="btn btn-outline-primary {{ $stockMode == 1 ? 'active' : '' }}" onclick="switchStockMode(1)">
  28. <input type="radio" name="stock_mode" value="1" {{ $stockMode == 1 ? 'checked' : '' }}> 普通模式
  29. </label>
  30. <label class="btn btn-outline-success {{ $stockMode == 2 ? 'active' : '' }}" onclick="switchStockMode(2)">
  31. <input type="radio" name="stock_mode" value="2" {{ $stockMode == 2 ? 'checked' : '' }}> 库存模式
  32. </label>
  33. </div>
  34. <span style="margin-left: 15px; color: #666;">
  35. 当前:<strong>{{ $stockMode == 2 ? '库存模式' : '普通模式' }}</strong>
  36. </span>
  37. </div>
  38. </div>
  39. <style>
  40. .table-wrapper {
  41. max-height: calc(100vh - 250px);
  42. overflow-y: auto;
  43. position: relative;
  44. border: 1px solid #ddd;
  45. }
  46. .config-table {
  47. width: 100%;
  48. border-collapse: collapse;
  49. margin: 0;
  50. background: #fff;
  51. }
  52. .config-table th,
  53. .config-table td {
  54. border: 1px solid #ddd;
  55. padding: 8px;
  56. text-align: center;
  57. font-size: 14px;
  58. }
  59. .config-table thead {
  60. position: sticky;
  61. top: 0;
  62. z-index: 100;
  63. }
  64. .config-table th {
  65. background-color: #4CAF50;
  66. color: white;
  67. font-weight: bold;
  68. position: sticky;
  69. top: 0;
  70. box-shadow: 0 2px 2px -1px rgba(0, 0, 0, 0.4);
  71. }
  72. .config-table tbody tr:nth-child(even) {
  73. background-color: #f9f9f9;
  74. }
  75. .config-table tbody tr:hover {
  76. background-color: #f0f0f0;
  77. }
  78. .config-table input[type="number"],
  79. .config-table input[type="text"] {
  80. width: 95%;
  81. padding: 5px;
  82. border: 1px solid transparent;
  83. border-radius: 3px;
  84. text-align: center;
  85. background: transparent;
  86. cursor: pointer;
  87. }
  88. .config-table input[type="number"]:focus,
  89. .config-table input[type="text"]:focus {
  90. border: 1px solid #4CAF50;
  91. background: #fff;
  92. outline: none;
  93. box-shadow: 0 0 5px rgba(76, 175, 80, 0.3);
  94. }
  95. .config-table input[type="number"]:read-only,
  96. .config-table input[type="text"]:read-only {
  97. cursor: pointer;
  98. }
  99. .config-table input[type="checkbox"] {
  100. width: 20px;
  101. height: 20px;
  102. cursor: pointer;
  103. }
  104. .editable-cell {
  105. cursor: pointer;
  106. position: relative;
  107. }
  108. .editable-cell:hover::after {
  109. content: '✎';
  110. position: absolute;
  111. right: 5px;
  112. top: 50%;
  113. transform: translateY(-50%);
  114. color: #4CAF50;
  115. font-size: 14px;
  116. }
  117. .group-header {
  118. background-color: #2196F3 !important;
  119. color: white !important;
  120. font-weight: bold;
  121. position: sticky;
  122. z-index: 50;
  123. }
  124. .field-label {
  125. color: #ccc;
  126. font-size: 11px;
  127. }
  128. /* 滚动条美化 */
  129. .table-wrapper::-webkit-scrollbar {
  130. width: 8px;
  131. }
  132. .table-wrapper::-webkit-scrollbar-track {
  133. background: #f1f1f1;
  134. border-radius: 4px;
  135. }
  136. .table-wrapper::-webkit-scrollbar-thumb {
  137. background: #888;
  138. border-radius: 4px;
  139. }
  140. .table-wrapper::-webkit-scrollbar-thumb:hover {
  141. background: #555;
  142. }
  143. </style>
  144. <form id="configForm">
  145. <div class="table-wrapper">
  146. <table class="config-table">
  147. <thead>
  148. <tr>
  149. <th>ID</th>
  150. <th>个控最小值<br><span class="field-label">(ZMin)</span></th>
  151. <th>个控最大值<br><span class="field-label">(ZMax)</span></th>
  152. <th>倍率最小<br><span class="field-label">(MultiMin)</span></th>
  153. <th>倍率最大<br><span class="field-label">(MultiMax)</span></th>
  154. <th>权重<br><span class="field-label">(Weight)</span></th>
  155. <th>个控调节<br><span class="field-label">(WeightAdjust)</span></th>
  156. </tr>
  157. </thead>
  158. <tbody>
  159. @if(count($configs) == 0)
  160. <tr>
  161. <td colspan="7" style="text-align: center; padding: 40px; color: #999;">
  162. <i class="mdi mdi-alert-circle" style="font-size: 48px;"></i>
  163. <p style="margin-top: 10px; font-size: 16px;">该游戏暂无配置数据</p>
  164. </td>
  165. </tr>
  166. @else
  167. @php
  168. $currentGroup = null;
  169. @endphp
  170. @foreach($configs as $config)
  171. @php
  172. $groupKey = $config->ZMin . '-' . $config->ZMax;
  173. $isNewGroup = ($groupKey !== $currentGroup);
  174. $currentGroup = $groupKey;
  175. @endphp
  176. @if($isNewGroup)
  177. <tr class="group-header">
  178. <td colspan="7">个控区间:{{ $config->ZMin }} - {{ $config->ZMax }}</td>
  179. </tr>
  180. @endif
  181. <tr>
  182. <td>{{ $config->ConfigID }}</td>
  183. <td>
  184. <input type="number"
  185. name="configs[{{ $config->ConfigID }}][ZMin]"
  186. value="{{ $config->ZMin }}"
  187. min="0"
  188. step="1">
  189. </td>
  190. <td>
  191. <input type="number"
  192. name="configs[{{ $config->ConfigID }}][ZMax]"
  193. value="{{ $config->ZMax }}"
  194. min="0"
  195. step="1">
  196. </td>
  197. <td>
  198. <input type="number"
  199. name="configs[{{ $config->ConfigID }}][MultiMin]"
  200. value="{{ number_format($config->MultiMin, 2, '.', '') }}"
  201. min="0"
  202. step="0.01">
  203. </td>
  204. <td>
  205. <input type="number"
  206. name="configs[{{ $config->ConfigID }}][MultiMax]"
  207. value="{{ number_format($config->MultiMax, 2, '.', '') }}"
  208. min="0"
  209. step="0.01">
  210. </td>
  211. <td>
  212. <input type="number"
  213. name="configs[{{ $config->ConfigID }}][Weight]"
  214. value="{{ $config->Weight }}"
  215. min="0"
  216. step="1">
  217. </td>
  218. <td>
  219. <input type="text"
  220. name="configs[{{ $config->ConfigID }}][WeightAdjust]"
  221. value="{{ $config->WeightAdjust }}"
  222. placeholder="如: 15000-300Z"
  223. style="width: 120px;">
  224. </td>
  225. </tr>
  226. @endforeach
  227. @endif
  228. </tbody>
  229. </table>
  230. </div>
  231. @if(count($configs) > 0)
  232. <div style="text-align: center; margin: 20px 0;">
  233. <button type="button" class="btn btn-primary btn-lg" onclick="saveConfig()">保存配置</button>
  234. </div>
  235. @endif
  236. </form>
  237. <script>
  238. // 切换游戏
  239. function switchGame(gameId) {
  240. // 检查是否有未保存的修改
  241. if (!checkUnsavedChanges('切换游戏')) {
  242. $('#game_select').val('{{ $gameId }}');
  243. return;
  244. }
  245. // 切换到选择的游戏,保持当前的库存模式
  246. const stockMode = {{ $stockMode }};
  247. window.location.href = '/admin/game-some-config?game_id=' + gameId + '&stock_mode=' + stockMode;
  248. }
  249. // 切换库存模式
  250. function switchStockMode(mode) {
  251. // 检查是否有未保存的修改
  252. if (!checkUnsavedChanges('切换库存模式')) {
  253. return;
  254. }
  255. // 切换到选择的模式,保持当前的游戏选择
  256. const gameId = {{ $gameId }};
  257. window.location.href = '/admin/game-some-config?game_id=' + gameId + '&stock_mode=' + mode;
  258. }
  259. // 检查是否有未保存的修改
  260. function checkUnsavedChanges(action) {
  261. let hasUnsavedChanges = false;
  262. $('input[name^="configs"]').each(function() {
  263. const name = $(this).attr('name');
  264. const currentValue = $(this).val();
  265. if (originalData[name] && originalData[name] !== currentValue) {
  266. hasUnsavedChanges = true;
  267. return false; // break
  268. }
  269. });
  270. if (hasUnsavedChanges) {
  271. return confirm('有未保存的修改,确定要' + action + '吗?');
  272. }
  273. return true;
  274. }
  275. // 保存原始数据
  276. const originalData = {};
  277. $(document).ready(function() {
  278. // 记录所有字段的原始值
  279. $('input[name^="configs"]').each(function() {
  280. const name = $(this).attr('name');
  281. if ($(this).attr('type') === 'checkbox') {
  282. originalData[name] = $(this).prop('checked');
  283. } else {
  284. originalData[name] = $(this).val();
  285. // 设置为只读,点击后才能编辑
  286. $(this).attr('readonly', true);
  287. }
  288. });
  289. // 点击input时移除只读,进入编辑模式
  290. $('input[type="number"], input[type="text"]').on('click', function() {
  291. $(this).attr('readonly', false);
  292. $(this).select(); // 选中内容,方便修改
  293. });
  294. // 失去焦点时恢复只读
  295. $('input[type="number"], input[type="text"]').on('blur', function() {
  296. $(this).attr('readonly', true);
  297. });
  298. });
  299. function saveConfig() {
  300. // 收集有变动的数据
  301. const changedData = {};
  302. let hasChanges = false;
  303. $('input[name^="configs"]').each(function() {
  304. const name = $(this).attr('name');
  305. let currentValue;
  306. if ($(this).attr('type') === 'checkbox') {
  307. currentValue = $(this).prop('checked');
  308. } else {
  309. currentValue = $(this).val();
  310. }
  311. // 只添加有变动的字段
  312. if (originalData[name] !== currentValue) {
  313. changedData[name] = currentValue;
  314. hasChanges = true;
  315. }
  316. });
  317. if (!hasChanges) {
  318. layer.msg('没有数据被修改', {icon: 0});
  319. return;
  320. }
  321. // 构建只包含变动数据的表单
  322. const formData = $.param(changedData);
  323. layer.msg('正在保存 ' + Object.keys(changedData).length + ' 个变动...', {icon: 16, time: 0, shade: 0.3});
  324. $.ajax({
  325. url: '/admin/game-some-config/update',
  326. type: 'POST',
  327. data: formData,
  328. dataType: 'json',
  329. success: function(res) {
  330. layer.closeAll();
  331. if (res.code === 200) {
  332. layer.msg('配置更新成功!', {icon: 1});
  333. setTimeout(function() {
  334. location.reload();
  335. }, 1000);
  336. } else {
  337. layer.msg('更新失败: ' + (res.msg || '未知错误'), {icon: 2});
  338. }
  339. },
  340. error: function(xhr) {
  341. layer.closeAll();
  342. layer.msg('请求失败: ' + xhr.statusText, {icon: 2});
  343. }
  344. });
  345. }
  346. </script>
  347. </div>
  348. </div>
  349. </div>
  350. </div>
  351. </div>
  352. </div>
  353. @endsection