Browse Source

feat: new db setting

M1Screw 2 years ago
parent
commit
3df9be7c85
46 changed files with 2372 additions and 2294 deletions
  1. 17 4
      app/routes.php
  2. 0 1
      composer.json
  3. 15 45
      config/settings.json
  4. 26 0
      db/migration_sample.php
  5. 6 19
      db/migrations/20230201-init.php
  6. 34 0
      db/migrations/20230216-drop_user_token.php
  7. 0 4
      phpinsights.php
  8. 0 1
      public/index.php
  9. 0 1793
      resources/views/tabler/admin/setting.tpl
  10. 324 0
      resources/views/tabler/admin/setting/billing.tpl
  11. 158 0
      resources/views/tabler/admin/setting/captcha.tpl
  12. 273 0
      resources/views/tabler/admin/setting/email.tpl
  13. 250 0
      resources/views/tabler/admin/setting/im.tpl
  14. 158 0
      resources/views/tabler/admin/setting/ref.tpl
  15. 234 0
      resources/views/tabler/admin/setting/reg.tpl
  16. 145 0
      resources/views/tabler/admin/setting/support.tpl
  17. 31 6
      resources/views/tabler/admin/tabler_header.tpl
  18. 11 18
      resources/views/tabler/user/server.tpl
  19. 0 2
      src/Command/Job.php
  20. 16 7
      src/Command/Migration.php
  21. 136 0
      src/Controllers/Admin/Setting/BillingController.php
  22. 73 0
      src/Controllers/Admin/Setting/CaptchaController.php
  23. 110 0
      src/Controllers/Admin/Setting/EmailController.php
  24. 84 0
      src/Controllers/Admin/Setting/ImController.php
  25. 72 0
      src/Controllers/Admin/Setting/RefController.php
  26. 84 0
      src/Controllers/Admin/Setting/RegController.php
  27. 72 0
      src/Controllers/Admin/Setting/SupportController.php
  28. 0 196
      src/Controllers/Admin/SettingController.php
  29. 1 1
      src/Controllers/Admin/UserController.php
  30. 14 7
      src/Controllers/AuthController.php
  31. 1 1
      src/Controllers/UserController.php
  32. 5 5
      src/Controllers/WebAPI/UserController.php
  33. 2 2
      src/Middleware/Admin.php
  34. 2 3
      src/Middleware/Auth.php
  35. 0 21
      src/Models/Node.php
  36. 0 11
      src/Models/Token.php
  37. 0 11
      src/Models/User.php
  38. 2 2
      src/Services/Captcha.php
  39. 0 2
      src/Services/Gateway/AbstractPayment.php
  40. 11 13
      src/Services/Gateway/PAYJS.php
  41. 0 111
      src/Services/Gateway/PaymentWall.php
  42. 0 1
      src/Utils/CloudflareDriver.php
  43. 0 1
      src/Utils/ResponseHelper.php
  44. 4 4
      src/Utils/Telegram/Callbacks/Callback.php
  45. 0 1
      src/Utils/Telegram/Commands/StartCommand.php
  46. 1 1
      src/Utils/Tools.php

+ 17 - 4
app/routes.php

@@ -242,10 +242,23 @@ return static function (Slim\App $app): void {
         $group->post('/detect/ban/ajax', App\Controllers\Admin\DetectBanLogController::class . ':ajaxLog');
 
         // 设置中心
-        $group->get('/setting', App\Controllers\Admin\SettingController::class . ':index');
-        $group->post('/setting', App\Controllers\Admin\SettingController::class . ':save');
-        $group->post('/setting/email', App\Controllers\Admin\SettingController::class . ':test');
-        $group->post('/setting/payment', App\Controllers\Admin\SettingController::class . ':payment');
+        $group->get('/setting/billing', App\Controllers\Admin\Setting\BillingController::class . ':billing');
+        $group->post('/setting/billing', App\Controllers\Admin\Setting\BillingController::class . ':saveBilling');
+        $group->get('/setting/captcha', App\Controllers\Admin\Setting\CaptchaController::class . ':captcha');
+        $group->post('/setting/captcha', App\Controllers\Admin\Setting\CaptchaController::class . ':saveCaptcha');
+        $group->get('/setting/email', App\Controllers\Admin\Setting\EmailController::class . ':email');
+        $group->post('/setting/email', App\Controllers\Admin\Setting\EmailController::class . ':saveEmail');
+        $group->get('/setting/im', App\Controllers\Admin\Setting\ImController::class . ':im');
+        $group->post('/setting/im', App\Controllers\Admin\Setting\ImController::class . ':saveIm');
+        $group->get('/setting/other', App\Controllers\Admin\Setting\OtherController::class . ':other');
+        $group->post('/setting/other', App\Controllers\Admin\Setting\OtherController::class . ':saveOther');
+        $group->get('/setting/ref', App\Controllers\Admin\Setting\RefController::class . ':ref');
+        $group->post('/setting/ref', App\Controllers\Admin\Setting\RefController::class . ':saveRef');
+        $group->get('/setting/reg', App\Controllers\Admin\Setting\RegController::class . ':reg');
+        $group->post('/setting/reg', App\Controllers\Admin\Setting\RegController::class . ':saveReg');
+        $group->get('/setting/support', App\Controllers\Admin\Setting\SupportController::class . ':support');
+        $group->post('/setting/support', App\Controllers\Admin\Setting\SupportController::class . ':saveSupport');
+        $group->post('/setting/test_email', App\Controllers\Admin\Setting\EmailController::class . ':testEmail');
 
         // 礼品卡
         $group->get('/giftcard', App\Controllers\Admin\GiftCardController::class . ':index');

+ 0 - 1
composer.json

@@ -18,7 +18,6 @@
         "league/html-to-markdown": "^5.1",
         "league/omnipay": "^3.2.1",
         "mailgun/mailgun-php": "^3",
-        "paymentwall/paymentwall-php": "^2",
         "phpmailer/phpmailer": "^6",
         "ramsey/uuid": "^4",
         "sendgrid/sendgrid": "^8",

+ 15 - 45
config/settings.json

@@ -156,7 +156,7 @@
         "class": "stripe",
         "is_public": 0,
         "type": "string",
-        "default": "stripe_sk",
+        "default": "",
         "mark": "stripe_sk"
     },
     {
@@ -166,7 +166,7 @@
         "class": "stripe",
         "is_public": 0,
         "type": "string",
-        "default": "stripe_pk",
+        "default": "",
         "mark": "stripe_pk"
     },
     {
@@ -176,7 +176,7 @@
         "class": "stripe",
         "is_public": 0,
         "type": "string",
-        "default": "stripe_webhook_key",
+        "default": "",
         "mark": "web_hook密钥"
     },
     {
@@ -669,46 +669,6 @@
         "default": "none",
         "mark": "客服系统开关"
     },
-    {
-        "id": null,
-        "item": "pmw_publickey",
-        "value": "",
-        "class": "pmw",
-        "is_public": 0,
-        "type": "string",
-        "default": "",
-        "mark": "pmw公钥"
-    },
-    {
-        "id": null,
-        "item": "pmw_privatekey",
-        "value": "",
-        "class": "pmw",
-        "is_public": 0,
-        "type": "string",
-        "default": "",
-        "mark": "pmw私钥"
-    },
-    {
-        "id": null,
-        "item": "pmw_widget",
-        "value": "m2_1",
-        "class": "pmw",
-        "is_public": 0,
-        "type": "string",
-        "default": "m2_1",
-        "mark": "pmw_widget"
-    },
-    {
-        "id": null,
-        "item": "pmw_height",
-        "value": "350px",
-        "class": "pmw",
-        "is_public": 0,
-        "type": "string",
-        "default": "350px",
-        "mark": "pmw_height"
-    },
     {
         "id": null,
         "item": "reg_mode",
@@ -749,6 +709,16 @@
         "default": "5",
         "mark": "验证码有效期内单个ip可请求的发信次数"
     },
+    {
+        "id": null,
+        "item": "email_verify_email_limit",
+        "value": "5",
+        "class": "register",
+        "is_public": 0,
+        "type": "int",
+        "default": "5",
+        "mark": "验证码有效期内单个邮箱可请求的发信次数"
+    },
     {
         "id": null,
         "item": "enable_reg_im",
@@ -1252,11 +1222,11 @@
     {
         "id": null,
         "item": "db_version",
-        "value": "20230201000",
+        "value": "20230201",
         "class": "db",
         "is_public": 0,
         "type": "int",
-        "default": "20230201000",
+        "default": "20230201",
         "mark": "当前数据库版本"
     }
 ]

+ 26 - 0
db/migration_sample.php

@@ -0,0 +1,26 @@
+<?php
+
+declare(strict_types=1);
+
+use App\Interfaces\MigrationInterface;
+use App\Services\DB;
+
+return new class() implements MigrationInterface {
+    private const UP = <<< END
+        // Your upgrade SQL here 
+END;
+
+    private const DOWN = <<< END
+        // Your downgrade SQL here(optional)
+END;
+
+    public function up(): void
+    {
+        DB::getPdo()->exec(self::UP);
+    }
+
+    public function down(): void
+    {
+        DB::getPdo()->exec(self::DOWN);
+    }
+};

+ 6 - 19
db/migrations/20230201-init.php

