瀏覽代碼

added DDNS系统初版(已支持阿里云&Namesilo)

兔姬桑 4 年之前
父節點
當前提交
d038accc82

+ 68 - 0
app/Components/DDNS.php

@@ -0,0 +1,68 @@
+<?php
+
+namespace App\Components;
+
+use App\Components\DDNS\Aliyun;
+use App\Components\DDNS\Namesilo;
+use Log;
+
+/**
+ * Class DDNS 域名解析
+ *
+ * @package App\Components
+ */
+class DDNS
+{
+    /**
+     * 删除解析记录
+     *
+     * @param  string  $domain  域名
+     * @param  string|null  $type
+     * @return false|int
+     */
+    public static function destory($domain, $type = null)
+    {
+        return self::getClient($domain)->destroy($type);
+    }
+
+    public static function getClient($domain)
+    {
+        switch (sysConfig('ddns_mode')) {
+            case 'aliyun':
+                return (new Aliyun($domain));
+            case 'namesilo':
+                return new Namesilo($domain);
+            default:
+                Log::error("未知渠道:".sysConfig('ddns_mode'));
+
+                return false;
+        }
+    }
+
+    /**
+     * 修改解析记录
+     *
+     * @param  string  $domain  域名
+     * @param  string  $ip  ip地址
+     * @param  string  $type  记录类型,默认为 A
+     * @return void
+     */
+    public static function update($domain, $ip, $type = 'A')
+    {
+        return self::getClient($domain)->update($ip, $type);
+    }
+
+    /**
+     * 添加解析记录
+     *
+     * @param  string  $domain  域名
+     * @param  string  $ip  ip地址
+     * @param  string  $type  记录类型,默认为 A
+     * @return void
+     */
+    public static function store($domain, $ip, $type = 'A')
+    {
+        return self::getClient($domain)->store($ip, $type);
+    }
+
+}

+ 152 - 0
app/Components/DDNS/Aliyun.php

@@ -0,0 +1,152 @@
+<?php
+
+namespace App\Components\DDNS;
+
+use Arr;
+use Http;
+use Log;
+
+class Aliyun
+{
+    private static $subDomain;
+
+    public function __construct($subDomain)
+    {
+        self::$subDomain = $subDomain;
+    }
+
+    public function store($ip, $type)
+    {
+        $domainInfo = $this->analysisDomain();
+
+        if ($domainInfo) {
+            return $this->send('AddDomainRecord', ['DomainName' => $domainInfo[0], 'RR' => $domainInfo[1], 'Type' => $type, 'Value' => $ip]);
+        }
+
+        return false;
+    }
+
+    private function analysisDomain()
+    {
+        $domainList = $this->domainList();
+        if ($domainList) {
+            foreach ($domainList as $domain) {
+                if (strpos(self::$subDomain, $domain) !== false) {
+                    return [$domain, rtrim(substr(self::$subDomain, 0, -(strlen($domain))), '.')];
+                }
+            }
+        }
+
+        return false;
+    }
+
+    public function domainList()
+    {
+        $result = $this->send('DescribeDomains');
+        if ($result) {
+            $result = $result['Domains']['Domain'];
+            if ($result) {
+                return Arr::pluck($result, 'DomainName');
+            }
+        }
+
+        return false;
+    }
+
+    private function send($action, $data = [])
+    {
+        $public = [
+            'Format'           => 'JSON',
+            'Version'          => '2015-01-09',
+            'AccessKeyId'      => sysConfig('ddns_key'),
+            'SignatureMethod'  => 'HMAC-SHA1',
+            'Timestamp'        => gmdate("Y-m-d\TH:i:s\Z"),//公共参数Timestamp GMT时间
+            'SignatureVersion' => '1.0',
+            'SignatureNonce'   => str_replace('.', '', microtime(true)),//唯一数,用于防止网络重放攻击
+        ];
+        $parameters = array_merge(['Action' => $action], $data, $public);
+        $parameters['Signature'] = $this->computeSignature($parameters);
+
+        $response = Http::timeout(15)->post('https://alidns.aliyuncs.com/?'.http_build_query($parameters));
+        $message = $response->json();
+
+        if ($response->failed()) {
+            if ($message && $message['Code']) {
+                $error = $message['Message'];
+            } else {
+                $error = $response->body();
+            }
+            Log::error('[Aliyun - '.$action.'] 请求失败:'.$error);
+
+            return false;
+        }
+
+        return $message;
+    }
+
+    // 签名
+    private function computeSignature($parameters): string
+    {
+        ksort($parameters);
+
+        $stringToBeSigned = 'POST&%2F&'.urlencode(http_build_query($parameters));
+
+        return base64_encode(hash_hmac('sha1', $stringToBeSigned, sysConfig('ddns_secret').'&', true));
+    }
+
+    public function update($ip, $type)
+    {
+        $recordId = $this->getRecordId($type);
+        $domainInfo = $this->analysisDomain();
+        if ($recordId && $domainInfo) {
+            return $this->send('UpdateDomainRecord', ['RR' => $domainInfo[1], 'RecordId' => $recordId[0], 'Type' => $type, 'Value' => $ip]);
+        }
+
+        return false;
+    }
+
+    /**
+     * 域名信息
+     *
+     * @param  string|null  $type  记录类型,默认为 null
+     * @return array|false
+     */
+    private function getRecordId($type = null)
+    {
+        $parameters = ['SubDomain' => self::$subDomain];
+        if ($type) {
+            $parameters['Type'] = $type;
+        }
+        $records = $this->send('DescribeSubDomainRecords', $parameters)['DomainRecords']['Record'];
+
+        if ($records) {
+            $data = null;
+            foreach ($records as $record) {
+                $data[] = $record['RecordId'];
+            }
+
+            return $data ?: false;
+        }
+
+        return false;
+    }
+
+    public function destroy($type)
+    {
+        $records = $this->getRecordId($type);
+        if ($records) {
+            $count = 0;
+            foreach ($records as $record) {
+                $result = $this->send('DeleteDomainRecord', ['RecordId' => $record]);
+                if ($result) {
+                    $count++;
+                }
+            }
+
+            return $count;
+        }
+
+        return false;
+    }
+
+}

+ 139 - 0
app/Components/DDNS/Namesilo.php

@@ -0,0 +1,139 @@
+<?php
+
+namespace App\Components\DDNS;
+
+use Arr;
+use Log;
+
+class Namesilo
+{
+    private static $subDomain;
+
+    public function __construct($subDomain)
+    {
+        self::$subDomain = $subDomain;
+    }
+
+    public function store($ip, $type = 'A')
+    {
+        $domainInfo = $this->analysisDomain();
+        if ($domainInfo) {
+            return $this->send('dnsAddRecord', [
+                'domain'  => $domainInfo[0],
+                'rrtype'  => $type,
+                'rrhost'  => $domainInfo[1],
+                'rrvalue' => $ip,
+                'rrttl'   => 3600,
+            ]);
+        }
+
+        return false;
+    }
+
+    private function analysisDomain()
+    {
+        // TODO: 尚未进行,多域名环境下,获取信息测试
+        $domainList = $this->domainList();
+        if ($domainList) {
+            foreach ($domainList as $domain) {
+                if (strpos(self::$subDomain, $domain) !== false) {
+                    return [$domain, rtrim(substr(self::$subDomain, 0, -(strlen($domain))), '.')];
+                }
+            }
+        }
+
+        return false;
+    }
+
+    public function domainList()
+    {
+        $data = $this->send('listDomains');
+        if ($data) {
+            return $data['domains'];
+        }
+
+        return false;
+    }
+
+    private function send($operation, $data = [])
+    {
+        $params = [
+            'version' => 1,
+            'type'    => 'xml',
+            'key'     => sysConfig('ddns_key'),
+        ];
+        $query = array_merge($params, $data);
+
+        $result = file_get_contents('https://www.namesilo.com/api/'.$operation.'?'.http_build_query($query));
+        $result = json_decode(json_encode(simplexml_load_string(trim($result))), true);
+
+        if ($result && $result['reply']['code'] === '300' && $result['reply']['detail'] === 'success') {
+            return $result['reply'];
+        }
+
+        Log::error('[Namesilo API] - ['.$operation.'] 请求失败:'.var_export($result, true));
+
+        return false;
+    }
+
+    public function update($ip, $type)
+    {
+        $recordId = $this->getRecordId($type);
+        $domainInfo = $this->analysisDomain();
+
+        return $this->send('dnsUpdateRecord', [
+            'domain'  => $domainInfo[0],
+            'rrid'    => $recordId[0],
+            'rrhost'  => $domainInfo[1],
+            'rrvalue' => $ip,
+            'rrttl'   => 3600,
+        ]);
+    }
+
+    private function getRecordId($type = null)
+    {
+        $domainInfo = $this->analysisDomain();
+        if ($domainInfo) {
+            $records = $this->send('dnsListRecords', ['domain' => $domainInfo[0]]);
+
+            if ($records && Arr::has($records, 'resource_record')) {
+                $records = $records['resource_record'];
+                $data = null;
+                foreach ($records as $record) {
+                    if (Arr::has($record, ['host', 'type', 'record_id']) && $record['host'] === self::$subDomain) {
+                        if ($type) {
+                            if ($type === $record['type']) {
+                                $data[] = $record['record_id'];
+                            }
+                        } else {
+                            $data[] = $record['record_id'];
+                        }
+                    }
+                }
+
+                return $data ?: false;
+            }
+        }
+
+        return false;
+    }
+
+    public function destory($type)
+    {
+        $records = $this->getRecordId($type);
+        $domainInfo = $this->analysisDomain();
+        if ($records && $domainInfo) {
+            $count = 0;
+            foreach ($records as $record) {
+                $result = $this->send('dnsDeleteRecord', ['domain' => $domainInfo[0], 'rrid' => $record]);
+                if ($result) {
+                    $count++;
+                }
+            }
+
+            return $count;
+        }
+
+        return false;
+    }
+}

