system.blade.php 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652
  1. @extends('admin.layouts')
  2. @section('css')
  3. <link href="/assets/global/vendor/bootstrap-select/bootstrap-select.min.css" rel="stylesheet">
  4. <link href="/assets/global/vendor/switchery/switchery.min.css" rel="stylesheet">
  5. <link href="/assets/global/vendor/dropify/dropify.min.css" rel="stylesheet">
  6. <style>
  7. .hr-text::after {
  8. content: attr(data-content);
  9. position: absolute;
  10. top: -0.8em;
  11. left: 45%;
  12. transform: translateX(-50%);
  13. background: #fff;
  14. padding: 0 15px;
  15. font-size: 16px;
  16. }
  17. </style>
  18. @endsection
  19. @section('content')
  20. <div class="page-content container-fluid">
  21. <x-ui.panel :title="trans('admin.menu.setting.system')" icon="fas fa-cog">
  22. <div class="nav-tabs-horizontal" data-plugin="tabs">
  23. @php
  24. $tabs = [
  25. 'webSetting' => ['icon' => 'globe', 'text' => trans('admin.setting.system.web')],
  26. 'account' => ['icon' => 'user-gear', 'text' => trans('admin.setting.system.account')],
  27. 'node' => ['icon' => 'sitemap', 'text' => trans('admin.setting.system.node')],
  28. 'security' => ['icon' => 'shield-alt', 'text' => trans('admin.setting.system.security')],
  29. 'payment' => ['icon' => 'credit-card', 'text' => trans('admin.setting.system.payment')],
  30. 'notify' => ['icon' => 'bell', 'text' => trans('admin.setting.system.notify')],
  31. 'automation' => ['icon' => 'robot', 'text' => trans('admin.setting.system.auto_job')],
  32. ];
  33. @endphp
  34. <ul class="nav nav-tabs" role="tablist">
  35. @foreach ($tabs as $id => $tab)
  36. <li class="nav-item" role="presentation">
  37. <a class="nav-link {{ $loop->first ? 'active' : '' }}" data-toggle="tab" href="#{{ $id }}" role="tab"
  38. aria-controls="{{ $id }}">
  39. <i class="icon fas fa-{{ $tab['icon'] }}" aria-hidden="true"></i>
  40. {{ $tab['text'] }}
  41. </a>
  42. </li>
  43. @endforeach
  44. <li class="dropdown nav-item" role="presentation">
  45. <a class="dropdown-toggle nav-link" data-toggle="dropdown" href="#" aria-expanded="false">
  46. {{ trans('admin.setting.system.menu') }}
  47. </a>
  48. <div class="dropdown-menu" role="menu">
  49. @foreach ($tabs as $id => $tab)
  50. <a class="dropdown-item {{ $loop->first ? 'active' : '' }}" data-toggle="tab" href="#{{ $id }}" role="tab"
  51. aria-controls="{{ $id }}">
  52. <i class="icon fas fa-{{ $tab['icon'] }}" aria-hidden="true"></i>
  53. {{ $tab['text'] }}
  54. </a>
  55. @endforeach
  56. </div>
  57. </li>
  58. </ul>
  59. <div class="tab-content py-35 px-35">
  60. <!-- 网站常规 -->
  61. <x-system.tab-pane id="webSetting" :active="true">
  62. <div class="col-12">
  63. @if ($errors->any())
  64. <x-alert type="danger" :message="$errors->all()" />
  65. @endif
  66. @if (Session::has('successMsg'))
  67. <x-alert :message="Session::pull('successMsg')" />
  68. @endif
  69. </div>
  70. <x-system.input code="website_name" :value="$configs['website_name']" />
  71. <x-system.input type="url" code="website_url" :value="$configs['website_url']" />
  72. <x-system.select code="standard_currency" :list="array_column(config('common.currency'), 'code', 'name')" />
  73. <x-system.input type="email" code="AppStore_id" :value="$configs['AppStore_id']" />
  74. <x-system.input type="password" code="AppStore_password" :value="$configs['AppStore_password']" />
  75. <x-system.input type="email" code="webmaster_email" :value="$configs['webmaster_email']" />
  76. <div class="form-group col-lg-6">
  77. <div class="form-row">
  78. <label class="col-md-3 col-form-label" for="website_security_code">{{ trans('model.config.website_security_code') }}</label>
  79. <div class="col-md-6">
  80. <div class="input-group">
  81. <input class="form-control" id="website_security_code" type="text" value="{{ $configs['website_security_code'] }}" />
  82. <span class="input-group-append">
  83. <button class="btn btn-info" type="button" onclick="makeWebsiteSecurityCode()">{{ trans('common.generate') }}</button>
  84. <button class="btn btn-primary" type="button"
  85. onclick="update('website_security_code')">{{ trans('common.update') }}</button>
  86. </span>
  87. </div>
  88. <span class="text-help">{!! trans('admin.system.hint.website_security_code', ['url' => route('login') . '?securityCode=']) !!}</span>
  89. </div>
  90. </div>
  91. </div>
  92. <x-system.input type="url" code="website_home_logo" :value="$configs['website_home_logo']" />
  93. <x-system.input type="url" code="website_logo" :value="$configs['website_logo']" />
  94. <form class="upload-form col-lg-12 row" role="form" action="{{ route('admin.system.extend') }}" method="post"
  95. enctype="multipart/form-data">@csrf
  96. <x-system.input-file code="website_home_logo" :value="$configs['website_home_logo']" />
  97. <x-system.input-file code="website_logo" :value="$configs['website_logo']" />
  98. </form>
  99. <x-system.textarea code="website_statistics_code" :value="$configs['website_statistics_code']" />
  100. <x-system.textarea code="website_customer_service_code" :value="$configs['website_customer_service_code']" />
  101. </x-system.tab-pane>
  102. <!-- 账号设置 -->
  103. <x-system.tab-pane id="account">
  104. <x-system.switch code="is_register" :check="$configs['is_register']" />
  105. <x-system.select code="oauth_path" multiple :list="array_flip(config('common.oauth.labels'))" />
  106. <x-system.select code="username_type" :list="[
  107. trans('admin.system.username.email') => 'email',
  108. trans('admin.system.username.mobile') => 'numeric',
  109. trans('admin.system.username.any') => 'string',
  110. ]" />
  111. <x-system.select code="is_email_filtering" :list="[trans('common.status.closed') => '', trans('admin.setting.email.black') => 1, trans('admin.setting.email.white') => 2]" />
  112. <x-system.select code="is_invite_register" :list="[trans('common.status.closed') => '', trans('admin.optional') => 1, trans('admin.require') => 2]" />
  113. <x-system.select code="is_activate_account" :list="[
  114. trans('common.status.closed') => '',
  115. trans('admin.system.active_account.before') => 1,
  116. trans('admin.system.active_account.after') => 2,
  117. ]" />
  118. <x-system.select code="password_reset_notification" :list="[trans('common.status.closed') => '', trans('admin.system.notification.channel.email') => 'mail']" />
  119. <x-system.switch code="is_free_code" :check="$configs['is_free_code']" />
  120. <x-system.input code="affiliate_link_salt" :value="$configs['affiliate_link_salt']" />
  121. <x-system.switch code="is_rand_port" :check="$configs['is_rand_port']" />
  122. <x-system.input-limit code="min_port" hcode="max_port" :value="$configs['min_port']" min="1000" max="$('#max_port').val()" :hvalue="$configs['max_port']"
  123. hmin="$
  124. ('#min_port').val()" hmax="65535" />
  125. <x-system.input-limit code="default_days" :value="$configs['default_days']" unit="{{ trans_choice('common.days.attribute', 1) }}" />
  126. <x-system.input-limit code="default_traffic" :value="$configs['default_traffic']" unit="MB" />
  127. <x-system.input-limit code="reset_password_times" :value="$configs['reset_password_times']" />
  128. <x-system.input-limit code="active_times" :value="$configs['active_times']" />
  129. <x-system.input-limit code="register_ip_limit" :value="$configs['register_ip_limit']" />
  130. <x-system.input-limit code="invite_num" :value="$configs['invite_num']" />
  131. <x-system.input-limit code="user_invite_days" :value="$configs['user_invite_days']" min="1" unit="{{ trans_choice('common.days.attribute', 1) }}" />
  132. <x-system.input-limit code="admin_invite_days" :value="$configs['admin_invite_days']" min="1"
  133. unit="{{ trans_choice('common.days.attribute', 1) }}" />
  134. <hr class="col-12 hr-text" data-content="{{ trans('admin.aff.referral') }}" />
  135. <x-system.switch code="referral_status" :check="$configs['referral_status']" />
  136. <x-system.input-limit code="referral_traffic" :value="$configs['referral_traffic']" unit="MB" />
  137. <x-system.select code="referral_reward_type" :list="[
  138. trans('common.status.closed') => '',
  139. trans('admin.system.referral.once') => 1,
  140. trans('admin.system.referral.loop') => 2,
  141. ]" />
  142. <x-system.input-limit code="referral_percent" :value="$configs['referral_percent'] * 100" max="100" unit="%" />
  143. <x-system.input-limit code="referral_money" :value="$configs['referral_money']"
  144. unit="{{ array_column(config('common.currency'), 'symbol', 'code')[sysConfig('standard_currency')] }}" />
  145. <hr class="col-12 hr-text" data-content="{{ trans('user.home.attendance.attribute') }}" />
  146. <x-system.input-limit code="checkin_interval" :value="$configs['checkin_interval']" unit="{{ ucfirst(trans('validation.attributes.minute')) }}" />
  147. <x-system.input-limit code="checkin_reward" hcode="checkin_reward_max" :value="$configs['checkin_reward']" :hvalue="$configs['checkin_reward_max']" :max="$configs['checkin_reward_max']"
  148. :hmin="$configs['checkin_reward']" unit="MB" />
  149. </x-system.tab-pane>
  150. <!-- 节点设置 -->
  151. <x-system.tab-pane id="node">
  152. <x-system.input type="url" code="subscribe_domain" :value="$configs['subscribe_domain']" :holder="trans('admin.system.placeholder.default_url', ['url' => $configs['website_url']])" />
  153. <x-system.input-limit code="subscribe_max" :value="$configs['subscribe_max']" />
  154. <x-system.switch code="rand_subscribe" :check="$configs['rand_subscribe']" />
  155. <x-system.switch code="is_custom_subscribe" :check="$configs['is_custom_subscribe']" />
  156. <x-system.input type="url" code="web_api_url" :value="$configs['web_api_url']" />
  157. <x-system.input code="v2ray_license" :value="$configs['v2ray_license']" />
  158. <x-system.input code="trojan_license" :value="$configs['trojan_license']" />
  159. <x-system.input code="v2ray_tls_provider" :value="$configs['v2ray_tls_provider']" />
  160. <hr class="col-lg-12 hr-text" data-content="{{ trans('model.node.ddns') }}">
  161. <x-system.select code="ddns_mode" :list="$ddns_labels" />
  162. <x-system.input code="ddns_key" :value="$configs['ddns_key']" />
  163. <x-system.input code="ddns_secret" :value="$configs['ddns_secret']" />
  164. </x-system.tab-pane>
  165. <!-- 安全&验证 -->
  166. <x-system.tab-pane id="security">
  167. <x-system.select code="forbid_mode" :list="[
  168. trans('common.status.closed') => '',
  169. trans('admin.system.forbid.mainland') => 'ban_mainland',
  170. trans('admin.system.forbid.china') => 'ban_china',
  171. trans('admin.system.forbid.oversea') => 'ban_oversea',
  172. ]" />
  173. <x-system.switch code="is_forbid_robot" :check="$configs['is_forbid_robot']" />
  174. <x-system.input type="url" code="redirect_url" :value="$configs['redirect_url']" />
  175. <hr class="col-lg-12 hr-text" data-content="{{ trans('auth.captcha.attribute') }}">
  176. <x-system.select code="is_captcha" :list="[
  177. trans('common.status.closed') => '',
  178. trans('admin.system.captcha.standard') => 1,
  179. trans('admin.system.captcha.geetest') => 2,
  180. trans('admin.system.captcha.recaptcha') => 3,
  181. trans('admin.system.captcha.hcaptcha') => 4,
  182. trans('admin.system.captcha.turnstile') => 5,
  183. ]" />
  184. <x-system.input code="captcha_key" :value="$configs['captcha_key']" />
  185. <x-system.input code="captcha_secret" :value="$configs['captcha_secret']" />
  186. <hr class="col-lg-12 hr-text" data-content="{{ trans('auth.maintenance') }}">
  187. <x-system.switch code="maintenance_mode" :check="$configs['maintenance_mode']" :url="route('admin.login')" />
  188. <x-system.input type="datetime-local" code="maintenance_time" :value="$configs['maintenance_time']" />
  189. <x-system.textarea code="maintenance_content" :value="$configs['maintenance_content']" row="3" />
  190. </x-system.tab-pane>
  191. <!-- 支付系统 -->
  192. <x-system.tab-pane id="payment">
  193. <div class="tab-content pb-100 w-p100">
  194. <x-system.tab-pane id="paymentSetting" :active="true">
  195. <x-system.select code="is_AliPay" :list="[trans('common.status.closed') => '', ...$paymentLists['ali']]" />
  196. <x-system.select code="is_QQPay" :list="[trans('common.status.closed') => '', ...$paymentLists['qq']]" />
  197. <x-system.select code="is_WeChatPay" :list="[trans('common.status.closed') => '', ...$paymentLists['wechat']]" />
  198. <x-system.select code="is_otherPay" multiple :list="$paymentLists['other']" />
  199. <x-system.input code="subject_name" :value="$configs['subject_name']" />
  200. <x-system.input type="url" code="payment_callback_url" :value="$configs['payment_callback_url']" :holder="trans('admin.system.placeholder.default_url', ['url' => $configs['website_url']])" />
  201. </x-system.tab-pane>
  202. @foreach ($paymentForms as $code => $forms)
  203. <x-system.tab-pane :id="$code">
  204. <div class="form-group col-lg-6 d-flex">
  205. <label class="col-md-3 col-form-label">{{ trans("admin.system.payment.channel.$code") }}</label>
  206. <div class="col-md-9">
  207. {!! $forms['button'] ?? (trans("admin.system.payment.hint.$code") !== "admin.system.payment.hint.$code" ? trans("admin.system.payment.hint.$code") : '') !!}
  208. </div>
  209. </div>
  210. @foreach ($forms['settings'] as $key => $details)
  211. <x-system.input :code="$key" :value="$configs[$key]" :type="$details['type'] ?? null" :holder="$details['holder'] ?? null" />
  212. @endforeach
  213. </x-system.tab-pane>
  214. @endforeach
  215. <x-system.tab-pane id="manual">
  216. <div class="form-group col-lg-12 d-flex">
  217. <label class="col-md-3 col-form-label">{{ trans('admin.system.payment.channel.manual') }}</label>
  218. <div class="col-md-7">
  219. {!! trans('admin.system.payment.hint.manual') !!}
  220. </div>
  221. </div>
  222. @if ($errors->any())
  223. <x-alert class="col-12" :message="$errors->all()" />
  224. @endif
  225. @if (Session::has('successMsg'))
  226. <x-alert class="col-12" :message="Session::pull('successMsg')" />
  227. @endif
  228. <x-system.input type="url" code="alipay_qrcode" :value="$configs['alipay_qrcode']" />
  229. <x-system.input type="url" code="wechat_qrcode" :value="$configs['wechat_qrcode']" />
  230. <form class="upload-form col-lg-12 row" role="form" action="{{ route('admin.system.extend') }}" method="post"
  231. enctype="multipart/form-data">@csrf
  232. <x-system.input-file code="alipay_qrcode" :value="$configs['alipay_qrcode']" />
  233. <x-system.input-file code="wechat_qrcode" :value="$configs['wechat_qrcode']" />
  234. </form>
  235. </x-system.tab-pane>
  236. </div>
  237. <ul class="nav nav-tabs nav-tabs-bottom nav-tabs-line dropup" role="tablist">
  238. <li class="nav-item">
  239. <a class="nav-link active" data-toggle="tab" href="#paymentSetting" role="tab"
  240. aria-controls="paymentSetting">{{ trans('admin.system.payment.attribute') }}</a>
  241. </li>
  242. @foreach ($paymentTabs as $tab)
  243. <li class="nav-item">
  244. <a class="nav-link" data-toggle="tab" href="#{{ $tab }}" role="tab"
  245. aria-controls="{{ $tab }}">{{ trans("admin.system.payment.channel.$tab") }}</a>
  246. </li>
  247. @endforeach
  248. </ul>
  249. <ul class="nav nav-tabs nav-tabs-bottom nav-tabs-line dropup" role="tablist">
  250. <li class="nav-item dropdown" style="display: none;">
  251. <a class="dropdown-toggle nav-link" data-toggle="dropdown" href="#" aria-expanded="false"
  252. aria-haspopup="true">{{ trans('admin.setting.system.menu') }}</a>
  253. <div class="dropdown-menu" role="menu">
  254. <a class="dropdown-item active" data-toggle="tab" href="#paymentSetting" role="tab"
  255. aria-controls="paymentSetting">{{ trans('admin.system.payment.attribute') }}</a>
  256. @foreach ($paymentTabs as $tab)
  257. <a class="dropdown-item" data-toggle="tab" href="#{{ $tab }}" role="tab"
  258. aria-controls="{{ $tab }}">{{ trans("admin.system.payment.channel.$tab") }}</a>
  259. @endforeach
  260. </div>
  261. </li>
  262. </ul>
  263. </x-system.tab-pane>
  264. <!-- 通知系统 -->
  265. <x-system.tab-pane id="notify">
  266. @foreach ($notifyForms as $code => $config)
  267. <x-system.input code="{{ $code }}" :value="$configs[$code]" holder="{{ trans('admin.system.placeholder.' . $code) }}"
  268. :url="$config['url'] ?? null" :test="$config['test'] ?? null" />
  269. @endforeach
  270. <hr class="col-12 hr-text" data-content="{{ trans('notification.attribute') }}" />
  271. <x-system.input-limit code="expire_days" :value="$configs['expire_days']" unit="{{ trans_choice('common.days.attribute', 1) }}" />
  272. <x-system.select code="account_expire_notification" multiple :list="[
  273. trans('admin.system.notification.channel.email') => 'mail',
  274. trans('admin.system.notification.channel.site') => 'database',
  275. ]" />
  276. <x-system.input-limit code="traffic_warning_percent" :value="$configs['traffic_warning_percent']" unit="%" />
  277. <x-system.select code="data_exhaust_notification" multiple :list="[
  278. trans('admin.system.notification.channel.email') => 'mail',
  279. trans('admin.system.notification.channel.site') => 'database',
  280. ]" />
  281. <x-system.input-limit code="offline_check_times" :value="$configs['offline_check_times']" unit="{{ trans('admin.times') }}" />
  282. <x-system.select code="node_offline_notification" multiple :list="[
  283. trans('admin.system.notification.channel.email') => 'mail',
  284. trans('admin.system.notification.channel.bark') => 'bark',
  285. trans('admin.system.notification.channel.serverchan') => 'serverChan',
  286. trans('admin.system.notification.channel.pushdeer') => 'pushDear',
  287. trans('admin.system.notification.channel.iyuu') => 'iYuu',
  288. trans('admin.system.notification.channel.telegram') => 'telegram',
  289. trans('admin.system.notification.channel.dingtalk') => 'dingTalk',
  290. trans('admin.system.notification.channel.wechat') => 'weChat',
  291. trans('admin.system.notification.channel.tg_chat') => 'tgChat',
  292. trans('admin.system.notification.channel.pushplus') => 'pushPlus',
  293. ]" />
  294. <x-system.input-limit code="detection_check_times" :value="$configs['detection_check_times']" max="12" unit="{{ trans('admin.times') }}" />
  295. <x-system.select code="node_blocked_notification" multiple :list="[
  296. trans('admin.system.notification.channel.email') => 'mail',
  297. trans('admin.system.notification.channel.serverchan') => 'serverChan',
  298. trans('admin.system.notification.channel.pushdeer') => 'pushDear',
  299. trans('admin.system.notification.channel.iyuu') => 'iYuu',
  300. trans('admin.system.notification.channel.telegram') => 'telegram',
  301. trans('admin.system.notification.channel.wechat') => 'weChat',
  302. trans('admin.system.notification.channel.tg_chat') => 'tgChat',
  303. trans('admin.system.notification.channel.pushplus') => 'pushPlus',
  304. ]" />
  305. <x-system.select code="node_renewal_notification" multiple :list="[
  306. trans('admin.system.notification.channel.email') => 'mail',
  307. trans('admin.system.notification.channel.bark') => 'bark',
  308. trans('admin.system.notification.channel.serverchan') => 'serverChan',
  309. trans('admin.system.notification.channel.pushdeer') => 'pushDear',
  310. trans('admin.system.notification.channel.iyuu') => 'iYuu',
  311. trans('admin.system.notification.channel.telegram') => 'telegram',
  312. trans('admin.system.notification.channel.dingtalk') => 'dingTalk',
  313. trans('admin.system.notification.channel.wechat') => 'weChat',
  314. trans('admin.system.notification.channel.tg_chat') => 'tgChat',
  315. trans('admin.system.notification.channel.pushplus') => 'pushPlus',
  316. trans('admin.system.notification.channel.site') => 'database',
  317. ]" />
  318. <x-system.select code="payment_received_notification" multiple :list="[
  319. trans('admin.system.notification.channel.email') => 'mail',
  320. trans('admin.system.notification.channel.site') => 'database',
  321. trans('admin.system.notification.channel.telegram') => 'telegram',
  322. ]" />
  323. <x-system.select code="payment_confirm_notification" :list="[
  324. trans('common.status.closed') => '',
  325. trans('admin.system.notification.channel.telegram') => 'telegram',
  326. trans('admin.system.notification.channel.dingtalk') => 'dingTalk',
  327. trans('admin.system.notification.channel.wechat') => 'weChat',
  328. ]" />
  329. <x-system.select code="ticket_created_notification" multiple :list="[
  330. trans('admin.system.notification.channel.email') => 'mail',
  331. trans('admin.system.notification.channel.bark') => 'bark',
  332. trans('admin.system.notification.channel.serverchan') => 'serverChan',
  333. trans('admin.system.notification.channel.pushdeer') => 'pushDear',
  334. trans('admin.system.notification.channel.iyuu') => 'iYuu',
  335. trans('admin.system.notification.channel.telegram') => 'telegram',
  336. trans('admin.system.notification.channel.dingtalk') => 'dingTalk',
  337. trans('admin.system.notification.channel.wechat') => 'weChat',
  338. trans('admin.system.notification.channel.tg_chat') => 'tgChat',
  339. trans('admin.system.notification.channel.pushplus') => 'pushPlus',
  340. ]" />
  341. <x-system.select code="ticket_replied_notification" multiple :list="[
  342. trans('admin.system.notification.channel.email') => 'mail',
  343. trans('admin.system.notification.channel.bark') => 'bark',
  344. trans('admin.system.notification.channel.serverchan') => 'serverChan',
  345. trans('admin.system.notification.channel.pushdeer') => 'pushDear',
  346. trans('admin.system.notification.channel.iyuu') => 'iYuu',
  347. trans('admin.system.notification.channel.telegram') => 'telegram',
  348. trans('admin.system.notification.channel.dingtalk') => 'dingTalk',
  349. trans('admin.system.notification.channel.wechat') => 'weChat',
  350. trans('admin.system.notification.channel.tg_chat') => 'tgChat',
  351. trans('admin.system.notification.channel.pushplus') => 'pushPlus',
  352. ]" />
  353. <x-system.select code="ticket_closed_notification" multiple :list="[
  354. trans('admin.system.notification.channel.email') => 'mail',
  355. trans('admin.system.notification.channel.bark') => 'bark',
  356. trans('admin.system.notification.channel.serverchan') => 'serverChan',
  357. trans('admin.system.notification.channel.pushdeer') => 'pushDear',
  358. trans('admin.system.notification.channel.iyuu') => 'iYuu',
  359. trans('admin.system.notification.channel.telegram') => 'telegram',
  360. trans('admin.system.notification.channel.dingtalk') => 'dingTalk',
  361. trans('admin.system.notification.channel.wechat') => 'weChat',
  362. trans('admin.system.notification.channel.tg_chat') => 'tgChat',
  363. trans('admin.system.notification.channel.pushplus') => 'pushPlus',
  364. ]" />
  365. </x-system.tab-pane>
  366. <!-- 自动化任务 -->
  367. <x-system.tab-pane id="automation">
  368. <x-system.switch code="is_clear_log" :check="$configs['is_clear_log']" feature="tasks_clean" />
  369. <x-system.input-limit code="tasks_chunk" :value="$configs['tasks_chunk']" :min="100" />
  370. <x-system.switch code="reset_traffic" :check="$configs['reset_traffic']" />
  371. <x-system.input-limit code="subscribe_rate_limit" :value="$configs['subscribe_rate_limit']" />
  372. <x-system.select code="data_anomaly_notification" multiple :list="[
  373. trans('admin.system.notification.channel.email') => 'mail',
  374. trans('admin.system.notification.channel.bark') => 'bark',
  375. trans('admin.system.notification.channel.serverchan') => 'serverChan',
  376. trans('admin.system.notification.channel.pushdeer') => 'pushDear',
  377. trans('admin.system.notification.channel.iyuu') => 'iYuu',
  378. trans('admin.system.notification.channel.telegram') => 'telegram',
  379. trans('admin.system.notification.channel.dingtalk') => 'dingTalk',
  380. trans('admin.system.notification.channel.wechat') => 'weChat',
  381. trans('admin.system.notification.channel.tg_chat') => 'tgChat',
  382. trans('admin.system.notification.channel.pushplus') => 'pushPlus',
  383. ]" />
  384. <x-system.input-limit code="traffic_abuse_limit" :value="$configs['traffic_abuse_limit']" min="1" unit="GB" />
  385. <x-system.input-limit code="ban_duration" :value="$configs['ban_duration']" unit="{{ ucfirst(trans('validation.attributes.minute')) }}" />
  386. <x-system.input-limit code="auto_release_port" min="0" :value="$configs['auto_release_port']"
  387. unit="{{ ucfirst(trans('validation.attributes.day')) }}" />
  388. <x-system.switch code="is_ban_status" :check="$configs['is_ban_status']" />
  389. <x-system.select code="node_daily_notification" multiple :list="[
  390. trans('admin.system.notification.channel.email') => 'mail',
  391. trans('admin.system.notification.channel.serverchan') => 'serverChan',
  392. trans('admin.system.notification.channel.pushdeer') => 'pushDear',
  393. trans('admin.system.notification.channel.iyuu') => 'iYuu',
  394. trans('admin.system.notification.channel.telegram') => 'telegram',
  395. trans('admin.system.notification.channel.dingtalk') => 'dingTalk',
  396. trans('admin.system.notification.channel.wechat') => 'weChat',
  397. trans('admin.system.notification.channel.tg_chat') => 'tgChat',
  398. trans('admin.system.notification.channel.pushplus') => 'pushPlus',
  399. ]" />
  400. <x-system.input-limit code="recently_heartbeat" :value="$configs['recently_heartbeat']" :min="1"
  401. unit="{{ ucfirst(trans('validation.attributes.minute')) }}" />
  402. <x-system.task-group type="clean" :items="$configs['tasks_clean']" :units="['minutes', 'hours', 'days', 'months', 'years']" feature="tasks_clean" />
  403. <x-system.task-group type="close" :items="$configs['tasks_close']" :units="['minutes', 'hours']" />
  404. </x-system.tab-pane>
  405. </div>
  406. </div>
  407. </x-ui.panel>
  408. </div>
  409. @endsection
  410. @section('javascript')
  411. <script src="/assets/global/vendor/lodash/lodash.min.js"></script>
  412. <script src="/assets/global/vendor/bootstrap-select/bootstrap-select.min.js"></script>
  413. <script src="/assets/global/vendor/switchery/switchery.min.js"></script>
  414. <script src="/assets/global/vendor/dropify/dropify.min.js"></script>
  415. <script src="/assets/global/js/Plugin/bootstrap-select.js"></script>
  416. <script src="/assets/global/js/Plugin/switchery.js"></script>
  417. <script src="/assets/global/js/Plugin/responsive-tabs.js"></script>
  418. <script src="/assets/global/js/Plugin/tabs.js"></script>
  419. <script src="/assets/custom/jump-tab.js"></script>
  420. <script src="/assets/global/js/Plugin/dropify.js"></script>
  421. <script>
  422. $(document).ready(function() {
  423. const selectorValues = {
  424. forbid_mode: '{{ $configs['forbid_mode'] }}',
  425. username_type: '{{ $configs['username_type'] ?: 'email' }}',
  426. is_invite_register: '{{ $configs['is_invite_register'] }}',
  427. is_activate_account: '{{ $configs['is_activate_account'] }}',
  428. ddns_mode: '{{ $configs['ddns_mode'] }}',
  429. is_captcha: '{{ $configs['is_captcha'] }}',
  430. referral_reward_type: '{{ $configs['referral_reward_type'] }}',
  431. is_email_filtering: '{{ $configs['is_email_filtering'] }}',
  432. is_AliPay: '{{ $configs['is_AliPay'] }}',
  433. is_QQPay: '{{ $configs['is_QQPay'] }}',
  434. is_WeChatPay: '{{ $configs['is_WeChatPay'] }}',
  435. is_otherPay: {!! $configs['is_otherPay'] ?: 'null' !!},
  436. standard_currency: '{{ $configs['standard_currency'] }}',
  437. oauth_path: {!! $configs['oauth_path'] ?: 'null' !!},
  438. account_expire_notification: {!! $configs['account_expire_notification'] ?: 'null' !!},
  439. data_anomaly_notification: {!! $configs['data_anomaly_notification'] ?: 'null' !!},
  440. data_exhaust_notification: {!! $configs['data_exhaust_notification'] ?: 'null' !!},
  441. node_blocked_notification: {!! $configs['node_blocked_notification'] ?: 'null' !!},
  442. node_daily_notification: {!! $configs['node_daily_notification'] ?: 'null' !!},
  443. node_offline_notification: {!! $configs['node_offline_notification'] ?: 'null' !!},
  444. node_renewal_notification: {!! $configs['node_renewal_notification'] ?: 'null' !!},
  445. password_reset_notification: '{{ $configs['password_reset_notification'] }}',
  446. payment_confirm_notification: '{{ $configs['payment_confirm_notification'] }}',
  447. payment_received_notification: {!! $configs['payment_received_notification'] ?: 'null' !!},
  448. ticket_closed_notification: {!! $configs['ticket_closed_notification'] ?: 'null' !!},
  449. ticket_created_notification: {!! $configs['ticket_created_notification'] ?: 'null' !!},
  450. ticket_replied_notification: {!! $configs['ticket_replied_notification'] ?: 'null' !!}
  451. };
  452. Object.entries(selectorValues).forEach(([selector, value]) => {
  453. $(`#${selector}`).selectpicker("val", value);
  454. });
  455. const disableOptions = (ids, enabledOptions) => {
  456. ids.forEach(id => {
  457. const element = $(`#${id}`);
  458. element.find("option").each(function() {
  459. optionValue = $(this).val();
  460. if (optionValue !== "" && !enabledOptions.includes(optionValue)) {
  461. $(this).prop("disabled", true);
  462. }
  463. });
  464. element.selectpicker("refresh");
  465. });
  466. };
  467. disableOptions(["is_AliPay", "is_QQPay", "is_WeChatPay", "is_otherPay"], @json($payments));
  468. disableOptions(["account_expire_notification", "data_anomaly_notification", "data_exhaust_notification", "node_blocked_notification",
  469. "node_daily_notification", "node_offline_notification", "node_renewal_notification", "payment_received_notification",
  470. "ticket_closed_notification", "ticket_created_notification", "ticket_replied_notification"
  471. ], @json($notifies));
  472. @if (!$captcha)
  473. disableOptions(["is_captcha"], ["1"]);
  474. @endif
  475. });
  476. // Feature Tab显示
  477. document.addEventListener("DOMContentLoaded", () => {
  478. document.querySelectorAll("[data-feature-toggle]").forEach(toggle => {
  479. const feature = toggle.dataset.featureToggle; // 更简洁的dataset访问方式
  480. const navItem = document.querySelector(`[data-feature="${feature}"]`);
  481. // 防御性编程
  482. if (!navItem) return;
  483. const handleToggle = (show) => {
  484. navItem.classList.toggle("d-none", !show);
  485. };
  486. // 初始状态 + 事件监听
  487. handleToggle(toggle.checked);
  488. toggle.addEventListener("change", (e) => handleToggle(e.target.checked));
  489. });
  490. });
  491. // 系统设置更新
  492. const systemUpdate = _.debounce(function(systemItem, value) {
  493. @can('admin.system.update')
  494. ajaxPost('{{ route('admin.system.update') }}', {
  495. name: systemItem,
  496. value: value
  497. }, function(ret) {
  498. if (ret.status === "success") {
  499. toastr.success(ret.message, document.querySelector(`label[for="${systemItem}"]`)?.textContent);
  500. } else {
  501. showMessage({
  502. title: ret.message,
  503. icon: "error"
  504. }, () => window.location.reload());
  505. }
  506. });
  507. @else
  508. showMessage({
  509. title: '{{ trans('admin.setting.no_permission') }}',
  510. icon: "error",
  511. timer: 1500
  512. });
  513. @endcan
  514. }, 100);
  515. // 正常input更新
  516. const update = systemItem => systemUpdate(systemItem, $(`#${systemItem}`).val());
  517. // 需要检查限制的更新
  518. const updateFromInput = (systemItem, lowerBound = null, upperBound = null) => {
  519. const value = parseInt($(`#${systemItem}`).val());
  520. let errorMessage = null;
  521. if (lowerBound !== null && value < lowerBound) {
  522. errorMessage = `值不能小于 ${lowerBound}`;
  523. } else if (upperBound !== null && value > upperBound) {
  524. errorMessage = `值不能大于 ${upperBound}`;
  525. }
  526. if (errorMessage) {
  527. showMessage({
  528. title: errorMessage,
  529. icon: "warning",
  530. timer: 1500
  531. });
  532. } else {
  533. systemUpdate(systemItem, value);
  534. }
  535. };
  536. const updateJson = (key) => {
  537. const form = document.getElementById(key);
  538. const inputs = form.querySelectorAll("input, select");
  539. const temp = {};
  540. inputs.forEach(input => {
  541. const [_, name, type] = input.name.split(":");
  542. if (!temp[name]) {
  543. temp[name] = {};
  544. }
  545. temp[name][type] = input.value;
  546. });
  547. const result = {};
  548. Object.keys(temp).forEach(name => {
  549. const val = temp[name].value;
  550. const unit = temp[name].unit;
  551. if (val && unit) {
  552. result[name] = `-${val} ${unit}`;
  553. }
  554. });
  555. systemUpdate(key, JSON.stringify(result));
  556. };
  557. // 其他项更新选择
  558. const updateFromOther = (inputType, systemItem) => {
  559. const input = $(`#${systemItem}`);
  560. let pendingValue = null; // 用于存储待更新的值
  561. const updateActions = {
  562. select: () => input.on("changed.bs.select", () => systemUpdate(systemItem, input.val())),
  563. multiSelect: () => input.on("changed.bs.select", () => {
  564. // 存储当前选择的值
  565. pendingValue = input.val();
  566. }).on("hidden.bs.select", () => {
  567. // 当 selectpicker 隐藏时进行更新
  568. if (pendingValue !== null) {
  569. systemUpdate(systemItem, pendingValue);
  570. pendingValue = null; // 清除待更新的值
  571. }
  572. }),
  573. switch: () => systemUpdate(systemItem, document.getElementById(systemItem).checked ? 1 : 0)
  574. };
  575. updateActions[inputType] && updateActions[inputType]();
  576. };
  577. // 使用通知渠道 发送测试消息
  578. @can('admin.test.notify')
  579. function sendTestNotification(channel) {
  580. ajaxPost('{{ route('admin.test.notify') }}', {
  581. channel: channel
  582. }, function(ret) {
  583. if (ret.status === "success") {
  584. showMessage({
  585. title: ret.message,
  586. icon: "success",
  587. timer: 1500
  588. });
  589. } else {
  590. showMessage({
  591. title: ret.message,
  592. icon: "error"
  593. });
  594. }
  595. });
  596. }
  597. @endcan
  598. // 生成网站安全码
  599. function makeWebsiteSecurityCode() {
  600. ajaxGet('{{ route('createStr') }}', {}, function(securityCode) {
  601. $("#website_security_code").val(securityCode);
  602. });
  603. }
  604. @can('admin.test.epay')
  605. function epayInfo() {
  606. ajaxGet('{{ route('admin.test.epay') }}', function(ret) {
  607. if (ret.status === "success") {
  608. showMessage({
  609. title: "易支付信息(仅供参考)",
  610. html: "商户状态: " + ret.data["active"] + " | 账号余额: " + ret.data["money"] + " | 结算账号:" +
  611. ret.data["account"] + "<br\><br\>渠道手续费:【支付宝 - " + (100 - ret.data["alirate"]) +
  612. "% | 微信 - " + (100 - ret.data["wxrate"]) + "% | QQ钱包 - " + (100 - ret.data["qqrate"]) +
  613. "%】<br\><br\> 请按照支付平台的介绍为准,本信息纯粹为Api获取信息",
  614. icon: "info"
  615. });
  616. } else {
  617. showMessage({
  618. title: ret.message,
  619. icon: "error"
  620. });
  621. }
  622. });
  623. }
  624. @endcan
  625. </script>
  626. @endsection