@@ -6,7 +6,7 @@ use App\Interfaces\MigrationInterface;
 use App\Services\DB;
 
 return new class() implements MigrationInterface {
-    private const INIT = <<< END
+    private const UP = <<< END
       CREATE TABLE `alive_ip` (
         `id` bigint(20) NOT NULL AUTO_INCREMENT,
         `nodeid` int(11) DEFAULT NULL,
@@ -324,7 +324,7 @@ return new class() implements MigrationInterface {
         `invite_num` int(11) DEFAULT 0 COMMENT '可用邀请次数',
         `money` decimal(10,2) NOT NULL DEFAULT 0.00,
         `ref_by` bigint(20) unsigned DEFAULT 0 COMMENT '邀请人ID',
-        `method` varchar(255) DEFAULT 'rc4-md5' COMMENT 'SS/SSR加密方式',
+        `method` varchar(255) DEFAULT 'rc4-md5' COMMENT 'Shadowsocks加密方式',
         `reg_ip` varchar(255) DEFAULT '127.0.0.1' COMMENT '注册IP',
         `node_speedlimit` double NOT NULL DEFAULT 0 COMMENT '用户限速',
         `node_iplimit` smallint(6) unsigned NOT NULL DEFAULT 0 COMMENT '同时可连接IP数',
@@ -342,13 +342,8 @@ return new class() implements MigrationInterface {
         `ga_enable` int(11) DEFAULT 0,
         `remark` text DEFAULT '' COMMENT '备注',
         `node_group` int(11) unsigned NOT NULL DEFAULT 0 COMMENT '节点分组',
-        `protocol` varchar(255) DEFAULT 'origin' COMMENT 'SS/SSR协议方式',
-        `protocol_param` varchar(255) DEFAULT '',
-        `obfs` varchar(255) DEFAULT 'plain' COMMENT 'SS/SSR混淆方式',
-        `obfs_param` varchar(255) DEFAULT '',
         `is_banned` int(11) DEFAULT 0 COMMENT '是否封禁',
         `banned_reason` varchar(255) DEFAULT '' COMMENT '封禁理由',
-        `is_multi_user` int(11) DEFAULT 0,
         `telegram_id` bigint(20) DEFAULT 0,
         `expire_notified` tinyint(1) DEFAULT 0,
         `traffic_notified` tinyint(1) DEFAULT 0,
@@ -420,22 +415,14 @@ return new class() implements MigrationInterface {
         `request_user_agent` text DEFAULT NULL COMMENT '请求 UA 信息',
         PRIMARY KEY (`id`),
         KEY `user_id` (`user_id`)
-      ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-      
-      CREATE TABLE `user_token` (
-        `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
-        `token` varchar(255) DEFAULT NULL,
-        `user_id` bigint(20) unsigned DEFAULT NULL,
-        `create_time` bigint(20) unsigned DEFAULT NULL,
-        `expire_time` bigint(20) DEFAULT NULL,
-        PRIMARY KEY (`id`),
-        KEY `user_id` (`user_id`)
-      ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;      
+      ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;   
 END;
 
+    private const DOWN = '';
+
     public function up(): void
     {
-        DB::getPdo()->exec(self::INIT);
+        DB::getPdo()->exec(self::UP);
     }
 
     public function down(): void

+ 34 - 0
db/migrations/20230216-drop_user_token.php

@@ -0,0 +1,34 @@
+<?php
+
+declare(strict_types=1);
+
+use App\Interfaces\MigrationInterface;
+use App\Services\DB;
+
+return new class() implements MigrationInterface {
+    private const UP = <<< END
+        DROP TABLE IF EXISTS `user_token`;   
+END;
+
+    private const DOWN = <<< END
+        CREATE TABLE `user_token` (
+            `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+            `token` varchar(255) DEFAULT NULL,
+            `user_id` bigint(20) unsigned DEFAULT NULL,
+            `create_time` bigint(20) unsigned DEFAULT NULL,
+            `expire_time` bigint(20) DEFAULT NULL,
+            PRIMARY KEY (`id`),
+            KEY `user_id` (`user_id`)
+          ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;   
+END;
+
+    public function up(): void
+    {
+        DB::getPdo()->exec(self::UP);
+    }
+
+    public function down(): void
+    {
+        DB::getPdo()->exec(self::DOWN);
+    }
+};

+ 0 - 4
phpinsights.php

@@ -10,12 +10,9 @@ return [
         NunoMaduro\PhpInsights\Domain\Insights\ForbiddenDefineFunctions::class,
         NunoMaduro\PhpInsights\Domain\Insights\ForbiddenDefineGlobalConstants::class,
         NunoMaduro\PhpInsights\Domain\Insights\ForbiddenGlobals::class,
-        PHP_CodeSniffer\Standards\Generic\Sniffs\Commenting\TodoSniff::class,
         PHP_CodeSniffer\Standards\Generic\Sniffs\Files\LineLengthSniff::class,
-        PHP_CodeSniffer\Standards\Generic\Sniffs\Formatting\SpaceAfterNotSniff::class,
         PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP\EvalSniff::class,
         PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP\GlobalKeywordSniff::class,
-        PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\NoSilencedErrorsSniff::class,
         PhpCsFixer\Fixer\Import\OrderedImportsFixer::class,
         SlevomatCodingStandard\Sniffs\ControlStructures\DisallowShortTernaryOperatorSniff::class,
         SlevomatCodingStandard\Sniffs\Classes\ForbiddenPublicPropertySniff::class,
@@ -25,7 +22,6 @@ return [
         SlevomatCodingStandard\Sniffs\Classes\SuperfluousInterfaceNamingSniff::class,
         SlevomatCodingStandard\Sniffs\Functions\FunctionLengthSniff::class,
         SlevomatCodingStandard\Sniffs\Functions\UnusedParameterSniff::class,
-        SlevomatCodingStandard\Sniffs\Namespaces\UseSpacingSniff::class,
         SlevomatCodingStandard\Sniffs\TypeHints\DisallowArrayTypeHintSyntaxSniff::class,
         SlevomatCodingStandard\Sniffs\TypeHints\DisallowMixedTypeHintSniff::class,
         SlevomatCodingStandard\Sniffs\TypeHints\ReturnTypeHintSniff::class,

+ 0 - 1
public/index.php

@@ -22,7 +22,6 @@ use GuzzleHttp\Psr7\ServerRequest;
 use Slim\Factory\AppFactory;
 use Slim\Http\Factory\DecoratedResponseFactory;
 
-// TODO: legacy boot function
 Boot::setTime();
 Boot::bootSentry();
 Boot::bootDb();

+ 0 - 1793
resources/views/tabler/admin/setting.tpl

@@ -1,1793 +0,0 @@
-{include file='admin/main.tpl'}
-
-<main class="content">
-    <div class="content-header ui-content-header">
-        <div class="container">
-            <h1 class="content-heading">设置中心</h1>
-        </div>
-    </div>
-
-    <div class="container">
-        <div class="col-xx-12 col-sm-12">
-            <div class="card quickadd">
-                <div class="card-main">
-                    <div class="card-inner">
-                        <nav class="tab-nav margin-top-no">
-                            <ul class="nav nav-list">
-                                <li class="active">
-                                    <a data-toggle="tab" href="#payment_settings"><i class="mdi mdi-credit-card-outline icon-lg"></i>&nbsp;支付</a>
-                                </li>
-                                <li>
-                                    <a data-toggle="tab" href="#mail_settings"><i class="mdi mdi-email icon-lg"></i>&nbsp;邮件</a>
-                                </li>
-                                <li>
-                                    <a data-toggle="tab" href="#customer_service_system_settings"><i class="mdi mdi-face-agent icon-lg"></i>&nbsp;客服</a>
-                                </li>
-                                <li>
-                                    <a data-toggle="tab" href="#verification_code_settings"><i class="mdi mdi-shield-check icon-lg"></i>&nbsp;验证</a>
-                                </li>
-                                <li>
-                                    <a data-toggle="tab" href="#registration_settings"><i class="mdi mdi-account-plus icon-lg"></i>&nbsp;注册</a>
-                                </li>
-                                <li>
-                                    <a data-toggle="tab" href="#invitation_settings"><i class="mdi mdi-account-multiple-plus icon-lg"></i>&nbsp;邀请</a>
-                                </li>
-                                <li>
-                                    <a data-toggle="tab" href="#telegram_settings"><i class="mdi mdi-send-circle icon-lg"></i>&nbsp;Telegram</a>
-                                </li>
-                            </ul>
-                        </nav>
-                                
-                        <div class="card-inner">
-                           <div class="tab-content">
-                                <div class="tab-pane fade" id="mail_settings">
-                                    <nav class="tab-nav margin-top-no">
-                                        <ul class="nav nav-list">
-                                            <li class="active">
-                                                <a data-toggle="tab" href="#email_auth_settings">&nbsp;设置</a>
-                                            </li>
-                                            <li>
-                                                <a data-toggle="tab" href="#smtp">&nbsp;smtp</a>
-                                            </li>
-                                            <li>
-                                                <a data-toggle="tab" href="#sendgrid">&nbsp;sendgrid</a>
-                                            </li>
-                                            <li>
-                                                <a data-toggle="tab" href="#mailgun">&nbsp;mailgun</a>
-                                            </li>
-                                            <li>
-                                                <a data-toggle="tab" href="#ses">&nbsp;ses</a>
-                                            </li>
-                                        </ul>
-                                    </nav>
-                                            
-                                    <div class="tab-pane fade active in" id="email_auth_settings">
-                                        <!-- mail_driver -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">邮件服务</label>
-                                            <select id="mail_driver" class="form-control maxwidth-edit">
-                                                <option value="none" {if $settings['mail_driver'] == "none"}selected{/if}>none</option>
-                                                <option value="mailgun" {if $settings['mail_driver'] == "mailgun"}selected{/if}>mailgun</option>
-                                                <option value="sendgrid" {if $settings['mail_driver'] == "sendgrid"}selected{/if}>sendgrid</option>
-                                                <option value="ses" {if $settings['mail_driver'] == "ses"}selected{/if}>ses</option>
-                                                <option value="smtp" {if $settings['mail_driver'] == "smtp"}selected{/if}>smtp</option>
-                                            </select>
-                                        </div>
-
-                                        <button id="submit_mail" type="submit" class="btn  btn-brand btn-dense">提交</button>
-
-                                        <!-- smtp_test_recipient -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">测试邮件收件人</label>
-                                            <input class="form-control maxwidth-edit" id="testing_email_recipients">
-                                            <p class="form-control-guide"><i class="mdi mdi-information"></i>邮件配置保存完成后,如需验证是否可用,可在上方填写一个有效邮箱,系统将发送一封测试邮件到该邮箱。如果能够正常接收,则说明配置可用</p>
-                                            {if $settings['mail_driver'] == "none"}
-                                            <p class="form-control-guide"><i class="mdi mdi-information"></i>如需使用发信测试功能,请先在上方选择一个发信方式,并配置有效的相关参数</p>
-                                            {/if}
-                                        </div>
-                                        
-                                        <button id="submit_email_test" type="submit" class="btn btn-brand btn-dense" {if $settings['mail_driver'] == "none"}disabled{/if}>测试</button>
-                                    </div>
-                                    <div class="tab-pane fade" id="smtp">
-                                        <!-- smtp_host -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">SMTP主机地址</label>
-                                            <input class="form-control maxwidth-edit" id="smtp_host" value="{$settings['smtp_host']}">
-                                            <p class="form-control-guide"><i class="mdi mdi-information"></i>例如:smtpdm-ap-southeast-1.aliyun.com</p>
-                                        </div>
-                                        <!-- smtp_username -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">SMTP账户名</label>
-                                            <input class="form-control maxwidth-edit" id="smtp_username" value="{$settings['smtp_username']}">
-                                            <p class="form-control-guide"><i class="mdi mdi-information"></i>例如:[email protected]</p>
-                                        </div>
-                                        <!-- smtp_password -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">SMTP账户密码</label>
-                                            <input class="form-control maxwidth-edit" id="smtp_password" value="{$settings['smtp_password']}">
-                                            <p class="form-control-guide"><i class="mdi mdi-information"></i>如果你使用 QQ 邮箱或 163 邮箱,此处应当填写单独的授权码</p>
-                                        </div>
-                                        <!-- smtp_port -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">SMTP端口</label>
-                                            <select id="smtp_port" class="form-control maxwidth-edit">
-                                                <option value="465" {if $settings['smtp_port'] == "465"}selected{/if}>465</option>
-                                                <option value="587" {if $settings['smtp_port'] == "587"}selected{/if}>587</option>
-                                                <option value="2525" {if $settings['smtp_port'] == "2525"}selected{/if}>2525</option>
-                                                <option value="25" {if $settings['smtp_port'] == "25"}selected{/if}>25</option>
-                                            </select>
-                                            <p class="form-control-guide"><i class="mdi mdi-information"></i>常见端口一般就这些</p>
-                                        </div>
-                                        <!-- smtp_name -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">SMTP发信名称</label>
-                                            <input class="form-control maxwidth-edit" id="smtp_name" value="{$settings['smtp_name']}">
-                                            <p class="form-control-guide"><i class="mdi mdi-information"></i>这里的设置在邮箱的邮件列表中可见。你可以设置为网站名称</p>
-                                        </div>
-                                        <!-- smtp_sender -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">SMTP账户发信地址</label>
-                                            <input class="form-control maxwidth-edit" id="smtp_sender" value="{$settings['smtp_sender']}">
-                                            <p class="form-control-guide"><i class="mdi mdi-information"></i>如不知道填什么,请与此项保持一致:SMTP账户名</p>
-                                        </div>
-                                        <!-- smtp_ssl -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">是否使用 TLS/SSL 发信</label>
-                                            <select id="smtp_ssl" class="form-control maxwidth-edit">
-                                                <option value="1" {if $settings['smtp_ssl'] == true}selected{/if}>开启</option>
-                                                <option value="0" {if $settings['smtp_ssl'] == false}selected{/if}>关闭</option>
-                                            </select>
-                                        </div>
-                                        <!-- smtp_bbc -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">发给用户的邮件密送给指定邮箱备份</label>
-                                            <input class="form-control maxwidth-edit" id="smtp_bbc" value="{$settings['smtp_bbc']}">
-                                            <p class="form-control-guide"><i class="mdi mdi-information"></i>如无需使用此功能,请留空</p>
-                                        </div>
-
-                                        <button id="submit_smtp" type="submit" class="btn  btn-brand btn-dense">提交</button>
-                                    </div>
-                                    <div class="tab-pane fade" id="sendgrid">
-                                        <!-- sendgrid_key -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">Sendgrid 密钥</label>
-                                            <input class="form-control maxwidth-edit" id="sendgrid_key" value="{$settings['sendgrid_key']}">
-                                        </div>
-                                        <!-- sendgrid_sender -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">Sendgrid 发件邮箱</label>
-                                            <input class="form-control maxwidth-edit" id="sendgrid_sender" value="{$settings['sendgrid_sender']}">
-                                        </div>
-                                        <!-- sendgrid_name -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">Sendgrid 发件人名称</label>
-                                            <input class="form-control maxwidth-edit" id="sendgrid_name" value="{$settings['sendgrid_name']}">
-                                        </div>
-
-                                        <button id="submit_sendgrid" type="submit" class="btn btn-brand btn-dense">提交</button>
-                                    </div>
-                                    <div class="tab-pane fade" id="mailgun">
-                                        <!-- mailgun_key -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">Mailgun 密钥</label>
-                                            <input class="form-control maxwidth-edit" id="mailgun_key" value="{$settings['mailgun_key']}">
-                                        </div>
-                                        <!-- mailgun_domain -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">Mailgun 域名</label>
-                                            <input class="form-control maxwidth-edit" id="mailgun_domain" value="{$settings['mailgun_domain']}">
-                                        </div>
-                                        <!-- mailgun_sender -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">Mailgun 发送者</label>
-                                            <input class="form-control maxwidth-edit" id="mailgun_sender" value="{$settings['mailgun_sender']}">
-                                        </div>
-
-                                        <button id="submit_mailgun" type="submit" class="btn btn-brand btn-dense">提交</button>
-                                    </div>
-                                    <div class="tab-pane fade" id="ses">
-                                        <!-- aws_access_key_id -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">AWS 密钥 ID</label>
-                                            <input class="form-control maxwidth-edit" id="aws_access_key_id" value="{$settings['aws_access_key_id']}">
-                                        </div>
-                                        <!-- aws_secret_access_key -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">AWS 密钥 KEY</label>
-                                            <input class="form-control maxwidth-edit" id="aws_secret_access_key" value="{$settings['aws_secret_access_key']}">
-                                        </div>
-                                        <!-- aws_region -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">AWS 区域</label>
-                                            <input class="form-control maxwidth-edit" id="aws_region" value="{$settings['aws_region']}">
-                                        </div>
-                                        <!-- aws_ses_sender -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">AWS SES 发送者</label>
-                                            <input class="form-control maxwidth-edit" id="aws_ses_sender" value="{$settings['aws_ses_sender']}">
-                                        </div>
-
-                                        <button id="submit_ses" type="submit" class="btn btn-brand btn-dense">提交</button>
-                                    </div>
-                                </div>
-
-                                <div class="tab-pane fade active in" id="payment_settings">
-                                    <nav class="tab-nav margin-top-no">
-                                        <ul class="nav nav-list">
-                                            <li class="active">
-                                                <a data-toggle="tab" href="#public_payment_settings">&nbsp;设置</a>
-                                            </li>
-                                            {foreach $payment_gateways as $key => $value}
-                                            <li>
-                                                <a data-toggle="tab" href="#{$value}">{$key}</a>
-                                            </li>
-                                            {/foreach}
-                                        </ul>
-                                    </nav>
-                                            
-                                    <div class="tab-pane fade active in" id="public_payment_settings">
-                                        <div class="form-group form-group-label">
-                                        {foreach $payment_gateways as $key => $value}
-                                            <div class="checkbox switch">
-                                                <label for="{$value}_switch">
-                                                    <input class="access-hide" type="checkbox" id="{$value}_switch" name="{$value}_switch"
-                                                    {if in_array($value, $active_payment_gateway)}
-                                                    checked
-                                                    {/if}
-                                                    ><span class="switch-toggle"></span>{$key}
-                                                </label>
-                                            </div>
-                                        {/foreach}
-                                        </div>
-
-                                        <button id="submit_payment" type="submit" class="btn btn-block btn-brand">提交</button>
-                                    </div>
-
-                                    <div class="tab-pane fade" id="payjs">
-                                        <p class="form-control-guide"><i class="mdi mdi-information"></i>此处申请: <a href="https://payjs.cn" target="view_window">https://payjs.cn</a></p>
-                                        <!-- payjs_url -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">payjs_url</label>
-                                            <input class="form-control maxwidth-edit" id="payjs_url" value="{$settings['payjs_url']}">
-                                        </div>
-                                        <!-- payjs_mchid -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">payjs_mchid</label>
-                                            <input class="form-control maxwidth-edit" id="payjs_mchid" value="{$settings['payjs_mchid']}">
-                                        </div>
-                                        <!-- payjs_key -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">payjs_key</label>
-                                            <input class="form-control maxwidth-edit" id="payjs_key" value="{$settings['payjs_key']}">
-                                        </div>
-
-                                        <button id="submit_payjs_pay" type="submit" class="btn btn-block btn-brand">提交</button>
-                                    </div>
-
-                                    <div class="tab-pane fade" id="paymentwall">
-                                        <p class="form-control-guide"><i class="mdi mdi-information"></i>此处申请: <a href="https://www.paymentwall.com/cn" target="view_window">https://www.paymentwall.com/cn</a></p>
-                                        <!-- pmw_publickey -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">pmw公钥</label>
-                                            <textarea class="form-control maxwidth-edit" id="pmw_publickey" rows="5">{$settings['pmw_publickey']}</textarea>
-                                        </div>
-                                        <!-- pmw_privatekey -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">pmw私钥</label>
-                                            <textarea class="form-control maxwidth-edit" id="pmw_privatekey" rows="7">{$settings['pmw_privatekey']}</textarea>
-                                        </div>
-                                        <!-- pmw_widget -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">pmw_widget</label>
-                                            <input class="form-control maxwidth-edit" id="pmw_widget" value="{$settings['pmw_widget']}">
-                                        </div>
-                                        <!-- pmw_height -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">pmw_height</label>
-                                            <input class="form-control maxwidth-edit" id="pmw_height" value="{$settings['pmw_height']}">
-                                        </div>
-
-                                        <button id="submit_paymentwall" type="submit" class="btn btn-block btn-brand">提交</button>
-                                    </div>
-                                    
-                                    <div class="tab-pane fade" id="theadpay">
-                                        <p class="form-control-guide"><i class="mdi mdi-information"></i>此处申请:<a href="https://theadpay.com" target="view_window">https://theadpay.com</a></p>
-                                        <!-- theadpay_url -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">theadpay_url</label>
-                                            <input class="form-control maxwidth-edit" id="theadpay_url" value="{$settings['theadpay_url']}">
-                                        </div>
-                                        <!-- theadpay_mchid -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">theadpay_mchid</label>
-                                            <input class="form-control maxwidth-edit" id="theadpay_mchid" value="{$settings['theadpay_mchid']}">
-                                        </div>
-                                        <!-- theadpay_key -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">theadpay_key</label>
-                                            <input class="form-control maxwidth-edit" id="theadpay_key" value="{$settings['theadpay_key']}">
-                                        </div>
-
-                                        <button id="submit_theadpay" type="submit" class="btn btn-block btn-brand">提交</button>
-                                    </div>
-
-                                    <div class="tab-pane fade" id="stripe_card">
-                                        <p class="form-control-guide"><i class="mdi mdi-alert"></i>提供虚拟专用网络业务符合 Stripe 用户协议,但可能不符合 Stripe 提供的部分支付通道(如支付宝、微信)用户协议,相关支付通道可能存在被关闭的风险</p>
-                                        <h5>支付渠道</h5>
-                                        <!-- stripe_card_select -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">银行卡支付</label>
-                                            <select id="stripe_card_select" class="form-control maxwidth-edit">
-                                                <option value="0">停用</option>
-                                                <option value="1" {if $settings['stripe_card'] == true}selected{/if}>
-                                                    启用
-                                                </option>
-                                            </select>
-                                        </div>
-                                        <h5>支付设置</h5>
-                                        <!-- stripe_currency -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">货币单位</label>
-                                            <input class="form-control maxwidth-edit" id="stripe_currency" value="{$settings['stripe_currency']}">
-                                        </div>
-                                        <!-- stripe_min_recharge -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">最低充值限额(整数)</label>
-                                            <input class="form-control maxwidth-edit" id="stripe_min_recharge" value="{$settings['stripe_min_recharge']}">
-                                        </div>
-                                        <!-- stripe_max_recharge -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">最高充值限额(整数)</label>
-                                            <input class="form-control maxwidth-edit" id="stripe_max_recharge" value="{$settings['stripe_max_recharge']}">
-                                        </div>
-                                        <!-- stripe_pk -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">stripe_pk</label>
-                                            <input class="form-control maxwidth-edit" id="stripe_pk" value="{$settings['stripe_pk']}">
-                                        </div>
-                                        <!-- stripe_sk -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">stripe_sk</label>
-                                            <input class="form-control maxwidth-edit" id="stripe_sk" value="{$settings['stripe_sk']}">
-                                        </div>
-                                        <!-- stripe_webhook_key -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">WebHook密钥</label>
-                                            <input class="form-control maxwidth-edit" id="stripe_webhook_key" value="{$settings['stripe_webhook_key']}">
-                                        </div>
-
-                                        <button id="submit_stripe" type="submit" class="btn btn-block btn-brand">提交</button>
-                                    </div>
-                                    
-                                    <div class="tab-pane fade" id="vmqpay">
-                                        <p class="form-control-guide"><i class="mdi mdi-information"></i>此支付方式需自建网关并配置各项参数。访问 <a href="https://github.com/szvone/vmqphp" target="view_window">https://github.com/szvone/vmqphp</a> 了解更多</p>
-                                        <p class="form-control-guide"><i class="mdi mdi-information"></i>开源的 Android 监听端(推荐):<a href="https://gitee.com/yuniks/VMQAPK" target="view_window">https://gitee.com/yuniks/VMQAPK</a></p>
-                                        <p class="form-control-guide"><i class="mdi mdi-information"></i>不开源的 Windows 监听端(不推荐):<a href="https://toscode.gitee.com/pmhw/Vpay" target="view_window">https://toscode.gitee.com/pmhw/Vpay</a></p>
-                                        <!-- vmq_gateway -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">V免签网关</label>
-                                            <input class="form-control maxwidth-edit" id="vmq_gateway" value="{$settings['vmq_gateway']}">
-                                            <p class="form-control-guide"><i class="mdi mdi-information"></i>形如:https://pay.com</p>
-                                        </div>
-                                        <!-- vmq_key -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">V免签密钥</label>
-                                            <input class="form-control maxwidth-edit" id="vmq_key" value="{$settings['vmq_key']}">
-                                        </div>
-                                        
-                                        <button id="submit_vmq_pay" type="submit" class="btn btn-block btn-brand">提交</button>
-                                    </div>
-                                    
-                                    <div class="tab-pane fade" id="f2fpay">
-                                        <p class="form-control-guide"><i class="mdi mdi-information"></i>此处申请: <a href="https://b.alipay.com/signing/productDetailV2.htm?productId=I1011000290000001003" target="view_window">https://b.alipay.com/signing/productDetailV2.htm?productId=I1011000290000001003</a></p>
-                                        <!-- f2f_pay_app_id -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">App ID</label>
-                                            <input class="form-control maxwidth-edit" id="f2f_pay_app_id" value="{$settings['f2f_pay_app_id']}">
-                                        </div>
-                                        <!-- f2f_pay_pid -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">PID</label>
-                                            <input class="form-control maxwidth-edit" id="f2f_pay_pid" value="{$settings['f2f_pay_pid']}">
-                                            <p class="form-control-guide"><i class="mdi mdi-information"></i>此项可留空,不影响使用</p>
-                                        </div>
-                                        <!-- f2f_pay_public_key -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">公钥</label>
-                                            <textarea class="form-control maxwidth-edit" id="f2f_pay_public_key" rows="4">{$settings['f2f_pay_public_key']}</textarea>
-                                        </div>
-                                        <!-- f2f_pay_private_key -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">私钥</label>
-                                            <textarea class="form-control maxwidth-edit" id="f2f_pay_private_key" rows="12">{$settings['f2f_pay_private_key']}</textarea>
-                                        </div>
-                                        <!-- f2f_pay_notify_url -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">自定义回调地址</label>
-                                            <input class="form-control maxwidth-edit" id="f2f_pay_notify_url" value="{$settings['f2f_pay_notify_url']}">
-                                            <p class="form-control-guide"><i class="mdi mdi-information"></i>此项可留空,不影响使用</p>
-                                        </div>
-                                        
-                                        <button id="submit_f2f_pay" type="submit" class="btn btn-block btn-brand">提交</button>
-                                    </div>
-								
-								<div class="tab-pane fade" id="epay">
-                                        <!-- epay_url -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">易支付URL</label>
-                                            <input class="form-control maxwidth-edit" id="epay_url" value="{$settings['epay_url']}">
-											<p class="form-control-guide"><i class="mdi mdi-information"></i>不同易支付url后缀不同,1:域名后面带/ 2:域名后面带submit.php/</p>
-                                        </div>
-                                        <!-- epay_pid -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">商户ID</label>
-                                            <input class="form-control maxwidth-edit" id="epay_pid" value="{$settings['epay_pid']}">
-                                            <p class="form-control-guide"><i class="mdi mdi-information"></i>必填</p>
-                                        </div>
-                                        <!-- epay_key -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">商户Key</label>
-											<input class="form-control maxwidth-edit" id="epay_key" value="{$settings['epay_key']}">
-                                        
-											<p class="form-control-guide"><i class="mdi mdi-information"></i>必填</p>
-                                        </div>
-                                        <!-- epay_alipay -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">支付宝</label>
-                                            <select id="epay_alipay" class="form-control maxwidth-edit">
-                                                <option value="0">停用</option>
-                                                <option value="1" {if $settings['epay_alipay'] == true}selected{/if}>
-                                                    启用
-                                                </option>
-                                            </select>
-                                        </div>
-                                        <!-- epay_wechat -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">微信支付</label>
-                                            <select id="epay_wechat" class="form-control maxwidth-edit">
-                                                <option value="0">停用</option>
-                                                <option value="1" {if $settings['epay_wechat'] == true}selected{/if}>
-                                                    启用
-                                                </option>
-                                            </select>
-                                        </div>
-                                        <!-- epay_qq -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">QQ钱包</label>
-                                            <select id="epay_qq" class="form-control maxwidth-edit">
-                                                <option value="0">停用</option>
-                                                <option value="1" {if $settings['epay_qq'] == true}selected{/if}>
-                                                    启用
-                                                </option>
-                                            </select>
-                                        </div>
-                                        <!-- epay_usdt -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">USDT</label>
-                                            <select id="epay_usdt" class="form-control maxwidth-edit">
-                                                <option value="0">停用</option>
-                                                <option value="1" {if $settings['epay_usdt'] == true}selected{/if}>
-                                                    启用
-                                                </option>
-                                            </select>
-                                        </div>
-                                        <button id="submit_e_pay" type="submit" class="btn btn-block btn-brand">提交</button>
-                                     </div>
-                                </div>
-
-                                <div class="tab-pane fade" id="customer_service_system_settings">
-                                    <nav class="tab-nav margin-top-no">
-                                        <ul class="nav nav-list">
-                                            <li class="active">
-                                                <a data-toggle="tab" href="#web_customer_service_system">&nbsp;网页客服</a>
-                                            </li>
-                                            <li>
-                                                <a data-toggle="tab" href="#admin_contact">&nbsp;联系站长</a>
-                                            </li>
-                                        </ul>
-                                    </nav>
-                                    <div class="tab-pane fade active in" id="web_customer_service_system">
-                                        <!-- live_chat -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">网页客服系统</label>
-                                            <select id="live_chat" class="form-control maxwidth-edit">
-                                                <option value="none" {if $settings['live_chat'] == "none"}selected{/if}>不启用</option>
-                                                <option value="tawk" {if $settings['live_chat'] == "tawk"}selected{/if}>Tawk</option>
-                                                <option value="crisp" {if $settings['live_chat'] == "crisp"}selected{/if}>Crisp</option>
-                                                <option value="livechat" {if $settings['live_chat'] == "livechat"}selected{/if}>LiveChat</option>
-                                                <option value="mylivechat" {if $settings['live_chat'] == "mylivechat"}selected{/if}>MyLiveChat</option>
-                                            </select>
-                                            <p class="form-control-guide"><i class="mdi mdi-information"></i>目前仅 Crisp 与 LiveChat 支持在聊天时传递用户部分账户信息(如账户余额、到期时间、已用流量和剩余流量等)</p>
-                                        </div>
-                                        <!-- tawk_id -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">Tawk</label>
-                                            <input class="form-control maxwidth-edit" id="tawk_id" value="{$settings['tawk_id']}">
-                                            <p class="form-control-guide"><i class="mdi mdi-information"></i>在 <a href="https://tawk.to" target="view_window">https://tawk.to</a> 申请,这应该是 24 位字符</p>
-                                        </div>
-                                        <!-- crisp_id -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">Crisp</label>
-                                            <input class="form-control maxwidth-edit" id="crisp_id" value="{$settings['crisp_id']}">
-                                            <p class="form-control-guide"><i class="mdi mdi-information"></i>在 <a href="https://crisp.chat/en" target="view_window">https://crisp.chat/en</a> 申请,这应该是一个 UUID</p>
-                                        </div>
-                                        <!-- livechat_id -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">LiveChat</label>
-                                            <input class="form-control maxwidth-edit" id="livechat_id" value="{$settings['livechat_id']}">
-                                            <p class="form-control-guide"><i class="mdi mdi-information"></i>在 <a href="https://www.livechat.com/cn" target="view_window">https://www.livechat.com/cn</a> 申请,这应该是 8 位数字</p>
-                                        </div>
-                                        <!-- mylivechat_id -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">MyLiveChat</label>
-                                            <input class="form-control maxwidth-edit" id="mylivechat_id" value="{$settings['mylivechat_id']}">
-                                            <p class="form-control-guide"><i class="mdi mdi-information"></i>在 <a href="https://www.mylivechat.com" target="view_window">https://www.mylivechat.com</a> 申请,这个我不知道</p>
-                                        </div>
-
-                                        <button id="submit_web_customer_service_system" type="submit" class="btn btn-block btn-brand">提交</button>
-                                    </div>
-                                    <div class="tab-pane fade" id="admin_contact">
-                                        <p class="form-control-guide"><i class="mdi mdi-information"></i>注意:留空的联系方式将不显示</p>
-                                        <p class="form-control-guide"><i class="mdi mdi-information"></i>支持使用 HTML 标签。你可以通过配置 a 标签,达到点击即可唤起对应app会话窗口的效果</p>
-                                        <p class="form-control-guide"><i class="mdi mdi-information"></i>若开启此功能,此页面展示的联系方式将显示在:</p>
-                                        <p class="form-control-guide"><i class="mdi mdi-information"></i>1. 注册或重置密码页面点击【无法收到验证码】按钮</p>
-                                        <p class="form-control-guide"><i class="mdi mdi-information"></i>2. 用户账户被停用的告知页面</p>
-                                        <p class="form-control-guide"><i class="mdi mdi-information"></i>3. 充值页面提示充值未到账的用户</p>
-                                        <p class="form-control-guide"><i class="mdi mdi-information"></i>4. 用户中心首页公告栏下方</p>
-                                        <!-- enable_admin_contact -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">是否显示站长联系方式</label>
-                                            <select id="enable_admin_contact" class="form-control maxwidth-edit">
-                                                <option value="0" {if $settings['enable_admin_contact'] == false}selected{/if}>关闭</option>
-                                                <option value="1" {if $settings['enable_admin_contact'] == true}selected{/if}>开启</option>
-                                            </select>
-                                        </div>
-                                        <!-- admin_contact1 -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">站长联系方式一</label>
-                                            <input class="form-control maxwidth-edit" id="admin_contact1" value="{htmlspecialchars($settings['admin_contact1'])}">
-                                        </div>
-                                        <!-- admin_contact2 -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">站长联系方式二</label>
-                                            <input class="form-control maxwidth-edit" id="admin_contact2" value="{htmlspecialchars($settings['admin_contact2'])}">
-                                        </div>
-                                        <!-- admin_contact3 -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">站长联系方式三</label>
-                                            <input class="form-control maxwidth-edit" id="admin_contact3" value="{htmlspecialchars($settings['admin_contact3'])}">
-                                        </div>
-
-                                        <button id="submit_admin_contact" type="submit" class="btn btn-block btn-brand">提交</button>
-                                    </div>
-                                </div>
-
-                                <div class="tab-pane fade" id="verification_code_settings">
-                                    <nav class="tab-nav margin-top-no">
-                                        <ul class="nav nav-list">
-                                            <li class="active">
-                                                <a data-toggle="tab" href="#verification_code_public_settings">&nbsp;设置</a>
-                                            </li>
-                                            <li>
-                                                <a data-toggle="tab" href="#turnstile">&nbsp;Turnstile</a>
-                                            </li>
-                                            <li>
-                                                <a data-toggle="tab" href="#geetest">&nbsp;Geetest</a>
-                                            </li>
-                                        </ul>
-                                    </nav>
-                                            
-                                    <div class="tab-pane fade active in" id="verification_code_public_settings">
-                                        <!-- captcha_provider -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">验证码提供商</label>
-                                            <select id="captcha_provider" class="form-control maxwidth-edit">
-                                                <option value="turnstile" {if $settings['captcha_provider'] == "turnstile"}selected{/if}>Turnstile</option>
-                                                <option value="geetest" {if $settings['captcha_provider'] == "geetest"}selected{/if}>Geetest</option>
-                                            </select>
-                                        </div>
-                                        <!-- enable_reg_captcha -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">注册验证码</label>
-                                            <select id="enable_reg_captcha" class="form-control maxwidth-edit">
-                                                <option value="0" {if $settings['enable_reg_captcha'] == false}selected{/if}>关闭</option>
-                                                <option value="1" {if $settings['enable_reg_captcha'] == true}selected{/if}>开启</option>
-                                            </select>
-                                        </div>
-                                        <!-- enable_login_captcha -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">登录验证码</label>
-                                            <select id="enable_login_captcha" class="form-control maxwidth-edit">
-                                                <option value="0" {if $settings['enable_login_captcha'] == false}selected{/if}>关闭</option>
-                                                <option value="1" {if $settings['enable_login_captcha'] == true}selected{/if}>开启</option>
-                                            </select>
-                                        </div>
-                                        <!-- enable_checkin_captcha -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">签到验证码</label>
-                                            <select id="enable_checkin_captcha" class="form-control maxwidth-edit">
-                                                <option value="0" {if $settings['enable_checkin_captcha'] == false}selected{/if}>关闭</option>
-                                                <option value="1" {if $settings['enable_checkin_captcha'] == true}selected{/if}>开启</option>
-                                            </select>
-                                        </div>
-                                        <!-- enable_reset_password_captcha -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">重置密码验证码</label>
-                                            <select id="enable_reset_password_captcha" class="form-control maxwidth-edit">
-                                                <option value="0" {if $settings['enable_reset_password_captcha'] == false}selected{/if}>关闭</option>
-                                                <option value="1" {if $settings['enable_reset_password_captcha'] == true}selected{/if}>开启</option>
-                                            </select>
-                                        </div>
-
-                                        <button id="submit_verify_code" type="submit" class="btn btn-block btn-brand">提交</button>
-                                    </div>
-                                    <div class="tab-pane fade" id="turnstile">
-                                        <p class="form-control-guide"><i class="mdi mdi-information"></i>在 <a href="https://developers.cloudflare.com/turnstile/get-started/#sitekey-and-secret-key" target="view_window">https://developers.cloudflare.com/turnstile/get-started/#sitekey-and-secret-key</a> 申请</p>
-                                        <!-- turnstile_sitekey -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">Turnstile Site Key</label>
-                                            <input class="form-control maxwidth-edit" id="turnstile_sitekey" value="{$settings['turnstile_sitekey']}">
-                                        </div>
-                                        <!-- turnstile_secret -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">Turnstile Secret</label>
-                                            <input class="form-control maxwidth-edit" id="turnstile_secret" value="{$settings['turnstile_secret']}">
-                                        </div>
-
-                                        <button id="submit_turnstile" type="submit" class="btn btn-block btn-brand">提交</button>
-                                    </div>
-                                    <div class="tab-pane fade" id="geetest">
-                                        <p class="form-control-guide"><i class="mdi mdi-information"></i>在 <a href="https://gtaccount.geetest.com/sensebot/overview" target="view_window">https://gtaccount.geetest.com/sensebot/overview</a> 申请</p>
-                                        <!-- geetest_id -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">Geetest ID</label>
-                                            <input class="form-control maxwidth-edit" id="geetest_id" value="{$settings['geetest_id']}">
-                                        </div>
-                                        <!-- geetest_key -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">Geetest Key</label>
-                                            <input class="form-control maxwidth-edit" id="geetest_key" value="{$settings['geetest_key']}">
-                                        </div>
-
-                                        <button id="submit_geetest" type="submit" class="btn btn-block btn-brand">提交</button>
-                                    </div>
-                                </div>
-
-                                <div class="tab-pane fade" id="registration_settings">
-                                    <nav class="tab-nav margin-top-no">
-                                        <ul class="nav nav-list">
-                                            <li class="active">
-                                                <a data-toggle="tab" href="#reg_mode_and_verify">&nbsp;注册模式与验证</a>
-                                            </li>
-                                            <li>
-                                                <a data-toggle="tab" href="#register_default_value">&nbsp;默认值</a>
-                                            </li>
-                                        </ul>
-                                    </nav>
-                                            
-                                    <div class="tab-pane fade active in" id="reg_mode_and_verify">
-                                        <!-- reg_mode -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">注册模式设置</label>
-                                            <select id="reg_mode" class="form-control maxwidth-edit">
-                                                <option value="close" {if $settings['reg_mode'] == 'close'}selected{/if}>关闭公共注册</option>
-                                                <option value="open" {if $settings['reg_mode'] == 'open'}selected{/if}>开启公共注册</option>
-                                                <option value="invite" {if $settings['reg_mode'] == 'invite'}selected{/if}>仅限用户邀请注册</option>
-                                            </select>
-                                        </div>
-                                        <!-- reg_email_verify -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">注册邮箱验证码验证</label>
-                                            <select id="reg_email_verify" class="form-control maxwidth-edit">
-                                                <option value="0" {if $settings['reg_email_verify'] == false}selected{/if}>关闭</option>
-                                                <option value="1" {if $settings['reg_email_verify'] == true}selected{/if}>开启</option>
-                                            </select>
-                                        </div>
-                                        <!-- email_verify_ttl -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">注册邮箱验证码有效期(单位:秒)</label>
-                                            <input class="form-control maxwidth-edit" id="email_verify_ttl" value="{$settings['email_verify_ttl']}">
-                                        </div>
-                                        <!-- email_verify_ip_limit -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">验证码有效期内单个ip可请求的发件次数</label>
-                                            <input class="form-control maxwidth-edit" id="email_verify_ip_limit" value="{$settings['email_verify_ip_limit']}">
-                                        </div>
-
-                                        <button type="submit" class="btn btn-block btn-brand submit_register_settings">提交</button>
-                                    </div>
-
-                                    <div class="tab-pane fade" id="register_default_value">
-                                        <h5>注册默认</h5>
-                                        <!-- random_group -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">注册时随机分配到的分组,多个分组请用英文半角逗号分隔</label>
-                                            <input class="form-control maxwidth-edit" id="random_group" value="{$settings['random_group']}">
-                                        </div>
-                                        <!-- min_port -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">用户端口池最小值,0为用户在注册的时候不会被分配多用户端口</label>
-                                            <input class="form-control maxwidth-edit" id="min_port" value="{$settings['min_port']}">
-                                        </div>
-                                        <!-- max_port -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">用户端口池最大值,0为用户在注册的时候不会被分配多用户端口</label>
-                                            <input class="form-control maxwidth-edit" id="max_port" value="{$settings['max_port']}">
-                                        </div>
-                                        <!-- sign_up_for_free_traffic -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">注册时赠送的流量(单位:GB)</label>
-                                            <input class="form-control maxwidth-edit" id="sign_up_for_free_traffic" value="{$settings['sign_up_for_free_traffic']}">
-                                        </div>
-                                        <!-- free_user_reset_day -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">免费用戶的流量重置日,0为不重置</label>
-                                            <input class="form-control maxwidth-edit" id="free_user_reset_day" value="{$settings['free_user_reset_day']}">
-                                        </div>
-                                        <!-- free_user_reset_bandwidth -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">需要重置的免费流量,0为不重置</label>
-                                            <input class="form-control maxwidth-edit" id="free_user_reset_bandwidth" value="{$settings['free_user_reset_bandwidth']}">
-                                        </div>
-                                        <!-- sign_up_for_free_time -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">注册时赠送的时长(单位:天)</label>
-                                            <input class="form-control maxwidth-edit" id="sign_up_for_free_time" value="{$settings['sign_up_for_free_time']}">
-                                        </div>
-                                        <!-- sign_up_for_class -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">注册时设定的等级</label>
-                                            <input class="form-control maxwidth-edit" id="sign_up_for_class" value="{$settings['sign_up_for_class']}">
-                                        </div>
-                                        <!-- sign_up_for_class_time -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">注册时设定的等级过期时间(单位:天)</label>
-                                            <input class="form-control maxwidth-edit" id="sign_up_for_class_time" value="{$settings['sign_up_for_class_time']}">
-                                        </div>
-                                        <h5>注册限制</h5>
-                                        <!-- sign_up_for_invitation_codes -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">初始邀请注册链接使用次数限制</label>
-                                            <input class="form-control maxwidth-edit" id="sign_up_for_invitation_codes" value="{$settings['sign_up_for_invitation_codes']}">
-                                        </div>
-                                        <!-- connection_device_limit -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">连接设备限制</label>
-                                            <input class="form-control maxwidth-edit" id="connection_device_limit" value="{$settings['connection_device_limit']}">
-                                        </div>
-                                        <!-- connection_rate_limit -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">使用速率限制</label>
-                                            <input class="form-control maxwidth-edit" id="connection_rate_limit" value="{$settings['connection_rate_limit']}">
-                                        </div>
-                                        <h5>Shadowsocks 设置</h5>
-                                        <!-- sign_up_for_method -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">默认加密</label>
-                                            <input class="form-control maxwidth-edit" id="sign_up_for_method" value="{$settings['sign_up_for_method']}">
-                                        </div>
-                                        <h5>其他</h5>
-                                        <!-- reg_forbidden_ip -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">注册时默认禁止访问IP列表</label>
-                                            <input class="form-control maxwidth-edit" id="reg_forbidden_ip" value="{$settings['reg_forbidden_ip']}">
-                                        </div>
-                                        <!-- reg_forbidden_port -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">注册时默认禁止访问端口列表</label>
-                                            <input class="form-control maxwidth-edit" id="reg_forbidden_port" value="{$settings['reg_forbidden_port']}">
-                                        </div>
-                                        <!-- sign_up_for_daily_report -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">注册后是否默认接收每日用量邮件推送</label>
-                                            <select id="sign_up_for_daily_report" class="form-control maxwidth-edit">
-                                                <option value="0" {if $settings['sign_up_for_daily_report'] == false}selected{/if}>关闭</option>
-                                                <option value="1" {if $settings['sign_up_for_daily_report'] == true}selected{/if}>开启</option>
-                                            </select>
-                                        </div>
-                                        <!-- enable_reg_im -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">注册时是否要求用户输入IM联系方式</label>
-                                            <select id="enable_reg_im" class="form-control maxwidth-edit">
-                                                <option value="0" {if $settings['enable_reg_im'] == false}selected{/if}>关闭</option>
-                                                <option value="1" {if $settings['enable_reg_im'] == true}selected{/if}>开启</option>
-                                            </select>
-                                        </div>
-
-                                        <button type="submit" class="btn btn-block btn-brand submit_register_settings">提交</button>
-                                    </div>
-                                </div>
-
-                                <div class="tab-pane fade" id="invitation_settings">
-                                    <nav class="tab-nav margin-top-no">
-                                        <ul class="nav nav-list">
-                                            <li class="active">
-                                                <a data-toggle="tab" href="#invite_gernal_settings">&nbsp;设置</a>
-                                            </li>
-                                            <li>
-                                                <a data-toggle="tab" href="#rebate_mode">&nbsp;模式</a>
-                                            </li>
-                                        </ul>
-                                    </nav>
-
-                                    <div class="tab-pane fade active in" id="invite_gernal_settings">
-                                        <!-- invitation_to_register_balance_reward -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">若有人使用现存用户的邀请链接注册,被邀请人所能获得的余额奖励(单位:元)</label>
-                                            <input class="form-control maxwidth-edit" id="invitation_to_register_balance_reward" value="{$settings['invitation_to_register_balance_reward']}">
-                                        </div>
-                                        <!-- invitation_to_register_traffic_reward -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">若有人使用现存用户的邀请链接注册,邀请人所能获得的流量奖励(单位:GB)</label>
-                                            <input class="form-control maxwidth-edit" id="invitation_to_register_traffic_reward" value="{$settings['invitation_to_register_traffic_reward']}">
-                                        </div>
-                                        <!-- invite_price -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">用户购买邀请码所需要的价格,价格小于0时视为不开放购买</label>
-                                            <input class="form-control maxwidth-edit" id="invite_price" value="{$settings['invite_price']}">
-                                        </div>
-                                        <!-- custom_invite_price -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">用户定制邀请码所需要的价格,价格小于0时视为不开放购买</label>
-                                            <input class="form-control maxwidth-edit" id="custom_invite_price" value="{$settings['custom_invite_price']}">
-                                        </div>
-
-                                        <br/>
-                                        
-                                        <button type="submit" class="btn btn-block btn-brand submit_invite_settings">提交</button>
-                                    </div>
-                                            
-                                    <div class="tab-pane fade" id="rebate_mode">
-                                        <!-- invitation_mode -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">邀请模式</label>
-                                            <select id="invitation_mode" class="form-control maxwidth-edit">
-                                                <option value="registration_only" {if $settings['invitation_mode'] == 'registration_only'}selected{/if}>
-                                                仅使用邀请注册功能,不返利</option>
-                                                <option value="after_recharge" {if $settings['invitation_mode'] == 'after_recharge'}selected{/if}>
-                                                使用邀请注册功能,并在被邀请用户充值时返利</option>
-                                                <option value="after_purchase" {if $settings['invitation_mode'] == 'after_purchase'}selected{/if}>
-                                                使用邀请注册功能,并在被邀请用户购买时返利</option>
-                                            </select>
-                                        </div>
-                                        <!-- invite_rebate_mode -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">返利模式</label>
-                                            <select id="invite_rebate_mode" class="form-control maxwidth-edit">
-                                                <option value="continued" {if $settings['invite_rebate_mode'] == 'continued'}selected{/if}>
-                                                持续返利</option>
-                                                <option value="limit_frequency" {if $settings['invite_rebate_mode'] == 'limit_frequency'}selected{/if}>
-                                                限制邀请人能从被邀请人身上获得的总返利次数</option>
-                                                <option value="limit_amount" {if $settings['invite_rebate_mode'] == 'limit_amount'}selected{/if}>
-                                                限制邀请人能从被邀请人身上获得的总返利金额</option>
-                                                <option value="limit_time_range" {if $settings['invite_rebate_mode'] == 'limit_time_range'}selected{/if}>
-                                                限制邀请人能从被邀请人身上获得返利的时间范围</option>
-                                            </select>
-                                        </div>
-                                        <!-- rebate_ratio -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">返利比例。10 元商品反 2 元就填 0.2</label>
-                                            <input class="form-control maxwidth-edit" id="rebate_ratio" value="{$settings['rebate_ratio']}">
-                                        </div>
-                                        <h5>返利限制模式</h5>
-                                        <p class="form-control-guide"><i class="mdi mdi-information"></i>以下设置项仅在选择对应返利限制模式时生效</p>
-                                        <!-- rebate_time_range_limit -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">返利时间范围限制(单位:天)</label>
-                                            <input class="form-control maxwidth-edit" id="rebate_time_range_limit" value="{$settings['rebate_time_range_limit']}">
-                                        </div>
-                                        <!-- rebate_frequency_limit -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">返利总次数限制</label>
-                                            <input class="form-control maxwidth-edit" id="rebate_frequency_limit" value="{$settings['rebate_frequency_limit']}">
-                                        </div>
-                                        <p class="form-control-guide"><i class="mdi mdi-information"></i>例如:设置为 3 时,一个被邀请用户先后购买了售价为 10,20,50,100 的商品,则只对前三笔订单返利(假设设置为在购买时返利)</p>
-                                        <!-- rebate_amount_limit -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">返利总金额限制</label>
-                                            <input class="form-control maxwidth-edit" id="rebate_amount_limit" value="{$settings['rebate_amount_limit']}">
-                                        </div>
-                                        <p class="form-control-guide"><i class="mdi mdi-information"></i>例如:设置为 10 时,一个被邀请用户先后购买了售价为 10,20,50,100 的商品,若返点设置为 20% ,则第一次购买返利为 2;第二次为 4;第三次为 4;第四次及之后的购买,邀请人所能获得的返利均为 0(假设设置为在购买时返利)</p>
-                                        <p class="form-control-guide"><i class="mdi mdi-information"></i>在进行第三次返利计算时,按设置应返利订单金额的 20% ,即 10 元。但因已获得历史返利 6 元,则只能获得返利总金额限制与历史返利的差值</p>
-                                        
-                                        <br/>
-                                        
-                                        <button type="submit" class="btn btn-block btn-brand submit_invite_settings">提交</button>
-                                    </div>
-                                </div>
-
-                                <div class="tab-pane fade" id="telegram_settings">
-                                    <nav class="tab-nav margin-top-no">
-                                        <ul class="nav nav-list">
-                                            <li class="active">
-                                                <a data-toggle="tab" href="#telegram_gernal_settings">&nbsp;设置</a>
-                                            </li>
-                                        </ul>
-                                    </nav>
-                                    <div class="tab-pane fade active in" id="telegram_gernal_settings">
-                                        <!-- telegram_add_node -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">添加节点通知</label>
-                                            <select id="telegram_add_node" class="form-control maxwidth-edit">
-                                                <option value="0" {if $settings['telegram_add_node'] == false}selected{/if}>关闭</option>
-                                                <option value="1" {if $settings['telegram_add_node'] == true}selected{/if}>开启</option>
-                                            </select>
-                                        </div>
-                                        <!-- telegram_add_node_text -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">添加节点通知文本</label>
-                                            <input class="form-control maxwidth-edit" id="telegram_add_node_text" value="{$settings['telegram_add_node_text']}">
-                                        </div>
-                                        <!-- telegram_update_node -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">修改节点通知</label>
-                                            <select id="telegram_update_node" class="form-control maxwidth-edit">
-                                                <option value="0" {if $settings['telegram_update_node'] == false}selected{/if}>关闭</option>
-                                                <option value="1" {if $settings['telegram_update_node'] == true}selected{/if}>开启</option>
-                                            </select>
-                                        </div>
-                                        <!-- telegram_update_node_text -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">修改节点通知文本</label>
-                                            <input class="form-control maxwidth-edit" id="telegram_update_node_text" value="{$settings['telegram_update_node_text']}">
-                                        </div>
-                                        <!-- telegram_delete_node -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">删除节点通知</label>
-                                            <select id="telegram_delete_node" class="form-control maxwidth-edit">
-                                                <option value="0" {if $settings['telegram_delete_node'] == false}selected{/if}>关闭</option>
-                                                <option value="1" {if $settings['telegram_delete_node'] == true}selected{/if}>开启</option>
-                                            </select>
-                                        </div>
-                                        <!-- telegram_delete_node_text -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">删除节点通知文本</label>
-                                            <input class="form-control maxwidth-edit" id="telegram_delete_node_text" value="{$settings['telegram_delete_node_text']}">
-                                        </div>
-                                        <!-- telegram_node_gfwed -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">节点被墙通知</label>
-                                            <select id="telegram_node_gfwed" class="form-control maxwidth-edit">
-                                                <option value="0" {if $settings['telegram_node_gfwed'] == false}selected{/if}>关闭</option>
-                                                <option value="1" {if $settings['telegram_node_gfwed'] == true}selected{/if}>开启</option>
-                                            </select>
-                                        </div>
-                                        <!-- telegram_node_gfwed_text -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">节点被墙通知文本</label>
-                                            <input class="form-control maxwidth-edit" id="telegram_node_gfwed_text" value="{$settings['telegram_node_gfwed_text']}">
-                                        </div>
-                                        <!-- telegram_node_ungfwed -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">节点被墙恢复通知</label>
-                                            <select id="telegram_node_ungfwed" class="form-control maxwidth-edit">
-                                                <option value="0" {if $settings['telegram_node_ungfwed'] == false}selected{/if}>关闭</option>
-                                                <option value="1" {if $settings['telegram_node_ungfwed'] == true}selected{/if}>开启</option>
-                                            </select>
-                                        </div>
-                                        <!-- telegram_node_ungfwed_text -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">节点被墙恢复通知文本</label>
-                                            <input class="form-control maxwidth-edit" id="telegram_node_ungfwed_text" value="{$settings['telegram_node_ungfwed_text']}">
-                                        </div>
-                                        <!-- telegram_node_online -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">节点恢复上线通知</label>
-                                            <select id="telegram_node_online" class="form-control maxwidth-edit">
-                                                <option value="0" {if $settings['telegram_node_online'] == false}selected{/if}>关闭</option>
-                                                <option value="1" {if $settings['telegram_node_online'] == true}selected{/if}>开启</option>
-                                            </select>
-                                        </div>
-                                        <!-- telegram_node_online_text -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">节点恢复上线通知文本</label>
-                                            <input class="form-control maxwidth-edit" id="telegram_node_online_text" value="{$settings['telegram_node_online_text']}">
-                                        </div>
-                                        <!-- telegram_node_offline -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">节点离线通知</label>
-                                            <select id="telegram_node_offline" class="form-control maxwidth-edit">
-                                                <option value="0" {if $settings['telegram_node_offline'] == false}selected{/if}>关闭</option>
-                                                <option value="1" {if $settings['telegram_node_offline'] == true}selected{/if}>开启</option>
-                                            </select>
-                                        </div>
-                                        <!-- telegram_node_offline_text -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">节点离线通知文本</label>
-                                            <input class="form-control maxwidth-edit" id="telegram_node_offline_text" value="{$settings['telegram_node_offline_text']}">
-                                        </div>
-                                        <!-- telegram_daily_job -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">每日任务通知</label>
-                                            <select id="telegram_daily_job" class="form-control maxwidth-edit">
-                                                <option value="0" {if $settings['telegram_daily_job'] == false}selected{/if}>关闭</option>
-                                                <option value="1" {if $settings['telegram_daily_job'] == true}selected{/if}>开启</option>
-                                            </select>
-                                        </div>
-                                        <!-- telegram_daily_job_text -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">每日任务通知文本</label>
-                                            <input class="form-control maxwidth-edit" id="telegram_daily_job_text" value="{$settings['telegram_daily_job_text']}">
-                                        </div>
-                                        <!-- telegram_diary -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">系统运行状况通知</label>
-                                            <select id="telegram_diary" class="form-control maxwidth-edit">
-                                                <option value="0" {if $settings['telegram_diary'] == false}selected{/if}>关闭</option>
-                                                <option value="1" {if $settings['telegram_diary'] == true}selected{/if}>开启</option>
-                                            </select>
-                                        </div>
-                                        <!-- telegram_diary_text -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">系统运行状况通知文本</label>
-                                            <input class="form-control maxwidth-edit" id="telegram_diary_text" value="{$settings['telegram_diary_text']}">
-                                        </div>
-                                        <!-- telegram_unbind_kick_member -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">解绑Telegram账户后自动踢出群组</label>
-                                            <select id="telegram_unbind_kick_member" class="form-control maxwidth-edit">
-                                                <option value="0" {if $settings['telegram_unbind_kick_member'] == false}selected{/if}>关闭</option>
-                                                <option value="1" {if $settings['telegram_unbind_kick_member'] == true}selected{/if}>开启</option>
-                                            </select>
-                                        </div>
-                                        <!-- telegram_group_bound_user -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">仅允许已绑定Telegram账户的用户加入群组</label>
-                                            <select id="telegram_group_bound_user" class="form-control maxwidth-edit">
-                                                <option value="0" {if $settings['telegram_group_bound_user'] == false}selected{/if}>关闭</option>
-                                                <option value="1" {if $settings['telegram_group_bound_user'] == true}selected{/if}>开启</option>
-                                            </select>
-                                        </div>
-                                        <!-- telegram_show_group_link -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">启用Telegram机器人显示用户群组链接</label>
-                                            <select id="telegram_show_group_link" class="form-control maxwidth-edit">
-                                                <option value="0" {if $settings['telegram_show_group_link'] == false}selected{/if}>关闭</option>
-                                                <option value="1" {if $settings['telegram_show_group_link'] == true}selected{/if}>开启</option>
-                                            </select>
-                                        </div>
-                                        <!-- telegram_group_link -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">用户群组链接</label>
-                                            <input class="form-control maxwidth-edit" id="telegram_group_link" value="{$settings['telegram_group_link']}">
-                                        </div>
-
-                                        <button id="submit_telegram_gernal_settings" type="submit" class="btn btn-block btn-brand">提交</button>
-                                    </div>
-                                </div>
-                            </div>
-                        </div>
-                    </div>
-                </div>
-            </div>
-        </div>
-        {include file='dialog.tpl'}
-    </div>
-</main>
-
-{include file='admin/footer.tpl'}
-
-<script>
-    window.addEventListener('load', () => {
-        $$.getElementById('submit_f2f_pay').addEventListener('click', () => {
-            $.ajax({
-                type: "POST",
-                url: "/admin/setting",
-                dataType: "json",
-                data: {
-                    class: 'f2f_pay',
-                    f2f_pay_app_id: $$getValue('f2f_pay_app_id'),
-                    f2f_pay_pid: $$getValue('f2f_pay_pid'),
-                    f2f_pay_public_key: $$getValue('f2f_pay_public_key'),
-                    f2f_pay_private_key: $$getValue('f2f_pay_private_key'),
-                    f2f_pay_notify_url: $$getValue('f2f_pay_notify_url')
-                },
-                success: data => {
-                    $("#result").modal();
-                    $$.getElementById('msg').innerHTML = data.msg;
-                    if (data.ret) {
-                        window.setTimeout("location.href='/admin/setting'", {$config['jump_delay']});
-                    }
-                },
-                error: jqXHR => {
-                    alert(`发生错误:${
-                            jqXHR.status
-                            }`);
-                }
-            })
-        })
-    })
-</script>
-<script>
-    window.addEventListener('load', () => {
-        $$.getElementById('submit_e_pay').addEventListener('click', () => {
-            $.ajax({
-                type: "POST",
-                url: "/admin/setting",
-                dataType: "json",
-                data: {
-                    class: 'e_pay',
-                    epay_url: $$getValue('epay_url'),
-                    epay_pid: $$getValue('epay_pid'),
-                    epay_key: $$getValue('epay_key'),
-                    epay_alipay: $$getValue('epay_alipay'),
-                    epay_wechat: $$getValue('epay_wechat'),
-                    epay_qq: $$getValue('epay_qq'),
-                    epay_usdt: $$getValue('epay_usdt')
-                    
-                },
-                success: data => {
-                    $("#result").modal();
-                    $$.getElementById('msg').innerHTML = data.msg;
-                    if (data.ret) {
-                        window.setTimeout("location.href='/admin/setting'", {$config['jump_delay']});
-                    }
-                },
-                error: jqXHR => {
-                    alert(`发生错误:${
-                            jqXHR.status
-                            }`);
-                }
-            })
-        })
-    })
-</script>
-<script>
-    window.addEventListener('load', () => {
-        $$.getElementById('submit_payment').addEventListener('click', () => {
-            {foreach $payment_gateways as $key => $value}
-            if ($$.getElementById("{$value}_switch").checked) {
-                var {$value} = 1;
-            } else {
-                var {$value} = 0;
-            }
-            {/foreach}
-            
-            $.ajax({
-                type: "POST",
-                url: "/admin/setting/payment",
-                dataType: "json",
-                data: {
-                    {foreach $payment_gateways as $key => $value}
-                    {$value},
-                    {/foreach}
-                    class: 'payment'
-                },
-                success: data => {
-                    $("#result").modal();
-                    $$.getElementById('msg').innerHTML = data.msg;
-                    if (data.ret) {
-                        window.setTimeout("location.href='/admin/setting'", {$config['jump_delay']});
-                    }
-                },
-                error: jqXHR => {
-                    alert(`发生错误:${
-                            jqXHR.status
-                            }`);
-                }
-            })
-        })
-    })
-</script>
-
-<script>
-    window.addEventListener('load', () => {
-        $$.getElementById('submit_vmq_pay').addEventListener('click', () => {
-            $.ajax({
-                type: "POST",
-                url: "/admin/setting",
-                dataType: "json",
-                data: {
-                    class: 'vmq_pay',
-                    vmq_gateway: $$getValue('vmq_gateway'),
-                    vmq_key: $$getValue('vmq_key')
-                },
-                success: data => {
-                    $("#result").modal();
-                    $$.getElementById('msg').innerHTML = data.msg;
-                    if (data.ret) {
-                        window.setTimeout("location.href='/admin/setting'", {$config['jump_delay']});
-                    }
-                },
-                error: jqXHR => {
-                    alert(`发生错误:${
-                            jqXHR.status
-                            }`);
-                }
-            })
-        })
-    })
-</script>
-
-<script>
-    window.addEventListener('load', () => {
-        $$.getElementById('submit_mail').addEventListener('click', () => {
-            $.ajax({
-                type: "POST",
-                url: "/admin/setting",
-                dataType: "json",
-                data: {
-                    class: 'mail',
-                    mail_driver: $$getValue('mail_driver')
-                },
-                success: data => {
-                    $("#result").modal();
-                    $$.getElementById('msg').innerHTML = data.msg;
-                    if (data.ret) {
-                        window.setTimeout("location.href='/admin/setting'", {$config['jump_delay']});
-                    }
-                },
-                error: jqXHR => {
-                    alert(`发生错误:${
-                            jqXHR.status
-                            }`);
-                }
-            })
-        })
-    })
-</script>
-
-<script>
-    window.addEventListener('load', () => {
-        $$.getElementById('submit_smtp').addEventListener('click', () => {
-            $.ajax({
-                type: "POST",
-                url: "/admin/setting",
-                dataType: "json",
-                data: {
-                    class: 'smtp',
-                    smtp_host: $$getValue('smtp_host'),
-                    smtp_username: $$getValue('smtp_username'),
-                    smtp_password: $$getValue('smtp_password'),
-                    smtp_port: $$getValue('smtp_port'),
-                    smtp_name: $$getValue('smtp_name'),
-                    smtp_sender: $$getValue('smtp_sender'),
-                    smtp_ssl: $$getValue('smtp_ssl'),
-                    smtp_bbc: $$getValue('smtp_bbc')
-                },
-                success: data => {
-                    $("#result").modal();
-                    $$.getElementById('msg').innerHTML = data.msg;
-                    if (data.ret) {
-                        window.setTimeout("location.href='/admin/setting'", {$config['jump_delay']});
-                    }
-                },
-                error: jqXHR => {
-                    alert(`发生错误:${
-                            jqXHR.status
-                            }`);
-                }
-            })
-        })
-    })
-</script>
-
-<script>
-    window.addEventListener('load', () => {
-        $$.getElementById('submit_email_test').addEventListener('click', () => {
-            $.ajax({
-                type: "POST",
-                url: "/admin/setting/email",
-                dataType: "json",
-                data: {
-                    recipient: $$getValue('testing_email_recipients')
-                },
-                success: data => {
-                    $("#result").modal();
-                    $$.getElementById('msg').innerHTML = data.msg;
-                    if (data.ret) {
-                        window.setTimeout("location.href='/admin/setting'", {$config['jump_delay']});
-                    }
-                },
-                error: jqXHR => {
-                    alert(`发生错误:${
-                            jqXHR.status
-                            }`);
-                }
-            })
-        })
-    })
-</script>
-
-<script>
-    window.addEventListener('load', () => {
-        $$.getElementById('submit_verify_code').addEventListener('click', () => {
-            $.ajax({
-                type: "POST",
-                url: "/admin/setting",
-                dataType: "json",
-                data: {
-                    class: 'verify_code',
-                    captcha_provider: $$getValue('captcha_provider'),
-                    enable_reg_captcha: $$getValue('enable_reg_captcha'),
-                    enable_login_captcha: $$getValue('enable_login_captcha'),
-                    enable_checkin_captcha: $$getValue('enable_checkin_captcha'),
-                    enable_reset_password_captcha: $$getValue('enable_reset_password_captcha')
-                },
-                success: data => {
-                    $("#result").modal();
-                    $$.getElementById('msg').innerHTML = data.msg;
-                    if (data.ret) {
-                        window.setTimeout("location.href='/admin/setting'", {$config['jump_delay']});
-                    }
-                },
-                error: jqXHR => {
-                    alert(`发生错误:${
-                            jqXHR.status
-                            }`);
-                }
-            })
-        })
-    })
-</script>
-
-<script>
-    window.addEventListener('load', () => {
-        $$.getElementById('submit_geetest').addEventListener('click', () => {
-            $.ajax({
-                type: "POST",
-                url: "/admin/setting",
-                dataType: "json",
-                data: {
-                    class: 'verify_code_geetest',
-                    geetest_id: $$getValue('geetest_id'),
-                    geetest_key: $$getValue('geetest_key')
-                },
-                success: data => {
-                    $("#result").modal();
-                    $$.getElementById('msg').innerHTML = data.msg;
-                    if (data.ret) {
-                        window.setTimeout("location.href='/admin/setting'", {$config['jump_delay']});
-                    }
-                },
-                error: jqXHR => {
-                    alert(`发生错误:${
-                            jqXHR.status
-                            }`);
-                }
-            })
-        })
-    })
-</script>
-
-<script>
-    window.addEventListener('load', () => {
-        $$.getElementById('submit_turnstile').addEventListener('click', () => {
-            $.ajax({
-                type: "POST",
-                url: "/admin/setting",
-                dataType: "json",
-                data: {
-                    class: 'verify_code_turnstile',
-                    turnstile_sitekey: $$getValue('turnstile_sitekey'),
-                    turnstile_secret: $$getValue('turnstile_secret')
-                },
-                success: data => {
-                    $("#result").modal();
-                    $$.getElementById('msg').innerHTML = data.msg;
-                    if (data.ret) {
-                        window.setTimeout("location.href='/admin/setting'", {$config['jump_delay']});
-                    }
-                },
-                error: jqXHR => {
-                    alert(`发生错误:${
-                            jqXHR.status
-                            }`);
-                }
-            })
-        })
-    })
-</script>
-
-<script>
-    window.addEventListener('load', () => {
-        $$.getElementById('submit_mailgun').addEventListener('click', () => {
-            $.ajax({
-                type: "POST",
-                url: "/admin/setting",
-                dataType: "json",
-                data: {
-                    class: 'mailgun',
-                    mailgun_key: $$getValue('mailgun_key'),
-                    mailgun_domain: $$getValue('mailgun_domain'),
-                    mailgun_sender: $$getValue('mailgun_sender')
-                },
-                success: data => {
-                    $("#result").modal();
-                    $$.getElementById('msg').innerHTML = data.msg;
-                    if (data.ret) {
-                        window.setTimeout("location.href='/admin/setting'", {$config['jump_delay']});
-                    }
-                },
-                error: jqXHR => {
-                    alert(`发生错误:${
-                            jqXHR.status
-                            }`);
-                }
-            })
-        })
-    })
-</script>
-
-<script>
-    window.addEventListener('load', () => {
-        $$.getElementById('submit_sendgrid').addEventListener('click', () => {
-            $.ajax({
-                type: "POST",
-                url: "/admin/setting",
-                dataType: "json",
-                data: {
-                    class: 'sendgrid',
-                    sendgrid_key: $$getValue('sendgrid_key'),
-                    sendgrid_sender: $$getValue('sendgrid_sender'),
-                    sendgrid_name: $$getValue('sendgrid_name')
-                },
-                success: data => {
-                    $("#result").modal();
-                    $$.getElementById('msg').innerHTML = data.msg;
-                    if (data.ret) {
-                        window.setTimeout("location.href='/admin/setting'", {$config['jump_delay']});
-                    }
-                },
-                error: jqXHR => {
-                    alert(`发生错误:${
-                            jqXHR.status
-                            }`);
-                }
-            })
-        })
-    })
-</script>
-
-<script>
-    window.addEventListener('load', () => {
-        $$.getElementById('submit_ses').addEventListener('click', () => {
-            $.ajax({
-                type: "POST",
-                url: "/admin/setting",
-                dataType: "json",
-                data: {
-                    class: 'ses',
-                    aws_access_key_id: $$getValue('aws_access_key_id'),
-                    aws_secret_access_key: $$getValue('aws_secret_access_key'),
-                    aws_region: $$getValue('aws_region'),
-                    aws_ses_sender: $$getValue('aws_ses_sender')
-                },
-                success: data => {
-                    $("#result").modal();
-                    $$.getElementById('msg').innerHTML = data.msg;
-                    if (data.ret) {
-                        window.setTimeout("location.href='/admin/setting'", {$config['jump_delay']});
-                    }
-                },
-                error: jqXHR => {
-                    alert(`发生错误:${
-                            jqXHR.status
-                            }`);
-                }
-            })
-        })
-    })
-</script>
-
-<script>
-    window.addEventListener('load', () => {
-        $$.getElementById('submit_payjs_pay').addEventListener('click', () => {
-            $.ajax({
-                type: "POST",
-                url: "/admin/setting",
-                dataType: "json",
-                data: {
-                    class: 'payjs_pay',
-                    payjs_url: $$getValue('payjs_url'),
-                    payjs_mchid: $$getValue('payjs_mchid'),
-                    payjs_key: $$getValue('payjs_key')
-                },
-                success: data => {
-                    $("#result").modal();
-                    $$.getElementById('msg').innerHTML = data.msg;
-                    if (data.ret) {
-                        window.setTimeout("location.href='/admin/setting'", {$config['jump_delay']});
-                    }
-                },
-                error: jqXHR => {
-                    alert(`发生错误:${
-                            jqXHR.status
-                            }`);
-                }
-            })
-        })
-    })
-</script>
-
-<script>
-    window.addEventListener('load', () => {
-        $$.getElementById('submit_paymentwall').addEventListener('click', () => {
-            $.ajax({
-                type: "POST",
-                url: "/admin/setting",
-                dataType: "json",
-                data: {
-                    class: 'paymentwall',
-                    pmw_publickey: $$getValue('pmw_publickey'),
-                    pmw_privatekey: $$getValue('pmw_privatekey'),
-                    pmw_widget: $$getValue('pmw_widget'),
-                    pmw_height: $$getValue('pmw_height')
-                },
-                success: data => {
-                    $("#result").modal();
-                    $$.getElementById('msg').innerHTML = data.msg;
-                    if (data.ret) {
-                        window.setTimeout("location.href='/admin/setting'", {$config['jump_delay']});
-                    }
-                },
-                error: jqXHR => {
-                    alert(`发生错误:${
-                            jqXHR.status
-                            }`);
-                }
-            })
-        })
-    })
-</script>
-
-<script>
-    window.addEventListener('load', () => {
-        $$.getElementById('submit_admin_contact').addEventListener('click', () => {
-            $.ajax({
-                type: "POST",
-                url: "/admin/setting",
-                dataType: "json",
-                data: {
-                    class: 'admin_contact',
-                    enable_admin_contact: $$getValue('enable_admin_contact'),
-                    admin_contact1: $$getValue('admin_contact1'),
-                    admin_contact2: $$getValue('admin_contact2'),
-                    admin_contact3: $$getValue('admin_contact3')
-                },
-                success: data => {
-                    $("#result").modal();
-                    $$.getElementById('msg').innerHTML = data.msg;
-                    if (data.ret) {
-                        window.setTimeout("location.href='/admin/setting'", {$config['jump_delay']});
-                    }
-                },
-                error: jqXHR => {
-                    alert(`发生错误:${
-                            jqXHR.status
-                            }`);
-                }
-            })
-        })
-    })
-</script>
-
-<script>
-    window.addEventListener('load', () => {
-        $$.getElementById('submit_web_customer_service_system').addEventListener('click', () => {
-            $.ajax({
-                type: "POST",
-                url: "/admin/setting",
-                dataType: "json",
-                data: {
-                    class: 'web_customer_service_system',
-                    live_chat: $$getValue('live_chat'),
-                    tawk_id: $$getValue('tawk_id'),
-                    crisp_id: $$getValue('crisp_id'),
-                    livechat_id: $$getValue('livechat_id'),
-                    mylivechat_id: $$getValue('mylivechat_id')
-                },
-                success: data => {
-                    $("#result").modal();
-                    $$.getElementById('msg').innerHTML = data.msg;
-                    if (data.ret) {
-                        window.setTimeout("location.href='/admin/setting'", {$config['jump_delay']});
-                    }
-                },
-                error: jqXHR => {
-                    alert(`发生错误:${
-                            jqXHR.status
-                            }`);
-                }
-            })
-        })
-    })
-</script>
-
-<script>
-    window.addEventListener('load', () => {
-        $$.getElementById('submit_theadpay').addEventListener('click', () => {
-            $.ajax({
-                type: "POST",
-                url: "/admin/setting",
-                dataType: "json",
-                data: {
-                    class: 'theadpay',
-                    theadpay_url: $$getValue('theadpay_url'),
-                    theadpay_mchid: $$getValue('theadpay_mchid'),
-                    theadpay_key: $$getValue('theadpay_key')
-                },
-                success: data => {
-                    $("#result").modal();
-                    $$.getElementById('msg').innerHTML = data.msg;
-                    if (data.ret) {
-                        window.setTimeout("location.href='/admin/setting'", {$config['jump_delay']});
-                    }
-                },
-                error: jqXHR => {
-                    alert(`发生错误:${
-                            jqXHR.status
-                            }`);
-                }
-            })
-        })
-    })
-</script>
-
-<script>
-    window.addEventListener('load', () => {
-        $$.getElementById('submit_stripe').addEventListener('click', () => {
-            $.ajax({
-                type: "POST",
-                url: "/admin/setting",
-                dataType: "json",
-                data: {
-                    class: 'stripe',
-                    stripe_card: $$getValue('stripe_card_select'),
-                    stripe_currency: $$getValue('stripe_currency'),
-                    stripe_min_recharge: $$getValue('stripe_min_recharge'),
-                    stripe_max_recharge: $$getValue('stripe_max_recharge'),
-                    stripe_pk: $$getValue('stripe_pk'),
-                    stripe_sk: $$getValue('stripe_sk'),
-                    stripe_webhook_key: $$getValue('stripe_webhook_key')
-                },
-                success: data => {
-                    $("#result").modal();
-                    $$.getElementById('msg').innerHTML = data.msg;
-                    if (data.ret) {
-                        window.setTimeout("location.href='/admin/setting'", {$config['jump_delay']});
-                    }
-                },
-                error: jqXHR => {
-                    alert(`发生错误:${
-                            jqXHR.status
-                            }`);
-                }
-            })
-        })
-    })
-</script>
-
-<script>
-    window.addEventListener('load', () => {
-        $('.submit_register_settings').click( () => {
-            $.ajax({
-                type: "POST",
-                url: "/admin/setting",
-                dataType: "json",
-                data: {
-                    class: 'register',
-                    reg_mode: $$getValue('reg_mode'),
-                    reg_email_verify: $$getValue('reg_email_verify'),
-                    email_verify_ttl: $$getValue('email_verify_ttl'),
-                    email_verify_ip_limit: $$getValue('email_verify_ip_limit'),
-                    random_group: $$getValue('random_group'),
-                    min_port: $$getValue('min_port'),
-                    max_port: $$getValue('max_port'),
-                    sign_up_for_free_traffic: $$getValue('sign_up_for_free_traffic'),
-                    free_user_reset_day: $$getValue('free_user_reset_day'),
-                    free_user_reset_bandwidth: $$getValue('free_user_reset_bandwidth'),
-                    sign_up_for_free_time: $$getValue('sign_up_for_free_time'),
-                    sign_up_for_class: $$getValue('sign_up_for_class'),
-                    sign_up_for_class_time: $$getValue('sign_up_for_class_time'),
-                    sign_up_for_invitation_codes: $$getValue('sign_up_for_invitation_codes'),
-                    connection_device_limit: $$getValue('connection_device_limit'),
-                    connection_rate_limit: $$getValue('connection_rate_limit'),
-                    sign_up_for_method: $$getValue('sign_up_for_method'),
-                    reg_forbidden_ip: $$getValue('reg_forbidden_ip'),
-                    reg_forbidden_port: $$getValue('reg_forbidden_port'),
-                    sign_up_for_daily_report: $$getValue('sign_up_for_daily_report'),
-                    enable_reg_im: $$getValue('enable_reg_im')
-                },
-                success: data => {
-                    $("#result").modal();
-                    $$.getElementById('msg').innerHTML = data.msg;
-                    if (data.ret) {
-                        window.setTimeout("location.href='/admin/setting'", {$config['jump_delay']});
-                    }
-                },
-                error: jqXHR => {
-                    alert(`发生错误:${
-                            jqXHR.status
-                            }`);
-                }
-            })
-        })
-    })
-</script>
-
-<script>
-    window.addEventListener('load', () => {
-        $('.submit_invite_settings').click( () => {
-            $.ajax( {
-                type: "POST",
-                url: "/admin/setting",
-                dataType: "json",
-                data: {
-                    class: 'invite',
-                    invitation_mode: $$getValue('invitation_mode'),
-                    invite_rebate_mode: $$getValue('invite_rebate_mode'),
-                    rebate_ratio: $$getValue('rebate_ratio'),
-                    rebate_frequency_limit: $$getValue('rebate_frequency_limit'),
-                    rebate_amount_limit: $$getValue('rebate_amount_limit'),
-                    rebate_time_range_limit: $$getValue('rebate_time_range_limit'),
-                    invitation_to_register_balance_reward: $$getValue('invitation_to_register_balance_reward'),
-                    invitation_to_register_traffic_reward: $$getValue('invitation_to_register_traffic_reward'),
-                    invite_price: $$getValue('invite_price'),
-                    custom_invite_price: $$getValue('custom_invite_price')
-                },
-                success: data => {
-                    $("#result").modal();
-                    $$.getElementById('msg').innerHTML = data.msg;
-                    if (data.ret) {
-                        window.setTimeout("location.href='/admin/setting'", {$config['jump_delay']});
-                    }
-                },
-                error: jqXHR => {
-                    alert(`发生错误:${
-                            jqXHR.status
-                            }`);
-                }
-            } )
-        } )
-    } )
-</script>
-
-<script>
-    window.addEventListener('load', () => {
-        $$.getElementById('submit_telegram_gernal_settings').addEventListener('click', () => {
-            $.ajax({
-                type: "POST",
-                url: "/admin/setting",
-                dataType: "json",
-                data: {
-                    class: 'telegram',
-                    telegram_add_node: $$getValue('telegram_add_node'),
-                    telegram_add_node_text: $$getValue('telegram_add_node_text'),
-                    telegram_update_node: $$getValue('telegram_update_node'),
-                    telegram_update_node_text: $$getValue('telegram_update_node_text'),
-                    telegram_delete_node: $$getValue('telegram_delete_node'),
-                    telegram_delete_node_text: $$getValue('telegram_delete_node_text'),
-                    telegram_node_gfwed: $$getValue('telegram_node_gfwed'),
-                    telegram_node_gfwed_text: $$getValue('telegram_node_gfwed_text'),
-                    telegram_node_ungfwed: $$getValue('telegram_node_ungfwed'),
-                    telegram_node_ungfwed_text: $$getValue('telegram_node_ungfwed_text'),
-                    telegram_node_online: $$getValue('telegram_node_online'),
-                    telegram_node_online_text: $$getValue('telegram_node_online_text'),
-                    telegram_node_offline: $$getValue('telegram_node_offline'),
-                    telegram_node_offline_text: $$getValue('telegram_node_offline_text'),
-                    telegram_daily_job: $$getValue('telegram_daily_job'),
-                    telegram_daily_job_text: $$getValue('telegram_daily_job_text'),
-                    telegram_diary: $$getValue('telegram_diary'),
-                    telegram_diary_text: $$getValue('telegram_diary_text'),
-                    telegram_unbind_kick_member: $$getValue('telegram_unbind_kick_member'),
-                    telegram_group_bound_user: $$getValue('telegram_group_bound_user'),
-                    telegram_show_group_link: $$getValue('telegram_show_group_link'),
-                    telegram_group_link: $$getValue('telegram_group_link')
-                },
-                success: data => {
-                    $("#result").modal();
-                    $$.getElementById('msg').innerHTML = data.msg;
-                    if (data.ret) {
-                        window.setTimeout("location.href='/admin/setting'", {$config['jump_delay']});
-                    }
-                },
-                error: jqXHR => {
-                    alert(`发生错误:${
-                            jqXHR.status
-                            }`);
-                }
-            })
-        })
-    })
-</script>

+ 324 - 0
resources/views/tabler/admin/setting/billing.tpl

@@ -0,0 +1,324 @@
+{include file='admin/tabler_header.tpl'}
+
+<div class="page-wrapper">
+    <div class="container-xl">
+        <div class="page-header d-print-none text-white">
+            <div class="row align-items-center">
+                <div class="col">
+                    <h2 class="page-title">
+                        <span class="home-title">财务设置</span>
+                    </h2>
+                    <div class="page-pretitle my-3">
+                        <span class="home-subtitle">设置站点的财务系统</span>
+                    </div>
+                </div>
+                <div class="col-auto ms-auto d-print-none">
+                    <div class="btn-list">
+                        <a id="save-setting" href="#" class="btn btn-primary">
+                            <i class="icon ti ti-device-floppy"></i>
+                            保存
+                        </a>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <div class="page-body">
+        <div class="container-xl">
+            <div class="row row-deck row-cards">
+                <div class="col-md-12">
+                    <div class="card">
+                    <div class="card-header">
+                    <ul class="nav nav-tabs card-header-tabs" data-bs-toggle="tabs">
+                        <li class="nav-item">
+                            <a href="#gateway" class="nav-link active" data-bs-toggle="tab">网关选择</a>
+                        </li>
+                        <li class="nav-item">
+                            <a href="#f2f" class="nav-link" data-bs-toggle="tab">支付宝当面付</a>
+                        </li>
+                        <li class="nav-item">
+                            <a href="#vmq" class="nav-link" data-bs-toggle="tab">V免签</a>
+                        </li>
+                        <li class="nav-item">
+                            <a href="#payjs" class="nav-link" data-bs-toggle="tab">PayJS</a>
+                        </li>
+                        <li class="nav-item">
+                            <a href="#theadpay" class="nav-link" data-bs-toggle="tab">TheadPay</a>
+                        </li>
+                        <li class="nav-item">
+                            <a href="#stripe" class="nav-link" data-bs-toggle="tab">Stripe</a>
+                        </li>
+                        <li class="nav-item">
+                            <a href="#epay" class="nav-link" data-bs-toggle="tab">EPay</a>
+                        </li>
+                    </ul>
+                </div>
+                <div class="card-body">
+                    <div class="tab-content">
+                        <div class="tab-pane active show" id="gateway">
+                            {foreach $payment_gateways as $key => $value}
+                            <div class="form-group mb-3 row">
+                                <div class="row align-items-center">
+                                    <label class="form-label col-3 col-form-label">{$key}</label>
+                                    <label class="col-auto ms-auto form-check form-check-single form-switch">
+                                        <input id="{$value}_enable" class="form-check-input" type="checkbox"
+                                        {if in_array($value, $active_payment_gateway)}checked="" {/if}>
+                                    </label>
+                                </div>
+                            </div>
+                            {/foreach}
+                        </div>
+                        <div class="tab-pane" id="f2f">
+                            <div class="card-body">
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">App ID</label>
+                                    <div class="col">
+                                        <input id="f2f_pay_app_id" type="text" class="form-control" value="{$settings['f2f_pay_app_id']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">PID</label>
+                                    <div class="col">
+                                        <input id="f2f_pay_pid" type="text" class="form-control" value="{$settings['f2f_pay_pid']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">公钥</label>
+                                    <div class="col">
+                                        <input id="f2f_pay_public_key" type="text" class="form-control" value="{$settings['f2f_pay_public_key']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">私钥</label>
+                                    <div class="col">
+                                        <input id="f2f_pay_private_key" type="text" class="form-control" value="{$settings['f2f_pay_private_key']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">自定义回调地址(可选)</label>
+                                    <div class="col">
+                                        <input id="f2f_pay_notify_url" type="text" class="form-control" value="{$settings['f2f_pay_notify_url']}">
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="tab-pane" id="vmq">
+                            <div class="card-body">
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">网关地址</label>
+                                    <div class="col">
+                                        <input id="vmq_gateway" type="text" class="form-control" value="{$settings['vmq_gateway']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">密钥</label>
+                                    <div class="col">
+                                        <input id="vmq_key" type="text" class="form-control" value="{$settings['vmq_key']}">
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="tab-pane" id="payjs">
+                            <div class="card-body">
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">网关地址</label>
+                                    <div class="col">
+                                        <input id="payjs_url" type="text" class="form-control" value="{$settings['payjs_url']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">商户ID</label>
+                                    <div class="col">
+                                        <input id="payjs_mchid" type="text" class="form-control" value="{$settings['payjs_mchid']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">密钥</label>
+                                    <div class="col">
+                                        <input id="payjs_key" type="text" class="form-control" value="{$settings['payjs_key']}">
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="tab-pane" id="theadpay">
+                            <div class="card-body">
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">网关地址</label>
+                                    <div class="col">
+                                        <input id="theadpay_url" type="text" class="form-control" value="{$settings['theadpay_url']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">商户ID</label>
+                                    <div class="col">
+                                        <input id="theadpay_mchid" type="text" class="form-control" value="{$settings['theadpay_mchid']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">密钥</label>
+                                    <div class="col">
+                                        <input id="theadpay_key" type="text" class="form-control" value="{$settings['theadpay_key']}">
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="tab-pane" id="stripe">
+                            <div class="card-body">
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">银行卡支付</label>
+                                    <div class="col">
+                                        <select id="stripe_card" class="col form-select" value="{$settings['stripe_card']}">
+                                            <option value="0">停用</option>
+                                            <option value="1" {if $settings['stripe_card'] === true}selected{/if}>启用</option>
+                                        </select>
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">支付宝支付</label>
+                                    <div class="col">
+                                        <select id="stripe_alipay" class="col form-select" value="{$settings['stripe_alipay']}">
+                                            <option value="0">停用</option>
+                                            <option value="1" {if $settings['stripe_alipay'] === true}selected{/if}>启用</option>
+                                        </select>
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">微信支付</label>
+                                    <div class="col">
+                                        <select id="stripe_wechat" class="col form-select" value="{$settings['stripe_wechat']}">
+                                            <option value="0">停用</option>
+                                            <option value="1" {if $settings['stripe_wechat'] === true}selected{/if}>启用</option>
+                                        </select>
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">网关货币</label>
+                                    <div class="col">
+                                        <input id="stripe_currency" type="text" class="form-control" value="{$settings['stripe_currency']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">最低充值限额(整数)</label>
+                                    <div class="col">
+                                        <input id="stripe_min_recharge" type="text" class="form-control" value="{$settings['stripe_min_recharge']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">最高充值限额(整数)</label>
+                                    <div class="col">
+                                        <input id="stripe_max_recharge" type="text" class="form-control" value="{$settings['stripe_max_recharge']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">公钥</label>
+                                    <div class="col">
+                                        <input id="stripe_pk" type="text" class="form-control" value="{$settings['stripe_pk']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">私钥</label>
+                                    <div class="col">
+                                        <input id="stripe_sk" type="text" class="form-control" value="{$settings['stripe_sk']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">WebHook密钥</label>
+                                    <div class="col">
+                                        <input id="stripe_webhook_key" type="text" class="form-control" value="{$settings['stripe_webhook_key']}">
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="tab-pane" id="epay">
+                            <div class="card-body">
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">网关地址</label>
+                                    <div class="col">
+                                        <input id="epay_url" type="text" class="form-control" value="{$settings['epay_url']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">商户ID</label>
+                                    <div class="col">
+                                        <input id="epay_pid" type="text" class="form-control" value="{$settings['epay_pid']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">密钥</label>
+                                    <div class="col">
+                                        <input id="epay_key" type="text" class="form-control" value="{$settings['epay_key']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">支付宝</label>
+                                    <div class="col">
+                                        <select id="epay_alipay" class="col form-select" value="{$settings['epay_alipay']}">
+                                            <option value="0">停用</option>
+                                            <option value="1" {if $settings['epay_alipay'] === true}selected{/if}>启用</option>
+                                        </select>
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">微信支付</label>
+                                    <div class="col">
+                                        <select id="epay_wechat" class="col form-select" value="{$settings['epay_wechat']}">
+                                            <option value="0">停用</option>
+                                            <option value="1" {if $settings['epay_wechat'] === true}selected{/if}>启用</option>
+                                        </select>
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">QQ钱包</label>
+                                    <div class="col">
+                                        <select id="epay_qq" class="col form-select" value="{$settings['epay_qq']}">
+                                            <option value="0">停用</option>
+                                            <option value="1" {if $settings['epay_qq'] === true}selected{/if}>启用</option>
+                                        </select>
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">USDT</label>
+                                    <div class="col">
+                                        <select id="epay_usdt" class="col form-select" value="{$settings['epay_usdt']}">
+                                            <option value="0">停用</option>
+                                            <option value="1" {if $settings['epay_usdt'] === true}selected{/if}>启用</option>
+                                        </select>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+<script>
+    $("#save-setting").click(function() {
+        $.ajax({
+            url: '/admin/setting/billing',
+            type: 'POST',
+            dataType: "json",
+            data: {
+                {foreach $update_field as $key}
+                {$key}: $('#{$key}').val(),
+                {/foreach}
+                {foreach $payment_gateways as $key => $value}
+                {$key}: $("#{$key}_enable").is(":checked"),
+                {/foreach}
+            },
+            success: function(data) {
+                if (data.ret == 1) {
+                    $('#success-message').text(data.msg);
+                    $('#success-dialog').modal('show');
+                } else {
+                    $('#fail-message').text(data.msg);
+                    $('#fail-dialog').modal('show');
+                }
+            }
+        })
+    });
+</script>
+
+{include file='admin/tabler_footer.tpl'}

+ 158 - 0
resources/views/tabler/admin/setting/captcha.tpl

@@ -0,0 +1,158 @@
+{include file='admin/tabler_header.tpl'}
+
+<div class="page-wrapper">
+    <div class="container-xl">
+        <div class="page-header d-print-none text-white">
+            <div class="row align-items-center">
+                <div class="col">
+                    <h2 class="page-title">
+                        <span class="home-title">人机验证设置</span>
+                    </h2>
+                    <div class="page-pretitle my-3">
+                        <span class="home-subtitle">设置站点的人机验证系统</span>
+                    </div>
+                </div>
+                <div class="col-auto ms-auto d-print-none">
+                    <div class="btn-list">
+                        <a id="save-setting" href="#" class="btn btn-primary">
+                            <i class="icon ti ti-device-floppy"></i>
+                            保存
+                        </a>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <div class="page-body">
+        <div class="container-xl">
+            <div class="row row-deck row-cards">
+                <div class="col-md-12">
+                    <div class="card">
+                    <div class="card-header">
+                    <ul class="nav nav-tabs card-header-tabs" data-bs-toggle="tabs">
+                        <li class="nav-item">
+                            <a href="#captcha" class="nav-link active" data-bs-toggle="tab">验证设置</a>
+                        </li>
+                        <li class="nav-item">
+                            <a href="#turnstile" class="nav-link" data-bs-toggle="tab">Turnstile</a>
+                        </li>
+                        <li class="nav-item">
+                            <a href="#geetest" class="nav-link" data-bs-toggle="tab">Geetest</a>
+                        </li>
+                    </ul>
+                </div>
+                <div class="card-body">
+                    <div class="tab-content">
+                        <div class="tab-pane active show" id="captcha">
+                            <div class="card-body">
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">验证码提供商</label>
+                                    <div class="col">
+                                        <select id="captcha_provider" class="col form-select" value="{$settings['captcha_provider']}">
+                                            <option value="turnstile" {if $settings['captcha_provider'] == "turnstile"}selected{/if}>Turnstile</option>
+                                            <option value="geetest" {if $settings['captcha_provider'] == "geetest"}selected{/if}>Geetest</option>
+                                        </select>
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">注册验证码</label>
+                                    <div class="col">
+                                        <select id="enable_reg_captcha" class="col form-select" value="{$settings['enable_reg_captcha']}">
+                                            <option value="0" {if $settings['enable_reg_captcha'] == false}selected{/if}>关闭</option>
+                                            <option value="1" {if $settings['enable_reg_captcha'] == true}selected{/if}>开启</option>
+                                        </select>
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">登录验证码</label>
+                                    <div class="col">
+                                        <select id="enable_login_captcha" class="col form-select" value="{$settings['enable_login_captcha']}">
+                                            <option value="0" {if $settings['enable_login_captcha'] == false}selected{/if}>关闭</option>
+                                            <option value="1" {if $settings['enable_login_captcha'] == true}selected{/if}>开启</option>
+                                        </select>
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">签到验证码</label>
+                                    <div class="col">
+                                        <select id="enable_checkin_captcha" class="col form-select" value="{$settings['enable_checkin_captcha']}">
+                                            <option value="0" {if $settings['enable_checkin_captcha'] == false}selected{/if}>关闭</option>
+                                            <option value="1" {if $settings['enable_checkin_captcha'] == true}selected{/if}>开启</option>
+                                        </select>
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">重置密码验证码</label>
+                                    <div class="col">
+                                        <select id="enable_reset_password_captcha" class="col form-select" value="{$settings['enable_reset_password_captcha']}">
+                                            <option value="0" {if $settings['enable_reset_password_captcha'] == false}selected{/if}>关闭</option>
+                                            <option value="1" {if $settings['enable_reset_password_captcha'] == true}selected{/if}>开启</option>
+                                        </select>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="tab-pane" id="turnstile">
+                            <div class="card-body">
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">Turnstile Site Key</label>
+                                    <div class="col">
+                                        <input id="turnstile_sitekey" type="text" class="form-control" value="{$settings['turnstile_sitekey']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">Turnstile Secret</label>
+                                    <div class="col">
+                                        <input id="turnstile_secret" type="text" class="form-control" value="{$settings['turnstile_secret']}">
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="tab-pane" id="geetest">
+                            <div class="card-body">
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">Geetest ID</label>
+                                    <div class="col">
+                                        <input id="geetest_id" type="text" class="form-control" value="{$settings['geetest_id']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">Geetest Key</label>
+                                    <div class="col">
+                                        <input id="geetest_key" type="text" class="form-control" value="{$settings['geetest_key']}">
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+<script>
+    $("#save-setting").click(function() {
+        $.ajax({
+            url: '/admin/setting/captcha',
+            type: 'POST',
+            dataType: "json",
+            data: {
+                {foreach $update_field as $key}
+                {$key}: $('#{$key}').val(),
+                {/foreach}
+            },
+            success: function(data) {
+                if (data.ret == 1) {
+                    $('#success-message').text(data.msg);
+                    $('#success-dialog').modal('show');
+                } else {
+                    $('#fail-message').text(data.msg);
+                    $('#fail-dialog').modal('show');
+                }
+            }
+        })
+    });
+</script>
+
+{include file='admin/tabler_footer.tpl'}

+ 273 - 0
resources/views/tabler/admin/setting/email.tpl

@@ -0,0 +1,273 @@
+{include file='admin/tabler_header.tpl'}
+
+<div class="page-wrapper">
+    <div class="container-xl">
+        <div class="page-header d-print-none text-white">
+            <div class="row align-items-center">
+                <div class="col">
+                    <h2 class="page-title">
+                        <span class="home-title">邮件设置</span>
+                    </h2>
+                    <div class="page-pretitle my-3">
+                        <span class="home-subtitle">设置站点的邮件系统</span>
+                    </div>
+                </div>
+                <div class="col-auto ms-auto d-print-none">
+                    <div class="btn-list">
+                        <a id="save-setting" href="#" class="btn btn-primary">
+                            <i class="icon ti ti-device-floppy"></i>
+                            保存
+                        </a>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <div class="page-body">
+        <div class="container-xl">
+            <div class="row row-deck row-cards">
+                <div class="col-md-12">
+                    <div class="card">
+                    <div class="card-header">
+                    <ul class="nav nav-tabs card-header-tabs" data-bs-toggle="tabs">
+                        <li class="nav-item">
+                            <a href="#email" class="nav-link active" data-bs-toggle="tab">邮件设置</a>
+                        </li>
+                        <li class="nav-item">
+                            <a href="#smtp" class="nav-link" data-bs-toggle="tab">SMTP</a>
+                        </li>
+                        <li class="nav-item">
+                            <a href="#sendgrid" class="nav-link" data-bs-toggle="tab">Sendgrid</a>
+                        </li>
+                        <li class="nav-item">
+                            <a href="#mailgun" class="nav-link" data-bs-toggle="tab">Mailgun</a>
+                        </li>
+                        <li class="nav-item">
+                            <a href="#ses" class="nav-link" data-bs-toggle="tab">AWS SES</a>
+                        </li>
+                    </ul>
+                </div>
+                <div class="card-body">
+                    <div class="tab-content">
+                        <div class="tab-pane active show" id="email">
+                            <div class="card-body">
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">邮件服务提供商</label>
+                                    <div class="col">
+                                        <select id="mail_driver" class="col form-select" value="{$settings['mail_driver']}">
+                                            <option value="none" {if $settings['mail_driver'] == "none"}selected{/if}>none</option>
+                                            <option value="smtp" {if $settings['mail_driver'] == "smtp"}selected{/if}>smtp</option>
+                                            <option value="sendgrid" {if $settings['mail_driver'] == "sendgrid"}selected{/if}>sendgrid</option>
+                                            <option value="mailgun" {if $settings['mail_driver'] == "mailgun"}selected{/if}>mailgun</option>
+                                            <option value="ses" {if $settings['mail_driver'] == "ses"}selected{/if}>ses</option>
+                                        </select>
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">测试邮件接收地址</label>
+                                    <input type="text" class="form-control" id="recipient" value="">
+                                    <div class="row my-3">
+                                        <div class="col">
+                                            <button id="test-email" class="btn btn-primary">发送测试邮件</button>
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="tab-pane" id="smtp">
+                            <div class="card-body">
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">SMTP 主机地址</label>
+                                    <div class="col">
+                                        <input id="smtp_host" type="text" class="form-control" value="{$settings['smtp_host']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">SMTP 用户名</label>
+                                    <div class="col">
+                                        <input id="smtp_username" type="text" class="form-control" value="{$settings['smtp_username']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">SMTP 用户名</label>
+                                    <div class="col">
+                                        <input id="smtp_username" type="text" class="form-control" value="{$settings['smtp_username']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">SMTP 密码</label>
+                                    <div class="col">
+                                        <input id="smtp_password" type="text" class="form-control" value="{$settings['smtp_password']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">SMTP 用户名</label>
+                                    <div class="col">
+                                        <input id="smtp_username" type="text" class="form-control" value="{$settings['smtp_username']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">SMTP 端口</label>
+                                    <div class="col">
+                                        <select id="smtp_port" class="col form-select" value="{$settings['smtp_port']}">
+                                            <option value="465" {if $settings['smtp_port'] == "465"}selected{/if}>465</option>
+                                            <option value="587" {if $settings['smtp_port'] == "587"}selected{/if}>587</option>
+                                            <option value="443" {if $settings['smtp_port'] == "443"}selected{/if}>2525</option>
+                                            <option value="80" {if $settings['smtp_port'] == "80"}selected{/if}>2525</option>
+                                            <option value="25" {if $settings['smtp_port'] == "25"}selected{/if}>25</option>
+                                        </select>
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">SMTP 发件人名称</label>
+                                    <div class="col">
+                                        <input id="smtp_name" type="text" class="form-control" value="{$settings['smtp_name']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">SMTP 发信地址</label>
+                                    <div class="col">
+                                        <input id="smtp_sender" type="text" class="form-control" value="{$settings['smtp_sender']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">是否使用 TLS/SSL</label>
+                                    <div class="col">
+                                    <select id="smtp_ssl" class="col form-select" value="{$settings['smtp_ssl']}">
+                                        <option value="1" {if $settings['smtp_ssl'] == true}selected{/if}>开启</option>
+                                        <option value="0" {if $settings['smtp_ssl'] == false}selected{/if}>关闭</option>
+                                    </select>
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">客户邮件副本接收邮箱</label>
+                                    <div class="col">
+                                        <input id="smtp_bbc" type="text" class="form-control" value="{$settings['smtp_bbc']}">
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="tab-pane" id="sendgrid">
+                            <div class="card-body">
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">Sendgrid 密钥</label>
+                                    <div class="col">
+                                        <input id="sendgrid_key" type="text" class="form-control" value="{$settings['sendgrid_key']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">Sendgrid 发信地址</label>
+                                    <div class="col">
+                                        <input id="sendgrid_sender" type="text" class="form-control" value="{$settings['sendgrid_sender']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">Sendgrid 发件人名称</label>
+                                    <div class="col">
+                                        <input id="sendgrid_name" type="text" class="form-control" value="{$settings['sendgrid_name']}">
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="tab-pane" id="mailgun">
+                            <div class="card-body">
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">Mailgun 密钥</label>
+                                    <div class="col">
+                                        <input id="mailgun_key" type="text" class="form-control" value="{$settings['mailgun_key']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">Mailgun 域名</label>
+                                    <div class="col">
+                                        <input id="mailgun_domain" type="text" class="form-control" value="{$settings['mailgun_domain']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">Mailgun 发信地址</label>
+                                    <div class="col">
+                                        <input id="mailgun_sender" type="text" class="form-control" value="{$settings['mailgun_sender']}">
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="tab-pane" id="ses">
+                            <div class="card-body">
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">AWS 密钥 ID</label>
+                                    <div class="col">
+                                        <input id="aws_access_key_id" type="text" class="form-control" value="{$settings['aws_access_key_id']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">AWS 密钥</label>
+                                    <div class="col">
+                                        <input id="aws_secret_access_key" type="text" class="form-control" value="{$settings['aws_secret_access_key']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">AWS 区域</label>
+                                    <div class="col">
+                                        <input id="aws_region" type="text" class="form-control" value="{$settings['aws_region']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">AWS SES 发信地址</label>
+                                    <div class="col">
+                                        <input id="aws_ses_sender" type="text" class="form-control" value="{$settings['aws_ses_sender']}">
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+<script>
+    $("#save-setting").click(function() {
+        $.ajax({
+            url: '/admin/setting/captcha',
+            type: 'POST',
+            dataType: "json",
+            data: {
+                {foreach $update_field as $key}
+                {$key}: $('#{$key}').val(),
+                {/foreach}
+            },
+            success: function(data) {
+                if (data.ret == 1) {
+                    $('#success-message').text(data.msg);
+                    $('#success-dialog').modal('show');
+                } else {
+                    $('#fail-message').text(data.msg);
+                    $('#fail-dialog').modal('show');
+                }
+            }
+        })
+    });
+
+    $("#test-email").click(function() {
+        $.ajax({
+            url: '/admin/setting/test_email',
+            type: 'POST',
+            dataType: "json",
+            data: {
+                recipient: $('#recipient').val(),
+            },
+            success: function(data) {
+                if (data.ret == 1) {
+                    $('#success-message').text(data.msg);
+                    $('#success-dialog').modal('show');
+                } else {
+                    $('#fail-message').text(data.msg);
+                    $('#fail-dialog').modal('show');
+                }
+            }
+        })
+    });
+</script>
+
+{include file='admin/tabler_footer.tpl'}

+ 250 - 0
resources/views/tabler/admin/setting/im.tpl

@@ -0,0 +1,250 @@
+{include file='admin/tabler_header.tpl'}
+
+<div class="page-wrapper">
+    <div class="container-xl">
+        <div class="page-header d-print-none text-white">
+            <div class="row align-items-center">
+                <div class="col">
+                    <h2 class="page-title">
+                        <span class="home-title">IM 设置</span>
+                    </h2>
+                    <div class="page-pretitle my-3">
+                        <span class="home-subtitle">管理站点的 IM 集成设置</span>
+                    </div>
+                </div>
+                <div class="col-auto ms-auto d-print-none">
+                    <div class="btn-list">
+                        <a id="save-setting" href="#" class="btn btn-primary">
+                            <i class="icon ti ti-device-floppy"></i>
+                            保存
+                        </a>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <div class="page-body">
+        <div class="container-xl">
+            <div class="row row-deck row-cards">
+                <div class="col-md-12">
+                    <div class="card">
+                    <div class="card-header">
+                    <ul class="nav nav-tabs card-header-tabs" data-bs-toggle="tabs">
+                        <li class="nav-item">
+                            <a href="#telegram_notification" class="nav-link active" data-bs-toggle="tab">Telegram 通知设定</a>
+                        </li>
+                        <li class="nav-item">
+                            <a href="#telegram_bot" class="nav-link" data-bs-toggle="tab">Telegram Bot 设定</a>
+                        </li>
+                    </ul>
+                </div>
+                <div class="card-body">
+                    <div class="tab-content">
+                        <div class="tab-pane active show" id="telegram_notification">
+                            <div class="card-body">
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">添加节点通知</label>
+                                    <div class="col">
+                                        <select id="telegram_add_node" class="col form-select" value="{$settings['telegram_add_node']}">
+                                            <option value="0" {if $settings['telegram_add_node'] == false}selected{/if}>关闭</option>
+                                            <option value="1" {if $settings['telegram_add_node'] == true}selected{/if}>开启</option>
+                                        </select>
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">添加节点通知文本</label>
+                                    <div class="col">
+                                        <input id="telegram_add_node_text" type="text" class="form-control" value="{$settings['telegram_add_node_text']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">修改节点通知</label>
+                                    <div class="col">
+                                        <select id="telegram_update_node" class="col form-select" value="{$settings['telegram_update_node']}">
+                                            <option value="0" {if $settings['telegram_update_node'] == false}selected{/if}>关闭</option>
+                                            <option value="1" {if $settings['telegram_update_node'] == true}selected{/if}>开启</option>
+                                        </select>
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">修改节点通知文本</label>
+                                    <div class="col">
+                                        <input id="telegram_update_node_text" type="text" class="form-control" value="{$settings['telegram_update_node_text']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">删除节点通知</label>
+                                    <div class="col">
+                                        <select id="telegram_delete_node" class="col form-select" value="{$settings['telegram_delete_node']}">
+                                            <option value="0" {if $settings['telegram_delete_node'] == false}selected{/if}>关闭</option>
+                                            <option value="1" {if $settings['telegram_delete_node'] == true}selected{/if}>开启</option>
+                                        </select>
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">删除节点通知文本</label>
+                                    <div class="col">
+                                        <input id="telegram_delete_node_text" type="text" class="form-control" value="{$settings['telegram_delete_node_text']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">节点被墙通知</label>
+                                    <div class="col">
+                                        <select id="telegram_node_gfwed" class="col form-select" value="{$settings['telegram_node_gfwed']}">
+                                            <option value="0" {if $settings['telegram_node_gfwed'] == false}selected{/if}>关闭</option>
+                                            <option value="1" {if $settings['telegram_node_gfwed'] == true}selected{/if}>开启</option>
+                                        </select>
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">节点被墙通知文本</label>
+                                    <div class="col">
+                                        <input id="telegram_node_gfwed_text" type="text" class="form-control" value="{$settings['telegram_node_gfwed_text']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">节点被墙恢复通知</label>
+                                    <div class="col">
+                                        <select id="telegram_node_ungfwed" class="col form-select" value="{$settings['telegram_node_ungfwed']}">
+                                            <option value="0" {if $settings['telegram_node_ungfwed'] == false}selected{/if}>关闭</option>
+                                            <option value="1" {if $settings['telegram_node_ungfwed'] == true}selected{/if}>开启</option>
+                                        </select>
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">节点被墙恢复通知文本</label>
+                                    <div class="col">
+                                        <input id="telegram_node_ungfwed_text" type="text" class="form-control" value="{$settings['telegram_node_ungfwed_text']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">节点离线通知</label>
+                                    <div class="col">
+                                        <select id="telegram_node_offline" class="col form-select" value="{$settings['telegram_node_offline']}">
+                                            <option value="0" {if $settings['telegram_node_offline'] == false}selected{/if}>关闭</option>
+                                            <option value="1" {if $settings['telegram_node_offline'] == true}selected{/if}>开启</option>
+                                        </select>
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">节点离线通知文本</label>
+                                    <div class="col">
+                                        <input id="telegram_node_offline_text" type="text" class="form-control" value="{$settings['telegram_node_offline_text']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">节点上线通知</label>
+                                    <div class="col">
+                                        <select id="telegram_node_online" class="col form-select" value="{$settings['telegram_node_online']}">
+                                            <option value="0" {if $settings['telegram_node_online'] == false}selected{/if}>关闭</option>
+                                            <option value="1" {if $settings['telegram_node_online'] == true}selected{/if}>开启</option>
+                                        </select>
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">节点上线通知文本</label>
+                                    <div class="col">
+                                        <input id="telegram_node_online_text" type="text" class="form-control" value="{$settings['telegram_node_online_text']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">每日任务通知</label>
+                                    <div class="col">
+                                        <select id="telegram_daily_job" class="col form-select" value="{$settings['telegram_daily_job']}">
+                                            <option value="0" {if $settings['telegram_daily_job'] == false}selected{/if}>关闭</option>
+                                            <option value="1" {if $settings['telegram_daily_job'] == true}selected{/if}>开启</option>
+                                        </select>
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">每日任务通知文本</label>
+                                    <div class="col">
+                                        <input id="telegram_daily_job_text" type="text" class="form-control" value="{$settings['telegram_daily_job_text']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">系统运行状况通知</label>
+                                    <div class="col">
+                                        <select id="telegram_diary" class="col form-select" value="{$settings['telegram_diary']}">
+                                            <option value="0" {if $settings['telegram_diary'] == false}selected{/if}>关闭</option>
+                                            <option value="1" {if $settings['telegram_diary'] == true}selected{/if}>开启</option>
+                                        </select>
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">系统运行状况通知文本</label>
+                                    <div class="col">
+                                        <input id="telegram_diary_text" type="text" class="form-control" value="{$settings['telegram_diary_text']}">
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="tab-pane" id="telegram_bot">
+                            <div class="card-body">
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">解绑 Telegram 账户后自动踢出群组</label>
+                                    <div class="col">
+                                        <select id="telegram_unbind_kick_member" class="col form-select" value="{$settings['telegram_unbind_kick_member']}">
+                                            <option value="0" {if $settings['telegram_unbind_kick_member'] == false}selected{/if}>关闭</option>
+                                            <option value="1" {if $settings['telegram_unbind_kick_member'] == true}selected{/if}>开启</option>
+                                        </select>
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">仅允许已绑定 Telegram 账户的用户加入群组</label>
+                                    <div class="col">
+                                        <select id="telegram_group_bound_user" class="col form-select" value="{$settings['telegram_group_bound_user']}">
+                                            <option value="0" {if $settings['telegram_group_bound_user'] == false}selected{/if}>关闭</option>
+                                            <option value="1" {if $settings['telegram_group_bound_user'] == true}selected{/if}>开启</option>
+                                        </select>
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">启用 Telegram 机器人显示用户群组链接</label>
+                                    <div class="col">
+                                        <select id="telegram_show_group_link" class="col form-select" value="{$settings['telegram_show_group_link']}">
+                                            <option value="0" {if $settings['telegram_show_group_link'] == false}selected{/if}>关闭</option>
+                                            <option value="1" {if $settings['telegram_show_group_link'] == true}selected{/if}>开启</option>
+                                        </select>
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">用户群组链接</label>
+                                    <div class="col">
+                                        <input id="telegram_group_link" type="text" class="form-control" value="{$settings['telegram_group_link']}">
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+<script>
+    $("#save-setting").click(function() {
+        $.ajax({
+            url: '/admin/setting/im',
+            type: 'POST',
+            dataType: "json",
+            data: {
+                {foreach $update_field as $key}
+                {$key}: $('#{$key}').val(),
+                {/foreach}
+            },
+            success: function(data) {
+                if (data.ret == 1) {
+                    $('#success-message').text(data.msg);
+                    $('#success-dialog').modal('show');
+                } else {
+                    $('#fail-message').text(data.msg);
+                    $('#fail-dialog').modal('show');
+                }
+            }
+        })
+    });
+</script>
+
+{include file='admin/tabler_footer.tpl'}

+ 158 - 0
resources/views/tabler/admin/setting/ref.tpl

@@ -0,0 +1,158 @@
+{include file='admin/tabler_header.tpl'}
+
+<div class="page-wrapper">
+    <div class="container-xl">
+        <div class="page-header d-print-none text-white">
+            <div class="row align-items-center">
+                <div class="col">
+                    <h2 class="page-title">
+                        <span class="home-title">邀请设置</span>
+                    </h2>
+                    <div class="page-pretitle my-3">
+                        <span class="home-subtitle">管理站点的邀请设置</span>
+                    </div>
+                </div>
+                <div class="col-auto ms-auto d-print-none">
+                    <div class="btn-list">
+                        <a id="save-setting" href="#" class="btn btn-primary">
+                            <i class="icon ti ti-device-floppy"></i>
+                            保存
+                        </a>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <div class="page-body">
+        <div class="container-xl">
+            <div class="row row-deck row-cards">
+                <div class="col-md-12">
+                    <div class="card">
+                    <div class="card-header">
+                    <ul class="nav nav-tabs card-header-tabs" data-bs-toggle="tabs">
+                        <li class="nav-item">
+                            <a href="#invite" class="nav-link active" data-bs-toggle="tab">邀请设置</a>
+                        </li>
+                        <li class="nav-item">
+                            <a href="#rebate" class="nav-link" data-bs-toggle="tab">返利</a>
+                        </li>
+                    </ul>
+                </div>
+                <div class="card-body">
+                    <div class="tab-content">
+                        <div class="tab-pane active show" id="invite">
+                            <div class="card-body">
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">使用邀请链接注册所能获得的余额奖励(元)</label>
+                                    <div class="col">
+                                        <input id="invitation_to_register_balance_reward" type="text" class="form-control" value="{$settings['invitation_to_register_balance_reward']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">使用邀请链接注册所能获得的流量奖励(GB)</label>
+                                    <div class="col">
+                                        <input id="invitation_to_register_traffic_reward" type="text" class="form-control" value="{$settings['invitation_to_register_traffic_reward']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">邀请码价格,设为小于 0 时不开放购买</label>
+                                    <div class="col">
+                                        <input id="invite_price" type="text" class="form-control" value="{$settings['invite_price']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">定制邀请码价格,设为小于 0 时不开放购买</label>
+                                    <div class="col">
+                                        <input id="custom_invite_price" type="text" class="form-control" value="{$settings['custom_invite_price']}">
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="tab-pane" id="rebate">
+                            <div class="card-body">
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">邀请模式</label>
+                                    <div class="col">
+                                        <select id="invitation_mode" class="col form-select" value="{$settings['invitation_mode']}">
+                                            <option value="registration_only" {if $settings['invitation_mode'] == 'registration_only'}selected{/if}>
+                                            不返利</option>
+                                            <option value="after_recharge" {if $settings['invitation_mode'] == 'after_recharge'}selected{/if}>
+                                            被邀请用户充值时返利</option>
+                                            <option value="after_purchase" {if $settings['invitation_mode'] == 'after_purchase'}selected{/if}>
+                                            被邀请用户购买时返利</option>
+                                        </select>
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">邀请模式</label>
+                                    <div class="col">
+                                        <select id="invite_rebate_mode" class="col form-select" value="{$settings['invite_rebate_mode']}">
+                                            <option value="continued" {if $settings['invite_rebate_mode'] == 'continued'}selected{/if}>
+                                            持续返利</option>
+                                            <option value="limit_frequency" {if $settings['invite_rebate_mode'] == 'limit_frequency'}selected{/if}>
+                                            限制邀请人能从被邀请人身上获得的返利次数</option>
+                                            <option value="limit_amount" {if $settings['invite_rebate_mode'] == 'limit_amount'}selected{/if}>
+                                            限制邀请人能从被邀请人身上获得的返利金额</option>
+                                            <option value="limit_time_range" {if $settings['invite_rebate_mode'] == 'limit_time_range'}selected{/if}>
+                                            限制邀请人能从被邀请人身上获得返利的时间范围</option>
+                                        </select>
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">返利比例,10% 填 0.1</label>
+                                    <div class="col">
+                                        <input id="rebate_ratio" type="text" class="form-control" value="{$settings['rebate_ratio']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">返利时间范围(天)</label>
+                                    <div class="col">
+                                        <input id="rebate_time_range_limit" type="text" class="form-control" value="{$settings['rebate_time_range_limit']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">返利次数</label>
+                                    <div class="col">
+                                        <input id="rebate_frequency_limit" type="text" class="form-control" value="{$settings['rebate_frequency_limit']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">返利金额限制</label>
+                                    <div class="col">
+                                        <input id="rebate_amount_limit" type="text" class="form-control" value="{$settings['rebate_amount_limit']}">
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+<script>
+    $("#save-setting").click(function() {
+        $.ajax({
+            url: '/admin/setting/ref',
+            type: 'POST',
+            dataType: "json",
+            data: {
+                {foreach $update_field as $key}
+                {$key}: $('#{$key}').val(),
+                {/foreach}
+            },
+            success: function(data) {
+                if (data.ret == 1) {
+                    $('#success-message').text(data.msg);
+                    $('#success-dialog').modal('show');
+                } else {
+                    $('#fail-message').text(data.msg);
+                    $('#fail-dialog').modal('show');
+                }
+            }
+        })
+    });
+</script>
+
+{include file='admin/tabler_footer.tpl'}

+ 234 - 0
resources/views/tabler/admin/setting/reg.tpl

@@ -0,0 +1,234 @@
+{include file='admin/tabler_header.tpl'}
+
+<div class="page-wrapper">
+    <div class="container-xl">
+        <div class="page-header d-print-none text-white">
+            <div class="row align-items-center">
+                <div class="col">
+                    <h2 class="page-title">
+                        <span class="home-title">注册设置</span>
+                    </h2>
+                    <div class="page-pretitle my-3">
+                        <span class="home-subtitle">管理站点的注册设置</span>
+                    </div>
+                </div>
+                <div class="col-auto ms-auto d-print-none">
+                    <div class="btn-list">
+                        <a id="save-setting" href="#" class="btn btn-primary">
+                            <i class="icon ti ti-device-floppy"></i>
+                            保存
+                        </a>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <div class="page-body">
+        <div class="container-xl">
+            <div class="row row-deck row-cards">
+                <div class="col-md-12">
+                    <div class="card">
+                    <div class="card-header">
+                    <ul class="nav nav-tabs card-header-tabs" data-bs-toggle="tabs">
+                        <li class="nav-item">
+                            <a href="#reg" class="nav-link active" data-bs-toggle="tab">注册设置</a>
+                        </li>
+                        <li class="nav-item">
+                            <a href="#default_value" class="nav-link" data-bs-toggle="tab">默认值</a>
+                        </li>
+                        <li class="nav-item">
+                            <a href="#limit" class="nav-link" data-bs-toggle="tab">账户限制</a>
+                        </li>
+                    </ul>
+                </div>
+                <div class="card-body">
+                    <div class="tab-content">
+                        <div class="tab-pane active show" id="reg">
+                            <div class="card-body">
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">注册模式</label>
+                                    <div class="col">
+                                        <select id="reg_mode" class="col form-select" value="{$settings['reg_mode']}">
+                                            <option value="close" {if $settings['reg_mode'] == 'close'}selected{/if}>关闭注册</option>
+                                            <option value="open" {if $settings['reg_mode'] == 'open'}selected{/if}>公开注册</option>
+                                            <option value="invite" {if $settings['reg_mode'] == 'invite'}selected{/if}>仅限用户邀请注册</option>
+                                        </select>
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">邮箱验证</label>
+                                    <div class="col">
+                                        <select id="reg_email_verify" class="col form-select" value="{$settings['reg_email_verify']}">
+                                            <option value="0" {if $settings['reg_email_verify'] == false}selected{/if}>关闭</option>
+                                            <option value="1" {if $settings['reg_email_verify'] == true}selected{/if}>开启</option>
+                                        </select>
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">邮箱验证码有效期(秒)</label>
+                                    <div class="col">
+                                        <input id="email_verify_ttl" type="text" class="form-control" value="{$settings['email_verify_ttl']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">验证码有效期内单个 IP 可请求次数</label>
+                                    <div class="col">
+                                        <input id="email_verify_ip_limit" type="text" class="form-control" value="{$settings['email_verify_ip_limit']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">验证码有效期内单个邮箱地址可请求次数</label>
+                                    <div class="col">
+                                        <input id="email_verify_email_limit" type="text" class="form-control" value="{$settings['email_verify_email_limit']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">默认接收每日用量邮件推送</label>
+                                    <div class="col">
+                                        <select id="sign_up_for_daily_report" class="col form-select" value="{$settings['sign_up_for_daily_report']}">
+                                            <option value="0" {if $settings['sign_up_for_daily_report'] == false}selected{/if}>关闭</option>
+                                            <option value="1" {if $settings['sign_up_for_daily_report'] == true}selected{/if}>开启</option>
+                                        </select>
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">是否要求用户输入IM联系方式</label>
+                                    <div class="col">
+                                        <select id="enable_reg_im" class="col form-select" value="{$settings['enable_reg_im']}">
+                                            <option value="0" {if $settings['enable_reg_im'] == false}selected{/if}>关闭</option>
+                                            <option value="1" {if $settings['enable_reg_im'] == true}selected{/if}>开启</option>
+                                        </select>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="tab-pane" id="default_value">
+                            <div class="card-body">
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">注册时随机分配到的分组,多个分组请用英文半角逗号分隔</label>
+                                    <div class="col">
+                                        <input id="random_group" type="text" class="form-control" value="{$settings['random_group']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">用户端口池最小值,设为 0 时用户不会被分配端口</label>
+                                    <div class="col">
+                                        <input id="min_port" type="text" class="form-control" value="{$settings['min_port']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">用户端口池最大值,设为 0 时用户不会被分配端口</label>
+                                    <div class="col">
+                                        <input id="max_port" type="text" class="form-control" value="{$settings['max_port']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">注册时赠送的流量(GB)</label>
+                                    <div class="col">
+                                        <input id="sign_up_for_free_traffic" type="text" class="form-control" value="{$settings['sign_up_for_free_traffic']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">免费用戶的流量重置日,设为 0 时不重置</label>
+                                    <div class="col">
+                                        <input id="free_user_reset_day" type="text" class="form-control" value="{$settings['free_user_reset_day']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">需要重置的免费流量,设为 0 时不重置</label>
+                                    <div class="col">
+                                        <input id="free_user_reset_bandwidth" type="text" class="form-control" value="{$settings['free_user_reset_bandwidth']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">注册时赠送的时长(天)</label>
+                                    <div class="col">
+                                        <input id="sign_up_for_free_time" type="text" class="form-control" value="{$settings['sign_up_for_free_time']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">注册时设定的等级</label>
+                                    <div class="col">
+                                        <input id="sign_up_for_class" type="text" class="form-control" value="{$settings['sign_up_for_class']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">注册时设定的等级过期时间(天)</label>
+                                    <div class="col">
+                                        <input id="sign_up_for_class_time" type="text" class="form-control" value="{$settings['sign_up_for_class_time']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">默认加密</label>
+                                    <div class="col">
+                                        <input id="sign_up_for_method" type="text" class="form-control" value="{$settings['sign_up_for_method']}">
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="tab-pane" id="limit">
+                            <div class="card-body">
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">邀请链接使用次数限制</label>
+                                    <div class="col">
+                                        <input id="sign_up_for_invitation_codes" type="text" class="form-control" value="{$settings['sign_up_for_invitation_codes']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">连接设备限制</label>
+                                    <div class="col">
+                                        <input id="connection_device_limit" type="text" class="form-control" value="{$settings['connection_device_limit']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">使用速率限制</label>
+                                    <div class="col">
+                                        <input id="connection_rate_limit" type="text" class="form-control" value="{$settings['connection_rate_limit']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">禁止访问的 IP 列表</label>
+                                    <div class="col">
+                                        <input id="reg_forbidden_ip" type="text" class="form-control" value="{$settings['reg_forbidden_ip']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">禁止访问的端口列表</label>
+                                    <div class="col">
+                                        <input id="reg_forbidden_port" type="text" class="form-control" value="{$settings['reg_forbidden_port']}">
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+<script>
+    $("#save-setting").click(function() {
+        $.ajax({
+            url: '/admin/setting/reg',
+            type: 'POST',
+            dataType: "json",
+            data: {
+                {foreach $update_field as $key}
+                {$key}: $('#{$key}').val(),
+                {/foreach}
+            },
+            success: function(data) {
+                if (data.ret == 1) {
+                    $('#success-message').text(data.msg);
+                    $('#success-dialog').modal('show');
+                } else {
+                    $('#fail-message').text(data.msg);
+                    $('#fail-dialog').modal('show');
+                }
+            }
+        })
+    });
+</script>
+
+{include file='admin/tabler_footer.tpl'}

+ 145 - 0
resources/views/tabler/admin/setting/support.tpl

@@ -0,0 +1,145 @@
+{include file='admin/tabler_header.tpl'}
+
+<div class="page-wrapper">
+    <div class="container-xl">
+        <div class="page-header d-print-none text-white">
+            <div class="row align-items-center">
+                <div class="col">
+                    <h2 class="page-title">
+                        <span class="home-title">客服设置</span>
+                    </h2>
+                    <div class="page-pretitle my-3">
+                        <span class="home-subtitle">设置站点的客服系统</span>
+                    </div>
+                </div>
+                <div class="col-auto ms-auto d-print-none">
+                    <div class="btn-list">
+                        <a id="save-setting" href="#" class="btn btn-primary">
+                            <i class="icon ti ti-device-floppy"></i>
+                            保存
+                        </a>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <div class="page-body">
+        <div class="container-xl">
+            <div class="row row-deck row-cards">
+                <div class="col-md-12">
+                    <div class="card">
+                    <div class="card-header">
+                    <ul class="nav nav-tabs card-header-tabs" data-bs-toggle="tabs">
+                        <li class="nav-item">
+                            <a href="#support" class="nav-link active" data-bs-toggle="tab">网页客服系统</a>
+                        </li>
+                        <li class="nav-item">
+                            <a href="#admin_contact" class="nav-link" data-bs-toggle="tab">管理员联络方式</a>
+                        </li>
+                    </ul>
+                </div>
+                <div class="card-body">
+                    <div class="tab-content">
+                        <div class="tab-pane active show" id="support">
+                            <div class="card-body">
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">客服系统提供商</label>
+                                    <div class="col">
+                                        <select id="live_chat" class="col form-select" value="{$settings['live_chat']}">
+                                            <option value="none" {if $settings['live_chat'] == "none"}selected{/if}>无</option>
+                                            <option value="tawk" {if $settings['live_chat'] == "tawk"}selected{/if}>Tawk</option>
+                                            <option value="crisp" {if $settings['live_chat'] == "crisp"}selected{/if}>Crisp</option>
+                                            <option value="livechat" {if $settings['live_chat'] == "livechat"}selected{/if}>LiveChat</option>
+                                            <option value="mylivechat" {if $settings['live_chat'] == "mylivechat"}selected{/if}>MyLiveChat</option>
+                                        </select>
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">Tawk ID</label>
+                                    <div class="col">
+                                        <input id="tawk_id" type="text" class="form-control" value="{$settings['tawk_id']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">Crisp ID</label>
+                                    <div class="col">
+                                        <input id="crisp_id" type="text" class="form-control" value="{$settings['crisp_id']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">LiveChat ID</label>
+                                    <div class="col">
+                                        <input id="livechat_id" type="text" class="form-control" value="{$settings['livechat_id']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">MyLiveChat ID</label>
+                                    <div class="col">
+                                        <input id="mylivechat_id" type="text" class="form-control" value="{$settings['mylivechat_id']}">
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="tab-pane" id="admin_contact">
+                            <div class="card-body">
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">是否显示管理员联系方式</label>
+                                    <div class="col">
+                                        <select id="live_chat" class="col form-select" value="{$settings['enable_admin_contact']}">
+                                            <option value="0" {if $settings['enable_admin_contact'] == false}selected{/if}>关闭</option>
+                                            <option value="1" {if $settings['enable_admin_contact'] == true}selected{/if}>开启</option>
+                                        </select>
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">联系方式一</label>
+                                    <div class="col">
+                                        <input id="admin_contact1" type="text" class="form-control" value="{$settings['admin_contact1']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">联系方式二</label>
+                                    <div class="col">
+                                        <input id="admin_contact2" type="text" class="form-control" value="{$settings['admin_contact2']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">联系方式三</label>
+                                    <div class="col">
+                                        <input id="admin_contact3" type="text" class="form-control" value="{$settings['admin_contact3']}">
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+<script>
+    $("#save-setting").click(function() {
+        $.ajax({
+            url: '/admin/setting/support',
+            type: 'POST',
+            dataType: "json",
+            data: {
+                {foreach $update_field as $key}
+                {$key}: $('#{$key}').val(),
+                {/foreach}
+            },
+            success: function(data) {
+                if (data.ret == 1) {
+                    $('#success-message').text(data.msg);
+                    $('#success-dialog').modal('show');
+                } else {
+                    $('#fail-message').text(data.msg);
+                    $('#fail-dialog').modal('show');
+                }
+            }
+        })
+    });
+</script>
+
+{include file='admin/tabler_footer.tpl'}

+ 31 - 6
resources/views/tabler/admin/tabler_header.tpl

@@ -11,12 +11,12 @@
     <!-- CSS files -->
     <link href="//cdn.jsdelivr.net/npm/@tabler/core@latest/dist/css/tabler.min.css" rel="stylesheet" />
     <link href="//cdn.jsdelivr.net/npm/@tabler/icons@latest/iconfont/tabler-icons.min.css" rel="stylesheet" />
-    <link href="//cdn.datatables.net/v/bs5/dt-1.13.1/datatables.min.css" rel="stylesheet" />
+    <link href="//cdn.datatables.net/v/bs5/dt-1.13.2/datatables.min.css" rel="stylesheet" />
     <!-- JS files -->
     <script src="//cdn.jsdelivr.net/npm/[email protected]/qrcode.min.js"></script>
     <script src="//cdn.jsdelivr.net/npm/[email protected]/dist/clipboard.min.js"></script>
     <script src="//cdn.jsdelivr.net/npm/jquery/dist/jquery.min.js"></script>
-    <script src="//cdn.datatables.net/v/bs5/dt-1.13.1/datatables.min.js"></script>
+    <script src="//cdn.datatables.net/v/bs5/dt-1.13.2/datatables.min.js"></script>
     <style>
         .home-subtitle {
             font-size: 14px;
@@ -89,10 +89,35 @@
                                 <div class="dropdown-menu">
                                     <div class="dropdown-menu-columns">
                                         <div class="dropdown-menu-column">
-                                            <a class="dropdown-item" href="/admin/setting">
-                                                <i class="ti ti-tool"></i>&nbsp;
-                                                设置
-                                            </a>
+                                            <div class="dropend">
+                                                <a class="dropdown-item dropdown-toggle" href="#" data-bs-toggle="dropdown" data-bs-auto-close="outside" role="button" aria-expanded="false" >
+                                                    <i class="ti ti-settings"></i>&nbsp;
+                                                    设置
+                                                </a>
+                                                <div class="dropdown-menu">
+                                                    <a href="/admin/setting/billing" class="dropdown-item">
+                                                      财务
+                                                    </a>
+                                                    <a href="/admin/setting/email" class="dropdown-item">
+                                                      邮件
+                                                    </a>
+                                                    <a href="/admin/setting/support" class="dropdown-item">
+                                                      客服
+                                                    </a>
+                                                    <a href="/admin/setting/captcha" class="dropdown-item">
+                                                      验证
+                                                    </a>
+                                                    <a href="/admin/setting/reg" class="dropdown-item">
+                                                      注册
+                                                    </a>
+                                                    <a href="/admin/setting/ref" class="dropdown-item">
+                                                      邀请
+                                                    </a>
+                                                    <a href="/admin/setting/im" class="dropdown-item">
+                                                      IM
+                                                    </a>
+                                                </div>
+                                            </div>
                                             <a class="dropdown-item" href="/admin/user">
                                                 <i class="ti ti-users"></i>&nbsp;
                                                 用户

+ 11 - 18
resources/views/tabler/user/server.tpl

@@ -34,24 +34,6 @@
                             <div class="tab-content">
                                 <div class="row row-cards">
                                     {foreach $servers as $server}
-                                        {if $user->class < $server["class"]}
-                                        <div class="col-lg-12">
-                                            <div class="card bg-primary-lt">
-                                                {if $server["class"] == 0}
-                                                <div class="ribbon bg-red">免费</div>
-                                                {else}
-                                                <div class="ribbon bg-red">LV. {$server["class"]}</div>
-                                                {/if}
-                                                <div class="card-body">
-                                                    <p class="text-muted">
-                                                        <i class="ti ti-info-circle icon text-blue"></i>
-                                                        你当前的账户等级小于下列节点等级,因此无法使用。可前往 <a
-                                                            href="/user/shop">商店</a> 订购相应等级套餐
-                                                    </p>
-                                                </div>
-                                            </div>
-                                        </div>
-                                        {/if}
                                         <div class="col-lg-4 col-md-6 col-sm-12">
                                             <div class="card">
                                                 {if $server["class"] == 0}
@@ -121,6 +103,17 @@
                                                     </div>
                                                 </div>
                                             </div>
+                                            {if $user->class < $server["class"]}
+                                            <div class="card bg-primary-lt">
+                                                <div class="card-body">
+                                                    <p class="text-muted">
+                                                        <i class="ti ti-info-circle icon text-blue"></i>
+                                                        你当前的账户等级小于节点等级,因此无法使用。可前往 <a
+                                                            href="/user/shop">商店</a> 订购相应等级套餐
+                                                    </p>
+                                                </div>
+                                            </div>
+                                            {/if}
                                         </div>
                                     {/foreach}
                                 </div>

+ 0 - 2
src/Command/Job.php

@@ -17,7 +17,6 @@ use App\Models\Setting;
 use App\Models\Shop;
 use App\Models\StreamMedia;
 use App\Models\TelegramSession;
-use App\Models\Token;
 use App\Models\User;
 use App\Models\UserHourlyUsage;
 use App\Models\UserSubscribeLog;
@@ -65,7 +64,6 @@ EOL;
         // ------- 清理各表记录
         UserSubscribeLog::where('request_time', '<', date('Y-m-d H:i:s', \time() - 86400 * (int) $_ENV['subscribeLog_keep_days']))->delete();
         UserHourlyUsage::where('datetime', '<', \time() - 86400 * (int) $_ENV['trafficLog_keep_days'])->delete();
-        Token::where('expire_time', '<', \time())->delete();
         DetectLog::where('datetime', '<', \time() - 86400 * 3)->delete();
         EmailVerify::where('expire_in', '<', \time() - 86400 * 3)->delete();
         EmailQueue::where('time', '<', \time() - 86400 * 3)->delete();

+ 16 - 7
src/Command/Migration.php

@@ -32,9 +32,10 @@ END;
         // (min_version, max_version]
         $min_version = 0;
         $max_version = 0;
+        $current = Setting::obtain('db_version');
         $target = $this->argv[2] ?? 0;
         if ($target === 'latest') {
-            $min_version = Setting::obtain('db_version');
+            $min_version = $current;
             $max_version = PHP_INT_MAX;
         } elseif ($target === 'new') {
             $tables = []; //DB::select('SHOW TABLES');
@@ -47,7 +48,6 @@ END;
             }
         } elseif (is_numeric($target)) {
             $target = (int) $target;
-            $current = Setting::obtain('db_version');
             if ($target < $current) {
                 $reverse = true;
                 $min_version = $target;
@@ -57,10 +57,12 @@ END;
                 $max_version = $target;
             }
         } else {
-            echo "Illegle version argument\n";
+            echo "Illegal version argument.\n";
             return;
         }
 
+        echo "Current database version {$current}.\n";
+
         $queue = [];
         $files = scandir(BASE_PATH . '/db/migrations/', SCANDIR_SORT_NONE);
         if ($files) {
@@ -69,7 +71,9 @@ END;
                     continue;
                 }
                 $version = (int) (explode('-', $file, 1)[0] ?? 0);
-                if (!($version > $min_version && $version <= $max_version)) {
+                echo "Found migration version {$version}.\n";
+                if ($version <= $min_version || $version > $max_version) {
+                    echo "Skip migration version {$version}.\n";
                     continue;
                 }
                 $object = require BASE_PATH . '/db/migrations/' . $file;
@@ -84,15 +88,20 @@ END;
             foreach ($queue as $version => $object) {
                 echo "Reverse to {$version}\n";
                 $object->down();
+                if ($version < $current) {
+                    $current = $version;
+                }
             }
-            $current = $min_version;
         } else {
             ksort($queue);
+            $current = 0;
             foreach ($queue as $version => $object) {
                 echo "Forward to {$version}\n";
                 $object->up();
+                if ($version > $current) {
+                    $current = $version;
+                }
             }
-            $current = $max_version;
         }
         if ($target === 'new') {
             $sql = 'INSERT INTO `config` (`item`, `value`, `type`, `default`) VALUES("db_version", ?, "int", "20230201000")';
@@ -102,6 +111,6 @@ END;
         DB::insert($sql, [$current]);
 
         $count = count($queue);
-        echo "Imigration complete. {$count} items processed.\n";
+        echo "Migration complete. {$count} item(s) processed.\n";
     }
 }

+ 136 - 0
src/Controllers/Admin/Setting/BillingController.php

@@ -0,0 +1,136 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Controllers\Admin\Setting;
+
+use App\Controllers\BaseController;
+use App\Models\Setting;
+use App\Services\Payment;
+
+final class BillingController extends BaseController
+{
+    public static $update_field = [
+        // 支付宝当面付
+        'f2f_pay_app_id',
+        'f2f_pay_pid',
+        'f2f_pay_public_key',
+        'f2f_pay_private_key',
+        'f2f_pay_notify_url',
+        // V免签
+        'vmq_gateway',
+        'vmq_key',
+        // PayJS
+        'payjs_url',
+        'payjs_mchid',
+        'payjs_key',
+        // TheadPay
+        'theadpay_url',
+        'theadpay_mchid',
+        'theadpay_key',
+        // Stripe
+        'stripe_card',
+        'stripe_alipay',
+        'stripe_wechat',
+        'stripe_currency',
+        'stripe_pk',
+        'stripe_sk',
+        'stripe_webhook_key',
+        'stripe_min_recharge',
+        'stripe_max_recharge',
+        // EPay
+        'epay_url',
+        'epay_pid',
+        'epay_key',
+        'epay_alipay',
+        'epay_wechat',
+        'epay_qq',
+        'epay_usdt',
+    ];
+
+    public function billing($request, $response, $args)
+    {
+        $settings = [];
+        $settings_raw = Setting::get(['item', 'value', 'type']);
+
+        foreach ($settings_raw as $setting) {
+            if ($setting->type === 'bool') {
+                $settings[$setting->item] = (bool) $setting->value;
+            } else {
+                $settings[$setting->item] = (string) $setting->value;
+            }
+        }
+
+        return $response->write(
+            $this->view()
+                ->assign('update_field', self::$update_field)
+                ->assign('settings', $settings)
+                ->assign('payment_gateways', self::returnGatewaysList())
+                ->assign('active_payment_gateway', self::returnActiveGateways())
+                ->fetch('admin/setting/billing.tpl')
+        );
+    }
+
+    public function saveBilling($request, $response, $args)
+    {
+        $gateway_in_use = [];
+
+        foreach (array_values(self::returnGatewaysList()) as $value) {
+            $payment_enable = $request->getParam("${value}");
+            if ($payment_enable === 'true') {
+                \array_push($gateway_in_use, $value);
+            }
+        }
+
+        $gateway = Setting::where('item', '=', 'payment_gateway')->first();
+        $gateway->value = \json_encode($gateway_in_use);
+
+        if (! $gateway->save()) {
+            return $response->withJson([
+                'ret' => 0,
+                'msg' => '保存支付网关时出错',
+            ]);
+        }
+
+        $list = self::$update_field;
+
+        foreach ($list as $item) {
+            $setting = Setting::where('item', '=', $item)->first();
+
+            if ($setting->type === 'array') {
+                $setting->value = \json_encode($request->getParam("${item}"));
+            } else {
+                $setting->value = $request->getParam("${item}");
+            }
+
+            if (! $setting->save()) {
+                return $response->withJson([
+                    'ret' => 0,
+                    'msg' => "保存 ${item} 时出错",
+                ]);
+            }
+        }
+
+        return $response->withJson([
+            'ret' => 1,
+            'msg' => '保存成功',
+        ]);
+    }
+
+    public function returnGatewaysList()
+    {
+        $result = [];
+
+        foreach (Payment::getAllPaymentMap() as $payment) {
+            $result[$payment::_name()] = $payment::_name();
+        }
+
+        return $result;
+    }
+
+    public function returnActiveGateways()
+    {
+        $payment_gateways = Setting::where('item', '=', 'payment_gateway')->first();
+        return \json_decode($payment_gateways->value);
+    }
+}

+ 73 - 0
src/Controllers/Admin/Setting/CaptchaController.php

@@ -0,0 +1,73 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Controllers\Admin\Setting;
+
+use App\Controllers\BaseController;
+use App\Models\Setting;
+
+final class CaptchaController extends BaseController
+{
+    public static $update_field = [
+        'captcha_provider',
+        'enable_reg_captcha',
+        'enable_login_captcha',
+        'enable_checkin_captcha',
+        'enable_reset_password_captcha',
+        // Turnstile
+        'turnstile_sitekey',
+        'turnstile_secret',
+        // Geetest
+        'geetest_id',
+        'geetest_key',
+    ];
+
+    public function captcha($request, $response, $args)
+    {
+        $settings = [];
+        $settings_raw = Setting::get(['item', 'value', 'type']);
+
+        foreach ($settings_raw as $setting) {
+            if ($setting->type === 'bool') {
+                $settings[$setting->item] = (bool) $setting->value;
+            } else {
+                $settings[$setting->item] = (string) $setting->value;
+            }
+        }
+
+        return $response->write(
+            $this->view()
+                ->assign('update_field', self::$update_field)
+                ->assign('settings', $settings)
+                ->fetch('admin/setting/captcha.tpl')
+        );
+    }
+
+    public function saveCaptcha($request, $response, $args)
+    {
+        $list = self::$update_field;
+
+        foreach ($list as $item) {
+            $setting = Setting::where('item', '=', $item)->first();
+
+            if ($setting->type === 'array') {
+                $setting->value = \json_encode($request->getParam("${item}"));
+            } else {
+                $setting->value = $request->getParam("${item}");
+            }
+
+            if (! $setting->save()) {
+                return $response->withJson([
+                    'ret' => 0,
+                    'msg' => "保存 ${item} 时出错",
+                ]);
+            }
+        }
+
+        return $response->withJson([
+            'ret' => 1,
+            'msg' => '保存成功',
+        ]);
+    }
+}

+ 110 - 0
src/Controllers/Admin/Setting/EmailController.php

@@ -0,0 +1,110 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Controllers\Admin\Setting;
+
+use App\Controllers\BaseController;
+use App\Models\Setting;
+use App\Services\Mail;
+
+final class EmailController extends BaseController
+{
+    public static $update_field = [
+        'mail_driver',
+        // SMTP
+        'smtp_host',
+        'smtp_username',
+        'smtp_password',
+        'smtp_port',
+        'smtp_name',
+        'smtp_sender',
+        'smtp_ssl',
+        'smtp_bbc',
+        // Mailgun
+        'mailgun_key',
+        'mailgun_domain',
+        'mailgun_sender',
+        // Sendgrid
+        'sendgrid_key',
+        'sendgrid_sender',
+        'sendgrid_name',
+        // AWS SES
+        'aws_access_key_id',
+        'aws_secret_access_key',
+        'aws_region',
+        'aws_ses_sender',
+    ];
+
+    public function email($request, $response, $args)
+    {
+        $settings = [];
+        $settings_raw = Setting::get(['item', 'value', 'type']);
+
+        foreach ($settings_raw as $setting) {
+            if ($setting->type === 'bool') {
+                $settings[$setting->item] = (bool) $setting->value;
+            } else {
+                $settings[$setting->item] = (string) $setting->value;
+            }
+        }
+
+        return $response->write(
+            $this->view()
+                ->assign('update_field', self::$update_field)
+                ->assign('settings', $settings)
+                ->fetch('admin/setting/email.tpl')
+        );
+    }
+
+    public function saveEmail($request, $response, $args)
+    {
+        $list = self::$update_field;
+
+        foreach ($list as $item) {
+            $setting = Setting::where('item', '=', $item)->first();
+
+            if ($setting->type === 'array') {
+                $setting->value = \json_encode($request->getParam("${item}"));
+            } else {
+                $setting->value = $request->getParam("${item}");
+            }
+
+            if (! $setting->save()) {
+                return $response->withJson([
+                    'ret' => 0,
+                    'msg' => "保存 ${item} 时出错",
+                ]);
+            }
+        }
+
+        return $response->withJson([
+            'ret' => 1,
+            'msg' => '保存成功',
+        ]);
+    }
+
+    public function testEmail($request, $response, $args)
+    {
+        $to = $request->getParam('recipient');
+
+        try {
+            Mail::send(
+                $to,
+                '测试邮件',
+                'auth/test.tpl',
+                [],
+                []
+            );
+        } catch (\Throwable $e) {
+            return $response->withJson([
+                'ret' => 0,
+                'msg' => '测试邮件发送失败',
+            ]);
+        }
+        return $response->withJson([
+            'ret' => 1,
+            'msg' => '测试邮件发送成功',
+        ]);
+    }
+}

+ 84 - 0
src/Controllers/Admin/Setting/ImController.php

@@ -0,0 +1,84 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Controllers\Admin\Setting;
+
+use App\Controllers\BaseController;
+use App\Models\Setting;
+
+final class ImController extends BaseController
+{
+    public static $update_field = [
+        'telegram_add_node',
+        'telegram_add_node_text',
+        'telegram_update_node',
+        'telegram_update_node_text',
+        'telegram_delete_node',
+        'telegram_delete_node_text',
+        'telegram_node_gfwed',
+        'telegram_node_gfwed_text',
+        'telegram_node_ungfwed',
+        'telegram_node_ungfwed_text',
+        'telegram_node_offline',
+        'telegram_node_offline_text',
+        'telegram_node_online',
+        'telegram_node_online_text',
+        'telegram_daily_job',
+        'telegram_daily_job_text',
+        'telegram_diary',
+        'telegram_diary_text',
+        'telegram_unbind_kick_member',
+        'telegram_group_bound_user',
+        'telegram_show_group_link',
+        'telegram_group_link',
+    ];
+
+    public function im($request, $response, $args)
+    {
+        $settings = [];
+        $settings_raw = Setting::get(['item', 'value', 'type']);
+
+        foreach ($settings_raw as $setting) {
+            if ($setting->type === 'bool') {
+                $settings[$setting->item] = (bool) $setting->value;
+            } else {
+                $settings[$setting->item] = (string) $setting->value;
+            }
+        }
+
+        return $response->write(
+            $this->view()
+                ->assign('update_field', self::$update_field)
+                ->assign('settings', $settings)
+                ->fetch('admin/setting/im.tpl')
+        );
+    }
+
+    public function saveIm($request, $response, $args)
+    {
+        $list = self::$update_field;
+
+        foreach ($list as $item) {
+            $setting = Setting::where('item', '=', $item)->first();
+
+            if ($setting->type === 'array') {
+                $setting->value = \json_encode($request->getParam("${item}"));
+            } else {
+                $setting->value = $request->getParam("${item}");
+            }
+
+            if (! $setting->save()) {
+                return $response->withJson([
+                    'ret' => 0,
+                    'msg' => "保存 ${item} 时出错",
+                ]);
+            }
+        }
+
+        return $response->withJson([
+            'ret' => 1,
+            'msg' => '保存成功',
+        ]);
+    }
+}

+ 72 - 0
src/Controllers/Admin/Setting/RefController.php

@@ -0,0 +1,72 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Controllers\Admin\Setting;
+
+use App\Controllers\BaseController;
+use App\Models\Setting;
+
+final class RefController extends BaseController
+{
+    public static $update_field = [
+        'invitation_to_register_balance_reward',
+        'invitation_to_register_traffic_reward',
+        'invite_price',
+        'custom_invite_price',
+        'invitation_mode',
+        'invite_rebate_mode',
+        'rebate_ratio',
+        'rebate_frequency_limit',
+        'rebate_amount_limit',
+        'rebate_time_range_limit',
+    ];
+
+    public function ref($request, $response, $args)
+    {
+        $settings = [];
+        $settings_raw = Setting::get(['item', 'value', 'type']);
+
+        foreach ($settings_raw as $setting) {
+            if ($setting->type === 'bool') {
+                $settings[$setting->item] = (bool) $setting->value;
+            } else {
+                $settings[$setting->item] = (string) $setting->value;
+            }
+        }
+
+        return $response->write(
+            $this->view()
+                ->assign('update_field', self::$update_field)
+                ->assign('settings', $settings)
+                ->fetch('admin/setting/ref.tpl')
+        );
+    }
+
+    public function saveRef($request, $response, $args)
+    {
+        $list = self::$update_field;
+
+        foreach ($list as $item) {
+            $setting = Setting::where('item', '=', $item)->first();
+
+            if ($setting->type === 'array') {
+                $setting->value = \json_encode($request->getParam("${item}"));
+            } else {
+                $setting->value = $request->getParam("${item}");
+            }
+
+            if (! $setting->save()) {
+                return $response->withJson([
+                    'ret' => 0,
+                    'msg' => "保存 ${item} 时出错",
+                ]);
+            }
+        }
+
+        return $response->withJson([
+            'ret' => 1,
+            'msg' => '保存成功',
+        ]);
+    }
+}

+ 84 - 0
src/Controllers/Admin/Setting/RegController.php

@@ -0,0 +1,84 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Controllers\Admin\Setting;
+
+use App\Controllers\BaseController;
+use App\Models\Setting;
+
+final class RegController extends BaseController
+{
+    public static $update_field = [
+        'reg_mode',
+        'reg_email_verify',
+        'email_verify_ttl',
+        'email_verify_ip_limit',
+        'email_verify_email_limit',
+        'sign_up_for_daily_report',
+        'enable_reg_im',
+        'random_group',
+        'min_port',
+        'max_port',
+        'sign_up_for_free_traffic',
+        'free_user_reset_day',
+        'free_user_reset_bandwidth',
+        'sign_up_for_free_time',
+        'sign_up_for_class',
+        'sign_up_for_class_time',
+        'sign_up_for_method',
+        'sign_up_for_invitation_codes',
+        'connection_device_limit',
+        'connection_rate_limit',
+        'reg_forbidden_ip',
+        'reg_forbidden_port',
+    ];
+
+    public function reg($request, $response, $args)
+    {
+        $settings = [];
+        $settings_raw = Setting::get(['item', 'value', 'type']);
+
+        foreach ($settings_raw as $setting) {
+            if ($setting->type === 'bool') {
+                $settings[$setting->item] = (bool) $setting->value;
+            } else {
+                $settings[$setting->item] = (string) $setting->value;
+            }
+        }
+
+        return $response->write(
+            $this->view()
+                ->assign('update_field', self::$update_field)
+                ->assign('settings', $settings)
+                ->fetch('admin/setting/reg.tpl')
+        );
+    }
+
+    public function saveReg($request, $response, $args)
+    {
+        $list = self::$update_field;
+
+        foreach ($list as $item) {
+            $setting = Setting::where('item', '=', $item)->first();
+
+            if ($setting->type === 'array') {
+                $setting->value = \json_encode($request->getParam("${item}"));
+            } else {
+                $setting->value = $request->getParam("${item}");
+            }
+
+            if (! $setting->save()) {
+                return $response->withJson([
+                    'ret' => 0,
+                    'msg' => "保存 ${item} 时出错",
+                ]);
+            }
+        }
+
+        return $response->withJson([
+            'ret' => 1,
+            'msg' => '保存成功',
+        ]);
+    }
+}

+ 72 - 0
src/Controllers/Admin/Setting/SupportController.php

@@ -0,0 +1,72 @@
+<?php
+
+declare(strict_types=1);
+
+namespace App\Controllers\Admin\Setting;
+
+use App\Controllers\BaseController;
+use App\Models\Setting;
+
+final class SupportController extends BaseController
+{
+    public static $update_field = [
+        'live_chat',
+        'tawk_id',
+        'crisp_id',
+        'livechat_id',
+        'mylivechat_id',
+        // Admin Contact
+        'enable_admin_contact',
+        'admin_contact1',
+        'admin_contact2',
+        'admin_contact3',
+    ];
+
+    public function support($request, $response, $args)
+    {
+        $settings = [];
+        $settings_raw = Setting::get(['item', 'value', 'type']);
+
+        foreach ($settings_raw as $setting) {
+            if ($setting->type === 'bool') {
+                $settings[$setting->item] = (bool) $setting->value;
+            } else {
+                $settings[$setting->item] = (string) $setting->value;
+            }
+        }
+
+        return $response->write(
+            $this->view()
+                ->assign('update_field', self::$update_field)
+                ->assign('settings', $settings)
+                ->fetch('admin/setting/support.tpl')
+        );
+    }
+
+    public function saveSupport($request, $response, $args)
+    {
+        $list = self::$update_field;
+
+        foreach ($list as $item) {
+            $setting = Setting::where('item', '=', $item)->first();
+
+            if ($setting->type === 'array') {
+                $setting->value = \json_encode($request->getParam("${item}"));
+            } else {
+                $setting->value = $request->getParam("${item}");
+            }
+
+            if (! $setting->save()) {
+                return $response->withJson([
+                    'ret' => 0,
+                    'msg' => "保存 ${item} 时出错",
+                ]);
+            }
+        }
+
+        return $response->withJson([
+            'ret' => 1,
+            'msg' => '保存成功',
+        ]);
+    }
+}

+ 0 - 196
src/Controllers/Admin/SettingController.php

@@ -1,196 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace App\Controllers\Admin;
-
-use App\Controllers\BaseController;
-use App\Models\Setting;
-use App\Services\Mail;
-use App\Services\Payment;
-
-final class SettingController extends BaseController
-{
-    public function index($request, $response, $args)
-    {
-        $config = [];
-        $settings = Setting::get(['item', 'value', 'type']);
-
-        foreach ($settings as $setting) {
-            if ($setting->type === 'bool') {
-                $config[$setting->item] = (bool) $setting->value;
-            } else {
-                $config[$setting->item] = (string) $setting->value;
-            }
-        }
-
-        return $response->write(
-            $this->view()
-                //->registerClass('Setting', Setting::class)
-                ->assign('settings', $config)
-                ->assign('payment_gateways', self::returnGatewaysList())
-                ->assign('active_payment_gateway', self::returnActiveGateways())
-                ->fetch('admin/setting.tpl')
-        );
-    }
-
-    public function save($request, $response, $args)
-    {
-        $class = $request->getParam('class');
-
-        switch ($class) {
-            // 支付
-            case 'f2f_pay':
-                $list = ['f2f_pay_app_id', 'f2f_pay_pid', 'f2f_pay_public_key', 'f2f_pay_private_key', 'f2f_pay_notify_url'];
-                break;
-            case 'vmq_pay':
-                $list = ['vmq_gateway', 'vmq_key'];
-                break;
-            case 'payjs_pay':
-                $list = ['payjs_url','payjs_mchid', 'payjs_key'];
-                break;
-            case 'theadpay':
-                $list = ['theadpay_url', 'theadpay_mchid', 'theadpay_key'];
-                break;
-            case 'paymentwall':
-                $list = ['pmw_publickey', 'pmw_privatekey', 'pmw_widget', 'pmw_height'];
-                break;
-            case 'stripe':
-                $list = ['stripe_card', 'stripe_currency', 'stripe_pk', 'stripe_sk', 'stripe_webhook_key', 'stripe_min_recharge', 'stripe_max_recharge'];
-                break;
-            case 'e_pay':
-                $list = ['epay_url', 'epay_pid', 'epay_key', 'epay_alipay', 'epay_wechat', 'epay_qq', 'epay_usdt'];
-                break;
-                // 邮件
-            case 'mail':
-                $list = ['mail_driver'];
-                break;
-            case 'smtp':
-                $list = ['smtp_host', 'smtp_username', 'smtp_password', 'smtp_port', 'smtp_name', 'smtp_sender', 'smtp_ssl', 'smtp_bbc'];
-                break;
-            case 'mailgun':
-                $list = ['mailgun_key', 'mailgun_domain', 'mailgun_sender'];
-                break;
-            case 'sendgrid':
-                $list = ['sendgrid_key', 'sendgrid_sender', 'sendgrid_name'];
-                break;
-            case 'ses':
-                $list = ['aws_access_key_id', 'aws_secret_access_key', 'aws_region', 'aws_ses_sender'];
-                break;
-                // 验证码
-            case 'verify_code':
-                $list = ['captcha_provider', 'enable_reg_captcha', 'enable_login_captcha', 'enable_checkin_captcha', 'enable_reset_password_captcha'];
-                break;
-            case 'verify_code_turnstile':
-                $list = ['turnstile_sitekey', 'turnstile_secret'];
-                break;
-            case 'verify_code_geetest':
-                $list = ['geetest_id', 'geetest_key'];
-                break;
-                // 客户服务
-            case 'admin_contact':
-                $list = ['enable_admin_contact', 'admin_contact1', 'admin_contact2', 'admin_contact3'];
-                break;
-            case 'web_customer_service_system':
-                $list = ['live_chat', 'tawk_id', 'crisp_id', 'livechat_id', 'mylivechat_id'];
-                break;
-                // 注册设置
-            case 'register':
-                $list = ['reg_mode', 'reg_email_verify', 'email_verify_ttl', 'email_verify_ip_limit', 'random_group', 'min_port', 'max_port',   'sign_up_for_free_traffic','free_user_reset_day', 'free_user_reset_bandwidth', 'sign_up_for_free_time', 'sign_up_for_class', 'sign_up_for_class_time', 'sign_up_for_invitation_codes', 'connection_device_limit', 'connection_rate_limit', 'sign_up_for_method', 'reg_forbidden_ip', 'reg_forbidden_port', 'enable_reg_im', 'sign_up_for_daily_report'];
-                break;
-                // 邀请设置
-            case 'invite':
-                $list = ['invitation_to_register_balance_reward', 'invitation_to_register_traffic_reward', 'invite_price', 'custom_invite_price',
-                    'invitation_mode', 'invite_rebate_mode', 'rebate_ratio', 'rebate_frequency_limit', 'rebate_amount_limit', 'rebate_time_range_limit',
-                ];
-                break;
-                // Telegram 设置
-            case 'telegram':
-                $list = ['telegram_add_node', 'telegram_add_node_text', 'telegram_update_node', 'telegram_update_node_text', 'telegram_delete_node', 'telegram_delete_node_text', 'telegram_node_gfwed', 'telegram_node_gfwed_text', 'telegram_node_ungfwed', 'telegram_node_ungfwed_text', 'telegram_node_online', 'telegram_node_online_text', 'telegram_node_offline', 'telegram_node_offline_text', 'telegram_daily_job', 'telegram_daily_job_text', 'telegram_diary', 'telegram_diary_text', 'telegram_unbind_kick_member', 'telegram_group_bound_user', 'telegram_show_group_link', 'telegram_group_link'];
-                break;
-        }
-
-        foreach ($list as $item) {
-            $setting = Setting::where('item', '=', $item)->first();
-
-            if ($setting->type === 'array') {
-                $setting->value = \json_encode($request->getParam("${item}"));
-            } else {
-                $setting->value = $request->getParam("${item}");
-            }
-
-            if (! $setting->save()) {
-                return $response->withJson([
-                    'ret' => 0,
-                    'msg' => "保存 ${item} 时出错",
-                ]);
-            }
-        }
-
-        return $response->withJson([
-            'ret' => 1,
-            'msg' => '保存成功',
-        ]);
-    }
-
-    public function test($request, $response, $args)
-    {
-        $to = $request->getParam('recipient');
-
-        try {
-            Mail::send(
-                $to,
-                '测试邮件',
-                'auth/test.tpl',
-                [],
-                []
-            );
-        } catch (\Throwable $e) {
-            return $response->withJson([
-                'ret' => 0,
-                'msg' => '测试邮件发送失败',
-            ]);
-        }
-        return $response->withJson([
-            'ret' => 1,
-            'msg' => '测试邮件发送成功',
-        ]);
-    }
-
-    public function returnGatewaysList()
-    {
-        $result = [];
-
-        foreach (Payment::getAllPaymentMap() as $payment) {
-            $result[$payment::_name()] = $payment::_name();
-        }
-
-        return $result;
-    }
-
-    public function returnActiveGateways()
-    {
-        $payment_gateways = Setting::where('item', '=', 'payment_gateway')->first();
-        return \json_decode($payment_gateways->value);
-    }
-
-    public function payment($request, $response, $args)
-    {
-        $gateway_in_use = [];
-        foreach (array_values(self::returnGatewaysList()) as $value) {
-            $payment_switch = $request->getParam("${value}");
-            if ($payment_switch === '1') {
-                array_push($gateway_in_use, $value);
-            }
-        }
-
-        $gateway = Setting::where('item', '=', 'payment_gateway')->first();
-        $gateway->value = \json_encode($gateway_in_use);
-        $gateway->save();
-
-        return $response->withJson([
-            'ret' => 1,
-            'msg' => '保存成功',
-        ]);
-    }
-}

+ 1 - 1
src/Controllers/Admin/UserController.php

@@ -119,7 +119,7 @@ final class UserController extends BaseController
             if ($email === '') {
                 throw new \Exception('请填写邮箱');
             }
-            if (!Check::isEmailLegal($email)) {
+            if (! Check::isEmailLegal($email)) {
                 throw new \Exception('邮箱格式不正确');
             }
             $exist = User::where('email', $email)->first();

+ 14 - 7
src/Controllers/AuthController.php

@@ -66,7 +66,7 @@ final class AuthController extends BaseController
     {
         if (Setting::obtain('enable_login_captcha') === true) {
             $ret = Captcha::verify($request->getParams());
-            if (!$ret) {
+            if (! $ret) {
                 return $response->withJson([
                     'ret' => 0,
                     'msg' => '系统无法接受您的验证结果,请刷新页面后重试。',
@@ -87,7 +87,7 @@ final class AuthController extends BaseController
             ]);
         }
 
-        if (!Hash::checkPassword($user->pass, $passwd)) {
+        if (! Hash::checkPassword($user->pass, $passwd)) {
             // 记录登录失败
             $user->collectLoginIP($_SERVER['REMOTE_ADDR'], 1);
             return $response->withJson([
@@ -99,7 +99,7 @@ final class AuthController extends BaseController
         if ($user->ga_enable === 1) {
             $ga = new GoogleAuthenticator();
             $rcode = $ga->verifyCode($user->ga_token, $code);
-            if (!$rcode) {
+            if (! $rcode) {
                 return $response->withJson([
                     'ret' => 0,
                     'msg' => '两步验证码错误,如果您是丢失了生成器或者错误地设置了这个选项,您可以尝试重置密码,即可取消这个选项。',
@@ -195,27 +195,32 @@ final class AuthController extends BaseController
             if ($email === '') {
                 return ResponseHelper::error($response, '未填写邮箱');
             }
+
             // check email format
             $check_res = Check::isEmailLegal($email);
             if ($check_res['ret'] === 0) {
                 return $response->withJson($check_res);
             }
+
             $user = User::where('email', $email)->first();
             if ($user !== null) {
                 return ResponseHelper::error($response, '此邮箱已经注册');
             }
+
             $ipcount = EmailVerify::where('ip', '=', $_SERVER['REMOTE_ADDR'])
                 ->where('expire_in', '>', \time())
                 ->count();
-            if ($ipcount >= Setting::obtain('email_verify_ip_limit')) {
+            if ($ipcount > Setting::obtain('email_verify_ip_limit')) {
                 return ResponseHelper::error($response, '此IP请求次数过多');
             }
+
             $mailcount = EmailVerify::where('email', '=', $email)
                 ->where('expire_in', '>', \time())
                 ->count();
-            if ($mailcount >= 3) {
+            if ($mailcount > Setting::obtain('email_verify_email_limit')) {
                 return ResponseHelper::error($response, '此邮箱请求次数过多');
             }
+
             $code = Tools::genRandomChar(6);
             $ev = new EmailVerify();
             $ev->expire_in = \time() + Setting::obtain('email_verify_ttl');
@@ -223,6 +228,7 @@ final class AuthController extends BaseController
             $ev->email = $email;
             $ev->code = $code;
             $ev->save();
+
             try {
                 Mail::send(
                     $email,
@@ -237,6 +243,7 @@ final class AuthController extends BaseController
             } catch (Exception $e) {
                 return ResponseHelper::error($response, '邮件发送失败,请联系网站管理员。');
             }
+
             return ResponseHelper::successfully($response, '验证码发送成功,请查收邮件。');
         }
         return ResponseHelper::error($response, ' 不允许注册');
@@ -340,7 +347,7 @@ final class AuthController extends BaseController
             $user->node_group = $random_group[array_rand(explode(',', $random_group))];
         }
 
-        if ($user->save() && !$is_admin_reg) {
+        if ($user->save() && ! $is_admin_reg) {
             Auth::login($user->id, 3600);
             $user->collectLoginIP($_SERVER['REMOTE_ADDR']);
 
@@ -365,7 +372,7 @@ final class AuthController extends BaseController
 
         if (Setting::obtain('enable_reg_captcha') === true) {
             $ret = Captcha::verify($request->getParams());
-            if (!$ret) {
+            if (! $ret) {
                 return ResponseHelper::error($response, '系统无法接受您的验证结果,请刷新页面后重试。');
             }
         }

+ 1 - 1
src/Controllers/UserController.php

@@ -600,7 +600,7 @@ final class UserController extends BaseController
 
         $newusername = $antiXss->xss_clean($request->getParam('newusername'));
         $user = $this->user;
-        
+
         $user->user_name = $newusername;
         $user->save();
 

+ 5 - 5
src/Controllers/WebAPI/UserController.php

@@ -104,7 +104,7 @@ final class UserController extends BaseController
     public function addTraffic(Request $request, Response $response, array $args): ResponseInterface
     {
         $data = \json_decode($request->getBody()->__toString());
-        if (!$data || !\is_array($data?->data)) {
+        if (! $data || ! \is_array($data?->data)) {
             return $response->withJson([
                 'ret' => 0,
             ]);
@@ -158,7 +158,7 @@ final class UserController extends BaseController
     public function addAliveIp(Request $request, Response $response, array $args): ResponseInterface
     {
         $data = \json_decode($request->getBody()->__toString());
-        if (!$data || !\is_array($data?->data)) {
+        if (! $data || ! \is_array($data?->data)) {
             return $response->withJson([
                 'ret' => 0,
             ]);
@@ -167,7 +167,7 @@ final class UserController extends BaseController
 
         $node_id = $request->getQueryParam('node_id');
 
-        if ($node_id === null || !Node::where('id', $node_id)->exists()) {
+        if ($node_id === null || ! Node::where('id', $node_id)->exists()) {
             return $response->withJson([
                 'ret' => 0,
             ]);
@@ -203,7 +203,7 @@ final class UserController extends BaseController
     public function addDetectLog(Request $request, Response $response, array $args): ResponseInterface
     {
         $data = \json_decode($request->getBody()->__toString());
-        if (!$data || !\is_array($data?->data)) {
+        if (! $data || ! \is_array($data?->data)) {
             return $response->withJson([
                 'ret' => 0,
             ]);
@@ -212,7 +212,7 @@ final class UserController extends BaseController
 
         $node_id = $request->getQueryParam('node_id');
 
-        if ($node_id === null || !Node::where('id', $node_id)->exists()) {
+        if ($node_id === null || ! Node::where('id', $node_id)->exists()) {
             return $response->withJson([
                 'ret' => 0,
             ]);

+ 2 - 2
src/Middleware/Admin.php

@@ -16,10 +16,10 @@ final class Admin implements MiddlewareInterface
     public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
     {
         $user = AuthService::getUser();
-        if (!$user->isLogin) {
+        if (! $user->isLogin) {
             return AppFactory::determineResponseFactory()->createResponse(302)->withHeader('Location', '/auth/login');
         }
-        if (!$user->is_admin) {
+        if (! $user->is_admin) {
             return AppFactory::determineResponseFactory()->createResponse(302)->withHeader('Location', '/user');
         }
         return $handler->handle($request);

+ 2 - 3
src/Middleware/Auth.php

@@ -10,7 +10,6 @@ use Psr\Http\Message\ServerRequestInterface;
 use Psr\Http\Server\MiddlewareInterface;
 use Psr\Http\Server\RequestHandlerInterface;
 use Slim\Factory\AppFactory;
-
 use function in_array;
 
 final class Auth implements MiddlewareInterface
@@ -18,11 +17,11 @@ final class Auth implements MiddlewareInterface
     public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
     {
         $user = AuthService::getUser();
-        if (!$user->isLogin) {
+        if (! $user->isLogin) {
             return AppFactory::determineResponseFactory()->createResponse(302)->withHeader('Location', '/auth/login');
         }
         $enablePages = ['/user/banned', '/user/backtoadmin', '/user/logout'];
-        if ($user->is_banned === 1 && !in_array($request->getUri()->getPath(), $enablePages)) {
+        if ($user->is_banned === 1 && ! in_array($request->getUri()->getPath(), $enablePages)) {
             return AppFactory::determineResponseFactory()->createResponse(302)->withHeader('Location', '/user/banned');
         }
         $request = $request->withAttribute('user', $user);

+ 0 - 21
src/Models/Node.php

@@ -4,27 +4,6 @@ declare(strict_types=1);
 
 namespace App\Models;
 
-/**
- * Node Model
- *
- * @property-read   int     $id         id
- *
- * @property        string  $name       Display name
- * @property        bool    $type       If node display @todo Correct column name and type
- * @property        string  $server     Domain
- * @property        string  $method     Crypt method @deprecated
- * @property        string  $info       Infomation
- * @property        string  $status     Status description
- * @property        int     $sort       Node type @todo Correct column name to `type`
- * @property        int     $custom_method  Customs node crypt @deprecated
- * @property        float   $traffic_rate   Node traffic rate
- *
- * @todo More property
- *
- * @property        bool    $online     If node is online
- * @property        bool    $gfw_block  If node is blocked by GFW
- */
-
 final class Node extends Model
 {
     protected $connection = 'default';

+ 0 - 11
src/Models/Token.php

@@ -1,11 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace App\Models;
-
-final class Token extends Model
-{
-    protected $connection = 'default';
-    protected $table = 'user_token';
-}

+ 0 - 11
src/Models/User.php

@@ -11,17 +11,6 @@ use App\Utils\Tools;
 use Exception;
 use Ramsey\Uuid\Uuid;
 
-/**
- * User Model
- *
- * @property-read   int     $id         ID
- *
- * @todo More property
- *
- * @property        bool    $is_admin           是否管理员
- * @property        bool    $expire_notified    If user is notified for expire
- * @property        bool    $traffic_notified   If user is noticed for low traffic
- */
 final class User extends Model
 {
     /**

+ 2 - 2
src/Services/Captcha.php

@@ -46,7 +46,7 @@ final class Captcha
                         'content' => $postdata,
                     ],
                     ];
-                    $json = @file_get_contents('https://challenges.cloudflare.com/turnstile/v0/siteverify', false, stream_context_create($opts));
+                    $json = file_get_contents('https://challenges.cloudflare.com/turnstile/v0/siteverify', false, stream_context_create($opts));
                     $result = \json_decode($json)->success;
                 }
                 break;
@@ -76,7 +76,7 @@ final class Captcha
                             'timeout' => 5,
                         ],
                     ];
-                    $json = @file_get_contents(
+                    $json = file_get_contents(
                         'http://gcaptcha4.geetest.com/validate?captcha_id=' . $captcha_id,
                         false,
                         stream_context_create($opts)

+ 0 - 2
src/Services/Gateway/AbstractPayment.php

@@ -33,8 +33,6 @@ abstract class AbstractPayment
 
     /**
      * 是否启用支付网关
-     *
-     * TODO: 传入目前用户信, etc..
      */
     abstract public static function _enable(): bool;
 

+ 11 - 13
src/Services/Gateway/PAYJS.php

@@ -86,33 +86,33 @@ final class PAYJS extends AbstractPayment
     public function purchase(Request $request, Response $response, array $args): ResponseInterface
     {
         $price = $request->getParam('price');
+
         if ($price <= 0) {
-            return $response->withJson(['code' => -1, 'errmsg' => '非法的金额.']);
+            return $response->withJson([
+                'code' => -1,
+                'errmsg' => '非法的金额.',
+            ]);
         }
+
         $user = Auth::getUser();
         $pl = new Paylist();
         $pl->userid = $user->id;
         $pl->total = $price;
         $pl->tradeno = self::generateGuid();
         $pl->save();
-        //if ($type != 'alipay') {
-        //$type = '';
-        //}
         $data = [];
         $data['mchid'] = Setting::obtain('payjs_mchid');
-        //$data['type'] = $type;
         $data['out_trade_no'] = $pl->tradeno;
         $data['total_fee'] = (float) $price * 100;
         $data['notify_url'] = self::getCallbackUrl();
-        //$data['callback_url'] = $_ENV['baseUrl'] . '/user/code';
         $params = $this->prepareSign($data);
         $data['sign'] = $this->sign($params);
-        //$url = 'https://payjs.cn/api/cashier?' . http_build_query($data);
         $url = Setting::obtain('payjs_url') . '/cashier?' . http_build_query($data);
-        return $response->withJson(['code' => 0, 'url' => $url, 'pid' => $data['out_trade_no']]);
-        //$result = \json_decode($this->post($data), true);
-        //$result['pid'] = $pl->tradeno;
-        //return \json_encode($result);
+        return $response->withJson([
+            'code' => 0,
+            'url' => $url,
+            'pid' => $data['out_trade_no'],
+        ]);
     }
     public function query($tradeNo)
     {
@@ -129,7 +129,6 @@ final class PAYJS extends AbstractPayment
 
         if ($return_code === 1) {
             // 验证签名
-            // $in_sign = $data['sign'];
             unset($data['sign']);
             $data = array_filter($data);
             ksort($data);
@@ -175,7 +174,6 @@ final class PAYJS extends AbstractPayment
         } else {
             $data = $request->getParsedBody();
 
-            // $in_sign = $data['sign'];
             unset($data['sign']);
             $data = array_filter($data);
             ksort($data);

+ 0 - 111
src/Services/Gateway/PaymentWall.php

@@ -1,111 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace App\Services\Gateway;
-
-use App\Models\Code;
-use App\Models\Payback;
-use App\Models\Setting;
-use App\Models\User;
-use App\Services\Auth;
-use Paymentwall_Config;
-use Paymentwall_Pingback;
-use Paymentwall_Widget;
-use Psr\Http\Message\ResponseInterface;
-use Slim\Http\Response;
-use Slim\Http\ServerRequest;
-
-final class PaymentWall extends AbstractPayment
-{
-    public static function _name(): string
-    {
-        return 'paymentwall';
-    }
-
-    public static function _enable(): bool
-    {
-        return self::getActiveGateway('paymentwall');
-    }
-
-    public static function _readableName(): string
-    {
-        return 'PaymentWall';
-    }
-
-    public function purchase(Request $request, Response $response, array $args): ResponseInterface
-    {
-        return $response->withStatus(204);
-        // TODO: Implement purchase() method.
-    }
-
-    public function notify($request, $response, $args): ResponseInterface
-    {
-        $configs = Setting::getClass('pmw');
-        if ($configs['pmw_publickey'] !== '') {
-            Paymentwall_Config::getInstance()->set([
-                'api_type' => Paymentwall_Config::API_VC,
-                'public_key' => $configs['pmw_publickey'],
-                'private_key' => $configs['pmw_privatekey'],
-            ]);
-            $pingback = new Paymentwall_Pingback($_GET, $_SERVER['REMOTE_ADDR']);
-            if ($pingback->validate()) {
-                $virtualCurrency = $pingback->getVirtualCurrencyAmount();
-                // if ($pingback->isDeliverable()) {
-                //     // deliver the virtual currency
-                // } elseif ($pingback->isCancelable()) {
-                //     // withdraw the virual currency
-                // }
-                $user = User::find($pingback->getUserId());
-                $user->money += $pingback->getVirtualCurrencyAmount();
-                $user->save();
-                $codeq = new Code();
-                $codeq->code = 'Payment Wall 充值';
-                $codeq->isused = 1;
-                $codeq->type = -1;
-                $codeq->number = $pingback->getVirtualCurrencyAmount();
-                $codeq->usedatetime = date('Y-m-d H:i:s');
-                $codeq->userid = $user->id;
-                $codeq->save();
-                // 返利
-                if ($user->ref_by > 0 && Setting::obtain('invitation_mode') === 'after_recharge') {
-                    Payback::rebate($user->id, $virtualCurrency);
-                }
-
-                return $response->write('OK');
-            }
-
-            return $response->write($pingback->getErrorSummary());
-        }
-        return $response->write('error');
-    }
-
-    public static function getPurchaseHTML(): string
-    {
-        $configs = Setting::getClass('pmw');
-        Paymentwall_Config::getInstance()->set([
-            'api_type' => Paymentwall_Config::API_VC,
-            'public_key' => $configs['pmw_publickey'],
-            'private_key' => $configs['pmw_privatekey'],
-        ]);
-        $user = Auth::getUser();
-        $widget = new Paymentwall_Widget(
-            $user->id, // id of the end-user who's making the payment
-            $configs['pmw_widget'],      // widget code, e.g. p1; can be picked inside of your merchant account
-            [],     // array of products - leave blank for Virtual Currency API
-            [
-                'email' => $user->email,
-                'history' => [
-                    'registration_date' => strtotime($user->reg_date),
-                    'registration_ip' => $user->reg_ip,
-                    'payments_number' => Code::where('userid', '=', $user->id)->where('type', '=', -1)->count(),
-                    'membership' => $user->class,
-                ],
-                'customer' => [
-                    'username' => $user->user_name,
-                ],
-            ] // additional parameters
-        );
-        return $widget->getHtmlCode(['height' => $configs['pmw_height'], 'width' => '100%']);
-    }
-}

+ 0 - 1
src/Utils/CloudflareDriver.php

@@ -11,7 +11,6 @@ use Cloudflare\API\Endpoints\Zones;
 
 final class CloudflareDriver
 {
-    // @todo: parameters
     public static function modifyRecord(DNS $dns, $zoneID, $recordID, $name, $content, $proxied = false)
     {
         $details = ['type' => 'A', 'name' => $name, 'content' => $content, 'proxied' => $proxied];

+ 0 - 1
src/Utils/ResponseHelper.php

@@ -7,7 +7,6 @@ namespace App\Utils;
 use Psr\Http\Message\RequestInterface;
 use Psr\Http\Message\ResponseInterface;
 use Slim\Http\Response;
-
 use function array_keys;
 use function hash;
 use function json_encode;

+ 4 - 4
src/Utils/Telegram/Callbacks/Callback.php

@@ -215,7 +215,7 @@ final class Callback
 
     public static function getUserIndexKeyboard($user)
     {
-        $checkin = (!$user->isAbleToCheckin() ? '已签到' : '签到');
+        $checkin = (! $user->isAbleToCheckin() ? '已签到' : '签到');
         $Keyboard = [
             [
                 [
@@ -395,7 +395,7 @@ final class Callback
                 foreach ($totallogin as $single) {
                     $location = $iplocation->getlocation($single->ip);
                     $loginiplocation = iconv('gbk', 'utf-8//IGNORE', $location['country'] . $location['area']);
-                    if (!\in_array($loginiplocation, $userloginip)) {
+                    if (! \in_array($loginiplocation, $userloginip)) {
                         $userloginip[] = $loginiplocation;
                     }
                 }
@@ -888,7 +888,7 @@ final class Callback
     {
         $paybacks_sum = Payback::where('ref_by', $this->User->id)->sum('ref_get');
 
-        if (!is_null($paybacks_sum)) {
+        if (! is_null($paybacks_sum)) {
             $paybacks_sum = 0;
         }
         $invitation = Setting::getClass('invite');
@@ -992,7 +992,7 @@ final class Callback
             $temp['keyboard'] = [
                 [
                     [
-                        'text' => (!$this->User->isAbleToCheckin() ? '已签到' : '签到'),
+                        'text' => (! $this->User->isAbleToCheckin() ? '已签到' : '签到'),
                         'callback_data' => 'user.checkin.' . $this->triggerUser['id'],
                     ],
                 ],

+ 0 - 1
src/Utils/Telegram/Commands/StartCommand.php

@@ -7,7 +7,6 @@ namespace App\Utils\Telegram\Commands;
 use App\Models\User;
 use App\Utils\Telegram\TelegramTools;
 use App\Utils\TelegramSessionManager;
-
 use Telegram\Bot\Actions;
 use Telegram\Bot\Commands\Command;
 

+ 1 - 1
src/Utils/Tools.php

@@ -157,7 +157,7 @@ final class Tools
     {
         $user = User::orderBy('id', 'desc')->first();
         if ($user === null) {
-            return 1024; // @todo
+            return 1024;
         }
         return $user->port;
     }