+ 2 - 3
app/Components/Helpers.php

@@ -170,19 +170,18 @@ class Helpers
      * @param  string  $content  内容
      * @param  int  $type  发送类型
      * @param  string  $address  收信方
-     * @param  int  $status  投递状态
      * @param  string  $error  投递失败时记录的异常信息
      *
      * @return int
      */
-    public static function addNotificationLog(string $title, string $content, int $type, $address = 'admin', $status = 1, $error = ''): int
+    public static function addNotificationLog(string $title, string $content, int $type, $address = 'admin', $error = ''): int
     {
         $log = new NotificationLog();
         $log->type = $type;
         $log->address = $address;
         $log->title = $title;
         $log->content = $content;
-        $log->status = $status;
+        $log->status = 0;
         $log->error = $error;
         $log->save();
 

+ 0 - 77
app/Components/Namesilo.php

@@ -1,77 +0,0 @@
-<?php
-
-namespace App\Components;
-
-use Http;
-use Log;
-use LSS\XML2Array;
-
-class Namesilo
-{
-    private static $host = 'https://www.namesilo.com/api/';
-
-    // 列出账号下所有域名 Todo Debug测试
-    public function listDomains()
-    {
-        return $this->send('listDomains');
-    }
-
-    // 发送请求
-    private function send($operation, $data = [])
-    {
-        $params = [
-            'version' => 1,
-            'type'    => 'xml',
-            'key'     => sysConfig('namesilo_key'),
-        ];
-        $query = array_merge($params, $data);
-
-        $content = '请求操作:['.$operation.'] --- 请求数据:['.http_build_query($query).']';
-
-        $response = Http::timeout(15)->get(self::$host.$operation.'?'.http_build_query($query));
-        if ($response->failed()) {
-            Log::error('[Namesilo]请求失败:'.var_export($response, true));
-            Helpers::addNotificationLog('[Namesilo API] - ['.$operation.']', $content, 1, sysConfig('webmaster_email'),
-                0, var_export($response, true));
-
-            return false;
-        }
-
-        $result = XML2Array::createArray($response->json());
-
-        // 出错
-        if (empty($result['namesilo']) || $result['namesilo']['reply']['code'] !== 300 || $result['namesilo']['reply']['detail'] !== 'success') {
-            Helpers::addNotificationLog('[Namesilo API] - ['.$operation.']', $content, 1,
-                sysConfig('webmaster_email'), 0, $result['namesilo']['reply']['detail']);
-        } else {
-            Helpers::addNotificationLog('[Namesilo API] - ['.$operation.']', $content, 1,
-                sysConfig('webmaster_email'), 1, $result['namesilo']['reply']['detail']);
-        }
-
-        return $result['namesilo']['reply'];
-    }
-
-    // 列出指定域名的所有DNS记录
-    public function dnsListRecords($domain)
-    {
-        return $this->send('dnsListRecords', ['domain' => $domain]);
-    }
-
-    // 为指定域名添加DNS记录
-    public function dnsAddRecord($domain, $host, $value, $type = 'A', $ttl = 7207)
-    {
-        return $this->send('dnsAddRecord', ['domain' => $domain, 'rrtype' => $type, 'rrhost' => $host, 'rrvalue' => $value, 'rrttl' => $ttl]);
-    }
-
-    // 更新DNS记录
-    public function dnsUpdateRecord($domain, $id, $host, $value, $ttl = 7207)
-    {
-        return $this->send('dnsUpdateRecord', ['domain' => $domain, 'rrid' => $id, 'rrhost' => $host, 'rrvalue' => $value, 'rrttl' => $ttl]);
-    }
-
-    // 删除DNS记录
-    public function dnsDeleteRecord($domain, $id)
-    {
-        return $this->send('dnsDeleteRecord', ['domain' => $domain, 'rrid' => $id]);
-    }
-}

+ 18 - 4
app/Components/PushNotification.php

@@ -3,6 +3,7 @@
 
 namespace App\Components;
 
+use Cache;
 use Http;
 use Log;
 
@@ -30,8 +31,21 @@ class PushNotification
      */
     private static function ServerChan(string $title, string $content)
     {
-        // TODO:一天仅可发送不超过500条
-        $response = Http::timeout(15)->get('https://sc.ftqq.com/'.sysConfig('server_chan_key').'.send?text='.$title.'&desp='.urlencode($content));
+        $cacheKey = 'serverChanCount'.date('d');
+        if (Cache::has($cacheKey)) {
+            Cache::increment($cacheKey);
+        } else {
+            Cache::put($cacheKey, 1, Day); // 24小时
+        }
+
+        // 一天仅可发送不超过500条
+        if (Cache::get($cacheKey) < 500) {
+            $response = Http::timeout(15)->get('https://sc.ftqq.com/'.sysConfig('server_chan_key').'.send?text='.$title.'&desp='.urlencode($content));
+        } else {
+            Log::error('ServerChan消息推送异常:今日500条限额已耗尽!');
+
+            return false;
+        }
 
         // 发送成功
         if ($response->ok()) {
@@ -42,7 +56,7 @@ class PushNotification
                 return $message;
             }
             // 发送失败
-            Helpers::addNotificationLog($title, $content, 2, 'admin', -1, $message ? $message['errmsg'] : '未知');
+            Helpers::addNotificationLog($title, $content, 2, 'admin', $message ? $message['errmsg'] : '未知');
 
             return false;
         }
@@ -73,7 +87,7 @@ class PushNotification
                 return $message;
             }
             // 发送失败
-            Helpers::addNotificationLog($title, $content, 3, 'admin', -1, $message);
+            Helpers::addNotificationLog($title, $content, 3, 'admin', $message);
 
             return false;
         }

+ 0 - 2
app/Http/Controllers/Admin/NodeController.php

@@ -71,7 +71,6 @@ class NodeController extends Controller
     // 添加节点
     public function store(NodeRequest $request): JsonResponse
     {
-        // TODO:判断是否已存在绑定了相同域名的节点,提示是否要强制替换,或者不提示之前强制将其他节点的绑定域名置为空,然后发起域名绑定请求,或者请求进入队列
         try {
             $node = Node::create($request->except('_token', 'labels'));
 
@@ -115,7 +114,6 @@ class NodeController extends Controller
                 (new NodeService())->makeLabels($node->id, $request->input('labels'));
             }
 
-            // TODO:更新节点绑定的域名DNS(将节点IP更新到域名DNS 的A记录)
             if ($node->update($request->except('_token', 'labels'))) {
                 return Response::json(['status' => 'success', 'message' => '编辑成功']);
             }

+ 1 - 1
app/Http/Controllers/Admin/SystemController.php

@@ -148,7 +148,7 @@ class SystemController extends Controller
                 'max_rand_traffic',
                 'push_bear_send_key',
                 'push_bear_qrcode',
-                'is_forbid_china',
+                'forbid_mode',
                 'website_security_code',
             ];
 

+ 23 - 10
app/Http/Middleware/isForbidden.php

@@ -45,20 +45,33 @@ class isForbidden
             return Response::view('auth.error', ['message' => trans('error.ForbiddenAccess')], 403);
         }
 
