瀏覽代碼

1.3

功能添加/重置
1. 商品限购功能重置 - 商品为0时下架
2. 添加用户付费自行重置套餐流量 - 可规定价格让用户重置或不开启功能
3. 邮箱注册增加白名单 - 白名单为用户只能使用固定邮箱后缀注册
4. 节点TCP和ICMP检测 - 节点阻断检测
5. 优惠券规则添加 - 满XX元抵XX,或者满XX元打折

页面添加与修改
1. 节点信息简化
2. 系统页面排版优化
3. 注册页面全新的TOS和AUP显示
4. 添加订阅记录查询页面
5. 人性化删除确认页

BUG修复和优化
1. 流量重置日相关代码统一
2. 众多代码简化
3. auth相关css导致的宽度变动bug修复
Bretton 5 年之前
父節點
當前提交
d1581f0e33
共有 100 個文件被更改,包括 3753 次插入3507 次删除
  1. 766 918
      _ide_helper.php
  2. 3 3
      app/Components/Namesilo.php
  3. 0 210
      app/Console/Commands/AutoCheckNodeTCP.php
  4. 1 7
      app/Console/Commands/AutoJob.php
  5. 284 0
      app/Console/Commands/NodeBlockedDetection.php
  6. 3 3
      app/Console/Kernel.php
  7. 64 46
      app/Http/Controllers/AdminController.php
  8. 1 6
      app/Http/Controllers/Api/AlipayController.php
  9. 1 6
      app/Http/Controllers/Api/F2fpayController.php
  10. 2 6
      app/Http/Controllers/Api/YzyController.php
  11. 34 12
      app/Http/Controllers/AuthController.php
  12. 2 2
      app/Http/Controllers/Controller.php
  13. 9 8
      app/Http/Controllers/CouponController.php
  14. 35 44
      app/Http/Controllers/PaymentController.php
  15. 1 0
      app/Http/Controllers/SensitiveWordsController.php
  16. 24 3
      app/Http/Controllers/ShopController.php
  17. 38 19
      app/Http/Controllers/SubscribeController.php
  18. 3 3
      app/Http/Controllers/TicketController.php
  19. 94 97
      app/Http/Controllers/UserController.php
  20. 10 0
      app/Http/Models/Coupon.php
  21. 10 0
      app/Http/Models/Goods.php
  22. 20 0
      app/Http/Models/Invite.php
  23. 1 0
      app/Http/Models/Order.php
  24. 21 0
      app/Http/Models/Ticket.php
  25. 1 1
      app/Http/Models/UserSubscribe.php
  26. 4 0
      app/Http/Models/UserSubscribeLog.php
  27. 3 2
      composer.json
  28. 142 142
      composer.lock
  29. 二進制
      composer.phar
  30. 202 0
      config/debugbar.php
  31. 53 37
      public/assets/examples/css/pages/login-v3.css
  32. 4 2
      resources/lang/zh-CN/auth.php
  33. 4 5
      resources/views/admin/addArticle.blade.php
  34. 2 7
      resources/views/admin/addGroup.blade.php
  35. 2 7
      resources/views/admin/addLabel.blade.php
  36. 65 158
      resources/views/admin/addNode.blade.php
  37. 25 52
      resources/views/admin/addUser.blade.php
  38. 17 26
      resources/views/admin/analysis.blade.php
  39. 1 1
      resources/views/admin/applyDetail.blade.php
  40. 1 3
      resources/views/admin/applyList.blade.php
  41. 66 73
      resources/views/admin/config.blade.php
  42. 7 14
      resources/views/admin/convert.blade.php
  43. 1 2
      resources/views/admin/decompile.blade.php
  44. 4 4
      resources/views/admin/editArticle.blade.php
  45. 2 7
      resources/views/admin/editGroup.blade.php
  46. 2 8
      resources/views/admin/editLabel.blade.php
  47. 69 168
      resources/views/admin/editNode.blade.php
  48. 30 58
      resources/views/admin/editUser.blade.php
  49. 1 3
      resources/views/admin/emailLog.blade.php
  50. 3 3
      resources/views/admin/groupList.blade.php
  51. 1 1
      resources/views/admin/import.blade.php
  52. 25 18
      resources/views/admin/inviteList.blade.php
  53. 3 3
      resources/views/admin/labelList.blade.php
  54. 1 4
      resources/views/admin/layouts.blade.php
  55. 4 13
      resources/views/admin/nodeList.blade.php
  56. 1 6
      resources/views/admin/onlineIPMonitor.blade.php
  57. 1 11
      resources/views/admin/orderList.blade.php
  58. 1 1
      resources/views/admin/profile.blade.php
  59. 814 705
      resources/views/admin/system.blade.php
  60. 2 6
      resources/views/admin/trafficLog.blade.php
  61. 1 2
      resources/views/admin/userBalanceLogList.blade.php
  62. 1 2
      resources/views/admin/userBanLogList.blade.php
  63. 9 20
      resources/views/admin/userList.blade.php
  64. 1 6
      resources/views/admin/userOnlineIPList.blade.php
  65. 1 4
      resources/views/admin/userRebateList.blade.php
  66. 1 2
      resources/views/admin/userTrafficLogList.blade.php
  67. 1 3
      resources/views/auth/active.blade.php
  68. 5 7
      resources/views/auth/activeUser.blade.php
  69. 2 5
      resources/views/auth/error.blade.php
  70. 1 1
      resources/views/auth/free.blade.php
  71. 37 43
      resources/views/auth/layouts.blade.php
  72. 5 21
      resources/views/auth/login.blade.php
  73. 300 53
      resources/views/auth/register.blade.php
  74. 5 7
      resources/views/auth/reset.blade.php
  75. 5 7
      resources/views/auth/resetPassword.blade.php
  76. 32 24
      resources/views/coupon/addCoupon.blade.php
  77. 4 7
      resources/views/coupon/couponList.blade.php
  78. 1 3
      resources/views/marketing/emailList.blade.php
  79. 2 5
      resources/views/marketing/pushList.blade.php
  80. 1 5
      resources/views/payment/callbackList.blade.php
  81. 1 3
      resources/views/payment/detail.blade.php
  82. 2 7
      resources/views/sensitiveWords/addSensitiveWords.blade.php
  83. 26 9
      resources/views/sensitiveWords/sensitiveWordsList.blade.php
  84. 74 64
      resources/views/shop/addGoods.blade.php
  85. 51 46
      resources/views/shop/editGoods.blade.php
  86. 6 12
      resources/views/shop/goodsList.blade.php
  87. 1 2
      resources/views/subscribe/deviceList.blade.php
  88. 4 8
      resources/views/subscribe/subscribeList.blade.php
  89. 59 0
      resources/views/subscribe/subscribeLog.blade.php
  90. 1 6
      resources/views/ticket/addTicket.blade.php
  91. 2 2
      resources/views/ticket/replyTicket.blade.php
  92. 2 9
      resources/views/ticket/ticketList.blade.php
  93. 18 20
      resources/views/user/buy.blade.php
  94. 55 105
      resources/views/user/help.blade.php
  95. 14 14
      resources/views/user/index.blade.php
  96. 23 16
      resources/views/user/invite.blade.php
  97. 1 1
      resources/views/user/invoiceDetail.blade.php
  98. 2 7
      resources/views/user/layouts.blade.php
  99. 2 2
      resources/views/user/nodeList.blade.php
  100. 3 3
      resources/views/user/profile.blade.php

File diff suppressed because it is too large
+ 766 - 918
_ide_helper.php


+ 3 - 3
app/Components/Namesilo.php

@@ -90,15 +90,15 @@ class Namesilo
 
 			// 出错
 			if(empty($result['namesilo']) || $result['namesilo']['reply']['code'] != 300 || $result['namesilo']['reply']['detail'] != 'success'){
-				Helpers::addEmailLog(self::$systemConfig['crash_warning_email'], '[Namesilo API] - ['.$operation.']', $content, 0, $result['namesilo']['reply']['detail']);
+				Helpers::addEmailLog(self::$systemConfig['webmaster_email'], '[Namesilo API] - ['.$operation.']', $content, 0, $result['namesilo']['reply']['detail']);
 			}else{
-				Helpers::addEmailLog(self::$systemConfig['crash_warning_email'], '[Namesilo API] - ['.$operation.']', $content, 1, $result['namesilo']['reply']['detail']);
+				Helpers::addEmailLog(self::$systemConfig['webmaster_email'], '[Namesilo API] - ['.$operation.']', $content, 1, $result['namesilo']['reply']['detail']);
 			}
 
 			return $result['namesilo']['reply'];
 		} catch(Exception $e){
 			Log::error('CURL请求失败:'.$e->getMessage().' --- '.$e->getLine());
-			Helpers::addEmailLog(self::$systemConfig['crash_warning_email'], '[Namesilo API] - ['.$operation.']', $content, 0, $e->getMessage());
+			Helpers::addEmailLog(self::$systemConfig['webmaster_email'], '[Namesilo API] - ['.$operation.']', $content, 0, $e->getMessage());
 
 			return FALSE;
 		}

+ 0 - 210
app/Console/Commands/AutoCheckNodeTCP.php

@@ -1,210 +0,0 @@
-<?php
-
-namespace App\Console\Commands;
-
-use App\Components\Helpers;
-use App\Components\ServerChan;
-use App\Http\Models\SsNode;
-use App\Mail\nodeCrashWarning;
-use Cache;
-use Exception;
-use GuzzleHttp\Exception\GuzzleException;
-use Illuminate\Console\Command;
-use Log;
-use Mail;
-
-class AutoCheckNodeTCP extends Command
-{
-	protected $signature = 'autoCheckNodeTCP';
-	protected $description = '自动检测节点是否被TCP阻断';
-	protected static $systemConfig;
-
-	public function __construct()
-	{
-		parent::__construct();
-		self::$systemConfig = Helpers::systemConfig();
-	}
-
-	public function handle()
-	{
-		$jobStartTime = microtime(TRUE);
-
-		if(self::$systemConfig['is_tcp_check']){
-			if(!Cache::has('tcp_check_time')){
-				$this->checkNodes();
-			}elseif(Cache::get('tcp_check_time') <= time()){
-				$this->checkNodes();
-			}else{
-				Log::info('下次节点TCP阻断检测时间:'.date('Y-m-d H:i:s', Cache::get('tcp_check_time')));
-			}
-		}
-
-		$jobEndTime = microtime(TRUE);
-		$jobUsedTime = round(($jobEndTime-$jobStartTime), 4);
-
-		Log::info('执行定时任务【'.$this->description.'】,耗时'.$jobUsedTime.'秒');
-	}
-
-	// 监测节点状态
-	private function checkNodes()
-	{
-		$title = "节点异常警告";
-
-		$nodeList = SsNode::query()->where('is_transit', 0)->where('is_nat', 0)->where('status', 1)->where('is_tcp_check', 1)->get();
-		foreach($nodeList as $node){
-			$tcpCheck = $this->tcpCheck($node->ip);
-			if(FALSE !== $tcpCheck){
-				switch($tcpCheck){
-					case 1:
-						$text = '服务器宕机';
-						break;
-					case 2:
-						$text = '海外不通';
-						break;
-					case 3:
-						$text = 'TCP阻断';
-						break;
-					case 0:
-					default:
-						$text = '正常';
-				}
-
-				// 异常才发通知消息
-				if($tcpCheck){
-					if(self::$systemConfig['tcp_check_warning_times']){
-						// 已通知次数
-						$cacheKey = 'tcp_check_warning_times_'.$node->id;
-						if(Cache::has($cacheKey)){
-							$times = Cache::get($cacheKey);
-						}else{
-							Cache::put($cacheKey, 1, 725); // 最多设置提醒12次,12*60=720分钟缓存时效,多5分钟防止异常
-							$times = 1;
-						}
-
-						if($times < self::$systemConfig['tcp_check_warning_times']){
-							Cache::increment($cacheKey);
-
-							$this->notifyMaster($title, "节点**{$node->name}【{$node->ip}】**:**".$text."**", $node->name, $node->server);
-						}elseif($times >= self::$systemConfig['tcp_check_warning_times']){
-							Cache::forget($cacheKey);
-							SsNode::query()->where('id', $node->id)->update(['status' => 0]);
-
-							$this->notifyMaster($title, "节点**{$node->name}【{$node->ip}】**:**".$text."**,节点自动进入维护状态", $node->name, $node->server);
-						}
-					}else{
-						$this->notifyMaster($title, "节点**{$node->name}【{$node->ip}】**:**".$text."**", $node->name, $node->server);
-					}
-				}
-
-				Log::info("【TCP阻断检测】".$node->name.' - '.$node->ip.' - '.$text);
-			}
-		}
-
-		// 随机生成下次检测时间
-		$nextCheckTime = time()+mt_rand(1800, 3600);
-		Cache::put('tcp_check_time', $nextCheckTime, 60);
-	}
-
-	/**
-	 * 用ipcheck.need.sh进行TCP阻断检测
-	 *
-	 * @param string $ip 被检测的IP
-	 *
-	 * @return bool|int
-	 */
-	private function tcpCheck($ip)
-	{
-		try{
-			$url = 'https://ipcheck.need.sh/api_v2.php?ip='.$ip;
-			$ret = $this->curlRequest($url);
-			$ret = json_decode($ret);
-			if(!$ret || $ret->result != 'success'){
-				Log::warning("【TCP阻断检测】检测".$ip."时,接口返回异常");
-
-				return FALSE;
-			}
-		} catch(Exception $e){
-			Log::warning("【TCP阻断检测】检测".$ip."时,接口请求超时");
-
-			return FALSE;
-		}
-
-		if(!$ret->data->inside_gfw->tcp->alive && !$ret->data->outside_gfw->tcp->alive){
-			return 1; // 服务器宕机或者检测接口挂了
-		}elseif($ret->data->inside_gfw->tcp->alive && !$ret->data->outside_gfw->tcp->alive){
-			return 2; // 国外访问异常
-		}elseif(!$ret->data->inside_gfw->tcp->alive && $ret->data->outside_gfw->tcp->alive){
-			return 3; // 被墙
-		}else{
-			return 0; // 正常
-		}
-	}
-
-	/**
-	 * 通知管理员
-	 *
-	 * @param string $title      消息标题
-	 * @param string $content    消息内容
-	 * @param string $nodeName   节点名称
-	 * @param string $nodeServer 节点域名
-	 *
-	 * @throws GuzzleException
-	 */
-	private function notifyMaster($title, $content, $nodeName, $nodeServer)
-	{
-		$this->notifyMasterByEmail($title, $content, $nodeName, $nodeServer);
-		ServerChan::send($title, $content);
-	}
-
-	/**
-	 * 发邮件通知管理员
-	 *
-	 * @param string $title      消息标题
-	 * @param string $content    消息内容
-	 * @param string $nodeName   节点名称
-	 * @param string $nodeServer 节点域名
-	 */
-	private function notifyMasterByEmail($title, $content, $nodeName, $nodeServer)
-	{
-		if(self::$systemConfig['crash_warning_email']){
-			$logId = Helpers::addEmailLog(self::$systemConfig['crash_warning_email'], $title, $content);
-			Mail::to(self::$systemConfig['crash_warning_email'])->send(new nodeCrashWarning($logId, $nodeName, $nodeServer));
-		}
-	}
-
-	/**
-	 * 发起一个CURL请求
-	 *
-	 * @param string $url  请求地址
-	 * @param array  $data POST数据,留空则为GET
-	 *
-	 * @return mixed
-	 */
-	private function curlRequest($url, $data = [])
-	{
-		$data = json_encode($data, JSON_UNESCAPED_UNICODE);
-
-		$ch = curl_init();
-		curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
-		curl_setopt($ch, CURLOPT_TIMEOUT, 10);
-		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
-		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
-		curl_setopt($ch, CURLOPT_URL, $url);
-//        curl_setopt($ch, CURLOPT_HTTPHEADER, [
-//            'Accept: application/json', // 请求报头
-//            'Content-Type: application/json', // 实体报头
-//            'Content-Length: ' . strlen($data)
-//        ]);
-
-		// 如果data有数据,则用POST请求
-		if($data){
-			curl_setopt($ch, CURLOPT_POST, 1);
-			curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
-		}
-
-		$result = curl_exec($ch);
-		curl_close($ch);
-
-		return $result;
-	}
-}

+ 1 - 7
app/Console/Commands/AutoJob.php

@@ -400,13 +400,7 @@ class AutoJob extends Command
 
 							// 套餐就改流量重置日,流量包不改
 							if($goods->type == 2){
-								if(date('m') == 2 && date('d') == 29){
-									$traffic_reset_day = 28;
-								}else{
-									$traffic_reset_day = date('d') == 31? 30 : abs(date('d'));
-								}
-
-								User::query()->where('id', $order->user_id)->update(['traffic_reset_day' => $traffic_reset_day, 'expire_time' => $expireTime, 'enable' => 1]);
+								User::query()->where('id', $order->user_id)->update(['traffic_reset_day' =>  date('d'), 'expire_time' => $expireTime, 'enable' => 1]);
 							}else{
 								User::query()->where('id', $order->user_id)->update(['expire_time' => $expireTime, 'enable' => 1]);
 							}

+ 284 - 0
app/Console/Commands/NodeBlockedDetection.php

@@ -0,0 +1,284 @@
+<?php
+
+namespace App\Console\Commands;
+
+use App\Components\Helpers;
+use App\Components\ServerChan;
+use App\Http\Models\SsNode;
+use App\Mail\nodeCrashWarning;
+use Cache;
+use Exception;
+use GuzzleHttp\Exception\GuzzleException;
+use Illuminate\Console\Command;
+use Log;
+use Mail;
+
+class NodeBlockedDetection extends Command
+{
+	protected $signature = 'NodeBlockedDetection';
+	protected $description = '节点阻断检测';
+	protected static $systemConfig;
+
+	public function __construct()
+	{
+		parent::__construct();
+		self::$systemConfig = Helpers::systemConfig();
+	}
+
+	public function handle()
+	{
+		$jobStartTime = microtime(TRUE);
+
+		if(self::$systemConfig['nodes_detection']){
+			if(!Cache::has('LastCheckTime')){
+				$this->checkNodes();
+			}elseif(Cache::get('LastCheckTime') <= time()){
+				$this->checkNodes();
+			}else{
+				Log::info('下次节点TCP阻断检测时间:'.date('Y-m-d H:i:s', Cache::get('LastCheckTime')));
+			}
+		}
+
+		$jobEndTime = microtime(TRUE);
+		$jobUsedTime = round(($jobEndTime-$jobStartTime), 4);
+
+		Log::info("执行定时任务【{$this->description}】,耗时 {$jobUsedTime} 秒");
+	}
+
+	// 监测节点状态
+	private function checkNodes()
+	{
+		$title = "节点异常警告";
+		$nodeList = SsNode::query()->where('is_transit', 0)->where('status', 1)->where('detectionType', '>', 0)->get();
+		foreach($nodeList as $node){
+			// 使用DDNS的node先通过gethostbyname获取ipv4地址
+			if($node->is_ddns){
+				$ip = gethostbyname($node->server);
+				if(strcmp($ip, $node->server) != 0){
+					$node->ip = $ip;
+				}else{
+					Log::warning("【节点阻断检测】检测".$node->server."时,IP获取失败".$ip." | ".$node->server);
+					$this->notifyMaster($title, "节点**{$node->name}**:** IP获取失败 **", $node->name, $node->server);
+				}
+			}
+			$text = '| 协议 | 状态 |'.PHP_EOL.'| ------ | ------ |'.PHP_EOL;
+			$sendText = FALSE;
+			if($node->detectionType == 1 || $node->detectionType == 3){
+				$tcpCheck = $this->tcpCheck($node->ip, $node->single? $node->port : NULL);
+				if($tcpCheck != FALSE){
+					$text .= '| TCP |';
+					switch($tcpCheck){
+						case 1:
+							$text .= ' 海外阻断 |'.PHP_EOL;
+							break;
+						case 2:
+							$text .= ' 国内阻断 |'.PHP_EOL;
+							break;
+						case 3:
+							$text .= ' 机器宕机 |'.PHP_EOL;
+							break;
+						case 0:
+							$text .= ' 检测正常 |'.PHP_EOL;
+							break;
+						default:
+							$text .= ' 未知 |'.PHP_EOL;
+					}
+					if($tcpCheck > 0){
+						$sendText = TRUE;
+					}
+				}
+			}
+			if($node->detectionType == 2 || $node->detectionType == 3){
+				$icmpCheck = $this->icmpCheck($node->ip);
+				if($icmpCheck != FALSE){
+					$text .= '| ICMP |';
+					switch($icmpCheck){
+						case 1:
+							$text .= ' 海外阻断 |'.PHP_EOL;
+							break;
+						case 2:
+							$text .= ' 国内阻断 |'.PHP_EOL;
+							break;
+						case 3:
+							$text .= ' 机器宕机 |'.PHP_EOL;
+							break;
+						case 0:
+							$text .= ' 检测正常 |'.PHP_EOL;
+							break;
+						default:
+							$text .= ' 未知 |'.PHP_EOL;
+					}
+					if($icmpCheck > 0){
+						$sendText = TRUE;
+					}
+				}
+			}
+			// 异常才发通知消息
+			if($sendText){
+				if(self::$systemConfig['numberOfWarningTimes']){
+					// 已通知次数
+					$cacheKey = 'numberOfWarningTimes'.$node->id;
+					if(Cache::has($cacheKey)){
+						$times = Cache::get($cacheKey);
+					}else{
+						Cache::put($cacheKey, 1, 725); // 最多设置提醒12次,12*60=720分钟缓存时效,多5分钟防止异常
+						$times = 1;
+					}
+
+					if($times < self::$systemConfig['numberOfWarningTimes']){
+						Cache::increment($cacheKey);
+
+						$this->notifyMaster($title, "**{$node->name} - 【{$node->ip}】**:".PHP_EOL.$text, $node->name, $node->server);
+					}elseif($times >= self::$systemConfig['numberOfWarningTimes']){
+						Cache::forget($cacheKey);
+						SsNode::query()->where('id', $node->id)->update(['status' => 0]);
+
+						$this->notifyMaster($title, "**{$node->name} - 【{$node->ip}】**:".PHP_EOL.$text."节点自动进入维护状态".PHP_EOL, $node->name, $node->server);
+					}
+				}else{
+					$this->notifyMaster($title, "**{$node->name} - 【{$node->ip}】**:".PHP_EOL.$text, $node->name, $node->server);
+				}
+				Log::info("【节点阻断检测】{$node->name} - 【{$node->ip}】: ".PHP_EOL.$text);
+			}
+		}
+
+		// 随机生成下次检测时间
+		$nextCheckTime = time()+3600;
+		Cache::put('LastCheckTime', $nextCheckTime, 60);
+	}
+
+	/**
+	 * 用api.50network.com进行节点阻断检测
+	 *
+	 * @param string $ip   被检测的IP
+	 * @param int    $port 检测端口
+	 *
+	 * @return bool|int
+	 */
+	private function tcpCheck($ip, $port)
+	{
+		try{
+			if(isset($port)){
+				$url = 'https://api.50network.com/china-firewall/check/ip/tcp_port/'.$ip.'/'.$port;
+			}else{
+				$url = 'https://api.50network.com/china-firewall/check/ip/tcp_ack/'.$ip;
+			}
+			$ret = json_decode($this->curlRequest($url), TRUE);
+			if(!$ret){
+				Log::warning("【TCP阻断检测】检测".$ip."时,接口返回异常访问链接:");
+
+				return FALSE;
+			}elseif(!$ret['success']){
+				Log::warning("【TCP阻断检测】检测".$ip."时,返回".$ret->error);
+
+				return FALSE;
+			}
+		} catch(Exception $e){
+			Log::warning("【TCP阻断检测】检测".$ip."时,接口请求超时");
+
+			return FALSE;
+		}
+
+		if($ret['firewall-enable'] && $ret['firewall-disable']){
+			return 0; // 正常
+		}elseif($ret['firewall-enable'] && !$ret['firewall-disable']){
+			return 1; // 国外访问异常
+		}elseif(!$ret['firewall-enable'] && $ret['firewall-disable']){
+			return 2; // 被墙
+		}else{
+			return 3; // 服务器宕机
+		}
+	}
+
+	/**
+	 * 用api.50network.com进行ICMP阻断检测
+	 *
+	 * @param string $ip 被检测的IP
+	 *
+	 * @return bool|int
+	 */
+	private function icmpCheck($ip)
+	{
+		try{
+			$url = 'https://api.50network.com/china-firewall/check/ip/icmp/'.$ip;
+			$ret = json_decode($this->curlRequest($url), TRUE);
+			if(!$ret){
+				Log::warning("【ICMP阻断检测】检测".$ip."时,接口返回异常访问链接:");
+
+				return FALSE;
+			}elseif(!$ret['success']){
+				Log::warning("【ICMP阻断检测】检测".$ip."时,返回".$ret->error);
+
+				return FALSE;
+			}
+		} catch(Exception $e){
+			Log::warning("【ICMP阻断检测】检测".$ip."时,接口请求超时");
+
+			return FALSE;
+		}
+
+		if($ret['firewall-enable'] && $ret['firewall-disable']){
+			return 0; // 正常
+		}elseif($ret['firewall-enable'] && !$ret['firewall-disable']){
+			return 1; // 国外访问异常
+		}elseif(!$ret['firewall-enable'] && $ret['firewall-disable']){
+			return 2; // 被墙
+		}else{
+			return 3; // 服务器宕机
+		}
+	}
+
+	/**
+	 * 通知管理员
+	 *
+	 * @param string $title      消息标题
+	 * @param string $content    消息内容
+	 * @param string $nodeName   节点名称
+	 * @param string $nodeServer 节点域名
+	 *
+	 * @throws GuzzleException
+	 */
+	private function notifyMaster($title, $content, $nodeName, $nodeServer)
+	{
+		$this->notifyMasterByEmail($title, $content, $nodeName, $nodeServer);
+		ServerChan::send($title, $content);
+	}
+
+	/**
+	 * 发邮件通知管理员
+	 *
+	 * @param string $title      消息标题
+	 * @param string $content    消息内容
+	 * @param string $nodeName   节点名称
+	 * @param string $nodeServer 节点域名
+	 */
+	private function notifyMasterByEmail($title, $content, $nodeName, $nodeServer)
+	{
+		if(self::$systemConfig['webmaster_email']){
+			$logId = Helpers::addEmailLog(self::$systemConfig['webmaster_email'], $title, $content);
+			Mail::to(self::$systemConfig['webmaster_email'])->send(new nodeCrashWarning($logId, $nodeName, $nodeServer));
+		}
+	}
+
+	/**
+	 * 发起一个CURL请求
+	 *
+	 * @param string $url  请求地址
+	 * @param array  $data POST数据,留空则为GET
+	 *
+	 * @return mixed
+	 */
+	private function curlRequest($url)
+	{
+		$ch = curl_init();
+		curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
+		curl_setopt($ch, CURLOPT_TIMEOUT, 10);
+		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
+		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
+		curl_setopt($ch, CURLOPT_URL, $url);
+		$result = curl_exec($ch);
+		curl_close($ch);
+
+		return $result;
+	}
+}

+ 3 - 3
app/Console/Kernel.php

@@ -2,7 +2,7 @@
 
 namespace App\Console;
 
-use App\Console\Commands\AutoCheckNodeTCP;
+use App\Console\Commands\NodeBlockedDetection;
 use App\Console\Commands\AutoClearLog;
 use App\Console\Commands\AutoDecGoodsTraffic;
 use App\Console\Commands\AutoJob;
@@ -35,7 +35,7 @@ class Kernel extends ConsoleKernel
 		AutoClearLog::class,
 		AutoDecGoodsTraffic::class,
 		AutoResetUserTraffic::class,
-		AutoCheckNodeTCP::class,
+		NodeBlockedDetection::class,
 		AutoStatisticsNodeDailyTraffic::class,
 		AutoStatisticsNodeHourlyTraffic::class,
 		AutoStatisticsUserDailyTraffic::class,
@@ -64,7 +64,7 @@ class Kernel extends ConsoleKernel
 		$schedule->command('autoClearLog')->everyThirtyMinutes();
 		$schedule->command('autoDecGoodsTraffic')->everyTenMinutes();
 		$schedule->command('autoResetUserTraffic')->daily();
-		$schedule->command('autoCheckNodeTCP')->everyMinute();
+		$schedule->command('NodeBlockedDetection')->everyThirtyMinutes();
 		$schedule->command('autoStatisticsNodeDailyTraffic')->dailyAt('23:55');
 		$schedule->command('autoStatisticsNodeHourlyTraffic')->hourly();
 		$schedule->command('autoStatisticsUserDailyTraffic')->dailyAt('23:50');

File diff suppressed because it is too large
+ 64 - 46
app/Http/Controllers/AdminController.php


+ 1 - 6
app/Http/Controllers/Api/AlipayController.php

@@ -188,12 +188,7 @@ class AlipayController extends Controller
 
 				// 套餐就改流量重置日,流量包不改
 				if($goods->type == 2){
-					if(date('m') == 2 && date('d') == 29){
-						$traffic_reset_day = 28;
-					}else{
-						$traffic_reset_day = date('d') == 31? 30 : abs(date('d'));
-					}
-					User::query()->where('id', $order->user_id)->update(['traffic_reset_day' => $traffic_reset_day, 'expire_time' => $expireTime, 'enable' => 1]);
+					User::query()->where('id', $order->user_id)->update(['traffic_reset_day' =>  date('d'), 'expire_time' => $expireTime, 'enable' => 1]);
 				}else{
 					User::query()->where('id', $order->user_id)->update(['expire_time' => $expireTime, 'enable' => 1]);
 				}

+ 1 - 6
app/Http/Controllers/Api/F2fpayController.php

@@ -208,12 +208,7 @@ class F2fpayController extends Controller
 
 				// 套餐就改流量重置日,流量包不改
 				if($goods->type == 2){
-					if(date('m') == 2 && date('d') == 29){
-						$traffic_reset_day = 28;
-					}else{
-						$traffic_reset_day = date('d') == 31? 30 : abs(date('d'));
-					}
-					User::query()->where('id', $order->user_id)->update(['traffic_reset_day' => $traffic_reset_day, 'expire_time' => $expireTime, 'enable' => 1]);
+					User::query()->where('id', $order->user_id)->update(['traffic_reset_day' =>  date('d'), 'expire_time' => $expireTime, 'enable' => 1]);
 				}else{
 					User::query()->where('id', $order->user_id)->update(['expire_time' => $expireTime, 'enable' => 1]);
 				}

+ 2 - 6
app/Http/Controllers/Api/YzyController.php

@@ -226,12 +226,8 @@ class YzyController extends Controller
 
 				// 套餐就改流量重置日,流量包不改
 				if($goods->type == 2){
-					if(date('m') == 2 && date('d') == 29){
-						$traffic_reset_day = 28;
-					}else{
-						$traffic_reset_day = date('d') == 31? 30 : abs(date('d'));
-					}
-					User::query()->where('id', $order->user_id)->update(['traffic_reset_day' => $traffic_reset_day, 'expire_time' => $expireTime, 'enable' => 1]);
+
+					User::query()->where('id', $order->user_id)->update(['traffic_reset_day' =>  date('d'), 'expire_time' => $expireTime, 'enable' => 1]);
 				}else{
 					User::query()->where('id', $order->user_id)->update(['expire_time' => $expireTime, 'enable' => 1]);
 				}

+ 34 - 12
app/Http/Controllers/AuthController.php

@@ -6,6 +6,7 @@ use App\Components\Helpers;
 use App\Components\IPIP;
 use App\Components\QQWry;
 use App\Http\Models\Invite;
+use App\Http\Models\SensitiveWords;
 use App\Http\Models\User;
 use App\Http\Models\UserLabel;
 use App\Http\Models\UserLoginLog;
@@ -150,6 +151,7 @@ class AuthController extends Controller
 				'username'   => 'required|email|unique:user',
 				'password'   => 'required|min:6',
 				'repassword' => 'required|same:password',
+				'term'       => 'accepted'
 			], [
 				'username.required'   => trans('auth.email_null'),
 				'username.email'      => trans('auth.email_legitimate'),
@@ -157,7 +159,8 @@ class AuthController extends Controller
 				'password.required'   => trans('auth.password_null'),
 				'password.min'        => trans('auth.password_limit'),
 				'repassword.required' => trans('auth.retype_password'),
-				'repassword.same'     => trans('auth.password_same')
+				'repassword.same'     => trans('auth.password_same'),
+				'term.accepted'       => trans('auth.unaccepted')
 			]);
 
 			// 防止重复提交
@@ -172,11 +175,20 @@ class AuthController extends Controller
 				return Redirect::back()->withErrors(trans('auth.register_close'));
 			}
 
-			// 校验域名邮箱是否在敏感词中
-			$sensitiveWords = $this->sensitiveWords();
-			$usernameSuffix = explode('@', $request->username); // 提取邮箱后缀
-			if(in_array(strtolower($usernameSuffix[1]), $sensitiveWords)){
-				return Redirect::back()->withInput()->withErrors(trans('auth.email_banned'));
+			// 校验域名邮箱黑白名单
+			if(self::$systemConfig['sensitiveType']){
+				// 校验域名邮箱是否在黑名单中
+				$sensitiveWords = $this->sensitiveWords(1);
+				$usernameSuffix = explode('@', $request->username); // 提取邮箱后缀
+				if(in_array(strtolower($usernameSuffix[1]), $sensitiveWords)){
+					return Redirect::back()->withInput()->withErrors(trans('auth.email_banned'));
+				}
+			}else{
+				$sensitiveWords = $this->sensitiveWords(2);
+				$usernameSuffix = explode('@', $request->username); // 提取邮箱后缀
+				if(!in_array(strtolower($usernameSuffix[1]), $sensitiveWords)){
+					return Redirect::back()->withInput()->withErrors(trans('auth.email_invalid'));
+				}
 			}
 
 			// 如果需要邀请注册
@@ -357,9 +369,10 @@ class AuthController extends Controller
 
 			return Redirect::to('login')->withInput();
 		}else{
+			$view['emailList'] = self::$systemConfig['sensitiveType']? NULL : SensitiveWords::query()->where('type', 2)->get();
 			Session::put('register_token', makeRandStr(16));
 
-			return Response::view('auth.register');
+			return Response::view('auth.register', $view);
 		}
 	}
 
@@ -606,11 +619,20 @@ class AuthController extends Controller
 			return Response::json(['status' => 'fail', 'data' => '', 'message' => $validator->getMessageBag()->first()]);
 		}
 
-		// 校验域名邮箱是否在敏感词中
-		$sensitiveWords = $this->sensitiveWords();
-		$usernameSuffix = explode('@', $request->username); // 提取邮箱后缀
-		if(in_array(strtolower($usernameSuffix[1]), $sensitiveWords)){
-			return Response::json(['status' => 'fail', 'data' => '', 'message' => trans('auth.email_banned')]);
+		// 校验域名邮箱黑白名单
+		if(self::$systemConfig['sensitiveType']){
+			// 校验域名邮箱是否在黑名单中
+			$sensitiveWords = $this->sensitiveWords(1);
+			$usernameSuffix = explode('@', $request->username); // 提取邮箱后缀
+			if(in_array(strtolower($usernameSuffix[1]), $sensitiveWords)){
+				return Response::json(['status' => 'fail', 'data' => '', 'message' => trans('auth.email_banned')]);
+			}
+		}else{
+			$sensitiveWords = $this->sensitiveWords(2);
+			$usernameSuffix = explode('@', $request->username); // 提取邮箱后缀
+			if(!in_array(strtolower($usernameSuffix[1]), $sensitiveWords)){
+				return Response::json(['status' => 'fail', 'data' => '', 'message' => trans('auth.email_invalid')]);
+			}
 		}
 
 		// 是否开启注册发送验证码

+ 2 - 2
app/Http/Controllers/Controller.php

@@ -134,9 +134,9 @@ class Controller extends BaseController
 	}
 
 	// 获取敏感词
-	public function sensitiveWords()
+	public function sensitiveWords($type)
 	{
-		return SensitiveWords::query()->get()->pluck('words')->toArray();
+		return SensitiveWords::query()->where('type',$type)->get()->pluck('words')->toArray();
 	}
 
 	// 将Base64图片转换为本地图片并保存

+ 9 - 8
app/Http/Controllers/CouponController.php

@@ -81,6 +81,7 @@ class CouponController extends Controller
 					$obj->usage = $request->usage;
 					$obj->amount = $request->type == 2? 0 : $request->amount;
 					$obj->discount = $request->type != 2? 0 : $request->discount;
+					$obj->rule = $request->rule;
 					$obj->available_start = strtotime(date('Y-m-d 00:00:00', strtotime($request->available_start)));
 					$obj->available_end = strtotime(date('Y-m-d 23:59:59', strtotime($request->available_end)));
 					$obj->status = 0;
@@ -113,9 +114,9 @@ class CouponController extends Controller
 	// 导出卡券
 	public function exportCoupon(Request $request)
 	{
-		$cashCouponList = Coupon::type(1)->where('status', 0)->get();
+		$voucherList = Coupon::type(1)->where('status', 0)->get();
 		$discountCouponList = Coupon::type(2)->where('status', 0)->get();
-		$chargeCouponList = Coupon::type(3)->where('status', 0)->get();
+		$refillList = Coupon::type(3)->where('status', 0)->get();
 
 		$filename = '卡券'.date('Ymd').'.xlsx';
 		$spreadsheet = new Spreadsheet();
@@ -125,11 +126,11 @@ class CouponController extends Controller
 		$spreadsheet->setActiveSheetIndex(0);
 		$sheet = $spreadsheet->getActiveSheet();
 		$sheet->setTitle('抵用券');
-		$sheet->fromArray(['名称', '类型', '有效期', '券码', '金额(元)'], NULL);
-		foreach($cashCouponList as $k => $vo){
+		$sheet->fromArray(['名称', '类型', '有效期', '券码', '金额(元)', '使用限制(元)'], NULL);
+		foreach($voucherList as $k => $vo){
 			$usage = $vo->usage == 1? '一次性' : '重复使用';
 			$dateRange = date('Y-m-d', $vo->available_start).' ~ '.date('Y-m-d', $vo->available_end);
-			$sheet->fromArray([$vo->name, $usage, $dateRange, $vo->sn, $vo->amount], NULL, 'A'.($k+2));
+			$sheet->fromArray([$vo->name, $usage, $dateRange, $vo->sn, $vo->amount, $vo->rule], NULL, 'A'.($k+2));
 		}
 
 		// 折扣券
@@ -137,11 +138,11 @@ class CouponController extends Controller
 		$spreadsheet->setActiveSheetIndex(1);
 		$sheet = $spreadsheet->getActiveSheet();
 		$sheet->setTitle('折扣券');
-		$sheet->fromArray(['名称', '类型', '有效期', '券码', '折扣(折)'], NULL);
+		$sheet->fromArray(['名称', '类型', '有效期', '券码', '折扣(折)', '使用限制(元)'], NULL);
 		foreach($discountCouponList as $k => $vo){
 			$usage = $vo->usage == 1? '一次性' : '重复使用';
 			$dateRange = date('Y-m-d', $vo->available_start).' ~ '.date('Y-m-d', $vo->available_end);
-			$sheet->fromArray([$vo->name, $usage, $dateRange, $vo->sn, $vo->discount], NULL, 'A'.($k+2));
+			$sheet->fromArray([$vo->name, $usage, $dateRange, $vo->sn, $vo->discount, $vo->rule], NULL, 'A'.($k+2));
 		}
 
 		// 充值券
@@ -150,7 +151,7 @@ class CouponController extends Controller
 		$sheet = $spreadsheet->getActiveSheet();
 		$sheet->setTitle('充值券');
 		$sheet->fromArray(['名称', '类型', '有效期', '券码', '金额(元)'], NULL);
-		foreach($chargeCouponList as $k => $vo){
+		foreach($refillList as $k => $vo){
 			$usage = '一次性';
 			$dateRange = date('Y-m-d', $vo->available_start).' ~ '.date('Y-m-d', $vo->available_end);
 			$sheet->fromArray([$vo->name, $usage, $dateRange, $vo->sn, $vo->amount], NULL, 'A'.($k+2));

+ 35 - 44
app/Http/Controllers/PaymentController.php

@@ -57,20 +57,11 @@ class PaymentController extends Controller
 			return Response::json(['status' => 'fail', 'data' => '', 'message' => '创建支付单失败:尚有未支付的订单,请先去支付']);
 		}
 
-		// 限购控制
-		$strategy = self::$systemConfig['goods_purchase_limit_strategy'];
-		if($strategy == 'all' || ($strategy == 'package' && $goods->type == 2) || ($strategy == 'free' && $goods->price == 0) || ($strategy == 'package&free' && ($goods->type == 2 || $goods->price == 0))){
-			$noneExpireOrderExist = Order::uid()->where('status', '>=', 0)->where('is_expire', 0)->where('goods_id', $goods_id)->exists();
-			if($noneExpireOrderExist){
-				return Response::json(['status' => 'fail', 'data' => '', 'message' => '创建支付单失败:商品不可重复购买']);
-			}
-		}
-
 		// 单个商品限购
-		if($goods->is_limit == 1){
-			$noneExpireOrderExist = Order::uid()->where('status', '>=', 0)->where('goods_id', $goods_id)->exists();
-			if($noneExpireOrderExist){
-				return Response::json(['status' => 'fail', 'data' => '', 'message' => '创建支付单失败:此商品每人限购1次']);
+		if($goods->limit_num){
+			$count = Order::uid()->where('status', '>=', 0)->where('goods_id', $goods_id)->count();
+			if($count >= $goods->limit_num){
+				return Response::json(['status' => 'fail', 'data' => '', 'message' => '此商品/服务限购'.$goods->limit_num.'次,您已购买'.$count.'次']);
 			}
 		}
 
@@ -103,7 +94,7 @@ class PaymentController extends Controller
 
 			foreach($existOrderList as $vo){
 				if($vo->goods->days > $goods->days){
-					return Response::json(['status' => 'fail', 'data' => '', 'message' => '支付失败:您已存在有效期更长的套餐,只能购买流量包']);
+					return Response::json(['status' => 'info', 'title' => '套餐冲突', 'message' => '是否将本次套餐存为 【预支付】?套餐会在已有套餐失效后生效,或者您可以手动激活套餐']);
 				}
 			}
 		}
@@ -162,37 +153,37 @@ class PaymentController extends Controller
 			}elseif(self::$systemConfig['is_f2fpay']){
 				// TODO:goods表里增加一个字段用于自定义商品付款时展示的商品名称,
 				// TODO:这里增加一个随机商品列表,根据goods的价格随机取值
-				$result = Charge::run("ali_qr", ['use_sandbox' => FALSE, "partner" => self::$systemConfig['f2fpay_app_id'], 'app_id' => self::$systemConfig['f2fpay_app_id'], 'sign_type' => 'RSA2', 'ali_public_key' => self::$systemConfig['f2fpay_public_key'], 'rsa_private_key' => self::$systemConfig['f2fpay_private_key'], 'notify_url' => self::$systemConfig['website_url']."/api/f2fpay", // 异步回调接口
-				                                 'return_url'  => self::$systemConfig['website_url'], 'return_raw' => FALSE], ['body' => '', 'subject' => self::$systemConfig['f2fpay_subject_name'], 'order_no' => $orderSn, 'amount' => $amount,]);
-			}
+					$result = Charge::run("ali_qr", ['use_sandbox' => FALSE, "partner" => self::$systemConfig['f2fpay_app_id'], 'app_id' => self::$systemConfig['f2fpay_app_id'], 'sign_type' => 'RSA2', 'ali_public_key' => self::$systemConfig['f2fpay_public_key'], 'rsa_private_key' => self::$systemConfig['f2fpay_private_key'], 'notify_url' => self::$systemConfig['website_url']."/api/f2fpay", // 异步回调接口
+					                                 'return_url'  => self::$systemConfig['website_url'], 'return_raw' => FALSE], ['body' => '', 'subject' => self::$systemConfig['f2fpay_subject_name'], 'order_no' => $orderSn, 'amount' => $amount,]);
+				}
 
-			$payment = new Payment();
-			$payment->sn = $sn;
-			$payment->user_id = Auth::user()->id;
-			$payment->oid = $order->oid;
-			$payment->order_sn = $orderSn;
-			$payment->pay_way = 1;
-			$payment->amount = $amount;
-			if(self::$systemConfig['is_youzan']){
-				$payment->qr_id = $result['response']['qr_id'];
-				$payment->qr_url = $result['response']['qr_url'];
-				$payment->qr_code = $result['response']['qr_code'];
-				$payment->qr_local_url = $this->base64ImageSaver($result['response']['qr_code']);
-			}elseif(self::$systemConfig['is_alipay']){
-				$payment->qr_code = $result;
-			}elseif(self::$systemConfig['is_f2fpay']){
-				$payment->qr_code = $result;
-				$payment->qr_url = 'http://qr.topscan.com/api.php?text='.$result.'&bg=ffffff&fg=000000&pt=1c73bd&m=10&w=400&el=1&inpt=1eabfc&logo=https://t.alipayobjects.com/tfscom/T1Z5XfXdxmXXXXXXXX.png';
-				$payment->qr_local_url = $payment->qr_url;
-			}
-			$payment->status = 0;
-			$payment->save();
-
-			// 优惠券置为已使用
-			if(!empty($coupon)){
-				if($coupon->usage == 1){
-					$coupon->status = 1;
-					$coupon->save();
+				$payment = new Payment();
+				$payment->sn = $sn;
+				$payment->user_id = Auth::user()->id;
+				$payment->oid = $order->oid;
+				$payment->order_sn = $orderSn;
+				$payment->pay_way = 1;
+				$payment->amount = $amount;
+				if(self::$systemConfig['is_youzan']){
+					$payment->qr_id = $result['response']['qr_id'];
+					$payment->qr_url = $result['response']['qr_url'];
+					$payment->qr_code = $result['response']['qr_code'];
+					$payment->qr_local_url = $this->base64ImageSaver($result['response']['qr_code']);
+				}elseif(self::$systemConfig['is_alipay']){
+					$payment->qr_code = $result;
+				}elseif(self::$systemConfig['is_f2fpay']){
+					$payment->qr_code = $result;
+					$payment->qr_url = 'http://qr.topscan.com/api.php?text='.$result.'&bg=ffffff&fg=000000&pt=1c73bd&m=10&w=400&el=1&inpt=1eabfc&logo=https://t.alipayobjects.com/tfscom/T1Z5XfXdxmXXXXXXXX.png';
+					$payment->qr_local_url = $payment->qr_url;
+				}
+				$payment->status = 0;
+				$payment->save();
+
+				// 优惠券置为已使用
+				if(!empty($coupon)){
+					if($coupon->usage == 1){
+						$coupon->status = 1;
+						$coupon->save();
 				}
 
 				Helpers::addCouponLog($coupon->id, $goods_id, $order->oid, '在线支付使用');

+ 1 - 0
app/Http/Controllers/SensitiveWordsController.php

@@ -39,6 +39,7 @@ class SensitiveWordsController extends Controller
 		}
 
 		$obj = new SensitiveWords();
+		$obj->type = $request->type;
 		$obj->words = strtolower($request->words);
 		$obj->save();
 		if($obj->id){

+ 24 - 3
app/Http/Controllers/ShopController.php

@@ -54,6 +54,9 @@ class ShopController extends Controller
 				return Redirect::back()->withInput()->withErrors('套餐价格必须大于0');
 			}
 
+			if($request->renew < 0){
+				return Redirect::back()->withInput()->withErrors('流量重置价格必须大于0');
+			}
 			// 套餐有效天数必须大于30天
 			if($request->type == 2 && $request->days < 1){
 				return Redirect::back()->withInput()->withErrors('套餐有效天数必须不能少于1天');
@@ -85,12 +88,13 @@ class ShopController extends Controller
 				$goods->logo = $logo;
 				$goods->traffic = $request->traffic;
 				$goods->price = round($request->price, 2);
+				$goods->renew = round($request->renew, 2);
 				$goods->type = $request->type;
 				$goods->days = $request->days;
 				$goods->color = $request->color;
 				$goods->sort = $request->sort;
 				$goods->is_hot = $request->is_hot;
-				$goods->is_limit = $request->is_limit;
+				$goods->limit_num = $request->limit_num;
 				$goods->status = $request->status;
 				$goods->save();
 
@@ -133,11 +137,12 @@ class ShopController extends Controller
 			$info = $request->input('info');
 			$desc = $request->input('desc');
 			$price = round($request->input('price'), 2);
+			$renew = round($request->input('renew'), 2);
 			$labels = $request->input('labels');
 			$color = $request->input('color');
 			$sort = $request->input('sort');
 			$is_hot = $request->input('is_hot');
-			$is_limit = $request->input('is_limit');
+			$limit_num = $request->input('limit_num');
 			$status = $request->input('status');
 
 			$goods = Goods::query()->where('id', $id)->first();
@@ -160,6 +165,12 @@ class ShopController extends Controller
 				return Redirect::back()->withInput();
 			}
 
+			if($renew < 0){
+				Session::flash('errorMsg', '流量重置价格必须大于0');
+
+				return Redirect::back()->withInput();
+			}
+
 			// 商品LOGO
 			$logo = '';
 			if($request->hasFile('logo')){
@@ -180,7 +191,17 @@ class ShopController extends Controller
 
 			DB::beginTransaction();
 			try{
-				$data = ['name' => $name, 'info' => $info, 'desc' => $desc, 'price' => $price*100, 'sort' => $sort, 'color' => $color, 'is_hot' => $is_hot, 'is_limit' => $is_limit, 'status' => $status];
+				$data = [
+					'name'      => $name,
+					'info'      => $info,
+					'desc'      => $desc,
+					'price'     => $price*100,
+					'renew'     => $renew*100,
+					'sort'      => $sort,
+					'color'     => $color,
+					'is_hot'    => $is_hot,
+					'limit_num' => $limit_num,
+					'status'    => $status];
 
 				if($logo){
 					$data['logo'] = $logo;

+ 38 - 19
app/Http/Controllers/SubscribeController.php

@@ -37,7 +37,7 @@ class SubscribeController extends Controller
 		$username = $request->input('username');
 		$status = $request->input('status');
 
-		$query = UserSubscribe::with(['User']);
+		$query = UserSubscribe::with(['user:id,username']);
 
 		if(isset($user_id)){
 			$query->where('user_id', $user_id);
@@ -58,6 +58,21 @@ class SubscribeController extends Controller
 		return Response::view('subscribe.subscribeList', $view);
 	}
 
+	//订阅记录
+	public function subscribeLog(Request $request)
+	{
+		$id = $request->input('id');
+		$query = UserSubscribeLog::with('user:username');
+
+		if(isset($id)){
+			$query->where('sid',$id);
+		}
+
+		$view['subscribeLog'] = $query->orderBy('id', 'desc')->paginate(20)->appends($request->except('page'));
+
+		return Response::view('subscribe.subscribeLog', $view);
+	}
+
 	// 订阅设备列表
 	public function deviceList(Request $request)
 	{
@@ -175,8 +190,7 @@ class SubscribeController extends Controller
 
 		// 展示到期时间和剩余流量
 		if(self::$systemConfig['is_custom_subscribe']){
-			$scheme .= $this->expireDate($user);
-			$scheme .= $this->lastTraffic($user);
+			$scheme .= $this->expireDate($user).$this->lastTraffic($user);
 		}
 
 		foreach($nodeList as $key => $node){
@@ -184,32 +198,37 @@ class SubscribeController extends Controller
 			if(self::$systemConfig['subscribe_max'] && $key >= self::$systemConfig['subscribe_max']){
 				break;
 			}
-
 			// 获取分组名称
+			$host = $node['server']? : $node['ip'];
 			if($node['type'] == 1){
 				$group = SsGroup::query()->where('id', $node['group_id'])->first();
-
-				$obfs_param = $user->obfs_param? $user->obfs_param : $node['obfs_param'];
-				$protocol_param = $node['single']? $user->port.':'.$user->passwd : $user->protocol_param;
+				$group = empty($group)? Helpers::systemConfig()['website_name'] : $group->name;
+				$obfs_param = $user->obfs_param? : $node['obfs_param'];
+
+				if($node['single']){
+					$port = $node['port'];
+					$protocol = $node['protocol'];
+					$method = $node['method'];
+					$obfs = $node['obfs'];
+					$passwd = $node['passwd'];
+					$protocol_param = $user->port.':'.$user->passwd;
+				}else{
+					$port = $user->port;
+					$protocol = $user->protocol;
+					$method = $user->method;
+					$obfs = $user->obfs;
+					$passwd = $user->passwd;
+					$protocol_param = $user->protocol_param;
+				}
 
 				// 生成ssr scheme
-				$ssr_str = ($node['server']? $node['server'] : $node['ip']).':'.($node['single']? $node['single_port'] : $user->port);
-				$ssr_str .= ':'.($node['single']? $node['single_protocol'] : $user->protocol).':'.($node['single']? $node['single_method'] : $user->method);
-				$ssr_str .= ':'.($node['single']? $node['single_obfs'] : $user->obfs).':'.($node['single']? base64url_encode($node['single_passwd']) : base64url_encode($user->passwd));
-				$ssr_str .= '/?obfsparam='.base64url_encode($obfs_param);
-				$ssr_str .= '&protoparam='.($node['single']? base64url_encode($user->port.':'.$user->passwd) : base64url_encode($protocol_param));
-				$ssr_str .= '&remarks='.base64url_encode($node['name']);
-				$ssr_str .= '&group='.base64url_encode(empty($group)? Helpers::systemConfig()['website_name'] : $group->name);
-				$ssr_str .= '&udpport=0';
-				$ssr_str .= '&uot=0';
-				$ssr_str = base64url_encode($ssr_str);
-				$scheme .= 'ssr://'.$ssr_str."\n";
+				$scheme .= 'ssr://'.base64url_encode($host.':'.$port.':'.$protocol.':'.$method.':'.$obfs.':'.base64url_encode($passwd).'/?obfsparam='.base64url_encode($obfs_param).'&protoparam='.base64url_encode($protocol_param).'&remarks='.base64url_encode($node['name']).'&group='.base64url_encode($group).'&udpport=0&uot=0')."\n";
 			}else{
 				// 生成v2ray scheme
 				$v2_json = [
 					"v"    => "2",
 					"ps"   => $node['name'],
-					"add"  => $node['server']? $node['server'] : $node['ip'],
+					"add"  => $host,
 					"port" => $node['v2_port'],
 					"id"   => $user->vmess_id,
 					"aid"  => $node['v2_alter_id'],

+ 3 - 3
app/Http/Controllers/TicketController.php

@@ -75,9 +75,9 @@ class TicketController extends Controller
 
 				// 发通知邮件
 				if(!Auth::user()->is_admin){
-					if(self::$systemConfig['crash_warning_email']){
-						$logId = Helpers::addEmailLog(self::$systemConfig['crash_warning_email'], $title, $content);
-						Mail::to(self::$systemConfig['crash_warning_email'])->send(new replyTicket($logId, $title, $content));
+					if(self::$systemConfig['webmaster_email']){
+						$logId = Helpers::addEmailLog(self::$systemConfig['webmaster_email'], $title, $content);
+						Mail::to(self::$systemConfig['webmaster_email'])->send(new replyTicket($logId, $title, $content));
 					}
 				}else{
 					$logId = Helpers::addEmailLog($ticket->user->username, $title, $content);

+ 94 - 97
app/Http/Controllers/UserController.php

@@ -74,7 +74,7 @@ class UserController extends Controller
 		$view['resetDays'] = $resetDays;
 		$view['unusedTransfer'] = $unusedTransfer;
 		$view['expireTime'] = $expireTime;
-		$view['banedTime'] =  Auth::user()->ban_time != 0? date('Y-m-d H:i:s', Auth::user()->ban_time) : 0;;
+		$view['banedTime'] = Auth::user()->ban_time != 0? date('Y-m-d H:i:s', Auth::user()->ban_time) : 0;;
 		$view['unusedPercent'] = $totalTransfer > 0? round($unusedTransfer/$totalTransfer, 2) : 0;
 		$view['noticeList'] = Article::type(2)->orderBy('id', 'desc')->Paginate(1); // 公告
 		//流量异常判断
@@ -176,82 +176,63 @@ class UserController extends Controller
 		$nodeList = DB::table('ss_node')->selectRaw('ss_node.*')->leftJoin('ss_node_label', 'ss_node.id', '=', 'ss_node_label.node_id')->whereIn('ss_node_label.label_id', $userLabelIds)->where('ss_node.status', 1)->groupBy('ss_node.id')->orderBy('ss_node.sort', 'desc')->orderBy('ss_node.id', 'asc')->get();
 
 		$allNodes = ''; // 全部节点SSR链接,用于一键复制所有节点
-		foreach($nodeList as &$node){
+		foreach($nodeList as $node){
 			// 获取分组名称
 			$group = SsGroup::query()->where('id', $node->group_id)->first();
-
+			$host = $node->server? : $node->ip;
 			if($node->type == 1){
-				$server = $node->server? : $node->ip;
-				$port = $node->single? $node->single_port : Auth::user()->port;
-				$protocol = $node->single? $node->single_protocol : Auth::user()->protocol;
-				$method = $node->single? $node->single_method : Auth::user()->method;
-				$obfs = $node->single? $node->single_obfs : Auth::user()->obfs;
-				$passwd = $node->single? $node->single_passwd : Auth::user()->passwd;
-				$obfs_param = Auth::user()->obfs_param? Auth::user()->obfs_param : $node->obfs_param;
-				$protocol_param = $node->single? Auth::user()->port.':'.Auth::user()->passwd : Auth::user()->protocol_param;
+				$obfs_param = Auth::user()->obfs_param? : $node->obfs_param;
 				$group = empty($group)? Helpers::systemConfig()['website_name'] : $group->name;
+				if($node->single){
+					$port = $node->port;
+					$protocol = $node->protocol;
+					$method = $node->method;
+					$obfs = $node->obfs;
+					$passwd = $node->passwd;
+					$protocol_param = Auth::user()->port.':'.Auth::user()->passwd;
+				}else{
+					$port = Auth::user()->port;
+					$protocol = Auth::user()->protocol;
+					$method = Auth::user()->method;
+					$obfs = Auth::user()->obfs;
+					$passwd = Auth::user()->passwd;
+					$protocol_param = Auth::user()->protocol_param;
+				}
 
 				// 生成ssr scheme
-				$ssr_str = $server.':'.$port;
-				$ssr_str .= ':'.$protocol.':'.$method;
-				$ssr_str .= ':'.$obfs.':'.base64url_encode($passwd);
-				$ssr_str .= '/?obfsparam='.base64url_encode($obfs_param);
-				$ssr_str .= '&protoparam='.base64url_encode($protocol_param);
-				$ssr_str .= '&remarks='.base64url_encode($node->name);
-				$ssr_str .= '&group='.base64url_encode($group);
-				$ssr_str .= '&udpport=0';
-				$ssr_str .= '&uot=0';
-				$ssr_str = base64url_encode($ssr_str);
-				$ssr_scheme = 'ssr://'.$ssr_str;
-
+				$node->ssr_scheme = 'ssr://'.base64url_encode($host.':'.$port.':'.$protocol.':'.$method.':'.$obfs.':'.base64url_encode($passwd).'/?obfsparam='.base64url_encode($obfs_param).'&protoparam='.base64url_encode($protocol_param).'&remarks='.base64url_encode($node->name).'&group='.base64url_encode($group).'&udpport=0&uot=0');
+				$allNodes .= $node->ssr_scheme.'|';
 				// 生成ss scheme
-				$ss_str = Auth::user()->method.':'.Auth::user()->passwd.'@';
-				$ss_str .= ($node->server? : $node->ip).':'.Auth::user()->port;
-				$ss_str = base64url_encode($ss_str).'#'.'VPN';
-				$ss_scheme = 'ss://'.$ss_str;
+				$node->ss_scheme = $node->compatible? 'ss://'.base64url_encode(Auth::user()->method.':'.Auth::user()->passwd.'@'.$host.':'.Auth::user()->port).'#'.$group : '';
 
 				// 生成文本配置信息
-				$txt = "服务器:".$server.PHP_EOL;
-				if($node->ipv6){
-					$txt .= "IPv6:".$node->ipv6.PHP_EOL;
-				}
-				$txt .= "远程端口:".$port.PHP_EOL;
-				$txt .= "密码:".$passwd.PHP_EOL;
-				$txt .= "加密方法:".$method.PHP_EOL;
-				$txt .= "路由:绕过局域网及中国大陆地址".PHP_EOL.PHP_EOL;
-				$txt .= "协议:".$protocol.PHP_EOL;
-				$txt .= "协议参数:".$protocol_param.PHP_EOL;
-				$txt .= "混淆方式:".$obfs.PHP_EOL;
-				$txt .= "混淆参数:".$obfs_param.PHP_EOL;
-				$txt .= "本地端口:1080".PHP_EOL;
-
-				$node->txt = $txt;
-				$node->ssr_scheme = $ssr_scheme;
-				$node->ss_scheme = $node->compatible? $ss_scheme : ''; // 节点兼容原版才显示
-
-				$allNodes .= $ssr_scheme.'|';
+				$node->txt = "服务器:".$host.PHP_EOL.
+					($node->ipv6? "IPv6:".$node->ipv6.PHP_EOL : '').
+					"远程端口:".$port.PHP_EOL.
+					"密码:".$passwd.PHP_EOL.
+					"加密方法:".$method.PHP_EOL.
+					"路由:绕过局域网及中国大陆地址".PHP_EOL.
+					"协议:".$protocol.PHP_EOL.
+					"协议参数:".$protocol_param.PHP_EOL.
+					"混淆方式:".$obfs.PHP_EOL.
+					"混淆参数:".$obfs_param.PHP_EOL.
+					"本地端口:1080".PHP_EOL;
 			}else{
 				// 生成v2ray scheme
-				$v2_json = ["v" => "2", "ps" => $node->name, "add" => $node->server? : $node->ip, "port" => $node->v2_port, "id" => Auth::user()->vmess_id, "aid" => $node->v2_alter_id, "net" => $node->v2_net, "type" => $node->v2_type, "host" => $node->v2_host, "path" => $node->v2_path, "tls" => $node->v2_tls == 1? "tls" : ""];
-				$v2_scheme = 'vmess://'.base64_encode(json_encode($v2_json, JSON_PRETTY_PRINT));
+				$node->v2_scheme = 'vmess://'.base64_encode(json_encode(["v" => "2", "ps" => $node->name, "add" => $node->server? : $node->ip, "port" => $node->v2_port, "id" => Auth::user()->vmess_id, "aid" => $node->v2_alter_id, "net" => $node->v2_net, "type" => $node->v2_type, "host" => $node->v2_host, "path" => $node->v2_path, "tls" => $node->v2_tls == 1? "tls" : ""], JSON_PRETTY_PRINT));
 
 				// 生成文本配置信息
-				$txt = "服务器:".$node->server? : $node->ip.PHP_EOL;
-				if($node->ipv6){
-					$txt .= "IPv6:".$node->ipv6.PHP_EOL;
-				}
-				$txt .= "端口:".$node->v2_port.PHP_EOL;
-				$txt .= "加密方式:".$node->v2_method.PHP_EOL;
-				$txt .= "用户ID:".Auth::user()->vmess_id.PHP_EOL;
-				$txt .= "额外ID:".$node->v2_alter_id.PHP_EOL;
-				$txt .= "传输协议:".$node->v2_net.PHP_EOL;
-				$txt .= "伪装类型:".$node->v2_type.PHP_EOL;
-				$txt .= $node->v2_host? "伪装域名:".$node->v2_host.PHP_EOL : "";
-				$txt .= $node->v2_path? "路径:".$node->v2_path.PHP_EOL : "";
-				$txt .= $node->v2_tls? "TLS:tls".PHP_EOL : "";
-
-				$node->txt = $txt;
-				$node->v2_scheme = $v2_scheme;
+				$node->txt = "服务器:".$host.PHP_EOL.
+					($node->ipv6? "IPv6:".$node->ipv6.PHP_EOL : '').
+					"端口:".$node->v2_port.PHP_EOL.
+					"加密方式:".$node->v2_method.PHP_EOL.
+					"用户ID:".Auth::user()->vmess_id.PHP_EOL.
+					"额外ID:".$node->v2_alter_id.PHP_EOL.
+					"传输协议:".$node->v2_net.PHP_EOL.
+					"伪装类型:".$node->v2_type.PHP_EOL.
+					($node->v2_host? "伪装域名:".$node->v2_host.PHP_EOL : "").
+					($node->v2_path? "路径:".$node->v2_path.PHP_EOL : "").
+					($node->v2_tls? "TLS:tls".PHP_EOL : "");
 			}
 
 			// 节点在线状态
@@ -343,10 +324,33 @@ class UserController extends Controller
 		// 余额充值商品,只取10个
 		$view['chargeGoodsList'] = Goods::type(3)->where('status', 1)->orderBy('price', 'asc')->orderBy('price', 'asc')->limit(10)->get();
 		$view['goodsList'] = Goods::query()->where('status', 1)->where('type', '<=', '2')->orderBy('type', 'desc')->orderBy('sort', 'desc')->paginate(10)->appends($request->except('page'));
+		$temp = Order::uid()->where('status', 2)->where('is_expire', 0)->first();
+		$view['renewTraffic'] = $temp? Goods::query()->where('id', $temp->goods_id)->first()->renew : 0;
+
 
 		return Response::view('user.services', $view);
 	}
 
+	//重置流量
+	public function resetUserTraffic(Request $request)
+	{
+		$temp = Order::uid()->where('status', 2)->where('is_expire', 0)->first();
+		$renewCost = Goods::query()->where('id', $temp->goods_id)->first()->renew;
+		if(Auth::user()->balance < $renewCost){
+			return Response::json(['status' => 'fail', 'data' => '', 'message' => '余额不足,请充值余额']);
+		}else{
+			User::uid()->update(['u' => 0, 'd' => 0]);
+
+			// 扣余额
+			User::query()->where('id', Auth::user()->id)->decrement('balance', $renewCost*100);
+
+			// 记录余额操作日志
+			$this->addUserBalanceLog(Auth::user()->id, '', Auth::user()->balance, Auth::user()->balance-$renewCost, -1*$renewCost, '用户自行重置流量');
+
+			return Response::json(['status' => 'success', 'data' => '', 'message' => '重置成功']);
+		}
+	}
+
 	// 工单
 	public function ticketList(Request $request)
 	{
@@ -394,9 +398,9 @@ class UserController extends Controller
 			$content = "标题:【".$title."】<br>用户:".Auth::user()->username."<br>内容:".$content;
 
 			// 发邮件通知管理员
-			if(self::$systemConfig['crash_warning_email']){
-				$logId = Helpers::addEmailLog(self::$systemConfig['crash_warning_email'], $emailTitle, $content);
-				Mail::to(self::$systemConfig['crash_warning_email'])->send(new newTicket($logId, $emailTitle, $content));
+			if(self::$systemConfig['webmaster_email']){
+				$logId = Helpers::addEmailLog(self::$systemConfig['webmaster_email'], $emailTitle, $content);
+				Mail::to(self::$systemConfig['webmaster_email'])->send(new newTicket($logId, $emailTitle, $content));
 			}
 
 			ServerChan::send($emailTitle, $content);
@@ -442,9 +446,9 @@ class UserController extends Controller
 				$content = "标题:【".$ticket->title."】<br>用户回复:".$content;
 
 				// 发邮件通知管理员
-				if(self::$systemConfig['crash_warning_email']){
-					$logId = Helpers::addEmailLog(self::$systemConfig['crash_warning_email'], $title, $content);
-					Mail::to(self::$systemConfig['crash_warning_email'])->send(new replyTicket($logId, $title, $content));
+				if(self::$systemConfig['webmaster_email']){
+					$logId = Helpers::addEmailLog(self::$systemConfig['webmaster_email'], $title, $content);
+					Mail::to(self::$systemConfig['webmaster_email'])->send(new replyTicket($logId, $title, $content));
 				}
 
 				ServerChan::send($title, $content);
@@ -480,7 +484,7 @@ class UserController extends Controller
 	public function invite(Request $request)
 	{
 		if(Order::uid()->where('status', 2)->where('is_expire', 0)->where('origin_amount', '>', 0)->get()->isEmpty()){
-			return Response::view('auth.error', ['message' => '本功能对非付费用户禁用!请 <a class="btn btn-sm btn-danger" href="/">返回</a>']);
+			return Response::view('auth.error', ['message' => '本功能对非付费用户禁用!请 <a class="btn btn-sm btn-danger" href="/">返 回</a>']);
 		}
 		// 已生成的邀请码数量
 		$num = Invite::uid()->count();
@@ -517,25 +521,28 @@ class UserController extends Controller
 	public function redeemCoupon(Request $request)
 	{
 		$coupon_sn = $request->input('coupon_sn');
+		$good_price = $request->input('price');
 
 		if(empty($coupon_sn)){
-			return Response::json(['status' => 'fail', 'data' => '', 'message' => '优惠券不能为空']);
+			return Response::json(['status' => 'fail', 'title' => '使用失败', 'message' => '请输入您的优惠劵!']);
 		}
 
 		$coupon = Coupon::query()->where('sn', $coupon_sn)->whereIn('type', [1, 2])->first();
 		if(!$coupon){
-			return Response::json(['status' => 'fail', 'data' => '', 'message' => '该优惠券不存在']);
+			return Response::json(['status' => 'fail', 'title' => '优惠券不存在', 'message' => '请确认优惠券是否输入正确!']);
 		}elseif($coupon->status == 1){
-			return Response::json(['status' => 'fail', 'data' => '', 'message' => '该优惠券已使用,请换一个试试']);
+			return Response::json(['status' => 'fail', 'title' => '抱歉', 'message' => '优惠券已被使用!']);
 		}elseif($coupon->status == 2){
-			return Response::json(['status' => 'fail', 'data' => '', 'message' => '该优惠券已失效,请换一个试试']);
+			return Response::json(['status' => 'fail', 'title' => '抱歉', 'message' => '优惠券已失效!']);
 		}elseif($coupon->available_end < time()){
 			$coupon->status = 2;
 			$coupon->save();
 
-			return Response::json(['status' => 'fail', 'data' => '', 'message' => '该优惠券已失效,请换一个试试']);
+			return Response::json(['status' => 'fail', 'title' => '抱歉', 'message' => '优惠券已失效!']);
 		}elseif($coupon->available_start > time()){
-			return Response::json(['status' => 'fail', 'data' => '', 'message' => '该优惠券尚不可用,请换一个试试']);
+			return Response::json(['status' => 'fail', 'title' => '优惠券尚未生效', 'message' => '请等待活动正式开启']);
+		}elseif($good_price < $coupon->rule){
+			return Response::json(['status' => 'fail', 'title' => '使用条件未满足', 'message' => '请购买价格更高的套餐']);
 		}
 
 		$data = ['name' => $coupon->name, 'type' => $coupon->type, 'amount' => $coupon->amount, 'discount' => $coupon->discount];
@@ -554,20 +561,11 @@ class UserController extends Controller
 				return Response::json(['status' => 'fail', 'data' => '', 'message' => '支付失败:商品或服务已下架']);
 			}
 
-			// 限购控制:all-所有商品限购, free-价格为0的商品限购, none-不限购(默认)
-			$strategy = self::$systemConfig['goods_purchase_limit_strategy'];
-			if($strategy == 'all' || ($strategy == 'package' && $goods->type == 2) || ($strategy == 'free' && $goods->price == 0) || ($strategy == 'package&free' && ($goods->type == 2 || $goods->price == 0))){
-				$noneExpireGoodExist = Order::uid()->where('status', '>=', 0)->where('is_expire', 0)->where('goods_id', $goods_id)->exists();
-				if($noneExpireGoodExist){
-					return Response::json(['status' => 'fail', 'data' => '', 'message' => '支付失败:商品不可重复购买']);
-				}
-			}
-
-			// 单个商品限购
-			if($goods->is_limit == 1){
-				$noneExpireOrderExist = Order::uid()->where('status', '>=', 0)->where('goods_id', $goods_id)->exists();
-				if($noneExpireOrderExist){
-					return Response::json(['status' => 'fail', 'data' => '', 'message' => '创建支付单失败:此商品每人限购1次']);
+			// 商品限购
+			if($goods->limit_num){
+				$count = Order::uid()->where('status', '>=', 0)->where('goods_id', $goods_id)->count();
+				if($count >= $goods->limit_num){
+					return Response::json(['status' => 'fail', 'data' => '', 'message' => '此商品/服务限购'.$goods->limit_num.'次,您已购买'.$count.'次']);
 				}
 			}
 
@@ -587,12 +585,12 @@ class UserController extends Controller
 
 			// 价格异常判断
 			if($amount < 0){
-				return Response::json(['status' => 'fail', 'data' => '', 'message' => '支付失败:订单总价异常']);
+				return Response::json(['status' => 'fail', 'data' => '', 'message' => '订单总价异常']);
 			}
 
 			// 验证账号余额是否充足
 			if(Auth::user()->balance < $amount){
-				return Response::json(['status' => 'fail', 'data' => '', 'message' => '支付失败:您的余额不足,请先充值']);
+				return Response::json(['status' => 'fail', 'data' => '', 'message' => '您的余额不足,请先充值']);
 			}
 
 			// 验证账号是否存在有效期更长的套餐
@@ -603,7 +601,7 @@ class UserController extends Controller
 
 				foreach($existOrderList as $vo){
 					if($vo->goods->days > $goods->days){
-						return Response::json(['status' => 'fail', 'data' => '', 'message' => '支付失败:您已存在有效期更长的套餐,只能购买流量包']);
+						return Response::json(['status' => 'info', 'title' => '套餐冲突', 'message' => '是否将本次套餐存为 【预支付】?套餐会在已有套餐失效后生效,或者您可以手动激活套餐']);
 					}
 				}
 			}
@@ -683,8 +681,7 @@ class UserController extends Controller
 
 				// 套餐就改流量重置日,流量包不改
 				if($goods->type == 2){
-					$traffic_reset_day = date('d');
-					User::query()->uid()->update(['traffic_reset_day' => $traffic_reset_day, 'expire_time' => $expireTime, 'enable' => 1]);
+					User::query()->uid()->update(['traffic_reset_day' => date('d'), 'expire_time' => $expireTime, 'enable' => 1]);
 				}else{
 					User::query()->uid()->update(['expire_time' => $expireTime, 'enable' => 1]);
 				}
@@ -750,7 +747,7 @@ class UserController extends Controller
 	public function referral(Request $request)
 	{
 		if(Order::uid()->where('status', 2)->where('is_expire', 0)->where('origin_amount', '>', 0)->get()->isEmpty()){
-			return Response::view('auth.error', ['message' => '本功能对非付费用户禁用!请 <a class="btn btn-sm btn-danger" href="/">返回</a>']);
+			return Response::view('auth.error', ['message' => '本功能对非付费用户禁用!请 <a class="btn btn-sm btn-danger" href="/">返 回</a>']);
 		}
 		$view['referral_traffic'] = flowAutoShow(self::$systemConfig['referral_traffic']*1048576);
 		$view['referral_percent'] = self::$systemConfig['referral_percent'];

+ 10 - 0
app/Http/Models/Coupon.php

@@ -46,4 +46,14 @@ class Coupon extends Model
 	{
 		$this->attributes['discount'] = $value/10;
 	}
+
+	function getRuleAttribute($value)
+	{
+		return $value/100;
+	}
+
+	function setRuleAttribute($value)
+	{
+		$this->attributes['rule'] = $value*100;
+	}
 }

+ 10 - 0
app/Http/Models/Goods.php

@@ -40,6 +40,16 @@ class Goods extends Model
 		$this->attributes['price'] = $value*100;
 	}
 
+	function getRenewAttribute($value)
+	{
+		return $value/100;
+	}
+
+	function setRenewAttribute($value)
+	{
+		return $this->attributes['renew'] = $value*100;
+	}
+
 	function getTrafficLabelAttribute()
 	{
 		$traffic_label = flowAutoShow($this->attributes['traffic']*1048576);

+ 20 - 0
app/Http/Models/Invite.php

@@ -13,6 +13,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
  *
  * @package App\Http\Models
  * @mixin Eloquent
+ * @property-read mixed $status_label
  */
 class Invite extends Model
 {
@@ -37,4 +38,23 @@ class Invite extends Model
 		return $this->hasOne(User::class, 'id', 'fuid');
 	}
 
+	function getStatusLabelAttribute()
+	{
+		switch($this->attributes['status']){
+			case 0:
+				$status_label = '<span class="badge badge-success">'.trans('home.invite_code_table_status_un').'</span>';
+				break;
+			case 1:
+				$status_label = '<span class="badge badge-danger">'.trans('home.invite_code_table_status_yes').'</span>';
+				break;
+			case 2:
+				$status_label = '<span class="badge badge-default">'.trans('home.invite_code_table_status_expire').'</span>';
+				break;
+			default:
+				$status_label = '<span class="badge badge-default"> 未知 </span>';
+		}
+
+		return $status_label;
+	}
+
 }

+ 1 - 0
app/Http/Models/Order.php

@@ -12,6 +12,7 @@ use Illuminate\Database\Eloquent\Model;
  *
  * @package App\Http\Models
  * @mixin Eloquent
+ * @property-read mixed $status_label
  */
 class Order extends Model
 {

+ 21 - 0
app/Http/Models/Ticket.php

@@ -12,6 +12,7 @@ use Illuminate\Database\Eloquent\Model;
  *
  * @package App\Http\Models
  * @mixin Eloquent
+ * @property-read mixed $status_label
  */
 class Ticket extends Model
 {
@@ -27,4 +28,24 @@ class Ticket extends Model
 	{
 		return $this->hasOne(User::class, 'id', 'user_id');
 	}
+
+	function getStatusLabelAttribute()
+	{
+		switch($this->attributes['status']){
+			case 0:
+				$status_label = '<span class="badge badge-lg badge-success">'.trans('home.ticket_table_status_wait').'</span>';
+				break;
+			case 1:
+				$status_label = '<span class="badge badge-lg badge-danger">'.trans('home.ticket_table_status_reply').'</span>';
+				break;
+			case 2:
+				$status_label = '<span class="badge badge-lg badge-default">'.trans('home.ticket_table_status_close').'</span>';
+				break;
+			default:
+				$status_label = '<span class="badge badge-lg badge-default"> 未知 </span>';
+		}
+
+		return $status_label;
+	}
+
 }

+ 1 - 1
app/Http/Models/UserSubscribe.php

@@ -23,7 +23,7 @@ class UserSubscribe extends Model
 		return $query->where('user_id', Auth::user()->id);
 	}
 
-	function User()
+	function user()
 	{
 		return $this->hasOne(User::class, 'id', 'user_id');
 	}

+ 4 - 0
app/Http/Models/UserSubscribeLog.php

@@ -18,4 +18,8 @@ class UserSubscribeLog extends Model
 	protected $primaryKey = 'id';
 	public $timestamps = FALSE;
 
+	function user()
+	{
+		return $this->hasManyThrough(User::class, UserSubscribe::class, 'id', 'id', 'sid', 'user_id');
+	}
 }

+ 3 - 2
composer.json

@@ -6,7 +6,6 @@
   "type": "project",
   "require": {
     "php": "^7.1.3",
-    "barryvdh/laravel-debugbar": "^3.2",
     "fideloper/proxy": "^4.0",
     "guzzlehttp/guzzle": "^6.3",
     "ipip/db": "^1.0",
@@ -25,9 +24,11 @@
     "rap2hpoutre/laravel-log-viewer": "^1.0",
     "riverslei/payment": "*",
     "spatie/laravel-permission": "^2.29",
-    "youzanyun/open-sdk": "^2.0"
+    "youzanyun/open-sdk": "^2.0",
+    "ext-json": "*"
   },
   "require-dev": {
+    "barryvdh/laravel-debugbar": "^3.2",
     "barryvdh/laravel-ide-helper": "^2.6",
     "filp/whoops": "^2.0",
     "fzaninotto/faker": "^1.4",

+ 142 - 142
composer.lock

@@ -4,82 +4,8 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "289a4aa7e26844e508f3349856ee02a2",
+    "content-hash": "c575616151e10cb51aa5566f583e33d8",
     "packages": [
-        {
-            "name": "barryvdh/laravel-debugbar",
-            "version": "v3.2.8",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/barryvdh/laravel-debugbar.git",
-                "reference": "18208d64897ab732f6c04a19b319fe8f1d57a9c0"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/18208d64897ab732f6c04a19b319fe8f1d57a9c0",
-                "reference": "18208d64897ab732f6c04a19b319fe8f1d57a9c0",
-                "shasum": "",
-                "mirrors": [
-                    {
-                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
-                        "preferred": true
-                    }
-                ]
-            },
-            "require": {
-                "illuminate/routing": "^5.5|^6",
-                "illuminate/session": "^5.5|^6",
-                "illuminate/support": "^5.5|^6",
-                "maximebf/debugbar": "~1.15.0",
-                "php": ">=7.0",
-                "symfony/debug": "^3|^4",
-                "symfony/finder": "^3|^4"
-            },
-            "require-dev": {
-                "laravel/framework": "5.5.x"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "3.2-dev"
-                },
-                "laravel": {
-                    "providers": [
-                        "Barryvdh\\Debugbar\\ServiceProvider"
-                    ],
-                    "aliases": {
-                        "Debugbar": "Barryvdh\\Debugbar\\Facade"
-                    }
-                }
-            },
-            "autoload": {
-                "psr-4": {
-                    "Barryvdh\\Debugbar\\": "src/"
-                },
-                "files": [
-                    "src/helpers.php"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Barry vd. Heuvel",
-                    "email": "barryvdh@gmail.com"
-                }
-            ],
-            "description": "PHP Debugbar integration for Laravel",
-            "keywords": [
-                "debug",
-                "debugbar",
-                "laravel",
-                "profiler",
-                "webprofiler"
-            ],
-            "time": "2019-08-29T07:01:03+00:00"
-        },
         {
             "name": "caouecs/laravel-lang",
             "version": "4.0.6",
@@ -1751,73 +1677,6 @@
             ],
             "time": "2019-10-06T11:29:25+00:00"
         },
-        {
-            "name": "maximebf/debugbar",
-            "version": "v1.15.1",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/maximebf/php-debugbar.git",
-                "reference": "6c4277f6117e4864966c9cb58fb835cee8c74a1e"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/6c4277f6117e4864966c9cb58fb835cee8c74a1e",
-                "reference": "6c4277f6117e4864966c9cb58fb835cee8c74a1e",
-                "shasum": "",
-                "mirrors": [
-                    {
-                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
-                        "preferred": true
-                    }
-                ]
-            },
-            "require": {
-                "php": ">=5.6",
-                "psr/log": "^1.0",
-                "symfony/var-dumper": "^2.6|^3|^4"
-            },
-            "require-dev": {
-                "phpunit/phpunit": "^5"
-            },
-            "suggest": {
-                "kriswallsmith/assetic": "The best way to manage assets",
-                "monolog/monolog": "Log using Monolog",
-                "predis/predis": "Redis storage"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.15-dev"
-                }
-            },
-            "autoload": {
-                "psr-4": {
-                    "DebugBar\\": "src/DebugBar/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Maxime Bouroumeau-Fuseau",
-                    "email": "maxime.bouroumeau@gmail.com",
-                    "homepage": "http://maximebf.com"
-                },
-                {
-                    "name": "Barry vd. Heuvel",
-                    "email": "barryvdh@gmail.com"
-                }
-            ],
-            "description": "Debug bar in the browser for php application",
-            "homepage": "https://github.com/maximebf/php-debugbar",
-            "keywords": [
-                "debug",
-                "debugbar"
-            ],
-            "time": "2019-09-24T14:55:42+00:00"
-        },
         {
             "name": "mews/captcha",
             "version": "2.3.0",
@@ -4959,6 +4818,80 @@
         }
     ],
     "packages-dev": [
+        {
+            "name": "barryvdh/laravel-debugbar",
+            "version": "v3.2.8",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/barryvdh/laravel-debugbar.git",
+                "reference": "18208d64897ab732f6c04a19b319fe8f1d57a9c0"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/18208d64897ab732f6c04a19b319fe8f1d57a9c0",
+                "reference": "18208d64897ab732f6c04a19b319fe8f1d57a9c0",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "illuminate/routing": "^5.5|^6",
+                "illuminate/session": "^5.5|^6",
+                "illuminate/support": "^5.5|^6",
+                "maximebf/debugbar": "~1.15.0",
+                "php": ">=7.0",
+                "symfony/debug": "^3|^4",
+                "symfony/finder": "^3|^4"
+            },
+            "require-dev": {
+                "laravel/framework": "5.5.x"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.2-dev"
+                },
+                "laravel": {
+                    "providers": [
+                        "Barryvdh\\Debugbar\\ServiceProvider"
+                    ],
+                    "aliases": {
+                        "Debugbar": "Barryvdh\\Debugbar\\Facade"
+                    }
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Barryvdh\\Debugbar\\": "src/"
+                },
+                "files": [
+                    "src/helpers.php"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Barry vd. Heuvel",
+                    "email": "barryvdh@gmail.com"
+                }
+            ],
+            "description": "PHP Debugbar integration for Laravel",
+            "keywords": [
+                "debug",
+                "debugbar",
+                "laravel",
+                "profiler",
+                "webprofiler"
+            ],
+            "time": "2019-08-29T07:01:03+00:00"
+        },
         {
             "name": "barryvdh/laravel-ide-helper",
             "version": "v2.6.5",
@@ -6003,6 +5936,73 @@
             ],
             "time": "2019-09-25T14:49:45+00:00"
         },
+        {
+            "name": "maximebf/debugbar",
+            "version": "v1.15.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/maximebf/php-debugbar.git",
+                "reference": "6c4277f6117e4864966c9cb58fb835cee8c74a1e"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/6c4277f6117e4864966c9cb58fb835cee8c74a1e",
+                "reference": "6c4277f6117e4864966c9cb58fb835cee8c74a1e",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "php": ">=5.6",
+                "psr/log": "^1.0",
+                "symfony/var-dumper": "^2.6|^3|^4"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^5"
+            },
+            "suggest": {
+                "kriswallsmith/assetic": "The best way to manage assets",
+                "monolog/monolog": "Log using Monolog",
+                "predis/predis": "Redis storage"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.15-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "DebugBar\\": "src/DebugBar/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Maxime Bouroumeau-Fuseau",
+                    "email": "maxime.bouroumeau@gmail.com",
+                    "homepage": "http://maximebf.com"
+                },
+                {
+                    "name": "Barry vd. Heuvel",
+                    "email": "barryvdh@gmail.com"
+                }
+            ],
+            "description": "Debug bar in the browser for php application",
+            "homepage": "https://github.com/maximebf/php-debugbar",
+            "keywords": [
+                "debug",
+                "debugbar"
+            ],
+            "time": "2019-09-24T14:55:42+00:00"
+        },
         {
             "name": "mockery/mockery",
             "version": "1.2.4",

二進制
composer.phar


+ 202 - 0
config/debugbar.php

@@ -0,0 +1,202 @@
+<?php
+
+return [
+
+    /*
+     |--------------------------------------------------------------------------
+     | Debugbar Settings
+     |--------------------------------------------------------------------------
+     |
+     | Debugbar is enabled by default, when debug is set to true in app.php.
+     | You can override the value by setting enable to true or false instead of null.
+     |
+     | You can provide an array of URI's that must be ignored (eg. 'api/*')
+     |
+     */
+
+    'enabled' => env('DEBUGBAR_ENABLED', null),
+    'except' => [
+        'telescope*'
+    ],
+
+    /*
+     |--------------------------------------------------------------------------
+     | Storage settings
+     |--------------------------------------------------------------------------
+     |
+     | DebugBar stores data for session/ajax requests.
+     | You can disable this, so the debugbar stores data in headers/session,
+     | but this can cause problems with large data collectors.
+     | By default, file storage (in the storage folder) is used. Redis and PDO
+     | can also be used. For PDO, run the package migrations first.
+     |
+     */
+    'storage' => [
+        'enabled'    => true,
+        'driver'     => 'file', // redis, file, pdo, custom
+        'path'       => storage_path('debugbar'), // For file driver
+        'connection' => null,   // Leave null for default connection (Redis/PDO)
+        'provider'   => '' // Instance of StorageInterface for custom driver
+    ],
+
+    /*
+     |--------------------------------------------------------------------------
+     | Vendors
+     |--------------------------------------------------------------------------
+     |
+     | Vendor files are included by default, but can be set to false.
+     | This can also be set to 'js' or 'css', to only include javascript or css vendor files.
+     | Vendor files are for css: font-awesome (including fonts) and highlight.js (css files)
+     | and for js: jquery and and highlight.js
+     | So if you want syntax highlighting, set it to true.
+     | jQuery is set to not conflict with existing jQuery scripts.
+     |
+     */
+
+    'include_vendors' => true,
+
+    /*
+     |--------------------------------------------------------------------------
+     | Capture Ajax Requests
+     |--------------------------------------------------------------------------
+     |
+     | The Debugbar can capture Ajax requests and display them. If you don't want this (ie. because of errors),
+     | you can use this option to disable sending the data through the headers.
+     |
+     | Optionally, you can also send ServerTiming headers on ajax requests for the Chrome DevTools.
+     */
+
+    'capture_ajax' => true,
+    'add_ajax_timing' => false,
+
+    /*
+     |--------------------------------------------------------------------------
+     | Custom Error Handler for Deprecated warnings
+     |--------------------------------------------------------------------------
+     |
+     | When enabled, the Debugbar shows deprecated warnings for Symfony components
+     | in the Messages tab.
+     |
+     */
+    'error_handler' => false,
+
+    /*
+     |--------------------------------------------------------------------------
+     | Clockwork integration
+     |--------------------------------------------------------------------------
+     |
+     | The Debugbar can emulate the Clockwork headers, so you can use the Chrome
+     | Extension, without the server-side code. It uses Debugbar collectors instead.
+     |
+     */
+    'clockwork' => false,
+
+    /*
+     |--------------------------------------------------------------------------
+     | DataCollectors
+     |--------------------------------------------------------------------------
+     |
+     | Enable/disable DataCollectors
+     |
+     */
+
+    'collectors' => [
+        'phpinfo'         => true,  // Php version
+        'messages'        => true,  // Messages
+        'time'            => true,  // Time Datalogger
+        'memory'          => true,  // Memory usage
+        'exceptions'      => true,  // Exception displayer
+        'log'             => true,  // Logs from Monolog (merged in messages if enabled)
+        'db'              => true,  // Show database (PDO) queries and bindings
+        'views'           => true,  // Views with their data
+        'route'           => true,  // Current route information
+        'auth'            => false, // Display Laravel authentication status
+        'gate'            => true, // Display Laravel Gate checks
+        'session'         => true,  // Display session data
+        'symfony_request' => true,  // Only one can be enabled..
+        'mail'            => true,  // Catch mail messages
+        'laravel'         => false, // Laravel version and environment
+        'events'          => false, // All events fired
+        'default_request' => false, // Regular or special Symfony request logger
+        'logs'            => false, // Add the latest log messages
+        'files'           => false, // Show the included files
+        'config'          => false, // Display config settings
+        'cache'           => false, // Display cache events
+        'models'          => false, // Display models
+    ],
+
+    /*
+     |--------------------------------------------------------------------------
+     | Extra options
+     |--------------------------------------------------------------------------
+     |
+     | Configure some DataCollectors
+     |
+     */
+
+    'options' => [
+        'auth' => [
+            'show_name' => true,   // Also show the users name/email in the debugbar
+        ],
+        'db' => [
+            'with_params'       => true,   // Render SQL with the parameters substituted
+            'backtrace'         => true,   // Use a backtrace to find the origin of the query in your files.
+            'timeline'          => false,  // Add the queries to the timeline
+            'explain' => [                 // Show EXPLAIN output on queries
+                'enabled' => false,
+                'types' => ['SELECT'],     // // workaround ['SELECT'] only. https://github.com/barryvdh/laravel-debugbar/issues/888 ['SELECT', 'INSERT', 'UPDATE', 'DELETE']; for MySQL 5.6.3+
+            ],
+            'hints'             => true,    // Show hints for common mistakes
+        ],
+        'mail' => [
+            'full_log' => false
+        ],
+        'views' => [
+            'data' => false,    //Note: Can slow down the application, because the data can be quite large..
+        ],
+        'route' => [
+            'label' => true  // show complete route on bar
+        ],
+        'logs' => [
+            'file' => null
+        ],
+        'cache' => [
+            'values' => true // collect cache values
+        ],
+    ],
+
+    /*
+     |--------------------------------------------------------------------------
+     | Inject Debugbar in Response
+     |--------------------------------------------------------------------------
+     |
+     | Usually, the debugbar is added just before </body>, by listening to the
+     | Response after the App is done. If you disable this, you have to add them
+     | in your template yourself. See http://phpdebugbar.com/docs/rendering.html
+     |
+     */
+
+    'inject' => true,
+
+    /*
+     |--------------------------------------------------------------------------
+     | DebugBar route prefix
+     |--------------------------------------------------------------------------
+     |
+     | Sometimes you want to set route prefix to be used by DebugBar to load
+     | its resources from. Usually the need comes from misconfigured web server or
+     | from trying to overcome bugs like this: http://trac.nginx.org/nginx/ticket/97
+     |
+     */
+    'route_prefix' => '_debugbar',
+
+    /*
+     |--------------------------------------------------------------------------
+     | DebugBar route domain
+     |--------------------------------------------------------------------------
+     |
+     | By default DebugBar route served from the same domain that request served.
+     | To override default domain, specify it as a non-empty value.
+     */
+    'route_domain' => null,
+];

+ 53 - 37
public/assets/examples/css/pages/login-v3.css

@@ -1,45 +1,61 @@
 .page-login-v3:before {
-  position: fixed;
-  top: 0;
-  left: 0;
-  content: '';
-  width: 100%;
-  height: 100%;
-  background-position: center top;
-  background-size: cover;
-  z-index: -1;
-  background: #3e8ef7;
-  /* Old browsers */
-  /* IE9 SVG, needs conditional override of 'filter' to 'none' */
-  background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzYyYThlYSIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiMxNTcxYjEiIHN0b3Atb3BhY2l0eT0iMSIvPgogIDwvbGluZWFyR3JhZGllbnQ+CiAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkLXVjZ2ctZ2VuZXJhdGVkKSIgLz4KPC9zdmc+);
-  background-image: linear-gradient(to bottom, #3e8ef7 0%, #0b69e3 100%);
-  background-repeat: repeat-x; }
+    position: fixed;
+    top: 0;
+    left: 0;
+    content: '';
+    width: 100%;
+    height: 100%;
+    background-position: center top;
+    background-size: cover;
+    z-index: -1;
+    background: #3e8ef7;
+    /* Old browsers */
+    /* IE9 SVG, needs conditional override of 'filter' to 'none' */
+    background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzYyYThlYSIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiMxNTcxYjEiIHN0b3Atb3BhY2l0eT0iMSIvPgogIDwvbGluZWFyR3JhZGllbnQ+CiAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkLXVjZ2ctZ2VuZXJhdGVkKSIgLz4KPC9zdmc+);
+    background-image: linear-gradient(to bottom, #3e8ef7 0%, #0b69e3 100%);
+    background-repeat: repeat-x;
+}
 
 .page-login-v3 .panel {
-  width: 400px;
-  margin-bottom: 45px;
-  background: #fff;
-  border-radius: 0.286rem; }
-  .page-login-v3 .panel .brand-text {
-    margin-top: 8px; }
+    width: 400px;
+    margin-bottom: 45px;
+    background: #fff;
+    border-radius: 0.286rem;
+}
+
+.page-login-v3 .panel .brand-text {
+    margin-top: 12px;
+}
 
 .page-login-v3 form {
-  margin: 45px 0 30px; }
-  .page-login-v3 form a {
-    margin-left: 20px; }
-  .page-login-v3 form .form-material.floating + .page-login-v3 form .form-material.floating {
-    margin-top: 30px; }
-  .page-login-v3 form .form-material label {
+    margin: 0 0 30px;
+}
+
+.page-login-v3 form .form-material.floating + .page-login-v3 form .form-material.floating {
+    margin-top: 30px;
+}
+
+.page-login-v3 form .form-material label {
     color: #a3afb7;
-    font-weight: 300; }
+    font-weight: 300;
+}
 
 @media (max-width: 479.98px) {
-  .page-login-v3 .page-content {
-    padding: 30px 20px;
-  }
-
-  .page-login-v3 .panel {
-    width: auto;
-    padding: 10px;
-  }
-}
+    .page-login-v3 .panel {
+        width: 330px;
+        padding: 10px;
+    }
+}
+
+@media screen and (max-height: 575px) {
+    .g-recaptcha {
+        -webkit-transform: scale(0.81);
+        transform: scale(0.81);
+        -webkit-transform-origin: 0 0;
+        transform-origin: 0 0;
+    }
+}
+
+.geetest_holder.geetest_wind {
+    min-width: 245px !important;
+}

+ 4 - 2
resources/lang/zh-CN/auth.php

@@ -47,7 +47,8 @@ return [
 	'email_null'                 => '请输入邮箱账号',
 	'email_normal'               => '账号状态正常,无需激活',
 	'email_legitimate'           => '邮箱地址不合规',
-	'email_banned'               => '邮箱含有敏感词,请使用其他有效邮箱',
+	'email_banned'               => '本站屏蔽了您使用的邮箱服务商,请使用其他有效邮箱',
+	'email_invalid'              => '使用邮箱不在本站支持邮箱列表内',
 	'email_exist'                => '账号已存在,如果忘记密码请找回密码',
 	'email_notExist'             => '账号不存在,请重试',
 	'login_error'                => '邮箱或密码错误',
@@ -67,5 +68,6 @@ return [
 	'rest_password_same_fail'    => '新旧密码一样,请重新输入',
 	'rest_password_fail'         => '重设密码失败',
 	'reset_password_new'         => '新密码设置成功,请自行登录',
-	'request_error'              => '请求异常,请刷新页面后重试'
+	'request_error'              => '请求异常,请刷新页面后重试',
+	'unaccepted'                 => '请阅读用户条款和可接受使用条款,并同意'
 ];

+ 4 - 5
resources/views/admin/addArticle.blade.php

@@ -42,7 +42,7 @@
 						<label class="col-form-label col-md-2" for="title">标题</label>
 						<div class="col-md-4">
 							<input type="text" class="form-control" name="title" id="title" autofocus required/>
-							<input type="hidden" name="_token" value="{{csrf_token()}}">
+							{{csrf_field()}}
 						</div>
 					</div>
 					<div class="form-group row" id="summary">
@@ -78,8 +78,8 @@
 					</div>
 					<div class="form-actions text-right">
 						<div class="btn-group">
-							<a href="/admin/articleList" class="btn btn-danger">返回</a>
-							<button type="submit" class="btn btn-success">提交</button>
+							<a href="/admin/articleList" class="btn btn-danger">返 回</a>
+							<button type="submit" class="btn btn-success">提 交</button>
 						</div>
 					</div>
 				</form>
@@ -94,8 +94,7 @@
 	<script src="/assets/global/js/Plugin/summernote.js" type="text/javascript"></script>
 	<script type="text/javascript">
         $("input:radio[name='type']").on('change', function () {
-            const type = parseInt($(this).val());
-            switch (type) {
+            switch (parseInt($(this).val())) {
                 case 1:
                     $("#summary").show();
                     $("#sort").show();

+ 2 - 7
resources/views/admin/addGroup.blade.php

@@ -16,7 +16,6 @@
 					<div class="form-group row">
 						<label class="col-form-label col-md-1" for="name">分组名称</label>
 						<input type="text" class="form-control col-md-5" name="name" value="" id="name" required/>
-						<input type="hidden" name="_token" value="{{csrf_token()}}"/>
 					</div>
 					<div class="form-group row">
 						<label class="col-form-label col-md-1" for="level">分组级别</label>
@@ -30,7 +29,7 @@
 						<span class="text-help offset-md-1">暂时无用&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span>
 					</div>
 					<div class="form-actions">
-						<button type="submit" class="btn btn-success">提交</button>
+						<button type="submit" class="btn btn-success">提 交</button>
 					</div>
 				</form>
 			</div>
@@ -41,15 +40,11 @@
 	<script type="text/javascript">
         // ajax同步提交
         function Submit() {
-            const _token = '{{csrf_token()}}';
-            const name = $('#name').val();
-            const level = $("#level option:selected").val();
-
             $.ajax({
                 type: "POST",
                 url: "/admin/addGroup",
                 async: false,
-                data: {_token: _token, name: name, level: level},
+                data: {_token: '{{csrf_token()}}', name: $('#name').val(), level: $("#level option:selected").val()},
                 dataType: 'json',
                 success: function (ret) {
                     if (ret.status === 'success') {

+ 2 - 7
resources/views/admin/addLabel.blade.php

@@ -16,7 +16,6 @@
 					<div class="form-group row">
 						<label for="name" class="col-form-label col-md-1">标签</label>
 						<input type="text" class="form-control col-md-6" name="name" id="name" autofocus required/>
-						<input type="hidden" name="_token" value="{{csrf_token()}}">
 					</div>
 					<div class="form-group row">
 						<label for="sort" class="col-form-label col-md-1">排序</label>
@@ -24,7 +23,7 @@
 						<span class="text-help offset-md-1"> 排序值越高显示时越靠前 &ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span>
 					</div>
 					<div class="form-actions">
-						<button type="submit" class="btn btn-success">提交</button>
+						<button type="submit" class="btn btn-success">提 交</button>
 					</div>
 				</form>
 			</div>
@@ -35,15 +34,11 @@
 	<script type="text/javascript">
         // ajax同步提交
         function Submit() {
-            const _token = '{{csrf_token()}}';
-            const name = $('#name').val();
-            const sort = $('#sort').val();
-
             $.ajax({
                 type: "POST",
                 url: "/admin/addLabel",
                 async: false,
-                data: {_token: _token, name: name, sort: sort},
+                data: {_token: '{{csrf_token()}}', name: $('#name').val(), sort: $('#sort').val()},
                 dataType: 'json',
                 success: function (ret) {
                     if (ret.status === 'success') {

+ 65 - 158
resources/views/admin/addNode.blade.php

@@ -42,22 +42,22 @@
 										</ul>
 									</div>
 									<div class="form-group row">
-										<label for="is_nat" class="col-md-3 col-form-label">NAT</label>
+										<label for="is_ddns" class="col-md-3 col-form-label">DDNS</label>
 										<ul class="col-md-9 list-unstyled list-inline">
 											<li class="list-inline-item">
 												<div class="radio-custom radio-primary">
-													<input type="radio" name="is_nat" value="1">
+													<input type="radio" name="is_ddns" value="1">
 													<label>是</label>
 												</div>
 											</li>
 											<li class="list-inline-item">
 												<div class="radio-custom radio-primary">
-													<input type="radio" name="is_nat" value="0" checked>
+													<input type="radio" name="is_ddns" value="0" checked>
 													<label>否</label>
 												</div>
 											</li>
 										</ul>
-										<span class="text-help offset-md-3"> NAT机需要<a href="https://github.com/ssrpanel/SSRPanel/wiki/NAT-VPS%E9%85%8D%E7%BD%AE%E6%95%99%E7%A8%8B" target="_blank">配置DDNS</a>,TCP阻断检测无效,务必填写域名 </span>
+										<span class="text-help offset-md-3"> 动态IP节点需要<a href="https://github.com/NewFuture/DDNS" target="_blank">配置DDNS</a>,对此类型节点,节点阻断功能会通过域名进行检测 </span>
 									</div>
 									<div class="form-group row">
 										<label for="name" class="col-md-3 col-form-label"> 节点名称 </label>
@@ -107,10 +107,10 @@
 									<div class="form-group row">
 										<label for="country_code" class="col-md-3 col-form-label"> 国家/地区 </label>
 										<select data-plugin="selectpicker" data-style="btn-outline btn-primary" class="col-md-5 form-control" name="country_code" id="country_code">
-											<option value="">请选择</option>
+											<option value="" hidden>请选择</option>
 											@if(!$country_list->isEmpty())
 												@foreach($country_list as $country)
-													<option value="{{$country->country_code}}">{{$country->country_code}} - {{$country->country_name}}</option>
+													<option value="{{$country->code}}">{{$country->code}} - {{$country->name}}</option>
 												@endforeach
 											@endif
 										</select>
@@ -258,40 +258,34 @@
 											</ul>
 										</div>
 										<div class="form-group row">
-											<label for="is_udp" class="col-md-3 col-form-label">UDP</label>
+											<label for="detectionType" class="col-md-3 col-form-label">节点阻断检测</label>
 											<ul class="col-md-9 list-unstyled list-inline">
 												<li class="list-inline-item">
 													<div class="radio-custom radio-primary">
-														<input type="radio" name="is_udp" value="1" checked>
-														<label>允许</label>
+														<input type="radio" name="detectionType" value="0" checked/>
+														<label>关闭</label>
 													</div>
 												</li>
 												<li class="list-inline-item">
 													<div class="radio-custom radio-primary">
-														<input type="radio" name="is_udp" value="0">
-														<label>不允许</label>
+														<input type="radio" name="detectionType" value="1"/>
+														<label>只检测TCP</label>
 													</div>
 												</li>
-											</ul>
-											<span class="text-help offset-md-3"> 禁止UDP,则无法用于加速游戏 </span>
-										</div>
-										<div class="form-group row">
-											<label for="is_tcp_check" class="col-md-3 col-form-label">TCP阻断检测</label>
-											<ul class="col-md-9 list-unstyled list-inline">
 												<li class="list-inline-item">
 													<div class="radio-custom radio-primary">
-														<input type="radio" name="is_tcp_check" value="1" checked>
-														<label>开启</label>
+														<input type="radio" name="detectionType" value="2"/>
+														<label>只检测ICMP</label>
 													</div>
 												</li>
 												<li class="list-inline-item">
 													<div class="radio-custom radio-primary">
-														<input type="radio" name="is_tcp_check" value="0">
-														<label>关闭</label>
+														<input type="radio" name="detectionType" value="3"/>
+														<label>检测全部</label>
 													</div>
 												</li>
 											</ul>
-											<span class="text-help offset-md-3"> 每30~60分钟随机进行TCP阻断检测 </span>
+											<span class="text-help offset-md-3"> 每30~60分钟随机进行节点阻断检测 </span>
 										</div>
 										<hr/>
 										<div class="form-group row">
@@ -314,49 +308,14 @@
 										</div>
 										<div class="single-setting hidden">
 											<div class="form-group row">
-												<label for="single_force" class="col-md-3 col-form-label">[单] 模式</label>
-												<select data-plugin="selectpicker" data-style="btn-outline btn-primary" class="col-md-5 form-control" name="single_force" id="single_force">
-													<option value="0" selected>兼容模式</option>
-													<option value="1">严格模式</option>
-												</select>
-												<span class="text-help offset-md-3"> 严格模式:用户的端口无法连接,只能通过以下指定的端口进行连接(<a href="javascript:showPortsOnlyConfig();">如何配置</a>)</span>
-											</div>
-											<div class="form-group row">
-												<label for="single_port" class="col-md-3 col-form-label">[单] 端口</label>
-												<input type="text" class="form-control col-md-4" name="single_port" value="" id="single_port" placeholder="443">
+												<label for="port" class="col-md-3 col-form-label">[单] 端口</label>
+												<input type="text" class="form-control col-md-4" name="port" value="" id="port" placeholder="443">
 												<span class="text-help offset-md-3"> 推荐80或443,服务端需要配置 </span>
+												<span class="text-help offset-md-3"> 严格模式:用户的端口无法连接,只能通过以下指定的端口进行连接(<a href="javascript:showPortsOnlyConfig();">如何配置</a>)</span>
 											</div>
 											<div class="form-group row">
-												<label for="single_passwd" class="col-md-3 col-form-label">[单] 密码</label>
-												<input type="text" class="form-control col-md-4" name="single_passwd" value="" id="single_passwd" placeholder="password">
-											</div>
-											<div class="form-group row">
-												<label for="single_method" class="col-md-3 col-form-label">[单] 加密方式</label>
-												<select data-plugin="selectpicker" data-style="btn-outline btn-primary" class="col-md-5 form-control" name="single_method" id="single_method">
-													@foreach ($method_list as $method)
-														<option value="{{$method->name}}" @if($method->is_default) selected @endif>{{$method->name}}</option>
-													@endforeach
-												</select>
-											</div>
-											<div class="form-group row">
-												<label for="single_protocol" class="col-md-3 col-form-label">[单] 协议</label>
-												<select data-plugin="selectpicker" data-style="btn-outline btn-primary" class="col-md-5 form-control" name="single_protocol" id="single_protocol">
-													<option value="origin">origin</option>
-													<option value="verify_deflate">verify_deflate</option>
-													<option value="auth_sha1_v4">auth_sha1_v4</option>
-													<option value="auth_aes128_md5">auth_aes128_md5</option>
-													<option value="auth_aes128_sha1">auth_aes128_sha1</option>
-													<option value="auth_chain_a" selected>auth_chain_a</option>
-												</select>
-											</div>
-											<div class="form-group row">
-												<label for="single_obfs" class="col-md-3 col-form-label">[单] 混淆</label>
-												<select data-plugin="selectpicker" data-style="btn-outline btn-primary" class="col-md-5 form-control" name="single_obfs" id="single_obfs">
-													<option value="plain">plain</option>
-													<option value="http_simple">http_simple</option>
-													<option value="random_head">random_head</option>
-													<option value="tls1.2_ticket_auth" selected>tls1.2_ticket_auth</option>
-												</select>
+												<label for="passwd" class="col-md-3 col-form-label">[单] 密码</label>
+												<input type="text" class="form-control col-md-4" name="passwd" value="" id="passwd" placeholder="password">
 											</div>
 										</div>
 									</div>
@@ -459,100 +418,51 @@
 	<script type="text/javascript">
         // ajax同步提交
         function Submit() {
-            var name = $('#name').val();
-            var labels = $("#labels").val();
-            var group_id = $("#group_id option:selected").val();
-            var country_code = $("#country_code option:selected").val();
-            var server = $('#server').val();
-            var ip = $('#ip').val();
-            var ipv6 = $('#ipv6').val();
-            var desc = $('#desc').val();
-            var method = $('#method').val();
-            var traffic_rate = $('#traffic_rate').val();
-            var protocol = $('#protocol').val();
-            var protocol_param = $('#protocol_param').val();
-            var obfs = $('#obfs').val();
-            var obfs_param = $('#obfs_param').val();
-            var bandwidth = $('#bandwidth').val();
-            var traffic = $('#traffic').val();
-            var monitor_url = $('#monitor_url').val();
-            var is_subscribe = $("input:radio[name='is_subscribe']:checked").val();
-            var is_nat = $("input:radio[name='is_nat']:checked").val();
-            var is_transit = $("input:radio[name='is_transit']:checked").val();
-            var ssh_port = $('#ssh_port').val();
-            var compatible = $("input:radio[name='compatible']:checked").val();
-            var single = $("input:radio[name='single']:checked").val();
-            var single_force = $('#single_force').val();
-            var single_port = $('#single_port').val();
-            var single_passwd = $('#single_passwd').val();
-            var single_method = $('#single_method').val();
-            var single_protocol = $('#single_protocol').val();
-            var single_obfs = $('#single_obfs').val();
-            var sort = $('#sort').val();
-            var status = $("input:radio[name='status']:checked").val();
-            var is_tcp_check = $("input:radio[name='is_tcp_check']:checked").val();
-
-            var service = $("input:radio[name='service']:checked").val();
-            var v2_alter_id = $('#v2_alter_id').val();
-            var v2_port = $('#v2_port').val();
-            var v2_method = $("#v2_method option:selected").val();
-            var v2_net = $('#v2_net').val();
-            var v2_type = $('#v2_type').val();
-            var v2_host = $('#v2_host').val();
-            var v2_path = $('#v2_path').val();
-            var v2_tls = $("input:radio[name='v2_tls']:checked").val();
-            var v2_insider_port = $('#v2_insider_port').val();
-            var v2_outsider_port = $('#v2_outsider_port').val();
-
             $.ajax({
                 type: "POST",
                 url: "/admin/addNode",
                 async: false,
                 data: {
                     _token: '{{csrf_token()}}',
-                    name: name,
-                    labels: labels,
-                    group_id: group_id,
-                    country_code: country_code,
-                    server: server,
-                    ip: ip,
-                    ipv6: ipv6,
-                    desc: desc,
-                    method: method,
-                    traffic_rate: traffic_rate,
-                    protocol: protocol,
-                    protocol_param: protocol_param,
-                    obfs: obfs,
-                    obfs_param: obfs_param,
-                    bandwidth: bandwidth,
-                    traffic: traffic,
-                    monitor_url: monitor_url,
-                    is_subscribe: is_subscribe,
-                    is_nat: is_nat,
-                    is_transit: is_transit,
-                    ssh_port: ssh_port,
-                    compatible: compatible,
-                    single: single,
-                    single_force: single_force,
-                    single_port: single_port,
-                    single_passwd: single_passwd,
-                    single_method: single_method,
-                    single_protocol: single_protocol,
-                    single_obfs: single_obfs,
-                    sort: sort,
-                    status: status,
-                    is_tcp_check: is_tcp_check,
-                    type: service,
-                    v2_alter_id: v2_alter_id,
-                    v2_port: v2_port,
-                    v2_method: v2_method,
-                    v2_net: v2_net,
-                    v2_type: v2_type,
-                    v2_host: v2_host,
-                    v2_path: v2_path,
-                    v2_tls: v2_tls,
-                    v2_insider_port: v2_insider_port,
-                    v2_outsider_port: v2_outsider_port
+                    name: $('#name').val(),
+                    labels: $('#labels').val(),
+                    group_id: $('#group_id option:selected').val(),
+                    country_code: $('#country_code option:selected').val(),
+                    server: $('#server').val(),
+                    ip: $('#ip').val(),
+                    ipv6: $('#ipv6').val(),
+                    desc: $('#desc').val(),
+                    method: $('#method').val(),
+                    traffic_rate: $('#traffic_rate').val(),
+                    protocol: $('#protocol').val(),
+                    protocol_param: $('#protocol_param').val(),
+                    obfs: $('#obfs').val(),
+                    obfs_param: $('#obfs_param').val(),
+                    bandwidth: $('#bandwidth').val(),
+                    traffic: $('#traffic').val(),
+                    monitor_url: $('#monitor_url').val(),
+                    is_subscribe: $("input:radio[name='is_subscribe']:checked").val(),
+                    is_ddns: $("input:radio[name='is_ddns']:checked").val(),
+                    is_transit: $("input:radio[name='is_transit']:checked").val(),
+                    ssh_port: $('#ssh_port').val(),
+                    compatible: $("input:radio[name='compatible']:checked").val(),
+                    single: $("input:radio[name='single']:checked").val(),
+                    port: $('#port').val(),
+                    passwd: $('#passwd').val(),
+                    sort: $('#sort').val(),
+                    status: $("input:radio[name='status']:checked").val(),
+                    detectionType: $("input:radio[name='detectionType']:checked").val(),
+                    type: $("input:radio[name='service']:checked").val(),
+                    v2_alter_id: $('#v2_alter_id').val(),
+                    v2_port: $('#v2_port').val(),
+                    v2_method: $("#v2_method option:selected").val(),
+                    v2_net: $('#v2_net').val(),
+                    v2_type: $('#v2_type').val(),
+                    v2_host: $('#v2_host').val(),
+                    v2_path: $('#v2_path').val(),
+                    v2_tls: $("input:radio[name='v2_tls']:checked").val(),
+                    v2_insider_port: $('#v2_insider_port').val(),
+                    v2_outsider_port: $('#v2_outsider_port').val()
                 },
                 dataType: 'json',
                 success: function (ret) {
@@ -569,8 +479,7 @@
 
         // 设置单端口多用户
         $("input:radio[name='single']").on('change', function () {
-            const single = parseInt($(this).val());
-            if (single) {
+            if (parseInt($(this).val())) {
                 $(".single-setting").show();
             } else {
                 $(".single-setting").hide();
@@ -579,8 +488,7 @@
 
         // 设置服务类型
         $("input:radio[name='service']").on('change', function () {
-            const service = parseInt($(this).val());
-            if (service === 1) {
+            if (parseInt($(this).val()) === 1) {
                 $(".ssr-setting").show();
                 $(".v2ray-setting").hide();
             } else {
@@ -589,10 +497,9 @@
             }
         });
 
-        // 设置是否为NAT
-        $("input:radio[name='is_nat']").on('change', function () {
-            const is_nat = parseInt($(this).val());
-            if (is_nat === 1) {
+        // 设置是否使用DDNS
+        $("input:radio[name='is_ddns']").on('change', function () {
+            if (parseInt($(this).val()) === 1) {
                 $("#ip").val("1.1.1.1").attr("readonly", "readonly");
                 $("#server").attr("required", "required");
             } else {

+ 25 - 52
resources/views/admin/addUser.blade.php

@@ -325,31 +325,6 @@
 
         // ajax同步提交
         function Submit() {
-            const _token = '{{csrf_token()}}';
-            const username = $('#username').val();
-            const password = $('#password').val();
-            const pay_way = $("input:radio[name='pay_way']:checked").val();
-            const status = $("input:radio[name='status']:checked").val();
-            const labels = $('#labels').val();
-            const enable_time = $('#enable_time').val();
-            const expire_time = $('#expire_time').val();
-            const wechat = $('#wechat').val();
-            const qq = $('#qq').val();
-            const remark = $('#remark').val();
-            const level = $("#level option:selected").val();
-            const port = $('#port').val();
-            const passwd = $('#passwd').val();
-            const method = $('#method').val();
-            const transfer_enable = $('#transfer_enable').val();
-            const enable = $("input:radio[name='enable']:checked").val();
-            const protocol = $('#protocol').val();
-            const protocol_param = $('#protocol_param').val();
-            const obfs = $('#obfs').val();
-            const obfs_param = $('#obfs_param').val();
-            const speed_limit_per_con = $('#speed_limit_per_con').val();
-            const speed_limit_per_user = $('#speed_limit_per_user').val();
-            const vmess_id = $('#vmess_id').val();
-
             // 用途
             let usage = '';
             $.each($("input:checkbox[name='usage']"), function () {
@@ -357,39 +332,37 @@
                     usage += $(this).val() + ',';
                 }
             });
-            usage = usage.substring(0, usage.length - 1);
 
             $.ajax({
                 type: "POST",
                 url: "/admin/addUser",
                 async: false,
                 data: {
-                    _token: _token,
-                    username: username,
-                    password: password,
-                    usage: usage,
-                    pay_way: pay_way,
-                    status: status,
-                    labels: labels,
-                    enable_time: enable_time,
-                    expire_time: expire_time,
-                    expire_time: expire_time,
-                    wechat: wechat,
-                    qq: qq,
-                    remark: remark,
-                    level: level,
-                    port: port,
-                    passwd: passwd,
-                    method: method,
-                    transfer_enable: transfer_enable,
-                    enable: enable,
-                    protocol: protocol,
-                    protocol_param: protocol_param,
-                    obfs: obfs,
-                    obfs_param: obfs_param,
-                    speed_limit_per_con: speed_limit_per_con,
-                    speed_limit_per_user: speed_limit_per_user,
-                    vmess_id: vmess_id
+                    _token: '{{csrf_token()}}',
+                    username: $('#username').val(),
+                    password: $('#password').val(),
+                    usage: usage.substring(0, usage.length - 1),
+                    pay_way: $("input:radio[name='pay_way']:checked").val(),
+                    status: $("input:radio[name='status']:checked").val(),
+                    labels: $('#labels').val(),
+                    enable_time: $('#enable_time').val(),
+                    expire_time: $('#expire_time').val(),
+                    wechat: $('#wechat').val(),
+                    qq: $('#qq').val(),
+                    remark: $('#remark').val(),
+                    level: $("#level option:selected").val(),
+                    port: $('#port').val(),
+                    passwd: $('#passwd').val(),
+                    method: $('#method').val(),
+                    transfer_enable: $('#transfer_enable').val(),
+                    enable: $("input:radio[name='enable']:checked").val(),
+                    protocol: $('#protocol').val(),
+                    protocol_param: $('#protocol_param').val(),
+                    obfs: $('#obfs').val(),
+                    obfs_param: $('#obfs_param').val(),
+                    speed_limit_per_con: $('#speed_limit_per_con').val(),
+                    speed_limit_per_user: $('#speed_limit_per_user').val(),
+                    vmess_id: $('#vmess_id').val()
                 },
                 dataType: 'json',
                 success: function (ret) {

+ 17 - 26
resources/views/admin/analysis.blade.php

@@ -17,32 +17,29 @@
 				</div>
 			@endif
 			<div class="panel-body">
-				<div class="example">
-					<table class="text-md-center" data-toggle="table" data-mobile-responsive="true">
-						<thead class="thead-default">
+				<table class="text-md-center" data-toggle="table" data-mobile-responsive="true">
+					<thead class="thead-default">
+					<tr>
+						<th>近期请求地址</th>
+					</tr>
+					</thead>
+					<tbody>
+					@if(empty($urlList))
 						<tr>
-							<th>近期请求地址</th>
+							<td colspan="1">访问记录不足15000条,无法分析数据</td>
 						</tr>
-						</thead>
-						<tbody>
-						@if(empty($urlList))
+					@else
+						@foreach($urlList as $url)
 							<tr>
-								<td colspan="1">访问记录不足15000条,无法分析数据</td>
+								<td> {{$url}} </td>
 							</tr>
-						@else
-							@foreach($urlList as $url)
-								<tr>
-									<td> {{$url}} </td>
-								</tr>
-							@endforeach
-						@endif
-						</tbody>
-					</table>
-				</div>
+						@endforeach
+					@endif
+					</tbody>
+				</table>
 			</div>
 		</div>
 	</div>
-	</div>
 
 @endsection
 @section('script')
@@ -94,13 +91,7 @@
 
         $('#is_rand_port').on({
             'switchChange.bootstrapSwitch': function (event, state) {
-                var is_rand_port = 0;
-
-                if (state) {
-                    is_rand_port = 1;
-                }
-
-                $.post("/admin/enableRandPort", {_token: '{{csrf_token()}}', value: is_rand_port}, function (ret) {
+                $.post("/admin/enableRandPort", {_token: '{{csrf_token()}}', value: state ? 1 : 0}, function (ret) {
                     console.log(ret);
                 });
             }

+ 1 - 1
resources/views/admin/applyDetail.blade.php

@@ -13,7 +13,7 @@
 					@elseif($info->status == 2)
 						<span class="badge badge-lg badge-success"> 已打款 </span>
 					@endif
-						<a href="/admin/applyList" class="btn btn-danger"> 返回</a>
+					<a href="/admin/applyList" class="btn btn-danger"> 返 回</a>
 				</div>
 			</div>
 			<div class="panel-body">

+ 1 - 3
resources/views/admin/applyList.blade.php

@@ -116,9 +116,7 @@
 
         // 搜索
         function Search() {
-            const username = $("#username").val();
-            const status = $("#status option:selected").val();
-            window.location.href = '/admin/applyList?username=' + username + '&status=' + status;
+            window.location.href = '/admin/applyList?username=' + $("#username").val() + '&status=' + $("#status option:selected").val();
         }
 
         // 更改状态

+ 66 - 73
resources/views/admin/config.blade.php

@@ -7,32 +7,32 @@
 	<div class="page-content container">
 		<div class="panel">
 			<div class="panel-heading">
-				<h3 class="panel-title">通用配置</h3>
+				<h1 class="panel-title"><i class="icon wb-settings" aria-hidden="true"></i>通用配置</h1>
 			</div>
-			<div class="panel-body">
+			<div class="panel-body container-fluid">
 				<div class="nav-tabs-vertical" data-plugin="tabs">
 					<ul class="nav nav-tabs mr-25" role="tablist">
 						<li class="nav-item" role="presentation">
-							<a class="nav-link active" data-toggle="tab" href="#tab1" aria-controls="tab1" role="tab">加密</a>
+							<a class="nav-link active" data-toggle="tab" href="#method" aria-controls="method" role="tab">加密</a>
 						</li>
 						<li class="nav-item" role="presentation">
-							<a class="nav-link" data-toggle="tab" href="#tab2" aria-controls="tab2" role="tab">协议</a>
+							<a class="nav-link" data-toggle="tab" href="#protocol" aria-controls="protocol" role="tab">协议</a>
 						</li>
 						<li class="nav-item" role="presentation">
-							<a class="nav-link" data-toggle="tab" href="#tab3" aria-controls="tab3" role="tab">混淆</a>
+							<a class="nav-link" data-toggle="tab" href="#obfs" aria-controls="obfs" role="tab">混淆</a>
 						</li>
 						<li class="nav-item" role="presentation">
-							<a class="nav-link" data-toggle="tab" href="#tab4" aria-controls="tab4" role="tab">等级</a>
+							<a class="nav-link" data-toggle="tab" href="#level" aria-controls="level" role="tab">等级</a>
 						</li>
 						<li class="nav-item" role="presentation">
-							<a class="nav-link" data-toggle="tab" href="#tab5" aria-controls="tab5" role="tab">国家地区</a>
+							<a class="nav-link" data-toggle="tab" href="#country" aria-controls="country" role="tab">国家地区</a>
 						</li>
 					</ul>
-					<div class="tab-content">
-						<div class="tab-pane active" id="tab1" role="tabpanel">
+					<div class="tab-content py-15">
+						<div class="tab-pane active" id="method" role="tabpanel">
 							<button class="btn btn-primary float-right mb-10" data-toggle="modal" data-target="#add_config_modal"> 新增
 								<i class="icon wb-plus"></i></button>
-							<table class="text-md-center" data-toggle="table" data-mobile-responsive="true">
+							<table class="text-md-center" data-toggle="table" data-height="700" data-virtual-scroll="true" data-mobile-responsive="true">
 								<thead class="thead-default">
 								<tr>
 									<th> 名称</th>
@@ -53,8 +53,8 @@
 													<span class='badge badge-lg badge-default'>默认</span>
 												@else
 													<div class="btn-group">
-														<button class="btn btn-primary" onclick="setDefault('1', '{{$method->id}}')">默认</button>
-														<button class="btn btn-danger" onclick="delConfig('1', '{{$method->id}}')">
+														<button class="btn btn-primary" onclick="setDefault('{{$method->id}}')">默认</button>
+														<button class="btn btn-danger" onclick="delConfig('{{$method->id}}','{{$method->name}}')">
 															<i class="icon wb-trash"></i>
 														</button>
 													</div>
@@ -66,10 +66,10 @@
 								</tbody>
 							</table>
 						</div>
-						<div class="tab-pane" id="tab2" role="tabpanel">
+						<div class="tab-pane" id="protocol" role="tabpanel">
 							<button class="btn btn-primary float-right mb-10" data-toggle="modal" data-target="#add_config_modal"> 新增
 								<i class="icon wb-plus"></i></button>
-							<table class="text-md-center" data-toggle="table" data-mobile-responsive="true">
+							<table class="text-md-center" data-toggle="table" data-height="700" data-virtual-scroll="true" data-mobile-responsive="true">
 								<thead class="thead-default">
 								<tr>
 									<th> 名称</th>
@@ -77,7 +77,7 @@
 								</tr>
 								</thead>
 								<tbody>
-								@if($method_list->isEmpty())
+								@if($protocol_list->isEmpty())
 									<tr>
 										<td colspan="2">暂无数据</td>
 									</tr>
@@ -90,8 +90,8 @@
 													<span class="badge badge-lg badge-default">默认</span>
 												@else
 													<div class="btn-group">
-														<button class="btn btn-primary" onclick="setDefault('2', '{{$protocol->id}}')">默认</button>
-														<button class="btn btn-danger" onclick="delConfig('2', '{{$protocol->id}}')">
+														<button class="btn btn-primary" onclick="setDefault('{{$protocol->id}}')">默认</button>
+														<button class="btn btn-danger" onclick="delConfig('{{$protocol->id}}','{{$protocol->name}}')">
 															<i class="icon wb-trash"></i>
 														</button>
 													</div>
@@ -103,11 +103,10 @@
 								</tbody>
 							</table>
 						</div>
-
-						<div class="tab-pane" id="tab3" role="tabpanel">
+						<div class="tab-pane" id="obfs" role="tabpanel">
 							<button class="btn btn-primary float-right mb-10" data-toggle="modal" data-target="#add_config_modal"> 新增
 								<i class="icon wb-plus"></i></button>
-							<table class="text-md-center" data-toggle="table" data-mobile-responsive="true">
+							<table class="text-md-center" data-toggle="table" data-height="700" data-virtual-scroll="true" data-mobile-responsive="true">
 								<thead class="thead-default">
 								<tr>
 									<th> 名称</th>
@@ -127,8 +126,8 @@
 												@if($obfs->is_default)
 													<span class="badge badge-lg badge-default">默认</span>
 												@else
-													<button class="btn btn-primary" onclick="setDefault('3', '{{$obfs->id}}')">默认</button>
-													<button class="btn btn-danger" onclick="delConfig('3', '{{$obfs->id}}')">
+													<button class="btn btn-primary" onclick="setDefault('{{$obfs->id}}')">默认</button>
+													<button class="btn btn-danger" onclick="delConfig('{{$obfs->id}}','{{$obfs->name}}')">
 														<i class="icon wb-trash"></i>
 													</button>
 												@endif
@@ -139,10 +138,10 @@
 								</tbody>
 							</table>
 						</div>
-						<div class="tab-pane" id="tab4" role="tabpanel">
+						<div class="tab-pane" id="level" role="tabpanel">
 							<button class="btn btn-primary float-right mb-10" data-toggle="modal" data-target="#add_level_modal"> 新增
 								<i class="icon wb-plus"></i></button>
-							<table class="text-md-center" data-toggle="table" data-mobile-responsive="true">
+							<table class="text-md-center" data-toggle="table" data-height="700" data-virtual-scroll="true" data-mobile-responsive="true">
 								<thead class="thead-default">
 								<tr>
 									<th> 等级</th>
@@ -166,8 +165,8 @@
 											</td>
 											<td>
 												<div class="btn-group">
-													<button type="button" class="btn btn-primary" onclick="updateLevel('4', '{{$level->id}}')">修改</button>
-													<button type="button" class="btn btn-danger" onclick="delLevel('4', '{{$level->id}}')">
+													<button type="button" class="btn btn-primary" onclick="updateLevel('{{$level->id}}')">修改</button>
+													<button type="button" class="btn btn-danger" onclick="delLevel('{{$level->id}}','{{$level->level_name}}')">
 														<i class="icon wb-trash"></i>
 													</button>
 												</div>
@@ -178,10 +177,10 @@
 								</tbody>
 							</table>
 						</div>
-						<div class="tab-pane" id="tab5" role="tabpanel">
+						<div class="tab-pane" id="country" role="tabpanel">
 							<button class="btn btn-primary float-right mb-10" data-toggle="modal" data-target="#add_country_modal"> 新增
 								<i class="icon wb-plus"></i></button>
-							<table class="text-md-center" data-toggle="table" data-mobile-responsive="true">
+							<table class="text-md-center" data-toggle="table" data-height="600" data-virtual-scroll="true" data-mobile-responsive="true">
 								<thead class="thead-default">
 								<tr>
 									<th> 图标</th>
@@ -199,20 +198,20 @@
 									@foreach($country_list as $country)
 										<tr>
 											<td>
-												<svg class="w-50 h-50 text-center" aria-hidden="true">
-													<use xlink:href="@if($country->country_code)#icon-{{$country->country_code}}@endif"></use>
+												<svg class="w-40 h-40 text-center" aria-hidden="true">
+													<use xlink:href="@if($country->code)#icon-{{$country->code}}@endif"></use>
 												</svg>
 											</td>
 											<td>
-												<input id="country_name_{{$country->id}}" name="country_name" value="{{$country->country_name}}" type="text" class="form-control">
+												<input id="country_name_{{$country->id}}" name="country_name" value="{{$country->name}}" type="text" class="form-control">
 											</td>
 											<td>
-												<input id="country_code_{{$country->id}}" name="country_code" value="{{$country->country_code}}" type="text" class="form-control">
+												<input id="country_code_{{$country->id}}" name="country_code" value="{{$country->code}}" type="text" class="form-control">
 											</td>
 											<td>
 												<div class="btn-group">
-													<button type="button" class="btn btn-primary" onclick="updateCountry('5', '{{$country->id}}')">修改</button>
-													<button type="button" class="btn btn-danger" onclick="delCountry('5', '{{$country->id}}')"><i class="icon wb-trash"></i></button>
+													<button type="button" class="btn btn-primary" onclick="updateCountry('{{$country->id}}')">修改</button>
+													<button type="button" class="btn btn-danger" onclick="delCountry('{{$country->id}}','{{$country->name}}')"><i class="icon wb-trash"></i></button>
 												</div>
 											</td>
 										</tr>
@@ -223,7 +222,6 @@
 						</div>
 					</div>
 				</div>
-
 			</div>
 		</div>
 	</div>
@@ -253,13 +251,12 @@
 					</div>
 				</form>
 				<div class="modal-footer">
-					<button class="btn btn-danger" data-dismiss="modal">关闭</button>
-					<button class="btn btn-primary" onclick="addConfig()">提交</button>
+					<button class="btn btn-danger" data-dismiss="modal">关 闭</button>
+					<button class="btn btn-primary" onclick="addConfig()">提 交</button>
 				</div>
 			</div>
 		</div>
 	</div>
-
 	<div class="modal fade" id="add_level_modal" aria-hidden="true" role="dialog" tabindex="-1">
 		<div class="modal-dialog modal-simple modal-center">
 			<div class="modal-content">
@@ -281,13 +278,12 @@
 					</div>
 				</form>
 				<div class="modal-footer">
-					<button data-dismiss="modal" class="btn btn-danger">关闭</button>
-					<button class="btn btn-primary" onclick="addLevel('4')">提交</button>
+					<button data-dismiss="modal" class="btn btn-danger">关 闭</button>
+					<button class="btn btn-primary" onclick="addLevel('4')">提 交</button>
 				</div>
 			</div>
 		</div>
 	</div>
-
 	<div class="modal fade" id="add_country_modal" aria-hidden="true" role="dialog" tabindex="-1">
 		<div class="modal-dialog modal-simple modal-center">
 			<div class="modal-content">
@@ -309,13 +305,12 @@
 					</div>
 				</form>
 				<div class="modal-footer">
-					<button data-dismiss="modal" class="btn btn-danger">关闭</button>
-					<button class="btn btn-primary" onclick="addCountry('5')">提交</button>
+					<button data-dismiss="modal" class="btn btn-danger">关 闭</button>
+					<button class="btn btn-primary" onclick="addCountry('5')">提 交</button>
 				</div>
 			</div>
 		</div>
 	</div>
-
 @endsection
 @section('script')
 	<script src="/assets/global/vendor/matchheight/jquery.matchHeight-min.js" type="text/javascript"></script>
@@ -325,7 +320,7 @@
 
 	<script type="text/javascript">
         // 添加等级
-        function addLevel(tabId) {
+        function addLevel() {
             const level = $('#add_level').val();
             const level_name = $('#add_level_name').val();
 
@@ -354,31 +349,29 @@
                         return false;
                     }
                     $("#add_level_modal").modal("hide");
-                    window.location.href = '/admin/config?tab=' + tabId;
+                    window.location.href = '/admin/config';
                 },
                 error: function () {
                     $("#level_msg").show().html("请求错误,请重试");
                 },
                 complete: function () {
+                    swal.fire({title: '添加成功', type: "success", timer: 1000, showConfirmButton: false}).then(() => window.location.reload())
                 }
             });
         }
 
         // 更新等级
-        function updateLevel(tabId, id) {
-            const level = $('#level_' + id).val();
-            const level_name = $('#level_name_' + id).val();
-
+        function updateLevel(id) {
             $.ajax({
                 type: "POST",
                 url: "/admin/updateLevel",
                 async: false,
-                data: {_token: '{{csrf_token()}}', id: id, level: level, level_name: level_name},
+                data: {_token: '{{csrf_token()}}', id: id, level: $('#level_' + id).val(), level_name: $('#level_name_' + id).val()},
                 dataType: 'json',
                 success: function (ret) {
                     if (ret.status === 'success') {
                         swal.fire({title: ret.message, type: 'success', timer: 1000, showConfirmButton: false})
-                            .then(() => window.location.href = '/admin/config?tab=' + tabId)
+                            .then(() => window.location.href = '/admin/config')
                     } else {
                         swal.fire({title: ret.message, type: "error"}).then(() => window.location.reload())
                     }
@@ -387,9 +380,9 @@
         }
 
         // 删除等级
-        function delLevel(tabId, id) {
+        function delLevel(id, name) {
             swal.fire({
-                title: '确定删除该等级吗?',
+                title: '确定删除等级 【' + name + '】 ?',
                 type: 'question',
                 allowEnterKey: false,
                 showCancelButton: true,
@@ -400,7 +393,7 @@
                     $.post("/admin/delLevel", {id: id, _token: '{{csrf_token()}}'}, function (ret) {
                         if (ret.status === 'success') {
                             swal.fire({title: ret.message, type: 'success', timer: 1000, showConfirmButton: false})
-                                .then(() => window.location.href = '/admin/config?tab=' + tabId)
+                                .then(() => window.location.href = '/admin/config')
                         } else {
                             swal.fire({title: ret.message, type: "error"}).then(() => window.location.reload())
                         }
@@ -410,7 +403,7 @@
         }
 
         // 添加国家/地区
-        function addCountry(tabId) {
+        function addCountry() {
             var country_name = $('#add_country_name').val();
             var country_code = $('#add_country_code').val();
 
@@ -439,18 +432,19 @@
                         return false;
                     }
                     $("#add_country_modal").modal("hide");
-                    window.location.href = '/admin/config?tab=' + tabId;
+                    window.location.href = '/admin/config';
                 },
                 error: function () {
                     $("#country_msg").show().html("请求错误,请重试");
                 },
                 complete: function () {
+                    swal.fire({title: '添加成功', type: "success", timer: 1000, showConfirmButton: false}).then(() => window.location.reload())
                 }
             });
         }
 
         // 更新国家/地区
-        function updateCountry(tabId, id) {
+        function updateCountry(id) {
             const country_name = $('#country_name_' + id).val();
             const country_code = $('#country_code_' + id).val();
 
@@ -463,18 +457,18 @@
                 success: function (ret) {
                     if (ret.status === 'success') {
                         swal.fire({title: ret.message, type: 'success', timer: 1000, showConfirmButton: false})
-                            .then(() => window.location.href = '/admin/config?tab=' + tabId)
+                            .then(() => window.location.href = '/admin/config')
                     } else {
-                        swal.fire({title: ret.message, type: "error"}).then(() => window.location.reload())
+                        swal.fire({title: ret.message, type: "error"});
                     }
                 }
             });
         }
 
         // 删除国家/地区
-        function delCountry(tabId, id) {
+        function delCountry(id, name) {
             swal.fire({
-                title: '确定删除该国家/地区吗?',
+                title: '确定删除 【' + name + '】 信息?',
                 type: 'question',
                 allowEnterKey: false,
                 showCancelButton: true,
@@ -485,9 +479,9 @@
                     $.post("/admin/delCountry", {id: id, _token: '{{csrf_token()}}'}, function (ret) {
                         if (ret.status === 'success') {
                             swal.fire({title: ret.message, type: 'success', timer: 1000, showConfirmButton: false})
-                                .then(() => window.location.href = '/admin/config?tab=' + tabId)
+                                .then(() => window.location.href = '/admin/config')
                         } else {
-                            swal.fire({title: ret.message, type: "error"}).then(() => window.location.reload())
+                            swal.fire({title: ret.message, type: "error"});
                         }
                     });
                 }
@@ -496,7 +490,6 @@
 
         // 添加配置
         function addConfig() {
-            const _token = '{{csrf_token()}}';
             const name = $("#name").val();
             const type = $("#type").val();
 
@@ -509,7 +502,7 @@
             $.ajax({
                 url: '/admin/config',
                 type: "POST",
-                data: {_token: _token, name: name, type: type},
+                data: {_token: '{{csrf_token()}}', name: name, type: type},
                 beforeSend: function () {
                     $("#msg").show().html("正在添加");
                 },
@@ -525,14 +518,15 @@
                     $("#msg").show().html("请求错误,请重试");
                 },
                 complete: function () {
+                    swal.fire({title: '添加成功', type: "success", timer: 1000, showConfirmButton: false}).then(() => window.location.reload())
                 }
             });
         }
 
         // 删除配置
-        function delConfig(tabId, id) {
+        function delConfig(id, name) {
             swal.fire({
-                title: '确定删除配置?',
+                title: '确定删除配置 【' + name + '】 ?',
                 type: 'question',
                 allowEnterKey: false,
                 showCancelButton: true,
@@ -543,7 +537,7 @@
                     $.post("/admin/delConfig", {id: id, _token: '{{csrf_token()}}'}, function (ret) {
                         if (ret.status === 'success') {
                             swal.fire({title: ret.message, type: 'success', timer: 1000, showConfirmButton: false})
-                                .then(() => window.location.href = '/admin/config?tab=' + tabId)
+                                .then(() => window.location.href = '/admin/config')
                         } else {
                             swal.fire({title: ret.message, type: "error"}).then(() => window.location.reload())
                         }
@@ -553,18 +547,17 @@
         }
 
         // 置为默认
-        function setDefault(tabId, id) {
-            const _token = '{{csrf_token()}}';
+        function setDefault(id) {
             $.ajax({
                 type: "POST",
                 url: "/admin/setDefaultConfig",
                 async: false,
-                data: {_token: _token, id: id},
+                data: {_token: '{{csrf_token()}}', id: id},
                 dataType: 'json',
                 success: function (ret) {
                     if (ret.status === 'success') {
                         swal.fire({title: ret.message, type: 'success', timer: 1000, showConfirmButton: false})
-                            .then(() => window.location.href = '/admin/config?tab=' + tabId)
+                            .then(() => window.location.href = '/admin/config')
                     } else {
                         swal.fire({title: ret.message, type: "error"}).then(() => window.location.reload())
                     }

+ 7 - 14
resources/views/admin/convert.blade.php

@@ -71,13 +71,6 @@
 	<script type="text/javascript">
         // 转换
         function Convert() {
-            const _token = '{{csrf_token()}}';
-            const method = $('#method').val();
-            const transfer_enable = $('#transfer_enable').val();
-            const protocol = $('#protocol').val();
-            const protocol_param = $('#protocol_param').val();
-            const obfs = $('#obfs').val();
-            const obfs_param = $('#obfs_param').val();
             const content = $('#content').val();
 
             if (content.trim() === '') {
@@ -98,13 +91,13 @@
                         url: "/admin/convert",
                         async: false,
                         data: {
-                            _token: _token,
-                            method: method,
-                            transfer_enable: transfer_enable,
-                            protocol: protocol,
-                            protocol_param: protocol_param,
-                            obfs: obfs,
-                            obfs_param: obfs_param,
+                            _token: '{{csrf_token()}}',
+                            method: $('#method').val(),
+                            transfer_enable: $('#transfer_enable').val(),
+                            protocol: $('#protocol').val(),
+                            protocol_param: $('#protocol_param').val(),
+                            obfs: $('#obfs').val(),
+                            obfs_param: $('#obfs_param').val(),
                             content: content
                         },
                         dataType: 'json',

+ 1 - 2
resources/views/admin/decompile.blade.php

@@ -28,7 +28,6 @@
 	<script type="text/javascript">
         // 转换
         function Decompile() {
-            const _token = '{{csrf_token()}}';
             const content = $('#content').val();
 
             if (content.trim() === '') {
@@ -48,7 +47,7 @@
                         type: "POST",
                         url: "/admin/decompile",
                         async: false,
-                        data: {_token: _token, content: content},
+                        data: {_token: '{{csrf_token()}}', content: content},
                         dataType: 'json',
                         success: function (ret) {
                             if (ret.status === 'success') {

+ 4 - 4
resources/views/admin/editArticle.blade.php

@@ -51,7 +51,7 @@
 						<div class="col-md-4">
 							<input type="text" class="form-control" name="title" id="title" value="{{$article->title}}" autofocus required/>
 							<input type="hidden" name="id" value="{{$article->id}}"/>
-							<input type="hidden" name="_token" value="{{csrf_token()}}"/>
+							{{csrf_field()}}
 						</div>
 					</div>
 					@if($article->type == 1)
@@ -76,7 +76,7 @@
 							<label class="col-form-label col-md-2" for="logo">LOGO/图标</label>
 							@if($article->type == 1)
 								<div class="col-md-4">
-									<input type="file" name="logo" id="logo" data-plugin="dropify" data-default-file=@if($article->logo) {{$article->logo}} @else /assets/images/noimage.png @endif />
+									<input type="file" name="logo" id="logo" data-plugin="dropify" data-default-file={{$article->logo?:'/assets/images/noimage.png'}} />
 									<span class="text-help"> 推荐尺寸:100x75 </span>
 								</div>
 							@else
@@ -100,8 +100,8 @@
 					</div>
 					<div class="form-actions text-right">
 						<div class="btn-group">
-							<a href="/admin/articleList" class="btn btn-danger">返回</a>
-							<button type="submit" class="btn btn-success">提交</button>
+							<a href="/admin/articleList" class="btn btn-danger">返 回</a>
+							<button type="submit" class="btn btn-success">提 交</button>
 						</div>
 					</div>
 				</form>

+ 2 - 7
resources/views/admin/editGroup.blade.php

@@ -16,7 +16,6 @@
 					<div class="form-group row">
 						<label class="col-form-label col-md-1">分组名称</label>
 						<input type="text" class="form-control col-md-5" name="name" value="{{$group->name}}" id="name" autofocus required/>
-						<input type="hidden" name="_token" value="{{csrf_token()}}"/>
 					</div>
 					<div class="form-group row">
 						<label class="col-form-label col-md-1">分组级别</label>
@@ -30,7 +29,7 @@
 						<span class="text-help offset-md-1">暂时无用&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span>
 					</div>
 					<div class="form-actions">
-						<button type="submit" class="btn btn-success">提交</button>
+						<button type="submit" class="btn btn-success">提 交</button>
 					</div>
 				</form>
 			</div>
@@ -41,15 +40,11 @@
 	<script type="text/javascript">
         // ajax同步提交
         function Submit() {
-            const _token = '{{csrf_token()}}';
-            const name = $('#name').val();
-            const level = $("#level option:selected").val();
-
             $.ajax({
                 type: "POST",
                 url: "/admin/editGroup/{{$group->id}}",
                 async: false,
-                data: {_token: _token, name: name, level: level},
+                data: {_token: '{{csrf_token()}}', name: $('#name').val(), level: $("#level option:selected").val()},
                 dataType: 'json',
                 success: function (ret) {
                     if (ret.status === 'success') {

+ 2 - 8
resources/views/admin/editLabel.blade.php

@@ -16,7 +16,6 @@
 					<div class="form-group row">
 						<label for="name" class="col-form-label col-md-1">标签</label>
 						<input type="text" class="form-control col-md-6" name="name" id="name" value="{{$label->name}}" autofocus required>
-						<input type="hidden" name="_token" value="{{csrf_token()}}">
 					</div>
 					<div class="form-group row">
 						<label for="sort" class="col-form-label col-md-1">排序</label>
@@ -24,7 +23,7 @@
 						<span class="text-help offset-md-1"> 排序值越高显示时越靠前 &ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;</span>
 					</div>
 					<div class="form-actions">
-						<button type="submit" class="btn btn-success">提交</button>
+						<button type="submit" class="btn btn-success">提 交</button>
 					</div>
 				</form>
 			</div>
@@ -35,16 +34,11 @@
 	<script type="text/javascript">
         // ajax同步提交
         function Submit() {
-            const _token = '{{csrf_token()}}';
-            const id = '{{$label->id}}';
-            const name = $('#name').val();
-            const sort = $('#sort').val();
-
             $.ajax({
                 type: "POST",
                 url: "/admin/editLabel",
                 async: false,
-                data: {_token: _token, id: id, name: name, sort: sort},
+                data: {_token: '{{csrf_token()}}', id: '{{$label->id}}', name: $('#name').val(), sort: $('#sort').val()},
                 dataType: 'json',
                 success: function (ret) {
                     if (ret.status === 'success') {

+ 69 - 168
resources/views/admin/editNode.blade.php

@@ -42,37 +42,36 @@
 										</ul>
 									</div>
 									<div class="form-group row">
-										<label for="is_nat" class="col-md-3 col-form-label">NAT</label>
+										<label for="is_ddns" class="col-md-3 col-form-label">DDNS</label>
 										<ul class="col-md-9 list-unstyled list-inline">
 											<li class="list-inline-item">
 												<div class="radio-custom radio-primary">
-													<input type="radio" name="is_nat" value="1" {{$node->is_nat ? 'checked' : ''}}>
+													<input type="radio" name="is_ddns" value="1" {{$node->is_ddns ? 'checked' : ''}}>
 													<label>是</label>
 												</div>
 											</li>
 											<li class="list-inline-item">
 												<div class="radio-custom radio-primary">
-													<input type="radio" name="is_nat" value="0" {{$node->is_nat ? '' : 'checked'}}>
+													<input type="radio" name="is_ddns" value="0" {{$node->is_ddns ? '' : 'checked'}}>
 													<label>否</label>
 												</div>
 											</li>
 										</ul>
-										<span class="text-help offset-md-3"> NAT机需要<a href="https://github.com/ssrpanel/SSRPanel/wiki/NAT-VPS%E9%85%8D%E7%BD%AE%E6%95%99%E7%A8%8B" target="_blank">配置DDNS</a>,TCP阻断检测无效,务必填写域名 </span>
+										<span class="text-help offset-md-3"> 动态IP节点需要<a href="https://github.com/NewFuture/DDNS" target="_blank">配置DDNS</a>,对此类型节点,节点阻断功能会通过域名进行检测 </span>
 									</div>
 									<div class="form-group row">
 										<label for="name" class="col-md-3 col-form-label"> 节点名称 </label>
 										<input type="text" class="form-control col-md-4" name="name" id="name" value="{{$node->name}}" autofocus required>
 										<input type="hidden" name="id" value="{{$node->id}}">
-										<input type="hidden" name="_token" value="{{csrf_token()}}">
 									</div>
 									<div class="form-group row">
 										<label for="server" class="col-md-3 col-form-label"> 域名 </label>
-										<input type="url" class="form-control col-md-4" name="server" id="server" value="{{$node->server}}" placeholder="服务器域名地址,填则优先取域名地址">
+										<input type="text" class="form-control col-md-4" name="server" id="server" value="{{$node->server}}" placeholder="服务器域名地址,填则优先取域名地址">
 										<span class="text-help offset-md-3">如果开启Namesilo且域名是Namesilo上购买的,则会强制更新域名的DNS记录为本节点IP,如果其他节点绑定了该域名则会清空其域名信息</span>
 									</div>
 									<div class="form-group row">
 										<label for="ip" class="col-md-3 col-form-label"> IPv4地址 </label>
-										<input type="text" class="form-control col-md-4" name="ip" id="ip" value="{{$node->ip}}" placeholder="服务器IPv4地址" {{$node->is_nat ? 'readonly=readonly' : ''}} required>
+										<input type="text" class="form-control col-md-4" name="ip" id="ip" value="{{$node->ip}}" placeholder="服务器IPv4地址" {{$node->is_ddns ? 'readonly=readonly' : ''}} required>
 									</div>
 									<div class="form-group row">
 										<label for="ipv6" class="col-md-3 col-form-label"> IPv6地址 </label>
@@ -113,7 +112,7 @@
 											<option value="">请选择</option>
 											@if(!$country_list->isEmpty())
 												@foreach($country_list as $country)
-													<option value="{{$country->country_code}}" {{$node->country_code == $country->country_code ? 'selected' : ''}}>{{$country->country_code}} - {{$country->country_name}}</option>
+													<option value="{{$country->code}}" {{$node->country_code == $country->code ? 'selected' : ''}}>{{$country->code}} - {{$country->name}}</option>
 												@endforeach
 											@endif
 										</select>
@@ -261,40 +260,34 @@
 											</ul>
 										</div>
 										<div class="form-group row">
-											<label for="is_udp" class="col-md-3 col-form-label">UDP</label>
+											<label for="detectionType" class="col-md-3 col-form-label">节点阻断检测</label>
 											<ul class="col-md-9 list-unstyled list-inline">
 												<li class="list-inline-item">
 													<div class="radio-custom radio-primary">
-														<input type="radio" name="is_udp" value="1" {{$node->is_udp ? 'checked' : ''}}>
-														<label>允许</label>
+														<input type="radio" name="detectionType" value="0" @if ($node->detectionType == 0) checked @endif/>
+														<label>关闭</label>
 													</div>
 												</li>
 												<li class="list-inline-item">
 													<div class="radio-custom radio-primary">
-														<input type="radio" name="is_udp" value="0" {{$node->is_udp ? '' : 'checked'}}>
-														<label>不允许</label>
+														<input type="radio" name="detectionType" value="1" @if ($node->detectionType == 1) checked @endif/>
+														<label>只检测TCP</label>
 													</div>
 												</li>
-											</ul>
-											<span class="text-help offset-md-3"> 禁止UDP,则无法用于加速游戏 </span>
-										</div>
-										<div class="form-group row">
-											<label for="is_tcp_check" class="col-md-3 col-form-label">TCP阻断检测</label>
-											<ul class="col-md-9 list-unstyled list-inline">
 												<li class="list-inline-item">
 													<div class="radio-custom radio-primary">
-														<input type="radio" name="is_tcp_check" value="1" {{$node->is_tcp_check ? 'checked' : ''}}>
-														<label>开启</label>
+														<input type="radio" name="detectionType" value="2" @if ($node->detectionType == 2) checked @endif/>
+														<label>只检测ICMP</label>
 													</div>
 												</li>
 												<li class="list-inline-item">
 													<div class="radio-custom radio-primary">
-														<input type="radio" name="is_tcp_check" value="0" {{$node->is_tcp_check ? '' : 'checked'}}>
-														<label>关闭</label>
+														<input type="radio" name="detectionType" value="3" @if ($node->detectionType == 3) checked @endif/>
+														<label>检测全部</label>
 													</div>
 												</li>
 											</ul>
-											<span class="text-help offset-md-3"> 每30~60分钟随机进行TCP阻断检测 </span>
+											<span class="text-help offset-md-3"> 每30~60分钟随机进行节点阻断检测 </span>
 										</div>
 										<hr/>
 										<div class="form-group row">
@@ -308,7 +301,7 @@
 												</li>
 												<li class="list-inline-item">
 													<div class="radio-custom radio-primary">
-														<input type="radio" name="single" value="0" {{$node->single ? '' : 'checked'}}>
+														<input type="radio" name="single" value="0" {{$node->single? '' : 'checked'}}>
 														<label>关闭</label>
 													</div>
 												</li>
@@ -317,49 +310,14 @@
 										</div>
 										<div class="single-setting {{!$node->single ? 'hidden' : ''}}">
 											<div class="form-group row">
-												<label for="single_force" class="col-md-3 col-form-label">[单] 模式</label>
-												<select data-plugin="selectpicker" data-style="btn-outline btn-primary" class="col-md-5 form-control" name="single_force" id="single_force">
-													<option value="0" {{$node->single_force == '0' ? 'selected' : ''}}>兼容模式</option>
-													<option value="1" {{$node->single_force == '1' ? 'selected' : ''}}>严格模式</option>
-												</select>
-												<span class="text-help offset-md-3"> 严格模式:用户的端口无法连接,只能通过以下指定的端口进行连接(<a href="javascript:showPortsOnlyConfig();">如何配置</a>)</span>
-											</div>
-											<div class="form-group row">
-												<label for="single_port" class="col-md-3 col-form-label">[单] 端口</label>
-												<input type="number" class="form-control col-md-4" name="single_port" id="single_port" value="{{$node->single_port}}" placeholder="443">
+												<label for="port" class="col-md-3 col-form-label">[单] 端口</label>
+												<input type="number" class="form-control col-md-4" name="port" id="port" value="{{$node->port}}" placeholder="443">
 												<span class="text-help offset-md-3"> 推荐80或443,服务端需要配置 </span>
+												<span class="text-help offset-md-3"> 严格模式:用户的端口无法连接,只能通过以下指定的端口进行连接(<a href="javascript:showPortsOnlyConfig();">如何配置</a>)</span>
 											</div>
 											<div class="form-group row">
-												<label for="single_passwd" class="col-md-3 col-form-label">[单] 密码</label>
-												<input type="text" class="form-control col-md-4" name="single_passwd" id="single_passwd" value="{{$node->single_passwd}}" placeholder="password">
-											</div>
-											<div class="form-group row">
-												<label for="single_method" class="col-md-3 col-form-label">[单] 加密方式</label>
-												<select data-plugin="selectpicker" data-style="btn-outline btn-primary" class="col-md-5 form-control" name="single_method" id="single_method">
-													@foreach ($method_list as $method)
-														<option value="{{$method->name}}" @if($method->name == $node->single_method) selected @endif>{{$method->name}}</option>
-													@endforeach
-												</select>
-											</div>
-											<div class="form-group row">
-												<label for="single_protocol" class="col-md-3 col-form-label">[单] 协议</label>
-												<select data-plugin="selectpicker" data-style="btn-outline btn-primary" class="col-md-5 form-control" name="single_protocol" id="single_protocol">
-													<option value="origin" {{$node->single_protocol == 'origin' ? 'selected' : ''}}>origin</option>
-													<option value="verify_deflate" {{$node->single_protocol == 'verify_deflate' ? 'selected' : ''}}>verify_deflate</option>
-													<option value="auth_sha1_v4" {{$node->single_protocol == 'auth_sha1_v4' ? 'selected' : ''}}>auth_sha1_v4</option>
-													<option value="auth_aes128_md5" {{$node->single_protocol == 'auth_aes128_md5' ? 'selected' : ''}}>auth_aes128_md5</option>
-													<option value="auth_aes128_sha1" {{$node->single_protocol == 'auth_aes128_sha1' ? 'selected' : ''}}>auth_aes128_sha1</option>
-													<option value="auth_chain_a" {{$node->single_protocol == 'auth_chain_a' ? 'selected' : ''}}>auth_chain_a</option>
-												</select>
-											</div>
-											<div class="form-group row">
-												<label for="single_obfs" class="col-md-3 col-form-label">[单] 混淆</label>
-												<select data-plugin="selectpicker" data-style="btn-outline btn-primary" class="col-md-5 form-control" name="single_obfs" id="single_obfs">
-													<option value="plain" {{$node->single_obfs == 'plain' ? 'selected' : ''}}>plain</option>
-													<option value="http_simple" {{$node->single_obfs == 'http_simple' ? 'selected' : ''}}>http_simple</option>
-													<option value="random_head" {{$node->single_obfs == 'random_head' ? 'selected' : ''}}>random_head</option>
-													<option value="tls1.2_ticket_auth" {{$node->single_obfs == 'tls1.2_ticket_auth' ? 'selected' : ''}}>tls1.2_ticket_auth</option>
-												</select>
+												<label for="passwd" class="col-md-3 col-form-label">[单] 密码</label>
+												<input type="text" class="form-control col-md-4" name="passwd" id="passwd" value="{{$node->passwd}}" placeholder="password">
 											</div>
 										</div>
 									</div>
@@ -461,103 +419,52 @@
 	<script type="text/javascript">
         // ajax同步提交
         function Submit() {
-            var _token = '{{csrf_token()}}';
-            var id = '{{Request::get('id')}}';
-            var name = $('#name').val();
-            var labels = $("#labels").val();
-            var group_id = $("#group_id option:selected").val();
-            var country_code = $("#country_code option:selected").val();
-            var server = $('#server').val();
-            var ip = $('#ip').val();
-            var ipv6 = $('#ipv6').val();
-            var desc = $('#desc').val();
-            var method = $('#method').val();
-            var traffic_rate = $('#traffic_rate').val();
-            var protocol = $('#protocol').val();
-            var protocol_param = $('#protocol_param').val();
-            var obfs = $('#obfs').val();
-            var obfs_param = $('#obfs_param').val();
-            var bandwidth = $('#bandwidth').val();
-            var traffic = $('#traffic').val();
-            var monitor_url = $('#monitor_url').val();
-            var is_subscribe = $("input:radio[name='is_subscribe']:checked").val();
-            var is_nat = $("input:radio[name='is_nat']:checked").val();
-            var is_transit = $("input:radio[name='is_transit']:checked").val();
-            var ssh_port = $('#ssh_port').val();
-            var compatible = $("input:radio[name='compatible']:checked").val();
-            var single = $("input:radio[name='single']:checked").val();
-            var single_force = $('#single_force').val();
-            var single_port = $('#single_port').val();
-            var single_passwd = $('#single_passwd').val();
-            var single_method = $('#single_method').val();
-            var single_protocol = $('#single_protocol').val();
-            var single_obfs = $('#single_obfs').val();
-            var sort = $('#sort').val();
-            var status = $("input:radio[name='status']:checked").val();
-            var is_tcp_check = $("input:radio[name='is_tcp_check']:checked").val();
-
-            var service = $("input:radio[name='service']:checked").val();
-            var v2_alter_id = $('#v2_alter_id').val();
-            var v2_port = $('#v2_port').val();
-            var v2_method = $("#v2_method option:selected").val();
-            var v2_net = $('#v2_net').val();
-            var v2_type = $('#v2_type').val();
-            var v2_host = $('#v2_host').val();
-            var v2_path = $('#v2_path').val();
-            var v2_tls = $("input:radio[name='v2_tls']:checked").val();
-            var v2_insider_port = $('#v2_insider_port').val();
-            var v2_outsider_port = $('#v2_outsider_port').val();
-
             $.ajax({
                 type: "POST",
                 url: "/admin/editNode",
                 async: false,
                 data: {
-                    _token: _token,
-                    id: id,
-                    name: name,
-                    labels: labels,
-                    group_id: group_id,
-                    country_code: country_code,
-                    server: server,
-                    ip: ip,
-                    ipv6: ipv6,
-                    desc: desc,
-                    method: method,
-                    traffic_rate: traffic_rate,
-                    protocol: protocol,
-                    protocol_param: protocol_param,
-                    obfs: obfs,
-                    obfs_param: obfs_param,
-                    bandwidth: bandwidth,
-                    traffic: traffic,
-                    monitor_url: monitor_url,
-                    is_subscribe: is_subscribe,
-                    is_nat: is_nat,
-                    is_transit: is_transit,
-                    ssh_port: ssh_port,
-                    compatible: compatible,
-                    single: single,
-                    single_force: single_force,
-                    single_port: single_port,
-                    single_passwd: single_passwd,
-                    single_method: single_method,
-                    single_protocol: single_protocol,
-                    single_obfs: single_obfs,
-                    sort: sort,
-                    status: status,
-                    is_tcp_check: is_tcp_check,
-                    type: service,
-                    v2_alter_id: v2_alter_id,
-                    v2_port: v2_port,
-                    v2_method: v2_method,
-                    v2_net: v2_net,
-                    v2_type: v2_type,
-                    v2_host: v2_host,
-                    v2_path: v2_path,
-                    v2_tls: v2_tls,
-                    v2_insider_port: v2_insider_port,
-                    v2_outsider_port: v2_outsider_port
+                    _token: '{{csrf_token()}}',
+                    id: '{{Request::get('id')}}',
+                    name: $('#name').val(),
+                    labels: $('#labels').val(),
+                    group_id: $('#group_id option:selected').val(),
+                    country_code: $('#country_code option:selected').val(),
+                    server: $('#server').val(),
+                    ip: $('#ip').val(),
+                    ipv6: $('#ipv6').val(),
+                    desc: $('#desc').val(),
+                    method: $('#method').val(),
+                    traffic_rate: $('#traffic_rate').val(),
+                    protocol: $('#protocol').val(),
+                    protocol_param: $('#protocol_param').val(),
+                    obfs: $('#obfs').val(),
+                    obfs_param: $('#obfs_param').val(),
+                    bandwidth: $('#bandwidth').val(),
+                    traffic: $('#traffic').val(),
+                    monitor_url: $('#monitor_url').val(),
+                    is_subscribe: $("input:radio[name='is_subscribe']:checked").val(),
+                    is_ddns: $("input:radio[name='is_ddns']:checked").val(),
+                    is_transit: $("input:radio[name='is_transit']:checked").val(),
+                    ssh_port: $('#ssh_port').val(),
+                    compatible: $("input:radio[name='compatible']:checked").val(),
+                    single: $("input:radio[name='single']:checked").val(),
+                    port: $('#port').val(),
+                    passwd: $('#passwd').val(),
+                    sort: $('#sort').val(),
+                    status: $("input:radio[name='status']:checked").val(),
+                    detectionType: $("input:radio[name='detectionType']:checked").val(),
+                    type: $("input:radio[name='service']:checked").val(),
+                    v2_alter_id: $('#v2_alter_id').val(),
+                    v2_port: $('#v2_port').val(),
+                    v2_method: $("#v2_method option:selected").val(),
+                    v2_net: $('#v2_net').val(),
+                    v2_type: $('#v2_type').val(),
+                    v2_host: $('#v2_host').val(),
+                    v2_path: $('#v2_path').val(),
+                    v2_tls: $("input:radio[name='v2_tls']:checked").val(),
+                    v2_insider_port: $('#v2_insider_port').val(),
+                    v2_outsider_port: $('#v2_outsider_port').val()
                 },
                 dataType: 'json',
                 success: function (ret) {
@@ -574,9 +481,7 @@
 
         // 设置单端口多用户
         $("input:radio[name='single']").on('change', function () {
-            const single = parseInt($(this).val());
-
-            if (single) {
+            if (parseInt($(this).val())) {
                 $(".single-setting").show();
             } else {
                 $(".single-setting").hide();
@@ -585,9 +490,7 @@
 
         // 设置服务类型
         $("input:radio[name='service']").on('change', function () {
-            const service = parseInt($(this).val());
-
-            if (service === 1) {
+            if (parseInt($(this).val()) === 1) {
                 $(".ssr-setting").show();
                 $(".v2ray-setting").hide();
             } else {
@@ -596,11 +499,9 @@
             }
         });
 
-        // 设置是否为NAT
-        $("input:radio[name='is_nat']").on('change', function () {
-            var is_nat = parseInt($(this).val());
-
-            if (is_nat === 1) {
+        // 设置是否使用DDNS
+        $("input:radio[name='is_ddns']").on('change', function () {
+            if (parseInt($(this).val())) {
                 $("#ip").val("1.1.1.1").attr("readonly", "readonly");
                 $("#server").attr("required", "required");
             } else {

+ 30 - 58
resources/views/admin/editUser.blade.php

@@ -231,7 +231,7 @@
 								<label class="col-md-2 col-sm-3 col-form-label" for="passwd">密码</label>
 								<div class="col-xl-5 col-sm-8">
 									<div class="input-group">
-										<input class="form-control" type="text" name="passwd id=" passwd"" value="{{$user->passwd}}"/>
+										<input class="form-control" type="text" name="passwd" id="passwd" value="{{$user->passwd}}"/>
 										<span class="input-group-append"><button class="btn btn-success" type="button" onclick="makePasswd()"> <i class="icon wb-refresh"></i> </button></span>
 									</div>
 								</div>
@@ -250,7 +250,7 @@
 								<label class="col-md-2 col-sm-3 col-form-label" for="transfer_enable">可用流量</label>
 								<div class="col-xl-5 col-sm-8">
 									<div class="input-group">
-										<input type="number" class="form-control" name="transfer_enable" value="{{$user->transfer_enable}}" id="transfer_enable" required>
+										<input type="text" class="form-control" name="transfer_enable" value="{{$user->transfer_enable}}" id="transfer_enable" required>
 										<span class="input-group-text">GB</span>
 									</div>
 								</div>
@@ -410,33 +410,6 @@
 
         // ajax同步提交
         function Submit() {
-            const _token = '{{csrf_token()}}';
-            const username = $('#username').val();
-            const password = $('#password').val();
-            const pay_way = $("input:radio[name='pay_way']:checked").val();
-            const balance = $('#balance').val();
-            const status = $("input:radio[name='status']:checked").val();
-            const labels = $('#labels').val();
-            const enable_time = $('#enable_time').val();
-            const expire_time = $('#expire_time').val();
-            const wechat = $('#wechat').val();
-            const qq = $('#qq').val();
-            const is_admin = $("input:radio[name='is_admin']:checked").val();
-            const remark = $('#remark').val();
-            const level = $("#level option:selected").val();
-            const port = $('#port').val();
-            const passwd = $('#passwd').val();
-            const method = $('#method option:selected').val();
-            const transfer_enable = $('#transfer_enable').val();
-            const enable = $("input:radio[name='enable']:checked").val();
-            const protocol = $('#protocol option:selected').val();
-            const protocol_param = $('#protocol_param').val();
-            const obfs = $('#obfs option:selected').val();
-            const obfs_param = $('#obfs_param').val();
-            const speed_limit_per_con = $('#speed_limit_per_con').val();
-            const speed_limit_per_user = $('#speed_limit_per_user').val();
-            const vmess_id = $('#vmess_id').val();
-
             // 用途
             let usage = '';
             $.each($("input:checkbox[name='usage']"), function () {
@@ -444,39 +417,38 @@
                     usage += $(this).val() + ',';
                 }
             });
-            usage = usage.substring(0, usage.length - 1);
             $.ajax({
                 type: "POST",
                 url: "/admin/editUser/{{$user->id}}",
                 async: false,
                 data: {
-                    _token: _token,
-                    username: username,
-                    password: password,
-                    usage: usage,
-                    pay_way: pay_way,
-                    balance: balance,
-                    status: status,
-                    labels: labels,
-                    enable_time: enable_time,
-                    expire_time: expire_time,
-                    wechat: wechat,
-                    qq: qq,
-                    is_admin: is_admin,
-                    remark: remark,
-                    level: level,
-                    port: port,
-                    passwd: passwd,
-                    method: method,
-                    transfer_enable: transfer_enable,
-                    enable: enable,
-                    protocol: protocol,
-                    protocol_param: protocol_param,
-                    obfs: obfs,
-                    obfs_param: obfs_param,
-                    speed_limit_per_con: speed_limit_per_con,
-                    speed_limit_per_user: speed_limit_per_user,
-                    vmess_id: vmess_id
+                    _token: '{{csrf_token()}}',
+                    username: $('#username').val(),
+                    password: $('#password').val(),
+                    usage: usage.substring(0, usage.length - 1),
+                    pay_way: $("input:radio[name='pay_way']:checked").val(),
+                    balance: $('#balance').val(),
+                    status: $("input:radio[name='status']:checked").val(),
+                    labels: $('#labels').val(),
+                    enable_time: $('#enable_time').val(),
+                    expire_time: $('#expire_time').val(),
+                    wechat: $('#wechat').val(),
+                    qq: $('#qq').val(),
+                    is_admin: $("input:radio[name='is_admin']:checked").val(),
+                    remark: $('#remark').val(),
+                    level: $("#level option:selected").val(),
+                    port: $('#port').val(),
+                    passwd: $('#passwd').val(),
+                    method: $('#method option:selected').val(),
+                    transfer_enable: $('#transfer_enable').val(),
+                    enable: $("input:radio[name='enable']:checked").val(),
+                    protocol: $('#protocol option:selected').val(),
+                    protocol_param: $('#protocol_param').val(),
+                    obfs: $('#obfs option:selected').val(),
+                    obfs_param: $('#obfs_param').val(),
+                    speed_limit_per_con: $('#speed_limit_per_con').val(),
+                    speed_limit_per_user: $('#speed_limit_per_user').val(),
+                    vmess_id: $('#vmess_id').val()
                 },
                 dataType: 'json',
                 success: function (ret) {
@@ -532,7 +504,7 @@
             const amount = $("#amount").val();
             const reg = /^(\-?)\d+(\.\d+)?$/; //只可以是正负数字
 
-            if (amount.trim() === '' || amount == 0 || !reg.test(amount)) {
+            if (amount.trim() === '' || amount === 0 || !reg.test(amount)) {
                 $("#msg").show().html("请输入充值金额");
                 $("#name").focus();
                 return false;

+ 1 - 3
resources/views/admin/emailLog.blade.php

@@ -92,9 +92,7 @@
 	<script type="text/javascript">
         // 搜索
         function Search() {
-            const username = $("#username").val();
-            const type = $("#type option:selected").val();
-            window.location.href = '/admin/emailLog?username=' + username + '&type=' + type;
+            window.location.href = '/admin/emailLog?username=' + $("#username").val() + '&type=' + $("#type option:selected").val();
         }
 	</script>
 @endsection

+ 3 - 3
resources/views/admin/groupList.blade.php

@@ -35,7 +35,7 @@
 								<td>
 									<div class="btn-group">
 										<a href="/admin/editGroup/{{$group->id}}" class="btn btn-primary"><i class="icon wb-edit"></i></a>
-										<button class="btn btn-danger" onclick="delGroup('{{$group->id}}')"><i class="icon wb-trash"></i></button>
+										<button class="btn btn-danger" onclick="delGroup('{{$group->id}}','{{$group->name}}')"><i class="icon wb-trash"></i></button>
 									</div>
 								</td>
 							</tr>
@@ -64,10 +64,10 @@
 	<script src="/assets/global/vendor/bootstrap-table/extensions/mobile/bootstrap-table-mobile.min.js" type="text/javascript"></script>
 	<script type="text/javascript">
         // 删除节点分组
-        function delGroup(id) {
+        function delGroup(id, name) {
             swal.fire({
                 title: '警告',
-                text: '确定删除分组?',
+                text: '确定删除分组 【' + name + '】 ?',
                 type: 'warning',
                 showCancelButton: true,
                 cancelButtonText: '{{trans('home.ticket_close')}}',

+ 1 - 1
resources/views/admin/import.blade.php

@@ -23,7 +23,7 @@
 			<div class="panel-body">
 				<form action="/admin/import" method="POST" enctype="multipart/form-data" class="upload-form">
 					<input type="file" id="inputUpload" name="uploadFile" data-plugin="dropify" data-default-file="" required/>
-					<input type="hidden" name="_token" value="{{csrf_token()}}"/>
+					{{csrf_field()}}
 					<button type="submit" class="btn btn-success float-right mt-10"> 导入</button>
 				</form>
 			</div>

+ 25 - 18
resources/views/admin/inviteList.blade.php

@@ -50,30 +50,18 @@
 									<tr>
 										<td> {{$invite->id}} </td>
 										<td>
-											<a href="/register?code={{$invite->code}}" target="_blank">{{$invite->code}}</a>
+											<a href="javascript:void(0)" class="mt-clipboard" data-clipboard-action="copy" data-clipboard-text="{{url('/register?code='.$invite->code)}}">{{$invite->code}}</a>
 										</td>
 										<td> {{$invite->dateline}} </td>
 										<td>
-											@if($invite->uid == '0')
-												系统生成
-											@else
-												{{empty($invite->generator) ? '【账号已删除】' : $invite->generator->username}}
-											@endif
+											{{$invite->uid == 0 ? '系统生成' : (empty($invite->generator) ? '【账号已删除】' : $invite->generator->username)}}
 										</td>
 										<td>
-											@if($invite->status == '0')
-												<span class="badge badge-success">{{trans('home.invite_code_table_status_un')}}</span>
-											@elseif($invite->status == '1')
-												<span class="badge badge-danger">{{trans('home.invite_code_table_status_yes')}}</span>
-											@else
-												<span class="badge badge-default">{{trans('home.invite_code_table_status_expire')}}</span>
-											@endif
+											{!!$invite->status_label!!}
+										</td>
+										<td>
+											{{$invite->status == 1 ? (empty($invite->user) ? '【账号已删除】' : $invite->user->username) : ''}}
 										</td>
-										@if($invite->status == '1')
-											<td> {{empty($invite->user) ? '【账号已删除】' : $invite->user->username}} </td>
-										@else
-											<td></td>
-										@endif
 									</tr>
 								@endforeach
 							@endif
@@ -99,6 +87,7 @@
 
 @endsection
 @section('script')
+	<script src="/assets/custom/Plugin/clipboardjs/clipboard.min.js" type="text/javascript"></script>
 	<script src="/assets/global/vendor/bootstrap-table/bootstrap-table.min.js" type="text/javascript"></script>
 	<script src="/assets/global/vendor/bootstrap-table/extensions/mobile/bootstrap-table-mobile.min.js" type="text/javascript"></script>
 	<script type="text/javascript">
@@ -138,5 +127,23 @@
                 }
             });
         }
+
+        const clipboard = new ClipboardJS('.mt-clipboard');
+        clipboard.on('success', function () {
+            swal.fire({
+                title: '复制成功',
+                type: 'success',
+                timer: 1300,
+                showConfirmButton: false
+            });
+        });
+        clipboard.on('error', function () {
+            swal.fire({
+                title: '复制失败,请手动复制',
+                type: 'error',
+                timer: 1500,
+                showConfirmButton: false
+            });
+        });
 	</script>
 @endsection

+ 3 - 3
resources/views/admin/labelList.blade.php

@@ -41,7 +41,7 @@
 								<td>
 									<div class="btn-group">
 										<a href="/admin/editLabel?id={{$label->id}}&page={{Request::get('page', 1)}}" class="btn btn-primary"><i class="icon wb-edit"></i></a>
-										<button class="btn btn-danger" onclick="delLabel('{{$label->id}}')"><i class="icon wb-trash"></i></button>
+										<button class="btn btn-danger" onclick="delLabel('{{$label->id}}','{{$label->name}}')"><i class="icon wb-trash"></i></button>
 									</div>
 								</td>
 							</tr>
@@ -70,10 +70,10 @@
 	<script src="/assets/global/vendor/bootstrap-table/extensions/mobile/bootstrap-table-mobile.min.js" type="text/javascript"></script>
 	<script type="text/javascript">
         // 删除标签
-        function delLabel(id) {
+        function delLabel(id, name) {
             swal.fire({
                 title: '警告',
-                text: '确定删除标签?',
+                text: '确定删除标签 【' + name + '】 ?',
                 type: 'warning',
                 showCancelButton: true,
                 cancelButtonText: '{{trans('home.ticket_close')}}',

+ 1 - 4
resources/views/admin/layouts.blade.php

@@ -23,14 +23,12 @@
 	<!-- 插件/Plugins -->
 	<link href="/assets/global/vendor/animsition/animsition.min.css" type="text/css" rel="stylesheet">
 	<link href="/assets/global/vendor/asscrollable/asScrollable.min.css" type="text/css" rel="stylesheet">
-	<link href="/assets/global/vendor/intro-js/introjs.min.css" type="text/css" rel="stylesheet">
 	<link href="/assets/global/vendor/slidepanel/slidePanel.min.css" type="text/css" rel="stylesheet">
 	<link href="/assets/global/vendor/flag-icon-css/flag-icon.min.css" type="text/css" rel="stylesheet">
 	@yield('css')
 	<link href="/assets/custom/Plugin/sweetalert2/sweetalert2.min.css" type="text/css" rel="stylesheet">
 	<!-- 字体/Fonts -->
 	<link href="/assets/global/fonts/web-icons/web-icons.min.css" type="text/css" rel="stylesheet">
-	<link href="/assets/global/fonts/brand-icons/brand-icons.min.css" type="text/css" rel="stylesheet">
 	<link href="//fonts.loli.net/css?family=Roboto:300,400,500,300italic" type="text/css" rel="stylesheet">
 	<!--[if lt IE 9]>
 	<script src="/assets/global/vendor/html5shiv/html5shiv.min.js" type="text/javascript"></script>
@@ -57,7 +55,7 @@
 			<i class="icon wb-more-horizontal" aria-hidden="true"></i>
 		</button>
 		<div class="navbar-brand navbar-brand-center">
-			<img src="{{\App\Components\Helpers::systemConfig()['website_logo']?\App\Components\Helpers::systemConfig()['website_logo']:'/assets/images/logo64.png'}}" class="navbar-brand-logo" alt="logo"/>
+			<img src="{{\App\Components\Helpers::systemConfig()['website_logo']? :'/assets/images/logo64.png'}}" class="navbar-brand-logo" alt="logo"/>
 			<span class="navbar-brand-text hidden-xs-down"> {{\App\Components\Helpers::systemConfig()['website_name']}}</span>
 		</div>
 	</div>
@@ -360,7 +358,6 @@
 <script src="/assets/global/vendor/asscrollable/jquery-asScrollable.min.js" type="text/javascript"></script>
 <script src="/assets/global/vendor/ashoverscroll/jquery-asHoverScroll.min.js" type="text/javascript"></script>
 <!-- 插件/Plugins -->
-<script src="/assets/global/vendor/intro-js/intro.min.js" type="text/javascript"></script>
 <script src="/assets/global/vendor/screenfull/screenfull.js" type="text/javascript"></script>
 <script src="/assets/global/vendor/slidepanel/jquery-slidePanel.min.js" type="text/javascript"></script>
 <!--[if lt IE 11]>

+ 4 - 13
resources/views/admin/nodeList.blade.php

@@ -48,7 +48,7 @@
 									@endif
 								</td>
 								<td> {{$node->name}} </td>
-								<td> {{$node->is_nat ? 'Nat' : $node->ip}} </td>
+								<td> {{$node->is_ddns ? 'DDNS' : $node->ip}} </td>
 								<td> {{$node->server}} </td>
 								<td> {{$node->uptime}} </td>
 								<td> {{$node->status? $node->load : '维护'}} </td>
@@ -63,7 +63,7 @@
 								<td>
 									<div class="btn-group">
 										<a href="/admin/editNode?id={{$node->id}}&page={{Request::get('page', 1)}}" class="btn btn-primary"><i class="icon wb-edit"></i></a>
-										<a href="javascript:delNode({{$node->id}})" class="btn btn-danger"><i class="icon wb-trash"></i></a>
+										<a href="javascript:delNode('{{$node->id}}','{{$node->name}}')" class="btn btn-danger"><i class="icon wb-trash"></i></a>
 										<a href="/admin/nodeMonitor/{{$node->id}})" class="btn btn-primary"><i class="icon wb-stats-bars"></i></a>
 									</div>
 								</td>
@@ -93,10 +93,10 @@
 	<script src="/assets/global/vendor/bootstrap-table/extensions/mobile/bootstrap-table-mobile.min.js" type="text/javascript"></script>
 	<script type="text/javascript">
         // 删除节点
-        function delNode(id) {
+        function delNode(id, name) {
             swal.fire({
                 title: '警告',
-                text: '确定删除节点?',
+                text: '确定删除节点 【' + name + '】 ?',
                 type: 'warning',
                 showCancelButton: true,
                 cancelButtonText: '{{trans('home.ticket_close')}}',
@@ -124,14 +124,5 @@
                 showConfirmButton: false,
             });
         }
-
-        // 修正table的dropdown
-        $('.table-scrollable').on('show.bs.dropdown', function () {
-            $('.table-scrollable').css("overflow", "inherit");
-        });
-
-        $('.table-scrollable').on('hide.bs.dropdown', function () {
-            $('.table-scrollable').css("overflow", "auto");
-        });
 	</script>
 @endsection

+ 1 - 6
resources/views/admin/onlineIPMonitor.blade.php

@@ -110,12 +110,7 @@
 
         // 搜索
         function Search() {
-            const id = $("#id").val();
-            const username = $("#username").val();
-            const ip = $("#ip").val();
-            const port = $("#port").val();
-            const nodeId = $("#nodeId option:selected").val();
-            window.location.href = '/admin/onlineIPMonitor?id=' + id + '&ip=' + ip + '&username=' + username + '&port=' + port + '&nodeId=' + nodeId;
+            window.location.href = '/admin/onlineIPMonitor?id=' + $("#id").val() + '&ip=' + $("#ip").val() + '&username=' + $("#username").val() + '&port=' + $("#port").val() + '&nodeId=' + $("#nodeId option:selected").val();
         }
 	</script>
 @endsection

+ 1 - 11
resources/views/admin/orderList.blade.php

@@ -183,17 +183,7 @@
 
         // 搜索
         function Search() {
-            const username = $("#username").val();
-            const order_sn = $("#order_sn").val();
-            const is_expire = $("#is_expire").val();
-            const is_coupon = $("#is_coupon").val();
-            const pay_way = $("#pay_way").val();
-            const status = $("#status").val();
-            const sort = $("input:radio[name='sort']:checked").val();
-            const startTime = $("#start").val();
-            const endTime = $("#end").val();
-            const range_time = [startTime, endTime];
-            window.location.href = '/admin/orderList?username=' + username + '&order_sn=' + order_sn + '&is_expire=' + is_expire + '&is_coupon=' + is_coupon + '&pay_way=' + pay_way + '&status=' + status + '&sort=' + sort + '&range_time=' + range_time;
+            window.location.href = '/admin/orderList?username=' + $("#username").val() + '&order_sn=' + $("#order_sn").val() + '&is_expire=' + $("#is_expire").val() + '&is_coupon=' + $("#is_coupon").val() + '&pay_way=' + $("#pay_way").val() + '&status=' + $("#status").val() + '&sort=' + $("input:radio[name='sort']:checked").val() + '&range_time=' + [$("#start").val(), $("#end").val()];
         }
 	</script>
 @endsection

+ 1 - 1
resources/views/admin/profile.blade.php

@@ -19,10 +19,10 @@
 			@endif
 			<div class="panel-body">
 				<form action="/admin/profile" method="post" enctype="multipart/form-data" class="form-bordered">
+					{{csrf_field()}}
 					<div class="form-group row">
 						<label for="old_password" class="col-md-2 col-form-label"> 旧密码 </label>
 						<input type="password" class="form-control col-md-5 round" name="old_password" id="old_password" autofocus required/>
-						<input type="hidden" name="_token" value="{{csrf_token()}}"/>
 					</div>
 					<div class="form-group row">
 						<label for="new_password" class="col-md-2 col-form-label"> 新密码 </label>

File diff suppressed because it is too large
+ 814 - 705
resources/views/admin/system.blade.php


+ 2 - 6
resources/views/admin/trafficLog.blade.php

@@ -18,7 +18,7 @@
 						<input type="text" class="form-control" name="username" id="username" value="{{Request::get('username')}}" placeholder="用户名"/>
 					</div>
 					<div class="form-group col-lg-2 col-sm-3">
-						<input type="number" class="form-control" name="port" id="port" value="{{Request::get('port')}}" placeholder="端口"/>
+						<input type="number" class="form-control" name="port" id="port" value="{{Request::get('port')}}" placeholder="用户端口"/>
 					</div>
 					<div class="form-group col-lg-3 col-sm-5">
 						<select class="form-control" name="nodeId" id="nodeId" onChange="Search()">
@@ -104,11 +104,7 @@
 
         // 搜索
         function Search() {
-            const port = $("#port").val();
-            const user_id = $("#user_id").val();
-            const username = $("#username").val();
-            const nodeId = $("#nodeId option:selected").val();
-            window.location.href = '/admin/trafficLog' + '?port=' + port + '&user_id=' + user_id + '&username=' + username + '&nodeId=' + nodeId;
+            window.location.href = '/admin/trafficLog' + '?port=' + $("#port").val() + '&user_id=' + $("#user_id").val() + '&username=' + $("#username").val() + '&nodeId=' + $("#nodeId option:selected").val();
         }
 	</script>
 @endsection

+ 1 - 2
resources/views/admin/userBalanceLogList.blade.php

@@ -88,8 +88,7 @@
 
         // 搜索
         function Search() {
-            const username = $("#username").val();
-            window.location.href = '/admin/userBalanceLogList?username=' + username;
+            window.location.href = '/admin/userBalanceLogList?username=' + $("#username").val();
         }
 	</script>
 @endsection

+ 1 - 2
resources/views/admin/userBanLogList.blade.php

@@ -80,8 +80,7 @@
 
         // 搜索
         function Search() {
-            const username = $("#username").val();
-            window.location.href = '/admin/userBanLogList?username=' + username;
+            window.location.href = '/admin/userBanLogList?username=' + $("#username").val();
         }
 	</script>
 @endsection

+ 9 - 20
resources/views/admin/userList.blade.php

@@ -94,11 +94,8 @@
 								<td> {{$user->username}} </td>
 								<td> {{$user->balance}} </td>
 								<td>
-									@if ($user->port)
-										{{$user->port}}
-									@else
-										<span class="badge badge-lg badge-danger"> 未分配 </span>
-									@endif</td>
+									{!!$user->port? : '<span class="badge badge-lg badge-danger"> 未分配 </span>'!!}
+								</td>
 								<td>
 									<a href="javascript:" class="copySubscribeLink" data-clipboard-action="copy" data-clipboard-text="{{$user->link}}">{{$user->subscribe->code}}</a>
 								</td>
@@ -131,11 +128,11 @@
 								<td>
 									<div class="btn-group">
 										<a href="/admin/editUser/{{$user->id}}{{Request::getQueryString()? '?'.Request::getQueryString() : ''}}" class="btn btn-primary"><i class="icon wb-edit" aria-hidden="true"></i></a>
-										<a href="javascript:delUser('{{$user->id}}');" class="btn btn-danger"><i class="icon wb-trash" aria-hidden="true"></i></a>
+										<a href="javascript:delUser('{{$user->id}}','{{$user->username}}');" class="btn btn-danger"><i class="icon wb-trash" aria-hidden="true"></i></a>
 										<a href="/admin/export/{{$user->id}}" class="btn btn-primary"><i class="icon wb-code" aria-hidden="true"></i></a>
 										<a href="/admin/userMonitor/{{$user->id}}" class="btn btn-primary"><i class="icon wb-stats-bars" aria-hidden="true"></i></a>
 										<a href="/admin/onlineIPMonitor?id={{$user->id}}" class="btn btn-primary"><i class="icon wb-cloud" aria-hidden="true"></i></a>
-										<a href="javascript:resetTraffic('{{$user->id}}');" class="btn btn-primary"><i class="icon wb-reload" aria-hidden="true"></i></a>
+										<a href="javascript:resetTraffic('{{$user->id}}','{{$user->username}}');" class="btn btn-primary"><i class="icon wb-reload" aria-hidden="true"></i></a>
 										<a href="javascript:switchToUser('{{$user->id}}');" class="btn btn-primary"><i class="icon wb-user" aria-hidden="true"></i></a>
 									</div>
 								</td>
@@ -209,22 +206,14 @@
 
         // 搜索
         function Search() {
-            const id = $("#id").val();
-            const username = $("#username").val();
-            const wechat = $("#wechat").val();
-            const qq = $("#qq").val();
-            const port = $("#port").val();
-            const pay_way = $("#pay_way option:selected").val();
-            const status = $("#status option:selected").val();
-            const enable = $("#enable option:selected").val();
-            window.location.href = '/admin/userList' + '?id=' + id + '&username=' + username + '&wechat=' + wechat + '&qq=' + qq + '&port=' + port + '&pay_way=' + pay_way + '&status=' + status + '&enable=' + enable;
+            window.location.href = '/admin/userList' + '?id=' + $("#id").val() + '&username=' + $("#username").val() + '&wechat=' + $("#wechat").val() + '&qq=' + $("#qq").val() + '&port=' + $("#port").val() + '&pay_way=' + $("#pay_way option:selected").val() + '&status=' + $("#status option:selected").val() + '&enable=' + $("#enable option:selected").val();
         }
 
         // 删除账号
-        function delUser(id) {
+        function delUser(id, username) {
             swal.fire({
                 title: '警告',
-                text: '确定删除账号?',
+                text: '确定删除用户 【' + username + '】 ?',
                 type: 'warning',
                 showCancelButton: true,
                 cancelButtonText: '{{trans('home.ticket_close')}}',
@@ -244,10 +233,10 @@
         }
 
         // 重置流量
-        function resetTraffic(id) {
+        function resetTraffic(id, username) {
             swal.fire({
                 title: '警告',
-                text: '确定重置该用户流量吗?',
+                text: '确定重置 【' + username + '】 流量吗?',
                 type: 'warning',
                 showCancelButton: true,
                 cancelButtonText: '{{trans('home.ticket_close')}}',

+ 1 - 6
resources/views/admin/userOnlineIPList.blade.php

@@ -131,12 +131,7 @@
 
         // 搜索
         function Search() {
-            const id = $("#id").val();
-            const username = $("#username").val();
-            const wechat = $("#wechat").val();
-            const qq = $("#qq").val();
-            const port = $("#port").val();
-            window.location.href = '/admin/userOnlineIPList' + '?id' + id + '&username=' + username + '&wechat=' + wechat + '&qq=' + qq + '&port=' + port;
+            window.location.href = '/admin/userOnlineIPList' + '?id' + $("#id").val() + '&username=' + $("#username").val() + '&wechat=' + $("#wechat").val() + '&qq=' + $("#qq").val() + '&port=' + $("#port").val();
         }
 	</script>
 @endsection

+ 1 - 4
resources/views/admin/userRebateList.blade.php

@@ -116,10 +116,7 @@
 
         // 搜索
         function Search() {
-            const username = $("#username").val();
-            const ref_username = $("#ref_username").val();
-            const status = $("#status option:selected").val();
-            window.location.href = '/admin/userRebateList' + '?username=' + username + '&ref_username=' + ref_username + '&status=' + status;
+            window.location.href = '/admin/userRebateList' + '?username=' + $("#username").val() + '&ref_username=' + $("#ref_username").val() + '&status=' + $("#status option:selected").val();
         }
 	</script>
 @endsection

+ 1 - 2
resources/views/admin/userTrafficLogList.blade.php

@@ -94,8 +94,7 @@
 
         // 搜索
         function Search() {
-            const username = $("#username").val();
-            window.location.href = '/admin/userTrafficLogList' + '?username=' + username;
+            window.location.href = '/admin/userTrafficLogList' + '?username=' + $("#username").val();
         }
 	</script>
 @endsection

+ 1 - 3
resources/views/auth/active.blade.php

@@ -12,8 +12,6 @@
 		</div>
 	@endif
 	<form action="{{url(Request::getRequestUri())}}" method="post">
-		<div class="form-group form-material pt-20" data-plugin="formMaterial">
-			<button class="btn btn-lg btn-success" onclick="login()">{{trans('auth.login')}}</button>
-		</div>
+		<a href="/login" class="btn btn-lg btn-block btn-success">{{trans('auth.login')}}</a>
 	</form>
 @endsection

+ 5 - 7
resources/views/auth/activeUser.blade.php

@@ -21,18 +21,16 @@
 			<div class="form-group form-material floating" data-plugin="formMaterial">
 				<input type="email" class="form-control" name="username" value="{{Request::get('username')}}" required/>
 				<label class="floating-label" for="username">{{trans('auth.username')}}</label>
-				<input type="hidden" name="_token" value="{{csrf_token()}}"/>
+				{{csrf_field()}}
 			</div>
 		@else
 			<div class="alert alert-danger">
 				<span> {{trans('auth.system_maintenance_tip',['email' => \App\Components\Helpers::systemConfig()['admin_email']])}}</span>
 			</div>
 		@endif
-		<div class="form-actions">
-			<button class="btn btn-danger btn-lg float-left" onclick="login()">{{trans('auth.back')}}</button>
-			@if(\App\Components\Helpers::systemConfig()['is_active_register'])
-				<button type="submit" class="btn btn-primary btn-lg float-right">{{trans('auth.active')}}</button>
-			@endif
-		</div>
+		<a href="/login" class="btn btn-danger btn-lg {{\App\Components\Helpers::systemConfig()['is_active_register']? 'float-left':'btn-block'}}">{{trans('auth.back')}}</a>
+		@if(\App\Components\Helpers::systemConfig()['is_active_register'])
+			<button type="submit" class="btn btn-lg btn-primary float-right">{{trans('auth.active')}}</button>
+		@endif
 	</form>
 @endsection

+ 2 - 5
resources/views/auth/error.blade.php

@@ -24,13 +24,11 @@
 	<!-- 插件/Plugins -->
 	<link href="/assets/global/vendor/animsition/animsition.min.css" type="text/css" rel="stylesheet">
 	<link href="/assets/global/vendor/asscrollable/asScrollable.min.css" type="text/css" rel="stylesheet">
-	<link href="/assets/global/vendor/intro-js/introjs.min.css" type="text/css" rel="stylesheet">
 	<link href="/assets/global/vendor/slidepanel/slidePanel.min.css" type="text/css" rel="stylesheet">
 	<link href="/assets/global/vendor/flag-icon-css/flag-icon.min.css" type="text/css" rel="stylesheet">
 	<link href="/assets/examples/css/pages/errors.min.css" type="text/css" rel="stylesheet">
 	<!-- 字体/Fonts -->
 	<link href="/assets/global/fonts/web-icons/web-icons.min.css" type="text/css" rel="stylesheet">
-	<link href="/assets/global/fonts/brand-icons/brand-icons.min.css" type="text/css" rel="stylesheet">
 	<link href="//fonts.loli.net/css?family=Roboto:300,400,500,300italic" type="text/css" rel="stylesheet">
 	<!--[if lt IE 9]>
 	<script src="/assets/global/vendor/html5shiv/html5shiv.min.js" type="text/javascript"></script>
@@ -48,8 +46,8 @@
 <body class="animsition page-error page-error-400 layout-full">
 <!--[if lt IE 8]>
 <p class="browserupgrade">您正在使用 <strong>过时/老旧</strong> 的浏览器。 为了您的使用体验,请
-	<a href="http://browsehappy.com/">升级您的浏览器</a> </br>You are using an <strong>outdated</strong> browser. Please
-	<a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p>
+	<a href="http://browsehappy.com/" target="_blank">升级您的浏览器</a> </br>You are using an <strong>outdated</strong> browser. Please
+	<a href="http://browsehappy.com/" target="_blank">upgrade your browser</a> to improve your experience.</p>
 <![endif]-->
 
 <div class="page vertical-align text-center" data-animsition-in="fade-in" data-animsition-out="fade-out">
@@ -73,7 +71,6 @@
 <script src="/assets/global/vendor/asscrollable/jquery-asScrollable.min.js" type="text/javascript"></script>
 <script src="/assets/global/vendor/ashoverscroll/jquery-asHoverScroll.min.js" type="text/javascript"></script>
 <!-- 插件/Plugins -->
-<script src="/assets/global/vendor/intro-js/intro.min.js" type="text/javascript"></script>
 <script src="/assets/global/vendor/screenfull/screenfull.js" type="text/javascript"></script>
 <script src="/assets/global/vendor/slidepanel/jquery-slidePanel.min.js" type="text/javascript"></script>
 <!-- 脚本/Scripts -->

+ 1 - 1
resources/views/auth/free.blade.php

@@ -44,7 +44,7 @@
 	</div>
 	@if(\App\Components\Helpers::systemConfig()['is_invite_register'] && \App\Components\Helpers::systemConfig()['is_free_code'])
 		<div class="mt-20">
-			<button class="btn btn-danger btn-lg float-left" onclick="login()">{{trans('auth.back')}}</button>
+			<a href="/login" class="btn btn-danger btn-lg float-left">{{trans('auth.back')}}</a>
 			<nav class="Page navigation float-right">
 				{{$inviteList->links()}}
 			</nav>

+ 37 - 43
resources/views/auth/layouts.blade.php

@@ -23,14 +23,12 @@
 	<!-- Plugins -->
 	<link href="/assets/global/vendor/animsition/animsition.min.css" type="text/css" rel="stylesheet">
 	<link href="/assets/global/vendor/asscrollable/asScrollable.min.css" type="text/css" rel="stylesheet">
-	<link href="/assets/global/vendor/intro-js/introjs.min.css" type="text/css" rel="stylesheet">
 	<link href="/assets/global/vendor/slidepanel/slidePanel.min.css" type="text/css" rel="stylesheet">
 	<link href="/assets/global/vendor/flag-icon-css/flag-icon.min.css" type="text/css" rel="stylesheet">
 	<link href="/assets/examples/css/pages/login-v3.css" type="text/css" rel="stylesheet">
 @yield('css')
 <!-- Fonts -->
 	<link href="/assets/global/fonts/web-icons/web-icons.min.css" type="text/css" rel="stylesheet">
-	<link href="/assets/global/fonts/brand-icons/brand-icons.min.css" type="text/css" rel="stylesheet">
 	<link href="//fonts.loli.net/css?family=Roboto:300,400,500,300italic" type="text/css" rel="stylesheet">
 	<!--[if lt IE 9]>
 	<script src="/assets/global/vendor/html5shiv/html5shiv.min.js" type="text/javascript"></script> <![endif]-->
@@ -45,10 +43,10 @@
 </head>
 <body class="animsition page-login-v3 layout-full" style="position: relative;">
 <!--[if lt IE 8]> <p class="browserupgrade">您正在使用 <strong>过时/老旧</strong> 的浏览器。 为了您的使用体验,请
-	<a href="http://browsehappy.com/">升级您的浏览器</a> </br>You are using an <strong>outdated</strong> browser. Please
-	<a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p>
+	<a href="http://browsehappy.com/" target="_blank">升级您的浏览器</a> </br>You are using an <strong>outdated</strong> browser. Please
+	<a href="http://browsehappy.com/" target="_blank">upgrade your browser</a> to improve your experience.</p>
 <![endif]-->
-@if(Agent::isMobile() && Agent::isiOS() && strpos(Agent::getUserAgent(), 'MicroMessenger') !== false)
+@if(Agent::isMobile() && Agent::is('iOS') && strpos(Agent::getUserAgent(), 'MicroMessenger') !== FALSE)
 	<style type="text/css">
 		.cover-up {
 			opacity: 0.1;
@@ -64,42 +62,45 @@
 	</div>
 @endif
 <div class="page vertical-align text-center cover-up" data-animsition-in="fade-in" data-animsition-out="fade-out">
-	<div class="page-content vertical-align-middle animation-slide-top animation-duration-1">
-		<div class="panel">
-			<div class="panel-heading">
-				<div class="panel-title">
-					<div class="brand">
-						<img src="{{\App\Components\Helpers::systemConfig()['website_home_logo']?\App\Components\Helpers::systemConfig()['website_home_logo']:'/assets/images/logo64.png'}}" class="brand-img" alt="logo"/>
-						<h3 class="brand-text">{{\App\Components\Helpers::systemConfig()['website_name']}}</h3>
+	<div class="page-content vertical-align-middle">
+		<div class="animation-slide-top animation-duration-1">
+			<div class="panel">
+				<div class="panel-heading">
+					<div class="panel-title">
+						<div class="brand">
+							<img src="{{\App\Components\Helpers::systemConfig()['website_home_logo']? :'/assets/images/logo64.png'}}" class="brand-img" alt="logo"/>
+							<h3 class="brand-text">{{\App\Components\Helpers::systemConfig()['website_name']}}</h3>
+						</div>
 					</div>
-				</div>
-				<div class="ribbon ribbon-reverse ribbon-info ribbon-clip">
-					<button class="ribbon-inner btn dropdown-toggle pt-0" id="language" data-toggle="dropdown" aria-expanded="false">
-						<i class="font-size-20 wb-globe"></i>
-					</button>
-					<div class="dropdown-menu dropdown-menu-bullet" aria-labelledby="language" role="menu">
-						<a class="dropdown-item" href="{{url('lang', ['locale' => 'zh-CN'])}}" role="menuitem">
-							<span class="flag-icon flag-icon-cn"></span>
-							简体中文</a>
-						<a class="dropdown-item" href="{{url('lang', ['locale' => 'zh-tw'])}}" role="menuitem">
-							<span class="flag-icon flag-icon-tw"></span>
-							繁體中文</a>
-						<a class="dropdown-item" href="{{url('lang', ['locale' => 'en'])}}" role="menuitem">
-							<span class="flag-icon flag-icon-gb"></span>
-							English</a>
-						<a class="dropdown-item" href="{{url('lang', ['locale' => 'ja'])}}" role="menuitem">
-							<span class="flag-icon flag-icon-jp"></span>
-							日本語</a>
-						<a class="dropdown-item" href="{{url('lang', ['locale' => 'ko'])}}" role="menuitem">
-							<span class="flag-icon flag-icon-kr"></span>
-							한국어</a>
+					<div class="ribbon ribbon-reverse ribbon-info ribbon-clip">
+						<button class="ribbon-inner btn dropdown-toggle pt-0" id="language" data-toggle="dropdown" aria-expanded="false">
+							<i class="font-size-20 wb-globe"></i>
+						</button>
+						<div class="dropdown-menu dropdown-menu-bullet" aria-labelledby="language" role="menu">
+							<a class="dropdown-item" href="{{url('lang', ['locale' => 'zh-CN'])}}" role="menuitem">
+								<span class="flag-icon flag-icon-cn"></span>
+								简体中文</a>
+							<a class="dropdown-item" href="{{url('lang', ['locale' => 'zh-tw'])}}" role="menuitem">
+								<span class="flag-icon flag-icon-tw"></span>
+								繁體中文</a>
+							<a class="dropdown-item" href="{{url('lang', ['locale' => 'en'])}}" role="menuitem">
+								<span class="flag-icon flag-icon-gb"></span>
+								English</a>
+							<a class="dropdown-item" href="{{url('lang', ['locale' => 'ja'])}}" role="menuitem">
+								<span class="flag-icon flag-icon-jp"></span>
+								日本語</a>
+							<a class="dropdown-item" href="{{url('lang', ['locale' => 'ko'])}}" role="menuitem">
+								<span class="flag-icon flag-icon-kr"></span>
+								한국어</a>
+						</div>
 					</div>
 				</div>
-			</div>
-			<div class="panel-body">
-				@yield('content')
+				<div class="panel-body">
+					@yield('content')
+				</div>
 			</div>
 		</div>
+		@yield('modal')
 	</div>
 </div>
 <!-- 核心/Core -->
@@ -112,9 +113,7 @@
 <script src="/assets/global/vendor/asscrollbar/jquery-asScrollbar.min.js" type="text/javascript"></script>
 <script src="/assets/global/vendor/asscrollable/jquery-asScrollable.min.js" type="text/javascript"></script>
 <script src="/assets/global/vendor/ashoverscroll/jquery-asHoverScroll.min.js" type="text/javascript"></script>
-
 <!-- 插件/Plugins -->
-<script src="/assets/global/vendor/intro-js/intro.min.js" type="text/javascript"></script>
 <script src="/assets/global/vendor/screenfull/screenfull.js" type="text/javascript"></script>
 <script src="/assets/global/vendor/slidepanel/jquery-slidePanel.min.js" type="text/javascript"></script>
 <script src="/assets/global/vendor/jquery-placeholder/jquery.placeholder.js" type="text/javascript"></script>
@@ -152,11 +151,6 @@
             Site.run();
         });
     })(document, window, jQuery);
-
-    // 登录
-    function login() {
-        window.location.href = '/login';
-    }
 </script>
 </body>
 </html>

+ 5 - 21
resources/views/auth/login.blade.php

@@ -1,21 +1,5 @@
 @extends('auth.layouts')
 @section('title', trans('auth.login'))
-@section('css')
-	<style type="text/css">
-		@media screen and (max-height: 575px) {
-			.g-recaptcha {
-				-webkit-transform: scale(0.81);
-				transform: scale(0.81);
-				-webkit-transform-origin: 0 0;
-				transform-origin: 0 0;
-			}
-		}
-
-		.geetest_holder.geetest_wind {
-			min-width: 245px !important;
-		}
-	</style>
-@endsection
 @section('content')
 	<form action="/login" method="post" id="login-form">
 		@if($errors->any())
@@ -36,9 +20,9 @@
 			<label class="floating-label" for="username">{{trans('auth.username')}}</label>
 		</div>
 		<div class="form-group form-material floating" data-plugin="formMaterial">
-			<input type="password" class="form-control" name="password" value="{{Request::old('password')}}" required/>
+			<input type="password" class="form-control" name="password" value="{{Request::old('password')}}" autocomplete required/>
 			<label class="floating-label" for="password">{{trans('auth.password')}}</label>
-			<input type="hidden" name="_token" value="{{csrf_token()}}"/>
+			{{csrf_field()}}
 		</div>
 		@switch(\App\Components\Helpers::systemConfig()['is_captcha'])
 			@case(1)<!-- Default Captcha -->
@@ -67,12 +51,12 @@
 				<input type="checkbox" id="inputCheckbox" name="remember">
 				<label for="inputCheckbox" for="remember">{{trans('auth.remember')}}</label>
 			</div>
-			<a class="float-right" href="/resetPassword">{{trans('auth.forget_password')}}</a>
+			<a href="/resetPassword" class="btn btn-xs bg-red-500 text-white float-right">{{trans('auth.forget_password')}}</a>
 		</div>
-		<button type="submit" class="btn btn-primary btn-block btn-lg mt-40">{{trans('auth.login')}}</button>
+		<button type="submit" class="btn btn-lg btn-block mt-40 bg-indigo-500 text-white">{{trans('auth.login')}}</button>
 	</form>
 	@if(\App\Components\Helpers::systemConfig()['is_register'])
-		<p>{{trans('auth.register_tip')}} <a href="/register">{{trans('auth.register')}}</a></p>
+		<p>{{trans('auth.register_tip')}} <a href="/register" class="btn btn-xs bg-purple-500 text-white">{{trans('auth.register')}} <i class="icon wb-arrow-right" aria-hidden="true"></i></a></p>
 	@endif
 @endsection
 @section('script')

+ 300 - 53
resources/views/auth/register.blade.php

@@ -1,24 +1,14 @@
 @extends('auth.layouts')
 @section('title', trans('auth.register'))
 @section('css')
+	<link href="/assets/global/vendor/bootstrap-select/bootstrap-select.min.css" type="text/css" rel="stylesheet">
 	<link href="/assets/custom/Plugin/sweetalert2/sweetalert2.min.css" type="text/css" rel="stylesheet">
-	<style type="text/css">
-		@media screen and (max-height: 575px) {
-			.g-recaptcha {
-				-webkit-transform: scale(0.81);
-				transform: scale(0.81);
-				-webkit-transform-origin: 0 0;
-				transform-origin: 0 0;
-			}
-		}
-
-		.geetest_holder.geetest_wind {
-			min-width: 245px !important;
-		}
-	</style>
 @endsection
 @section('content')
 	<form action="/register" method="post" id="register-form">
+		{{csrf_field()}}
+		<input type="hidden" name="register_token" value="{{Session::get('register_token')}}"/>
+		<input type="hidden" name="aff" value="{{Session::get('register_aff')}}"/>
 		@if(\App\Components\Helpers::systemConfig()['is_register'])
 			@if($errors->any())
 				<div class="alert alert-danger">
@@ -26,11 +16,26 @@
 				</div>
 			@endif
 			<div class="form-group form-material floating" data-plugin="formMaterial">
-				<input type="email" class="form-control" autocomplete="off" name="username" value="{{Request::old('username')}}" id="username" required/>
-				<label class="floating-label" for="username">{{trans('auth.username')}}</label>
-				<input type="hidden" name="register_token" value="{{Session::get('register_token')}}"/>
-				<input type="hidden" name="_token" value="{{csrf_token()}}"/>
-				<input type="hidden" name="aff" value="{{Session::get('register_aff')}}"/>
+				@if(\App\Components\Helpers::systemConfig()['sensitiveType'])
+					<input type="email" class="form-control" autocomplete="off" name="username" value="{{Request::old('username')}}" id="username" required/>
+					<label class="floating-label" for="username">{{trans('auth.username')}}</label>
+				@else
+					<div class="input-group">
+						<input type="text" class="form-control" autocomplete="off" name="emailHead" value="{{Request::old('emailHead')}}" id="emailHead" required/>
+						<label class="floating-label" for="emailHead">{{trans('auth.username')}}</label>
+						<div class="input-group-prepend">
+							<span class="input-group-text bg-indigo-600 text-white">@</span>
+						</div>
+						<select class="form-control" name="emailTail" id="emailTail" data-plugin="selectpicker" data-style="btn-outline-primary">
+							@if(!$emailList->isEmpty())
+								@foreach($emailList as $email)
+									<option value="{{$email->words}}">{{$email->words}}</option>
+								@endforeach
+							@endif
+						</select>
+						<input type="text" name="username" id="username" hidden/>
+					</div>
+				@endif
 			</div>
 			@if(\App\Components\Helpers::systemConfig()['is_verify_register'])
 				<div class="form-group form-material floating" data-plugin="formMaterial">
@@ -55,7 +60,7 @@
 			</div>
 			@if(\App\Components\Helpers::systemConfig()['is_invite_register'])
 				<div class="form-group form-material floating" data-plugin="formMaterial">
-					<input type="password" class="form-control" name="code" value="{{Request::old('code') ? Request::old('code') : Request::get('code')}}" @if(\App\Components\Helpers::systemConfig()['is_invite_register'] == 2) required @endif/>
+					<input type="password" class="form-control" name="code" value="{{Request::old('code') ? : Request::get('code')}}" @if(\App\Components\Helpers::systemConfig()['is_invite_register'] == 2) required @endif/>
 					<label class="floating-label" for="code">{{trans('auth.code')}}</label>
 				</div>
 				@if(\App\Components\Helpers::systemConfig()['is_free_code'])
@@ -66,42 +71,36 @@
 			@endif
 			@if(!\App\Components\Helpers::systemConfig()['is_verify_register'])
 				@switch(\App\Components\Helpers::systemConfig()['is_captcha'])
-					@case(2)
-				<!-- Geetest -->
+					@case(1)<!-- Default Captcha -->
 					<div class="form-group form-material floating input-group" data-plugin="formMaterial">
+						<input type="text" class="form-control" name="captcha" value="" required/>
+						<label class="floating-label" for="captcha">{{trans('auth.captcha')}}</label>
+						<img src="{{captcha_src()}}" class="float-right" onclick="this.src='/captcha/default?'+Math.random()" alt="{{trans('auth.captcha')}}"/>
+					</div>
+					@break
+					@case(2)<!-- Geetest -->
+					<div class="form-group form-material floating" data-plugin="formMaterial">
 						{!! Geetest::render() !!}
 					</div>
 					@break
-					@case(3)
-				<!-- Google noCAPTCHA -->
-					<div class="form-group form-material floating input-group" data-plugin="formMaterialis_verify_register">
+					@case(3)<!-- Google noCAPTCHA -->
+					<div class="form-group form-material floating" data-plugin="formMaterial">
 						{!! NoCaptcha::display() !!}
 						{!! NoCaptcha::renderJs(session::get('locale')) !!}
 					</div>
 					@break
-					@case(1)
-				<!-- Default Captcha -->
-					<div class="form-group form-material floating input-group" data-plugin="formMaterial">
-						<input type="text" class="form-control" name="captcha" value="" required/>
-						<label class="floating-label" for="captcha">{{trans('auth.captcha')}}</label>
-						<img src="{{captcha_src()}}" onclick="this.src='/captcha/default?'+Math.random()" alt="{{trans('auth.captcha')}}" style="float:right;"/>
-					</div>
-					@break
 					@default
 				@endswitch
 			@endif
 			<div class="form-group mt-20 mb-20">
-				<label class="mt-checkbox mt-checkbox-outline">
-					<input type="checkbox" name="tnc" checked="checked"/>
-					{{trans('auth.accept_term')}}
-					<a class="ml-0" href="https://docs.hentaiworld.cc/rule/tos">
-						{{trans('auth.tos')}}
-					</a>&
-					<a class="ml-0" href="https://docs.hentaiworld.cc/rule/aup">
-						{{trans('auth.aup')}}
-					</a>
-					<span></span>
-				</label>
+				<div class="checkbox-custom checkbox-primary">
+					<input type="checkbox" name="term" id="term" {{Request::old('term') ? 'checked':''}} />
+					<label for="term">{{trans('auth.accept_term')}}
+						<button class="btn btn-xs btn-primary" data-target="#tos" data-toggle="modal" type="button">{{trans('auth.tos')}}</button>
+						&
+						<button class="btn btn-xs btn-primary" data-target="#aup" data-toggle="modal" type="button">{{trans('auth.aup')}}</button>
+					</label>
+				</div>
 			</div>
 		@else
 			<div class="alert alert-danger">
@@ -110,25 +109,273 @@
                 </span>
 			</div>
 		@endif
-		<div class="form-actions">
-			<button class="btn btn-danger btn-lg float-left" onclick="login()">{{trans('auth.back')}}</button>
-			@if(\App\Components\Helpers::systemConfig()['is_register'])
-				<button type="submit" class="btn btn-primary btn-lg float-right">{{trans('auth.submit')}}</button>
-			@endif
-		</div>
+		<a href="/login" class="btn btn-danger btn-lg {{\App\Components\Helpers::systemConfig()['is_register']? 'float-left': 'btn-block'}}">{{trans('auth.back')}}</a>
+		@if(\App\Components\Helpers::systemConfig()['is_register'])
+			<button type="submit" class="btn btn-primary btn-lg float-right">{{trans('auth.register')}}</button>
+		@endif
 	</form>
+@endsection
+@section('modal')
+	<div class="modal fade modal-info text-left" id="tos" aria-hidden="true" aria-labelledby="tos" role="dialog" tabindex="-1">
+		<div class="modal-dialog modal-simple modal-sidebar modal-lg">
+			<div class="modal-content">
+				<div class="modal-header">
+					<button type="button" class="close mr-15" data-dismiss="modal" aria-label="Close" style="position:absolute;">
+						<span aria-hidden="true">×</span>
+					</button>
+					<h4 class="modal-title">{{\App\Components\Helpers::systemConfig()['website_name']}} - {{trans('auth.tos')}} <small>2019年11月28日10:49</small></h4>
+				</div>
+				<div class="modal-body">
+					<h2>当事双方及术语介绍</h2>
+					本协议所提及的当事人的定义如下:
+					<ol>
+						<li>就本协议中,提及的{{\App\Components\Helpers::systemConfig()['website_name']}}相关网站或数据传输服务,均简称为“本站”或“服务”。 当第一人称代词(我们等)在以下协议中使用,均指{{\App\Components\Helpers::systemConfig()['website_name']}}。
+						<li>您,本站客户 - 作为我们的客户或网站服务的使用者, 本协议可能使用任意第二人称代替。</li>
+					</ol>
+
+					请认真阅读下面的服务条款和条件。通过购买或注册本站服务,即表示您同意遵守本协议的所有条款和条件(协议)。如果同意本协议的条款和条件,请将选择框勾上,即表示你接受这些条款和条件。您可以通过打印或以其他方式保存本协议,作为未来可引用的副本。如果您不同意此服务和条款,请勿购买以及使用本站的任意产品和服务,并点击浏览器“返回”按钮,或关闭本网站。{{\App\Components\Helpers::systemConfig()['website_name']}}仅在您同意此服务条款后,为您提供服务。此协议是在全球和国内的商业法允许下签署。任何使用{{\App\Components\Helpers::systemConfig()['website_name']}}提供的服务的行为,都认为您知晓并同意以下服务条款。
+					<h2>使用条款</h2>
+					尽管此协议代表主要的使用条款,其他准则和规则在此通过引用并入本文。这些文件可以在我们网站上找到,其中包含:
+					<h3>一丶服务</h3>
+					<ol>
+						<li>在您选购本站的服务之前,您可以看到一系列罗列出的套餐。您可以从罗列的服务中选择所需套餐。所有您选择的服务,均适用此条款。 在您订购服务后,我们认为您接受此使用条款,本站会在购买后自动开启服务。本站保留以任何原因拒绝为您提供任何服务的权利。本站也有权在紧急状况中断接入服务进行定期维护需要。您可以随时订购额外的服务。所有的额外服务在下文被视为“服务”。所提供的所有服务都视情况而定,并适用于本协议的所有条款和条件。</li>
+						<li>本站服务只限定购买者本人使用以及其家庭成员之间共享使用,除此之外禁止以任何形式分享使用。为了避免本站账户泄漏或者用户主动分享,本站有权在用户不知情情况下对违规账号进行删除或者封禁处理。</li>
+					</ol>
+					<h3>二丶用户协议修订</h3>
+					本协议包含完整的条款和条件适用于您使用本站服务(定义如下)。本站可以在任何时间修改本协议的条款和费用(定义见下文)。
+					<ol>
+						<li>本站可能随时修改本协议,您同意本站保留修改本协议的权利。您同意我们有单方面这样做的权利。更新的版本将在发布后立即取代任何以往的版本,之前的版本是不再具备任何法律效力,除非修订版和之前版本一致。本协议的任何第三方修改版本均被视为无效。</li>
+						<li>本站同意,如果我们协议有任何改变,我们将在本协议的顶部更改“最后修改日期”。您同意定期重新访问该网页。您同意注意最后修订本协议的日期。如果“上次修改”日期仍从你最后一次查看本协议不变,那么你可以假定该协定已自上次你查看时它已经改变了。如果“上次修改”日期已经改变,那么你可以肯定协议中有关条款已被更改。</li>
+						<li>如果由于本站所做的任何修改,您需要终止本协议,必须于上述的“最后修改”日起三十(30)日内通过工单申请或者邮箱申请(<a href="mailto:{{\App\Components\Helpers::systemConfig()['webmaster_email']}}">{{\App\Components\Helpers::systemConfig()['webmaster_email']}}</a>)取消。在任何此类通知的生效日期后继续使用服务,即表示您接受这些修改。</li>
+						<li>弃权 – 如果您没有定期查看此协议, 您自行承担忽略此协定更改的责任。您拥有随时查看此修订版本的权利。由于您自己忽略查看的原因,本站不负任何责任。</li>
+					</ol>
+					<h3>三丶协议和取消政策期限</h3>
+					<ol>
+						<li>初始期限开始于确认你的订单或服务,并收到合法的资金的时间。这个期限的长度是由您选择的,并且在您订购本站服务时应注明。本协议不得终止您的初始期间,除非本站违约。</li>
+						<li>本站也可以在任何时间以任何理由或无理由终止本协议 (“无故终止”)。在这种情况下,本站会为您提供工单通知。</li>
+						<li>如果本站根据本协议任何条款概述取消本协议,没有根据本协议第3.2条款终止的原因外,本站不会给予退款。若您需要终止服务,您有义务在预付费服务生效前取消订阅。在由本站发起的终止情况,所有预付托管费将被没收,概不退还。本协议的终止并不解除支付任何费用。</li>
+						<li>
+							除此之外,本站拥有终止此协议中任意部分的权利。当以下情况发生,本站可以终止你的服务:
+							<ol type="a">
+								<li>违反了可接受使用条款(“AUP”)中的任意条款,</li>
+								<li>侵犯或违反任何第三方的知识产权或隐私权或版权,</li>
+								<li>不遵守任何适用的法律、法规或条例,或</li>
+								<li>已经上传,发布或传播任何本站认为违法或高风险的图像、文本、图形、编码或视频,在其自由裁量权。本协议中的任何内容的目的是,本站不负有任何责任或义务来监视或审查您的内容,或在任何时候你的用户上传或发布的内容。你仍然对你的内容负责,以及对由此产生的任何责任负责。</li>
+							</ol>
+						</li>
+						<li>本协议的终止将终止你访问你的服务和您的许可的托管材料(本协议5.2节所定义)。本站不需要您或任何第三方的允许即可终止你的服务。本协议终止时,本站有权维护备份您的数据文件和记录的副本,但不承担任何义务为您备份。本站保留在所有服务结算周期的最后一天之前实行提前终止的权利。</li>
+						<li>如果任何一方以任何原因取消或终止本协议,您将全权负责所有必需的安排。</li>
+					</ol>
+					<h3>四丶账户设置</h3>
+					<ol>
+						<li>注册账户时,您将被要求填写登录账户(电子邮件)和密码。您可以并只可以通过这样的用户标识和密码使用该服务或修改您的数据和内容。您完全负责维护您的用户名和密码的保密性和使用这些凭据的所有活动的机密性。您同意立即通知我们当任何未经授权的访问使用您的帐户或任何其他违反安全的情况。
+						</li>
+						<li>您必须为我们提供一个主要的电子邮件地址,定期检查。所有通知和我们之间的通信将被发送到您提供的电子邮件地址,因此,您需要保持这个地址畅通,如果您的地址更改,请通知我们。如果您的联系和/或帐单信息发生变化,您应该通知我们,以便我们可以更新您的帐户。它确保我们的域名不包括在由你或你的邮件提供商使用任何垃圾邮件阻止列表之内。</li>
+						<li>提供任何种类的错误或不准确的联系信息,依据本协议3中相关条款,可能会导致你的帐户被终止。</li>
+					</ol>
+					<h3>五丶知识产权</h3>
+					本站提供的所有服务仅允许用于合法目的。
+					<ol>
+						<li>在你和本站之间,本站承声明它不拥有你提供的使用在你的网站的所有权或内容(包括但不限于文字、软件、音乐、声音、视听作品、电影、图片、动画、视频和图形)(你的内容)。您特此授予本站使用你的内容,通过互联网广播传输非独家的、世界范围的、免版税许可、复制、制作衍生作品、展示、表演。</li>
+						<li>本站可以(但不是必须)为你提供一定的材料,包括但不限于计算机软件(目标代码或源代码形式)、数据文件或信息开发、本站或其供应商提供本协议项下的域名、电子邮件地址、分配给你的其他网络地址和其他专有技术、方法、设备和工艺,采用本站为您提供服务(“主材料”)。根据本协议的条款和条件,本站授予您与服务连接单独使用的主体材料有限的、可撤销、不可转让的、非排他性的许可。本协议终止时,该许可证终止。您承认并同意,本站拥有一切权利,所有权和利益,或以其他方式取得的主体材料的所有适用的许可证、所有的著作权、商业秘密、专利、商标和其他知识产权的权利。任何在本协议终止后的主机材料未经许可,严禁使用。您同意没有获得书面许可不会上传、传输、复制、分发或以任何方式利用任何主机材料。</li>
+						<li>本协议不构成许可使用本站服务标志或任何其他贸易徽章。没有本站事先书面同意的使用任意绅士本站服务标志或任何其他贸易标志是严格禁止的。</li>
+						<li>你知道,即使是名义的损害,也可能需要大量的法律费用,旅行费用,成本和其他金额。你同意你将支付所有这些费用和费用</li>
+					</ol>
+					<h3>六丶内容及可接受使用政策</h3>
+					<ol>
+						<li>您同意遵守本站的使用政策(AUP,即“ 可接受使用策略”),它可以通过访问的本页同目录下找到。其中部分并入本文作为参考并作为本文不可或缺的一部分。本站在网站上张贴修改后的政策,并保留在任何时间修改可接受使用策略的权力。您同意定期访问本站网站并查看最新的可接受使用策略,在任何可接受使用策略更改日志后继续使用本站服务,则代表您接受新的可接受使用策略并受到它的约束。如果最终用户的行为违反服务条款或者可接受使用策略,本站将有权在任何时间中止您对服务的访问。</li>
+						<li>本站不会主动侦测最终用户在本站服务上所使用的内容,虽然本站可以自行决定,以技术手段监测客户在本站网络上所使用的服务,并在法律、法规或政府组织要求的情况下透露您账户的任何必要信息。本站将调查侵犯第三方权利或违反可接受使用策略的投诉。本站将试图减少对本站服务的滥用。本站将有权与执法机关合作,并保留通知该机关的权力,如果执法机关怀疑您和您的最终用户进行违反的您和服务器所在地区法律、法规和相关政策的活动。本节包含的所有条款,是为了授予第三方权利,但没有第三方有权强制执行本协议的任何条款。</li>
+						<li>您必须同意本站将不承担您和您的最终用户任何违反可接受使用策略和您和服务器所在地区法律、法规和相关政策的行为,这包括数字千年版权法。</li>
+						<li>本站可自行决定终止您对服务的访问,并终止本协议。这是因为您或您的最终用户、下游客户违反了服务条款和可接受使用策略。</li>
+						<li>本站对于儿童色情问题非常重视,未成年人使用我们的服务存在潜在的危害,这应当是完全禁止的,然而,其监护人可以授权未成年人有限制地使用本站的服务。任何可能被认为是儿童色情的内容都将被删除并禁止访问,这适用于本站的云主机和云加速服务。任何通过本站访问儿童色情的客户都将被立即删除服务并通知当地执法机关。您同意和本站合作阻止儿童色情内容的的访问,任何儿童色情内容,或招揽、引诱或诱使未成年人的性活动或者猥亵行为也是严格禁止的,并将被视为同儿童色情相同问题。本站有权对在使用本站服务访问儿童色情内容的客户提起诉讼。</li>
+						<li>如果您怀疑本站网络被托管了儿童色情内容,我们鼓励您立即向本站的滥用投诉邮箱 <a href="mailto:{{\App\Components\Helpers::systemConfig()['webmaster_email']}}">{{\App\Components\Helpers::systemConfig()['webmaster_email']}}</a> )或者通过客户中心的工单系统向滥用投诉部门投诉,并包括客户的文件名或URL(或其他位置点)、受害者(如果知道的话)、出生日期、生产日期以及有关可疑图像(多个)和其他任何信息。或者,您可以使用CyberTipline报告可疑的儿童色情制品,涉及不由本站托管的儿童色情内容应该直接向执法部门或者该网站投诉:<a href="https://www.asacp.org/index.php?content=report" target="_blank">https://www.asacp.org/index.php?content=report</a>。</li>
+						<li>我们尊重各方的知识产权,并已通过了关于基于数字千年版权法案重复版权侵权者终止政策。我们的重复侵权终止政策的副本可应要求提供给我们的客户。</li>
+						<li>您同意您有责任防止您照顾的未成年人从您购买的本站服务直接或间接访问任何有害或不当的内容。您同意不允许未成年人访问任何服务,并采取相关的限制措施,以防止他们这样做。许多商业在线安全过滤器可这可以帮助用户限制未成年人有害的或不适当的访问请注意,本网站不作任何陈述或有关的任何产品或在这些网站上引用的服务的保证,推荐用户购买或安装任何在线过滤器前进行适当的尽职调查。您同意采取特别措施,防止未成年人浏览本网站如果您的计算机可以由未成年人进行访问。最后,您同意,如果你是父母或未成年子女的监护人,您有责任阻止未成年人通过本站服务访问任何不当内容,这是你的责任,不是我们的。</li>
+					</ol>
+					<h3>七丶垃圾邮件零容忍政策</h3>
+					<ol>
+						<li>对于任何垃圾邮件在本站网络上的使用是严格禁止的,如果您和您的最终用户在本站网络上使用SPAM,我们有权随时终止您的服务。</li>
+						<li>本站在网站上张贴修改后的政策,并保留在任何时间修改反垃圾邮件政策的权力。您同意定期访问本站网站并查看最新的反垃圾邮件政策,在任何反垃圾邮件政策更改日志后继续使用本站服务,则代表您接受新的反垃圾邮件政策并受到它的约束。如果最终用户的行为违反服务条款或者反垃圾邮件政策,本站将有权在任何时间中止您对服务的访问。</li>
+					</ol>
+					<h3>八丶支付及退款</h3>
+					<p>您同意支付任何由于使用本服务而造成的税款,包括个人所得税、增值税或销售税。本站不负责由于您使用本服务并使用银行支票、信用卡、资金不足以及任何您与您的金融机构产生的任何费用。本站应该得到全额付款,如果由于税收、汇率差异、银行收费、转账收费等产生额外费用,您需要自行支付。</p>
+					<p>一旦本站开始提供服务,我们就将不再受理任何退款请求,除非这是因为本站产品和服务存在广泛的,通用的并可被复现的质量问题或是在您没有出现违规使用行为的前提下,本站主动终止了您的服务。否则任何退款请求都将是不被接受的。您需要了解并同意,即使您请求取消了已购买的服务或产品,但是本站已经消耗了基础的成本并承担了风险,因此我们不会退还任何费用。</p>
+					<h3>九丶资源使用&安全</h3>
+					<p>本站没有对每个账户可使用的系统资源及硬件设限。我们不主动地停用用户帐户,除非它们大大超过可接受的使用水平,或者维持该客户的使用会严重影响其他客户的体验等。</p>
+					<p>除非法律明确允许,不得反向工程,反编译,反汇编本网站和/或材料的衍生作品。您同意不使用任何自动设备或手动过程监控或复制本网站或材料,不会使用任何设备,软件,计算机代码或病毒干扰或企图干扰或破坏我们的服务和网站。</p>
+					<p>安全 - 任何违反网站和/或服务的安全都是被禁止的,并可能导致刑事和民事责任。您同意不以此类活动违反或企图改变或操纵硬件和软件,危及服务器,或任何其他未经授权的使用。您被禁止从事:</p>
+					<ol>
+						<li>任何形式的未经授权的访问或使用数据,系统或网络,包括网站和/或服务。</li>
+						<li>对任何用户的服务,主机或网络进行未经授权的干扰。</li>
+						<li>将恶意程序引入网络或服务器(例如病毒和蠕虫),包括网站和/或服务。</li>
+						<li>规避任何主机,网络或账户的用户和安全认证。</li>
+						<li>利用我们的服务危及安全或其它网站。</li>
+					</ol>
+					<p>在您参与任何违反系统安全的情况下,我们有权为其他网站的系统管理员发布关于您的信息,以协助解决安全事件,我们也将与任何执法机构调查犯罪及违反系统或网络的安全性。此外,这些安全规定的违反可能导致您的帐户被禁用。</p>
+					<p>流量使用 - 您每月的数据传输量是由您购买特定的服务或订阅来决定。如果您的使用超过您的每月限额,您的服务可能被暂停,并根据不同的产品或服务在下个月月初或您的账单日恢复。未使用的流量不结转到下个月的流量。</p>
+					<p>公平使用政策 - 我们提供特定的服务或订阅给我们的客户,我们期望用户按照描述来使用每一项服务,这是指整个任何给定的计费周期来定义正常,公平,合理的使用。当我们判断某一个用户不合理使用服务或订阅,我们可能会采取行动,以减轻负面影响,这些手段包括但不限于连接限制和访问限制。不公平的使用包括但不限于以下内容:</p>
+					<h4>违规行为定义</h4>
+					<ol>
+						<li>
+							一般违规行为定义
+							<ol>
+								<li>在网络节点上进行违反该节点所在国家或地区相关法律法规的行为。</li>
+								<li>进行P2P下载,包括但不限于BT、PT、迅雷等。</li>
+								<li>长时间占用超过合理范围内的资源以至于影响其他用户的使用行为。(占用带宽50M以上,连续占用时间超过1个小时)</li>
+								<li>在游戏专用节点上进行大带宽使用行为,包括但不限于在线视频、文件上传下载、非游戏相关文件传输等。</li>
+							</ol>
+
+						</li>
+						<li>
+							严重违规行为定义
+							<ol>
+								<li>转借、泄露、二次销售账户或服务信息。</li>
+								<li>未提前告知的商业团队使用行为。</li>
+							</ol>
+						</li>
+					</ol>
+					<h4>处理办法</h4>
+					<ol>
+						<li>针对一般违规行为,首次触发,封禁账户7天,第二次触发,封禁账户至服务期结束,并拒绝后续一切服务请求。</li>
+						<li>针对严重违规行为,一旦触发,封禁账户至服务期结束,并拒绝后续一切服务请求。</li>
+					</ol>
+					<h3>十丶正常运行时间保障 </h3>
+					<p>本站尽力保证服务可用性。当遇到不可抗拒因素,软件故障、DDOS攻击等问题导致服务中断,本站会尽速恢复基础服务的运行,但不能保障完全恢复。您理解并同意,当您遇到可用性问题时,会通知本站进行处理。</p>
+					<h3>十一丶价格变化</h3>
+					<p>您支付的服务在一定时间内不会改变价格。我们保留在任何时候更改服务价格的权利,恕不另行通知,并保留修改提供给用户的资源数量及规模的权利。</p>
+					<h3>十二丶保障</h3>
+					<p>您同意维护,保障,并维护本站及其关联公司,免受任何及所有债权债务,包括合理的律师和专家费用,涉及到:</p>
+					<ol>
+						<li>违反您在本协议项下约定而产生的;</li>
+						<li>您使用服务而产生的;</li>
+						<li>所有的行为,并由您的用户名和密码发生的活动而产生的;</li>
+						<li>任何物品或服务的出售、与您的内容或您的信息和数据的广告;</li>
+						<li>包含您的内容或您的信息和数据中的任何诽谤,中伤或非法的材料;</li>
+						<li>任何索赔或论点,即您的内容或您的信息和数据侵犯任何第三方的专利,版权或其他知识产权或违反隐私或公开任何第三方的权利;</li>
+						<li>任何第三方的访问或使用您的内容或您的信息和数据;</li>
+						<li>违反任何适用的可接受使用政策;</li>
+					</ol>
+					<p>您保证并声明:</p>
+					<ol>
+						<li>您的内容与标题符合您所在国家的法律规定;</li>
+						<li>在您的内容中描述所有客户在18岁以上;</li>
+						<li>您的内容不包含构成儿童色情,淫秽,兽交,暴力的真实描述,或在中国不合法的任何图像。</li>
+					</ol>
+					<h3>十三丶 无额外保障</h3>
+					<p>您明确同意,您对服务的使用是您自行承担的风险。本站明确拒绝任何形式明示或默示的保修,包括所有的担保,包括但不限于适销性的隐含担保特定用途,所有权和非侵权。本站不保证该项服务会满足您的需求,或者说,这些服务将不中断,安全或无错误。有关宣传材料及发表任何言论都应被视为广告引用,并且不保证。您理解并同意,任何使用您的任何服务和/或数据下载或通过服务所获得的使用由您自行决定,风险自负,而您将是单方承担损害您的计算机系统或损失数据的结果和风险。</p>
+					<p>本站可能会提供不属于服务(“第三方服务或软件”)的一部分,第三方产品,服务和/或软件提供给您。本站无法控制第三方服务或软件的内容。任何第三方服务或软件的使用,您将个人独自承担风险并受您与第三方达成的单独协议的条款和条件的限制。</p>
+					<p>本站不提供有关任何产品和服务的保修。</p>
+				</div>
+				<div class="modal-footer">
+					<button type="button" class="btn btn-block bg-red-500 text-white mb-25" data-dismiss="modal">{{trans('auth.close')}}</button>
+				</div>
+			</div>
+		</div>
+	</div>
+	<div class="modal fade modal-info text-left" id="aup" aria-hidden="true" aria-labelledby="aup" role="dialog" tabindex="-1">
+		<div class="modal-dialog modal-simple modal-sidebar modal-lg">
+			<div class="modal-content">
+				<div class="modal-header">
+					<button type="button" class="close mr-15" data-dismiss="modal" aria-label="Close" style="position:absolute;">
+						<span aria-hidden="true">×</span>
+					</button>
+					<h4 class="modal-title">{{\App\Components\Helpers::systemConfig()['website_name']}} - {{trans('auth.aup')}}  <small>2019年11月28日10:49</small></h4>
+				</div>
+				<div class="modal-body">
+					<p class="mt-15">以下是本站的可接受使用策略(AUP)。在使用本站的服务之前,您必须同意此协议,您也同意要求您的最终用户遵守此协议。本站保留随时修改本协议的权力。您同意您将定期访问本页面查看最新协议,您继续使用本站服务代表您继续同意本协议。</p>
+					<p>根据您的服务发布协议,本站可自行决定终止您对服务的访问,如果您的行为违反了(或疑似违反了)本协议,或者您的最终用户违反了(或疑似违反了)本协议。</p>
+					<h3>禁止非法用途和违禁用途</h3>
+					作为使用服务的条款之一,您不能使用本服务用于任何非法用途,否则您将不能使用本服务。您不得使用任何有可能损害、禁用、过载或以其他方式损害本站的服务。您不得以任何方式尝试获取服务并未提供的任何信息。
+					<h3>服务使用</h3>
+					该服务旨在使您和您的最终用户通过互联网与他人沟通,您同意使用的服务(并要求用户使用到的服务),才发布、发送和接受信息。在适用时,您同意正确使用服务(而不是作为一个限制),举例来说,您和您的最终用户不会做出以下行为:
+					<ol>
+						<li>使用服务连接非法竞赛、赌博、非法彩票、发送垃圾邮件或任何重复并未经请求的信息。</li>
+						<li>诽谤,辱骂,骚扰,跟踪,威胁或以其他方式侵犯他人合法权利(如隐私权和公开权)。</li>
+						<li>出版,发布,上传,分发,运输或传播任何诽谤,猥亵或其他非法内容,如儿童色情或虚拟儿童色情制品。</li>
+						<li>发表,张贴,上传,分发或散布煽动歧视,仇恨或暴力对待一个人或因其属于种族,宗教或民族中的任何的主题,名称,材料或信息。</li>
+						<li>上传,或者以可用文件的方式以其他方式包含图像,照片,软件或其他材料受知识产权法保护(包括而不限于),而未进行限制,违反版权或商标法(或隐私或公开权),除非你拥有版权或已得到所有必要的许可这样做。</li>
+						<li>使用侵犯任何版权,商标,专利,商业秘密或任何一方的其他所有权的任何材料或信息,包括图片或照片的方式通过提供服务。</li>
+						<li>上传含有病毒,木马,蠕虫,定时恶意程序,以删除,损坏文件为目的,或任何其他类似的软件或程序,可能损害他人财产的文件。</li>
+						<li>下载、发布任何你知道或者理应知道不能被合法传播的文件。</li>
+						<li>伪造或删除任何作者归属,法律或其他适当声明,专有名称或包含在上传文件的软件或其他资料的原产地或来源标签。</li>
+						<li>超出限制以至影响其他用户享受服务的行为。</li>
+						<li>违反条款或可能适用于任何特定服务的其他准则中的任何内容。</li>
+						<li>收集或以其他方式收集他人,包括电子邮件地址的信息,除非这是运行你的网站必须的且你的网站的隐私政策允许的(如果有的话)。</li>
+						<li>违反任何适用的法律或法规。</li>
+						<li>创建误导他人为目的的假身份。</li>
+						<li>创建、运营一个TOR节点。</li>
+						<li>扫描、嗅探其他网络主机的端口,除非这是受到对方书面允许的,其他任何理由均为不允许的。</li>
+					</ol>
+					<p>本站保留在任何时候透露任何信息,当这些信息被法律、法规和政府要求时,或是编辑、删除、拒绝发布任何信息或资料。全部或部分这样做由本站自行决定。</p>
+					<p>本站不控制或认可服务中发现的任何内容、消息或信息。因此,本站明确拒绝承担任何责任,并不服务您参与产生的任何行为和问题。</p>
+					<p>当您的服务消耗了过多资源时,如大流量下载、采矿、PT/BT,本站有权随时限制提供给您的资源,以保证该节点其他用户的正常使用。</p>
+					<h3>终止/限制访问</h3>
+					<p>本站没有义务监督服务,然而,本站保留审查发布于本站的任何服务和材料,并有自行决定是否删除服务和内容的权力。本站保留权利自行决定在何时终止其所有或部分服务和相关服务,或限制其访问权限,并没有义务通知您,对于违反本协议的用于,一旦服务终止,本站没有任何义务进行后续维护。</p>
+					<h3>禁止SPAM</h3>
+					<p>本站将会立即终止任何被认为发送垃圾邮件或者大量未经请求的邮件的服务,并且没有任何义务进行恢复。</p>
+					<h3>注意涉及侵权</h3>
+					<p>本站尊重知识产权并要求我们的客户做到相同的责任,如果您认为您的知识产权被侵犯,或者我们认为您的内容侵犯了他人的知识产权,请向本站提供以下资料:
+						获得代表版权授权或其他知识产权利益所有者的个人的电子签名或亲笔签名;</p>
+					<ol>
+						<li>版权作品,或者你声称受到侵犯其他知识产权的描述;</li>
+						<li>描述您声称侵权服务的材料;</li>
+						<li>您的地址,电话号码和电子邮件地址;</li>
+						<li>通过你的陈述,您有充分理由相信该有争议内容未经著作所有人或者代理人授权或法律授权的内容;</li>
+						<li>一份声明,能够证明您上述信息是正确的,您是版权或者知识产权、著作的所有者、代理人、法定代表或者被授权者的信息。</li>
+					</ol>
+					您可以发送侵权通知到:<br>
+					<a href="mailto:{{\App\Components\Helpers::systemConfig()['webmaster_email']}}">{{\App\Components\Helpers::systemConfig()['webmaster_email']}}</a>
+					请不要通过代理发送信息或者发送其他任何信息。
+					<h3>通知和移除程序</h3>
+					<p>本站保留在任何时候删除被认为侵权或者收到侵权声明的服务和内容。本站保留随时有权禁止访问或者删除内容的方式阻止被侵权内容访问或任何声称是基于事实的侵权内容。</p>
+
+				</div>
+				<div class="modal-footer">
+					<button type="button" class="btn btn-block bg-red-500 text-white mb-25" data-dismiss="modal">{{trans('auth.close')}}</button>
+				</div>
+			</div>
+		</div>
+	</div>
 	@endsection
 @section('script')
 	<!--[if lt IE 11]>
 	<script src="/assets/custom/Plugin/sweetalert2/polyfill.min.js" type="text/javascript"></script>
 	<![endif]-->
 	<script src="/assets/custom/Plugin/sweetalert2/sweetalert2.min.js" type="text/javascript"></script>
+	<script src="/assets/global/vendor/bootstrap-select/bootstrap-select.min.js" type="text/javascript"></script>
+	<script src="/assets/global/js/Plugin/bootstrap-select.js" type="text/javascript"></script>
 	<script type="text/javascript">
+		@if(!\App\Components\Helpers::systemConfig()['sensitiveType'])
+        function getUsername() {
+            let username = $("#emailHead").val();
+            const emailTail = $("#emailTail").val();
+            if (username.trim() === '') {
+                swal.fire({title: '{{trans('auth.username_null')}}', type: 'warning', timer: 1500});
+                return false;
+            }
+            username = username.trim() + '@' + emailTail;
+            $("#username").val(username);
+        }
+
+        $('#register-form').submit(function () {
+            getUsername();
+            // 先检查Google reCAPTCHA有没有进行验证
+            if ($('#g-recaptcha-response').val() === '') {
+                Msg(false, "{{trans('login.required_captcha')}}", 'error');
+                return false;
+            }
+            return true; // return false to cancel form action
+        });
+
+		@endif
+
         // 发送注册验证码
         function sendVerifyCode() {
             let flag = true; // 请求成功与否标记
+			@if(!\App\Components\Helpers::systemConfig()['sensitiveType'])
+            getUsername();
+					@endif
             const username = $("#username").val();
-
             if (username.trim() === '') {
                 swal.fire({title: '{{trans('auth.username_null')}}', type: 'warning', timer: 1500});
                 return false;
@@ -146,13 +393,13 @@
                         $("#sendCode").attr('disabled', false);
                         flag = false;
                     } else {
-                        swal.fire('{{trans('auth.captcha_send')}}', '{{trans('auth.captcha_send')}}', 'error');
+                        swal.fire({title: '{{trans('auth.captcha_send')}}', type: 'error'});
                         $("#sendCode").attr('disabled', true);
                         flag = true;
                     }
                 },
                 error: function () {
-                    swal.fire('{{trans('auth.captcha_send')}}', '{{trans('auth.captcha_send')}}', 'error');
+                    swal.fire({title: '{{trans('auth.captcha_send')}}', type: 'error'});
                     flag = false;
                 }
             });

+ 5 - 7
resources/views/auth/reset.blade.php

@@ -23,18 +23,16 @@
 			<div class="form-group form-material floating" data-plugin="formMaterial">
 				<input class="form-control" type="password" autocomplete="off" name="password" value="" required/>
 				<label class="floating-label" for="password">{{trans('auth.new_password')}}</label>
-				<input type="hidden" name="_token" value="{{csrf_token()}}"/>
+				{{csrf_field()}}
 			</div>
 			<div class="form-group form-material floating" data-plugin="formMaterial">
 				<input class="form-control" type="password" autocomplete="off" name="repassword" value="" required/>
 				<label class="floating-label" for="repassword">{{trans('auth.retype_password')}}</label>
 			</div>
 		@endif
-		<div class="form-actions">
-			<button class="btn btn-danger btn-lg float-left" onclick="login()">{{trans('auth.back')}}</button>
-			@if ($verify->status == 0)
-				<button type="submit" class="btn btn-primary btn-lg float-right">{{trans('auth.submit')}}</button>
-			@endif
-		</div>
+		<a href="/login" class="btn btn-danger btn-lg {{$verify->status== 0? 'float-left': 'btn-block'}}">{{trans('auth.back')}}</a>
+		@if ($verify->status == 0)
+			<button type="submit" class="btn btn-primary btn-lg float-right">{{trans('auth.submit')}}</button>
+		@endif
 	</form>
 @endsection

+ 5 - 7
resources/views/auth/resetPassword.blade.php

@@ -19,18 +19,16 @@
 			<div class="form-group form-material floating" data-plugin="formMaterial">
 				<input type="email" class="form-control" name="username" value="{{Request::old('username')}}" required="required" autofocus="autofocus"/>
 				<label class="floating-label">{{trans('auth.username')}}</label>
-				<input type="hidden" name="_token" value="{{csrf_token()}}"/>
+				{{csrf_field()}}
 			</div>
 		@else
 			<div class="alert alert-danger">
 				<span> {{trans('auth.system_maintenance_tip',['email' => \App\Components\Helpers::systemConfig()['admin_email']])}} </span>
 			</div>
 		@endif
-		<div class="form-actions">
-			<button class="btn btn-danger btn-lg float-left" onclick="login()">{{trans('auth.back')}}</button>
-			@if(\App\Components\Helpers::systemConfig()['is_reset_password'])
-				<button type="submit" class="btn btn-primary btn-lg float-right">{{trans('auth.submit')}}</button>
-			@endif
-		</div>
+		<a href="/login" class="btn btn-danger btn-lg {{\App\Components\Helpers::systemConfig()['is_reset_password']? 'float-left':'btn-block'}}">{{trans('auth.back')}}</a>
+		@if(\App\Components\Helpers::systemConfig()['is_reset_password'])
+			<button type="submit" class="btn btn-primary btn-lg float-right">{{trans('auth.submit')}}</button>
+		@endif
 	</form>
 @endsection

+ 32 - 24
resources/views/coupon/addCoupon.blade.php

@@ -13,6 +13,9 @@
 		<div class="panel">
 			<div class="panel-heading">
 				<h1 class="panel-title">生成卡券</h1>
+				<div class="panel-actions">
+					<a href="/coupon/couponList" class="btn btn-danger">返 回</a>
+				</div>
 			</div>
 			@if (Session::has('successMsg'))
 				<div class="alert alert-success alert-dismissible">
@@ -32,7 +35,7 @@
 						<label class="col-md-2 col-form-label" for="name">卡券名称</label>
 						<div class="col-md-4">
 							<input type="text" class="form-control" name="name" id="name" value="{{Request::old('name')}}" required/>
-							<input name="_token" value="{{csrf_token()}}" hidden/>
+							{{csrf_field()}}
 						</div>
 						<span class="text-help"> 会用于前端显示 </span>
 					</div>
@@ -96,6 +99,14 @@
 							<span class="input-group-text">元</span>
 						</div>
 					</div>
+					<div class="form-group row usage">
+						<label class="col-md-2 col-form-label" for="rule">条件</label>
+						<div class="col-md-4 input-group">
+							<input type="number" class="form-control" name="rule" id="rule" value="{{Request::old('rule')}}" requied/>
+							<span class="input-group-text">元</span>
+						</div>
+						<span class="text-help"> 当套餐超过N值时,才能使用本优惠劵;0即使用无限制 </span>
+					</div>
 					<div class="form-group row">
 						<label class="col-md-2 col-form-label" for="num">数量</label>
 						<div class="col-md-4 input-group">
@@ -117,10 +128,7 @@
 						</div>
 					</div>
 					<div class="form-actions col-12 text-right">
-						<div class="btn-group">
-							<a href="/coupon/couponList" class="btn btn-danger">返回</a>
-							<button type="submit" class="btn btn-success">提交</button>
-						</div>
+						<button type="submit" class="btn btn-success">提 交</button>
 					</div>
 				</form>
 			</div>
@@ -139,25 +147,25 @@
         });
 
         $("input[name='type']").change(function () {
-            const type = $(this).val();
-            if (type === '2') {
-                $("#discount").attr("required", true);
-                $("#amount").attr("required", false);
-                $(".discount").show();
-                $(".usage").show();
-                $(".amount").hide();
-            } else if (type === '3') {
-                $("#discount").attr("required", false);
-                $("#amount").attr("required", true);
-                $(".discount").hide();
-                $(".usage").hide();
-                $(".amount").show();
-            } else {
-                $("#discount").attr("required", false);
-                $("#amount").attr("required", true);
-                $(".discount").hide();
-                $(".usage").show();
-                $(".amount").show();
+            switch (parseInt($(this).val())) {
+                case 2:
+                    $("#discount").attr("required", true);
+                    $("#amount").attr("required", false);
+                    $(".discount").show();
+                    $(".usage").show();
+                    $(".amount").hide();
+                case 3:
+                    $("#discount").attr("required", false);
+                    $("#amount").attr("required", true);
+                    $(".discount").hide();
+                    $(".usage").hide();
+                    $(".amount").show();
+                default:
+                    $("#discount").attr("required", false);
+                    $("#amount").attr("required", true);
+                    $(".discount").hide();
+                    $(".usage").show();
+                    $(".amount").show();
             }
         });
 	</script>

+ 4 - 7
resources/views/coupon/couponList.blade.php

@@ -102,7 +102,7 @@
 								</td>
 								<td>
 									@if($coupon->status != '1')
-										<button class="btn btn-danger" onclick="delCoupon('{{$coupon->id}}')"><i class="icon wb-close"></i></button>
+										<button class="btn btn-danger" onclick="delCoupon('{{$coupon->id}}','{{$coupon->name}}')"><i class="icon wb-close"></i></button>
 									@endif
 								</td>
 							</tr>
@@ -140,10 +140,7 @@
 
         // 搜索
         function Search() {
-            const sn = $("#sn").val();
-            const type = $("#type").val();
-            const status = $("#status").val();
-            window.location.href = '/coupon/couponList' + '?sn=' + sn + '&type=' + type + '&status=' + status;
+            window.location.href = '/coupon/couponList' + '?sn=' + $("#sn").val() + '&type=' + $("#type").val() + '&status=' + $("#status").val();
         }
 
         // 批量导出卡券
@@ -163,9 +160,9 @@
         }
 
         // 删除卡券
-        function delCoupon(id) {
+        function delCoupon(id, name) {
             swal.fire({
-                title: '确定删除卡券吗?',
+                title: '确定删除卡券 【' + name + '】 吗?',
                 type: 'question',
                 allowEnterKey: false,
                 showCancelButton: true,

+ 1 - 3
resources/views/marketing/emailList.blade.php

@@ -82,9 +82,7 @@
         }
 
         function Search() {
-            const status = $("#status option:selected").val();
-
-            window.location.href = "/marketing/emailList?status=" + status;
+            window.location.href = "/marketing/emailList?status=" + $("#status option:selected").val();
         }
 	</script>
 @endsection

+ 2 - 5
resources/views/marketing/pushList.blade.php

@@ -128,9 +128,7 @@
 	<script type="text/javascript">
         // 发送通道消息
         function send() {
-            const _token = '{{csrf_token()}}';
             const title = $("#title").val();
-            const content = $("#content").val();
 
             if (title.trim() === '') {
                 $("#msg").show().html("标题不能为空");
@@ -141,7 +139,7 @@
             $.ajax({
                 url: '/marketing/addPushMarketing',
                 type: "POST",
-                data: {_token: _token, title: title, content: content},
+                data: {_token: '{{csrf_token()}}', title: title, content: $("#content").val()},
                 beforeSend: function () {
                     $("#msg").show().html("正在添加...");
                 },
@@ -168,8 +166,7 @@
         });
 
         function Search() {
-            const status = $("#status").val();
-            window.location.href = "/marketing/pushList?status=" + status;
+            window.location.href = "/marketing/pushList?status=" + $("#status").val();
         }
 	</script>
 @endsection

+ 1 - 5
resources/views/payment/callbackList.blade.php

@@ -103,11 +103,7 @@
 
         // 搜索
         function Search() {
-            const trade_no = $("#trade_no").val();
-            const out_trade_no = $("#out_trade_no").val();
-            const type = $("#type option:selected").val();
-            const trade_status = $("#trade_status option:selected").val();
-            window.location.href = '/payment/callbackList?out_trade_no=' + out_trade_no + '&trade_no=' + trade_no + '&type=' + type + '&trade_status=' + trade_status;
+            window.location.href = '/payment/callbackList?out_trade_no=' + $("#trade_no").val() + '&trade_no=' + $("#out_trade_no").val() + '&type=' + $("#type option:selected").val() + '&trade_status=' + $("#trade_status option:selected").val();
         }
 	</script>
 @endsection

+ 1 - 3
resources/views/payment/detail.blade.php

@@ -52,9 +52,7 @@
 
         // 检查支付单状态
         function getStatus() {
-            var sn = '{{$payment->sn}}';
-
-            $.get("/payment/getStatus", {sn: sn}, function (ret) {
+            $.get("/payment/getStatus", {sn: '{{$payment->sn}}'}, function (ret) {
                 if (ret.status === 'success') {
                     swal.fire({title: ret.message, type: 'success', timer: 1500, showConfirmButton: false})
                         .then(() => window.location.href = '/invoices')

+ 2 - 7
resources/views/sensitiveWords/addSensitiveWords.blade.php

@@ -17,11 +17,10 @@
 						<label class="col-form-label col-md-2">敏感词</label>
 						<div class="col-md-5">
 							<input type="text" class="form-control" name="words" value="" id="words" required/>
-							<input type="hidden" name="_token" value="{{csrf_token()}}"/>
 						</div>
 					</div>
 					<div class="form-actions">
-						<button type="submit" class="btn btn-success">提交</button>
+						<button type="submit" class="btn btn-success">提 交</button>
 					</div>
 				</form>
 			</div>
@@ -51,14 +50,11 @@
 	<script type="text/javascript">
         // ajax同步提交
         function Submit() {
-            const _token = '{{csrf_token()}}';
-            const words = $('#words').val();
-
             $.ajax({
                 type: "POST",
                 url: "/admin/addSensitiveWords",
                 async: false,
-                data: {_token: _token, words: words},
+                data: {_token: '{{csrf_token()}}', words: $('#words').val()},
                 dataType: 'json',
                 success: function (ret) {
                     swal.fire({title: ret.message, timer: 1000, showConfirmButton: false,})
@@ -67,7 +63,6 @@
                         })
                 }
             });
-
             return false;
         }
 	</script>

+ 26 - 9
resources/views/sensitiveWords/sensitiveWordsList.blade.php

@@ -18,6 +18,7 @@
 					<thead class="thead-default">
 					<tr>
 						<th> #</th>
+						<th> 类型</th>
 						<th> 敏感词</th>
 						<th> 操作</th>
 					</tr>
@@ -31,9 +32,10 @@
 						@foreach($list as $vo)
 							<tr>
 								<td> {{$vo->id}} </td>
+								<td> {{$vo->type==1? '黑':'白'}} </td>
 								<td> {{$vo->words}} </td>
 								<td>
-									<button class="btn btn-danger" onclick="delWord('{{$vo->id}}')">
+									<button class="btn btn-danger" onclick="delWord('{{$vo->id}}','{{$vo->words}}')">
 										<i class="icon wb-trash"></i>
 									</button>
 								</td>
@@ -59,7 +61,7 @@
 	</div>
 
 	<div id="add_sensitive_words" class="modal fade" tabindex="-1" data-focus-on="input:first" data-keyboard="false">
-		<div class="modal-dialog modal-simple modal-center">
+		<div class="modal-dialog modal-simple modal-center modal-lg">
 			<div class="modal-content">
 				<div class="modal-header">
 					<button type="button" class="close" data-dismiss="modal" aria-label="Close">
@@ -68,7 +70,25 @@
 					<h4 class="modal-title"> 添加敏感词 </h4>
 				</div>
 				<div class="modal-body">
-					<input type="text" name="words" id="words" placeholder="请填入敏感词" class="form-control"/>
+					<div class="form-group row">
+						<label class="col-form-label col-md-2" for="type">类型</label>
+						<div class="col-md-10 d-flex align-items-center">
+							<div class="radio-custom radio-primary radio-inline">
+								<input type="radio" name="type" value="1" checked/>
+								<label for="type">黑名单</label>
+							</div>
+							<div class="radio-custom radio-primary radio-inline">
+								<input type="radio" name="type" value="2"/>
+								<label for="type">白名单</label>
+							</div>
+						</div>
+					</div>
+					<div class="form-group row">
+						<label class="col-form-label col-md-2" for="words">敏感词</label>
+						<div class="col-md-9">
+							<input type="text" class="form-control" name="words" id="words" placeholder="请填入敏感词"/>
+						</div>
+					</div>
 				</div>
 				<div class="modal-footer">
 					<button data-dismiss="modal" class="btn btn-danger"> 关 闭</button>
@@ -82,19 +102,17 @@
 @section('script')
 	<script src="/assets/global/vendor/bootstrap-table/bootstrap-table.min.js" type="text/javascript"></script>
 	<script src="/assets/global/vendor/bootstrap-table/extensions/mobile/bootstrap-table-mobile.min.js" type="text/javascript"></script>
-
 	<script type="text/javascript">
         // 添加敏感词
         function addSensitiveWords() {
             const words = $('#words').val();
-
             if (words.trim() === '') {
                 swal.fire({title: '敏感词不能为空', type: 'warning', timer: 1000, showConfirmButton: false});
                 $("#words").focus();
                 return false;
             }
 
-            $.post("/sensitiveWords/add", {_token: '{{csrf_token()}}', words: words}, function (ret) {
+            $.post("/sensitiveWords/add", {_token: '{{csrf_token()}}', type: $("input:radio[name='type']:checked").val(), words: words}, function (ret) {
                 if (ret.status === 'success') {
                     swal.fire({title: ret.message, type: 'success', timer: 1000, showConfirmButton: false})
                         .then(() => window.location.reload())
@@ -104,12 +122,11 @@
             });
         }
 
-
         // 删除敏感词
-        function delWord(id) {
+        function delWord(id, name) {
             swal.fire({
                 title: '警告',
-                text: '确定删除敏感词',
+                text: '确定删除敏感词 【' + name + '】 ?',
                 type: 'warning',
                 showCancelButton: true,
                 cancelButtonText: '取消',

+ 74 - 64
resources/views/shop/addGoods.blade.php

@@ -41,8 +41,8 @@
 					<div class="form-row">
 						<div class="col-lg-6 col-md-12">
 							<div class="form-group row">
-								<label class="col-md-2 col-form-label" for="type">类型</label>
-								<div class="col-md-10 d-flex align-items-center">
+								<label class="col-md-3 col-form-label" for="type">类型</label>
+								<div class="col-md-9 d-flex align-items-center">
 									<div class="radio-custom radio-primary radio-inline">
 										<input type="radio" name="type" value="1" checked/>
 										<label for="type">流量包</label>
@@ -56,51 +56,48 @@
 										<label for="type">充值</label>
 									</div>
 								</div>
-								<span class="offset-md-2 text-help"> 套餐与账号有效期有关,流量包只扣可用流量,不影响有效期 </span>
+								<span class="offset-md-3 text-help"> 套餐与账号有效期有关,流量包只扣可用流量,不影响有效期 </span>
 							</div>
 							<div class="form-group row">
-								<label class="col-md-2 col-form-label" for="name">名称</label>
+								<label class="col-md-3 col-form-label" for="name">名称</label>
 								<div class="col-md-6">
 									<input type="text" class="form-control" name="name" id="name" value="{{Request::old('name')}}" required/>
-									<input name="_token" value="{{csrf_token()}}" hidden/>
+									{{csrf_field()}}
 								</div>
 							</div>
 							<div class="form-group row package-money">
-								<label class="col-md-2 col-form-label" for="logo">商品图片</label>
-								<div class="col-md-9">
-									<input type="file" id="logo" name="logo" data-plugin="dropify" data-default-file="/assets/images/noimage.png"/>
-								</div>
-							</div>
-							<div class="form-group row package-money">
-								<label class="col-md-2 col-form-label" for="desc">描述</label>
-								<div class="col-md-9">
-									<textarea class="form-control" rows="2" name="desc" id="desc" placeholder="商品的简单描述">{{Request::old('desc')}}</textarea>
-								</div>
-							</div>
-							<div class="form-group row package-money">
-								<label class="col-md-2 col-form-label" for="info">自定义列表</label>
-								<div class="col-md-9">
-									<textarea class="form-control" rows="6" name="info" id="info" placeholder="商品的自定义列表添加">{{Request::old('info')}}</textarea>
+								<label class="col-md-3 col-form-label" for="traffic">流量额度</label>
+								<div class="col-md-4 input-group">
+									<input type="number" class="form-control" name="traffic" id="traffic" value="{{Request::old('traffic')? :1024}}" required/>
+									<span class="input-group-text">MB</span>
 								</div>
-								<span class="offset-md-2 text-help"> 每行内容请以<code>&lt;li&gt;</code> 开头 <code>&lt;/li&gt;</code> 结尾</span>
+								<span class="text-help"> *提交后不可修改 </span>
 							</div>
 							<div class="form-group row">
-								<label class="col-md-2 col-form-label" for="price">售价</label>
+								<label class="col-md-3 col-form-label" for="price">售价</label>
 								<div class="col-md-4 input-group">
 									<input type="number" class="form-control" name="price" id="price" value="{{Request::old('price')}}" required/>
 									<span class="input-group-text">元</span>
 								</div>
 							</div>
+							<div class="form-group row package-renew" style="display: none">
+								<label class="col-md-3 col-form-label" for="renew">流量重置价格</label>
+								<div class="col-md-4 input-group">
+									<input type="number" class="form-control" name="renew" id="renew" value="{{Request::old('renew')? :0}}" required/>
+									<span class="input-group-text">元</span>
+								</div>
+								<span class="offset-md-3 text-help"> 用户自行重置流量价格, <code>0</code> 时代表改该商品不提供重置功能 </span>
+							</div>
 							<div class="form-group row package-money">
-								<label class="col-md-2 col-form-label" for="traffic">内含流量</label>
+								<label class="col-md-3 col-form-label" for="limit_num">限购数量</label>
 								<div class="col-md-4 input-group">
-									<input type="number" class="form-control" name="traffic" id="traffic" value="{{Request::old('traffic')?Request::old('traffic') :1024}}" required/>
-									<span class="input-group-text">MB</span>
+									<input type="number" class="form-control" name="limit_num" id="limit_num" value="{{Request::old('limit_num')? :0}}" required/>
+									<span class="input-group-text"></span>
 								</div>
-								<span class="offset-md-12 text-help"> 提交后不可修改 </span>
+								<span class="offset-md-3 text-help"> 每个用户可以购买该商品次数,为 <code>0</code> 时代表不限购 </span>
 							</div>
 							<div class="form-group row package-money">
-								<label class="col-md-2 col-form-label" for="labels">标签</label>
+								<label class="col-md-3 col-form-label" for="labels">标签</label>
 								<div class="col-md-8">
 									<select class="form-control show-tick" name="labels[]" id="labels" data-plugin="selectpicker" data-style="btn-outline btn-primary" multiple>
 										@foreach($label_list as $label)
@@ -108,34 +105,19 @@
 										@endforeach
 									</select>
 								</div>
-								<span class="offset-md-2 text-help"> 自动给购买此商品的用户打上相应的标签 </span>
+								<span class="offset-md-3 text-help"> 自动给购买此商品的用户打上相应的标签 </span>
 							</div>
-						</div>
-						<div class="col-lg-6 col-md-12">
 							<div class="form-group row package-money">
-								<label class="col-md-2 col-form-label" for="days">有效期</label>
+								<label class="col-md-3 col-form-label" for="days">有效期</label>
 								<div class="col-md-3 input-group">
-									<input type="number" class="form-control" name="days" id="days" value="{{Request::old('days')?Request::old('days') :30}}" required/>
+									<input type="number" class="form-control" name="days" id="days" value="{{Request::old('days')? :30}}" required/>
 									<span class="input-group-text">天</span>
 								</div>
-								<span class="offset-md-2 text-help"> 到期后会自动从总流量扣减对应的流量,添加后不可修改 </span>
-							</div>
-							<div class="form-group row package-money">
-								<label class="col-md-2 col-form-label" for="sort">排序</label>
-								<div class="col-md-3">
-									<input type="number" class="form-control" name="sort" id="sort" value="{{Request::old('sort')?Request::old('days') :0}}"/>
-								</div>
-								<span class="text-help"> 排序值越大排越前 </span>
-							</div>
-							<div class="form-group row package-money">
-								<label class="col-md-2 col-form-label" for="color">颜色</label>
-								<div class="col-md-4">
-									<input type="text" class="form-control" name="color" id="color" data-plugin="asColorPicker" data-mode="simple" value="{{Request::old('color')?Request::old('color') :'#667AFA'}}"/>
-								</div>
+								<span class="text-help"> *提交后不可修改 </span>
 							</div>
 							<div class="form-group row package-money">
-								<label class="col-md-2 col-form-label" for="is_hot">热销</label>
-								<div class="col-md-10 d-flex align-items-center">
+								<label class="col-md-3 col-form-label" for="is_hot">热销</label>
+								<div class="col-md-9 d-flex align-items-center">
 									<div class="radio-custom radio-primary radio-inline">
 										<input type="radio" name="is_hot" value="1"/>
 										<label for="is_hot">是</label>
@@ -147,21 +129,8 @@
 								</div>
 							</div>
 							<div class="form-group row">
-								<label class="col-md-2 col-form-label" for="is_limit">限购</label>
-								<div class="col-md-10 d-flex align-items-center">
-									<div class="radio-custom radio-primary radio-inline">
-										<input type="radio" name="is_limit" value="1"/>
-										<label for="is_limit">是</label>
-									</div>
-									<div class="radio-custom radio-primary radio-inline">
-										<input type="radio" name="is_limit" value="0" checked/>
-										<label for="is_limit">否</label>
-									</div>
-								</div>
-							</div>
-							<div class="form-group row">
-								<label class="col-md-2 col-form-label" for="status">状态</label>
-								<div class="col-md-10 d-flex align-items-center">
+								<label class="col-md-3 col-form-label" for="status">状态</label>
+								<div class="col-md-9 d-flex align-items-center">
 									<div class="radio-custom radio-primary radio-inline">
 										<input type="radio" name="status" value="1" checked/>
 										<label for="status">上架</label>
@@ -173,7 +142,42 @@
 								</div>
 							</div>
 						</div>
+						<div class="col-lg-6 col-md-12 package-money">
+							<div class="form-group row">
+								<label class="col-md-3 col-form-label" for="sort">排序</label>
+								<div class="col-md-3">
+									<input type="number" class="form-control" name="sort" id="sort" value="{{Request::old('sort')? :0}}"/>
+								</div>
+								<span class="text-help"> 排序值越大排越前 </span>
+							</div>
+							<div class="form-group row">
+								<label class="col-md-3 col-form-label" for="color">颜色</label>
+								<div class="col-md-4">
+									<input type="text" class="form-control" name="color" id="color" data-plugin="asColorPicker" data-mode="simple" value="{{Request::old('color')? :'#667AFA'}}"/>
+								</div>
+							</div>
+							<div class="form-group row">
+								<label class="col-md-3 col-form-label" for="logo">商品图片</label>
+								<div class="col-md-9">
+									<input type="file" id="logo" name="logo" data-plugin="dropify" data-default-file="/assets/images/noimage.png"/>
+								</div>
+							</div>
+							<div class="form-group row">
+								<label class="col-md-3 col-form-label" for="desc">描述</label>
+								<div class="col-md-9">
+									<textarea class="form-control" rows="2" name="desc" id="desc" placeholder="商品的简单描述">{{Request::old('desc')}}</textarea>
+								</div>
+							</div>
+							<div class="form-group row">
+								<label class="col-md-3 col-form-label" for="info">自定义列表</label>
+								<div class="col-md-9">
+									<textarea class="form-control" rows="6" name="info" id="info" placeholder="商品的自定义列表添加">{{Request::old('info')}}</textarea>
+								</div>
+								<span class="offset-md-3 text-help"> 每行内容请以<code>&lt;li&gt;</code> 开头 <code>&lt;/li&gt;</code> 结尾</span>
+							</div>
+						</div>
 						<div class="form-actions col-12 text-right">
+							<a href="/shop/goodsList" class="btn btn-danger"> 返 回</a>
 							<button type="submit" class="btn btn-success"><i class="icon wb-check"></i> 提 交</button>
 						</div>
 					</div>
@@ -197,11 +201,17 @@
         // 选择商品类型
         $("input[name='type']").change(function () {
             const type = $(this).val();
-            if (type == 3) {
+            if (type === '3') {
                 $(".package-money").hide();
             } else {
                 $(".package-money").show();
             }
+
+            if (type === '2') {
+                $(".package-renew").show();
+            } else {
+                $(".package-renew").hide();
+            }
         });
 	</script>
 @endsection

+ 51 - 46
resources/views/shop/editGoods.blade.php

@@ -14,6 +14,9 @@
 		<div class="panel panel-bordered">
 			<div class="panel-heading">
 				<h1 class="panel-title"><i class="icon wb-shopping-cart" aria-hidden="true"></i>编辑商品</h1>
+				<div class="panel-actions">
+					<a href="/shop/goodsList" class="btn btn-danger">返 回</a>
+				</div>
 			</div>
 			@if (Session::has('successMsg'))
 				<div class="alert alert-success alert-dismissible" role="alert">
@@ -55,31 +58,10 @@
 						<label class="col-md-2 col-form-label" for="name">名称</label>
 						<div class="col-md-4">
 							<input type="text" class="form-control" name="name" id="name" value="{{$goods->name}}" required/>
-							<input name="_token" value="{{csrf_token()}}" hidden/>
+							{{csrf_field()}}
 							<input name="id" value="{{$goods->id}}" hidden/>
 						</div>
 					</div>
-					@if($goods->type <= 2)
-						<div class="form-group row">
-							<label class="col-md-2 col-form-label" for="logo">商品图片</label>
-							<div class="col-md-6">
-								<input type="file" id="logo" name="logo" data-plugin="dropify" data-default-file=@if($goods->logo){{$goods->logo}}@else"/assets/images/noimage.png"@endif/>
-							</div>
-						</div>
-						<div class="form-group row">
-							<label class="col-md-2 col-form-label" for="desc">描述</label>
-							<div class="col-md-8">
-								<textarea class="form-control" rows="2" name="desc" id="desc" placeholder="商品的简单描述">{{$goods->desc}}</textarea>
-							</div>
-						</div>
-						<div class="form-group row">
-							<label class="col-md-2 col-form-label" for="info">自定义列表</label>
-							<div class="col-md-8">
-								<textarea class="form-control" rows="6" name="info" id="info" placeholder="商品的自定义列表添加">{{$goods->info}}</textarea>
-							</div>
-							<span class="offset-md-2 text-help"> 每行内容请以<code>&lt;li&gt;</code> 开头 <code>&lt;/li&gt;</code> 结尾</span>
-						</div>
-					@endif
 					<div class="form-group row">
 						<label class="col-md-2 col-form-label" for="price">售价</label>
 						<div class="col-md-4 input-group">
@@ -87,24 +69,54 @@
 							<span class="input-group-text">元</span>
 						</div>
 					</div>
+					<div class="form-group row">
+						<label class="col-md-2 col-form-label" for="status">状态</label>
+						<div class="col-md-10 d-flex align-items-center">
+							<div class="radio-custom radio-primary radio-inline">
+								<input type="radio" name="status" value="1" @if($goods->status == 1) checked @endif/>
+								<label for="status">上架</label>
+							</div>
+							<div class="radio-custom radio-primary radio-inline">
+								<input type="radio" name="status" value="0" @if($goods->status == 0) checked @endif/>
+								<label for="status">下架</label>
+							</div>
+						</div>
+					</div>
 					@if($goods->type <= 2)
+						@if ($goods->type == 2)
+							<div class="form-group row">
+								<label class="col-md-2 col-form-label" for="renew">流量重置价格</label>
+								<div class="col-md-4 input-group">
+									<input type="number" class="form-control" name="renew" id="renew" value="{{$goods->renew}}"/>
+									<span class="input-group-text">元</span>
+								</div>
+							</div>
+						@endif
 						<div class="form-group row">
-							<label class="col-md-2 col-form-label" for="traffic">内含流量</label>
+							<label class="col-md-2 col-form-label" for="traffic">流量额度</label>
 							<div class="col-md-4 input-group">
 								<input type="number" class="form-control" name="traffic" id="traffic" value="{{$goods->traffic}}" disabled/>
 								<span class="input-group-text">MB</span>
 							</div>
 						</div>
+						<div class="form-group row">
+							<label class="col-md-2 col-form-label" for="limit_num">限购数量</label>
+							<div class="col-md-4 input-group">
+								<input type="number" class="form-control" name="limit_num" id="limit_num" value="{{$goods->limit_num}}" required/>
+								<span class="input-group-text">次</span>
+							</div>
+							<span class="text-help"> 每个用户可以购买该商品次数,为 0 时代表不限购 </span>
+						</div>
 						<div class="form-group row">
 							<label class="col-md-2 col-form-label" for="labels">标签</label>
-							<div class="col-md-7">
+							<div class="col-md-6">
 								<select class="form-control show-tick" name="labels[]" id="labels" data-plugin="selectpicker" data-style="btn-outline btn-primary" multiple>
 									@foreach($label_list as $label)
 										<option value="{{$label->id}}" @if(in_array($label->id, $goods->labels)) selected @endif>{{$label->name}}</option>
 									@endforeach
 								</select>
 							</div>
-							<span class="offset-md-2 text-help"> 自动给购买此商品的用户打上相应的标签 </span>
+							<span class="text-help"> 自动给购买此商品的用户打上相应的标签 </span>
 						</div>
 						<div class="form-group row">
 							<label class="col-md-2 col-form-label" for="days">有效期</label>
@@ -141,32 +153,25 @@
 							</div>
 						</div>
 						<div class="form-group row">
-							<label class="col-md-2 col-form-label" for="is_limit">限购</label>
-							<div class="col-md-10 d-flex align-items-center">
-								<div class="radio-custom radio-primary radio-inline">
-									<input type="radio" name="is_limit" value="1" @if($goods->is_limit == 1) checked @endif/>
-									<label for="is_limit">是</label>
-								</div>
-								<div class="radio-custom radio-primary radio-inline">
-									<input type="radio" name="is_limit" value="0" @if($goods->is_limit == 0) checked @endif/>
-									<label for="is_limit">否</label>
-								</div>
+							<label class="col-md-2 col-form-label" for="logo">商品图片</label>
+							<div class="col-md-6">
+								<input type="file" id="logo" name="logo" data-plugin="dropify" data-default-file={{$goods->logo?:'/assets/images/noimage.png'}} />
 							</div>
 						</div>
-					@endif
-					<div class="form-group row">
-						<label class="col-md-2 col-form-label" for="status">状态</label>
-						<div class="col-md-10 d-flex align-items-center">
-							<div class="radio-custom radio-primary radio-inline">
-								<input type="radio" name="status" value="1" @if($goods->status == 1) checked @endif/>
-								<label for="status">上架</label>
+						<div class="form-group row">
+							<label class="col-md-2 col-form-label" for="desc">描述</label>
+							<div class="col-md-8">
+								<textarea class="form-control" rows="2" name="desc" id="desc" placeholder="商品的简单描述">{{$goods->desc}}</textarea>
 							</div>
-							<div class="radio-custom radio-primary radio-inline">
-								<input type="radio" name="status" value="0" @if($goods->status == 0) checked @endif/>
-								<label for="status">下架</label>
+						</div>
+						<div class="form-group row">
+							<label class="col-md-2 col-form-label" for="info">自定义列表</label>
+							<div class="col-md-8">
+								<textarea class="form-control" rows="6" name="info" id="info" placeholder="商品的自定义列表添加">{{$goods->info}}</textarea>
 							</div>
+							<span class="offset-md-2 text-help"> 每行内容请以<code>&lt;li&gt;</code> 开头 <code>&lt;/li&gt;</code> 结尾</span>
 						</div>
-					</div>
+					@endif
 					<div class="form-actions col-12 text-right">
 						<button type="submit" class="btn btn-success"><i class="icon wb-check"></i> 提 交</button>
 					</div>

+ 6 - 12
resources/views/shop/goodsList.blade.php

@@ -44,7 +44,7 @@
 						<th> 售价</th>
 						<th> 排序</th>
 						<th> 热销</th>
-						<th> 限购</th>
+						<th> 限购</th>
 						<th> 状态</th>
 						<th> 操作</th>
 					</tr>
@@ -84,11 +84,7 @@
 									@endif
 								</td>
 								<td>
-									@if($goods->is_limit)
-										<span class="badge badge-lg badge-danger">是</span>
-									@else
-										<span class="badge badge-lg badge-default">否</span>
-									@endif
+									{{$goods->limit_num}}
 								</td>
 								<td>
 									@if($goods->status)
@@ -100,7 +96,7 @@
 								<td>
 									<div class="btn-group">
 										<a href="/shop/editGoods/{{$goods->id}}" class="btn btn-primary"><i class="icon wb-edit"></i></a>
-										<button class="btn btn-danger" onclick="delGoods('{{$goods->id}}')"><i class="icon wb-trash"></i></button>
+										<button class="btn btn-danger" onclick="delGoods('{{$goods->id}}','{{$goods->name}}')"><i class="icon wb-trash"></i></button>
 									</div>
 								</td>
 							</tr>
@@ -130,16 +126,14 @@
 	<script type="text/javascript">
         // 搜索
         function Search() {
-            const type = $("#type option:selected").val();
-            const status = $("#status option:selected").val();
-            window.location.href = '/shop/goodsList?type=' + type + '&status=' + status;
+            window.location.href = '/shop/goodsList?type=' + $("#type option:selected").val() + '&status=' + $("#status option:selected").val();
         }
 
         // 删除商品
-        function delGoods(id) {
+        function delGoods(id, name) {
             swal.fire({
                 title: '警告',
-                text: '确定删除商品?',
+                text: '确定删除商品 【' + name + '】 ?',
                 type: 'warning',
                 showCancelButton: true,
                 cancelButtonText: '取消',

+ 1 - 2
resources/views/subscribe/deviceList.blade.php

@@ -82,8 +82,7 @@
 	<script type="text/javascript">
         // 搜索
         function Search() {
-            const status = $("#status option:selected").val();
-            window.location.href = '/subscribe/deviceList' + '?status=' + status;
+            window.location.href = '/subscribe/deviceList' + '?status=' + $("#status option:selected").val();
         }
 
         // 启用禁用订阅设备

+ 4 - 8
resources/views/subscribe/subscribeList.blade.php

@@ -18,9 +18,8 @@
 					</div>
 					<div class="form-group col-lg-3 col-sm-6">
 						<select name="status" id="status" class="form-control" onChange="Search()">
-							<option value="" @if(Request::get('status') == '') selected hidden @endif>账号状态</option>
-							<option value="-1" @if(Request::get('status') == '-1') selected hidden @endif>禁用</option>
-							<option value="0" @if(Request::get('status') == '0') selected hidden @endif>未激活</option>
+							<option value="" @if(Request::get('status') == '') selected hidden @endif>状态</option>
+							<option value="0" @if(Request::get('status') == '0') selected hidden @endif>禁用</option>
 							<option value="1" @if(Request::get('status') == '1') selected hidden @endif>正常</option>
 						</select>
 					</div>
@@ -60,7 +59,7 @@
 								</td>
 								<td> {{$subscribe->code}} </td>
 								<td>
-									<a href="/admin/userSubscribeLog?user_id={{$subscribe->user->id}}" target="_blank">{{$subscribe->times}}</a>
+									<a href="/subscribe/subscribeLog?id={{$subscribe->id}}" target="_blank">{{$subscribe->times}}</a>
 								</td>
 								<td> {{$subscribe->updated_at}} </td>
 								<td> {{$subscribe->ban_time > 0 ? date('Y-m-d H:i', $subscribe->ban_time): ''}} </td>
@@ -108,10 +107,7 @@
 
         // 搜索
         function Search() {
-            const user_id = $("#user_id").val();
-            const username = $("#username").val();
-            const status = $("#status option:selected").val();
-            window.location.href = '/subscribe/subscribeList' + '?user_id=' + user_id + '&username=' + username + '&status=' + status;
+            window.location.href = '/subscribe/subscribeList' + '?user_id=' + $("#user_id").val() + '&username=' + $("#username").val() + '&status=' + $("#status option:selected").val();
         }
 
         // 启用禁用用户的订阅

+ 59 - 0
resources/views/subscribe/subscribeLog.blade.php

@@ -0,0 +1,59 @@
+@extends('admin.layouts')
+@section('css')
+	<link href="/assets/global/vendor/bootstrap-table/bootstrap-table.min.css" type="text/css" rel="stylesheet">
+@endsection
+@section('content')
+	<div class="page-content container-fluid">
+		<div class="panel">
+			<div class="panel-heading">
+				<h3 class="panel-title">订阅列表</h3>
+			</div>
+			<div class="panel-body">
+				<table class="text-md-center" data-toggle="table" data-mobile-responsive="true">
+					<thead class="thead-default">
+					<tr>
+						<th> #</th>
+						<th> 用户</th>
+						<th> 请求IP</th>
+						<th> 请求时间</th>
+						<th> 访问</th>
+					</tr>
+					</thead>
+					<tbody>
+					@if($subscribeLog->isEmpty())
+						<tr>
+							<td colspan="6">暂无数据</td>
+						</tr>
+					@else
+						@foreach($subscribeLog as $subscribe)
+							<tr>
+								<td>{{$subscribe->id}}</td>
+								<td>{{empty($subscribe->user) ? '用户已删除' : $subscribe->user[0]->username}}</td>
+								<td>{{$subscribe->request_ip}}</td>
+								<td>{{$subscribe->request_time}}</td>
+								<td>{{$subscribe->request_header}}</td>
+							</tr>
+						@endforeach
+					@endif
+					</tbody>
+				</table>
+			</div>
+			<div class="panel-footer">
+				<div class="row">
+					<div class="col-sm-4">
+						共 <code>{{$subscribeLog->total()}}</code> 条记录
+					</div>
+					<div class="col-sm-8">
+						<nav class="Page navigation float-right">
+							{{$subscribeLog->links()}}
+						</nav>
+					</div>
+				</div>
+			</div>
+		</div>
+	</div>
+@endsection
+@section('script')
+	<script src="/assets/global/vendor/bootstrap-table/bootstrap-table.min.js" type="text/javascript"></script>
+	<script src="/assets/global/vendor/bootstrap-table/extensions/mobile/bootstrap-table-mobile.min.js" type="text/javascript"></script>
+@endsection

+ 1 - 6
resources/views/ticket/addTicket.blade.php

@@ -49,22 +49,17 @@
 	<script type="text/javascript">
         // ajax同步提交
         function Submit() {
-            const username = $('#username').val();
-            const title = $('#title').val();
-            const content = $('#content').val();
-
             $.ajax({
                 type: "POST",
                 url: "/ticket/addTicket",
                 async: false,
-                data: {_token: '{{csrf_token()}}', username: username, title: title, content: content},
+                data: {_token: '{{csrf_token()}}', username: $('#username').val(), title: $('#title').val(), content: $('#content').val()},
                 dataType: 'json',
                 success: function (ret) {
                     swal.fire({title: ret.message, type: 'success', timer: 1000})
                         .then(() => window.location.href = '/ticket/ticketList');
                 }
             });
-
             return false;
         }
 	</script>

+ 2 - 2
resources/views/ticket/replyTicket.blade.php

@@ -9,7 +9,7 @@
 				<h1 class="panel-title cyan-600"><i class="icon wb-help-circle"></i> {{$ticket->title}} </h1>
 				@if($ticket->status != 2)
 					<div class="panel-actions">
-						<a href="/ticket/ticketList" class="btn btn-danger">返回</a>
+						<a href="/ticket/ticketList" class="btn btn-danger">返 回</a>
 						<button class="btn btn-danger" onclick="closeTicket()"> {{trans('home.ticket_close')}} </button>
 					</div>
 				@endif
@@ -105,7 +105,7 @@
                                 title: ret.message,
                                 type: 'success',
                                 timer: 1000,
-	                            showConfirmButton: false
+                                showConfirmButton: false
                             }).then(() => window.location.href = '/ticket/ticketList')
                         },
                         error: function () {

+ 2 - 9
resources/views/ticket/ticketList.blade.php

@@ -53,13 +53,7 @@
 									<a href="/ticket/replyTicket?id={{$ticket->id}}" target="_blank">{{$ticket->title}}</a>
 								</td>
 								<td>
-									@if ($ticket->status == 0)
-										<span class="badge badge-lg badge-info"> 待处理 </span>
-									@elseif ($ticket->status == 1)
-										<span class="badge badge-lg badge-success"> 已回复 </span>
-									@else
-										<span class="badge badge-lg badge-default"> 已关闭 </span>
-									@endif
+									{!!$ticket->status_label!!}
 								</td>
 							</tr>
 						@endforeach
@@ -96,8 +90,7 @@
 
         // 搜索
         function Search() {
-            const username = $("#username").val();
-            window.location.href = '/ticket/ticketList?username=' + username;
+            window.location.href = '/ticket/ticketList?username=' + $("#username").val();
         }
 	</script>
 @endsection

+ 18 - 20
resources/views/user/buy.blade.php

@@ -57,8 +57,7 @@
 							<div class="input-group">
 								<input class="form-control" type="text" name="coupon_sn" id="coupon_sn" placeholder="{{trans('home.coupon')}}"/>
 								<div class="input-group-btn">
-									<button type="submit" class="btn btn-info" onclick="redeemCoupon()"><i class="icon wb-loop" aria-hidden="true"></i> {{trans('home.redeem_coupon')}}
-									</button>
+									<button type="submit" class="btn btn-info" onclick="redeemCoupon()"><i class="icon wb-loop" aria-hidden="true"></i> {{trans('home.redeem_coupon')}}</button>
 								</div>
 							</div>
 						</div>
@@ -100,10 +99,9 @@
                 type: "POST",
                 url: "/redeemCoupon",
                 async: false,
-                data: {_token: '{{csrf_token()}}', coupon_sn: coupon_sn},
+                data: {_token: '{{csrf_token()}}', coupon_sn: coupon_sn, price: '{{$goods->price}}'},
                 dataType: 'json',
                 success: function (ret) {
-                    console.log(ret);
                     $(".input-group-prepend").remove();
                     if (ret.status === 'success') {
                         $("#coupon_sn").parent().prepend('<div class="input-group-prepend"><span class="input-group-text bg-green-700"><i class="icon wb-check white" aria-hidden="true"></i></span></div>');
@@ -111,14 +109,13 @@
                         let total_price = 0;
                         if (ret.data.type === 2) {
                             total_price = goods_price * (1 - ret.data.discount / 10);
-                            $(".page-invoice-amount").parent().prepend('<p>优惠码 - ' + ret.data.name + ' ' + ret.data.discount + '折<br> 优惠 <span>¥' + total_price.toFixed(2) + '</span></p>');
+                            $(".page-invoice-amount").parent().prepend('<p>优惠码 - ' + ret.data.name + ' ' + ret.data.discount + '折<br> 优惠 <span>¥ - ' + total_price.toFixed(2) + '</span></p>');
                             total_price = goods_price - total_price;
-                            console.log(total_price);
                         } else {
                             total_price = goods_price - ret.data.amount;
                             total_price = total_price > 0 ? total_price : 0;
                             if (ret.data.type === 1) {
-                                $(".page-invoice-amount").parent().prepend('优惠码-' + ret.data.name + ' <span>¥0</span>');
+                                $(".page-invoice-amount").parent().prepend('优惠码-' + ret.data.name + ' <span>¥ - '+ret.data.amount+'</span>');
                             }
                         }
 
@@ -127,17 +124,16 @@
                         swal.fire({
                             title: ret.message,
                             type: 'success',
-                            timer: 1500,
+                            timer: 1300,
                             showConfirmButton: false
                         });
                     } else {
                         $(".grand-total").text("¥" + goods_price);
                         $("#coupon_sn").parent().prepend('<div class="input-group-prepend"><span class="input-group-text bg-red-700"><i class="icon wb-close white" aria-hidden="true"></i></span></div>');
                         swal.fire({
-                            title: ret.message,
-                            type: 'error',
-                            timer: 1500,
-                            showConfirmButton: false
+                            title: ret.title,
+                            text: ret.message,
+                            type: 'error'
                         });
                     }
                 }
@@ -169,10 +165,12 @@
                         } else {
                             window.location.href = '/payment/' + ret.data;
                         }
+                    } else if(ret.status === 'info'){
+                        swal.fire({title: ret.title, text: ret.message, type: 'question'});
                     } else {
                         swal.fire({
                             title: ret.message,
-                            type: 'error',
+                            type: 'error'
                         })
                     }
                 },
@@ -184,24 +182,24 @@
 
         // 余额支付
         function pay() {
-            const goods_id = '{{$goods->id}}';
-            const coupon_sn = $('#coupon_sn').val();
             $.ajax({
                 type: "POST",
-                url: "/buy/" + goods_id,
+                url: "/buy/" + '{{$goods->id}}',
                 async: false,
-                data: {_token: '{{csrf_token()}}', coupon_sn: coupon_sn},
+                data: {_token: '{{csrf_token()}}', coupon_sn: $('#coupon_sn').val()},
                 dataType: 'json',
                 success: function (ret) {
                     if (ret.status === 'success') {
                         swal.fire({title: ret.message, type: 'success',})
                             .then(() => window.location.href = '/invoices')
-                    } else {
-                        swal.fire({title: ret.message, type: 'error',})
+                    } else if(ret.status === 'info'){
+                        swal.fire({title: ret.title, text: ret.message, type: 'question'});
+	                } else{
+                        swal.fire({title: ret.message, type: 'error'})
                     }
                 },
                 error: function () {
-                    swal.fire({title: '未知错误!请开工单通知客服', type: 'error',})
+                    swal.fire({title: '未知错误!请开工单通知客服', type: 'error'})
                 }
             });
         }

+ 55 - 105
resources/views/user/help.blade.php

@@ -19,12 +19,9 @@
 				<div class="panel">
 					<div class="panel-body">
 						<div class="list-group faq-list" role="tablist">
-							<a class="list-group-item list-group-item-action active" data-toggle="tab"
-							   href="#category-1" aria-controls="category-1" role="tab">使用&下载</a>
-							<a class="list-group-item" data-toggle="tab" href="#category-3" aria-controls="category-3"
-							   role="tab">账号&服务</a>
-							<a class="list-group-item" data-toggle="tab" href="#category-2" aria-controls="category-2"
-							   role="tab">面板相关</a>
+							<a class="list-group-item list-group-item-action active" data-toggle="tab" href="#category-1" aria-controls="category-1" role="tab">使用&下载</a>
+							<a class="list-group-item" data-toggle="tab" href="#category-3" aria-controls="category-3" role="tab">账号&服务</a>
+							<a class="list-group-item" data-toggle="tab" href="#category-2" aria-controls="category-2" role="tab">面板相关</a>
 						</div>
 					</div>
 				</div>
@@ -36,45 +33,33 @@
 					<div class="panel-body">
 						<div class="tab-content">
 							<div class="tab-pane animation-fade active" id="category-1" role="tabpanel">
-								<div class="panel-group panel-group-simple panel-group-continuous" id="accordion1"
-								     aria-multiselectable="true" role="tablist">
-									<div class="panel" role="tabpanel">
+								<div class="panel-group panel-group-simple panel-group-continuous" id="accordion1" aria-multiselectable="true" role="tablist">
+									<div class="panel">
 										<div class="panel-heading" id="question-1" role="tab">
-											<a class="panel-title cyan0-60" aria-controls="answer-1"
-											   aria-expanded="true" data-toggle="collapse" href="#answer-1"
-											   data-parent="#accordion1"><i
-														class="icon wb-link"></i>{{trans('home.subscribe_link')}}
+											<a class="panel-title cyan-600" aria-controls="answer-1" aria-expanded="true" data-toggle="collapse" href="#answer-1" data-parent="#accordion1"><i class="icon wb-link" aria-hidden="true"></i>{{trans('home.subscribe_link')}}
 											</a>
 										</div>
-										<div class="panel-collapse collapse show" id="answer-1"
-										     aria-labelledby="question-1" role="tabpanel">
+										<div class="panel-collapse collapse show" id="answer-1" aria-labelledby="question-1" role="tabpanel">
 											<div class="panel-body">
 												@if($subscribe_status)
 													<div class="alert alert-warning" role="alert">
-														<button class="close" data-dismiss="alert" aria-label="Close">
-															<span aria-hidden="true">&times;</span><span
-																	class="sr-only">{{trans('home.close')}}</span></button>
+														<button class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span><span class="sr-only">{{trans('home.close')}}</span></button>
 														{{trans('home.subscribe_warning')}}
 													</div>
 													<div class="input-group">
 														<input type="text" class="form-control" value="{{$link}}"/>
 														<span class="input-group-btn btn-group" role="group">
-                                                            <button class="btn btn-outline-info"
-                                                                    onclick="exchangeSubscribe();">
+                                                            <button class="btn btn-outline-info" onclick="exchangeSubscribe();">
                                                                 <i class="icon wb-refresh" aria-hidden="true"></i>
                                                                 {{trans('home.exchange_subscribe')}}</button>
-                                                            <button class="btn btn-outline-info mt-clipboard"
-                                                                    data-clipboard-action="copy"
-                                                                    data-clipboard-text="{{$link}}">
+                                                            <button class="btn btn-outline-info mt-clipboard" data-clipboard-action="copy" data-clipboard-text="{{$link}}">
                                                                 <i class="icon wb-copy" aria-hidden="true"></i>
                                                                 {{trans('home.copy_subscribe_address')}}</button>
                                                         </span>
 													</div>
 												@else
-													<div class="alert alert-danger" role="alert">
-														<button class="close" data-dismiss="alert" aria-label="Close">
-															<span aria-hidden="true">&times;</span><span
-																	class="sr-only">{{trans('home.close')}}</span></button>
+													<div class="alert alert-danger alert-dismissible" role="alert">
+														<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
 														{{trans('home.subscribe_baned')}}
 													</div>
 												@endif
@@ -83,51 +68,36 @@
 									</div>
 									<div class="panel">
 										<div class="panel-heading" id="question-2" role="tab">
-											<a class="panel-title cyan0-60" aria-controls="answer-2"
-											   aria-expanded="true" data-toggle="collapse" href="#answer-2"
-											   data-parent="#accordion1"><i
-														class="icon wb-extension"></i>{{trans('home.subscribe_help')}}
+											<a class="panel-title" aria-controls="answer-2" aria-expanded="true" data-toggle="collapse" href="#answer-2" data-parent="#accordion1"><i class="icon md-help-outline" aria-hidden="true"></i>客户端 下载与使用教程
 											</a>
 										</div>
-										<div class="panel-collapse collapse show" id="answer-2"
-										     aria-labelledby="question-2" role="tabpanel">
+										<div class="panel-collapse collapse show" id="answer-2" aria-labelledby="question-2" role="tabpanel">
 											<div class="panel-body">
 												<div class="nav-tabs-horizontal" data-plugin="tabs">
 													<ul class="nav nav-tabs nav-tabs-line mr-25" role="tablist">
 														<li class="nav-item" role="presentation">
-															<a class="nav-link active" data-toggle="tab" href="#tab_1"
-															   aria-controls="tab_1" role="tab" aria-expanded="true">
+															<a class="nav-link active" data-toggle="tab" href="#tab_1" aria-controls="tab_1" role="tab" aria-expanded="true">
 																<i class="icon fa-android" aria-hidden="true"></i>Android</a>
 														</li>
 														<li class="nav-item" role="presentation">
-															<a class="nav-link" data-toggle="tab" href="#tab_2"
-															   aria-controls="tab_2" role="tab">
-																<i class="icon fa-apple"
-																   aria-hidden="true"></i>iOS-小火箭<span
-																		class="badge badge-danger up">推荐</span></a>
+															<a class="nav-link" data-toggle="tab" href="#tab_2" aria-controls="tab_2" role="tab">
+																<i class="icon fa-apple" aria-hidden="true"></i>iOS-小火箭<span class="badge badge-danger up">推荐</span></a>
 														</li>
 														<li class="nav-item" role="presentation">
-															<a class="nav-link" data-toggle="tab" href="#tab_3"
-															   aria-controls="tab_3" role="tab">
+															<a class="nav-link" data-toggle="tab" href="#tab_3" aria-controls="tab_3" role="tab">
 																<i class="icon fa-windows" aria-hidden="true"></i>Windows</a>
 														</li>
 														<li class="nav-item" role="presentation">
-															<a class="nav-link" data-toggle="tab" href="#tab_4"
-															   aria-controls="tab_4" role="tab">
-																<i class="icon fa-windows" aria-hidden="true"></i>Windows<span
-																		class="badge badge-info up">游戏</span></a>
+															<a class="nav-link" data-toggle="tab" href="#tab_4" aria-controls="tab_4" role="tab">
+																<i class="icon fa-windows" aria-hidden="true"></i>Windows<span class="badge badge-info up">游戏</span></a>
 														</li>
 														<li class="nav-item" role="presentation">
-															<a class="nav-link" data-toggle="tab" href="#tab_5"
-															   aria-controls="tab_5" role="tab">
-																<i class="icon fa-apple"
-																   aria-hidden="true"></i>MacOS</a>
+															<a class="nav-link" data-toggle="tab" href="#tab_5" aria-controls="tab_5" role="tab">
+																<i class="icon fa-apple" aria-hidden="true"></i>MacOS</a>
 														</li>
 														<li class="nav-item" role="presentation">
-															<a class="nav-link" data-toggle="tab" href="#tab_6"
-															   aria-controls="tab_6" role="tab">
-																<i class="icon fa-apple" aria-hidden="true"></i>iOS-Quantumult<span
-																		class="badge badge-danger up">进阶</span></a>
+															<a class="nav-link" data-toggle="tab" href="#tab_6" aria-controls="tab_6" role="tab">
+																<i class="icon fa-apple" aria-hidden="true"></i>iOS-Quantumult<span class="badge badge-danger up">进阶</span></a>
 														</li>
 													</ul>
 													<div class="tab-content py-15">
@@ -348,18 +318,15 @@
 								</div>
 							</div>
 							<div class="tab-pane animation-fade" id="category-2" role="tabpanel">
-								<div class="panel-group panel-group-simple panel-group-continuous" id="accordion2"
-								     aria-multiselectable="true" role="tablist">
+								<div class="panel-group panel-group-simple panel-group-continuous" id="accordion2" aria-multiselectable="true" role="tablist">
 									<!-- Question 1 -->
 									<div class="panel">
 										<div class="panel-heading" id="question-1" role="tab">
-											<a class="panel-title" aria-controls="answer-1" aria-expanded="true"
-											   data-toggle="collapse" href="#answer-1" data-parent="#accordion2">
+											<a class="panel-title" aria-controls="answer-1" aria-expanded="true" data-toggle="collapse" href="#answer-1" data-parent="#accordion2">
 												面板菜单介绍
 											</a>
 										</div>
-										<div class="panel-collapse collapse show" id="answer-1"
-										     aria-labelledby="question-1" role="tabpanel">
+										<div class="panel-collapse collapse show" id="answer-1" aria-labelledby="question-1" role="tabpanel">
 											<div class="panel-body">
 												<button class="site-tour-trigger btn btn-outline-info">点我激活介绍功能</button>
 											</div>
@@ -370,22 +337,17 @@
 									<!-- Question 2 -->
 									<div class="panel">
 										<div class="panel-heading" id="question-2" role="tab">
-											<a class="panel-title" aria-controls="answer-2" aria-expanded="false"
-											   data-toggle="collapse" href="#answer-2" data-parent="#accordion2">
+											<a class="panel-title" aria-controls="answer-2" aria-expanded="false" data-toggle="collapse" href="#answer-2" data-parent="#accordion2">
 												我想续费/购买服务,该怎么操作?
 											</a>
 										</div>
-										<div class="panel-collapse collapse" id="answer-2" aria-labelledby="question-2"
-										     role="tabpanel">
+										<div class="panel-collapse collapse" id="answer-2" aria-labelledby="question-2" role="tabpanel">
 											<div class="panel-body">
 												<ol>
-													<li>在线支付,本支付方式支持微信,支付宝,QQ钱包。支付后即开即用。前往<a
-																href="/services">【{{trans('home.services')}}】</a>选择想要购买的套餐,在订单界面选择<code>在线支付</code>即可。
+													<li>在线支付,本支付方式支持支付宝。支付后即开即用。前往<a href="/services">【{{trans('home.services')}}】</a>选择想要购买的套餐,在订单界面选择<code>在线支付</code>即可。
 													</li>
 													<li>余额支付,本支付方法支持微信,支付宝。支付后需要等待充值到账,再购买服务。
-														,充值后等待充值到账,一般会在<code>24小时</code>内到账,到账后可以在<a
-																href="/">【{{trans('home.home')}}】</a>查看您的账号余额。 在<a
-																href="/services">【{{trans('home.services')}}】</a>选择想要购买的套餐,在订单界面选择<code>余额支付</code>即可。
+														,充值后等待充值到账,一般会在<code>24小时</code>内到账,到账后可以在<a href="/services">【{{trans('home.services')}}】</a> 页面查看您的账号余额。 在<a href="/services">【{{trans('home.services')}}】</a>选择想要购买的套餐,在订单界面选择<code>余额支付</code>即可。
 													</li>
 												</ol>
 											</div>
@@ -396,17 +358,13 @@
 									<!-- Question 3 -->
 									<div class="panel">
 										<div class="panel-heading" id="question-3" role="tab">
-											<a class="panel-title" aria-controls="answer-3" aria-expanded="false"
-											   data-toggle="collapse" href="#answer-3" data-parent="#accordion2">
+											<a class="panel-title" aria-controls="answer-3" aria-expanded="false" data-toggle="collapse" href="#answer-3" data-parent="#accordion2">
 												怎么样才能快速的联系上客服?
 											</a>
 										</div>
-										<div class="panel-collapse collapse" id="answer-3" aria-labelledby="question-3"
-										     role="tabpanel">
+										<div class="panel-collapse collapse" id="answer-3" aria-labelledby="question-3" role="tabpanel">
 											<div class="panel-body">
-												<blockquote class="blockquote custom-blockquote blockquote-warning">
-													请选择其一种方式联系客服,请勿重复发送请求!!!
-												</blockquote>
+												<blockquote class="blockquote custom-blockquote blockquote-warning">请选择其一种方式联系客服,请勿重复发送请求!!!</blockquote>
 												<ol>
 													<li>在<a href="/tickets">【{{trans('home.tickets')}}】</a>界面,创建新的工单,客服人员在上线后会在第一时刻处理。
 													</li>
@@ -417,18 +375,15 @@
 								</div>
 							</div>
 							<div class="tab-pane animation-fade" id="category-3" role="tabpanel">
-								<div class="panel-group panel-group-simple panel-group-continuous" id="accordion"
-								     aria-multiselectable="true" role="tablist">
+								<div class="panel-group panel-group-simple panel-group-continuous" id="accordion" aria-multiselectable="true" role="tablist">
 									<!-- Question 5 -->
 									<div class="panel">
 										<div class="panel-heading" id="question-5" role="tab">
-											<a class="panel-title" aria-controls="answer-5" aria-expanded="true"
-											   data-toggle="collapse" href="#answer-5" data-parent="#accordion">
+											<a class="panel-title" aria-controls="answer-5" aria-expanded="true" data-toggle="collapse" href="#answer-5" data-parent="#accordion">
 												不运行软件,就连不上网,怎么办?
 											</a>
 										</div>
-										<div class="panel-collapse collapse show" id="answer-5"
-										     aria-labelledby="question-5" role="tabpanel">
+										<div class="panel-collapse collapse show" id="answer-5" aria-labelledby="question-5" role="tabpanel">
 											<div class="panel-body">
 												<ol>
 													<li>
@@ -437,15 +392,14 @@
 													<li>
 														<ol>
 															<li>
-																键盘操作<code>Win</code> + <code>X</code>,或右击左下角开始菜单键
+																键盘操作<code>Win</code> + <code>X</code>,或右击左下角开始菜单键 (Win键看起来像 <i class="icon fa-windows" aria-hidden="true"></i> 这样)
 															</li>
 															<li>
-																按下 <code>A</code> 或者选择
+																按下 <code>A</code> 或者 手动选择
 																<code>命令提示符(管理员)/ Windows PowerShell(管理员)</code>
 															</li>
 															<li>
-																依次输入<code>Netsh winsock reset</code> 并回车,<code>netsh
-																	advfirewall reset</code> 并回车;
+																输入<code>Netsh winsock reset</code> 后回车,再输入 <code>netsh advfirewall reset</code> 后回车;
 															</li>
 														</ol>
 													</li>
@@ -458,26 +412,20 @@
 									<!-- Question 6 -->
 									<div class="panel">
 										<div class="panel-heading" id="question-6" role="tab">
-											<a class="panel-title" aria-controls="answer-6" aria-expanded="false"
-											   data-toggle="collapse" href="#answer-6" data-parent="#accordion">
+											<a class="panel-title" aria-controls="answer-6" aria-expanded="false" data-toggle="collapse" href="#answer-6" data-parent="#accordion">
 												为什么我的账号状态显示是<span class="red-700">禁用</span>?
 											</a>
 										</div>
-										<div class="panel-collapse collapse" id="answer-6" aria-labelledby="question-6"
-										     role="tabpanel">
+										<div class="panel-collapse collapse" id="answer-6" aria-labelledby="question-6" role="tabpanel">
 											<div class="panel-body">
 												账号在2种情况下会显示禁用;
 												<ol>
 													<li>
-														套餐过期/流量枯竭;此情况您需要重新<a
-																href="/services">【{{trans('home.services')}}】</a>;
+														套餐过期/流量枯竭;此情况您需要重新<a href="/services">【{{trans('home.services')}}】</a>;
 													</li>
 													<li>
 														近期流量使用异常;在<code>1小时</code>内使用流量超过
-														<code>{{\App\Components\Helpers::systemConfig()['traffic_ban_value']}}
-															GB</code>
-														,即会触发本站的流量异常保护;保护时长为<code>{{\App\Components\Helpers::systemConfig()['traffic_ban_time']}}
-															分钟</code>
+														<code>{{\App\Components\Helpers::systemConfig()['traffic_ban_value']}}GB</code> ,即会触发本站的流量异常保护;保护时长为<code>{{\App\Components\Helpers::systemConfig()['traffic_ban_time']}}分钟</code>
 													</li>
 												</ol>
 												如您对禁用情况有疑问,可以创建<a href="/tickets">【{{trans('home.tickets')}}】</a>,联系售后人员。
@@ -489,22 +437,25 @@
 									<!-- Question 7 -->
 									<div class="panel">
 										<div class="panel-heading" id="question-7" role="tab">
-											<a class="panel-title" aria-controls="answer-7" aria-expanded="false"
-											   data-toggle="collapse" href="#answer-7" data-parent="#accordion">
+											<a class="panel-title" aria-controls="answer-7" aria-expanded="false" data-toggle="collapse" href="#answer-7" data-parent="#accordion">
 												为什么我的订阅链接被禁用了?
 											</a>
 										</div>
-										<div class="panel-collapse collapse" id="answer-7" aria-labelledby="question-7"
-										     role="tabpanel">
+										<div class="panel-collapse collapse" id="answer-7" aria-labelledby="question-7" role="tabpanel">
 											<div class="panel-body">
-												订阅地址对于账号来说非常重要。所以本站对此设置了严格的限制措施,以防止用户无意间泄露给他人后,还有补救机会
+												订阅地址对于账号来说非常重要。所以本站对此设置了严格的限制措施,以防止用户无意间泄露给他人后,无法挽回
 												<p>限制为:
-													<code>24小时</code>内,订阅地址只允许请求<code>{{\App\Components\Helpers::systemConfig()['subscribe_ban_times']}}
-														次</code>
+													<code>24小时</code>内,订阅地址只允许请求<code>{{\App\Components\Helpers::systemConfig()['subscribe_ban_times']}}次</code>
 												</p>
 												<p>解封,请在过一段时间并确定无误后,创建<a href="/tickets">【{{trans('home.tickets')}}】</a>,联系售后人员
 												</p>
-												<p>小知识:如果您无意间的截图忘记将订阅地址打码了,您可以在首页自行更换订阅地址!</p>
+												<p>小知识:如果您无意间的截图忘记将订阅地址打码了,您可以
+													<button class="btn btn-sm btn-outline-info" onclick="exchangeSubscribe();">
+														<i class="icon wb-refresh" aria-hidden="true"></i>
+														点这里
+													</button>
+													更换链接
+												</p>
 											</div>
 										</div>
 									</div>
@@ -521,7 +472,6 @@
 
 @endsection
 @section('script')
-	<script src="/assets/custom/tour.js" type="text/javascript"></script>
 	<script src="/assets/custom/Plugin/clipboardjs/clipboard.min.js" type="text/javascript"></script>
 	<script src="/assets/global/js/Plugin/responsive-tabs.js" type="text/javascript"></script>
 	<script src="/assets/global/js/Plugin/tabs.js" type="text/javascript"></script>

+ 14 - 14
resources/views/user/index.blade.php

@@ -42,7 +42,7 @@
 								<i class="wb-close red-400 font-size-40 mr-10"></i>
 								<span class="font-size-40 font-weight-100">{{trans('home.disabled')}}</span>
 								<p class="font-weight-300 m-0 red-500">{{trans('home.reason_traffic_exhausted')}}</p>
-							@elseif($isTrafficWarning || $banTime != 0)
+							@elseif($isTrafficWarning || $banedTime != 0)
 								<i class="wb-alert orange-400 font-size-40 mr-10"></i>
 								<span class="font-size-40 font-weight-100">{{trans('home.limited')}}</span>
 								<p class="font-weight-300 m-0 orange-500">{!!trans('home.reason_overused', ['data'=>\App\Components\Helpers::systemConfig()['traffic_ban_value']])!!}</p>
@@ -143,8 +143,7 @@
 									<h4 class="card-title"><i class="wb-bell mr-10 yellow-600"></i>交流群</h4>
 								@endif
 								@if($not_paying_user)
-									<p class="card-link btn btn-outline btn-primary">
-										<i class="wb-lock mr-5"></i>购买套餐后解锁 用户交流群信息</p>
+									<p class="card-link btn btn-sm btn-primary"><i class="wb-lock mr-5"></i>购买服务后解锁</p>
 								@else
 									<div class="btn-group">
 										<a class="card-link btn btn-sm btn-pill-left btn-info" href="https://jq.qq.com/?_wv=1027&k=52AI188" target="_blank" rel="noopener">
@@ -156,20 +155,21 @@
 							</div>
 						</div>
 					</div>
+					<!--
 					<div class="col-xl-4 col-lg-6 pb-30">
-						{{--                        <div class="card card-shadow">--}}
-						{{--                            <div class="card-block p-20">--}}
-						{{--                                <h4 class="card-title"><i class="wb-info-circle blue-600 mr-10"></i>账号信息</h4>--}}
-						{{--                                <!--  TO Do--}}
-						{{--                                 添加 权限 信息--}}
-						{{--                                 添加 账号 总流量 信息--}}
-						{{--                                 -->--}}
-						{{--                            </div>--}}
-						{{--                        </div>--}}
+						<div class="card card-shadow">
+							<div class="card-block p-20">
+								<h4 class="card-title"><i class="wb-info-circle blue-600 mr-10"></i>账号信息</h4>
+								  TO Do
+								 添加 权限 信息
+								 添加 账号 总流量 信息
+							</div>
+						</div>
 					</div>
+					-->
 				</div>
 				<div class="row" data-plugin="matchHeight" data-by-row="true">
-					<div class="col-xxl-6">
+					<div class="col-xxl-6 mb-35">
 						<div class="panel panel-info panel-line h-full">
 							<div class="panel-heading">
 								<h2 class="panel-title"><i class="wb-volume-high mr-10"></i>{{trans('home.announcement')}}
@@ -371,7 +371,7 @@
             const distance = countDownDate - new Date().getTime();
             const minutes = Math.floor((distance % 3600000) / 60000);
             const seconds = Math.floor((distance % 60000) / 1000);
-            document.getElementById("countdown").innerHTML = hours + "时 " + minutes + "分 " + seconds + "秒";
+            document.getElementById("countdown").innerHTML = minutes + "分 " + seconds + "秒";
             if (distance <= 0) {
                 clearInterval(x);
                 window.location.reload();

+ 23 - 16
resources/views/user/invite.blade.php

@@ -49,23 +49,13 @@
 										<tr>
 											<td> {{$loop->iteration}} </td>
 											<td>
-												<a href="/register?aff={{Auth::user()->id}}&code={{$invite->code}}" target="_blank">{{$invite->code}}</a>
+												<a href="javascript:void(0)" class="mt-clipboard" data-clipboard-action="copy" data-clipboard-text="{{url('/register?aff='.Auth::user()->id.'&code='.$invite->code)}}">{{$invite->code}}</a>
 											</td>
 											<td> {{$invite->dateline}} </td>
 											<td>
-												@if($invite->status == '0')
-													<span class="badge badge-success">{{trans('home.invite_code_table_status_un')}}</span>
-												@elseif($invite->status == '1')
-													<span class="badge badge-danger">{{trans('home.invite_code_table_status_yes')}}</span>
-												@else
-													<span class="badge badge-default">{{trans('home.invite_code_table_status_expire')}}</span>
-												@endif
+												{!!$invite->$status_label!!}
 											</td>
-											@if($invite->status == '1')
-												<td> {{empty($invite->user) ? ($invite->status == 1 ? '【账号已删除】' : '') : $invite->user->username}} </td>
-											@else
-												<td></td>
-											@endif
+											{{$invite->status == 1 ? (empty($invite->user) ? '【账号已删除】' : $invite->user->username) : ''}}
 										</tr>
 									@endforeach
 								@endif
@@ -91,18 +81,17 @@
 	</div>
 @endsection
 @section('script')
+	<script src="/assets/custom/Plugin/clipboardjs/clipboard.min.js" type="text/javascript"></script>
 	<script src="/assets/global/vendor/bootstrap-table/bootstrap-table.min.js" type="text/javascript"></script>
 	<script src="/assets/global/vendor/bootstrap-table/extensions/mobile/bootstrap-table-mobile.min.js" type="text/javascript"></script>
 	<script type="text/javascript">
         // 生成邀请码
         function makeInvite() {
-            const _token = '{{csrf_token()}}';
-
             $.ajax({
                 type: "POST",
                 url: "/makeInvite",
                 async: false,
-                data: {_token: _token},
+                data: {_token: '{{csrf_token()}}'},
                 dataType: 'json',
                 success: function (ret) {
                     swal.fire({title: ret.message, type: 'success', timer: 1000})
@@ -115,5 +104,23 @@
             });
             return false;
         }
+
+        const clipboard = new ClipboardJS('.mt-clipboard');
+        clipboard.on('success', function () {
+            swal.fire({
+                title: '复制成功',
+                type: 'success',
+                timer: 1300,
+                showConfirmButton: false
+            });
+        });
+        clipboard.on('error', function () {
+            swal.fire({
+                title: '复制失败,请手动复制',
+                type: 'error',
+                timer: 1500,
+                showConfirmButton: false
+            });
+        });
 	</script>
 @endsection

+ 1 - 1
resources/views/user/invoiceDetail.blade.php

@@ -9,7 +9,7 @@
 				<div class="row">
 					<div class="col-lg-3">
 						<h3>
-							<img src="{{\App\Components\Helpers::systemConfig()['website_logo']?\App\Components\Helpers::systemConfig()['website_logo']:'/assets/images/logo64.png'}}" class="navbar-brand-logo" alt="logo">
+							<img src="{{\App\Components\Helpers::systemConfig()['website_logo']? :'/assets/images/logo64.png'}}" class="navbar-brand-logo" alt="logo">
 							{{\App\Components\Helpers::systemConfig()['website_name']}}
 						</h3>
 					</div>

+ 2 - 7
resources/views/user/layouts.blade.php

@@ -24,7 +24,6 @@
 	<!-- 插件/Plugins -->
 	<link href="/assets/global/vendor/animsition/animsition.min.css" type="text/css" rel="stylesheet">
 	<link href="/assets/global/vendor/asscrollable/asScrollable.min.css" type="text/css" rel="stylesheet">
-	<link href="/assets/global/vendor/intro-js/introjs.min.css" type="text/css" rel="stylesheet">
 	<link href="/assets/global/vendor/slidepanel/slidePanel.min.css" type="text/css" rel="stylesheet">
 	<link href="/assets/global/vendor/flag-icon-css/flag-icon.min.css" type="text/css" rel="stylesheet">
 	@yield('css')
@@ -32,7 +31,6 @@
 
 	<!-- 字体/Fonts -->
 	<link href="/assets/global/fonts/web-icons/web-icons.min.css" type="text/css" rel="stylesheet">
-	<link href="/assets/global/fonts/brand-icons/brand-icons.min.css" type="text/css" rel="stylesheet">
 	<link href="//fonts.loli.net/css?family=Roboto:300,400,500,300italic" type="text/css" rel="stylesheet">
 	<!--[if lt IE 9]>
 	<script src="/assets/global/vendor/html5shiv/html5shiv.min.js" type="text/javascript"></script>
@@ -59,7 +57,7 @@
 			<i class="icon wb-more-horizontal" aria-hidden="true"></i>
 		</button>
 		<div class="navbar-brand navbar-brand-center">
-			<img src="{{\App\Components\Helpers::systemConfig()['website_logo']?\App\Components\Helpers::systemConfig()['website_logo']:'/assets/images/logo64.png'}}" class="navbar-brand-logo" alt="logo"/>
+			<img src="{{\App\Components\Helpers::systemConfig()['website_logo']? :'/assets/images/logo64.png'}}" class="navbar-brand-logo" alt="logo"/>
 			<span class="navbar-brand-text hidden-xs-down"> {{\App\Components\Helpers::systemConfig()['website_name']}}</span>
 		</div>
 	</div>
@@ -233,7 +231,6 @@
 <script src="/assets/global/vendor/ashoverscroll/jquery-asHoverScroll.min.js" type="text/javascript"></script>
 
 <!-- 插件/Plugins -->
-<script src="/assets/global/vendor/intro-js/intro.min.js" type="text/javascript"></script>
 <script src="/assets/global/vendor/screenfull/screenfull.js" type="text/javascript"></script>
 <script src="/assets/global/vendor/slidepanel/jquery-slidePanel.min.js" type="text/javascript"></script>
 <!--[if lt IE 11]>
@@ -279,9 +276,7 @@
             $.ajax({
                 'type': "POST",
                 'url': "/switchToAdmin",
-                'data': {
-                    '_token': "{{csrf_token()}}"
-                },
+                'data': {'_token': '{{csrf_token()}}'},
                 'dataType': "json",
                 success: function (ret) {
                     swal.fire({

+ 2 - 2
resources/views/user/nodeList.blade.php

@@ -1,8 +1,8 @@
 @extends('user.layouts')
 @section('css')
 	<script src="//at.alicdn.com/t/font_682457_e6aq10jsbq0yhkt9.js" type="text/javascript"></script>
-	<link href="/assets/global/fonts/font-awesome/font-awesome.css" type="text/css" rel="stylesheet">
-	<link href="/assets/global/vendor/webui-popover/webui-popover.css" type="text/css" rel="stylesheet">
+	<link href="/assets/global/fonts/font-awesome/font-awesome.min.css" type="text/css" rel="stylesheet">
+	<link href="/assets/global/vendor/webui-popover/webui-popover.min.css" type="text/css" rel="stylesheet">
 @endsection
 @section('content')
 	<!-- BEGIN CONTENT BODY -->

+ 3 - 3
resources/views/user/profile.blade.php

@@ -52,7 +52,7 @@
 									<div class="form-group row">
 										<label for="old_password" class="col-md-2 col-form-label">{{trans('home.current_password')}}</label>
 										<input type="password" class="form-control col-md-5 round" name="old_password" id="old_password" autofocus required/>
-										<input type="hidden" name="_token" value="{{csrf_token()}}"/>
+										{{csrf_field()}}
 									</div>
 									<div class="form-group row">
 										<label for="new_password" class="col-md-2  col-form-label">{{trans('home.new_password')}}</label>
@@ -68,7 +68,7 @@
 									<div class="form-group row">
 										<label for="wechat" class="col-md-2 col-form-label">{{trans('home.wechat')}}</label>
 										<input type="text" class="form-control col-md-5 round" name="wechat" id="wechat" value="{{Auth::user()->wechat}}" required/>
-										<input type="hidden" name="_token" value="{{csrf_token()}}"/>
+										{{csrf_field()}}
 									</div>
 									<div class="form-group row">
 										<label for="qq" class="col-md-2 col-form-label">QQ</label>
@@ -84,7 +84,7 @@
 									<div class="form-group row">
 										<label for="passwd" class="col-md-2 col-form-label"> {{trans('home.connection_password')}} </label>
 										<input type="text" class="form-control col-md-5 round" name="passwd" id="passwd" value="{{Auth::user()->passwd}}" required/>
-										<input type="hidden" name="_token" value="{{csrf_token()}}"/>
+										{{csrf_field()}}
 									</div>
 									<div class="form-actions">
 										<button type="submit" class="btn btn-info"> {{trans('home.submit')}} </button>

Some files were not shown because too many files changed in this diff