index.blade.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. @extends('admin.table_layouts')
  2. @push('css')
  3. <link href="/assets/custom/range.min.css" rel="stylesheet">
  4. @endpush
  5. @section('content')
  6. <div class="page-content container-fluid">
  7. <x-admin.table-panel :title="trans('admin.menu.user.list')" :theads="[
  8. 'id' => '#',
  9. trans('model.user.username'),
  10. 'credit' => trans('model.user.credit'),
  11. 'port' => trans('model.user.port'),
  12. trans('model.subscribe.code'),
  13. trans('model.user.traffic_used'),
  14. 't' => trans('common.latest_at'),
  15. 'expired_at' => trans('common.expired_at'),
  16. trans('common.account'),
  17. trans('model.user.service'),
  18. trans('common.action'),
  19. ]" :count="trans('admin.user.counts', ['num' => $userList->total()])" :pagination="$userList->links()" :delete-config="['url' => route('admin.user.destroy', 'PLACEHOLDER'), 'attribute' => trans('model.user.attribute')]">
  20. @canany(['admin.user.batch', 'admin.user.create'])
  21. <x-slot:actions>
  22. @can('admin.user.batch')
  23. <button class="btn btn-outline-default" onclick="batchAddUsers()">
  24. <i class="icon wb-plus" aria-hidden="true"></i> {{ trans('common.generate') }}
  25. </button>
  26. @endcan
  27. @can('admin.user.create')
  28. <a class="btn btn-outline-primary" href="{{ route('admin.user.create') }}">
  29. <i class="icon wb-user-add" aria-hidden="true"></i> {{ trans('common.add') }}
  30. </a>
  31. @endcan
  32. </x-slot:actions>
  33. @endcanany
  34. <x-slot:filters>
  35. <x-admin.filter.input class="col-md-1 col-sm-4" name="id" type="number" :placeholder="trans('model.user.id')" />
  36. <x-admin.filter.input class="col-xxl-2 col-md-3 col-sm-4" name="username" :placeholder="trans('model.user.username')" />
  37. <x-admin.filter.input class="col-xxl-2 col-md-3 col-sm-4" name="wechat" :placeholder="trans('model.user.wechat')" />
  38. <x-admin.filter.input class="col-xxl-2 col-md-3 col-sm-4" name="qq" type="number" :placeholder="trans('model.user.qq')" />
  39. <x-admin.filter.input class="col-xxl-1 col-md-2 col-sm-4" name="port" type="number" :placeholder="trans('model.user.port')" />
  40. <x-admin.filter.selectpicker class="col-xxl-1 col-md-3 col-4" name="user_group_id" :title="trans('model.user_group.attribute')" :options="$userGroups" />
  41. <x-admin.filter.selectpicker class="col-xxl-1 col-md-3 col-4" name="level" :title="trans('model.common.level')" :options="$levels" />
  42. <x-admin.filter.selectpicker class="col-xxl-1 col-md-3 col-4" name="status" :title="trans('model.user.account_status')" :options="[-1 => trans('common.status.banned'), 0 => trans('common.status.inactive'), 1 => trans('common.status.normal')]" />
  43. <x-admin.filter.selectpicker class="col-xxl-1 col-md-3 col-4" name="enable" :title="trans('model.user.proxy_status')" :options="[1 => trans('common.status.enabled'), 0 => trans('common.status.banned')]" />
  44. </x-slot:filters>
  45. <x-slot:tbody>
  46. @foreach ($userList as $user)
  47. <tr class="{{ $user->ban_time ? 'table-danger' : '' }}">
  48. <td> {{ $user->id }} </td>
  49. <td> {{ $user->username }} </td>
  50. <td> {{ $user->credit }} </td>
  51. <td>
  52. {!! $user->port ?: '<span class="badge badge-lg badge-danger"> ' . trans('common.none') . ' </span>' !!}
  53. </td>
  54. <td>
  55. <a class="copySubscribeLink" data-clipboard-text="{{ $user->sub_url }}" href="javascript:">{{ $user->subscribe->code }}</a>
  56. </td>
  57. <td> {{ formatBytes($user->used_traffic) }} / {{ $user->transfer_enable_formatted }} </td>
  58. <td> {{ $user->t ? date('Y-m-d H:i', $user->t) : trans('common.status.unused') }} </td>
  59. <td>
  60. @if ($user->expiration_status !== 3)
  61. <span class="badge badge-lg badge-{{ ['danger', 'warning', 'default'][$user->expiration_status] }}">
  62. {{ $user->expiration_date }} </span>
  63. @else
  64. {{ $user->expiration_date }}
  65. @endif
  66. </td>
  67. <td>
  68. @if ($user->status > 0)
  69. <span class="badge badge-lg badge-primary">
  70. <i class="wb-check" aria-hidden="true"></i>
  71. </span>
  72. @elseif ($user->status < 0)
  73. <span class="badge badge-lg badge-danger">
  74. <i class="wb-close" aria-hidden="true"></i>
  75. </span>
  76. @else
  77. <span class="badge badge-lg badge-default">
  78. <i class="wb-minus" aria-hidden="true"></i>
  79. </span>
  80. @endif
  81. </td>
  82. <td>
  83. <span class="badge badge-lg badge-{{ $user->enable ? 'info' : 'danger' }}">
  84. <i class="wb-{{ $user->enable ? 'check' : 'close' }}" aria-hidden="true"></i>
  85. </span>
  86. </td>
  87. <td>
  88. @canany(['admin.user.edit', 'admin.user.destroy', 'admin.user.export', 'admin.user.monitor', 'admin.user.online', 'admin.user.reset',
  89. 'admin.user.switch'])
  90. <x-ui.dropdown>
  91. @can('admin.user.edit')
  92. <x-ui.dropdown-item :url="route('admin.user.edit', ['user' => $user->id, Request::getQueryString()])" icon="wb-edit" :text="trans('common.edit')" />
  93. @endcan
  94. @can('admin.user.destroy')
  95. <x-ui.dropdown-item color="red-600" url="javascript:(0)" attribute="data-action=delete" icon="wb-trash" :text="trans('common.delete')" />
  96. @endcan
  97. @can('admin.user.export')
  98. <x-ui.dropdown-item :url="route('admin.user.export', $user)" icon="wb-code" :text="trans('admin.user.proxy_info')" />
  99. @endcan
  100. @can('admin.user.monitor')
  101. <x-ui.dropdown-item :url="route('admin.user.monitor', $user)" icon="wb-stats-bars" :text="trans('admin.user.traffic_monitor')" />
  102. @endcan
  103. @can('admin.user.online')
  104. <x-ui.dropdown-item :url="route('admin.user.online', $user)" icon="wb-cloud" :text="trans('admin.user.online_monitor')" />
  105. @endcan
  106. @can('admin.user.reset')
  107. <x-ui.dropdown-item url="javascript:resetTraffic('{{ $user->id }}','{{ $user->username }}')" icon="wb-reload"
  108. :text="trans('admin.user.reset_traffic')" />
  109. @endcan
  110. @can('admin.user.switch')
  111. <x-ui.dropdown-item url="javascript:switchToUser('{{ $user->id }}')" icon="wb-user" :text="trans('admin.user.user_view')" />
  112. @endcan
  113. @can('admin.user.VNetInfo')
  114. <x-ui.dropdown-item id="vent_{{ $user->id }}" url="javascript:VNetInfo('{{ $user->id }}')" icon="wb-link-broken"
  115. :text="trans('admin.user.connection_test')" />
  116. @endcan
  117. </x-ui.dropdown>
  118. @endcanany
  119. </td>
  120. </tr>
  121. @endforeach
  122. </x-slot:tbody>
  123. </x-admin.table-panel>
  124. </div>
  125. @endsection
  126. @push('javascript')
  127. <script>
  128. @can('admin.user.batch')
  129. function batchAddUsers() { // 批量生成账号
  130. showConfirm({
  131. title: '{{ trans('admin.user.bulk_account_quantity') }}',
  132. input: "range",
  133. inputAttributes: {
  134. min: 1,
  135. max: 10
  136. },
  137. inputValue: 1,
  138. onConfirm: function(result) {
  139. if (result.value) {
  140. ajaxPost('{{ route('admin.user.batch') }}', {
  141. amount: result.value
  142. });
  143. }
  144. }
  145. });
  146. }
  147. @endcan
  148. @can('admin.user.reset')
  149. function resetTraffic(id, username) { // 重置流量
  150. showConfirm({
  151. title: '{{ trans('common.warning') }}',
  152. text: '{{ trans('admin.user.reset_confirm') }}'.replace('{username}', username),
  153. icon: 'warning',
  154. onConfirm: function() {
  155. ajaxPost(jsRoute('{{ route('admin.user.reset', 'PLACEHOLDER') }}', id));
  156. }
  157. });
  158. }
  159. @endcan
  160. @can('admin.user.switch')
  161. function switchToUser(id) { // 切换用户身份
  162. ajaxPost(jsRoute('{{ route('admin.user.switch', 'PLACEHOLDER') }}', id), {}, {
  163. success: function(ret) {
  164. handleResponse(ret, {
  165. redirectUrl: '/'
  166. });
  167. }
  168. });
  169. }
  170. @endcan
  171. @can('admin.user.VNetInfo')
  172. function VNetInfo(id) { // 节点连通性测试
  173. const $triggerElement = $(`#vent_${id}`);
  174. ajaxPost(jsRoute('{{ route('admin.user.VNetInfo', 'PLACEHOLDER') }}', id), {}, {
  175. success: function(ret) {
  176. if (ret.status === "success") {
  177. let str = "";
  178. for (let i in ret.data) {
  179. str += "<tr><td>" + ret.data[i]["id"] + "</td><td>" + ret.data[i]["name"] + "</td><td>" +
  180. ret.data[i]["avaliable"] + "</td></tr>";
  181. }
  182. showMessage({
  183. title: ret.title,
  184. html: '<table class="my-20"><thead class="thead-default"><tr><th> ID </th><th> {{ trans('model.node.attribute') }} </th> <th> {{ trans('common.status.attribute') }} </th></thead><tbody>' +
  185. str + "</tbody></table>",
  186. icon: "info",
  187. showConfirmButton: false
  188. });
  189. } else {
  190. showMessage({
  191. title: ret.title,
  192. message: ret.data,
  193. icon: "error"
  194. });
  195. }
  196. },
  197. beforeSend: function() {
  198. $triggerElement.removeClass("wb-link-broken").addClass("wb-loop icon-spin");
  199. },
  200. complete: function() {
  201. $triggerElement.removeClass("wb-loop icon-spin").addClass("wb-link-broken");
  202. }
  203. });
  204. }
  205. @endcan
  206. $(document).on('click', '.copySubscribeLink', function(e) {
  207. e.preventDefault();
  208. copyToClipboard($(this).data('clipboard-text'));
  209. });
  210. </script>
  211. @endpush