-        if (!in_array($ipLocation['country'], ['本机地址', '局域网'])) {
+        if (!in_array($ipLocation['country'], ['本机地址', '局域网']) && sysConfig('forbid_mode')) {
             // 拒绝大陆IP访问
-            if (sysConfig('is_forbid_china') && in_array($ipLocation['country'], ['China', '中国'])
-                && !in_array($ipLocation['province'], ['香港', '澳门', '台湾', '台湾省'])) {
-                Log::info('识别到大陆IP,拒绝访问:'.$ip);
+            switch (sysConfig('forbid_mode')) {
+                case 'ban_mainland':
+                    if (in_array($ipLocation['country'], ['China', '中国']) && !in_array($ipLocation['province'], ['香港', '澳门', '台湾', '台湾省'])) {
+                        Log::info('识别到大陆IP,拒绝访问:'.$ip);
 
-                return Response::view('auth.error', ['message' => trans('error.ForbiddenChina')], 403);
-            }
+                        return Response::view('auth.error', ['message' => trans('error.ForbiddenChina')], 403);
+                    }
+                    break;
+                case 'ban_china':
+                    if (in_array($ipLocation['country'], ['China', '中国', 'Taiwan', 'Hong Kong', 'Macao'])) {
+                        Log::info('识别到中国IP,拒绝访问:'.$ip);
 
-            // 拒绝非大陆IP访问
-            if (sysConfig('is_forbid_oversea') && !in_array($ipLocation['country'], ['China', '中国', 'Taiwan', 'Hong Kong', 'Macao'])) {
-                Log::info('识别到海外IP,拒绝访问:'.$ip.' - '.$ipLocation['country']);
+                        return Response::view('auth.error', ['message' => trans('error.ForbiddenChina')], 403);
+                    }
+                    break;
+                case 'ban_oversea':
+                    if (!in_array($ipLocation['country'], ['China', '中国', 'Taiwan', 'Hong Kong', 'Macao'])) {
+                        Log::info('识别到海外IP,拒绝访问:'.$ip.' - '.$ipLocation['country']);
 
-                return Response::view('auth.error', ['message' => trans('error.ForbiddenOversea')], 403);
+                        return Response::view('auth.error', ['message' => trans('error.ForbiddenOversea')], 403);
+                    }
+                    break;
+                default:
+                    Log::error('未知禁止访问模式!请在系统设置中修改【禁止访问模式】!');
+                    break;
             }
         }
 

+ 1 - 1
app/Http/Requests/Admin/NodeRequest.php

@@ -19,7 +19,7 @@ class NodeRequest extends FormRequest
             'speed_limit'    => 'required|numeric|min:0',
             'client_limit'   => 'required|numeric|min:0',
             'port'           => 'nullable|numeric|between:0,65535',
-            'ip'             => 'ipv4',
+            'ip'             => 'ipv4|required_if:is_ddns,0|nullable',
             'ipv6'           => 'nullable|ipv6',
             'relay_server'   => 'required_if:is_relay,1',
             'relay_port'     => 'required_if:is_relay,1|numeric|between:0,65535',

+ 49 - 0
app/Observers/NodeObserver.php

@@ -2,12 +2,14 @@
 
 namespace App\Observers;
 
+use App\Components\DDNS;
 use App\Jobs\VNet\reloadNode;
 use App\Models\Node;
 use App\Models\NodeAuth;
 use App\Models\RuleGroup;
 use App\Models\UserGroup;
 use App\Services\NodeService;
+use Arr;
 use Log;
 use Str;
 
@@ -27,10 +29,53 @@ class NodeObserver
         if (!$auth->save()) {
             Log::error('节点生成-自动生成授权时出现错误,请稍后自行生成授权!');
         }
+
+        if ($node->is_ddns == 0 && $node->server && sysConfig('ddns_mode')) {
+            if ($node->ip) {
+                DDNS::store($node->server, $node->ip);
+            }
+            if ($node->ipv6) {
+                DDNS::store($node->server, $node->ipv6, 'AAAA');
+            }
+        }
     }
 
     public function updated(Node $node): void
     {
+        if ($node->is_ddns == 0 && sysConfig('ddns_mode')) {
+            $changes = $node->getChanges();
+            if (Arr::hasAny($changes, ['ip', 'ipv6', 'server'])) {
+                if (Arr::exists($changes, 'server')) {
+                    DDNS::destory($node->getOriginal('server'));
+                    if ($node->ip) {
+                        DDNS::store($node->server, $node->ip);
+                    }
+                    if ($node->ipv6) {
+                        DDNS::store($node->server, $node->ipv6, 'AAAA');
+                    }
+                } else {
+                    if (Arr::exists($changes, 'ip')) {
+                        if ($node->ip && $node->getOriginal('ip')) {
+                            DDNS::update($node->server, $node->ip);
+                        } elseif ($node->ip) {
+                            DDNS::store($node->server, $node->ip);
+                        } else {
+                            DDNS::destory($node->server, 'A');
+                        }
+                    }
+                    if (Arr::exists($changes, 'ipv6')) {
+                        if ($node->ipv6 && $node->getOriginal('ipv6')) {
+                            DDNS::update($node->server, $node->ipv6, 'AAAA');
+                        } elseif ($node->ipv6) {
+                            DDNS::store($node->server, $node->ipv6, 'AAAA');
+                        } else {
+                            DDNS::destory($node->server, 'AAAA');
+                        }
+                    }
+                }
+            }
+        }
+
         if ($node->type === 4) {
             reloadNode::dispatchNow(Node::whereId($node->id)->get());
         }
@@ -66,5 +111,9 @@ class NodeObserver
                 $userGroup->save();
             }
         }
+
+        if ($node->is_ddns == 0 && $node->server && sysConfig('ddns_mode')) {
+            DDNS::destory($node->server);
+        }
     }
 }

+ 1 - 1
composer.json

@@ -12,6 +12,7 @@
     "ext-json": "*",
     "ext-mbstring": "*",
     "ext-openssl": "*",
+    "ext-simplexml": "*",
     "fideloper/proxy": "^4.2",
     "fruitcake/laravel-cors": "^2.0",
     "geoip2/geoip2": "^2.10",
@@ -23,7 +24,6 @@
     "laravel/tinker": "^2.0",
     "mews/captcha": "^3.1",
     "mews/purifier": "^3.3",
-    "openlss/lib-array2xml": "^1.0",
     "overtrue/laravel-lang": "^4.0",
     "phpoffice/phpspreadsheet": "^1.14",
     "rap2hpoutre/laravel-log-viewer": "^1.6",

+ 53 - 100
composer.lock

@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "24f73aa6d6cf6480b3991cd5070182a8",
+    "content-hash": "9e5eb2248177e1be57e3f9586f9447d2",
     "packages": [
         {
             "name": "asm89/stack-cors",
@@ -1241,16 +1241,16 @@
         },
         {
             "name": "laravel-lang/lang",
-            "version": "7.0.7",
+            "version": "7.0.8",
             "source": {
                 "type": "git",
                 "url": "https://github.com/Laravel-Lang/lang.git",
-                "reference": "7bed46cb9befef29660fb20f921a5e7b41aeaaa3"
+                "reference": "c1519eb78139869ab8829912adde5f58ca09552f"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/Laravel-Lang/lang/zipball/7bed46cb9befef29660fb20f921a5e7b41aeaaa3",
-                "reference": "7bed46cb9befef29660fb20f921a5e7b41aeaaa3",
+                "url": "https://api.github.com/repos/Laravel-Lang/lang/zipball/c1519eb78139869ab8829912adde5f58ca09552f",
+                "reference": "c1519eb78139869ab8829912adde5f58ca09552f",
                 "shasum": ""
             },
             "require": {
@@ -1278,7 +1278,7 @@
                 "laravel",
                 "lpm"
             ],
-            "time": "2020-10-02T16:55:34+00:00"
+            "time": "2020-10-11T08:55:55+00:00"
         },
         {
             "name": "laravel/framework",
@@ -1808,30 +1808,30 @@
         },
         {
             "name": "markbaker/complex",
-            "version": "1.5.0",
+            "version": "2.0.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/MarkBaker/PHPComplex.git",
-                "reference": "c3131244e29c08d44fefb49e0dd35021e9e39dd2"
+                "reference": "9999f1432fae467bc93c53f357105b4c31bb994c"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/MarkBaker/PHPComplex/zipball/c3131244e29c08d44fefb49e0dd35021e9e39dd2",
-                "reference": "c3131244e29c08d44fefb49e0dd35021e9e39dd2",
+                "url": "https://api.github.com/repos/MarkBaker/PHPComplex/zipball/9999f1432fae467bc93c53f357105b4c31bb994c",
+                "reference": "9999f1432fae467bc93c53f357105b4c31bb994c",
                 "shasum": ""
             },
             "require": {
-                "php": "^5.6.0|^7.0"
+                "php": "^7.2 || ^8.0"
             },
             "require-dev": {
-                "dealerdirect/phpcodesniffer-composer-installer": "^0.5.0",
+                "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
                 "phpcompatibility/php-compatibility": "^9.0",
                 "phpdocumentor/phpdocumentor": "2.*",
-                "phploc/phploc": "^4.0|^5.0|^6.0|^7.0",
+                "phploc/phploc": "^4.0",
                 "phpmd/phpmd": "2.*",
-                "phpunit/phpunit": "^4.8.35|^5.0|^6.0|^7.0",
-                "sebastian/phpcpd": "2.*",
-                "squizlabs/php_codesniffer": "^3.4.0"
+                "phpunit/phpunit": "^7.0 || ^8.0 || ^9.3",
+                "sebastian/phpcpd": "^4.0",
+                "squizlabs/php_codesniffer": "^3.4"
             },
             "type": "library",
             "autoload": {
@@ -1899,33 +1899,34 @@
                 "complex",
                 "mathematics"
             ],
-            "time": "2020-08-26T19:47:57+00:00"
+            "time": "2020-08-26T10:42:07+00:00"
         },
         {
             "name": "markbaker/matrix",
-            "version": "1.2.1",
+            "version": "2.0.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/MarkBaker/PHPMatrix.git",
-                "reference": "182d44c3b2e3b063468f7481ae3ef71c69dc1409"
+                "reference": "9567d9c4c519fbe40de01dbd1e4469dbbb66f46a"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/MarkBaker/PHPMatrix/zipball/182d44c3b2e3b063468f7481ae3ef71c69dc1409",
-                "reference": "182d44c3b2e3b063468f7481ae3ef71c69dc1409",
+                "url": "https://api.github.com/repos/MarkBaker/PHPMatrix/zipball/9567d9c4c519fbe40de01dbd1e4469dbbb66f46a",
+                "reference": "9567d9c4c519fbe40de01dbd1e4469dbbb66f46a",
                 "shasum": ""
             },
             "require": {
-                "php": "^5.6.0|^7.0.0"
+                "php": "^7.2 || ^8.0"
             },
             "require-dev": {
-                "dealerdirect/phpcodesniffer-composer-installer": "dev-master",
-                "phpcompatibility/php-compatibility": "dev-master",
-                "phploc/phploc": "^4",
-                "phpmd/phpmd": "dev-master",
-                "phpunit/phpunit": "^5.7|^6.0|7.0",
-                "sebastian/phpcpd": "^3.0",
-                "squizlabs/php_codesniffer": "^3.0@dev"
+                "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
+                "phpcompatibility/php-compatibility": "^9.0",
+                "phpdocumentor/phpdocumentor": "2.*",
+                "phploc/phploc": "^4.0",
+                "phpmd/phpmd": "2.*",
+                "phpunit/phpunit": "^7.0 || ^8.0 || ^9.3",
+                "sebastian/phpcpd": "^4.0",
+                "squizlabs/php_codesniffer": "^3.4"
             },
             "type": "library",
             "autoload": {
@@ -1958,7 +1959,7 @@
             "authors": [
                 {
                     "name": "Mark Baker",
-                    "email": "mark@lange.demon.co.uk"
+                    "email": "mark@demon-angel.eu"
                 }
             ],
             "description": "PHP Class for working with matrices",
@@ -1968,7 +1969,7 @@
                 "matrix",
                 "vector"
             ],
-            "time": "2020-08-28T19:41:55+00:00"
+            "time": "2020-08-28T17:11:00+00:00"
         },
         {
             "name": "maxmind-db/reader",
@@ -2413,16 +2414,16 @@
         },
         {
             "name": "nesbot/carbon",
-            "version": "2.41.0",
+            "version": "2.41.2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/briannesbitt/Carbon.git",
-                "reference": "8690b13ad4da6d54d692afea15aab30b36fee52e"
+                "reference": "35959c93ada06469107a05df6b15b65074a960cf"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/8690b13ad4da6d54d692afea15aab30b36fee52e",
-                "reference": "8690b13ad4da6d54d692afea15aab30b36fee52e",
+                "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/35959c93ada06469107a05df6b15b65074a960cf",
+                "reference": "35959c93ada06469107a05df6b15b65074a960cf",
                 "shasum": ""
             },
             "require": {
@@ -2498,7 +2499,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2020-10-04T09:11:05+00:00"
+            "time": "2020-10-10T23:35:06+00:00"
         },
         {
             "name": "nikic/php-parser",
@@ -2552,55 +2553,6 @@
             ],
             "time": "2020-09-26T10:30:38+00:00"
         },
-        {
-            "name": "openlss/lib-array2xml",
-            "version": "1.0.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/nullivex/lib-array2xml.git",
-                "reference": "a91f18a8dfc69ffabe5f9b068bc39bb202c81d90"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/nullivex/lib-array2xml/zipball/a91f18a8dfc69ffabe5f9b068bc39bb202c81d90",
-                "reference": "a91f18a8dfc69ffabe5f9b068bc39bb202c81d90",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.2"
-            },
-            "type": "library",
-            "autoload": {
-                "psr-0": {
-                    "LSS": ""
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "Apache-2.0"
-            ],
-            "authors": [
-                {
-                    "name": "Bryan Tong",
-                    "email": "bryan@nullivex.com",
-                    "homepage": "https://www.nullivex.com"
-                },
-                {
-                    "name": "Tony Butler",
-                    "email": "spudz76@gmail.com",
-                    "homepage": "https://www.nullivex.com"
-                }
-            ],
-            "description": "Array2XML conversion library credit to lalit.org",
-            "homepage": "https://www.nullivex.com",
-            "keywords": [
-                "array",
-                "array conversion",
-                "xml",
-                "xml conversion"
-            ],
-            "time": "2019-03-29T20:06:56+00:00"
-        },
         {
             "name": "opis/closure",
             "version": "3.5.7",
@@ -2773,16 +2725,16 @@
         },
         {
             "name": "phpoffice/phpspreadsheet",
-            "version": "1.14.1",
+            "version": "1.15.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/PHPOffice/PhpSpreadsheet.git",
-                "reference": "2383aad5689778470491581442aab38cec41bf1d"
+                "reference": "a8e8068b31b8119e1daa5b1eb5715a3a8ea8305f"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/2383aad5689778470491581442aab38cec41bf1d",
-                "reference": "2383aad5689778470491581442aab38cec41bf1d",
+                "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/a8e8068b31b8119e1daa5b1eb5715a3a8ea8305f",
+                "reference": "a8e8068b31b8119e1daa5b1eb5715a3a8ea8305f",
                 "shasum": ""
             },
             "require": {
@@ -2800,9 +2752,9 @@
                 "ext-zip": "*",
                 "ext-zlib": "*",
                 "maennchen/zipstream-php": "^2.1",
-                "markbaker/complex": "^1.4",
-                "markbaker/matrix": "^1.2",
-                "php": "^7.2",
+                "markbaker/complex": "^1.5|^2.0",
+                "markbaker/matrix": "^1.2|^2.0",
+                "php": "^7.2|^8.0",
                 "psr/http-client": "^1.0",
                 "psr/http-factory": "^1.0",
                 "psr/simple-cache": "^1.0"
@@ -2813,15 +2765,15 @@
                 "jpgraph/jpgraph": "^4.0",
                 "mpdf/mpdf": "^8.0",
                 "phpcompatibility/php-compatibility": "^9.3",
-                "phpunit/phpunit": "^8.5",
+                "phpunit/phpunit": "^8.5|^9.3",
                 "squizlabs/php_codesniffer": "^3.5",
                 "tecnickcom/tcpdf": "^6.3"
             },
             "suggest": {
-                "dompdf/dompdf": "Option for rendering PDF with PDF Writer",
+                "dompdf/dompdf": "Option for rendering PDF with PDF Writer (doesn't yet support PHP8)",
                 "jpgraph/jpgraph": "Option for rendering charts, or including charts with PDF or HTML Writers",
                 "mpdf/mpdf": "Option for rendering PDF with PDF Writer",
-                "tecnickcom/tcpdf": "Option for rendering PDF with PDF Writer"
+                "tecnickcom/tcpdf": "Option for rendering PDF with PDF Writer (doesn't yet support PHP8)"
             },
             "type": "library",
             "autoload": {
@@ -2865,7 +2817,7 @@
                 "xls",
                 "xlsx"
             ],
-            "time": "2020-07-19T09:51:35+00:00"
+            "time": "2020-10-11T13:20:59+00:00"
         },
         {
             "name": "phpoption/phpoption",
@@ -3862,12 +3814,12 @@
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/console.git",
-                "reference": "04c3a31fe8ea94b42c9e2d1acc93d19782133b00"
+                "reference": "ae789a8a2ad189ce7e8216942cdb9b77319f5eb8"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/console/zipball/04c3a31fe8ea94b42c9e2d1acc93d19782133b00",
-                "reference": "04c3a31fe8ea94b42c9e2d1acc93d19782133b00",
+                "url": "https://api.github.com/repos/symfony/console/zipball/ae789a8a2ad189ce7e8216942cdb9b77319f5eb8",
+                "reference": "ae789a8a2ad189ce7e8216942cdb9b77319f5eb8",
                 "shasum": ""
             },
             "require": {
@@ -10444,7 +10396,8 @@
         "php": "^7.2.5",
         "ext-json": "*",
         "ext-mbstring": "*",
-        "ext-openssl": "*"
+        "ext-openssl": "*",
+        "ext-simplexml": "*"
     },
     "platform-dev": [],
     "plugin-api-version": "1.1.0"

+ 46 - 0
database/migrations/2020_10_11_000217_add_ddns_to_config_table.php

@@ -0,0 +1,46 @@
+<?php
+
+use App\Models\Config;
+use Illuminate\Database\Migrations\Migration;
+
+class AddDdnsToConfigTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+
+    private static $dropConfigs = [
+        'is_user_rand_port', 'is_namesilo', 'namesilo_key', 'is_forbid_china', 'is_forbid_oversea',
+        'alipay_private_key', 'alipay_public_key', 'alipay_transport', 'alipay_currency',
+    ];
+
+    private static $newConfigs = ['forbid_mode', 'ddns_mode', 'ddns_key', 'ddns_secret'];
+
+
+    public function up()
+    {
+        foreach (self::$newConfigs as $config) {
+            Config::insert(['name' => $config]);
+        }
+        foreach (self::$dropConfigs as $config) {
+            Config::destroy(['name' => $config]);
+        }
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        foreach (self::$newConfigs as $config) {
+            Config::destroy(['name' => $config]);
+        }
+        foreach (self::$dropConfigs as $config) {
+            Config::insert(['name' => $config]);
+        }
+    }
+}

+ 124 - 253
resources/views/admin/config/system.blade.php

@@ -75,9 +75,7 @@
                                                 <div class="input-group">
                                                     <input type="text" class="form-control" id="website_name" value="{{$website_name}}"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="update('website_name')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="update('website_name')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -91,9 +89,7 @@
                                                 <div class="input-group">
                                                     <input type="url" class="form-control" id="website_url" value="{{$website_url}}"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="update('website_url')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="update('website_url')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -107,9 +103,7 @@
                                                 <div class="input-group">
                                                     <input type="email" class="form-control" id="AppStore_id" value="{{$AppStore_id}}"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="update('AppStore_id')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="update('AppStore_id')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -123,9 +117,7 @@
                                                 <div class="input-group">
                                                     <input type="password" class="form-control" id="AppStore_password" value="{{$AppStore_password}}"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="update('AppStore_password')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="update('AppStore_password')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -139,9 +131,7 @@
                                                 <div class="input-group">
                                                     <input type="email" class="form-control" id="webmaster_email" value="{{$webmaster_email}}"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="update('webmaster_email')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="update('webmaster_email')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -155,33 +145,27 @@
                                                 <div class="input-group">
                                                     <input type="text" class="form-control" id="website_security_code" value="{{$website_security_code}}"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-info" type="button" onclick="makeWebsiteSecurityCode()">
-                                                            生成
-                                                        </button>
-                                                        <button class="btn btn-primary" type="button" onclick="update('website_security_code')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-info" type="button" onclick="makeWebsiteSecurityCode()">生成</button>
+                                                        <button class="btn btn-primary" type="button" onclick="update('website_security_code')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
-                                            <span class="text-help offset-md-3">非空时必须通过<a href="/login?securityCode=" target="_blank">安全入口</a>
-                                                                                加上安全码才可访问</span>
-                                        </div>
-                                    </div>
-                                    <div class="form-group col-lg-6">
-                                        <div class="row">
-                                            <label class="col-md-3 col-form-label" for="is_forbid_china">阻止大陆访问</label>
-                                            <span class="col-md-9"><input type="checkbox" id="is_forbid_china" data-plugin="switchery" @if($is_forbid_china) checked
-                                                                          @endif onchange="updateFromOther('switch','is_forbid_china')"></span>
-                                            <span class="text-help offset-md-3"> 开启后大陆IP禁止访问 </span>
+                                            <span class="text-help offset-md-3">
+                                                非空时必须通过<a href="{{route('login')}}?securityCode=" target="_blank">安全入口</a>加上安全码才可访问
+                                            </span>
                                         </div>
                                     </div>
                                     <div class="form-group col-lg-6">
                                         <div class="row">
-                                            <label class="col-md-3 col-form-label" for="is_forbid_oversea">阻止海外访问</label>
-                                            <span class="col-md-9"><input type="checkbox" id="is_forbid_oversea" data-plugin="switchery" @if($is_forbid_oversea) checked
-                                                                          @endif onchange="updateFromOther('switch','is_forbid_oversea')"></span>
-                                            <span class="text-help offset-md-3"> 开启后海外IP(含港澳台)禁止访问 </span>
+                                            <label class="col-md-3 col-form-label" for="forbid_mode">禁止访问模式</label>
+                                            <select class="col-md-4" id="forbid_mode" data-plugin="selectpicker" data-style="btn-outline btn-primary"
+                                                    onchange="updateFromOther('select','forbid_mode')">
+                                                <option value="">关闭</option>
+                                                <option value="ban_mainland">阻拦大陆</option>
+                                                <option value="ban_china">阻拦中国</option>
+                                                <option value="ban_oversea">阻拦海外</option>
+                                            </select>
+                                            <span class="text-help offset-md-3"> 依据IP对对应地区进行阻拦,非阻拦地区可正常访问 </span>
                                         </div>
                                     </div>
                                     <div class="form-group col-lg-6">
@@ -207,9 +191,7 @@
                                                 <div class="input-group">
                                                     <input type="datetime-local" class="form-control" id="maintenance_time" value="{{$maintenance_time}}"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="update('maintenance_time')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="update('maintenance_time')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -223,9 +205,7 @@
                                                 <div class="input-group">
                                                     <textarea class="form-control" rows="3" id="maintenance_content">{{$maintenance_content}}</textarea>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="update('maintenance_content')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="update('maintenance_content')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -239,9 +219,7 @@
                                                 <div class="input-group">
                                                     <input type="text" class="form-control" id="redirect_url" value="{{$redirect_url}}"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="update('redirect_url')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="update('redirect_url')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -326,14 +304,6 @@
                                             <span class="text-help offset-md-3"> 端口范围:1000 - 65535 </span>
                                         </div>
                                     </div>
-                                    <div class="form-group col-lg-6">
-                                        <div class="row">
-                                            <label class="col-md-3 col-form-label" for="is_user_rand_port">自定义端口</label>
-                                            <span class="col-md-9"><input type="checkbox" id="is_user_rand_port" data-plugin="switchery" @if($is_user_rand_port) checked
-                                                                          @endif onchange="updateFromOther('switch','is_user_rand_port')"></span>
-                                            <span class="text-help offset-md-3"> 用户可以自定义端口 </span>
-                                        </div>
-                                    </div>
                                     <div class="form-group col-lg-6">
                                         <div class="row">
                                             <label class="col-md-3 col-form-label" for="default_days">初始有效期</label>
@@ -342,9 +312,7 @@
                                                     <input type="number" class="form-control" id="default_days" value="{{$default_days}}"/>
                                                     <div class="input-group-append">
                                                         <span class="input-group-text">天</span>
-                                                        <button class="btn btn-primary" type="button" onclick="updateFromInput('default_days','0')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="updateFromInput('default_days','0')">修改</button>
                                                     </div>
                                                 </div>
                                             </div>
@@ -359,9 +327,7 @@
                                                     <input type="number" class="form-control" id="default_traffic" value="{{$default_traffic}}"/>
                                                     <div class="input-group-append">
                                                         <span class="input-group-text">MB</span>
-                                                        <button class="btn btn-primary" type="button" onclick="updateFromInput('default_traffic','0')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="updateFromInput('default_traffic','0')">修改</button>
                                                     </div>
                                                 </div>
                                             </div>
@@ -375,9 +341,7 @@
                                                 <div class="input-group">
                                                     <input type="number" class="form-control" id="invite_num" value="{{$invite_num}}"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="updateFromInput('invite_num','0')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="updateFromInput('invite_num','0')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -391,9 +355,7 @@
                                                 <div class="input-group">
                                                     <input type="number" class="form-control" id="reset_password_times" value="{{$reset_password_times}}"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="updateFromInput('reset_password_times','0')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="updateFromInput('reset_password_times','0')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -409,8 +371,8 @@
                                                 <option value="1">黑名单</option>
                                                 <option value="2">白名单</option>
                                             </select>
-                                            <span class="text-help offset-md-3"> 黑名单: 用户可使用任意黑名单外的邮箱注册;白名单:
-                                                                                 用户只能选择使用白名单中的邮箱后缀注册 </span>
+                                            <span class="text-help offset-md-3">
+                                                黑名单: 用户可使用任意黑名单外的邮箱注册;白名单:用户只能选择使用白名单中的邮箱后缀注册 </span>
                                         </div>
                                     </div>
                                     <div class="form-group col-lg-6">
@@ -420,9 +382,7 @@
                                                 <div class="input-group">
                                                     <input type="number" class="form-control" id="active_times" value="{{$active_times}}"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="updateFromInput('active_times','0')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="updateFromInput('active_times','0')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -436,9 +396,7 @@
                                                 <div class="input-group">
                                                     <input type="number" class="form-control" id="register_ip_limit" value="{{$register_ip_limit}}"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="updateFromInput('register_ip_limit','0')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="updateFromInput('register_ip_limit','0')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -453,9 +411,7 @@
                                                     <input type="number" class="form-control" id="user_invite_days" value="{{$user_invite_days}}"/>
                                                     <div class="input-group-append">
                                                         <span class="input-group-text">天</span>
-                                                        <button class="btn btn-primary" type="button" onchange="updateFromOther('user_invite_days','1',false)">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onchange="updateFromOther('user_invite_days','1',false)">修改</button>
                                                     </div>
                                                 </div>
                                             </div>
@@ -471,9 +427,7 @@
                                                     <div class="input-group-append">
                                                         <span class="input-group-text">天</span>
                                                     </div>
-                                                    <button class="btn btn-primary" type="button" onclick="updateFromInput('admin_invite_days','1',false)">
-                                                        修改
-                                                    </button>
+                                                    <button class="btn btn-primary" type="button" onclick="updateFromInput('admin_invite_days','1',false)">修改</button>
                                                 </div>
                                             </div>
                                             <span class="text-help offset-md-3"> 管理员生成邀请码的有效期 </span>
@@ -492,9 +446,7 @@
                                                 <div class="input-group">
                                                     <input type="url" class="form-control" id="subscribe_domain" value="{{$subscribe_domain}}"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="update('subscribe_domain')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="update('subscribe_domain')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -509,9 +461,7 @@
                                                 <div class="input-group">
                                                     <input type="number" class="form-control" id="subscribe_max" value="{{$subscribe_max}}"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="updateFromInput('subscribe_max','0')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="updateFromInput('subscribe_max','0')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -551,14 +501,11 @@
                                                 <div class="input-group">
                                                     <input type="text" class="form-control" id="web_api_url" value="{{$web_api_url}}"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="update('web_api_url')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="update('web_api_url')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
-                                            <span class="text-help offset-md-3"> 用于 VNet后端
-                                                                                 授权,此域名需要解析A记录到面板,例:https://demo.proxypanel.ml</span>
+                                            <span class="text-help offset-md-3">用于 VNet后端授权,此域名需要解析A记录到面板,例:https://demo.proxypanel.ml</span>
                                         </div>
                                     </div>
                                     <div class="form-group col-lg-6">
@@ -568,9 +515,7 @@
                                                 <div class="input-group">
                                                     <input type="text" class="form-control" id="v2ray_license" value="{{$v2ray_license}}"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="update('v2ray_license')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="update('v2ray_license')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -583,9 +528,7 @@
                                                 <div class="input-group">
                                                     <input type="text" class="form-control" id="trojan_license" value="{{$trojan_license}}"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="update('trojan_license')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="update('trojan_license')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -593,15 +536,12 @@
                                     </div>
                                     <div class="form-group col-lg-6">
                                         <div class="row">
-                                            <label class="col-md-3 col-form-label" for="v2ray_tls_provider">V2Ray
-                                                TLS配置</label>
+                                            <label class="col-md-3 col-form-label" for="v2ray_tls_provider">V2Ray TLS配置</label>
                                             <div class="col-md-7">
                                                 <div class="input-group">
                                                     <input type="text" class="form-control" id="v2ray_tls_provider" value="{{$v2ray_tls_provider}}"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="update('v2ray_tls_provider')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="update('v2ray_tls_provider')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -616,33 +556,45 @@
                                 <div class="form-row">
                                     <div class="form-group col-lg-6">
                                         <div class="row">
-                                            <label class="col-md-3 col-form-label" for="is_namesilo">Namesilo</label>
-                                            <span class="col-md-9"><input type="checkbox" id="is_namesilo" data-plugin="switchery" @if($is_namesilo) checked
-                                                                          @endif onchange="updateFromOther('switch','is_namesilo')"></span>
-                                            <span class="text-help offset-md-3">
-                                                添加、编辑节点的绑定域名时自动更新域名DNS记录值为节点IP(<a href="https://www.namesilo.com/account_api.php?rid=326ec20pa" target="_blank">创建API
-                                                                                                                                                                KEY</a>)</span>
+                                            <label class="col-md-3 col-form-label" for="ddns_mode">DDNS模式</label>
+                                            <select class="col-md-4" id="ddns_mode" data-plugin="selectpicker" data-style="btn-outline btn-primary"
+                                                    onchange="updateFromOther('select','ddns_mode')">
+                                                <option value="">关闭</option>
+                                                <option value="namesilo">Namesilo</option>
+                                                <option value="aliyun">阿里云(国际&国内)</option>
+                                            </select>
+                                            <span class="text-help offset-md-3"> 添加/编辑/删除节点的【域名、ipv4、ipv6】时,自动更新对应内容至DNS服务商 </span>
                                         </div>
                                     </div>
                                     <div class="form-group col-lg-6">
                                         <div class="row">
-                                            <label class="col-md-3 col-form-label" for="namesilo_key">Namesilo API
-                                                KEY</label>
+                                            <label class="col-md-3 col-form-label" for="ddns_key">服务商Key</label>
                                             <div class="col-md-7">
                                                 <div class="input-group">
-                                                    <input type="text" class="form-control" id="namesilo_key" value="{{$namesilo_key}}" placeholder="填入Namesilo上申请的API KEY"/>
+                                                    <input type="text" class="form-control" id="ddns_key" value="{{$ddns_key}}"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="update('namesilo_key')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="update('ddns_key')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
                                             <span class="text-help offset-md-3">
-                                                域名必须是<a href="https://www.namesilo.com/?rid=326ec20pa" target="_blank">www.namesilo.com</a>上购买的
+                                                浏览<a href="https://proxypanel.gitbook.io/wiki/ddns" target="_blank">设置指南</a>来设置
                                             </span>
                                         </div>
                                     </div>
+                                    <div class="form-group col-lg-6">
+                                        <div class="row">
+                                            <label class="col-md-3 col-form-label" for="ddns_secret">服务商Secret</label>
+                                            <div class="col-md-7">
+                                                <div class="input-group">
+                                                    <input type="text" class="form-control" id="ddns_secret" value="{{$ddns_secret}}"/>
+                                                    <span class="input-group-append">
+                                                        <button class="btn btn-primary" type="button" onclick="update('ddns_secret')">修改</button>
+                                                    </span>
+                                                </div>
+                                            </div>
+                                        </div>
+                                    </div>
                                     <div class="form-group col-lg-6">
                                         <div class="row">
                                             <label class="col-md-3 col-form-label" for="is_captcha">验证码</label>
@@ -663,28 +615,23 @@
                                                 <div class="input-group">
                                                     <input type="text" class="form-control" id="geetest_id" value="{{$geetest_id}}"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="update('geetest_id')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="update('geetest_id')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
-                                            <span class="text-help offset-md-3"> 本功能需要
-                                                <a href="https://auth.geetest.com/login/" target="_blank">极验后台</a>
-                                                                                 申请权限及应用
+                                            <span class="text-help offset-md-3">
+                                                本功能需要<a href="https://auth.geetest.com/login/" target="_blank">极验后台</a>申请权限及应用
                                             </span>
                                         </div>
                                     </div>
                                     <div class="form-group col-lg-6">
                                         <div class="row">
-                                            <label class="col-md-3 col-form-label" for="geetest_key">极验KEY</label>
+                                            <label class="col-md-3 col-form-label" for="geetest_key">极验Key</label>
                                             <div class="col-md-7">
                                                 <div class="input-group">
                                                     <input type="text" class="form-control" id="geetest_key" value="{{$geetest_key}}"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="update('geetest_key')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="update('geetest_key')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -704,8 +651,7 @@
                                                 </div>
                                             </div>
                                             <span class="text-help offset-md-3">
-                                                本功能需要
-                                                <a href="https://www.google.com/recaptcha/admin" target="_blank">GooglereCAPTCHA后台</a>
+                                                本功能需要<a href="https://www.google.com/recaptcha/admin" target="_blank">GooglereCAPTCHA后台</a>
                                                 申请权限及应用 (申请需科学上网,日常验证不用)</span>
                                         </div>
                                     </div>
@@ -732,9 +678,7 @@
                                                 <div class="input-group">
                                                     <input type="text" class="form-control" id="hcaptcha_secret" value="{{$hcaptcha_secret}}"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="update('hcaptcha_secret')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="update('hcaptcha_secret')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -751,9 +695,7 @@
                                                 <div class="input-group">
                                                     <input type="text" class="form-control" id="hcaptcha_sitekey" value="{{$hcaptcha_sitekey}}"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="update('hcaptcha_sitekey')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="update('hcaptcha_sitekey')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -781,9 +723,7 @@
                                                     <input type="number" class="form-control" id="traffic_limit_time" value="{{$traffic_limit_time}}"/>
                                                     <div class="input-group-append">
                                                         <span class="input-group-text">分钟</span>
-                                                        <button class="btn btn-primary" type="button" onclick="updateFromInput('traffic_limit_time','0')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="updateFromInput('traffic_limit_time','0')">修改</button>
                                                     </div>
                                                 </div>
                                             </div>
@@ -849,9 +789,7 @@
                                                     <input type="number" class="form-control" id="referral_traffic" value="{{$referral_traffic}}"/>
                                                     <div class="input-group-append">
                                                         <span class="input-group-text">MB</span>
-                                                        <button class="btn btn-primary" type="button" onclick="updateFromInput('referral_traffic','0')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="updateFromInput('referral_traffic','0')">修改</button>
                                                     </div>
                                                 </div>
                                             </div>
@@ -866,9 +804,7 @@
                                                     <input type="number" class="form-control" id="referral_percent" value="{{$referral_percent * 100}}"/>
                                                     <div class="input-group-append">
                                                         <span class="input-group-text">%</span>
-                                                        <button class="btn btn-primary" type="button" onclick="updateFromInput('referral_percent','0','100')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="updateFromInput('referral_percent','0','100')">修改</button>
                                                     </div>
                                                 </div>
                                             </div>
@@ -883,9 +819,7 @@
                                                     <input type="number" class="form-control" id="referral_money" value="{{$referral_money}}"/>
                                                     <div class="input-group-append">
                                                         <span class="input-group-text">元</span>
-                                                        <button class="btn btn-primary" type="button" onclick="updateFromInput('referral_money','0')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="updateFromInput('referral_money','0')">修改</button>
                                                     </div>
                                                 </div>
                                             </div>
@@ -916,9 +850,7 @@
                                                     <input type="number" class="form-control" id="expire_days" value="{{$expire_days}}"/>
                                                     <div class="input-group-append">
                                                         <span class="input-group-text">天</span>
-                                                        <button class="btn btn-primary" type="button" onclick="updateFromInput('expire_days','0')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="updateFromInput('expire_days','0')">修改</button>
                                                     </div>
                                                 </div>
                                             </div>
@@ -942,9 +874,7 @@
                                                     <input type="number" class="form-control" id="traffic_warning_percent" value="{{$traffic_warning_percent}}"/>
                                                     <div class="input-group-append">
                                                         <span class="input-group-text">%</span>
-                                                        <button class="btn btn-primary" type="button" onclick="updateFromInput('traffic_warning_percent','0')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="updateFromInput('traffic_warning_percent','0')">修改</button>
                                                     </div>
                                                 </div>
                                             </div>
@@ -968,9 +898,7 @@
                                                     <input type="number" class="form-control" id="offline_check_times" value="{{$offline_check_times}}"/>
                                                     <div class="input-group-append">
                                                         <span class="input-group-text">次</span>
-                                                        <button class="btn btn-primary" type="button" onclick="updateFromInput('offline_check_times','0','60')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="updateFromInput('offline_check_times','0','60')">修改</button>
                                                     </div>
                                                 </div>
                                             </div>
@@ -993,9 +921,7 @@
                                                     <input type="number" class="form-control" id="detection_check_times" value="{{$detection_check_times}}"/>
                                                     <div class="input-group-append">
                                                         <span class="input-group-text">次</span>
-                                                        <button class="btn btn-primary" type="button" onclick="updateFromInput('detection_check_times','0','12')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="updateFromInput('detection_check_times','0','12')">修改</button>
                                                     </div>
                                                 </div>
                                             </div>
@@ -1022,9 +948,7 @@
                                                 <div class="input-group">
                                                     <input type="text" class="form-control" id="server_chan_key" value="{{$server_chan_key}}" placeholder="请到ServerChan申请"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="update('server_chan_key')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="update('server_chan_key')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -1040,9 +964,7 @@
                                                 <div class="input-group">
                                                     <input type="url" class="form-control" id="bark_key" value="{{$bark_key}}" placeholder="安装并打开Bark后取得"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="update('bark_key')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="update('bark_key')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -1063,15 +985,12 @@
                                     </div>
                                     <div class="form-group col-lg-6">
                                         <div class="row">
-                                            <label class="col-md-3 col-form-label" for="push_bear_send_key">PushBear
-                                                SendKey</label>
+                                            <label class="col-md-3 col-form-label" for="push_bear_send_key">PushBear SendKey</label>
                                             <div class="col-md-7">
                                                 <div class="input-group">
                                                     <input type="text" class="form-control" id="push_bear_send_key" value="{{$push_bear_send_key}}" placeholder="创建消息通道后即可获取"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="update('push_bear_send_key')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="update('push_bear_send_key')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -1085,9 +1004,7 @@
                                                 <div class="input-group">
                                                     <input type="url" class="form-control" id="push_bear_qrcode" value="{{$push_bear_qrcode}}" placeholder="填入消息通道的二维码URL"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="update('push_bear_qrcode')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="update('push_bear_qrcode')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -1131,9 +1048,7 @@
                                                 <div class="input-group">
                                                     <input type="number" class="form-control" id="subscribe_ban_times" value="{{$subscribe_ban_times}}"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="updateFromInput('subscribe_ban_times','0')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="updateFromInput('subscribe_ban_times','0')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -1157,9 +1072,7 @@
                                                     <input type="number" class="form-control" id="traffic_ban_value" value="{{$traffic_ban_value}}"/>
                                                     <div class="input-group-append">
                                                         <span class="input-group-text">GB</span>
-                                                        <button class="btn btn-primary" type="button" onclick="updateFromInput('traffic_ban_value', '1')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="updateFromInput('traffic_ban_value', '1')">修改</button>
                                                     </div>
                                                 </div>
                                             </div>
@@ -1174,9 +1087,7 @@
                                                     <input type="number" class="form-control" id="traffic_ban_time" value="{{$traffic_ban_time}}"/>
                                                     <div class="input-group-append">
                                                         <span class="input-group-text">分钟</span>
-                                                        <button class="btn btn-primary" type="button" onclick="updateFromInput('traffic_ban_time', '0')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="updateFromInput('traffic_ban_time', '0')">修改</button>
                                                     </div>
                                                 </div>
                                             </div>
@@ -1185,8 +1096,7 @@
                                     </div>
                                     <div class="form-group col-lg-6">
                                         <div class="row">
-                                            <label class="col-md-3 col-form-label"
-                                                   for="auto_release_port">端口自动释放</label>
+                                            <label class="col-md-3 col-form-label" for="auto_release_port">端口自动释放</label>
                                             <span class="col-md-9"><input type="checkbox" id="auto_release_port" data-plugin="switchery" @if($auto_release_port) checked
                                                                           @endif onchange="updateFromOther('switch','auto_release_port')"></span>
                                             <span class="text-help offset-md-3"> 被封禁和过期一个月的用户端口自动释放 </span>
@@ -1197,8 +1107,8 @@
                                             <label class="col-md-3 col-form-label" for="is_ban_status">过期自动封禁</label>
                                             <span class="col-md-9"><input type="checkbox" id="is_ban_status" data-plugin="switchery" @if($is_ban_status) checked
                                                                           @endif onchange="updateFromOther('switch','is_ban_status')"></span>
-                                            <span class="text-help offset-md-3"> (慎重)封禁整个账号会重置账号的所有数据且会导致用户无法登录,
-                                                                                 不开启状态下只封禁用户代理 </span>
+                                            <span class="text-help offset-md-3">
+                                                (慎重)封禁整个账号会重置账号的所有数据且会导致用户无法登录,不开启状态下只封禁用户代理 </span>
                                         </div>
                                     </div>
                                     <div class="form-group col-lg-6">
@@ -1308,9 +1218,7 @@
                                                 <div class="input-group">
                                                     <input type="text" class="form-control" id="subject_name" value="{{$subject_name}}"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="update('subject_name')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="update('subject_name')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -1324,9 +1232,7 @@
                                                 <div class="input-group">
                                                     <input type="text" class="form-control" id="website_callback_url" value="{{$website_callback_url}}"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="update('website_callback_url')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="update('website_callback_url')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -1340,7 +1246,7 @@
                                         <div class="row">
                                             <label class="col-md-3 col-form-label">支付宝F2F</label>
                                             <div class="col-md-7">
-                                                本功能需要<a href="https://open.alipay.com/platform/home.htm" target="_blank">蚂蚁金服开放平台</a>
+                                                本功能需要<a href="https://open.alipay.com/platform/appManage.htm?#/create/" target="_blank">蚂蚁金服开放平台</a>
                                                 申请权限及应用
                                             </div>
                                         </div>
@@ -1352,9 +1258,7 @@
                                                 <div class="input-group">
                                                     <input type="text" class="form-control" id="f2fpay_app_id" value="{{$f2fpay_app_id}}"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="update('f2fpay_app_id')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="update('f2fpay_app_id')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -1368,9 +1272,7 @@
                                                 <div class="input-group">
                                                     <input class="form-control" type="text" id="f2fpay_private_key" value="{{$f2fpay_private_key}}"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="update('f2fpay_private_key')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="update('f2fpay_private_key')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -1384,9 +1286,7 @@
                                                 <div class="input-group">
                                                     <input type="text" class="form-control" id="f2fpay_public_key" value="{{$f2fpay_public_key}}"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="update('f2fpay_public_key')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="update('f2fpay_public_key')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -1410,9 +1310,7 @@
                                                 <div class="input-group">
                                                     <input type="text" class="form-control" id="codepay_url" value="{{$codepay_url}}" placeholder="https://codepay.fateqq.com/creat_order/?"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="update('codepay_url')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="update('codepay_url')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -1425,9 +1323,7 @@
                                                 <div class="input-group">
                                                     <input type="text" class="form-control" id="codepay_id" value="{{$codepay_id}}"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="update('codepay_id')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="update('codepay_id')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -1440,9 +1336,7 @@
                                                 <div class="input-group">
                                                     <input type="text" class="form-control" id="codepay_key" value="{{$codepay_key}}"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="update('codepay_key')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="update('codepay_key')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -1454,9 +1348,7 @@
                                         <div class="row">
                                             <label class="col-md-3 col-form-label">易支付</label>
                                             <div class="col-md-7">
-                                                <button class="btn btn-primary" type="button" onclick="epayInfo()">
-                                                    咨询查询
-                                                </button>
+                                                <button class="btn btn-primary" type="button" onclick="epayInfo()">查询</button>
                                             </div>
                                         </div>
                                     </div>
@@ -1467,9 +1359,7 @@
                                                 <div class="input-group">
                                                     <input type="text" class="form-control" id="epay_url" value="{{$epay_url}}" placeholder="https://www.example.com"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="update('epay_url')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="update('epay_url')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -1482,9 +1372,7 @@
                                                 <div class="input-group">
                                                     <input type="text" class="form-control" id="epay_mch_id" value="{{$epay_mch_id}}"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="update('epay_mch_id')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="update('epay_mch_id')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -1497,9 +1385,7 @@
                                                 <div class="input-group">
                                                     <input type="text" class="form-control" id="epay_key" value="{{$epay_key}}"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="update('epay_key')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="update('epay_key')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -1522,9 +1408,7 @@
                                                 <div class="input-group">
                                                     <input type="text" class="form-control" id="payjs_mch_id" value="{{$payjs_mch_id}}"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="update('payjs_mch_id')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="update('payjs_mch_id')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -1538,9 +1422,7 @@
                                                 <div class="input-group">
                                                     <input type="text" class="form-control" id="payjs_key" value="{{$payjs_key}}"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="update('payjs_key')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="update('payjs_key')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -1552,9 +1434,8 @@
                                         <div class="row">
                                             <label class="col-md-3 col-form-label">麻瓜宝 MugglePay</label>
                                             <div class="col-md-7">
-                                                请到<a href="https://merchants.mugglepay.com/user/register?ref=MP904BEBB79FE0" target="_blank">麻瓜宝
-                                                    MugglePay</a>
-                                                申请账号
+                                                请到<a href="https://merchants.mugglepay.com/user/register?ref=MP904BEBB79FE0" target="_blank">
+                                                    麻瓜宝 MugglePay</a>申请账号
                                             </div>
                                         </div>
                                     </div>
@@ -1565,9 +1446,7 @@
                                                 <div class="input-group">
                                                     <input type="text" class="form-control" id="bitpay_secret" value="{{$bitpay_secret}}"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="update('bitpay_secret')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="update('bitpay_secret')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -1580,8 +1459,8 @@
                                         <div class="row">
                                             <label class="col-md-3 col-form-label">PayPal</label>
                                             <div class="col-md-7">
-                                                使用商家账号登录<a href="https://www.paypal.com/businessprofile/mytools/apiaccess/firstparty" target="_blank">API凭证申请页</a>,
-                                                同意并获取设置信息
+                                                使用商家账号登录<a href="https://www.paypal.com/businessprofile/mytools/apiaccess/firstparty" target="_blank">
+                                                    API凭证申请页</a>, 同意并获取设置信息
                                             </div>
                                         </div>
                                     </div>
@@ -1592,9 +1471,7 @@
                                                 <div class="input-group">
                                                     <input type="text" class="form-control" id="paypal_username" value="{{$paypal_username}}"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="update('paypal_username')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="update('paypal_username')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -1607,9 +1484,7 @@
                                                 <div class="input-group">
                                                     <input type="text" class="form-control" id="paypal_password" value="{{$paypal_password}}"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="update('paypal_password')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="update('paypal_password')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -1622,9 +1497,7 @@
                                                 <div class="input-group">
                                                     <input type="text" class="form-control" id="paypal_secret" value="{{$paypal_secret}}"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="update('paypal_secret')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="update('paypal_secret')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -1637,9 +1510,7 @@
                                                 <div class="input-group">
                                                     <input type="text" class="form-control" id="paypal_certificate" value="{{$paypal_certificate}}"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="update('paypal_certificate')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="update('paypal_certificate')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -1652,9 +1523,7 @@
                                                 <div class="input-group">
                                                     <input type="text" class="form-control" id="paypal_app_id" value="{{$paypal_app_id}}"/>
                                                     <span class="input-group-append">
-                                                        <button class="btn btn-primary" type="button" onclick="update('paypal_app_id')">
-                                                            修改
-                                                        </button>
+                                                        <button class="btn btn-primary" type="button" onclick="update('paypal_app_id')">修改</button>
                                                     </span>
                                                 </div>
                                             </div>
@@ -1682,11 +1551,13 @@
 
     <script type="text/javascript">
         $(document).ready(function() {
-            $('#is_invite_register').selectpicker('val', {{$is_invite_register}});
-            $('#is_activate_account').selectpicker('val', {{$is_activate_account}});
-            $('#is_captcha').selectpicker('val', {{$is_captcha}});
-            $('#referral_type').selectpicker('val', {{$referral_type}});
-            $('#is_email_filtering').selectpicker('val', {{$is_email_filtering}});
+            $('#forbid_mode').selectpicker('val', '{{$forbid_mode}}');
+            $('#is_invite_register').selectpicker('val', '{{$is_invite_register}}');
+            $('#is_activate_account').selectpicker('val', '{{$is_activate_account}}');
+            $('#ddns_mode').selectpicker('val', '{{$ddns_mode}}');
+            $('#is_captcha').selectpicker('val', '{{$is_captcha}}');
+            $('#referral_type').selectpicker('val', '{{$referral_type}}');
+            $('#is_email_filtering').selectpicker('val', '{{$is_email_filtering}}');
             $('#is_notification').selectpicker('val', '{{$is_notification}}');
             $('#is_AliPay').selectpicker('val', '{{$is_AliPay}}');
             $('#is_QQPay').selectpicker('val', '{{$is_QQPay}}');

+ 16 - 15
resources/views/admin/node/info.blade.php

@@ -44,7 +44,7 @@
                                     <div class="form-group row">
                                         <label for="server" class="col-md-3 col-form-label"> 域名 </label>
                                         <input type="text" class="form-control col-md-4" name="server" id="server" placeholder="服务器域名地址,填则优先取域名地址">
-                                        <span class="text-help offset-md-3">如果开启Namesilo且域名是Namesilo上购买的,则会强制更新域名的DNS记录为本节点IP,如果其他节点绑定了该域名则会清空其域名信息</span>
+                                        <span class="text-help offset-md-3">系统设置中开启【DDNS模式】,域名将会自动与下方IP内容进行绑定操作!无需再前往域名注册商页面修改IP信息了哟</span>
                                     </div>
                                     <div class="form-group row">
                                         <label for="ip" class="col-md-3 col-form-label"> IPv4地址 </label>
@@ -548,21 +548,20 @@
                 dataType: 'json',
                 success: function(ret) {
                     if (ret.status === 'success') {
-                        swal.fire({title: ret.message, type: 'success', timer: 1000, showConfirmButton: false}).then(() => window.location.href = '{{route('admin.node.index')}}');
+                        swal.fire({title: ret.message, type: 'success', timer: 1000, showConfirmButton: false}).
+                            then(() => window.location.href = '{{route('admin.node.index').(Request::getQueryString()?('?'.Request::getQueryString()):'') }}');
                     }
                     else {
                         swal.fire({title: '[错误 | Error]', text: ret.message, type: 'error'});
                     }
                 },
-                error: function(ret) {
+                error: function(data) {
                     let str = '';
-                    $.each(ret.responseJSON.errors, function(index, value) {str += '<li>' + value + '</li>';});
-                    swal.fire({
-                        title: '提示',
-                        html: str,
-                        type: 'error',
-                        confirmButtonText: '{{trans('home.ticket_confirm')}}',
-                    });
+                    const errors = data.responseJSON;
+                    if ($.isEmptyObject(errors) === false) {
+                        $.each(errors.errors, function(index, value) {str += '<li>' + value + '</li>';});
+                        swal.fire({title: '提示', html: str, type: 'error', confirmButtonText: '{{trans('home.ticket_confirm')}}'});
+                    }
                 },
             });
 
@@ -587,8 +586,8 @@
                 case 'is_relay':
                     if (check) {
                         $('.relay-setting').show();
-                        $('#relay_port').attr('required', 'required');
-                        $('#relay_server').attr('required', 'required');
+                        $('#relay_port').attr('required', true);
+                        $('#relay_server').attr('required', true);
                     }
                     else {
                         $('.relay-setting').hide();
@@ -599,11 +598,13 @@
                 // 设置是否使用DDNS
                 case 'is_ddns':
                     if (check) {
-                        $('#ip').val('1.1.1.1').attr('readonly', 'readonly');
-                        $('#server').attr('required', 'required');
+                        $('#ip').val('').attr('readonly', true);
+                        $('#ipv6').val('').attr('readonly', true);
+                        $('#server').attr('required', true);
                     }
                     else {
-                        $('#ip').val('').removeAttr('readonly');
+                        $('#ip').removeAttr('readonly');
+                        $('#ipv6').removeAttr('readonly');
                         $('#server').removeAttr('required');
                     }
                     break;

+ 5 - 7
resources/views/admin/user/info.blade.php

@@ -502,13 +502,11 @@
                 },
                 error: function(ret) {
                     let str = '';
-                    $.each(ret.responseJSON.errors, function(index, value) {str += '<li>' + value + '</li>';});
-                    swal.fire({
-                        title: '提示',
-                        html: str,
-                        type: 'error',
-                        confirmButtonText: '{{trans('home.ticket_confirm')}}',
-                    });
+                    const errors = data.responseJSON;
+                    if ($.isEmptyObject(errors) === false) {
+                        $.each(errors.errors, function(index, value) {str += '<li>' + value + '</li>';});
+                        swal.fire({title: '提示', html: str, type: 'error', confirmButtonText: '{{trans('home.ticket_confirm')}}'});
+                    }
                 },
             });
 

+ 0 - 1
tests/Feature/ExampleTest.php

@@ -2,7 +2,6 @@
 
 namespace Tests\Feature;
 
-use Illuminate\Foundation\Testing\RefreshDatabase;
 use Tests\TestCase;
 
 class ExampleTest extends TestCase