Browse Source

2.3 版本 功能添加与优化

加入新支付方式 PayJS ← 未实装,后续版本实装。目前本人还卡在他们的账号注册上面,没法测试代码o(╥﹏╥)o
用户注册等地方添加新字段: 昵称; 用于后续邮件,页面显示;还需要更多优化与应用;
用户头像获取与昵称获取; 前提是用户有填写QQ信息或者注册邮箱为正常的QQ邮箱;
添加 维护模式; 模式开启后,用户界面将自动导到维护界面,管理后台正常运行。哀悼日网站可以添加大厂一样的哀悼维护了 3.1 维护模式定时关闭功能; 3.2 维护模式自定义提示语;
Ping检测与定时记录; 4.1 添加Ping记录界面; 4.2 节点界面添加检测独立Ping按钮; 4.3 针对用户界面添加Ping参考信息;
余额充值自定义功能
部分界面js显示优化
模块化页面;
兔姬桑 5 years ago
parent
commit
0e2e5f61dd
100 changed files with 2021 additions and 1314 deletions
  1. 125 114
      app/Components/Callback.php
  2. 4 3
      app/Components/Helpers.php
  3. 31 0
      app/Components/NetworkDetection.php
  4. 68 0
      app/Components/QQInfo.php
  5. 9 0
      app/Console/Commands/AutoJob.php
  6. 57 0
      app/Console/Commands/AutoPingNode.php
  7. 1 1
      app/Console/Commands/DailyJob.php
  8. 5 5
      app/Console/Commands/UserExpireAutoWarning.php
  9. 1 1
      app/Console/Commands/UserTrafficAbnormalAutoWarning.php
  10. 3 3
      app/Console/Commands/UserTrafficAutoWarning.php
  11. 77 0
      app/Console/Commands/updateUserName.php
  12. 1 1
      app/Console/Commands/upgradeUserResetTime.php
  13. 3 0
      app/Console/Kernel.php
  14. 94 52
      app/Http/Controllers/AdminController.php
  15. 3 3
      app/Http/Controllers/Api/LoginController.php
  16. 58 0
      app/Http/Controllers/Api/PayJsController.php
  17. 61 56
      app/Http/Controllers/AuthController.php
  18. 96 57
      app/Http/Controllers/PaymentController.php
  19. 6 6
      app/Http/Controllers/SubscribeController.php
  20. 8 8
      app/Http/Controllers/TicketController.php
  21. 24 23
      app/Http/Controllers/UserController.php
  22. 4 0
      app/Http/Kernel.php
  23. 26 0
      app/Http/Middleware/isAdminlogin.php
  24. 27 0
      app/Http/Middleware/isMaintenance.php
  25. 46 0
      app/Http/Models/SsNodePing.php
  26. 2 0
      app/Http/Models/User.php
  27. 2 1
      app/Http/Models/VerifyCode.php
  28. 3 2
      composer.json
  29. 178 178
      composer.lock
  30. 3 1
      resources/lang/en/auth.php
  31. 2 2
      resources/lang/en/home.php
  32. 30 30
      resources/lang/ja/auth.php
  33. 2 2
      resources/lang/ja/home.php
  34. 28 28
      resources/lang/ko/auth.php
  35. 2 2
      resources/lang/ko/home.php
  36. 3 1
      resources/lang/zh-CN/auth.php
  37. 2 2
      resources/lang/zh-CN/home.php
  38. 3 2
      resources/lang/zh-tw/auth.php
  39. 3 3
      resources/lang/zh-tw/home.php
  40. 3 3
      resources/views/admin/addUser.blade.php
  41. 2 2
      resources/views/admin/applyDetail.blade.php
  42. 3 3
      resources/views/admin/applyList.blade.php
  43. 10 3
      resources/views/admin/editUser.blade.php
  44. 2 2
      resources/views/admin/emailLog.blade.php
  45. 1 1
      resources/views/admin/export.blade.php
  46. 2 2
      resources/views/admin/inviteList.blade.php
  47. 16 1
      resources/views/admin/layouts.blade.php
  48. 59 38
      resources/views/admin/nodeList.blade.php
  49. 84 0
      resources/views/admin/nodePingLog.blade.php
  50. 3 3
      resources/views/admin/onlineIPMonitor.blade.php
  51. 3 3
      resources/views/admin/orderList.blade.php
  52. 31 0
      resources/views/admin/system.blade.php
  53. 3 3
      resources/views/admin/trafficLog.blade.php
  54. 3 3
      resources/views/admin/userBalanceLogList.blade.php
  55. 4 4
      resources/views/admin/userBanLogList.blade.php
  56. 9 9
      resources/views/admin/userList.blade.php
  57. 1 1
      resources/views/admin/userMonitor.blade.php
  58. 3 3
      resources/views/admin/userOnlineIPList.blade.php
  59. 5 5
      resources/views/admin/userRebateList.blade.php
  60. 3 3
      resources/views/admin/userTrafficLogList.blade.php
  61. 2 2
      resources/views/auth/activeUser.blade.php
  62. 1 2
      resources/views/auth/layouts.blade.php
  63. 2 2
      resources/views/auth/login.blade.php
  64. 122 0
      resources/views/auth/maintenance.blade.php
  65. 40 248
      resources/views/auth/register.blade.php
  66. 2 2
      resources/views/auth/resetPassword.blade.php
  67. 1 0
      resources/views/docs/aup.blade.php
  68. 1 0
      resources/views/docs/tos.blade.php
  69. 24 15
      resources/views/payment/detail.blade.php
  70. 21 32
      resources/views/shop/addGoods.blade.php
  71. 79 89
      resources/views/shop/editGoods.blade.php
  72. 1 2
      resources/views/shop/goodsList.blade.php
  73. 3 3
      resources/views/subscribe/subscribeList.blade.php
  74. 1 1
      resources/views/subscribe/subscribeLog.blade.php
  75. 2 2
      resources/views/ticket/addTicket.blade.php
  76. 17 5
      resources/views/ticket/replyTicket.blade.php
  77. 3 3
      resources/views/ticket/ticketList.blade.php
  78. 20 38
      resources/views/user/buy.blade.php
  79. 7 0
      resources/views/user/components/avatar.blade.php
  80. 7 0
      resources/views/user/components/help/clients/android.blade.php
  81. 7 0
      resources/views/user/components/help/clients/game.blade.php
  82. 8 0
      resources/views/user/components/help/clients/ios.blade.php
  83. 5 0
      resources/views/user/components/help/clients/linux.blade.php
  84. 12 0
      resources/views/user/components/help/clients/mac.blade.php
  85. 12 0
      resources/views/user/components/help/clients/windows.blade.php
  86. 53 0
      resources/views/user/components/help/solution.blade.php
  87. 48 0
      resources/views/user/components/help/tutorial.blade.php
  88. 3 100
      resources/views/user/help.blade.php
  89. 3 2
      resources/views/user/index.blade.php
  90. 1 1
      resources/views/user/invite.blade.php
  91. 4 5
      resources/views/user/invoices.blade.php
  92. 2 2
      resources/views/user/layouts.blade.php
  93. 9 1
      resources/views/user/nodeList.blade.php
  94. 9 5
      resources/views/user/profile.blade.php
  95. 3 3
      resources/views/user/referral.blade.php
  96. 2 2
      resources/views/user/replyTicket.blade.php
  97. 98 57
      resources/views/user/services.blade.php
  98. 1 1
      routes/api.php
  99. 6 3
      routes/web.php
  100. 28 7
      sql/db.sql

+ 125 - 114
app/Components/Callback.php

@@ -35,22 +35,22 @@ trait Callback
 	private function tradePaid($msg, $pay_type)
 	{
 		$pay_type_name = $pay_type == 1? '余额支付' : ($pay_type == 4? '支付宝国际' : ($pay_type == 5? '支付宝当面付' : ''));
+		$payment = Payment::query()->with(['order', 'order.goods'])->where('status', 0)->where('order_sn', $msg['out_trade_no'])->first();
+		if(!$payment){
+			Log::info('【'.$pay_type_name.'】回调订单【'.$msg['out_trade_no'].'】不存在');
+
+			return FALSE;
+		}
 		if($pay_type != 1){
 			Log::info('【'.$pay_type_name.'】支付成功,开始处理回调订单');
 			// 获取未完成状态的订单防止重复增加时间
-			$payment = Payment::query()->with(['order', 'order.goods'])->where('status', 0)->where('order_sn', $msg['out_trade_no'])->first();
-			if(!$payment){
-				Log::info('【'.$pay_type_name.'】回调订单【'.$msg['out_trade_no'].'】不存在');
-
-				return FALSE;
-			}
 		}else{
 			Log::info('【'.$pay_type_name.'】订单处理');
 		}
 
 		// 处理订单
-		DB::beginTransaction();
 		try{
+			DB::beginTransaction();
 			if($pay_type != 1){
 				// 如果支付单中没有用户信息则创建一个用户
 				if(!$payment->user_id){
@@ -69,127 +69,138 @@ trait Callback
 
 			// 更新订单
 			$order = Order::query()->where('order_sn', $msg['out_trade_no'])->first();
-			// 提取商品信息
-			$goods = Goods::query()->where('id', $order->goods_id)->first();
-			// 取出用户信息
-			$user = User::query()->where('id', $order->user_id)->first();
-			// 商品为流量或者套餐
-			switch($goods->type){
-				case 1:
-					$order->status = 2;
-					$order->save();
-					Helpers::addUserTrafficModifyLog($order->user_id, $order->oid, $user->transfer_enable, $user->transfer_enable+$goods->traffic*1048576, '[在线支付]加上用户购买的套餐流量');
-					User::query()->where('id', $order->user_id)->increment('transfer_enable', $goods->traffic*1048576);
-					break;
-				case 2:
-					$activePlan = Order::query()
-						->where('user_id', $order->user_id)
-						->with(['goods'])
-						->whereHas('goods', function($q){
-							$q->where('type', 2);
-						})
-						->where('is_expire', 0)
-						->where('status', 2)
-						->exists();
-					// 2为开始生效,3为预支付
-					$order->status = $activePlan? 3 : 2;
-					$order->save();
-					// 预支付不执行
-					if(!$activePlan){
-						// 如果买的是套餐,则先将之前购买的套餐都无效化,重置用户已用、可用流量为0
-						Order::query()
+
+			if($order->goods_id == -1){
+				$order->status = 2;
+				$order->save();
+				User::query()->where('id', $order->user_id)->increment('balance', $order->amount*100);
+
+				// 余额变动记录日志
+				$this->addUserBalanceLog($order->user_id, $order->oid, $order->user->balance, $order->user->balance+$order->amount, $order->amount, '用户在线充值');
+			}else{
+
+				// 提取商品信息
+				$goods = Goods::query()->where('id', $order->goods_id)->first();
+				// 取出用户信息
+				$user = User::query()->where('id', $order->user_id)->first();
+				// 商品为流量或者套餐
+				switch($goods->type){
+					case 1:
+						$order->status = 2;
+						$order->save();
+						Helpers::addUserTrafficModifyLog($order->user_id, $order->oid, $user->transfer_enable, $user->transfer_enable+$goods->traffic*1048576, '[在线支付]加上用户购买的套餐流量');
+						User::query()->where('id', $order->user_id)->increment('transfer_enable', $goods->traffic*1048576);
+						break;
+					case 2:
+						$activePlan = Order::query()
 							->where('user_id', $order->user_id)
 							->with(['goods'])
 							->whereHas('goods', function($q){
-								$q->where('type', '<=', 2);
+								$q->where('type', 2);
 							})
 							->where('is_expire', 0)
 							->where('status', 2)
-							->where('oid', '<>', $order->oid)
-							->update(['expire_at' => date('Y-m-d H:i:s'), 'is_expire' => 1]);
-
-						Helpers::addUserTrafficModifyLog($order->user_id, $order->oid, $user->transfer_enable, 0, '[在线支付]用户购买新套餐,先清空流量');
-						User::query()->where('id', $order->user_id)->update(['u' => 0, 'd' => 0, 'transfer_enable' => 0]);
-
-						$userTraffic = $goods->traffic*1048576;
-						// 添加账号有效期
-						$expireTime = date('Y-m-d', strtotime("+".$goods->days." days"));
-						//账号下一个重置时间
-						$nextResetTime = date('Y-m-d', strtotime("+".$goods->period." days"));
-						if($nextResetTime >= $expireTime){
-							$nextResetTime = NULL;
-						}
+							->exists();
+						// 2为开始生效,3为预支付
+						$order->status = $activePlan? 3 : 2;
+						$order->save();
+						// 预支付不执行
+						if(!$activePlan){
+							// 如果买的是套餐,则先将之前购买的套餐都无效化,重置用户已用、可用流量为0
+							Order::query()
+								->where('user_id', $order->user_id)
+								->with(['goods'])
+								->whereHas('goods', function($q){
+									$q->where('type', '<=', 2);
+								})
+								->where('is_expire', 0)
+								->where('status', 2)
+								->where('oid', '<>', $order->oid)
+								->update(['expire_at' => date('Y-m-d H:i:s'), 'is_expire' => 1]);
 
-						// 写入用户标签
-						if($goods->label){
-							// 删除用户所有标签
-							UserLabel::query()->where('user_id', $order->user_id)->delete();
+							Helpers::addUserTrafficModifyLog($order->user_id, $order->oid, $user->transfer_enable, 0, '[在线支付]用户购买新套餐,先清空流量');
+							User::query()->where('id', $order->user_id)->update(['u' => 0, 'd' => 0, 'transfer_enable' => 0]);
+
+							$userTraffic = $goods->traffic*1048576;
+							// 添加账号有效期
+							$expireTime = date('Y-m-d', strtotime("+".$goods->days." days"));
+							//账号下一个重置时间
+							$nextResetTime = date('Y-m-d', strtotime("+".$goods->period." days"));
+							if($nextResetTime >= $expireTime){
+								$nextResetTime = NULL;
+							}
 
-							//取出 商品默认标签  & 系统默认标签 去重
-							$newUserLabels = array_values(array_unique(array_merge(GoodsLabel::query()->where('goods_id', $order->goods_id)->pluck('label_id')->toArray(), self::$systemConfig['initial_labels_for_user']? explode(',', self::$systemConfig['initial_labels_for_user']) : [])));
+							// 写入用户标签
+							if($goods->label){
+								// 删除用户所有标签
+								UserLabel::query()->where('user_id', $order->user_id)->delete();
 
-							// 生成标签
-							foreach($newUserLabels as $vo){
-								$obj = new UserLabel();
-								$obj->user_id = $order->user_id;
-								$obj->label_id = $vo;
-								$obj->save();
+								//取出 商品默认标签  & 系统默认标签 去重
+								$newUserLabels = array_values(array_unique(array_merge(GoodsLabel::query()->where('goods_id', $order->goods_id)->pluck('label_id')->toArray(), self::$systemConfig['initial_labels_for_user']? explode(',', self::$systemConfig['initial_labels_for_user']) : [])));
+
+								// 生成标签
+								foreach($newUserLabels as $vo){
+									$obj = new UserLabel();
+									$obj->user_id = $order->user_id;
+									$obj->label_id = $vo;
+									$obj->save();
+								}
 							}
-						}
 
-						// 写入返利日志
-						if($order->user->referral_uid){
-							$this->addReferralLog($order->user_id, $order->user->referral_uid, $order->oid, $order->amount, $order->amount*self::$systemConfig['referral_percent']);
-							// 邀请注册功能开启时,每成功邀请一名付费用户,返还邀请者邀请名额
-							if(self::$systemConfig['is_invite_register']){
-								User::query()->where('id', $order->user->referral_uid)->increment('invite_num', 1);
+							// 写入返利日志
+							if($order->user->referral_uid){
+								$this->addReferralLog($order->user_id, $order->user->referral_uid, $order->oid, $order->amount, $order->amount*self::$systemConfig['referral_percent']);
+								// 邀请注册功能开启时,每成功邀请一名付费用户,返还邀请者邀请名额
+								if(self::$systemConfig['is_invite_register']){
+									User::query()->where('id', $order->user->referral_uid)->increment('invite_num', 1);
+								}
 							}
+
+							Helpers::addUserTrafficModifyLog($order->user_id, $order->oid, $user->transfer_enable, $userTraffic, '[在线支付]加上用户购买的套餐流量');
+							User::query()->where('id', $order->user_id)->increment('invite_num', $goods->invite_num? : 0, ['transfer_enable' => $userTraffic, 'reset_time' => $nextResetTime, 'expire_time' => $expireTime, 'enable' => 1]);
+						}else{
+							//预支付订单先给上账号时间用于流量重置判断
+							User::query()->where('id', $order->user_id)->update(['expire_time' => date('Y-m-d', strtotime("+".$goods->days." days", strtotime($user->expire_time)))]);
 						}
+						break;
+					case 3:
+						$order->status = 2;
+						$order->save();
+						User::query()->where('id', $order->user_id)->increment('balance', $goods->price*100);
 
-						Helpers::addUserTrafficModifyLog($order->user_id, $order->oid, $user->transfer_enable, $userTraffic, '[在线支付]加上用户购买的套餐流量');
-						User::query()->where('id', $order->user_id)->increment('invite_num', $goods->invite_num? : 0, ['transfer_enable' => $userTraffic, 'reset_time' => $nextResetTime, 'expire_time' => $expireTime, 'enable' => 1]);
-					}else{
-						//预支付订单先给上账号时间用于流量重置判断
-						User::query()->where('id', $order->user_id)->update(['expire_time' => date('Y-m-d', strtotime("+".$goods->days." days", strtotime($user->expire_time)))]);
-					}
-					break;
-				case 3:
-					$order->status = 2;
-					$order->save();
-					User::query()->where('id', $order->user_id)->increment('balance', $goods->price*100);
-
-					// 余额变动记录日志
-					$this->addUserBalanceLog($order->user_id, $order->oid, $order->user->balance, $order->user->balance+$goods->price, $goods->price, '用户在线充值');
-					break;
-				default:
-					Log::info('【处理订单】出现错误-未知套餐类型');
-			}
-			// 自动提号机:如果order的email值不为空
-			if($order->email){
-				$title = '自动发送账号信息';
-				$content = [
-					'order_sn'      => $order->order_sn,
-					'goods_name'    => $order->goods->name,
-					'goods_traffic' => flowAutoShow($order->goods->traffic*1048576),
-					'port'          => $order->user->port,
-					'passwd'        => $order->user->passwd,
-					'method'        => $order->user->method,
-					//'protocol'       => $order->user->protocol,
-					//'protocol_param' => $order->user->protocol_param,
-					//'obfs'           => $order->user->obfs,
-					//'obfs_param'     => $order->user->obfs_param,
-					'created_at'    => $order->created_at->toDateTimeString(),
-					'expire_at'     => $order->expire_at
-				];
-
-				// 获取可用节点列表
-				$labels = UserLabel::query()->where('user_id', $order->user_id)->get()->pluck('label_id');
-				$nodeIds = SsNodeLabel::query()->whereIn('label_id', $labels)->get()->pluck('node_id');
-				$nodeList = SsNode::query()->whereIn('id', $nodeIds)->orderBy('sort', 'desc')->orderBy('id', 'desc')->get()->toArray();
-				$content['serverList'] = $nodeList;
-
-				$logId = Helpers::addEmailLog($order->email, $title, json_encode($content));
-				Mail::to($order->email)->send(new sendUserInfo($logId, $content));
+						// 余额变动记录日志
+						$this->addUserBalanceLog($order->user_id, $order->oid, $order->user->balance, $order->user->balance+$goods->price, $goods->price, '用户在线充值');
+						break;
+					default:
+						Log::info('【处理订单】出现错误-未知套餐类型');
+				}
+				// 自动提号机:如果order的email值不为空
+				if($order->email){
+					$title = '自动发送账号信息';
+					$content = [
+						'order_sn'      => $order->order_sn,
+						'goods_name'    => $order->goods->name,
+						'goods_traffic' => flowAutoShow($order->goods->traffic*1048576),
+						'port'          => $order->user->port,
+						'passwd'        => $order->user->passwd,
+						'method'        => $order->user->method,
+						//'protocol'       => $order->user->protocol,
+						//'protocol_param' => $order->user->protocol_param,
+						//'obfs'           => $order->user->obfs,
+						//'obfs_param'     => $order->user->obfs_param,
+						'created_at'    => $order->created_at->toDateTimeString(),
+						'expire_at'     => $order->expire_at
+					];
+
+					// 获取可用节点列表
+					$labels = UserLabel::query()->where('user_id', $order->user_id)->get()->pluck('label_id');
+					$nodeIds = SsNodeLabel::query()->whereIn('label_id', $labels)->get()->pluck('node_id');
+					$nodeList = SsNode::query()->whereIn('id', $nodeIds)->orderBy('sort', 'desc')->orderBy('id', 'desc')->get()->toArray();
+					$content['serverList'] = $nodeList;
+
+					$logId = Helpers::addEmailLog($order->email, $title, json_encode($content));
+					Mail::to($order->email)->send(new sendUserInfo($logId, $content));
+				}
 			}
 
 			DB::commit();

+ 4 - 3
app/Components/Helpers.php

@@ -60,17 +60,18 @@ class Helpers
 	/**
 	 * 添加用户
 	 *
-	 * @param string $username        用户邮箱
+	 * @param string $email           用户邮箱
 	 * @param string $password        用户密码
 	 * @param string $transfer_enable 可用流量
 	 * @param int    $data            可使用天数
 	 * @param int    $referral_uid    邀请人
 	 * @return int
 	 */
-	public static function addUser($username, $password, $transfer_enable, $data, $referral_uid = 0)
+	public static function addUser($email, $password, $transfer_enable, $data, $referral_uid = 0)
 	{
 		$user = new User();
-		$user->username = $username;
+		$user->username = $email;
+		$user->email = $email;
 		$user->password = $password;
 		// 生成一个可用端口
 		$user->port = self::systemConfig()['is_rand_port']? Helpers::getRandPort() : Helpers::getOnlyPort();

+ 31 - 0
app/Components/NetworkDetection.php

@@ -56,6 +56,37 @@ class NetworkDetection
 			return "机器宕机"; // 服务器宕机
 		}
 	}
+
+	/**
+	 * 用api.iiwl.cc进行Ping检测
+	 *
+	 * @param string $ip 被检测的IP或者域名
+	 *
+	 * @return bool|array
+	 */
+	public static function ping($ip)
+	{
+		$url = 'https://api.iiwl.cc/api/ping.php?url='.$ip;
+
+		try{
+			$ret = json_decode(Curl::send($url), TRUE);
+			if(!$ret){
+				Log::warning("【PING】检测".$ip."时,接口返回异常访问链接:".$url);
+
+				return FALSE;
+			}elseif($ret['code'] != 1 || $ret['msg'] != "检测成功!"){
+				Log::warning("【PING】检测".$ip."时,返回".json_encode($ret));
+
+				return FALSE;
+			}
+		} catch(Exception $e){
+			Log::warning("【Ping】检测".$ip."时,接口请求超时".$e);
+
+			return FALSE;
+		}
+
+		return $ret['data']; // 服务器宕机
+	}
 }
 
 ?>

+ 68 - 0
app/Components/QQInfo.php

@@ -0,0 +1,68 @@
+<?php
+
+namespace App\Components;
+
+class QQInfo
+{
+	/**
+	 * 通过QQ号查询头像与昵称信息
+	 *
+	 * @param string $qq QQ号
+	 *
+	 * @return string
+	 */
+	public static function getName($qq)
+	{
+
+		//向接口发起请求获取json数据
+		$url = 'https://r.qzone.qq.com/fcg-bin/cgi_get_portrait.fcg?get_nick=1&uins='.$qq;
+		$ret = mb_convert_encoding(Curl::send($url), "UTF-8", "GBK");
+		// 接口是否异常
+		//echo $ret;
+		if(strpos($ret, $qq) !== FALSE){
+			//对获取的json数据进行截取并解析成数组
+			$ret = json_decode(substr($ret, 17, -1), TRUE);
+
+			return stripslashes($ret[$qq][6]);
+		}
+
+		echo $qq.PHP_EOL;
+
+		return FALSE;
+	}
+
+	public static function getName2($qq)
+	{
+
+		//向接口发起请求获取json数据
+		$url = 'https://api.toubiec.cn/qq?qq='.$qq.'&size=100';
+		$ret = json_decode(Curl::send($url), TRUE);
+		// 接口是否异常
+		if($ret){
+			if($ret['code'] == 200){
+				return $ret['name'];
+			}
+		}
+
+		echo $qq.PHP_EOL;
+
+		return FALSE;
+	}
+
+	public static function getName3($qq)
+	{
+		//向接口发起请求获取json数据
+		$url = 'https://api.unipay.qq.com/v1/r/1450000186/wechat_query?cmd=1&pf=mds_storeopen_qb-__mds_qqclub_tab_-html5&pfkey=pfkey&from_h5=1&from_https=1&openid=openid&openkey=openkey&session_id=hy_gameid&session_type=st_dummy&qq_appid=&offerId=1450000186&sandbox=&provide_uin='.$qq;
+		$ret = json_decode(Curl::send($url), TRUE);
+		// 接口是否异常
+		if($ret){
+			if($ret['ret'] == 0){
+				return urldecode($ret['nick']);
+			}
+		}
+
+		echo $qq.PHP_EOL;
+
+		return FALSE;
+	}
+}

+ 9 - 0
app/Console/Commands/AutoJob.php

@@ -4,6 +4,7 @@ namespace App\Console\Commands;
 
 use App\Components\Helpers;
 use App\Components\ServerChan;
+use App\Http\Models\Config;
 use App\Http\Models\Coupon;
 use App\Http\Models\Invite;
 use App\Http\Models\Order;
@@ -61,6 +62,14 @@ class AutoJob extends Command
 		// 检测节点是否离线
 		$this->checkNodeStatus();
 
+		// 检查 维护模式
+		if(Helpers::systemConfig()['maintenance_mode']){
+			if(strtotime(Helpers::systemConfig()['maintenance_time']) < time()){
+				Config::query()->where('name', 'maintenance_mode')->update(['value' => 0]);
+				Config::query()->where('name', 'maintenance_time')->update(['value' => '']);
+			}
+		}
+
 		$jobEndTime = microtime(TRUE);
 		$jobUsedTime = round(($jobEndTime-$jobStartTime), 4);
 

+ 57 - 0
app/Console/Commands/AutoPingNode.php

@@ -0,0 +1,57 @@
+<?php
+
+namespace App\Console\Commands;
+
+use App\Components\Helpers;
+use App\Components\NetworkDetection;
+use App\Http\Models\SsNode;
+use App\Http\Models\SsNodePing;
+use Illuminate\Console\Command;
+use Log;
+
+class AutoPingNode extends Command
+{
+	private static $systemConfig;
+	protected $signature = 'autoPingNode';
+	protected $description = '节点定时Ping测速';
+
+	public function __construct()
+	{
+		parent::__construct();
+		self::$systemConfig = Helpers::systemConfig();
+	}
+
+	public function handle()
+	{
+		$jobStartTime = microtime(TRUE);
+
+		$nodeList = SsNode::query()->where('is_transit', 0)->where('status', 1)->get();
+		foreach($nodeList as $node){
+			$this->pingNode($node->id, $node->is_ddns? $node->server : $node->ip);
+		}
+
+		$jobEndTime = microtime(TRUE);
+		$jobUsedTime = round(($jobEndTime-$jobStartTime), 4);
+
+		Log::info('---【'.$this->description.'】完成---,耗时'.$jobUsedTime.'秒');
+	}
+
+	// 节点Ping测速
+	private function pingNode($nodeId, $ip)
+	{
+		$result = NetworkDetection::ping($ip);
+
+		if($result){
+			$obj = new SsNodePing();
+			$obj->node_id = $nodeId;
+			$obj->ct = intval($result['China Telecom']['time']);
+			$obj->cu = intval($result['China Unicom']['time']);
+			$obj->cm = intval($result['China Mobile']['time']);
+			$obj->hk = intval($result['Hong Kong']['time']);
+			$obj->save();
+		}else{
+			Log::info("【".$ip."】Ping测速获取失败");
+		}
+
+	}
+}

+ 1 - 1
app/Console/Commands/DailyJob.php

@@ -165,7 +165,7 @@ class DailyJob extends Command
 			}
 			// 重置流量
 			User::query()->where('id', $user->id)->update(['u' => 0, 'd' => 0, 'transfer_enable' => $order->goods->traffic*1048576, 'reset_time' => $nextResetTime]);
-			Log::info('用户[ID:'.$user->id.'  邮箱: '.$user->username.'] 流量重置为 '.($order->goods->traffic*1048576).'. 重置日期为 '.($nextResetTime? : '【无】'));
+			Log::info('用户[ID:'.$user->id.'  昵称: '.$user->username.'  邮箱: '.$user->email.'] 流量重置为 '.($order->goods->traffic*1048576).'. 重置日期为 '.($nextResetTime? : '【无】'));
 		}
 	}
 }

+ 5 - 5
app/Console/Commands/UserExpireAutoWarning.php

@@ -43,7 +43,7 @@ class UserExpireAutoWarning extends Command
 		$userList = User::query()->where('enable', 1)->get();
 		foreach($userList as $user){
 			// 用户名不是邮箱的跳过
-			if(FALSE === filter_var($user->username, FILTER_VALIDATE_EMAIL)){
+			if(FALSE === filter_var($user->email, FILTER_VALIDATE_EMAIL)){
 				continue;
 			}
 
@@ -53,14 +53,14 @@ class UserExpireAutoWarning extends Command
 				$title = '账号过期提醒';
 				$content = '您的账号将于今天晚上【24:00】过期。';
 
-				$logId = Helpers::addEmailLog($user->username, $title, $content);
-				Mail::to($user->username)->send(new userExpireWarningToday($logId));
+				$logId = Helpers::addEmailLog($user->email, $title, $content);
+				Mail::to($user->email)->send(new userExpireWarningToday($logId));
 			}elseif($lastCanUseDays > 0 && $lastCanUseDays <= self::$systemConfig['expire_days']){
 				$title = '账号过期提醒';
 				$content = '您的账号还剩'.$lastCanUseDays.'天即将过期。';
 
-				$logId = Helpers::addEmailLog($user->username, $title, $content);
-				Mail::to($user->username)->send(new userExpireWarning($logId, $lastCanUseDays));
+				$logId = Helpers::addEmailLog($user->email, $title, $content);
+				Mail::to($user->email)->send(new userExpireWarning($logId, $lastCanUseDays));
 			}
 		}
 	}

+ 1 - 1
app/Console/Commands/UserTrafficAbnormalAutoWarning.php

@@ -49,7 +49,7 @@ class UserTrafficAbnormalAutoWarning extends Command
 				if($vo->totalTraffic > (self::$systemConfig['traffic_ban_value']*1073741824)){
 					$traffic = UserTrafficHourly::query()->where('node_id', 0)->where('user_id', $vo->user_id)->where('created_at', '>=', date('Y-m-d H:i:s', time()-3900))->selectRaw("user_id, sum(`u`) as totalU, sum(`d`) as totalD, sum(total) as totalTraffic")->first();
 
-					$content = "用户**{$user->username}(ID:{$user->id})**,最近1小时**上行流量:".flowAutoShow($traffic->totalU).",下行流量:".flowAutoShow($traffic->totalD).",共计:".flowAutoShow($traffic->totalTraffic)."**。";
+					$content = "用户**{$user->email}(ID:{$user->id})**,最近1小时**上行流量:".flowAutoShow($traffic->totalU).",下行流量:".flowAutoShow($traffic->totalD).",共计:".flowAutoShow($traffic->totalTraffic)."**。";
 
 					ServerChan::send($title, $content);
 				}

+ 3 - 3
app/Console/Commands/UserTrafficAutoWarning.php

@@ -42,7 +42,7 @@ class UserTrafficAutoWarning extends Command
 		$userList = User::query()->where('status', '>=', 0)->where('enable', 1)->where('transfer_enable', '>', 0)->get();
 		foreach($userList as $user){
 			// 用户名不是邮箱的跳过
-			if(FALSE === filter_var($user->username, FILTER_VALIDATE_EMAIL)){
+			if(FALSE === filter_var($user->email, FILTER_VALIDATE_EMAIL)){
 				continue;
 			}
 
@@ -51,8 +51,8 @@ class UserTrafficAutoWarning extends Command
 				$title = '流量提醒';
 				$content = '流量已使用:'.$usedPercent.'%,请保持关注。';
 
-				$logId = Helpers::addEmailLog($user->username, $title, $content);
-				Mail::to($user->username)->send(new userTrafficWarning($logId, $usedPercent));
+				$logId = Helpers::addEmailLog($user->email, $title, $content);
+				Mail::to($user->email)->send(new userTrafficWarning($logId, $usedPercent));
 			}
 		}
 	}

+ 77 - 0
app/Console/Commands/updateUserName.php

@@ -0,0 +1,77 @@
+<?php
+
+namespace App\Console\Commands;
+
+use App\Components\QQInfo;
+use App\Http\Models\User;
+use Illuminate\Console\Command;
+use Log;
+
+class updateUserName extends Command
+{
+	protected $signature = 'updateUserName';
+	protected $description = '升级用户昵称';
+
+	public function __construct()
+	{
+		parent::__construct();
+	}
+
+	public function handle()
+	{
+		Log::info('----------------------------【升级用户昵称】开始----------------------------');
+
+		$userList = User::query()->get();
+		foreach($userList as $user){
+			$name = process($user->id);
+			User::query()->whereKey($user->id)->update(['username' => $name]);
+
+			Log::info('---用户[ID:'.$user->id.' - '.$user->email.'] :'.$user->username.'---');
+		}
+
+		foreach($userList as $user){
+			if($user->email == $user->username){
+				$name = process($user->id);
+
+				User::query()->whereKey($user->id)->update(['username' => $name]);
+
+				Log::info('---用户[ID:'.$user->id.' - '.$user->email.'] :'.$user->username.'---');
+			}
+		}
+
+		Log::info('----------------------------【升级用户昵称】结束----------------------------');
+	}
+}
+
+function process($id)
+{
+	$user = User::query()->whereKey($id)->first();
+	// 先设个默认值
+	$name = $user->email;
+	// 用户是否设置了QQ号
+	if($user->qq){
+		$name = QQInfo::getName3($user->qq);
+		// 检测用户注册是否为QQ邮箱
+	}elseif(strpos(strtolower($user->email), '@qq') != FALSE){
+		// 分离QQ邮箱后缀
+		$email = explode('@', $user->email);
+		if(is_numeric($email[0])){
+			$name = QQInfo::getName3($email[0]);
+		}else{
+			// 分离www前缀
+			if(strpos($email[0], '.') != FALSE){
+				$temp = explode('.', $email[0]);
+				if(is_numeric($temp[1])){
+					$name = QQInfo::getName3($temp[1]);
+				}else{
+					print_r($user->email.PHP_EOL);
+				}
+			}
+		}
+	}
+	if($name == FALSE){
+		$name = $user->email;
+	}
+
+	return $name;
+}

+ 1 - 1
app/Console/Commands/upgradeUserResetTime.php

@@ -56,7 +56,7 @@ class upgradeUserResetTime extends Command
 				User::query()->where('id', $user->id)->update(['reset_time' => $reset_time]);
 			}
 
-			Log::info('---用户[ID:'.$user->id.' - '.$user->username.']的新重置日期为'.($reset_time != NULL? '【'.$reset_time.'】' : '【无】').'---');
+			Log::info('---用户[ID:'.$user->id.' - '.$user->username.' ('.$user->email.')]的新重置日期为'.($reset_time != NULL? '【'.$reset_time.'】' : '【无】').'---');
 		}
 
 		Log::info('----------------------------【升级用户重置日期】结束----------------------------');

+ 3 - 0
app/Console/Kernel.php

@@ -4,6 +4,7 @@ namespace App\Console;
 
 use App\Console\Commands\AutoClearLog;
 use App\Console\Commands\AutoJob;
+use App\Console\Commands\AutoPingNode;
 use App\Console\Commands\AutoReportNode;
 use App\Console\Commands\AutoStatisticsNodeDailyTraffic;
 use App\Console\Commands\AutoStatisticsNodeHourlyTraffic;
@@ -29,6 +30,7 @@ class Kernel extends ConsoleKernel
 	protected $commands = [
 		AutoClearLog::class,
 		AutoJob::class,
+		AutoPingNode::class,
 		AutoReportNode::class,
 		AutoStatisticsNodeDailyTraffic::class,
 		AutoStatisticsNodeHourlyTraffic::class,
@@ -59,6 +61,7 @@ class Kernel extends ConsoleKernel
 		$schedule->command('autoStatisticsNodeHourlyTraffic')->hourly();
 		$schedule->command('autoStatisticsUserHourlyTraffic')->hourly();
 		$schedule->command('userTrafficAbnormalAutoWarning')->hourly();
+		$schedule->command('autoPingNode')->twiceDaily();
 		$schedule->command('dailyJob')->daily();
 		$schedule->command('autoReportNode')->dailyAt('09:00');
 		$schedule->command('userTrafficAutoWarning')->dailyAt('10:30');

+ 94 - 52
app/Http/Controllers/AdminController.php

@@ -24,6 +24,7 @@ use App\Http\Models\SsNodeInfo;
 use App\Http\Models\SsNodeIp;
 use App\Http\Models\SsNodeLabel;
 use App\Http\Models\SsNodeOnlineLog;
+use App\Http\Models\SsNodePing;
 use App\Http\Models\SsNodeTrafficDaily;
 use App\Http\Models\SsNodeTrafficHourly;
 use App\Http\Models\User;
@@ -110,7 +111,7 @@ class AdminController extends Controller
 	public function userList(Request $request)
 	{
 		$id = $request->input('id');
-		$username = $request->input('username');
+		$email = $request->input('email');
 		$wechat = $request->input('wechat');
 		$qq = $request->input('qq');
 		$port = $request->input('port');
@@ -128,8 +129,8 @@ class AdminController extends Controller
 			$query->where('id', $id);
 		}
 
-		if(isset($username)){
-			$query->where('username', 'like', '%'.$username.'%');
+		if(isset($email)){
+			$query->where('email', 'like', '%'.$email.'%');
 		}
 
 		if(isset($wechat)){
@@ -222,8 +223,8 @@ class AdminController extends Controller
 	public function addUser(Request $request)
 	{
 		if($request->isMethod('POST')){
-			// 校验username是否已存在
-			$exists = User::query()->where('username', $request->input('username'))->first();
+			// 校验email是否已存在
+			$exists = User::query()->where('email', $request->input('email'))->first();
 			if($exists){
 				return Response::json(['status' => 'fail', 'data' => '', 'message' => '用户名已存在,请重新输入']);
 			}
@@ -233,7 +234,7 @@ class AdminController extends Controller
 			}
 
 			$user = new User();
-			$user->username = trim($request->input('username'));
+			$user->email = trim($request->input('email'));
 			$user->password = Hash::make(trim($request->input('password'))? : makeRandStr());
 			$user->port = $request->input('port');
 			$user->passwd = empty($request->input('passwd'))? makeRandStr() : $request->input('passwd');
@@ -355,6 +356,7 @@ class AdminController extends Controller
 	{
 		if($request->isMethod('POST')){
 			$username = trim($request->input('username'));
+			$email = trim($request->input('email'));
 			$password = $request->input('password');
 			$port = $request->input('port');
 			$passwd = $request->input('passwd');
@@ -381,8 +383,8 @@ class AdminController extends Controller
 			$is_admin = $request->input('is_admin');
 			$reset_time = $request->input('reset_time');
 
-			// 校验username是否已存在
-			$exists = User::query()->where('id', '<>', $id)->where('username', $username)->first();
+			// 校验email是否已存在
+			$exists = User::query()->where('id', '<>', $id)->where('email', $email)->first();
 			if($exists){
 				return Response::json(['status' => 'fail', 'data' => '', 'message' => '用户名已存在,请重新输入']);
 			}
@@ -409,6 +411,7 @@ class AdminController extends Controller
 			try{
 				$data = [
 					'username'             => $username,
+					'email'                => $email,
 					'port'                 => $port,
 					'passwd'               => $passwd,
 					'vmess_id'             => $vmess_id,
@@ -842,6 +845,7 @@ class AdminController extends Controller
 			SsNodeOnlineLog::query()->where('node_id', $id)->delete();
 			SsNodeTrafficDaily::query()->where('node_id', $id)->delete();
 			SsNodeTrafficHourly::query()->where('node_id', $id)->delete();
+			SsNodePing::query()->where('node_id', $id)->delete();
 			UserTrafficDaily::query()->where('node_id', $id)->delete();
 			UserTrafficHourly::query()->where('node_id', $id)->delete();
 			UserTrafficLog::query()->where('node_id', $id)->delete();
@@ -917,6 +921,44 @@ class AdminController extends Controller
 		return Response::view('admin.nodeMonitor', $view);
 	}
 
+	// Ping节点延迟
+	public function pingNode(Request $request)
+	{
+		$node = SsNode::query()->where('id', $request->input('id'))->first();
+		if(!$node){
+			return Response::json(['status' => 'fail', 'message' => '节点不存在,请重试']);
+		}
+
+		$result = NetworkDetection::ping($node->is_ddns? $node->server : $node->ip);
+
+		if($result){
+			$data[0] = $result['China Telecom']['time']? : '无';
+			$data[1] = $result['China Unicom']['time']? : '无';
+			$data[2] = $result['China Mobile']['time']? : '无';
+			$data[3] = $result['Hong Kong']['time']? : '无';
+
+			return Response::json(['status' => 'success', 'message' => $data]);
+		}else{
+			return Response::json(['status' => 'fail', 'message' => 'Ping访问失败']);
+		}
+	}
+
+	public function nodePingLog(Request $request)
+	{
+
+		$node_id = $request->input('nodeId');
+		$query = SsNodePing::query();
+		if(isset($node_id)){
+			$query->where('node_id', $node_id);
+		}
+
+		$view['nodeList'] = SsNode::query()->orderBy('id', 'asc')->get();
+		$view['pingLogs'] = $query->orderBy('id', 'asc')->paginate(15)->appends($request->except('page'));
+
+		return Response::view('admin.nodePingLog', $view);
+	}
+
+
 	// 文章列表
 	public function articleList(Request $request)
 	{
@@ -1124,7 +1166,7 @@ class AdminController extends Controller
 	{
 		$port = $request->input('port');
 		$user_id = $request->input('user_id');
-		$username = $request->input('username');
+		$email = $request->input('email');
 		$nodeId = $request->input('nodeId');
 		$startTime = $request->input('startTime');
 		$endTime = $request->input('endTime');
@@ -1141,9 +1183,9 @@ class AdminController extends Controller
 			$query->where('user_id', $user_id);
 		}
 
-		if(isset($username)){
-			$query->whereHas('user', function($q) use ($username){
-				$q->where('username', 'like', '%'.$username.'%');
+		if(isset($email)){
+			$query->whereHas('user', function($q) use ($email){
+				$q->where('email', 'like', '%'.$email.'%');
 			});
 		}
 
@@ -1317,7 +1359,7 @@ class AdminController extends Controller
 				DB::beginTransaction();
 				foreach($data as $user){
 					$obj = new User();
-					$obj->username = $user->user;
+					$obj->email = $user->user;
 					$obj->password = Hash::make('123456');
 					$obj->port = $user->port;
 					$obj->passwd = $user->passwd;
@@ -1514,7 +1556,7 @@ EOF;
 		$view['trafficHourly'] = "'".implode("','", $hourlyData)."'";
 		$view['monthDays'] = "'".implode("','", $monthDays)."'";
 		$view['dayHours'] = "'".implode("','", $dayHours)."'";
-		$view['username'] = $user->username;
+		$view['email'] = $user->email;
 
 		return Response::view('admin.userMonitor', $view);
 	}
@@ -2041,13 +2083,13 @@ EOF;
 	// 提现申请列表
 	public function applyList(Request $request)
 	{
-		$username = $request->input('username');
+		$email = $request->input('email');
 		$status = $request->input('status');
 
 		$query = ReferralApply::with('user');
-		if(isset($username)){
-			$query->whereHas('user', function($q) use ($username){
-				$q->where('username', 'like', '%'.$username.'%');
+		if(isset($email)){
+			$query->whereHas('user', function($q) use ($email){
+				$q->where('email', 'like', '%'.$email.'%');
 			});
 		}
 
@@ -2081,7 +2123,7 @@ EOF;
 	// 订单列表
 	public function orderList(Request $request)
 	{
-		$username = $request->input('username');
+		$email = $request->input('email');
 		$order_sn = $request->input('order_sn');
 		$is_coupon = $request->input('is_coupon');
 		$is_expire = $request->input('is_expire');
@@ -2093,9 +2135,9 @@ EOF;
 
 		$query = Order::query()->with(['user', 'goods', 'coupon']);
 
-		if(isset($username)){
-			$query->whereHas('user', function($q) use ($username){
-				$q->where('username', 'like', '%'.$username.'%');
+		if(isset($email)){
+			$query->whereHas('user', function($q) use ($email){
+				$q->where('email', 'like', '%'.$email.'%');
 			});
 		}
 		if(isset($order_sn)){
@@ -2214,13 +2256,13 @@ EOF;
 	// 用户余额变动记录
 	public function userBalanceLogList(Request $request)
 	{
-		$username = $request->input('username');
+		$email = $request->input('email');
 
 		$query = UserBalanceLog::query()->with(['user'])->orderBy('id', 'desc');
 
-		if(isset($username)){
-			$query->whereHas('user', function($q) use ($username){
-				$q->where('username', 'like', '%'.$username.'%');
+		if(isset($email)){
+			$query->whereHas('user', function($q) use ($email){
+				$q->where('email', 'like', '%'.$email.'%');
 			});
 		}
 
@@ -2232,13 +2274,13 @@ EOF;
 	// 用户封禁记录
 	public function userBanLogList(Request $request)
 	{
-		$username = $request->input('username');
+		$email = $request->input('email');
 
 		$query = UserBanLog::query()->with(['user'])->orderBy('id', 'desc');
 
-		if(isset($username)){
-			$query->whereHas('user', function($q) use ($username){
-				$q->where('username', 'like', '%'.$username.'%');
+		if(isset($email)){
+			$query->whereHas('user', function($q) use ($email){
+				$q->where('email', 'like', '%'.$email.'%');
 			});
 		}
 
@@ -2250,13 +2292,13 @@ EOF;
 	// 用户流量变动记录
 	public function userTrafficLogList(Request $request)
 	{
-		$username = $request->input('username');
+		$email = $request->input('email');
 
 		$query = UserTrafficModifyLog::query()->with(['user', 'order', 'order.goods']);
 
-		if(isset($username)){
-			$query->whereHas('user', function($q) use ($username){
-				$q->where('username', 'like', '%'.$username.'%');
+		if(isset($email)){
+			$query->whereHas('user', function($q) use ($email){
+				$q->where('email', 'like', '%'.$email.'%');
 			});
 		}
 
@@ -2268,21 +2310,21 @@ EOF;
 	// 用户返利流水记录
 	public function userRebateList(Request $request)
 	{
-		$username = $request->input('username');
-		$ref_username = $request->input('ref_username');
+		$email = $request->input('email');
+		$ref_email = $request->input('ref_email');
 		$status = $request->input('status');
 
 		$query = ReferralLog::query()->with(['user', 'order'])->orderBy('status', 'asc')->orderBy('id', 'desc');
 
-		if(isset($username)){
-			$query->whereHas('user', function($q) use ($username){
-				$q->where('username', 'like', '%'.$username.'%');
+		if(isset($email)){
+			$query->whereHas('user', function($q) use ($email){
+				$q->where('email', 'like', '%'.$email.'%');
 			});
 		}
 
-		if(isset($ref_username)){
-			$query->whereHas('ref_user', function($q) use ($ref_username){
-				$q->where('username', 'like', '%'.$ref_username.'%');
+		if(isset($ref_email)){
+			$query->whereHas('ref_user', function($q) use ($ref_email){
+				$q->where('email', 'like', '%'.$ref_email.'%');
 			});
 		}
 
@@ -2298,15 +2340,15 @@ EOF;
 	// 用户在线IP记录
 	public function userOnlineIPList(Request $request)
 	{
-		$username = $request->input('username');
+		$email = $request->input('email');
 		$port = $request->input('port');
 		$wechat = $request->input('wechat');
 		$qq = $request->input('qq');
 
 		$query = User::query()->where('status', '>=', 0)->where('enable', 1);
 
-		if(isset($username)){
-			$query->where('username', 'like', '%'.$username.'%');
+		if(isset($email)){
+			$query->where('email', 'like', '%'.$email.'%');
 		}
 
 		if(isset($wechat)){
@@ -2426,13 +2468,13 @@ EOF;
 	// 邮件发送日志列表
 	public function emailLog(Request $request)
 	{
-		$username = $request->input('username');
+		$email = $request->input('email');
 		$type = $request->input('type');
 
 		$query = EmailLog::query();
 
-		if(isset($username)){
-			$query->where('address', 'like', '%'.$username.'%');
+		if(isset($email)){
+			$query->where('address', 'like', '%'.$email.'%');
 		}
 
 		if(isset($type)){
@@ -2448,7 +2490,7 @@ EOF;
 	public function onlineIPMonitor(Request $request)
 	{
 		$ip = $request->input('ip');
-		$username = $request->input('username');
+		$email = $request->input('email');
 		$port = $request->input('port');
 		$nodeId = $request->input('nodeId');
 		$userId = $request->input('id');
@@ -2459,9 +2501,9 @@ EOF;
 			$query->where('ip', $ip);
 		}
 
-		if(isset($username)){
-			$query->whereHas('user', function($q) use ($username){
-				$q->where('username', 'like', '%'.$username.'%');
+		if(isset($email)){
+			$query->whereHas('user', function($q) use ($email){
+				$q->where('email', 'like', '%'.$email.'%');
 			});
 		}
 

+ 3 - 3
app/Http/Controllers/Api/LoginController.php

@@ -33,11 +33,11 @@ class LoginController extends Controller
 	// 登录返回订阅信息
 	public function login(Request $request)
 	{
-		$username = trim($request->input('username'));
+		$email = trim($request->input('email'));
 		$password = trim($request->input('password'));
 		$cacheKey = 'request_times_'.md5(getClientIp());
 
-		if(!$username || !$password){
+		if(!$email || !$password){
 			Cache::increment($cacheKey);
 
 			return Response::json(['status' => 'fail', 'data' => [], 'message' => '请输入用户名和密码']);
@@ -52,7 +52,7 @@ class LoginController extends Controller
 			Cache::put($cacheKey, 1, 3600);
 		}
 
-		$user = User::query()->where('username', $username)->where('status', '>=', 0)->first();
+		$user = User::query()->where('email', $email)->where('status', '>=', 0)->first();
 		if(!$user){
 			Cache::increment($cacheKey);
 

+ 58 - 0
app/Http/Controllers/Api/PayJsController.php

@@ -0,0 +1,58 @@
+<?php
+
+namespace App\Http\Controllers\Api;
+
+use App\Components\Callback;
+use App\Http\Controllers\Controller;
+use Illuminate\Http\Request;
+use Log;
+use Xhat\Payjs\Payjs;
+
+class PayJsController extends Controller
+{
+	use Callback;
+
+	// 接收GET请求
+	public function index(Request $request)
+	{
+		Log::info("【PayJs】回调接口[GET]:".var_export($request->all(), TRUE).'['.getClientIp().']');
+		exit("【PayJs】接口正常");
+	}
+
+	// 接收POST请求
+	public function store(Request $request)
+	{
+		Log::info("【PayJs】回调接口[POST]:".var_export($request->all(), TRUE));
+		$config = [
+			'mchid' => self::$systemConfig['payjs_mch_id'],
+			'key'   => self::$systemConfig['payjs_key'],
+		];
+
+		// 初始化
+		$payjs = new Payjs($config);
+		$notify_info = $payjs->notify();
+
+		// 使用
+
+		$result = "fail";
+		if($notify_info['return_code'] == 1){ // 验证成功
+			$result = "success";
+			// 商户订单号
+			$data = [];
+			$data['out_trade_no'] = $request->input('out_trade_no');
+			// 接口交易号
+			$data['trade_no'] = $request->input('payjs_order_id');
+			// 交易状态
+			$data['trade_status'] = $request->input('return_code');
+			// 交易金额(这里是按照结算货币汇率的金额,和rmb_fee不相等)
+			$data['total_amount'] = $request->input('total_fee');
+
+			$this->tradePaid($data, 6);
+		}else{
+			Log::info('PayJs-POST:验证失败['.getClientIp().']');
+		}
+
+		// 返回验证结果
+		exit($result);
+	}
+}

+ 61 - 56
app/Http/Controllers/AuthController.php

@@ -50,14 +50,14 @@ class AuthController extends Controller
 	{
 		if($request->isMethod('POST')){
 			$this->validate($request, [
-				'username' => 'required',
+				'email'    => 'required',
 				'password' => 'required'
 			], [
-				'username.required' => trans('auth.email_null'),
+				'email.required'    => trans('auth.email_null'),
 				'password.required' => trans('auth.password_null')
 			]);
 
-			$username = $request->input('username');
+			$email = $request->input('email');
 			$captcha = $request->input('captcha');
 			$password = $request->input('password');
 			$remember = $request->input('remember');
@@ -94,7 +94,7 @@ class AuthController extends Controller
 			}
 
 			// 验证账号并创建会话
-			if(!Auth::attempt(['username' => $username, 'password' => $password], $remember)){
+			if(!Auth::attempt(['email' => $email, 'password' => $password], $remember)){
 				return Redirect::back()->withInput()->withErrors(trans('auth.login_error'));
 			}
 
@@ -107,7 +107,7 @@ class AuthController extends Controller
 				}elseif(Auth::user()->status == 0 && (self::$systemConfig['is_active_register'] || self::$systemConfig['is_verify_register'])){
 					Auth::logout(); // 强制销毁会话,因为Auth::attempt的时候会产生会话
 
-					return Redirect::back()->withInput()->withErrors(trans('auth.active_tip').'<a href="/activeUser?username='.$username.'" target="_blank"><span style="color:#000">【'.trans('auth.active_account').'】</span></a>');
+					return Redirect::back()->withInput()->withErrors(trans('auth.active_tip').'<a href="/activeUser?email='.$email.'" target="_blank"><span style="color:#000">【'.trans('auth.active_account').'】</span></a>');
 				}
 			}
 
@@ -199,14 +199,16 @@ class AuthController extends Controller
 
 		if($request->isMethod('POST')){
 			$this->validate($request, [
-				'username'        => 'required|email|unique:user',
+				'username'        => 'required',
+				'email'           => 'required|email|unique:user',
 				'password'        => 'required|min:6',
 				'confirmPassword' => 'required|same:password',
 				'term'            => 'accepted'
 			], [
 				'username.required'        => trans('auth.email_null'),
-				'username.email'           => trans('auth.email_legitimate'),
-				'username.unique'          => trans('auth.email_exist'),
+				'email.required'           => trans('auth.email_null'),
+				'email.email'              => trans('auth.email_legitimate'),
+				'email.unique'             => trans('auth.email_exist'),
 				'password.required'        => trans('auth.password_null'),
 				'password.min'             => trans('auth.password_limit'),
 				'confirmPassword.required' => trans('auth.confirm_password'),
@@ -215,6 +217,7 @@ class AuthController extends Controller
 			]);
 
 			$username = $request->input('username');
+			$email = $request->input('email');
 			$password = $request->input('password');
 			$register_token = $request->input('register_token');
 			$code = $request->input('code');
@@ -238,14 +241,14 @@ class AuthController extends Controller
 			if(self::$systemConfig['sensitiveType']){
 				// 校验域名邮箱是否在黑名单中
 				$sensitiveWords = $this->sensitiveWords(1);
-				$usernameSuffix = explode('@', $username); // 提取邮箱后缀
-				if(in_array(strtolower($usernameSuffix[1]), $sensitiveWords)){
+				$emailSuffix = explode('@', $email); // 提取邮箱后缀
+				if(in_array(strtolower($emailSuffix[1]), $sensitiveWords)){
 					return Redirect::back()->withInput()->withErrors(trans('auth.email_banned'));
 				}
 			}else{
 				$sensitiveWords = $this->sensitiveWords(2);
-				$usernameSuffix = explode('@', $username); // 提取邮箱后缀
-				if(!in_array(strtolower($usernameSuffix[1]), $sensitiveWords)){
+				$emailSuffix = explode('@', $email); // 提取邮箱后缀
+				if(!in_array(strtolower($emailSuffix[1]), $sensitiveWords)){
 					return Redirect::back()->withInput()->withErrors(trans('auth.email_invalid'));
 				}
 			}
@@ -271,7 +274,7 @@ class AuthController extends Controller
 				if(!$verify_code){
 					return Redirect::back()->withInput($request->except(['verify_code']))->withErrors(trans('auth.captcha_null'));
 				}else{
-					$verifyCode = VerifyCode::query()->where('username', $username)->where('code', $verify_code)->where('status', 0)->first();
+					$verifyCode = VerifyCode::query()->where('address', $email)->where('code', $verify_code)->where('status', 0)->firstOrFail();
 					if(!$verifyCode){
 						return Redirect::back()->withInput($request->except(['verify_code']))->withErrors(trans('auth.captcha_overtime'));
 					}
@@ -335,12 +338,14 @@ class AuthController extends Controller
 			$transfer_enable = 1048576*(self::$systemConfig['default_traffic']+($referral_uid? self::$systemConfig['referral_traffic'] : 0));
 
 			// 创建新用户
-			$uid = Helpers::addUser($username, Hash::make($password), $transfer_enable, self::$systemConfig['default_days'], $referral_uid);
+			$uid = Helpers::addUser($email, Hash::make($password), $transfer_enable, self::$systemConfig['default_days'], $referral_uid);
 
 			// 注册失败,抛出异常
 			if(!$uid){
 				return Redirect::back()->withInput()->withErrors(trans('auth.register_fail'));
 			}
+			// 更新昵称
+			User::query()->whereKey($uid)->update(['username' => $username]);
 
 			// 生成订阅码
 			$subscribe = new UserSubscribe();
@@ -378,11 +383,11 @@ class AuthController extends Controller
 			// 邮箱验证码关闭情况下,发送激活邮件
 			if(!self::$systemConfig['is_verify_register'] && self::$systemConfig['is_active_register']){
 				// 生成激活账号的地址
-				$token = $this->addVerifyUrl($uid, $username);
+				$token = $this->addVerifyUrl($uid, $email);
 				$activeUserUrl = self::$systemConfig['website_url'].'/active/'.$token;
 
-				$logId = Helpers::addEmailLog($username, '注册激活', '请求地址:'.$activeUserUrl);
-				Mail::to($username)->send(new activeUser($logId, $activeUserUrl));
+				$logId = Helpers::addEmailLog($email, '注册激活', '请求地址:'.$activeUserUrl);
+				Mail::to($email)->send(new activeUser($logId, $activeUserUrl));
 
 				Session::flash('regSuccessMsg', trans('auth.register_active_tip'));
 			}else{
@@ -454,9 +459,9 @@ class AuthController extends Controller
 	}
 
 	// 生成申请的请求地址
-	private function addVerifyUrl($uid, $username)
+	private function addVerifyUrl($uid, $email)
 	{
-		$token = md5(self::$systemConfig['website_name'].$username.microtime());
+		$token = md5(self::$systemConfig['website_name'].$email.microtime());
 		$verify = new Verify();
 		$verify->type = 1;
 		$verify->user_id = $uid;
@@ -473,13 +478,13 @@ class AuthController extends Controller
 		if($request->isMethod('POST')){
 			// 校验请求
 			$this->validate($request, [
-				'username' => 'required|email'
+				'email' => 'required|email'
 			], [
-				'username.required' => trans('auth.email_null'),
-				'username.email'    => trans('auth.email_legitimate')
+				'email.required' => trans('auth.email_null'),
+				'email.email'    => trans('auth.email_legitimate')
 			]);
 
-			$username = $request->input('username');
+			$email = $request->input('email');
 
 			// 是否开启重设密码
 			if(!self::$systemConfig['is_reset_password']){
@@ -487,30 +492,30 @@ class AuthController extends Controller
 			}
 
 			// 查找账号
-			$user = User::query()->where('username', $username)->first();
+			$user = User::query()->where('email', $email)->first();
 			if(!$user){
 				return Redirect::back()->withErrors(trans('auth.email_notExist'));
 			}
 
 			// 24小时内重设密码次数限制
 			$resetTimes = 0;
-			if(Cache::has('resetPassword_'.md5($username))){
-				$resetTimes = Cache::get('resetPassword_'.md5($username));
+			if(Cache::has('resetPassword_'.md5($email))){
+				$resetTimes = Cache::get('resetPassword_'.md5($email));
 				if($resetTimes >= self::$systemConfig['reset_password_times']){
 					return Redirect::back()->withErrors(trans('auth.reset_password_limit', ['time' => self::$systemConfig['reset_password_times']]));
 				}
 			}
 
 			// 生成取回密码的地址
-			$token = $this->addVerifyUrl($user->id, $username);
+			$token = $this->addVerifyUrl($user->id, $email);
 
 			// 发送邮件
 			$resetPasswordUrl = self::$systemConfig['website_url'].'/reset/'.$token;
 
-			$logId = Helpers::addEmailLog($username, '重置密码', '请求地址:'.$resetPasswordUrl);
-			Mail::to($username)->send(new resetPassword($logId, $resetPasswordUrl));
+			$logId = Helpers::addEmailLog($email, '重置密码', '请求地址:'.$resetPasswordUrl);
+			Mail::to($email)->send(new resetPassword($logId, $resetPasswordUrl));
 
-			Cache::put('resetPassword_'.md5($username), $resetTimes+1, 86400);
+			Cache::put('resetPassword_'.md5($email), $resetTimes+1, 86400);
 
 			return Redirect::back()->with('successMsg', trans('auth.reset_password_success_tip'));
 		}else{
@@ -582,13 +587,13 @@ class AuthController extends Controller
 	{
 		if($request->isMethod('POST')){
 			$this->validate($request, [
-				'username' => 'required|email|exists:user,username'
+				'email' => 'required|email|exists:user,email'
 			], [
-				'username.required' => trans('auth.email_null'),
-				'username.email'    => trans('auth.email_legitimate'),
-				'username.exists'   => trans('auth.email_notExist')
+				'email.required' => trans('auth.email_null'),
+				'email.email'    => trans('auth.email_legitimate'),
+				'email.exists'   => trans('auth.email_notExist')
 			]);
-			$username = $request->input('username');
+			$email = $request->input('email');
 
 			// 是否开启账号激活
 			if(!self::$systemConfig['is_active_register']){
@@ -596,7 +601,7 @@ class AuthController extends Controller
 			}
 
 			// 查找账号
-			$user = User::query()->where('username', $username)->first();
+			$user = User::query()->where('email', $email)->first();
 			if($user->status < 0){
 				return Redirect::back()->withErrors(trans('auth.login_ban', ['email' => self::$systemConfig['webmaster_email']]));
 			}elseif($user->status > 0){
@@ -605,23 +610,23 @@ class AuthController extends Controller
 
 			// 24小时内激活次数限制
 			$activeTimes = 0;
-			if(Cache::has('activeUser_'.md5($username))){
-				$activeTimes = Cache::get('activeUser_'.md5($username));
+			if(Cache::has('activeUser_'.md5($email))){
+				$activeTimes = Cache::get('activeUser_'.md5($email));
 				if($activeTimes >= self::$systemConfig['active_times']){
 					return Redirect::back()->withErrors(trans('auth.active_limit', ['time' => self::$systemConfig['webmaster_email']]));
 				}
 			}
 
 			// 生成激活账号的地址
-			$token = $this->addVerifyUrl($user->id, $username);
+			$token = $this->addVerifyUrl($user->id, $email);
 
 			// 发送邮件
 			$activeUserUrl = self::$systemConfig['website_url'].'/active/'.$token;
 
-			$logId = Helpers::addEmailLog($username, '激活账号', '请求地址:'.$activeUserUrl);
-			Mail::to($username)->send(new activeUser($logId, $activeUserUrl));
+			$logId = Helpers::addEmailLog($email, '激活账号', '请求地址:'.$activeUserUrl);
+			Mail::to($email)->send(new activeUser($logId, $activeUserUrl));
 
-			Cache::put('activeUser_'.md5($username), $activeTimes+1, 86400);
+			Cache::put('activeUser_'.md5($email), $activeTimes+1, 86400);
 
 			return Redirect::back()->with('successMsg', trans('auth.register_active_tip'));
 		}else{
@@ -689,14 +694,14 @@ class AuthController extends Controller
 	public function sendCode(Request $request)
 	{
 		$validator = Validator::make($request->all(), [
-			'username' => 'required|email|unique:user'
+			'email' => 'required|email|unique:user'
 		], [
-			'username.required' => trans('auth.email_null'),
-			'username.email'    => trans('auth.email_legitimate'),
-			'username.unique'   => trans('auth.email_exist')
+			'email.required' => trans('auth.email_null'),
+			'email.email'    => trans('auth.email_legitimate'),
+			'email.unique'   => trans('auth.email_exist')
 		]);
 
-		$username = $request->input('username');
+		$email = $request->input('email');
 
 		if($validator->fails()){
 			return Response::json(['status' => 'fail', 'data' => '', 'message' => $validator->getMessageBag()->first()]);
@@ -706,14 +711,14 @@ class AuthController extends Controller
 		if(self::$systemConfig['sensitiveType']){
 			// 校验域名邮箱是否在黑名单中
 			$sensitiveWords = $this->sensitiveWords(1);
-			$usernameSuffix = explode('@', $username); // 提取邮箱后缀
-			if(in_array(strtolower($usernameSuffix[1]), $sensitiveWords)){
+			$emailSuffix = explode('@', $email); // 提取邮箱后缀
+			if(in_array(strtolower($emailSuffix[1]), $sensitiveWords)){
 				return Response::json(['status' => 'fail', 'data' => '', 'message' => trans('auth.email_banned')]);
 			}
 		}else{
 			$sensitiveWords = $this->sensitiveWords(2);
-			$usernameSuffix = explode('@', $username); // 提取邮箱后缀
-			if(!in_array(strtolower($usernameSuffix[1]), $sensitiveWords)){
+			$emailSuffix = explode('@', $email); // 提取邮箱后缀
+			if(!in_array(strtolower($emailSuffix[1]), $sensitiveWords)){
 				return Response::json(['status' => 'fail', 'data' => '', 'message' => trans('auth.email_invalid')]);
 			}
 		}
@@ -730,10 +735,10 @@ class AuthController extends Controller
 
 		// 发送邮件
 		$code = makeRandStr(6, TRUE);
-		$logId = Helpers::addEmailLog($username, '发送注册验证码', '验证码:'.$code);
-		Mail::to($username)->send(new sendVerifyCode($logId, $code));
+		$logId = Helpers::addEmailLog($email, '发送注册验证码', '验证码:'.$code);
+		Mail::to($email)->send(new sendVerifyCode($logId, $code));
 
-		$this->addVerifyCode($username, $code);
+		$this->addVerifyCode($email, $code);
 
 		Cache::put('send_verify_code_'.md5(getClientIP()), getClientIP(), 60);
 
@@ -741,10 +746,10 @@ class AuthController extends Controller
 	}
 
 	// 生成注册验证码
-	private function addVerifyCode($username, $code)
+	private function addVerifyCode($email, $code)
 	{
 		$verify = new VerifyCode();
-		$verify->username = $username;
+		$verify->address = $email;
 		$verify->code = $code;
 		$verify->status = 0;
 		$verify->save();

+ 96 - 57
app/Http/Controllers/PaymentController.php

@@ -22,6 +22,7 @@ use Payment\Exceptions\ClassNotFoundException;
 use Payment\Exceptions\GatewayException;
 use Response;
 use Validator;
+use Xhat\Payjs\Payjs;
 
 /**
  * 支付控制器
@@ -40,82 +41,88 @@ class PaymentController extends Controller
 		$goods_id = $request->input('goods_id');
 		$coupon_sn = $request->input('coupon_sn');
 		$pay_type = $request->input('pay_type');
-
-
+		$balance = $request->input('amount');
 		$goods = Goods::query()->where('status', 1)->where('id', $goods_id)->first();
-		if(!$goods){
-			return Response::json(['status' => 'fail', 'data' => '', 'message' => '订单创建失败:商品或服务已下架']);
-		}
-		// 是否有生效的套餐
-		$activePlan = Order::uid()->with(['goods'])->whereHas('goods', function($q){ $q->where('type', 2); })->where('status', 2)->where('is_expire', 0)->doesntExist();
-		//无生效套餐,禁止购买加油包
-		if($goods->type == 1 && $activePlan){
-			return Response::json(['status' => 'fail', 'data' => '', 'message' => '购买加油包前,请先购买套餐']);
-		}
-
-		//非余额付款下,检查对应的在线支付是否开启
-		if($pay_type != 1){
-			// 判断是否开启在线支付
-			if(!self::$systemConfig['is_alipay'] && !self::$systemConfig['is_f2fpay']){
-				return Response::json(['status' => 'fail', 'data' => '', 'message' => '订单创建失败:系统并未开启在线支付功能']);
+		if(isset($balance)){
+			if(!is_numeric($balance) || $balance <= 0){
+				return Response::json(['status' => 'fail', 'data' => '', 'message' => '充值余额不合规']);
 			}
-
-			// 判断是否存在同个商品的未支付订单
-			$existsOrder = Order::uid()->where('status', 0)->where('goods_id', $goods_id)->exists();
-			if($existsOrder){
-				return Response::json(['status' => 'fail', 'data' => '', 'message' => '订单创建失败:尚有未支付的订单,请先去支付']);
+			$amount = $balance;
+		}elseif(isset($goods_id) && isset($pay_type)){
+			if(!$goods){
+				return Response::json(['status' => 'fail', 'data' => '', 'message' => '订单创建失败:商品或服务已下架']);
+			}
+			// 是否有生效的套餐
+			$activePlan = Order::uid()->with(['goods'])->whereHas('goods', function($q){ $q->where('type', 2); })->where('status', 2)->where('is_expire', 0)->doesntExist();
+			//无生效套餐,禁止购买加油包
+			if($goods->type == 1 && $activePlan){
+				return Response::json(['status' => 'fail', 'data' => '', 'message' => '购买加油包前,请先购买套餐']);
 			}
-		}
 
-		// 单个商品限购
-		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.'次']);
+			//非余额付款下,检查对应的在线支付是否开启
+			if($pay_type != 1){
+				// 判断是否开启在线支付
+				if(!self::$systemConfig['is_alipay'] && !self::$systemConfig['is_f2fpay']){
+					return Response::json(['status' => 'fail', 'data' => '', 'message' => '订单创建失败:系统并未开启在线支付功能']);
+				}
+
+				// 判断是否存在同个商品的未支付订单
+				$existsOrder = Order::uid()->where('status', 0)->where('goods_id', $goods_id)->exists();
+				if($existsOrder){
+					return Response::json(['status' => 'fail', 'data' => '', 'message' => '订单创建失败:尚有未支付的订单,请先去支付']);
+				}
 			}
-		}
 
-		// 使用优惠券
-		if($coupon_sn){
-			$coupon = Coupon::query()->where('status', 0)->whereIn('type', [1, 2])->where('sn', $coupon_sn)->first();
-			if(!$coupon){
-				return Response::json(['status' => 'fail', 'data' => '', 'message' => '订单创建失败:优惠券不存在']);
+			// 单个商品限购
+			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.'次']);
+				}
 			}
 
-			// 计算实际应支付总价
-			$amount = $coupon->type == 2? $goods->price*$coupon->discount/10 : $goods->price-$coupon->amount;
-			$amount = $amount > 0? round($amount, 2) : 0; // 四舍五入保留2位小数,避免无法正常创建订单
-		}else{
-			$amount = $goods->price;
-		}
+			// 使用优惠券
+			if($coupon_sn){
+				$coupon = Coupon::query()->where('status', 0)->whereIn('type', [1, 2])->where('sn', $coupon_sn)->first();
+				if(!$coupon){
+					return Response::json(['status' => 'fail', 'data' => '', 'message' => '订单创建失败:优惠券不存在']);
+				}
 
-		// 价格异常判断
-		if($amount < 0){
-			return Response::json(['status' => 'fail', 'data' => '', 'message' => '订单创建失败:订单总价异常']);
-		}elseif($amount == 0 && $pay_type != 1){
-			return Response::json(['status' => 'fail', 'data' => '', 'message' => '订单创建失败:订单总价为0,无需使用在线支付']);
-		}
+				// 计算实际应支付总价
+				$amount = $coupon->type == 2? $goods->price*$coupon->discount/10 : $goods->price-$coupon->amount;
+				$amount = $amount > 0? round($amount, 2) : 0; // 四舍五入保留2位小数,避免无法正常创建订单
+			}else{
+				$amount = $goods->price;
+			}
+
+			// 价格异常判断
+			if($amount < 0){
+				return Response::json(['status' => 'fail', 'data' => '', 'message' => '订单创建失败:订单总价异常']);
+			}elseif($amount == 0 && $pay_type != 1){
+				return Response::json(['status' => 'fail', 'data' => '', 'message' => '订单创建失败:订单总价为0,无需使用在线支付']);
+			}
 
-		// 验证账号余额是否充足
-		if($pay_type == 1 && Auth::user()->balance < $amount){
-			return Response::json(['status' => 'fail', 'data' => '', 'message' => '您的余额不足,请先充值']);
+			// 验证账号余额是否充足
+			if($pay_type == 1 && Auth::user()->balance < $amount){
+				return Response::json(['status' => 'fail', 'data' => '', 'message' => '您的余额不足,请先充值']);
+			}
 		}
 
-		DB::beginTransaction();
 		try{
+			DB::beginTransaction();
 			$orderSn = date('ymdHis').mt_rand(100000, 999999);
 
 			// 生成订单
 			$order = new Order();
 			$order->order_sn = $orderSn;
 			$order->user_id = Auth::user()->id;
-			$order->goods_id = $goods_id;
+			$order->goods_id = $balance? -1 : $goods_id;
 			$order->coupon_id = !empty($coupon)? $coupon->id : 0;
-			$order->origin_amount = $goods->price;
+			$order->origin_amount = $balance? : $goods->price;
 			$order->amount = $amount;
-			$order->expire_at = date("Y-m-d H:i:s", strtotime("+".$goods->days." days"));
+			$order->expire_at = $balance? NULL : date("Y-m-d H:i:s", strtotime("+".$goods->days." days"));
 			$order->is_expire = 0;
-			$order->pay_way = $pay_type;
+			$order->pay_way = $balance? 0 : $pay_type;
 			$order->status = 0;
 			$order->save();
 			// 生成支付单
@@ -200,6 +207,31 @@ class PaymentController extends Controller
 						exit;
 					}
 
+				}elseif($pay_type == 6){
+					$pay_way = 1;
+					// 配置通信参数
+					$config = [
+						'mchid' => self::$systemConfig['payjs_mch_id'],
+						'key'   => self::$systemConfig['payjs_key'],
+					];
+
+					// 初始化
+					$payjs = new Payjs($config);
+
+					$data = [
+						'body'         => '',
+						'total_fee'    => $amount,
+						'out_trade_no' => $orderSn,
+						'notify_url'   => self::$systemConfig['website_url']."/api/payjs",
+					];
+
+					$result = $payjs->native($data);
+					if(!$result['return_code']){
+						Log::error("【PayJs】错误: ".$result['return_msg']);
+
+						return Response::json(['status' => 'fail', 'data' => '', 'message' => '创建支付单失败:支付渠道暂时无法提供支付信息!']);
+					}
+
 				}else{
 					return Response::json(['status' => 'fail', 'data' => '', 'message' => '创建支付单失败:未知支付类型']);
 				}
@@ -211,12 +243,16 @@ class PaymentController extends Controller
 				$payment->order_sn = $orderSn;
 				$payment->pay_way = $pay_way? : 1;
 				$payment->amount = $amount;
-				if(self::$systemConfig['is_alipay'] && $pay_type == 4){
+				if($pay_type == 4){
 					$payment->qr_code = $result;
-				}elseif(self::$systemConfig['is_f2fpay'] && $pay_type == 5){
+				}elseif($pay_type == 5){
 					$payment->qr_code = $result['qr_code'];
 					$payment->qr_url = 'http://qr.topscan.com/api.php?text='.$result['qr_code'].'&bg=ffffff&fg=000000&pt=1c73bd&m=10&w=400&el=1&inpt=1eabfc&logo=https://t.alipayobjects.com/tfscom/T1Z5XfXdxmXXXXXXXX.png'; //后备:https://cli.im/api/qrcode/code?text=".$result['qr_code']."&mhid=5EfGCwztyckhMHcmI9ZcOKs
 					$payment->qr_local_url = $payment->qr_url;
+				}elseif($pay_type == 6){
+					$payment->qr_code = $result['code_url'];
+					$payment->qr_url = $result['qrcode'];
+					$payment->qr_local_url = $payment->qr_url;
 				}
 				$payment->status = 0;
 				$payment->save();
@@ -254,7 +290,10 @@ class PaymentController extends Controller
 	// 支付单详情
 	public function detail($sn)
 	{
-		$view['payment'] = Payment::uid()->with(['order', 'order.goods'])->where('sn', $sn)->firstOrFail();
+		$payment = Payment::uid()->with(['order', 'order.goods'])->where('sn', $sn)->firstOrFail();
+		$view['payment'] = $payment;
+		$view['name'] = $payment->order->goods? $payment->order->goods->name : '余额充值';
+		$view['days'] = $payment->order->goods? $payment->order->goods->days : 0;
 
 		return Response::view('payment.detail', $view);
 	}

+ 6 - 6
app/Http/Controllers/SubscribeController.php

@@ -33,18 +33,18 @@ class SubscribeController extends Controller
 	public function subscribeList(Request $request)
 	{
 		$user_id = $request->input('user_id');
-		$username = $request->input('username');
+		$email = $request->input('email');
 		$status = $request->input('status');
 
-		$query = UserSubscribe::with(['user:id,username']);
+		$query = UserSubscribe::with(['user:id,email']);
 
 		if(isset($user_id)){
 			$query->where('user_id', $user_id);
 		}
 
-		if(isset($username)){
-			$query->whereHas('user', function($q) use ($username){
-				$q->where('username', 'like', '%'.$username.'%');
+		if(isset($email)){
+			$query->whereHas('user', function($q) use ($email){
+				$q->where('email', 'like', '%'.$email.'%');
 			});
 		}
 
@@ -61,7 +61,7 @@ class SubscribeController extends Controller
 	public function subscribeLog(Request $request)
 	{
 		$id = $request->input('id');
-		$query = UserSubscribeLog::with('user:username');
+		$query = UserSubscribeLog::with('user:email');
 
 		if(isset($id)){
 			$query->where('sid', $id);

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

@@ -32,13 +32,13 @@ class TicketController extends Controller
 	// 工单列表
 	public function ticketList(Request $request)
 	{
-		$username = $request->input('username');
+		$email = $request->input('email');
 
 		$query = Ticket::query();
 
-		if(isset($username)){
-			$query->whereHas('user', function($q) use ($username){
-				$q->where('username', 'like', '%'.$username.'%');
+		if(isset($email)){
+			$query->whereHas('user', function($q) use ($email){
+				$q->where('email', 'like', '%'.$email.'%');
 			});
 		}
 
@@ -80,8 +80,8 @@ class TicketController extends Controller
 						Mail::to(self::$systemConfig['webmaster_email'])->send(new replyTicket($logId, $title, $content));
 					}
 				}else{
-					$logId = Helpers::addEmailLog($ticket->user->username, $title, $content);
-					Mail::to($ticket->user->username)->send(new replyTicket($logId, $title, $content));
+					$logId = Helpers::addEmailLog($ticket->user->email, $title, $content);
+					Mail::to($ticket->user->email)->send(new replyTicket($logId, $title, $content));
 				}
 
 				// 通过ServerChan发微信消息提醒管理员
@@ -121,8 +121,8 @@ class TicketController extends Controller
 		$content = "工单【".$ticket->title."】已关闭";
 
 		// 发邮件通知用户
-		$logId = Helpers::addEmailLog($ticket->user->username, $title, $content);
-		Mail::to($ticket->user->username)->send(new closeTicket($logId, $title, $content));
+		$logId = Helpers::addEmailLog($ticket->user->email, $title, $content);
+		Mail::to($ticket->user->email)->send(new closeTicket($logId, $title, $content));
 
 		return Response::json(['status' => 'success', 'data' => '', 'message' => '关闭成功']);
 	}

+ 24 - 23
app/Http/Controllers/UserController.php

@@ -15,6 +15,7 @@ use App\Http\Models\ReferralLog;
 use App\Http\Models\SsNode;
 use App\Http\Models\SsNodeInfo;
 use App\Http\Models\SsNodeLabel;
+use App\Http\Models\SsNodePing;
 use App\Http\Models\Ticket;
 use App\Http\Models\TicketReply;
 use App\Http\Models\User;
@@ -135,7 +136,7 @@ class UserController extends Controller
 			return Response::json(['status' => 'fail', 'message' => '已经签到过了,明天再来吧']);
 		}
 
-		$traffic = mt_rand((int)self::$systemConfig['min_rand_traffic'], (int)self::$systemConfig['max_rand_traffic']) * 1048576;
+		$traffic = mt_rand((int)self::$systemConfig['min_rand_traffic'], (int)self::$systemConfig['max_rand_traffic'])*1048576;
 		$ret = User::uid()->increment('transfer_enable', $traffic);
 		if(!$ret){
 			return Response::json(['status' => 'fail', 'message' => '签到失败,系统异常']);
@@ -171,6 +172,11 @@ class UserController extends Controller
 			$nodeList = SsNode::query()->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();
 
 			foreach($nodeList as $node){
+				$node->ct = number_format(SsNodePing::query()->where('node_id', $node->id)->where('ct', '>', '0')->avg('ct'), 1, '.', '');
+				$node->cu = number_format(SsNodePing::query()->where('node_id', $node->id)->where('cu', '>', '0')->avg('cu'), 1, '.', '');
+				$node->cm = number_format(SsNodePing::query()->where('node_id', $node->id)->where('cm', '>', '0')->avg('cm'), 1, '.', '');
+				$node->hk = number_format(SsNodePing::query()->where('node_id', $node->id)->where('hk', '>', '0')->avg('hk'), 1, '.', '');
+
 				// 节点在线状态
 				$node->offline = SsNodeInfo::query()->where('node_id', $node->id)->where('log_time', '>=', strtotime("-10 minutes"))->orderBy('id', 'desc')->doesntExist();
 				// 节点标签
@@ -197,6 +203,7 @@ class UserController extends Controller
 		if($request->isMethod('POST')){
 			$old_password = trim($request->input('old_password'));
 			$new_password = trim($request->input('new_password'));
+			$username = trim($request->input('username'));
 			$wechat = trim($request->input('wechat'));
 			$qq = trim($request->input('qq'));
 			$passwd = trim($request->input('passwd'));
@@ -220,33 +227,27 @@ class UserController extends Controller
 				}else{
 					return Redirect::to('profile#tab_1')->with('successMsg', '修改成功');
 				}
-			}
-
-			// 修改联系方式
-			if($wechat || $qq){
-				if(empty(clean($wechat)) && empty(clean($qq))){
-					return Redirect::to('profile#tab_2')->withErrors('修改失败');
-				}
-
-				$ret = User::uid()->update(['wechat' => $wechat, 'qq' => $qq]);
+				// 修改代理密码
+			}elseif($passwd){
+				$ret = User::uid()->update(['passwd' => $passwd]);
 				if(!$ret){
-					return Redirect::to('profile#tab_2')->withErrors('修改失败');
+					return Redirect::to('profile#tab_3')->withErrors('修改失败');
 				}else{
-					return Redirect::to('profile#tab_2')->with('successMsg', '修改成功');
+					return Redirect::to('profile#tab_3')->with('successMsg', '修改成功');
+				}
+			}else{
+				// 修改联系方式
+				if(empty($username)){
+					return Redirect::to('profile#tab_2')->withErrors('修改失败,昵称不能为空值');
 				}
-			}
 
-			// 修改代理密码
-			if($passwd){
-				$ret = User::uid()->update(['passwd' => $passwd]);
+				$ret = User::uid()->update(['username' => $username, 'wechat' => $wechat, 'qq' => $qq]);
 				if(!$ret){
-					return Redirect::to('profile#tab_3')->withErrors('修改失败');
+					return Redirect::to('profile#tab_2')->withErrors('修改失败');
 				}else{
-					return Redirect::to('profile#tab_3')->with('successMsg', '修改成功');
+					return Redirect::to('profile#tab_2')->with('successMsg', '修改成功');
 				}
 			}
-
-			return Redirect::to('profile#tab_1')->withErrors('非法请求');
 		}else{
 			return Response::view('user.profile');
 		}
@@ -347,7 +348,7 @@ class UserController extends Controller
 
 		if($obj->id){
 			$emailTitle = "新工单提醒";
-			$content = "标题:【".$title."】<br>用户:".Auth::user()->username."<br>内容:".$content;
+			$content = "标题:【".$title."】<br>用户:".Auth::user()->email."<br>内容:".$content;
 
 			// 发邮件通知管理员
 			if(self::$systemConfig['webmaster_email']){
@@ -531,7 +532,7 @@ class UserController extends Controller
 		$view['link'] = self::$systemConfig['website_url'].'/register?aff='.Auth::user()->id;
 		$view['referralLogList'] = ReferralLog::uid()->with('user')->orderBy('id', 'desc')->paginate(10, ['*'], 'log_page');
 		$view['referralApplyList'] = ReferralApply::uid()->with('user')->orderBy('id', 'desc')->paginate(10, ['*'], 'apply_page');
-		$view['referralUserList'] = User::query()->select(['username', 'created_at'])->where('referral_uid', Auth::user()->id)->orderBy('id', 'desc')->paginate(10, ['*'], 'user_page');
+		$view['referralUserList'] = User::query()->select(['email', 'created_at'])->where('referral_uid', Auth::user()->id)->orderBy('id', 'desc')->paginate(10, ['*'], 'user_page');
 
 		return Response::view('user.referral', $view);
 	}
@@ -651,8 +652,8 @@ class UserController extends Controller
 
 		$coupon = Coupon::query()->where('sn', $request->input('coupon_sn'))->first();
 
-		DB::beginTransaction();
 		try{
+			DB::beginTransaction();
 			// 写入日志
 			$this->addUserBalanceLog(Auth::user()->id, 0, Auth::user()->balance, Auth::user()->balance+$coupon->amount, $coupon->amount, '用户手动充值 - [充值券:'.$request->input('coupon_sn').']');
 

+ 4 - 0
app/Http/Kernel.php

@@ -6,8 +6,10 @@ use App\Http\Middleware\Affiliate;
 use App\Http\Middleware\CheckForMaintenanceMode;
 use App\Http\Middleware\EncryptCookies;
 use App\Http\Middleware\isAdmin;
+use App\Http\Middleware\isAdminlogin;
 use App\Http\Middleware\isForbidden;
 use App\Http\Middleware\isLogin;
+use App\Http\Middleware\isMaintenance;
 use App\Http\Middleware\isSecurity;
 use App\Http\Middleware\RedirectIfAuthenticated;
 use App\Http\Middleware\SetLocale;
@@ -85,7 +87,9 @@ class Kernel extends HttpKernel
 		'signed'        => ValidateSignature::class,
 		'throttle'      => ThrottleRequests::class,
 		'isAdmin'       => isAdmin::class,
+		'isAdminLogin'  => isAdminLogin::class,
 		'isLogin'       => isLogin::class,
+		'isMaintenance' => isMaintenance::class,
 		'isSecurity'    => isSecurity::class,
 		'isForbidden'   => isForbidden::class,
 		'affiliate'     => Affiliate::class,

+ 26 - 0
app/Http/Middleware/isAdminlogin.php

@@ -0,0 +1,26 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use Closure;
+use Illuminate\Http\Request;
+use Redirect;
+
+class isAdminlogin
+{
+	/**
+	 * Handle an incoming request.
+	 *
+	 * @param Request $request
+	 * @param Closure $next
+	 * @return mixed
+	 */
+	public function handle($request, Closure $next)
+	{
+		if(auth()->guest()){
+			return Redirect::to('admin/login');
+		}
+
+		return $next($request);
+	}
+}

+ 27 - 0
app/Http/Middleware/isMaintenance.php

@@ -0,0 +1,27 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use App\Components\Helpers;
+use Closure;
+use Illuminate\Http\Request;
+
+class isMaintenance
+{
+	/**
+	 * 校验是否开启维护模式
+	 *
+	 * @param Request $request
+	 * @param Closure $next
+	 *
+	 * @return mixed
+	 */
+	public function handle($request, Closure $next)
+	{
+		if(Helpers::systemConfig()['maintenance_mode']){
+			return response()->view('auth.maintenance', ['message' => Helpers::systemConfig()['maintenance_content'], 'time' => Helpers::systemConfig()['maintenance_time']? : '0']);
+		}
+
+		return $next($request);
+	}
+}

+ 46 - 0
app/Http/Models/SsNodePing.php

@@ -0,0 +1,46 @@
+<?php
+
+namespace App\Http\Models;
+
+use Eloquent;
+use Illuminate\Database\Eloquent\Builder;
+use Illuminate\Database\Eloquent\Model;
+use Illuminate\Support\Carbon;
+
+/**
+ * 节点定时Ping测速
+ * App\Http\Models\SsNodePing
+ *
+ * @mixin Eloquent
+ * @property int         $id
+ * @property int         $node_id 对应节点id
+ * @property int         $ct      电信
+ * @property int         $cu      联通
+ * @property int         $cm      移动
+ * @property int         $hk      香港
+ * @property Carbon      $created_at
+ * @property Carbon      $updated_at
+ * @method static Builder|SsNodePing newModelQuery()
+ * @method static Builder|SsNodePing newQuery()
+ * @method static Builder|SsNodePing query()
+ * @method static Builder|SsNodePing whereCm($value)
+ * @method static Builder|SsNodePing whereCreatedAt($value)
+ * @method static Builder|SsNodePing whereCu($value)
+ * @method static Builder|SsNodePing whereHk($value)
+ * @method static Builder|SsNodePing whereId($value)
+ * @method static Builder|SsNodePing whereNodeId($value)
+ * @method static Builder|SsNodePing whereUpdatedAt($value)
+ * @method static Builder|SsNodePing whereUt($value)
+ * @method static Builder|SsNodePing whereCt($value)
+ * @property-read SsNode $node
+ */
+class SsNodePing extends Model
+{
+	protected $table = 'ss_node_ping';
+	protected $primaryKey = 'id';
+
+	public function node()
+	{
+		return $this->hasOne(SsNode::class, 'id', 'node_id');
+	}
+}

+ 2 - 0
app/Http/Models/User.php

@@ -19,6 +19,7 @@ use Illuminate\Support\Carbon;
  * @package App\Http\Models
  * @mixin Eloquent
  * @property int                                                        $id
+ * @property string                                                     $email                邮箱
  * @property string                                                     $username             用户名
  * @property string                                                     $password             密码
  * @property int                                                        $port                 代理端口
@@ -70,6 +71,7 @@ use Illuminate\Support\Carbon;
  * @method static Builder|User newQuery()
  * @method static Builder|User query()
  * @method static Builder|User uid()
+ * @method static Builder|User whereEmail($value)
  * @method static Builder|User whereBalance($value)
  * @method static Builder|User whereBanTime($value)
  * @method static Builder|User whereCreatedAt($value)

+ 2 - 1
app/Http/Models/VerifyCode.php

@@ -14,7 +14,7 @@ use Illuminate\Support\Carbon;
  * @package App\Http\Models
  * @mixin Eloquent
  * @property int         $id
- * @property string      $username   用户邮箱
+ * @property string      $address    用户邮箱
  * @property string      $code       验证码
  * @property int         $status     状态:0-未使用、1-已使用、2-已失效
  * @property Carbon|null $created_at 创建时间
@@ -28,6 +28,7 @@ use Illuminate\Support\Carbon;
  * @method static Builder|VerifyCode whereStatus($value)
  * @method static Builder|VerifyCode whereUpdatedAt($value)
  * @method static Builder|VerifyCode whereUsername($value)
+ * @method static Builder|VerifyCode whereAddress($value)
  */
 class VerifyCode extends Model
 {

+ 3 - 2
composer.json

@@ -10,9 +10,9 @@
   "require": {
     "php": "^7.2",
     "ext-curl": "*",
+    "ext-dom": "*",
     "ext-json": "*",
     "ext-openssl": "*",
-    "ext-dom": "*",
     "barryvdh/laravel-debugbar": "^3.2",
     "barryvdh/laravel-ide-helper": "^2.6",
     "fideloper/proxy": "^4.2",
@@ -32,7 +32,8 @@
     "predis/predis": "^1.1",
     "rap2hpoutre/laravel-log-viewer": "^1.3",
     "riverslei/payment": "*",
-    "spatie/laravel-permission": "^3.4"
+    "spatie/laravel-permission": "^3.4",
+    "xhat/payjs": "^1.4"
   },
   "require-dev": {
     "filp/whoops": "^2.7",

File diff suppressed because it is too large
+ 178 - 178
composer.lock


+ 3 - 1
resources/lang/en/auth.php

@@ -1,6 +1,7 @@
 <?php
 
 return [
+	'username'               => 'Username',
 	'active'                 => 'Activate',
 	'active_account'         => 'Activate account',
 	'active_tip'             => 'Account is not active yet, Please ',
@@ -10,7 +11,7 @@ return [
 	'register'               => 'Sign Up',
 	'send'                   => 'Send',
 	'tip'                    => 'Tip',
-	'username'               => 'Email',
+	'email'                  => 'Email',
 	'password'               => 'Password',
 	'confirm_password'       => 'Please renter your password',
 	'back'                   => 'Back',
@@ -45,6 +46,7 @@ return [
 	'captcha_close'              => 'Verification code registration is disable',
 	'captcha_send'               => 'Verification code sent',
 	'code_error'                 => 'The invitation code is invalid! Please try again',
+	'username_null'              => 'Please enter your username',
 	'email_null'                 => 'Please enter your email address',
 	'email_normal'               => 'Your account has been activated',
 	'email_legitimate'           => 'Account must be a legitimate email',

+ 2 - 2
resources/lang/en/home.php

@@ -8,7 +8,7 @@ return [
 	'exchange_subscribe'              => 'Exchange Address',
 	'subscribe_warning'               => 'Warning: This subscription address is for personal use only. Do not propagate the address.',
 	'reset_password_title'            => 'Reset Password',
-	'username_placeholder'            => 'Please Enter Email',
+	'email_placeholder'               => 'Please Enter Email',
 	'system_down'                     => 'The system is being maintained',
 	'subscribe_baned'                 => 'Your subscription function has been banned. Please contact the administrator.',
 	'download'                        => 'Download',
@@ -199,6 +199,6 @@ return [
 	'promote_link'                    => 'With your promotion link registration and activation, both of you will receive :traffic traffic awards; when they are consumed, you will receive :referral_percent% of their consumption amount as a reward.',
 	'promote_invite_code'             => 'With your invite code registration and activation, both of you will receive :traffic traffic awards; when they are consumed, you will receive :referral_percent% of their consumption amount as a reward.',
 	'invite_user_title'               => 'Invitation record',
-	'invite_user_username'            => 'Username',
+	'invite_user_email'               => 'email',
 	'invite_user_created_at'          => 'Registration time',
 ];

+ 30 - 30
resources/lang/ja/auth.php

@@ -1,35 +1,35 @@
 <?php
 
 return [
-	'title'                => 'アカウントを有効にする',
-	'login_button'         => 'ログイン',
-	'username_placeholder' => 'アカウントを入力してください',
-	'tips'                 => 'システムメンテナンス中に、アカウントを有効にする必要がある場合は、管理者に連絡してください',
-	'back'                 => '戻る',
-	'submit'               => '有効化',
-	'username'             => 'アカウント',
-	'password'             => 'パスワード',
-	'captcha'              => '認証コード',
-	'remember'             => 'ログイン状態を保持',
-	'forget_password'      => 'パスワードを忘れた',
-	'login'                => 'ログイン',
-	'register'             => '登録する',
-	'register_tip'         => 'まだアカウントはありませんか?してください',
-	'loading_captcha'      => '確認コードを読み込んでいます...',
-	'required_captcha'     => '確認コードの操作を正しく完了してください',
-	'fail_captcha'         => 'サーバーの確認に失敗しました。もう一度お試しください',
-	'confirm_password'     => 'パスワードの確認',
-	'code'                 => '招待コード',
-	'send'                 => '送 信',
-	'tnc_button'           => '私はすでに読んで守ることに同意した',
-	'tnc_link'             => '私は利用規約を読み、同意した',
-	'tos'                  => '利用規約',
-	'aup'                  => '許容される使用ポリシー',
-	'register_alter'       => 'システムはメンテナンス中です',
-	'get_free_code'        => 'クリックすると無料の招待状コードが表示されます',
-	'tnc_title'            => '私は読んだことがあります',
-	'tnc_content'          => '現地法令を遵守してください。',
-	'overtime'             => 'リンクは有効期限切れです',
+	'title'             => 'アカウントを有効にする',
+	'login_button'      => 'ログイン',
+	'email_placeholder' => 'アカウントを入力してください',
+	'tips'              => 'システムメンテナンス中に、アカウントを有効にする必要がある場合は、管理者に連絡してください',
+	'back'              => '戻る',
+	'submit'            => '有効化',
+	'email'             => 'アカウント',
+	'password'          => 'パスワード',
+	'captcha'           => '認証コード',
+	'remember'          => 'ログイン状態を保持',
+	'forget_password'   => 'パスワードを忘れた',
+	'login'             => 'ログイン',
+	'register'          => '登録する',
+	'register_tip'      => 'まだアカウントはありませんか?してください',
+	'loading_captcha'   => '確認コードを読み込んでいます...',
+	'required_captcha'  => '確認コードの操作を正しく完了してください',
+	'fail_captcha'      => 'サーバーの確認に失敗しました。もう一度お試しください',
+	'confirm_password'  => 'パスワードの確認',
+	'code'              => '招待コード',
+	'send'              => '送 信',
+	'tnc_button'        => '私はすでに読んで守ることに同意した',
+	'tnc_link'          => '私は利用規約を読み、同意した',
+	'tos'               => '利用規約',
+	'aup'               => '許容される使用ポリシー',
+	'register_alter'    => 'システムはメンテナンス中です',
+	'get_free_code'     => 'クリックすると無料の招待状コードが表示されます',
+	'tnc_title'         => '私は読んだことがあります',
+	'tnc_content'       => '現地法令を遵守してください。',
+	'overtime'          => 'リンクは有効期限切れです',
 
 	'active'                 => 'Activate',
 	'active_account'         => 'Activate account',
@@ -38,7 +38,7 @@ return [
 	'code'                   => 'Invite Code',
 	'login'                  => 'Sign In',
 	'register'               => 'ログイン',
-	'username'               => 'メール',
+	'email'                  => 'メール',
 	'password'               => 'パスワード',
 	'confirm_password'       => 'パスワードの確認',
 	'back'                   => 'Back',

+ 2 - 2
resources/lang/ja/home.php

@@ -7,7 +7,7 @@ return [
 	'exchange_subscribe'              => '変更',
 	'subscribe_warning'               => '警告:この購読URLは個人用です。このURLは拡散しないでください。それ以外の場合は、アカウントのデータ通信量が異常である可能性があります。',
 	'reset_password_title'            => 'パスワードを再設定する',
-	'username_placeholder'            => 'アカウントを入力してください',
+	'email_placeholder'               => 'アカウントを入力してください',
 	'system_down'                     => 'システムはメンテナンス中です',
 	'subscribe_baned'                 => '購読が無効になっています。管理者にお問い合わせください。',
 	'download'                        => 'ダウンロード',
@@ -196,6 +196,6 @@ return [
 	'promote_link'                    => 'あなたの普及のリンクを通じて登録してアクティブにして、あなたたちの双方はすべて :traffic の流量の奨励を獲得します;彼らが消費する時、あなたは彼らの消費金額の :referral_percent% を獲得することを奨励します。',
 	'promote_invite_code'             => 'お客様の招待コードの登録をアクティブにして、あなた達の双方は獲得して :traffic 流量奨励;彼らが消费の時、あなたは獲得して彼らの消費金額の :referral_percent% ご褒美として。',
 	'invite_user_title'               => '招待状',
-	'invite_user_username'            => 'ユーザー名',
+	'invite_user_email'               => 'ユーザー名',
 	'invite_user_created_at'          => '登録時間',
 ];

+ 28 - 28
resources/lang/ko/auth.php

@@ -1,33 +1,33 @@
 <?php
 
 return [
-	'title'                => '아이디 활성화',
-	'login_button'         => '로그인',
-	'username_placeholder' => '아이디를 입력하세요',
-	'tips'                 => '서버 점검중입니다,아이디 활성화 하실려면 관리자에게 문의하세요',
-	'back'                 => '돌아가기',
-	'submit'               => '활성화 하기',
-	'username'             => '아이디',
-	'password'             => '비밀번호',
-	'captcha'              => '인증코드',
-	'remember'             => '로그인 상태 유지',
-	'forget_password'      => '비밀번호 찾기',
-	'login'                => '로그인',
-	'register'             => '회원가입',
-	'register_tip'         => '아직 계정이 없습니까? 제발 가라',
-	'loading_captcha'      => '인증 코드로드 중 ...',
-	'required_captcha'     => '인증 코드 작업을 올바르게 완료하십시오.',
-	'fail_captcha'         => '서버 확인에 실패했습니다. 다시 시도하십시오.',
-	'confirm_password'     => '비밀번호 재확인',
-	'code'                 => '처청코드',
-	'send'                 => '보내기',
-	'tnc_button'           => '이용약관에 됭의합니다',
-	'tos'                  => '이용 약관',
-	'aup'                  => '이용 목적 제한 방침',
-	'register_alter'       => '서버 점검중입니다',
-	'get_free_code'        => '무료 초대 코드를 받으려면 클릭하십시오.',
-	'tnc_title'            => '이용약관에 됭의합니다',
-	'tnc_content'          => '현지의 법률 법규를 준수하시오.',
-	'overtime'             => '링크가 만료되었습니다.',
+	'title'             => '아이디 활성화',
+	'login_button'      => '로그인',
+	'email_placeholder' => '아이디를 입력하세요',
+	'tips'              => '서버 점검중입니다,아이디 활성화 하실려면 관리자에게 문의하세요',
+	'back'              => '돌아가기',
+	'submit'            => '활성화 하기',
+	'email'             => '아이디',
+	'password'          => '비밀번호',
+	'captcha'           => '인증코드',
+	'remember'          => '로그인 상태 유지',
+	'forget_password'   => '비밀번호 찾기',
+	'login'             => '로그인',
+	'register'          => '회원가입',
+	'register_tip'      => '아직 계정이 없습니까? 제발 가라',
+	'loading_captcha'   => '인증 코드로드 중 ...',
+	'required_captcha'  => '인증 코드 작업을 올바르게 완료하십시오.',
+	'fail_captcha'      => '서버 확인에 실패했습니다. 다시 시도하십시오.',
+	'confirm_password'  => '비밀번호 재확인',
+	'code'              => '처청코드',
+	'send'              => '보내기',
+	'tnc_button'        => '이용약관에 됭의합니다',
+	'tos'               => '이용 약관',
+	'aup'               => '이용 목적 제한 방침',
+	'register_alter'    => '서버 점검중입니다',
+	'get_free_code'     => '무료 초대 코드를 받으려면 클릭하십시오.',
+	'tnc_title'         => '이용약관에 됭의합니다',
+	'tnc_content'       => '현지의 법률 법규를 준수하시오.',
+	'overtime'          => '링크가 만료되었습니다.',
 
 ];

+ 2 - 2
resources/lang/ko/home.php

@@ -7,7 +7,7 @@ return [
 	'exchange_subscribe'              => '주소변경',
 	'subscribe_warning'               => '경고: 구독 주소 는 개인적 으로 사용 되 지 말고 이 주소 를 전파 하지 마시오',
 	'reset_password_title'            => '비번리셋',
-	'username_placeholder'            => '아이디를 입력하세요',
+	'email_placeholder'               => '아이디를 입력하세요',
 	'system_down'                     => '서비스 점금중',
 	'subscribe_baned'                 => '구독주소가 금지되였습니다,관리자에게 문의해주세요',
 	'download'                        => '다운로드',
@@ -193,6 +193,6 @@ return [
 	'promote_link'                    => '보급 링크 등록을 통해 활성화, 양측 모두 :traffic 유량에 장려합니다; 그들이 소비할 때, 그들의 소비 금액을 얻을 수 있는 :referral_percent% 를 장려합니다.',
 	'promote_invite_code'             => '요청을 통해 등록 및 활성화, 양측 모두 :traffic 유량에 장려합니다, 그들이 소비할 때, 그들의 소비 금액을 얻을 수 있습니다 :referral_percent% 를 장려합니다',
 	'invite_user_title'               => '초대장',
-	'invite_user_username'            => '사용자 이름',
+	'invite_user_email'               => '사용자 이름',
 	'invite_user_created_at'          => '등록 시간',
 ];

+ 3 - 1
resources/lang/zh-CN/auth.php

@@ -10,7 +10,7 @@ return [
 	'register'                   => '注 册',
 	'send'                       => '发送',
 	'tip'                        => '提示',
-	'username'                   => '邮箱',
+	'email'                      => '邮箱',
 	'password'                   => '密码',
 	'confirm_password'           => '请再次输入密码',
 	'back'                       => '返 回',
@@ -44,6 +44,7 @@ return [
 	'captcha_close'              => '本站关闭了通过验证码注册',
 	'captcha_send'               => '验证码已发送至您的邮箱,请稍作等待或查看垃圾箱',
 	'code_error'                 => '邀请码不可用,请重试',
+	'username_null'              => '请输入昵称',
 	'email_null'                 => '请输入邮箱账号',
 	'email_normal'               => '账号状态正常,无需激活',
 	'email_legitimate'           => '邮箱地址不合规',
@@ -69,5 +70,6 @@ return [
 	'reset_password_fail'        => '重设密码失败',
 	'reset_password_new'         => '新密码设置成功,请自行登录',
 	'request_error'              => '请求异常,请刷新页面后重试',
+	'username'                   => '昵称',
 	'unaccepted'                 => '请阅读用户条款和可接受使用条款,并同意'
 ];

+ 2 - 2
resources/lang/zh-CN/home.php

@@ -8,7 +8,7 @@ return [
 	'exchange_subscribe'              => '更换',
 	'subscribe_warning'               => '警告:该订阅链接仅限个人使用,请勿传播该链接,否则会导致您的账号流量使用情况异常触发自动封号机制。',
 	'reset_password_title'            => '重置密码',
-	'username_placeholder'            => '请输入用户名',
+	'email_placeholder'               => '请输入用户名',
 	'system_down'                     => '系统维护中',
 	'subscribe_baned'                 => '您的订阅功能被禁用,请联系管理员恢复',
 	'download'                        => '下载',
@@ -204,6 +204,6 @@ return [
 	'promote_link'                    => '通过您的推广链接注册并激活,你们双方都将获得<mark>:traffic</mark>流量奖励;当他们消费时,您将获得他们消费金额的<mark>:referral_percent%</mark>作为奖励。',
 	'promote_invite_code'             => '通过您的邀请码注册并激活,你们双方都将获得<mark>:traffic</mark>流量奖励;当他们消费时,您将获得他们消费金额的<mark>:referral_percent%</mark>作为奖励。',
 	'invite_user_title'               => '邀请记录',
-	'invite_user_username'            => '用户名',
+	'invite_user_email'               => '邮箱',
 	'invite_user_created_at'          => '注册时间',
 ];

+ 3 - 2
resources/lang/zh-tw/auth.php

@@ -10,7 +10,7 @@ return [
 	'register'               => '注 冊',
 	'send'                   => '發送',
 	'tip'                    => '提示',
-	'username'               => '郵箱',
+	'email'                  => '郵箱',
 	'password'               => '密碼',
 	'confirm_password'       => '請再次輸入密碼',
 	'back'                   => '返 回',
@@ -68,5 +68,6 @@ return [
 	'reset_password_same_fail'   => '新舊密碼一樣,請重新輸入',
 	'reset_password_fail'        => '重設密碼失敗',
 	'reset_password_new'         => '新密碼設置成功,請自行登錄',
-	'request_error'              => '請求異常,請刷新頁面後重試'
+	'request_error'              => '請求異常,請刷新頁面後重試',
+	'username'                   => '昵稱'
 ];

+ 3 - 3
resources/lang/zh-tw/home.php

@@ -3,12 +3,12 @@
 return [
 	'panel'                           => '用戶中心',
 	'subscribe_help'                  => '互動式教程',
-	'subscribe_help'                  => '訂閱鏈接',
+	'subscribe_link'                  => '訂閱鏈接',
 	'copy_subscribe_address'          => '複製',
 	'exchange_subscribe'              => '更換',
 	'subscribe_warning'               => '注意:該訂閱鏈接僅限個人使用,請勿傳播該鏈接,這會導致您的帳號流量使用情况异常。',
 	'reset_password_title'            => '重置密碼',
-	'username_placeholder'            => '請輸入用戶名',
+	'email_placeholder'               => '請輸入用戶名',
 	'system_down'                     => '系統維護中',
 	'subscribe_baned'                 => '您的訂閱功能被暫時禁用,請聯系管理員恢復',
 	'download'                        => '下載',
@@ -197,6 +197,6 @@ return [
 	'promote_link'                    => '通過您的推廣連結注册並啟動,您和新用戶都會獲得 :traffic 流量獎勵;當他們消費時,您將獲得他們消費金額的 :referral_percent% 作為獎勵。',
 	'promote_invite_code'             => '通過您的邀請碼注册並啟動,您和新用戶都會獲得 :traffic 流量獎勵;當他們消費時,您將獲得他們消費金額的 :referral_percent% 作為獎勵。',
 	'invite_user_title'               => '邀請記錄',
-	'invite_user_username'            => '用戶名',
+	'invite_user_email'               => '郵箱',
 	'invite_user_created_at'          => '註冊時間',
 ];

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

@@ -15,9 +15,9 @@
 						<div class="col-lg-6">
 							<h4 class="example-title">账号信息</h4>
 							<div class="form-group row">
-								<label class="col-md-2 col-sm-3 col-form-label" for="username">用户名</label>
+								<label class="col-md-2 col-sm-3 col-form-label" for="email">邮箱</label>
 								<div class="col-xl-6 col-sm-8">
-									<input type="text" class="form-control" name="username" id="username" autocomplete="off" autofocus required/>
+									<input type="text" class="form-control" name="email" id="email" autocomplete="off" autofocus required/>
 								</div>
 							</div>
 							<div class="form-group row">
@@ -351,7 +351,7 @@
                 async: false,
                 data: {
                     _token: '{{csrf_token()}}',
-                    username: $('#username').val(),
+                    email: $('#email').val(),
                     password: $('#password').val(),
                     usage: usage.substring(0, usage.length - 1),
                     pay_way: $("input:radio[name='pay_way']:checked").val(),

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

@@ -21,7 +21,7 @@
 					<table class="text-md-center" data-toggle="table" data-mobile-responsive="true">
 						<thead class="thead-default">
 						<tr>
-							<th colspan="6">申请单ID:{{$info->id}} | 申请人:{{$info->user->username}} | 申请提现金额:¥{{$info->amount}} | 申请时间:{{$info->created_at}}</th>
+							<th colspan="6">申请单ID:{{$info->id}} | 申请人:{{$info->user->email}} | 申请提现金额:¥{{$info->amount}} | 申请时间:{{$info->created_at}}</th>
 						</tr>
 						<tr>
 							<th> #</th>
@@ -41,7 +41,7 @@
 							@foreach($list as $vo)
 								<tr>
 									<td> {{$vo->id}} </td>
-									<td> {{empty($vo->user) ? '【账号已删除】' : $vo->user->username}} </td>
+									<td> {{empty($vo->user) ? '【账号已删除】' : $vo->user->email}} </td>
 									<td>
 										<a href="/admin/orderList?order_sn={{$vo->order->order_sn}}" target="_blank">{{$vo->order->goods->name}}</a>
 									</td>

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

@@ -11,7 +11,7 @@
 			<div class="panel-body">
 				<div class="form-row">
 					<div class="form-group col-lg-2 col-sm-4">
-						<input type="text" class="form-control" name="username" value="{{Request::get('username')}}" id="username" placeholder="申请账号"/>
+						<input type="text" class="form-control" name="email" value="{{Request::get('email')}}" id="email" placeholder="申请账号"/>
 					</div>
 					<div class="form-group col-lg-2 col-sm-4">
 						<select class="form-control" name="status" id="status" onChange="Search()">
@@ -53,7 +53,7 @@
 									@if(empty($apply->user))
 										【账号已删除】
 									@else
-										<a href="/admin/userList?id={{$apply->user_id}}" target="_blank">{{$apply->user->username}}</a>
+										<a href="/admin/userList?id={{$apply->user_id}}" target="_blank">{{$apply->user->email}}</a>
 									@endif
 								</td>
 								<td> ¥{{$apply->amount}} </td>
@@ -116,7 +116,7 @@
 
         // 搜索
         function Search() {
-            window.location.href = '/admin/applyList?username=' + $("#username").val() + '&status=' + $("#status option:selected").val();
+            window.location.href = '/admin/applyList?email=' + $("#email").val() + '&status=' + $("#status option:selected").val();
         }
 
         // 更改状态

+ 10 - 3
resources/views/admin/editUser.blade.php

@@ -18,9 +18,15 @@
 						<div class="col-lg-6">
 							<h4 class="example-title">账号信息</h4>
 							<div class="form-group row">
-								<label class="col-md-2 col-sm-3 col-form-label" for="username">用户名</label>
+								<label class="col-md-2 col-sm-3 col-form-label" for="username">昵称</label>
 								<div class="col-xl-6 col-sm-8">
-									<input type="text" class="form-control" name="username" value="{{$user->username}}" id="username" autocomplete="off" autofocus required/>
+									<input type="text" class="form-control" name="username" value="{{$user->username}}" id="username" autocomplete="off" required/>
+								</div>
+							</div>
+							<div class="form-group row">
+								<label class="col-md-2 col-sm-3 col-form-label" for="email">邮箱</label>
+								<div class="col-xl-6 col-sm-8">
+									<input type="text" class="form-control" name="email" value="{{$user->email}}" id="email" autocomplete="off" autofocus required/>
 								</div>
 							</div>
 							<div class="form-group row">
@@ -224,7 +230,7 @@
 							<div class="form-group row">
 								<label class="col-md-2 col-sm-3 col-form-label" for="referral_uid">邀请人</label>
 								<div class="col-xl-6 col-sm-8">
-									<p class="form-control"> {{empty($user->referral) ? '无邀请人' : $user->referral->username}} </p>
+									<p class="form-control"> {{empty($user->referral) ? '无邀请人' : $user->referral->email}} </p>
 								</div>
 							</div>
 						</div>
@@ -435,6 +441,7 @@
                 data: {
                     _token: '{{csrf_token()}}',
                     username: $('#username').val(),
+                    email: $('#email').val(),
                     password: $('#password').val(),
                     usage: usage.substring(0, usage.length - 1),
                     pay_way: $("input:radio[name='pay_way']:checked").val(),

+ 2 - 2
resources/views/admin/emailLog.blade.php

@@ -11,7 +11,7 @@
 			<div class="panel-body">
 				<div class="form-row">
 					<div class="form-group col-lg-3 col-sm-4">
-						<input type="text" class="form-control" name="username" id="username" value="{{Request::get('username')}}" placeholder="用户名"/>
+						<input type="text" class="form-control" name="email" id="email" value="{{Request::get('email')}}" placeholder="用户名"/>
 					</div>
 					<div class="form-group col-lg-2 col-sm-4">
 						<select class="form-control" name="type" id="type" onChange="Search()">
@@ -92,7 +92,7 @@
 	<script type="text/javascript">
         // 搜索
         function Search() {
-            window.location.href = '/admin/emailLog?username=' + $("#username").val() + '&type=' + $("#type option:selected").val();
+            window.location.href = '/admin/emailLog?email=' + $("#email").val() + '&type=' + $("#type option:selected").val();
         }
 	</script>
 @endsection

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

@@ -7,7 +7,7 @@
 	<div class="page-content container-fluid">
 		<div class="panel">
 			<div class="panel-heading">
-				<h2 class="panel-title">【{{$user->username}}】连接配置信息</h2>
+				<h2 class="panel-title">【{{$user->email}}】连接配置信息</h2>
 			</div>
 			<div class="panel-body">
 				<table class="text-md-center" data-toggle="table" data-mobile-responsive="true">

+ 2 - 2
resources/views/admin/inviteList.blade.php

@@ -54,13 +54,13 @@
 										</td>
 										<td> {{$invite->dateline}} </td>
 										<td>
-											{{$invite->uid == 0 ? '系统生成' : (empty($invite->generator) ? '【账号已删除】' : $invite->generator->username)}}
+											{{$invite->uid == 0 ? '系统生成' : (empty($invite->generator) ? '【账号已删除】' : $invite->generator->email)}}
 										</td>
 										<td>
 											{!!$invite->status_label!!}
 										</td>
 										<td>
-											{{$invite->status == 1 ? (empty($invite->user) ? '【账号已删除】' : $invite->user->username) : ''}}
+											{{$invite->status == 1 ? (empty($invite->user) ? '【账号已删除】' : $invite->user->email) : ''}}
 										</td>
 									</tr>
 								@endforeach

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

@@ -145,11 +145,21 @@
 				<a href="javascript:void(0)">
 					<i class="site-menu-icon wb-chat-working" aria-hidden="true"></i>
 					<span class="site-menu-title">客服系统</span>
+					@if(\App\Http\Models\Ticket::query()->where('status','=','0')->count() > 0 )
+						<div class="site-menu-badge">
+							<span class="badge badge-pill badge-success">{{\App\Http\Models\Ticket::query()->where('status','=','0')->count()}}</span>
+						</div>
+					@endif
 				</a>
 				<ul class="site-menu-sub">
 					<li class="site-menu-item {{in_array(Request::path(), ['ticket/ticketList', 'ticket/addTicket','ticket/replyTicket']) ? 'active open' : ''}}">
 						<a href="/ticket/ticketList" class="animsition-link">
 							<span class="site-menu-title">服务工单</span>
+							@if(\App\Http\Models\Ticket::query()->where('status','=','0')->count() > 0 )
+								<div class="site-menu-label">
+									<span class="badge badge-danger badge-round mr-25">{{\App\Http\Models\Ticket::query()->where('status','=','0')->count()}}</span>
+								</div>
+							@endif
 						</a>
 					</li>
 					<li class="site-menu-item {{in_array(Request::path(), ['admin/articleList', 'admin/addArticle', 'admin/editArticle']) ? 'active open' : ''}}">
@@ -169,7 +179,7 @@
 					</li>
 				</ul>
 			</li>
-			<li class="site-menu-item has-sub {{in_array(Request::path(), ['admin/nodeList', 'admin/addNode', 'admin/editNode', 'admin/nodeMonitor', 'admin/labelList', 'admin/addLabel', 'admin/editLabel', 'admin/groupList', 'admin/addGroup', 'admin/editGroup']) ? 'active open' : ''}}">
+			<li class="site-menu-item has-sub {{in_array(Request::path(), ['admin/nodeList', 'admin/addNode', 'admin/editNode', 'admin/nodeMonitor', 'admin/labelList', 'admin/addLabel', 'admin/editLabel', 'admin/groupList', 'admin/addGroup', 'admin/editGroup','admin/nodePingLog']) ? 'active open' : ''}}">
 				<a href="javascript:void(0)">
 					<i class="site-menu-icon wb-grid-4" aria-hidden="true"></i>
 					<span class="site-menu-title">线路系统</span>
@@ -190,6 +200,11 @@
 							<span class="site-menu-title">分组管理</span>
 						</a>
 					</li>
+					<li class="site-menu-item {{in_array(Request::path(), ['admin/nodePingLog']) ? 'active open' : ''}}">
+						<a href="/admin/nodePingLog">
+							<span class="site-menu-title">测速日志</span>
+						</a>
+					</li>
 				</ul>
 			</li>
 			<li class="site-menu-item has-sub {{in_array(Request::path(), ['shop/goodsList', 'shop/addGoods', 'shop/editGoods', 'coupon/couponList', 'coupon/addCoupon','admin/orderList']) ? 'active open' : ''}}">

+ 59 - 38
resources/views/admin/nodeList.blade.php

@@ -35,47 +35,46 @@
 					</tr>
 					</thead>
 					<tbody>
-					@if($nodeList->isEmpty())
+					@forelse($nodeList as $node)
+						<tr class="{{!$node->isOnline && $node->status ? 'table-danger' : ''}}">
+							<td>
+								{{$node->id}}
+							</td>
+							<td>
+								@if($node->is_transit)
+									中转
+								@else
+									{{$node->type == 2 ? 'V2' : 'SSR'}}
+								@endif
+							</td>
+							<td> {{$node->name}} </td>
+							<td> {{$node->is_ddns ? 'DDNS' : $node->ip}} </td>
+							<td> {{$node->server}} </td>
+							<td> {{$node->uptime}} </td>
+							<td> {{$node->status? $node->load : '维护'}} </td>
+							<td> {{$node->online_users}} </td>
+							<td> {{$node->transfer}} </td>
+							<td> {{$node->traffic_rate}} </td>
+							<td>
+								@if($node->compatible) <span class="badge badge-lg badge-info">兼</span> @endif
+								@if($node->single) <span class="badge badge-lg badge-info">单</span> @endif
+								@if(!$node->is_subscribe) <span class="badge badge-lg badge-danger"><s>订</s></span> @endif
+							</td>
+							<td>
+								<div class="btn-group">
+									<a href="javascript:pingNode('{{$node->id}}')" class="btn btn-primary"><i id="ping{{$node->id}}" class="icon wb-order"></i></a>
+									<a href="javascript:testNode('{{$node->id}}')" class="btn btn-primary"><i id="node{{$node->id}}" class="icon wb-signal"></i></a>
+									<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}}','{{$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>
+						</tr>
+					@empty
 						<tr>
 							<td colspan="12">暂无数据</td>
 						</tr>
-					@else
-						@foreach($nodeList as $node)
-							<tr class="{{!$node->isOnline && $node->status ? 'table-danger' : ''}}">
-								<td>
-									{{$node->id}}
-								</td>
-								<td>
-									@if($node->is_transit)
-										中转
-									@else
-										{{$node->type == 2 ? 'V2' : 'SSR'}}
-									@endif
-								</td>
-								<td> {{$node->name}} </td>
-								<td> {{$node->is_ddns ? 'DDNS' : $node->ip}} </td>
-								<td> {{$node->server}} </td>
-								<td> {{$node->uptime}} </td>
-								<td> {{$node->status? $node->load : '维护'}} </td>
-								<td> {{$node->online_users}} </td>
-								<td> {{$node->transfer}} </td>
-								<td> {{$node->traffic_rate}} </td>
-								<td>
-									@if($node->compatible) <span class="badge badge-lg badge-info">兼</span> @endif
-									@if($node->single) <span class="badge badge-lg badge-info">单</span> @endif
-									@if(!$node->is_subscribe) <span class="badge badge-lg badge-danger"><s>订</s></span> @endif
-								</td>
-								<td>
-									<div class="btn-group">
-										<a href="javascript:testNode('{{$node->id}}')" class="btn btn-primary"><i id="node{{$node->id}}" class="icon wb-signal"></i></a>
-										<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}}','{{$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>
-							</tr>
-						@endforeach
-					@endif
+					@endforelse
 					</tbody>
 				</table>
 			</div>
@@ -120,6 +119,28 @@
             });
         }
 
+        //Ping 节点获取延迟
+        function pingNode(id) {
+            $.ajax({
+                type: "POST",
+                url: '/admin/pingNode',
+                data: {_token: '{{csrf_token()}}', id: id},
+                beforeSend: function () {
+                    $("#ping" + id).removeClass("wb-order").addClass("wb-loop icon-spin");
+                },
+                success: function (ret) {
+                    if (ret.status === 'success') {
+                        swal.fire({type: 'info', html: '<table class="my-20"><thead class="thead-default"><tr><th> 电信 </th> <th> 联通 </th> <th> 移动 </th> <th> 香港 </th></thead><tbody><tr><td>' + ret.message[0] + '</td><td>' + ret.message[1] + '</td><td>' + ret.message[2] + '</td><td>' + ret.message[3] + '</td></tr></tbody></table>', showConfirmButton: false})
+                    } else {
+                        swal.fire({title: ret.title, type: "error"})
+                    }
+                },
+                complete: function () {
+                    $("#ping" + id).removeClass("wb-loop icon-spin").addClass("wb-order");
+                }
+            });
+        }
+
         // 删除节点
         function delNode(id, name) {
             swal.fire({

+ 84 - 0
resources/views/admin/nodePingLog.blade.php

@@ -0,0 +1,84 @@
+@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">
+				<h2 class="panel-title">线路Ping测速日志</h2>
+			</div>
+			<div class="panel-body">
+				<div class="form-row">
+					<div class="form-group col-lg-2 col-sm-5">
+						<select name="nodeId" id="nodeId" class="form-control" onChange="Search()">
+							<option value="" @if(Request::get('nodeId') == '') selected @endif>选择节点</option>
+							@foreach($nodeList as $node)
+								<option value="{{$node->id}}" @if(Request::get('nodeId') == $node->id) selected @endif>{{$node->name}}</option>
+							@endforeach
+						</select>
+					</div>
+					<div class="form-group col-lg-1 col-sm-4 btn-group">
+						<button class="btn btn-primary" onclick="Search()">搜 索</button>
+						<a href="/admin/nodePingLog" class="btn btn-danger">重 置</a>
+					</div>
+				</div>
+				<table class="text-md-center" data-toggle="table" data-mobile-responsive="true">
+					<thead class="thead-default">
+					<tr>
+						<th rowspan="2"> #</th>
+						<th rowspan="2"> 节点</th>
+						<th colspan="4"> 速度</th>
+					</tr>
+					<tr>
+						<th>电信</th>
+						<th>联通</th>
+						<th>移动</th>
+						<th>香港</th>
+					</tr>
+					</thead>
+					<tbody>
+					@if($pingLogs->isEmpty())
+						<tr>
+							<td colspan="8">暂无数据</td>
+						</tr>
+					@else
+						@foreach($pingLogs as $log)
+							<tr>
+								<td> {{$log->id}} </td>
+								<td> {{$log->node->name}} </td>
+								<td> {{$log->ct? $log->ct.' ms': '无'}} </td>
+								<td> {{$log->cu? $log->cu.' ms': '无'}} </td>
+								<td> {{$log->cm? $log->cm.' ms': '无'}} </td>
+								<td> {{$log->hk? $log->hk.' ms': '无'}} </td>
+							</tr>
+						@endforeach
+					@endif
+					</tbody>
+				</table>
+			</div>
+			<div class="panel-footer">
+				<div class="row">
+					<div class="col-sm-4">
+						共 <code>{{$pingLogs->total()}}</code> 条记录
+					</div>
+					<div class="col-sm-8">
+						<nav class="Page navigation float-right">
+							{{$pingLogs->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>
+	<script type="text/javascript">
+        // 搜索
+        function Search() {
+            window.location.href = '/admin/nodePingLog?&nodeId=' + $("#nodeId option:selected").val();
+        }
+	</script>
+@endsection

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

@@ -16,7 +16,7 @@
 						<input type="number" class="form-control" name="id" id="id" value="{{Request::get('id')}}" placeholder="ID"/>
 					</div>
 					<div class="form-group col-lg-2 col-sm-5">
-						<input type="text" class="form-control" name="username" id="username" value="{{Request::get('username')}}" placeholder="用户名"/>
+						<input type="text" class="form-control" name="email" id="email" value="{{Request::get('email')}}" placeholder="用户名"/>
 					</div>
 					<div class="form-group col-lg-2 col-sm-5">
 						<input type="text" class="form-control" name="ip" id="ip" value="{{Request::get('ip')}}" placeholder="IP"/>
@@ -62,7 +62,7 @@
 								<td>{{$vo->created_at}}</td>
 								<td>{{$vo->type}}</td>
 								<td>{{$vo->node ? $vo->node->name : '【节点已删除】'}}</td>
-								<td>{{$vo->user ? $vo->user->username : '【用户已删除】'}}</td>
+								<td>{{$vo->user ? $vo->user->email : '【用户已删除】'}}</td>
 								<td>{{$vo->user ? $vo->user->address : '【用户已删除】'}}</td>
 								<td>
 									@if (strpos($vo->ip, ',') == TRUE)
@@ -110,7 +110,7 @@
 
         // 搜索
         function Search() {
-            window.location.href = '/admin/onlineIPMonitor?id=' + $("#id").val() + '&ip=' + $("#ip").val() + '&username=' + $("#username").val() + '&port=' + $("#port").val() + '&nodeId=' + $("#nodeId option:selected").val();
+            window.location.href = '/admin/onlineIPMonitor?id=' + $("#id").val() + '&ip=' + $("#ip").val() + '&email=' + $("#email").val() + '&port=' + $("#port").val() + '&nodeId=' + $("#nodeId option:selected").val();
         }
 	</script>
 @endsection

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

@@ -12,7 +12,7 @@
 			<div class="panel-body">
 				<div class="form-row">
 					<div class="form-group col-lg-2 col-sm-6">
-						<input type="text" class="form-control" name="username" id="username" value="{{Request::get('username')}}" placeholder="用户名"/>
+						<input type="text" class="form-control" name="email" id="email" value="{{Request::get('email')}}" placeholder="用户名"/>
 					</div>
 					<div class="form-group col-lg-2 col-sm-6">
 						<input type="number" class="form-control" name="order_sn" id="order_sn" value="{{Request::get('order_sn')}}" placeholder="订单号"/>
@@ -107,7 +107,7 @@
 									@if(empty($order->user) )
 										【账号不存在】
 									@else
-										<a href="/admin/userList?id={{$order->user->id}}" target="_blank">{{$order->user->username}} </a>
+										<a href="/admin/userList?id={{$order->user->id}}" target="_blank">{{$order->user->email}} </a>
 									@endif
 								</td>
 								<td> {{$order->order_sn}}</td>
@@ -183,7 +183,7 @@
 
         // 搜索
         function Search() {
-            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()];
+            window.location.href = '/admin/orderList?email=' + $("#email").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

+ 31 - 0
resources/views/admin/system.blade.php

@@ -164,6 +164,37 @@
 											<span class="text-help offset-md-3"> 如果是机器人、爬虫、代理访问网站则会抛出404错误 </span>
 										</div>
 									</div>
+									<div class="form-group col-lg-6">
+										<div class="row">
+											<label class="col-md-3 col-form-label" for="maintenance_mode">维护模式</label>
+											<span class="col-md-9"><input type="checkbox" id="maintenance_mode" data-plugin="switchery" @if($maintenance_mode) checked @endif onchange="updateFromOther('switch','maintenance_mode')"></span>
+											<span class="text-help offset-md-3"> 启用后,用户访问将转移至维护界面 </span>
+										</div>
+									</div>
+									<div class="form-group col-lg-6">
+										<div class="row">
+											<label class="col-md-3" for="maintenance_time">维护结束时间</label>
+											<div class="col-md-6">
+												<div class="input-group">
+													<input type="datetime-local" class="form-control" name="maintenance_time" id="maintenance_time" value="{{$maintenance_time}}" />
+													<span class="input-group-append"><button class="btn btn-primary" type="button" onclick="update('maintenance_time')">修改</button></span>
+												</div>
+											</div>
+											<span class="offset-md-3 text-help"> 用于维护界面倒计时 </span>
+										</div>
+									</div>
+									<div class="form-group col-lg-6">
+										<div class="row">
+											<label class="col-md-3" for="maintenance_content">维护介绍内容</label>
+											<div class="col-md-6">
+												<div class="input-group">
+													<textarea class="form-control" rows="3" name="maintenance_content" id="maintenance_content">{{$maintenance_content}}</textarea>
+													<span class="input-group-append"><button class="btn btn-primary" type="button" onclick="update('maintenance_content')">修改</button></span>
+												</div>
+											</div>
+											<span class="offset-md-3 text-help"> 自定义维护内容信息 </span>
+										</div>
+									</div>
 								</div>
 							</form>
 						</div>

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

@@ -15,7 +15,7 @@
 						<input type="number" class="form-control" name="user_id" id="user_id" value="{{Request::get('user_id')}}" placeholder="用户ID"/>
 					</div>
 					<div class="form-group col-lg-3 col-sm-8">
-						<input type="text" class="form-control" name="username" id="username" value="{{Request::get('username')}}" placeholder="用户名"/>
+						<input type="text" class="form-control" name="email" id="email" value="{{Request::get('email')}}" placeholder="用户名"/>
 					</div>
 					<div class="form-group col-lg-2 col-sm-4">
 						<input type="number" class="form-control" name="port" id="port" value="{{Request::get('port')}}" placeholder="用户端口"/>
@@ -71,7 +71,7 @@
 									@if(empty($vo->user))
 										【账号已删除】
 									@else
-										<a href="/admin/userList?id={{$vo->user->id}}" target="_blank"> {{$vo->user->username}} </a>
+										<a href="/admin/userList?id={{$vo->user->id}}" target="_blank"> {{$vo->user->email}} </a>
 									@endif
 								</td>
 								<td> {{$vo->node ? $vo->node->name : '【节点已删除】'}} </td>
@@ -121,7 +121,7 @@
 
         // 搜索
         function Search() {
-            window.location.href = '/admin/trafficLog' + '?port=' + $("#port").val() + '&user_id=' + $("#user_id").val() + '&username=' + $("#username").val() + '&nodeId=' + $("#nodeId option:selected").val() + '&startTime=' +$("#start").val() + '&endTime=' + $("#end").val();
+            window.location.href = '/admin/trafficLog' + '?port=' + $("#port").val() + '&user_id=' + $("#user_id").val() + '&email=' + $("#email").val() + '&nodeId=' + $("#nodeId option:selected").val() + '&startTime=' + $("#start").val() + '&endTime=' + $("#end").val();
         }
 	</script>
 @endsection

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

@@ -11,7 +11,7 @@
 			<div class="panel-body">
 				<div class="form-row">
 					<div class="form-group col-lg-3 col-sm-6">
-						<input type="text" class="form-control" name="username" id="username" value="{{Request::get('username')}}" placeholder="用户名"/>
+						<input type="text" class="form-control" name="email" id="email" value="{{Request::get('email')}}" placeholder="用户名"/>
 					</div>
 					<div class="form-group col-lg-2 col-sm-6 btn-group">
 						<button class="btn btn-primary" onclick="Search()">搜 索</button>
@@ -44,7 +44,7 @@
 									@if(empty($vo->user))
 										【账号已删除】
 									@else
-										<a href="/admin/userBalanceLogList?username={{$vo->user->username}}"> {{$vo->user->username}} </a>
+										<a href="/admin/userBalanceLogList?email={{$vo->user->email}}"> {{$vo->user->email}} </a>
 									@endif
 								</td>
 								<td> {{$vo->order_id}} </td>
@@ -88,7 +88,7 @@
 
         // 搜索
         function Search() {
-            window.location.href = '/admin/userBalanceLogList?username=' + $("#username").val();
+            window.location.href = '/admin/userBalanceLogList?email=' + $("#email").val();
         }
 	</script>
 @endsection

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

@@ -11,7 +11,7 @@
 			<div class="panel-body">
 				<div class="form-row">
 					<div class="form-group col-lg-3 col-sm-6">
-						<input type="text" class="form-control" name="username" id="username" value="{{Request::get('username')}}" placeholder="用户名"/>
+						<input type="text" class="form-control" name="email" id="email" value="{{Request::get('email')}}" placeholder="用户名"/>
 					</div>
 					<div class="form-group col-lg-2 col-sm-6 btn-group">
 						<button class="btn btn-primary" onclick="Search()">搜 索</button>
@@ -38,9 +38,9 @@
 						@foreach($list as $vo)
 							<tr>
 								<td>
-									<a href="/admin/userList?username={{$vo->id}}" target="_blank" rel="noopener"> {{$vo->id}}</a>
+									<a href="/admin/userList?email={{$vo->id}}" target="_blank" rel="noopener"> {{$vo->id}}</a>
 								</td>
-								<td> {{empty($vo->user) ? '【账号已删除】' : $vo->user->username}} </td>
+								<td> {{empty($vo->user) ? '【账号已删除】' : $vo->user->email}} </td>
 								<td> {{$vo->minutes}}分钟</td>
 								<td> {{$vo->desc}} </td>
 								<td> {{$vo->created_at}} </td>
@@ -80,7 +80,7 @@
 
         // 搜索
         function Search() {
-            window.location.href = '/admin/userBanLogList?username=' + $("#username").val();
+            window.location.href = '/admin/userBanLogList?email=' + $("#email").val();
         }
 	</script>
 @endsection

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

@@ -26,7 +26,7 @@
 						<input type="number" class="form-control" id="id" name="id" value="{{Request::get('id')}}" placeholder="ID"/>
 					</div>
 					<div class="form-group col-xxl-2 col-lg-3 col-md-3 col-sm-4">
-						<input type="text" class="form-control" id="username" name="username" value="{{Request::get('username')}}" placeholder="用户名"/>
+						<input type="text" class="form-control" id="email" name="email" value="{{Request::get('email')}}" placeholder="用户名"/>
 					</div>
 					<div class="form-group col-xxl-2 col-lg-3 col-md-3 col-sm-4">
 						<input type="text" class="form-control" id="wechat" name="wechat" value="{{Request::get('wechat')}}" placeholder="微信"/>
@@ -92,7 +92,7 @@
 						@foreach ($userList as $user)
 							<tr class="{{$user->trafficWarning ? ' table-danger' : ''}}">
 								<td> {{$user->id}} </td>
-								<td> {{$user->username}} </td>
+								<td> {{$user->email}} </td>
 								<td> {{$user->balance}} </td>
 								<td>
 									{!!$user->port? : '<span class="badge badge-lg badge-danger"> 未分配 </span>'!!}
@@ -129,11 +129,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}}','{{$user->username}}');" class="btn btn-danger"><i class="icon wb-trash" aria-hidden="true"></i></a>
+										<a href="javascript:delUser('{{$user->id}}','{{$user->email}}');" 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}}','{{$user->username}}');" class="btn btn-primary"><i class="icon wb-reload" aria-hidden="true"></i></a>
+										<a href="javascript:resetTraffic('{{$user->id}}','{{$user->email}}');" 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>
@@ -212,14 +212,14 @@
 
         // 搜索
         function Search() {
-            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();
+            window.location.href = '/admin/userList' + '?id=' + $("#id").val() + '&email=' + $("#email").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, username) {
+        function delUser(id, email) {
             swal.fire({
                 title: '警告',
-                text: '确定删除用户 【' + username + '】 ?',
+                text: '确定删除用户 【' + email + '】 ?',
                 type: 'warning',
                 showCancelButton: true,
                 cancelButtonText: '{{trans('home.ticket_close')}}',
@@ -239,10 +239,10 @@
         }
 
         // 重置流量
-        function resetTraffic(id, username) {
+        function resetTraffic(id, email) {
             swal.fire({
                 title: '警告',
-                text: '确定重置 【' + username + '】 流量吗?',
+                text: '确定重置 【' + email + '】 流量吗?',
                 type: 'warning',
                 showCancelButton: true,
                 cancelButtonText: '{{trans('home.ticket_close')}}',

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

@@ -7,7 +7,7 @@
 			</div>
 			<div class="alert alert-info alert-dismissible">
 				<button class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span><span class="sr-only">{{trans('home.close')}}</span></button>
-				<h4 class="block">{{$username}}</h4>
+				<h4 class="block">{{$email}}</h4>
 				<strong>提示:</strong> 月流量统计不会统计当天,日流量统计不会统计当前小时;如果无统计数据,请检查定时任务是否正常。(每月1日和每日0时因为没有统计流量,不显示流量)
 			</div>
 			<div class="panel-body">

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

@@ -16,7 +16,7 @@
 						<input type="number" class="form-control" id="id" name="id" value="{{Request::get('id')}}" placeholder="ID"/>
 					</div>
 					<div class="form-group col-lg-3 col-sm-8">
-						<input type="text" class="form-control" name="username" id="username" value="{{Request::get('username')}}" placeholder="用户名"/>
+						<input type="text" class="form-control" name="email" id="email" value="{{Request::get('email')}}" placeholder="用户名"/>
 					</div>
 					<div class="form-group col-lg-2 col-sm-6">
 						<input type="text" class="form-control" name="wechat" id="wechat" value="{{Request::get('wechat')}}" placeholder="微信"/>
@@ -52,7 +52,7 @@
 						@foreach ($userList as $user)
 							<tr>
 								<td> {{$user->id}} </td>
-								<td> {{$user->username}} </td>
+								<td> {{$user->email}} </td>
 								<td> {{$user->port}} </td>
 								<td>
 									@if ($user->status > 0)
@@ -131,7 +131,7 @@
 
         // 搜索
         function Search() {
-            window.location.href = '/admin/userOnlineIPList' + '?id' + $("#id").val() + '&username=' + $("#username").val() + '&wechat=' + $("#wechat").val() + '&qq=' + $("#qq").val() + '&port=' + $("#port").val();
+            window.location.href = '/admin/userOnlineIPList' + '?id' + $("#id").val() + '&email=' + $("#email").val() + '&wechat=' + $("#wechat").val() + '&qq=' + $("#qq").val() + '&port=' + $("#port").val();
         }
 	</script>
 @endsection

+ 5 - 5
resources/views/admin/userRebateList.blade.php

@@ -11,10 +11,10 @@
 			<div class="panel-body">
 				<div class="form-row">
 					<div class="form-group col-lg-4 col-sm-6">
-						<input type="text" class="form-control" name="username" id="username" value="{{Request::get('username')}}" placeholder="消费者"/>
+						<input type="text" class="form-control" name="email" id="email" value="{{Request::get('email')}}" placeholder="消费者"/>
 					</div>
 					<div class="form-group col-lg-4 col-sm-6">
-						<input type="text" class="form-control" name="ref_username" id="ref_username" value="{{Request::get('ref_username')}}" placeholder="邀请人"/>
+						<input type="text" class="form-control" name="ref_email" id="ref_email" value="{{Request::get('ref_email')}}" placeholder="邀请人"/>
 					</div>
 					<div class="form-group col-lg-2 col-sm-6">
 						<select name="status" id="status" class="form-control" onChange="Search()">
@@ -56,14 +56,14 @@
 									@if(empty($vo->user))
 										【账号已删除】
 									@else
-										<a href="/admin/userRebateList?username={{$vo->user->username}}"> {{$vo->user->username}} </a>
+										<a href="/admin/userRebateList?email={{$vo->user->email}}"> {{$vo->user->email}} </a>
 									@endif
 								</td>
 								<td>
 									@if(empty($vo->ref_user))
 										【账号已删除】
 									@else
-										<a href="/admin/userRebateList?ref_username={{$vo->ref_user->username}}"> {{$vo->ref_user->username}} </a>
+										<a href="/admin/userRebateList?ref_email={{$vo->ref_user->email}}"> {{$vo->ref_user->email}} </a>
 									@endif
 								</td>
 								<td> {{$vo->order_id}} </td>
@@ -116,7 +116,7 @@
 
         // 搜索
         function Search() {
-            window.location.href = '/admin/userRebateList' + '?username=' + $("#username").val() + '&ref_username=' + $("#ref_username").val() + '&status=' + $("#status option:selected").val();
+            window.location.href = '/admin/userRebateList' + '?email=' + $("#email").val() + '&ref_email=' + $("#ref_email").val() + '&status=' + $("#status option:selected").val();
         }
 	</script>
 @endsection

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

@@ -11,7 +11,7 @@
 			<div class="panel-body">
 				<div class="form-row">
 					<div class="form-group col-lg-4 col-sm-6">
-						<input type="text" class="form-control" name="username" id="username" value="{{Request::get('username')}}" placeholder="用户名"/>
+						<input type="text" class="form-control" name="email" id="email" value="{{Request::get('email')}}" placeholder="用户名"/>
 					</div>
 					<div class="form-group col-lg-2 col-sm-6 btn-group">
 						<button class="btn btn-primary" onclick="Search()">搜 索</button>
@@ -43,7 +43,7 @@
 									@if(empty($vo->user))
 										【账号已删除】
 									@else
-										<a href="/admin/userTrafficLogList?username={{$vo->user->username}}"> {{$vo->user->username}} </a>
+										<a href="/admin/userTrafficLogList?email={{$vo->user->email}}"> {{$vo->user->email}} </a>
 									@endif
 								</td>
 								<td>
@@ -94,7 +94,7 @@
 
         // 搜索
         function Search() {
-            window.location.href = '/admin/userTrafficLogList' + '?username=' + $("#username").val();
+            window.location.href = '/admin/userTrafficLogList' + '?email=' + $("#email").val();
         }
 	</script>
 @endsection

+ 2 - 2
resources/views/auth/activeUser.blade.php

@@ -19,8 +19,8 @@
 				<span class="form-title">{{trans('auth.active_account')}}</span>
 			</div>
 			<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="email" class="form-control" name="email" value="{{Request::get('email')}}" required/>
+				<label class="floating-label" for="email">{{trans('auth.email')}}</label>
 				{{csrf_field()}}
 			</div>
 		@else

+ 1 - 2
resources/views/auth/layouts.blade.php

@@ -7,7 +7,7 @@
 <html lang="{{app()->getLocale()}}">
 <!--<![endif]-->
 <head>
-	<meta charset="utf-8">
+	<meta charset="UTF-8">
 	<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
 	<meta name="viewport" content="width=device-width, initial-scale=1.0">
 	<meta name="description" content="">
@@ -136,7 +136,6 @@
 <script src="/assets/js/Site.js" type="text/javascript"></script>
 <script src="/assets/global/js/Plugin/asscrollable.js" type="text/javascript"></script>
 <script src="/assets/global/js/Plugin/slidepanel.js" type="text/javascript"></script>
-<script src="/assets/global/js/Plugin/switchery.js" type="text/javascript"></script>
 <script src="/assets/global/js/Plugin/jquery-placeholder.js" type="text/javascript"></script>
 <script src="/assets/global/js/Plugin/material.js" type="text/javascript"></script>
 <!-- 统计 -->

+ 2 - 2
resources/views/auth/login.blade.php

@@ -16,8 +16,8 @@
 			</div>
 		@endif
 		<div class="form-group form-material floating" data-plugin="formMaterial">
-			<input type="email" class="form-control" name="username" value="{{Request::old('username')}}" required/>
-			<label class="floating-label" for="username">{{trans('auth.username')}}</label>
+			<input type="email" class="form-control" name="email" value="{{Request::old('email')}}" required/>
+			<label class="floating-label" for="email">{{trans('auth.email')}}</label>
 		</div>
 		<div class="form-group form-material floating" data-plugin="formMaterial">
 			<input type="password" class="form-control" name="password" value="{{Request::old('password')}}" autocomplete required/>

+ 122 - 0
resources/views/auth/maintenance.blade.php

@@ -0,0 +1,122 @@
+<!DOCTYPE html>
+<!--[if IE 8]>
+<html lang="{{app()->getLocale()}}" class="ie8 no-js css-menubar"> <![endif]-->
+<!--[if IE 9]>
+<html lang="{{app()->getLocale()}}" class="ie9 no-js css-menubar"> <![endif]-->
+<!--[if !IE]><!-->
+<html lang="{{app()->getLocale()}}">
+<!--<![endif]-->
+<head>
+	<meta charset="UTF-8">
+	<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+	<meta name="viewport" content="width=device-width, initial-scale=1.0">
+	<meta name="description" content="">
+	<meta name="keywords" content="">
+	<meta name="author" content="兔姬菌">
+	<meta name="copyright" content="2017-2020©兔姬菌">
+	<title>维护 | Maintenance</title>
+	<link href="{{asset('favicon.ico')}}" rel="shortcut icon apple-touch-icon">
+	<!-- Stylesheets -->
+	<link href="/assets/global/css/bootstrap.min.css" type="text/css" rel="stylesheet">
+	<link href="/assets/global/css/bootstrap-extend.min.css" type="text/css" rel="stylesheet">
+	<link href="/assets/css/site.min.css" type="text/css" rel="stylesheet">
+	<!-- 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/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/maintenance.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="//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]-->
+	<!--[if lt IE 10]>
+	<script src="/assets/global/vendor/media-match/media.match.min.js" type="text/javascript"></script>
+	<script src="/assets/global/vendor/respond/respond.min.js" type="text/javascript"></script> <![endif]-->
+
+	<!-- Scripts -->
+	<script src="/assets/global/vendor/breakpoints/breakpoints.js" type="text/javascript"></script>
+	<script>
+        Breakpoints();
+	</script>
+</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/" 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]-->
+
+<!-- Page -->
+<div class="page vertical-align text-center" data-animsition-in="fade-in" data-animsition-out="fade-out">>
+	<div class="page-content vertical-align-middle">
+		<i class="icon wb-settings icon-spin page-maintenance-icon" aria-hidden="true"></i>
+		<h2>维护建设中</h2>
+		{!! $message !!}
+		<footer class="page-copyright">
+			<p id="countdown"></p>
+		</footer>
+	</div>
+</div>
+<!-- End Page -->
+
+<!-- 核心/Core -->
+<script src="/assets/global/vendor/babel-external-helpers/babel-external-helpers.js" type="text/javascript"></script>
+<script src="/assets/global/vendor/jquery/jquery.min.js" type="text/javascript"></script>
+<script src="/assets/global/vendor/popper-js/umd/popper.min.js" type="text/javascript"></script>
+<script src="/assets/global/vendor/bootstrap/bootstrap.min.js" type="text/javascript"></script>
+<script src="/assets/global/vendor/animsition/animsition.min.js" type="text/javascript"></script>
+<script src="/assets/global/vendor/mousewheel/jquery.mousewheel.js" type="text/javascript"></script>
+<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/screenfull/screenfull.js"></script>
+<script src="/assets/global/vendor/slidepanel/jquery-slidePanel.js"></script>
+<!-- 脚本/Scripts -->
+<script src="/assets/global/js/Component.js" type="text/javascript"></script>
+<script src="/assets/global/js/Plugin.js" type="text/javascript"></script>
+<script src="/assets/global/js/Base.js" type="text/javascript"></script>
+<script src="/assets/global/js/Config.js" type="text/javascript"></script>
+<script src="/assets/js/Section/Menubar.js" type="text/javascript"></script>
+<script src="/assets/js/Section/Sidebar.js" type="text/javascript"></script>
+<script src="/assets/js/Section/PageAside.js" type="text/javascript"></script>
+<script src="/assets/js/Plugin/menu.js" type="text/javascript"></script>
+<!-- 设置/Config -->
+<script src="/assets/global/js/config/colors.js" type="text/javascript"></script>
+<script type="text/javascript">
+    Config.set('assets', '/assets');
+</script>
+<!-- Page -->
+<script src="/assets/js/Site.js"></script>
+<script src="/assets/global/js/Plugin/asscrollable.js"></script>
+<script src="/assets/global/js/Plugin/slidepanel.js"></script>
+
+<script>
+    (function (document, window, $) {
+        'use strict';
+
+        var Site = window.Site;
+        $(document).ready(function () {
+            Site.run();
+        });
+    })(document, window, jQuery);
+
+    // 每秒更新计时器
+    const countDownDate = new Date("{{$time}}").getTime();
+    const x = setInterval(function () {
+        const distance = countDownDate - new Date().getTime();
+        const days = Math.floor(distance / 86400000);
+        const hours = Math.floor(distance % 86400000 / 3600000);
+        const minutes = Math.floor(distance % 3600000 / 60000);
+        const seconds = Math.floor(distance % 60000 / 1000);
+        document.getElementById("countdown").innerHTML = "<h2>" + days + " <span> 天 </span>: " + hours + "    <span>时</span>: " + minutes + " <span>分 </span>: " + seconds + "<span> 秒</span> </h2>";
+        if (distance <= 0) {
+            clearInterval(x);
+            document.getElementById("countdown").remove();
+        }
+    }, 1000);
+</script>
+</body>
+</html>

+ 40 - 248
resources/views/auth/register.blade.php

@@ -6,23 +6,27 @@
 @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">
 					<span>{{$errors->first()}}</span>
 				</div>
 			@endif
+			@csrf
+			<input type="hidden" name="register_token" value="{{Session::get('register_token')}}"/>
+			<input type="hidden" name="aff" value="{{Session::get('register_aff')}}"/>
+			<div class="form-group form-material floating" data-plugin="formMaterial">
+				<input type="text" class="form-control" name="username" value="{{Request::old('username') ? : Request::get('username')}}" required/>
+				<label class="floating-label" for="username">{{trans('auth.username')}}</label>
+			</div>
 			<div class="form-group form-material floating" data-plugin="formMaterial">
 				@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>
+					<input type="email" class="form-control" autocomplete="off" name="email" value="{{Request::old('email')}}" id="email" required/>
+					<label class="floating-label" for="email">{{trans('auth.email')}}</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>
+						<label class="floating-label" for="emailHead">{{trans('auth.email')}}</label>
 						<div class="input-group-prepend">
 							<span class="input-group-text bg-indigo-600 text-white">@</span>
 						</div>
@@ -33,7 +37,7 @@
 								@endforeach
 							@endif
 						</select>
-						<input type="text" name="username" id="username" hidden/>
+						<input type="text" name="email" id="email" hidden/>
 					</div>
 				@endif
 			</div>
@@ -43,9 +47,9 @@
 						<input type="text" class="form-control" name="verify_code" value="{{Request::old('verify_code')}}" required/>
 						<label class="floating-label" for="verify_code">{{trans('auth.captcha')}}</label>
 						<span class="input-group-btn">
-                            <span class="btn btn-success" id="sendCode" onclick="sendVerifyCode()">
+                            <button class="btn btn-success" id="sendCode" onclick="sendVerifyCode()">
                                 {{trans('auth.request')}}
-                            </span>
+                            </button>
                         </span>
 					</div>
 				</div>
@@ -124,145 +128,7 @@
 					<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>
+					@include('docs.tos')
 				</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>
@@ -280,53 +146,7 @@
 					<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>
-
+					@include('docs.aup')
 				</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>
@@ -344,38 +164,27 @@
 	<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();
+        function getEmail() {
+            let email = $("#emailHead").val();
             const emailTail = $("#emailTail").val();
-            if (username.trim() === '') {
-                swal.fire({title: '{{trans('auth.username_null')}}', type: 'warning', timer: 1500});
+            if (email.trim() === '') {
+                swal.fire({title: '{{trans('auth.email_null')}}', type: 'warning', timer: 1500});
                 return false;
             }
-            username = username.trim() + '@' + emailTail;
-            $("#username").val(username);
+            email = email.trim() + '@' + emailTail;
+            $("#email").val(email);
         }
-
-        $('#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();
+            getEmail();
 					@endif
-            const username = $("#username").val();
-            if (username.trim() === '') {
-                swal.fire({title: '{{trans('auth.username_null')}}', type: 'warning', timer: 1500});
+            const email = $("#email").val();
+            if (email.trim() === '') {
+                swal.fire({title: '{{trans('auth.email_null')}}', type: 'warning', timer: 1500});
                 return false;
             }
 
@@ -383,67 +192,50 @@
                 type: "POST",
                 url: "/sendCode",
                 async: false,
-                data: {_token: '{{csrf_token()}}', username: username},
+                data: {_token: '{{csrf_token()}}', email: email},
                 dataType: 'json',
                 success: function (ret) {
-                    if (ret.status === 'fail') {
+                    if (ret.status === "success") {
+                        swal.fire({title: ret.message, type: 'success'});
+                        $("#sendCode").attr('disabled', true);
+                        flag = true;
+                    } else {
                         swal.fire({title: ret.message, type: 'error', timer: 1000, showConfirmButton: false});
                         $("#sendCode").attr('disabled', false);
                         flag = false;
-                    } else {
-                        swal.fire({title: '{{trans('auth.captcha_send')}}', type: 'error'});
-                        $("#sendCode").attr('disabled', true);
-                        flag = true;
                     }
                 },
                 error: function () {
-                    swal.fire({title: '{{trans('auth.captcha_send')}}', type: 'error'});
+                    swal.fire({title: '发送失败', type: 'error'});
                     flag = false;
                 }
             });
 
             // 请求成功才开始倒计时
             if (flag) {
-                // 60秒后重新发送
+                // 60秒后才能重新申请发送
                 let left_time = 60;
                 const tt = window.setInterval(function () {
-                    left_time = left_time - 1;
+                    left_time--;
                     if (left_time <= 0) {
                         window.clearInterval(tt);
-                        $("#sendCode").attr('disabled', false).val('{{trans('auth.send')}}');
+                        $("#sendCode").removeAttr('disabled').text('{{trans('auth.request')}}');
                     } else {
-                        $("#sendCode").val(left_time);
+                        $("#sendCode").text(left_time + ' s');
                     }
                 }, 1000);
             }
         }
 
         $('#register-form').submit(function (event) {
+			@if(!\App\Components\Helpers::systemConfig()['sensitiveType'])
+            getEmail();
+			@endif
             // 先检查Google reCAPTCHA有没有进行验证
             if ($('#g-recaptcha-response').val() === '') {
-                Msg(false, "{{trans('login.required_captcha')}}", 'error');
+                swal.fire({title: '{{trans('auth.required_captcha')}}', type: 'error'});
                 return false;
             }
         });
-
-        // 生成提示
-        function Msg(clear, msg, type) {
-            if (!clear) $('.register-form .alert').remove();
-
-            var typeClass = 'alert-danger',
-                clear = clear ? clear : false,
-                $elem = $('.register-form');
-            type === 'error' ? typeClass = 'alert-danger' : typeClass = 'alert-success';
-
-            const tpl = '<div class="alert ' + typeClass + '">' +
-                '<button type="button" class="close" onclick="$(this).parent().remove();"></button>' +
-                '<span> ' + msg + ' </span></div>';
-
-            if (!clear) {
-                $elem.prepend(tpl);
-            } else {
-                $('.register-form .alert').remove();
-            }
-        }
 	</script>
 @endsection

+ 2 - 2
resources/views/auth/resetPassword.blade.php

@@ -17,8 +17,8 @@
 				{{trans('auth.resetPassword')}}
 			</div>
 			<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="email" class="form-control" name="email" value="{{Request::old('email')}}" required="required" autofocus="autofocus"/>
+				<label class="floating-label">{{trans('auth.email')}}</label>
 				{{csrf_field()}}
 			</div>
 		@else

+ 1 - 0
resources/views/docs/aup.blade.php

@@ -0,0 +1 @@
+<div style="padding: 20px; line-height: 22px; background-color: #393D49; color: #fff; font-weight: 300;">不得通过本站提供的服务发布、转载、传送含有下列内容之一的信息:<br>1.违反宪法确定的基本原则的;<br>2.危害国家安全,泄漏国家机密,颠覆国家政权,破坏国家统一的;<br>3.损害国家荣誉和利益的;<br>4.煽动民族仇恨、民族歧视,破坏民族团结的;<br>5.破坏国家宗教政策,宣扬邪教和封建迷信的; <br>6.散布谣言,扰乱社会秩序,破坏社会稳定的;<br>7.散布淫秽、色情、赌博、暴力、恐怖或者教唆犯罪的;<br>8.侮辱或者诽谤他人,侵害他人合法权益的;<br>9.煽动非法集会、结社、游行、示威、聚众扰乱社会秩序的;<br>10.以非法民间组织名义活动的;<br>11.含有法律、行政法规禁止的其他内容的。</div>

+ 1 - 0
resources/views/docs/tos.blade.php

@@ -0,0 +1 @@
+<div style="padding: 20px; line-height: 22px; background-color: #393D49; color: #fff; font-weight: 300;">不得通过本站提供的服务发布、转载、传送含有下列内容之一的信息:<br>1.违反宪法确定的基本原则的;<br>2.危害国家安全,泄漏国家机密,颠覆国家政权,破坏国家统一的;<br>3.损害国家荣誉和利益的;<br>4.煽动民族仇恨、民族歧视,破坏民族团结的;<br>5.破坏国家宗教政策,宣扬邪教和封建迷信的; <br>6.散布谣言,扰乱社会秩序,破坏社会稳定的;<br>7.散布淫秽、色情、赌博、暴力、恐怖或者教唆犯罪的;<br>8.侮辱或者诽谤他人,侵害他人合法权益的;<br>9.煽动非法集会、结社、游行、示威、聚众扰乱社会秩序的;<br>10.以非法民间组织名义活动的;<br>11.含有法律、行政法规禁止的其他内容的。</div>

+ 24 - 15
resources/views/payment/detail.blade.php

@@ -17,9 +17,11 @@
 					<div class="row col-8">
 						<div class="col-md-6">
 							<ul class="list-group list-group-dividered">
-								<li class="list-group-item">服务名称:{{$payment->order->goods->name}}</li>
+								<li class="list-group-item">服务名称:{{$name}}</li>
 								<li class="list-group-item">支付金额:{{$payment->amount}}元</li>
-								<li class="list-group-item">有效期:{{$payment->order->goods->days}} 天</li>
+								@if($days != 0)
+									<li class="list-group-item">有效期:{{$days}} 天</li>
+								@endif
 								<li class="list-group-item"> 请在<code>15分钟</code>内完成支付,否者订单将会自动关闭</li>
 							</ul>
 						</div>
@@ -46,24 +48,31 @@
                 document.body.innerHTML += unescapeHTML("{{$payment->qr_code}}");
             document.forms['alipaySubmit'].submit();
 			@endif
-            getStatus();
         });
 
         // 检查支付单状态
-        function getStatus() {
-            $.get("/payment/getStatus", {sn: '{{$payment->sn}}'}, function (ret) {
-                if (ret.status === 'success') {
-                    swal.fire({title: ret.message, type: 'success', timer: 1000, showConfirmButton: false})
-                        .then(() => window.location.href = '/invoices')
-                } else if (ret.status === 'error') {
-                    swal.fire({title: ret.message, type: "error", timer: 1000, showConfirmButton: false})
-                        .then(() => window.location.href = '/invoices')
-                } else {
-                    // 无结果时,每2秒查询一次订单状态
-                    setInterval("getStatus()", 2000);
+        const r = window.setInterval(function () {
+            $.ajax({
+                type: 'GET',
+                url: '/payment/getStatus',
+                data: {sn: '{{$payment->sn}}'},
+                dataType: 'json',
+                success: function (ret) {
+                    window.clearInterval();
+                    if (ret.status === 'success') {
+                        swal.fire({title: ret.message, type: 'success', timer: 1500, showConfirmButton: false})
+                            .then(() => {
+                                window.location.href = '/invoices'
+                            });
+                    } else if (ret.status === 'error') {
+                        swal.fire({title: ret.message, type: "error", timer: 1500, showConfirmButton: false})
+                            .then(() => {
+                                window.location.href = '/invoices'
+                            })
+                    }
                 }
             });
-        }
+        }, 3000);
 
         // 还原html脚本 < > & " '
         function unescapeHTML(str) {

+ 21 - 32
resources/views/shop/addGoods.blade.php

@@ -27,15 +27,6 @@
 					<span> {{$errors->first()}} </span>
 				</div>
 			@endif
-			<div class="alert alert-info alert-dismissible" role="alert">
-				<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
-				<h4>面板关于商品的规则</h4>
-				<ul>
-					<li>警告:用户购买新套餐则会覆盖所有已购但未过期的旧套餐并删除这些旧套餐对应的流量,所以设置商品时请务必注意类型和有效期,流量包则可叠加</li>
-					<li>套餐:仅展示12个上架的商品;流量:仅展示12个上架的商品</li>
-					<li>注意:添加后无法更改授予等级、商品类型;套餐有效期90天起,因为套餐每月会重置流量</li>
-				</ul>
-			</div>
 			<div class="panel-body">
 				<form action="/shop/addGoods" method="post" enctype="multipart/form-data" class="form-horizontal" role="form">
 					{{csrf_field()}}
@@ -52,10 +43,6 @@
 										<input type="radio" name="type" value="2"/>
 										<label for="type">套餐</label>
 									</div>
-									<div class="radio-custom radio-primary radio-inline">
-										<input type="radio" name="type" value="3"/>
-										<label for="type">充值</label>
-									</div>
 								</div>
 								<span class="offset-md-3 text-help"> 套餐与账号有效期有关,流量包只扣可用流量,不影响有效期 </span>
 							</div>
@@ -65,7 +52,7 @@
 									<input type="text" class="form-control" name="name" id="name" value="{{Request::old('name')}}" required/>
 								</div>
 							</div>
-							<div class="form-group row package-money">
+							<div class="form-group row">
 								<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/>
@@ -80,7 +67,7 @@
 									<span class="input-group-text">元</span>
 								</div>
 							</div>
-							<div class="form-group row package-renew" style="display: none">
+							<div class="form-group row package-renew">
 								<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}}" step="0.01" required/>
@@ -88,7 +75,7 @@
 								</div>
 								<span class="offset-md-3 text-help"> 用户自行重置流量价格, <code>0</code> 时代表改该商品不提供重置功能 </span>
 							</div>
-							<div class="form-group row package-renew" style="display: none">
+							<div class="form-group row package-renew">
 								<label class="col-md-3 col-form-label" for="period">重置周期</label>
 								<div class="col-md-4 input-group">
 									<input type="number" class="form-control" name="period" id="period" value="{{Request::old('period')? :30}}" required/>
@@ -96,7 +83,7 @@
 								</div>
 								<span class="offset-md-3 text-help"> 套餐流量会每N天重置 </span>
 							</div>
-							<div class="form-group row package-money">
+							<div class="form-group row">
 								<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="limit_num" id="limit_num" value="{{Request::old('limit_num')? :0}}" required/>
@@ -104,7 +91,7 @@
 								</div>
 								<span class="offset-md-3 text-help"> 每个用户可以购买该商品次数,为 <code>0</code> 时代表不限购 </span>
 							</div>
-							<div class="form-group row package-money">
+							<div class="form-group row">
 								<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>
@@ -115,7 +102,7 @@
 								</div>
 								<span class="offset-md-3 text-help"> 自动给购买此商品的用户打上相应的标签 </span>
 							</div>
-							<div class="form-group row package-renew" style="display: none">
+							<div class="form-group row package-renew">
 								<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')? :30}}" required/>
@@ -123,7 +110,7 @@
 								</div>
 								<span class="text-help"> *提交后不可修改 </span>
 							</div>
-							<div class="form-group row package-money">
+							<div class="form-group row">
 								<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">
@@ -150,7 +137,7 @@
 								</div>
 							</div>
 						</div>
-						<div class="col-lg-6 col-md-12 package-money">
+						<div class="col-lg-6 col-md-12">
 							<div class="form-group row">
 								<label class="col-md-3 col-form-label" for="sort">排序</label>
 								<div class="col-md-3">
@@ -206,20 +193,22 @@
 	<script src="/assets/global/js/Plugin/dropify.js" type="text/javascript"></script>
 
 	<script type="text/javascript">
-        // 选择商品类型
-        $("input[name='type']").change(function () {
-            const type = $(this).val();
-            if (type === '3') {
-                $(".package-money").hide();
+        function itemControl(value) {
+            if (value === 1) {
+                $(".package-renew").hide();
             } else {
-                $(".package-money").show();
-            }
-
-            if (type === '2') {
                 $(".package-renew").show();
-            } else {
-                $(".package-renew").hide();
             }
+        }
+
+        $(document).ready(function () {
+            itemControl(parseInt($("input[name='type']").val()))
         });
+
+        // 选择商品类型
+        $("input[name='type']").change(function () {
+            itemControl(parseInt($(this).val()));
+        });
+
 	</script>
 @endsection

+ 79 - 89
resources/views/shop/editGoods.blade.php

@@ -30,10 +30,6 @@
 					<strong>错误:</strong> {{$errors->first()}}
 				</div>
 			@endif
-			<div class="alert alert-info alert-dismissible" role="alert">
-				<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
-				<strong>警告:</strong>购买新套餐则会覆盖所有已购但未过期的旧套餐并删除这些旧套餐对应的流量,所以设置商品时请务必注意类型和有效期,流量包则可叠加
-			</div>
 			<div class="panel-body">
 				<form action="/shop/editGoods/{{$goods->id}}" method="post" enctype="multipart/form-data" class="form-horizontal" role="form">
 					<div class="form-group row">
@@ -47,10 +43,6 @@
 								<input type="radio" name="type" value="2" @if($goods->type == 2) checked @endif disabled/>
 								<label for="type">套餐</label>
 							</div>
-							<div class="radio-custom radio-primary radio-inline">
-								<input type="radio" name="type" value="3" @if($goods->type == 3) checked @endif disabled/>
-								<label for="type">充值</label>
-							</div>
 						</div>
 						<span class="offset-md-2 text-help"> 套餐与账号有效期有关,流量包只扣可用流量,不影响有效期 </span>
 					</div>
@@ -82,104 +74,102 @@
 							</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}}" step="0.01"/>
-									<span class="input-group-text">元</span>
-								</div>
-							</div>
-							<div class="form-group row">
-								<label class="col-md-2 col-form-label" for="period">重置周期</label>
-								<div class="col-md-4 input-group">
-									<input type="number" class="form-control" name="period" id="period" value="{{$goods->period}}" required/>
-									<span class="input-group-text">天</span>
-								</div>
-								<span class="text-help"> 套餐流量会每N天重置 </span>
-							</div>
-						@endif
+					@if ($goods->type == 2)
 						<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="renew">流量重置价格</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>
+								<input type="number" class="form-control" name="renew" id="renew" value="{{$goods->renew}}" step="0.01"/>
+								<span class="input-group-text">元</span>
 							</div>
 						</div>
 						<div class="form-group row">
-							<label class="col-md-2 col-form-label" for="limit_num">限购数量</label>
+							<label class="col-md-2 col-form-label" for="period">重置周期</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>
+								<input type="number" class="form-control" name="period" id="period" value="{{$goods->period}}" required/>
+								<span class="input-group-text">天</span>
 							</div>
-							<span class="text-help"> 每个用户可以购买该商品次数,为 0 时代表不限购 </span>
+							<span class="text-help"> 套餐流量会每N天重置 </span>
 						</div>
-						<div class="form-group row">
-							<label class="col-md-2 col-form-label" for="labels">标签</label>
-							<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="text-help"> 自动给购买此商品的用户打上相应的标签 </span>
+					@endif
+					<div class="form-group row">
+						<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 class="form-group row">
-							<label class="col-md-2 col-form-label" for="days">有效期</label>
-							<div class="col-md-4 input-group">
-								<input type="number" class="form-control" name="days" id="days" value="{{$goods->days}}" disabled/>
-								<span class="input-group-text">天</span>
-							</div>
-							<span class="text-help"> 到期后会自动从总流量扣减对应的流量 </span>
+					</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>
-						<div class="form-group row">
-							<label class="col-md-2 col-form-label" for="sort">排序</label>
-							<div class="col-md-4">
-								<input type="number" class="form-control" name="sort" id="sort" value="{{$goods->sort}}"/>
-							</div>
-							<span class="text-help"> 排序值越大排越前 </span>
+						<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-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>
-						<div class="form-group row">
-							<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="{{$goods->color}}"/>
-							</div>
+						<span class="text-help"> 自动给购买此商品的用户打上相应的标签 </span>
+					</div>
+					<div class="form-group row">
+						<label class="col-md-2 col-form-label" for="days">有效期</label>
+						<div class="col-md-4 input-group">
+							<input type="number" class="form-control" name="days" id="days" value="{{$goods->days}}" disabled/>
+							<span class="input-group-text">天</span>
 						</div>
-						<div class="form-group row">
-							<label class="col-md-2 col-form-label" for="is_hot">热销</label>
-							<div class="col-md-10 d-flex align-items-center">
-								<div class="radio-custom radio-primary radio-inline">
-									<input type="radio" name="is_hot" value="1" @if($goods->is_hot == 1) checked @endif/>
-									<label for="is_hot">是</label>
-								</div>
-								<div class="radio-custom radio-primary radio-inline">
-									<input type="radio" name="is_hot" value="0" @if($goods->is_hot == 0) checked @endif/>
-									<label for="is_hot">否</label>
-								</div>
-							</div>
+						<span class="text-help"> 到期后会自动从总流量扣减对应的流量 </span>
+					</div>
+					<div class="form-group row">
+						<label class="col-md-2 col-form-label" for="sort">排序</label>
+						<div class="col-md-4">
+							<input type="number" class="form-control" name="sort" id="sort" value="{{$goods->sort}}"/>
 						</div>
-						<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={{$goods->logo?:'/assets/images/noimage.png'}} />
-							</div>
+						<span class="text-help"> 排序值越大排越前 </span>
+					</div>
+					<div class="form-group row">
+						<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="{{$goods->color}}"/>
 						</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 class="form-group row">
+						<label class="col-md-2 col-form-label" for="is_hot">热销</label>
+						<div class="col-md-10 d-flex align-items-center">
+							<div class="radio-custom radio-primary radio-inline">
+								<input type="radio" name="is_hot" value="1" @if($goods->is_hot == 1) checked @endif/>
+								<label for="is_hot">是</label>
 							</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 class="radio-custom radio-primary radio-inline">
+								<input type="radio" name="is_hot" value="0" @if($goods->is_hot == 0) checked @endif/>
+								<label for="is_hot">否</label>
 							</div>
-							<span class="offset-md-2 text-help"> 每行内容请以<code>&lt;li&gt;</code> 开头 <code>&lt;/li&gt;</code> 结尾</span>
 						</div>
-					@endif
+					</div>
+					<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={{$goods->logo?:'/assets/images/noimage.png'}} />
+						</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>
 					<div class="form-actions col-12 text-right">
 						<button type="submit" class="btn btn-success"><i class="icon wb-check"></i> 提 交</button>
 					</div>

+ 1 - 2
resources/views/shop/goodsList.blade.php

@@ -18,7 +18,6 @@
 							<option value="" @if(Request::get('type') == '') selected hidden @endif>类型</option>
 							<option value="1" @if(Request::get('type') == '1') selected hidden @endif>流量包</option>
 							<option value="2" @if(Request::get('type') == '2') selected hidden @endif>套餐</option>
-							<option value="3" @if(Request::get('type') == '3') selected hidden @endif>余额充值</option>
 						</select>
 					</div>
 					<div class="form-group col-lg-2 col-sm-4">
@@ -73,7 +72,7 @@
 										<a href="{{$goods->logo}}" target="_blank"><img src="{{$goods->logo}}" alt="logo" class="h-50"/></a>
 									@endif
 								</td>
-								<td> {{$goods->type == 3 ? '' : $goods->traffic_label}} </td>
+								<td> {{$goods->traffic_label}} </td>
 								<td> {{$goods->price}}元</td>
 								<td> {{$goods->sort}} </td>
 								<td>

+ 3 - 3
resources/views/subscribe/subscribeList.blade.php

@@ -14,7 +14,7 @@
 						<input type="number" class="form-control" name="user_id" id="user_id" value="{{Request::get('user_id')}}" placeholder="ID"/>
 					</div>
 					<div class="form-group col-lg-4 col-sm-6">
-						<input type="text" class="form-control" name="username" id="username" value="{{Request::get('username')}}" placeholder="用户名"/>
+						<input type="text" class="form-control" name="email" id="email" value="{{Request::get('email')}}" placeholder="用户名"/>
 					</div>
 					<div class="form-group col-lg-3 col-sm-6">
 						<select name="status" id="status" class="form-control" onChange="Search()">
@@ -54,7 +54,7 @@
 									@if(empty($subscribe->user))
 										【账号已删除】
 									@else
-										<a href="/admin/userList?id={{$subscribe->user->id}}" target="_blank">{{$subscribe->user->username}}</a>
+										<a href="/admin/userList?id={{$subscribe->user->id}}" target="_blank">{{$subscribe->user->email}}</a>
 									@endif
 								</td>
 								<td> {{$subscribe->code}} </td>
@@ -107,7 +107,7 @@
 
         // 搜索
         function Search() {
-            window.location.href = '/subscribe/subscribeList' + '?user_id=' + $("#user_id").val() + '&username=' + $("#username").val() + '&status=' + $("#status option:selected").val();
+            window.location.href = '/subscribe/subscribeList' + '?user_id=' + $("#user_id").val() + '&email=' + $("#email").val() + '&status=' + $("#status option:selected").val();
         }
 
         // 启用禁用用户的订阅

+ 1 - 1
resources/views/subscribe/subscribeLog.blade.php

@@ -28,7 +28,7 @@
 						@foreach($subscribeLog as $subscribe)
 							<tr>
 								<td>{{$subscribe->id}}</td>
-								<td>{{empty($subscribe->user) ? '用户已删除' : $subscribe->user[0]->username}}</td>
+								<td>{{empty($subscribe->user) ? '用户已删除' : $subscribe->user[0]->email}}</td>
 								<td>{{$subscribe->request_ip}}</td>
 								<td>{{$subscribe->request_time}}</td>
 								<td>{{$subscribe->request_header}}</td>

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

@@ -17,7 +17,7 @@
 						<div class="form-group">
 							<label class="control-label col-md-2">用户名</label>
 							<div class="col-md-8">
-								<input type="text" class="form-control" name="username" value="{{Request::get('username')}}" id="username" autocomplete="off" autofocus required/>
+								<input type="text" class="form-control" name="email" value="{{Request::get('email')}}" id="email" autocomplete="off" autofocus required/>
 							</div>
 						</div>
 						<div class="form-group">
@@ -53,7 +53,7 @@
                 type: "POST",
                 url: "/ticket/addTicket",
                 async: false,
-                data: {_token: '{{csrf_token()}}', username: $('#username').val(), title: $('#title').val(), content: $('#content').val()},
+                data: {_token: '{{csrf_token()}}', email: $('#email').val(), title: $('#title').val(), content: $('#content').val()},
                 dataType: 'json',
                 success: function (ret) {
                     swal.fire({title: ret.message, type: 'success', timer: 1000})

+ 17 - 5
resources/views/ticket/replyTicket.blade.php

@@ -19,8 +19,14 @@
 					<div class="chats">
 						<div class="chat chat-left">
 							<div class="chat-avatar">
-								<p class="avatar" data-toggle="tooltip" data-placement="right" title="{{trans('home.ticket_reply_me')}}">
-									<img src="/assets/images/astronaut.svg" alt="{{trans('home.ticket_reply_me')}}"/>
+								<p class="avatar">
+									@if($ticket->user->qq)
+										<img src="http://q1.qlogo.cn/g?b=qq&nk={{$ticket->user->qq}}&s=640" alt="客户">
+									@elseif(strpos(strtolower($ticket->user->email),"@qq.com") !== FALSE)
+										<img src="http://q1.qlogo.cn/g?b=qq&nk={{$ticket->user->email}}&s=640" alt="客户">
+									@else
+										<img src="/assets/images/astronaut.svg" alt="客户">
+									@endif
 								</p>
 							</div>
 							<div class="chat-body">
@@ -36,12 +42,18 @@
 							<div class="chat @if (!$reply->user->is_admin) chat-left @endif">
 								<div class="chat-avatar">
 									@if ($reply->user->is_admin)
-										<p class="avatar" data-toggle="tooltip" data-placement="left" title="{{trans('home.ticket_reply_master')}}">
+										<p class="avatar">
 											<img src="/assets/images/logo64.png" alt="{{trans('home.ticket_reply_master')}}"/>
 										</p>
 									@else
-										<p class="avatar" data-toggle="tooltip" data-placement="left" title="{{trans('home.ticket_reply_me')}}">
-											<img src="/assets/images/astronaut.svg" alt="{{trans('home.ticket_reply_me')}}"/>
+										<p class="avatar">
+											@if($ticket->user->qq)
+												<img src="http://q1.qlogo.cn/g?b=qq&nk={{$ticket->user->qq}}&s=640" alt="客户">
+											@elseif(strpos(strtolower($ticket->user->email),"@qq.com") !== FALSE)
+												<img src="http://q1.qlogo.cn/g?b=qq&nk={{$ticket->user->email}}&s=640" alt="客户">
+											@else
+												<img src="/assets/images/astronaut.svg" alt="客户">
+											@endif
 										</p>
 									@endif
 								</div>

+ 3 - 3
resources/views/ticket/ticketList.blade.php

@@ -16,7 +16,7 @@
 			<div class="panel-body">
 				<div class="form-row">
 					<div class="form-group col-lg-3 col-sm-6">
-						<input type="text" class="form-control" name="username" id="username" value="{{Request::get('username')}}" placeholder="用户名" autocomplete="off"/>
+						<input type="text" class="form-control" name="email" id="email" value="{{Request::get('email')}}" placeholder="用户名" autocomplete="off"/>
 					</div>
 					<div class="form-group col-lg-2 col-sm-6 btn-group">
 						<button class="btn btn-primary" onclick="Search()">搜 索</button>
@@ -45,7 +45,7 @@
 									@if(!$ticket->user)
 										【账号已删除】
 									@else
-										<a href="/admin/userList?id={{$ticket->user->id}}" target="_blank">{{$ticket->user->username}}</a>
+										<a href="/admin/userList?id={{$ticket->user->id}}" target="_blank">{{$ticket->user->email}}</a>
 									@endif
 								</td>
 
@@ -90,7 +90,7 @@
 
         // 搜索
         function Search() {
-            window.location.href = '/ticket/ticketList?username=' + $("#username").val();
+            window.location.href = '/ticket/ticketList?email=' + $("#email").val();
         }
 	</script>
 @endsection

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

@@ -8,44 +8,26 @@
 			<div class="panel-body container-fluid">
 				<div class="page-invoice-table table-responsive">
 					<table class="table table-hover text-md-center">
-						@if($goods->type == 3)
-							<thead>
-							<tr>
-								<th class="invoice-title"> {{trans('home.service_name')}} </th>
-								<th class="invoice-title"> {{trans('home.service_price')}} </th>
-							</tr>
-							</thead>
-							<tbody>
-							<tr>
-								<td class="p-10">
-									<h2>{{$goods->name}}</h2>
-									充值金额:{{$goods->price}}元
-								</td>
-								<td> ¥{{$goods->price}} </td>
-							</tr>
-							</tbody>
-						@else
-							<thead>
-							<tr>
-								<th>{{trans('home.service_name')}}</th>
-								<th>{{trans('home.service_desc')}} </th>
-								<th>{{trans('home.service_price')}}</th>
-								<th>{{trans('home.service_quantity')}}</th>
-							</tr>
-							</thead>
-							<tbody>
-							<tr>
-								<td class="text-middle">{{$goods->name}} </td>
-								<td>{{trans('home.service_days')}}
-									<strong>{{$goods->type==1? $dataPlusDays:$goods->days}} {{trans('home.day')}}</strong>
-									<br>
-									<strong>{{$goods->traffic_label}}</strong> {{trans('home.bandwidth')}}
-								</td>
-								<td class="text-middle"> ¥{{$goods->price}} </td>
-								<td class="text-middle"> x 1</td>
-							</tr>
-							</tbody>
-						@endif
+						<thead>
+						<tr>
+							<th>{{trans('home.service_name')}}</th>
+							<th>{{trans('home.service_desc')}} </th>
+							<th>{{trans('home.service_price')}}</th>
+							<th>{{trans('home.service_quantity')}}</th>
+						</tr>
+						</thead>
+						<tbody>
+						<tr>
+							<td class="text-middle">{{$goods->name}} </td>
+							<td>{{trans('home.service_days')}}
+								<strong>{{$goods->type==1? $dataPlusDays:$goods->days}} {{trans('home.day')}}</strong>
+								<br>
+								<strong>{{$goods->traffic_label}}</strong> {{trans('home.bandwidth')}}
+							</td>
+							<td class="text-middle"> ¥{{$goods->price}} </td>
+							<td class="text-middle"> x 1</td>
+						</tr>
+						</tbody>
 					</table>
 				</div>
 				@if($goods->type <= 2)

+ 7 - 0
resources/views/user/components/avatar.blade.php

@@ -0,0 +1,7 @@
+@if(Auth::user()->qq)
+	<img src="http://q1.qlogo.cn/g?b=qq&nk={{Auth::user()->qq}}&s=640" alt="{{trans('home.ticket_reply_me')}}">
+@elseif(strpos(strtolower(Auth::user()->email),"@qq.com") !== FALSE)
+	<img src="http://q1.qlogo.cn/g?b=qq&nk={{Auth::user()->email}}&s=640" alt="{{trans('home.ticket_reply_me')}}">
+@else
+	<img src="/assets/images/astronaut.svg" alt="{{trans('home.ticket_reply_me')}}">
+@endif

+ 7 - 0
resources/views/user/components/help/clients/android.blade.php

@@ -0,0 +1,7 @@
+<ol>
+	<li><a href="clients/ShadowsocksRR-3.5.1.1.apk" target="_blank">点击此处</a>下载客户端并启动</li>
+	<li> 单击左上角的shadowsocksR进入配置文件页,点击右下角的“+”号,点击“添加/升级SSR订阅”,完整复制本页上方“订阅服务”处地址,填入订阅信息并保存</li>
+	<li> 选中任意一个节点,返回软件首页</li>
+	<li> 在软件首页处找到“路由”选项,并将其改为“绕过局域网及中国大陆地址”</li>
+	<li> 点击右上角的小飞机图标进行连接,提示是否添加(或创建)VPN连接,点同意(或允许)</li>
+</ol>

+ 7 - 0
resources/views/user/components/help/clients/game.blade.php

@@ -0,0 +1,7 @@
+<ol>
+	<li><a href="clients/SSTap-beta-setup-1.0.9.7.zip" target="_blank">点击此处</a>下载客户端并安装</li>
+	<li> 打开 SSTap,选择 <i class="fa fa-cog"></i> -&gt; SSR订阅 -&gt; SSR订阅管理,添加订阅地址</li>
+	<li> 添加完成后,再次选择 <i class="fa fa-cog"></i> - SSR订阅 - 手动更新SSR订阅,即可同步节点列表。</li>
+	<li> 在代理模式中选择游戏或「不代理中国IP」,点击「连接」即可加速。</li>
+	<li> 需要注意的是,一旦连接成功,客户端会自动缩小到任务栏,可在设置中关闭。</li>
+</ol>

+ 8 - 0
resources/views/user/components/help/clients/ios.blade.php

@@ -0,0 +1,8 @@
+<ol>
+	<li> 请从站长处获取 App Store 账号密码</li>
+	<li> 打开 Shadowrocket,点击右上角 “+”号 添加节点,类型选择 Subscribe</li>
+	<li> 完整复制本页上方 “订阅服务” 处地址,将其粘贴至 “URL”栏,点击右上角 “完成”</li>
+	<li> 左划新增的服务器订阅,点击 “更新”</li>
+	<li> 选定合适服务器节点,点击右上角连接开关,屏幕上方状态栏出现“VPN”图标</li>
+	<li> 当进行海外游戏时请将 Shadowrocket “首页” 页面中的 “全局路由” 切换至 “代理”,并确保“设置”页面中的“UDP”已开启转发</li>
+</ol>

+ 5 - 0
resources/views/user/components/help/clients/linux.blade.php

@@ -0,0 +1,5 @@
+<ol>
+	<li><a href="clients/Shadowsocks-qt5-3.0.1.zip" target="_blank">点击此处</a>下载客户端并启动</li>
+	<li> 单击状态栏小飞机,找到服务器 -&gt; 编辑订阅,复制黏贴订阅地址</li>
+	<li> 更新订阅设置即可</li>
+</ol>

+ 12 - 0
resources/views/user/components/help/clients/mac.blade.php

@@ -0,0 +1,12 @@
+<ol>
+	<li><a href="clients/ShadowsocksX-NG-R8-1.4.6.dmg" target="_blank">点击此处</a>下载客户端并启动</li>
+	<li> 点击状态栏纸飞机 -&gt; 服务器 -&gt; 编辑订阅</li>
+	<li> 点击窗口左下角 “+”号 新增订阅,完整复制本页上方“订阅服务”处地址,将其粘贴至“订阅地址”栏,点击右下角“OK”</li>
+	<li> 点击纸飞机 -&gt; 服务器 -&gt; 手动更新订阅</li>
+	<li> 点击纸飞机 -&gt; 服务器,选定合适服务器</li>
+	<li> 点击纸飞机 -&gt; 打开Shadowsocks</li>
+	<li> 点击纸飞机 -&gt; PAC自动模式</li>
+	<li> 点击纸飞机 -&gt; 代理设置-&gt;从 GFW List 更新 PAC</li>
+	<li> 打开系统偏好设置 -&gt; 网络,在窗口左侧选定显示为“已连接”的网络,点击右下角“高级...”</li>
+	<li> 切换至“代理”选项卡,勾选“自动代理配置”和“不包括简单主机名”,点击右下角“好”,再次点击右下角“应用”</li>
+</ol>

+ 12 - 0
resources/views/user/components/help/clients/windows.blade.php

@@ -0,0 +1,12 @@
+<ol>
+	<li> <a href="clients/ShadowsocksR-win.zip" target="_blank">点击此处</a>下载客户端并启动 </li>
+	<li> 运行 ShadowsocksR 文件夹内的 ShadowsocksR.exe </li>
+	<li> 右击桌面右下角状态栏(或系统托盘)纸飞机 -&gt; 服务器订阅 -&gt; SSR服务器订阅设置 </li>
+	<li> 点击窗口左下角 “Add” 新增订阅,完整复制本页上方 “订阅服务” 处地址,将其粘贴至“网址”栏,点击“确定” </li>
+	<li> 右击纸飞机 -&gt; 服务器订阅 -&gt; 更新SSR服务器订阅(不通过代理) </li>
+	<li> 右击纸飞机 -&gt; 服务器,选定合适服务器 </li>
+	<li> 右击纸飞机 -&gt; 系统代理模式 -&gt; PAC模式 </li>
+	<li> 右击纸飞机 -&gt; PAC -&gt; 更新PAC为GFWList </li>
+	<li> 右击纸飞机 -&gt; 代理规则 -&gt; 绕过局域网和大陆 </li>
+	<li> 右击纸飞机,取消勾选“服务器负载均衡” </li>
+</ol>

+ 53 - 0
resources/views/user/components/help/solution.blade.php

@@ -0,0 +1,53 @@
+<div class="nav-tabs-horizontal" data-plugin="tabs">
+	<ul class="nav nav-tabs" role="tablist">
+		<li class="nav-item" role="presentation">
+			<a class="nav-link active" data-toggle="tab" href="#android" aria-controls="android" role="tab">
+				<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="#ios" aria-controls="ios" role="tab">
+				<i class="icon fa-apple" aria-hidden="true"></i>iOS</a>
+		</li>
+		<li class="nav-item" role="presentation">
+			<a class="nav-link" data-toggle="tab" href="#Windows" aria-controls="Windows" 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="#MacOS" aria-controls="MacOS" role="tab">
+				<i class="icon fa-apple" aria-hidden="true"></i>MacOS</a>
+		</li>
+	</ul>
+	<div class="tab-content pt-20">
+		<div class="tab-pane active" id="android" role="tabpanel">
+			暂无
+		</div>
+		<div class="tab-pane" id="ios" role="tabpanel">
+			<h4>Q: 软件安装后,闪退?</h4>
+			<p>A: 闪退的情况大概分以下三种</p>
+			<ol>
+				<li>安装完成后,一打开就秒退。
+					<br> 解决办法:登陆网站上提供的对应ID,先在苹果商店搜索安装最新版,运行一次后,在通过网站直接覆盖安装。
+				</li>
+				<li>打开软件,且弹出ID验证框,输入ID后闪退。
+					<br> 解决办法:同上。
+				</li>
+				<li>打开软件,运行一段时间后闪退。
+					<br> 这类问题,一般是因为软件的适配性引起的,基本无解。
+				</li>
+			</ol>
+			<h4>Q: 软件安装失败?</h4>
+			<p>A: 出现此类问题,绝大多数是你的网络不好,更换个网络即可,最好使用数据流量进行下载。</p>
+		</div>
+		<div class="tab-pane" id="Windows" role="tabpanel">
+			{{--                                                            <h4>Q: PAC 更新失败</h4>--}}
+			{{--                                                            <p>A: 这个情况都是PC链接访问网站不稳定造成的!--}}
+			{{--                                                                <br>--}}
+			{{--                                                                解决方案: 手动下载--}}
+			{{--                                                            </p>--}}
+			暂无
+		</div>
+		<div class="tab-pane" id="MacOS" role="tabpanel">
+			暂无
+		</div>
+	</div>
+</div>

+ 48 - 0
resources/views/user/components/help/tutorial.blade.php

@@ -0,0 +1,48 @@
+<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="#android_client" aria-controls="android_client" 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="#ios_client" aria-controls="quantumult_client" 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="#windows_client" aria-controls="windows_client" 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="#game_client" aria-controls="game_client_sstap" 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="#linux_client" aria-controls="game_client_netch" role="tab">
+				<i class="icon fa-windows" aria-hidden="true"></i>Linux</a>
+		</li>
+		<li class="nav-item" role="presentation">
+			<a class="nav-link" data-toggle="tab" href="#mac_client" aria-controls="macos_client" role="tab">
+				<i class="icon fa-apple" aria-hidden="true"></i>Mac</a>
+		</li>
+	</ul>
+	<div class="tab-content py-15">
+		<div class="tab-pane active" id="android_client" role="tabpanel">
+			@include('user.components.help.client.android')
+		</div>
+		<div class="tab-pane" id="ios_client" role="tabpanel">
+			@include('user.components.help.client.ios')
+		</div>
+		<div class="tab-pane" id="windows_client" role="tabpanel">
+			@include('user.components.help.client.windows')
+		</div>
+		<div class="tab-pane" id="game_client" role="tabpanel">
+			@include('user.components.help.client.game')
+		</div>
+		<div class="tab-pane" id="linux_client" role="tabpanel">
+			@include('user.components.help.client.linux')
+		</div>
+		<div class="tab-pane" id="mac_client" role="tabpanel">
+			@include('user.components.help.client.mac')
+		</div>
+	</div>
+</div>

+ 3 - 100
resources/views/user/help.blade.php

@@ -73,53 +73,7 @@
 										</div>
 										<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="#android_client" aria-controls="android_client" 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="#shadowrocket_client" aria-controls="shadowrocket_client" role="tab">
-																<i class="icon fa-apple" aria-hidden="true"></i>iOS-小火箭<span class="badge badge-danger up">推荐</span></a>
-														</li>
-													</ul>
-													<div class="tab-content py-15">
-														<div class="tab-pane active" id="android_client" role="tabpanel">
-															<ol>
-																<li>点击<code>添加订阅地址</code> ->
-																	<button class="btn btn-xs btn-animate btn-animate-side btn-info mt-clipboard" data-clipboard-action="copy" data-clipboard-text="{{$link}}"><span><i class="icon wb-copy" aria-hidden="true"></i>点击复制订阅地址</span></button>
-																	-> 粘贴进输入框 ->
-																	<code>确定</code> -> <code>确定并更新</code></li>
-															</ol>
-														</div>
-														<div class="tab-pane" id="shadowrocket_client" role="tabpanel">
-															<ol>
-																<li>
-																	<a class="btn btn-xs btn-primary" href="{{$Shadowrocket_install}}"><i class="icon fa-hand-o-right" aria-hidden="true"></i> 点此下载客户端
-																		<i class="icon fa-hand-o-left" aria-hidden="true"></i></a> -> 弹窗选<code>安装</code> -> 等待下载 -> 启动
-																</li>
-																<li>返回手机主界面 -> 等待Shadowrocket下载/安装完毕 -> 进入软件</li>
-																@if (\App\Components\Helpers::systemConfig()['AppStore_id'] && \App\Components\Helpers::systemConfig()['AppStore_password'])
-																	<div class="alert alert-info" role="alert" style="width: fit-content">
-																		@if($not_paying_user)
-
-																		@else
-																			<i class="wb-unlock" aria-hidden="true"></i> 首次安装软件可能会需要苹果ID激活软件,请输入以下账号信息:
-																			<br>
-																			账号(Apple ID):
-																			<code id="accountId">{{\App\Components\Helpers::systemConfig()['AppStore_id']}}</code>
-																			<button class="btn btn-xs btn-primary mt-clipboard" data-clipboard-target="#accountId" data-clipboard-action="copy"><i class="wb-copy" aria-hidden="true"></i></button>
-																			<br> 密码:
-																			<code id="accountPasswd">{{\App\Components\Helpers::systemConfig()['AppStore_password']}}</code>
-																			<button class="btn btn-xs btn-primary mt-clipboard" data-clipboard-target="#accountPasswd" data-clipboard-action="copy"><i class="wb-copy" aria-hidden="true"></i></button>
-																		@endif
-																	</div>
-																@endif
-															</ol>
-														</div>
-													</div>
-												</div>
+												@include('user.components.help.tutorial')
 											</div>
 										</div>
 									</div>
@@ -130,59 +84,7 @@
 										</div>
 										<div class="panel-collapse collapse" id="answer-3" aria-labelledby="question-3" role="tabpanel">
 											<div class="panel-body">
-												<div class="nav-tabs-horizontal" data-plugin="tabs">
-													<ul class="nav nav-tabs" role="tablist">
-														<li class="nav-item" role="presentation">
-															<a class="nav-link active" data-toggle="tab" href="#android" aria-controls="android" role="tab">
-																<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="#ios" aria-controls="ios" role="tab">
-																<i class="icon fa-apple" aria-hidden="true"></i>iOS</a>
-														</li>
-														<li class="nav-item" role="presentation">
-															<a class="nav-link" data-toggle="tab" href="#Windows" aria-controls="Windows" 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="#MacOS" aria-controls="MacOS" role="tab">
-																<i class="icon fa-apple" aria-hidden="true"></i>MacOS</a>
-														</li>
-													</ul>
-													<div class="tab-content pt-20">
-														<div class="tab-pane active" id="android" role="tabpanel">
-															暂无
-														</div>
-														<div class="tab-pane" id="ios" role="tabpanel">
-															<h4>Q: 软件安装后,闪退?</h4>
-															<p>A: 闪退的情况大概分以下三种</p>
-															<ol>
-																<li>安装完成后,一打开就秒退。
-																	<br> 解决办法:登陆网站上提供的对应ID,先在苹果商店搜索安装最新版,运行一次后,在通过网站直接覆盖安装。
-																</li>
-																<li>打开软件,且弹出ID验证框,输入ID后闪退。
-																	<br> 解决办法:同上。
-																</li>
-																<li>打开软件,运行一段时间后闪退。
-																	<br> 这类问题,一般是因为软件的适配性引起的,基本无解。
-																</li>
-															</ol>
-															<h4>Q: 软件安装失败?</h4>
-															<p>A: 出现此类问题,绝大多数是你的网络不好,更换个网络即可,最好使用数据流量进行下载。</p>
-														</div>
-														<div class="tab-pane" id="Windows" role="tabpanel">
-															{{--                                                            <h4>Q: PAC 更新失败</h4>--}}
-															{{--                                                            <p>A: 这个情况都是PC链接访问网站不稳定造成的!--}}
-															{{--                                                                <br>--}}
-															{{--                                                                解决方案: 手动下载--}}
-															{{--                                                            </p>--}}
-															暂无
-														</div>
-														<div class="tab-pane" id="MacOS" role="tabpanel">
-															暂无
-														</div>
-													</div>
-												</div>
+												@include('user.components.help.solution')
 											</div>
 										</div>
 									</div>
@@ -346,6 +248,7 @@
 	<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>
+	<script src="/assets/custom/jump-tab.js" type="text/javascript"></script>
 	<script type="text/javascript">
         // 更换订阅地址
         function exchangeSubscribe() {

+ 3 - 2
resources/views/user/index.blade.php

@@ -351,12 +351,13 @@
         const countDownDate = new Date("{{$banedTime}}").getTime();
         const x = setInterval(function () {
             const distance = countDownDate - new Date().getTime();
+            const hours = Math.floor(distance % 86400000 / 3600000);
             const minutes = Math.floor((distance % 3600000) / 60000);
             const seconds = Math.floor((distance % 60000) / 1000);
-            document.getElementById("countdown").innerHTML = minutes + "分 " + seconds + "秒";
+            document.getElementById("countdown").innerHTML = hours + "时 " + minutes + "分 " + seconds + "秒";
             if (distance <= 0) {
                 clearInterval(x);
-                window.location.reload();
+                document.getElementById("countdown").remove();
             }
         }, 1000);
 		@endif

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

@@ -55,7 +55,7 @@
 											<td>
 												{!!$invite->status_label!!}
 											</td>
-											{{$invite->status == 1 ? (empty($invite->user) ? '【账号已删除】' : $invite->user->username) : ''}}
+											{{$invite->status == 1 ? (empty($invite->user) ? '【账号已删除】' : $invite->user->email) : ''}}
 										</tr>
 									@endforeach
 								@endif

+ 4 - 5
resources/views/user/invoices.blade.php

@@ -32,13 +32,12 @@
 						@foreach($orderList as $order)
 							<tr>
 								<td>{{$loop->iteration}}</td>
-								<td><a href="/invoice/{{$order->order_sn}}" target="_blank">{{$order->order_sn}}</a>
-								</td>
-								<td>{{empty($order->goods) ? trans('home.invoice_table_goods_deleted') : $order->goods->name}}</td>
+								<td><a href="/invoice/{{$order->order_sn}}" target="_blank">{{$order->order_sn}}</a></td>
+								<td>{{empty($order->goods) ? ($order->goods_id == -1 ? '余额充值': trans('home.invoice_table_goods_deleted')) : $order->goods->name}}</td>
 								<td>{{$order->pay_way === 1 ? trans('home.service_pay_button') : trans('home.online_pay')}}</td>
 								<td>¥{{$order->amount}}</td>
 								<td>{{$order->created_at}}</td>
-								<td>{{empty($order->goods) ? '' : $order->goods->type == 3 || $order->status == 3 ? '' : $order->expire_at}}</td>
+								<td>{{empty($order->goods) ? '' : $order->goods_id == -1 || $order->status == 3 ? '' : $order->expire_at}}</td>
 								<td>
 									@switch($order->status)
 										@case(-1)
@@ -51,7 +50,7 @@
 										<span class="badge badge-info">{{trans('home.invoice_status_wait_confirm')}}</span>
 										@break
 										@case(2)
-										@if (!empty($order->goods) && $order->goods->type == 3)
+										@if ($order->goods_id == -1)
 											<span class="badge badge-default">{{trans('home.invoice_status_payment_confirm')}}</span>
 										@else
 											@if($order->is_expire)

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

@@ -105,7 +105,7 @@
 				<li class="nav-item dropdown">
 					<a href="#" aria-expanded="false" class="nav-link navbar-avatar" data-animation="scale-up" data-toggle="dropdown" role="button">
                 <span class="avatar avatar-online">
-                  <img src="/assets/images/astronaut.svg" alt="头像">
+	              @include('user.components.avatar')
                   <i></i>
                 </span>
 					</a>
@@ -212,7 +212,7 @@
 @if(Session::get("admin"))
 	<div class="panel panel-bordered w-300 bg-grey-200" style="position:fixed;right:20px;bottom:0;">
 		<div class="panel-body text-right">
-			<h5>当前身份:{{Auth::user()->username}}</h5>
+			<h5>当前身份:{{Auth::user()->email}}</h5>
 			<button type="button" class="btn btn-danger btn-block mt-20" id="return_to_admin">
 				返回管理页面
 			</button>

+ 9 - 1
resources/views/user/nodeList.blade.php

@@ -36,6 +36,13 @@
 									<button class="btn btn-sm btn-outline-info" onclick="getInfo('{{$node->id}}','qrcode')"><i id="qrcode{{$node->id}}" class="icon fa-qrcode"></i></button>
 									<button class="btn btn-sm btn-outline-info" onclick="getInfo('{{$node->id}}','text')"><i id="text{{$node->id}}" class="icon fa-list"></i></button>
 								</p>
+								<p class="text-muted">
+									<span>电信: {{$node->ct>0 ?$node->ct.' ms' :'无数据'}} </span>
+									<span>联通: {{$node->cu>0 ?$node->cu.' ms' :'无数据'}} </span>
+									<br>
+									<span>移动: {{$node->cm>0 ?$node->cm.' ms' :'无数据'}} </span>
+									<span>香港: {{$node->hk>0 ?$node->hk.' ms' :'无数据'}} </span>
+								</p>
 							</div>
 						</div>
 					</div>
@@ -50,9 +57,10 @@
 	<script src="/assets/global/js/Plugin/webui-popover.js" type="text/javascript"></script>
 
 	<script type="text/javascript">
-        $(function() {
+        $(function () {
             $('.card').matchHeight();
         });
+
         function getInfo(id, type) {
             const oldClass = $("#" + type + id).attr("class");
             $.ajax({

+ 9 - 5
resources/views/user/profile.blade.php

@@ -5,16 +5,16 @@
 			<div class="col-lg-5">
 				<div class="card">
 					<div class="card-header white bg-cyan-600 p-30 clearfix">
-						<a class="avatar avatar-100 float-left mr-20" href="javascript:void(0)">
-							<img src="/assets/images/astronaut.svg" alt="头像">
-						</a>
+						<span class="avatar avatar-100 float-left mr-20">
+							@include('user.components.avatar')
+						</span>
 						<div class="float-left">
 							<div class="font-size-20 mb-15">{{Auth::user()->username}}</div>
 							<p class="mb-5 text-nowrap"><i class="icon bd-webchat mr-10" aria-hidden="true"></i>
-								<span class="text-break">@if(Auth::user()->wechat) {{Auth::user()->wechat}} @else 未添加 @endif</span>
+								<span class="text-break">微信: @if(Auth::user()->wechat) {{Auth::user()->wechat}} @else 未添加 @endif</span>
 							</p>
 							<p class="mb-5 text-nowrap"><i class="icon bd-qq mr-10" aria-hidden="true"></i>
-								<span class="text-break">@if(Auth::user()->qq) {{Auth::user()->qq}} @else 未添加 @endif</span>
+								<span class="text-break">QQ: @if(Auth::user()->qq) {{Auth::user()->qq}} @else 未添加 @endif</span>
 							</p>
 						</div>
 					</div>
@@ -65,6 +65,10 @@
 							</div>
 							<div class="tab-pane animation-slide-left" id="tab_2" role="tabpanel">
 								<form action="/profile" method="post" enctype="multipart/form-data" class="form-horizontal">
+									<div class="form-group row">
+										<label for="username" class="col-md-2 col-form-label">{{trans('auth.username')}}</label>
+										<input type="text" class="form-control col-md-5 round" name="username" id="username" value="{{Auth::user()->username}}"/>
+									</div>
 									<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}}"/>

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

@@ -38,7 +38,7 @@
 							<thead class="thead-default">
 							<tr>
 								<th data-cell-style="cellStyle"> #</th>
-								<th> {{trans('home.invite_user_username')}} </th>
+								<th> {{trans('home.invite_user_email')}} </th>
 								<th> {{trans('home.invite_user_created_at')}}</th>
 							</tr>
 							</thead>
@@ -51,7 +51,7 @@
 								@foreach($referralUserList as $vo)
 									<tr>
 										<td> {{$loop->iteration}} </td>
-										<td> {{str_replace(mb_substr($vo->username, 3, 4), "****", $vo->username)}}  </td>
+										<td> {{str_replace(mb_substr($vo->email, 3, 4), "****", $vo->email)}}  </td>
 										<td> {{$vo->created_at}} </td>
 									</tr>
 								@endforeach
@@ -99,7 +99,7 @@
 									<tr>
 										<td> {{$loop->iteration}} </td>
 										<td> {{$referralLog->created_at}} </td>
-										<td> {{empty($referralLog->user) ? '【账号已删除】' : str_replace(mb_substr($referralLog->user->username, 3, 4), "****", $referralLog->user->username)}} </td>
+										<td> {{empty($referralLog->user) ? '【账号已删除】' : str_replace(mb_substr($referralLog->user->email, 3, 4), "****", $referralLog->user->email)}} </td>
 										<td> ¥{{$referralLog->amount}} </td>
 										<td> ¥{{$referralLog->ref_amount}} </td>
 										<td>

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

@@ -19,7 +19,7 @@
 						<div class="chat">
 							<div class="chat-avatar">
 								<p class="avatar" data-toggle="tooltip" data-placement="right" title="{{trans('home.ticket_reply_me')}}">
-									<img src="/assets/images/astronaut.svg" alt="{{trans('home.ticket_reply_me')}}"/>
+									@include('user.components.avatar')
 								</p>
 							</div>
 							<div class="chat-body">
@@ -40,7 +40,7 @@
 										</p>
 									@else
 										<p class="avatar" data-toggle="tooltip" data-placement="left" title="{{trans('home.ticket_reply_me')}}">
-											<img src="/assets/images/astronaut.svg" alt="{{trans('home.ticket_reply_me')}}"/>
+											@include('user.components.avatar')
 										</p>
 									@endif
 								</div>

+ 98 - 57
resources/views/user/services.blade.php

@@ -1,4 +1,7 @@
 @extends('user.layouts')
+@section('css')
+	<link rel="stylesheet" href="assets/global/vendor/ionrangeslider/ionrangeslider.min.css">
+@endsection
 @section('content')
 	<div class="page-content">
 		<div class="row">
@@ -97,33 +100,29 @@
 				<div class="modal-body">
 					<div class="alert alert-danger" id="charge_msg" style="display: none;"></div>
 					<form action="#" method="post">
-						@if(\App\Components\Helpers::systemConfig()['alipay_qrcode'] || \App\Components\Helpers::systemConfig()['wechat_qrcode'] || ($chargeGoodsList->isNotEmpty() && (\App\Components\Helpers::systemConfig()['is_alipay'] || \App\Components\Helpers::systemConfig()['is_f2fpay'])))
+						@if(\App\Components\Helpers::systemConfig()['alipay_qrcode'] || \App\Components\Helpers::systemConfig()['wechat_qrcode'] || \App\Components\Helpers::systemConfig()['is_alipay'] || \App\Components\Helpers::systemConfig()['is_f2fpay'])
 							<div class="mb-15 w-p50">
 								<select class="form-control" name="charge_type" id="charge_type">
-									@if($chargeGoodsList->isNotEmpty() && (\App\Components\Helpers::systemConfig()['is_alipay'] || \App\Components\Helpers::systemConfig()['is_f2fpay']))
+									@if(\App\Components\Helpers::systemConfig()['is_alipay'] || \App\Components\Helpers::systemConfig()['is_f2fpay'])
 										<option value="1" selected>{{trans('home.online_pay')}}</option>
 									@endif
 									@if(\App\Components\Helpers::systemConfig()['alipay_qrcode'] || \App\Components\Helpers::systemConfig()['wechat_qrcode'])
-										<option value="2" @if($chargeGoodsList->isEmpty()) selected @endif>二维码</option>
+										<option value="2" @if(\App\Components\Helpers::systemConfig()['is_alipay'] || \App\Components\Helpers::systemConfig()['is_f2fpay']) selected @endif>二维码</option>
 									@endif
 									<option value="3">{{trans('home.coupon_code')}}</option>
 								</select>
 							</div>
 						@endif
-						@if($chargeGoodsList->isNotEmpty() && (\App\Components\Helpers::systemConfig()['is_alipay'] || \App\Components\Helpers::systemConfig()['is_f2fpay']))
-							<div class="form-group row" id="charge_balance">
-								<label for="online_pay" class="offset-md-2 col-md-2 col-form-label">充值金额</label>
-								<div class="col-md-6">
-									<select class="form-control round" name="online_pay" id="online_pay">
-										@foreach($chargeGoodsList as $goods)
-											<option value="{{$goods->id}}">充值{{$goods->price}}元</option>
-										@endforeach
-									</select>
+						@if(\App\Components\Helpers::systemConfig()['is_alipay'] || \App\Components\Helpers::systemConfig()['is_f2fpay'])
+							<div class="form-group row charge_balance">
+								<label for="amount" class="offset-md-1 col-md-2 col-form-label">充值金额</label>
+								<div class="col-md-8">
+									<input type="text" name="amount" id="amount" data-plugin="ionRangeSlider" data-min=1 data-max=300 data-from=40 data-prefix="¥"/>
 								</div>
 							</div>
 						@endif
 						@if(\App\Components\Helpers::systemConfig()['alipay_qrcode'] || \App\Components\Helpers::systemConfig()['wechat_qrcode'])
-							<div class="text-center" id="charge_qrcode" @if($chargeGoodsList->isNotEmpty() && (\App\Components\Helpers::systemConfig()['is_alipay'] || \App\Components\Helpers::systemConfig()['is_f2fpay']))style="display: none;" @endif>
+							<div class="text-center" id="charge_qrcode">
 								<div class="row">
 									<p class="col-md-12 mb-10">付款时,请
 										<mark>备注邮箱账号</mark>
@@ -144,7 +143,7 @@
 								</div>
 							</div>
 						@endif
-						<div class="form-group row" id="charge_coupon_code" @if(\App\Components\Helpers::systemConfig()['alipay_qrcode'] || \App\Components\Helpers::systemConfig()['wechat_qrcode']|| ($chargeGoodsList->isNotEmpty() && (\App\Components\Helpers::systemConfig()['is_alipay'] || \App\Components\Helpers::systemConfig()['is_f2fpay']))) style="display: none;" @endif>
+						<div class="form-group row" id="charge_coupon_code">
 							<label for="charge_coupon" class="offset-md-2 col-md-2 col-form-label"> {{trans('home.coupon_code')}} </label>
 							<div class="col-md-6">
 								<input type="text" class="form-control round" name="charge_coupon" id="charge_coupon" placeholder="{{trans('home.please_input_coupon')}}">
@@ -154,31 +153,46 @@
 				</div>
 				<div class="modal-footer">
 					<button type="button" class="btn btn-default" data-dismiss="modal">{{trans('home.close')}}</button>
+					@if(\App\Components\Helpers::systemConfig()['is_alipay'])
+						<button type="button" class="btn btn-primary charge_balance" onclick="charge('4')"> 支付宝扫码</button>
+					@elseif(\App\Components\Helpers::systemConfig()['is_f2fpay'])
+						<button type="button" class="btn btn-primary charge_balance" onclick="charge('5')"> 支付宝扫码</button>
+					@endif
 					<button type="button" class="btn btn-primary" id="change_btn" onclick="charge()">{{trans('home.recharge')}}</button>
 				</div>
 			</div>
 		</div>
 	</div>
 @endsection @section('script')
+	<script src="assets/global/vendor/ionrangeslider/ion.rangeSlider.min.js"></script>
+	<script src="assets/global/js/Plugin/ionrangeslider.js"></script>
 	<script type="text/javascript">
-        // 切换充值方式
-        $("#charge_type").change(function () {
-            if ($(this).val() === '1') {
-                $("#charge_balance").show();
-                $("#change_btn").show();
+        function itemControl(value) {
+            if (value === 1) {
+                $(".charge_balance").show();
+                $("#change_btn").hide();
                 $("#charge_qrcode").hide();
                 $("#charge_coupon_code").hide();
-            } else if ($(this).val() === '2') {
-                $("#charge_balance").hide();
+            } else if (value === 2) {
+                $(".charge_balance").hide();
                 $("#change_btn").hide();
                 $("#charge_qrcode").show();
                 $("#charge_coupon_code").hide();
             } else {
-                $("#charge_balance").hide();
+                $(".charge_balance").hide();
                 $("#charge_qrcode").hide();
                 $("#charge_coupon_code").show();
                 $("#change_btn").show();
             }
+        }
+
+        $(document).ready(function () {
+            itemControl(parseInt($('#charge_type').val()))
+        });
+
+        // 切换充值方式
+        $("#charge_type").change(function () {
+            itemControl(parseInt($(this).val()));
         });
 
         // 重置流量
@@ -205,44 +219,71 @@
         }
 
         // 充值
-        function charge() {
-            const paymentType = $('#charge_type').val();
-            const charge_coupon = $('#charge_coupon').val();
-
-            if (paymentType === '1') {
-                $("#charge_msg").show().html("正在跳转支付界面");
-                window.location.href = '/buy/' + $('#online_pay').val();
-                return false;
-            }
-
-            if (paymentType === '3' && charge_coupon.trim() === '') {
-                $("#charge_msg").show().html("{{trans('home.coupon_not_empty')}}");
-                $("#charge_coupon").focus();
-                return false;
-            }
+        function charge(id) {
+            const paymentType = parseInt($('#charge_type').val());
+            const charge_coupon = $('#charge_coupon').val().trim();
+            const amount = parseInt($('#amount').val());
+            id = parseInt(id);
+            console.log(paymentType, charge_coupon, amount);
+            if (paymentType === 1) {
+                if (amount <= 0) {
+                    swal.fire({title: "错误", text: "充值余额不合规", type: 'warning', timer: 1000, showConfirmButton: false});
+                    return false;
+                }
 
-            $.ajax({
-                type: "POST",
-                url: '/charge',
-                data: {_token: '{{csrf_token()}}', coupon_sn: charge_coupon},
-                beforeSend: function () {
-                    $("#charge_msg").show().html("{{trans('home.recharging')}}");
-                },
-                success: function (ret) {
-                    if (ret.status === 'fail') {
+                $.ajax({
+                    type: "POST",
+                    url: "/payment/create",
+                    data: {_token: '{{csrf_token()}}', amount: amount, pay_type: id},
+                    dataType: "json",
+                    beforeSend: function () {
+                        $("#charge_msg").show().html("创建支付单中...");
+                    },
+                    success: function (ret) {
                         $("#charge_msg").show().html(ret.message);
-                        return false;
-                    }
-
-                    $("#charge_modal").modal("hide");
-                    window.location.reload();
-                },
-                error: function () {
-                    $("#charge_msg").show().html("{{trans('home.error_response')}}");
-                },
-                complete: function () {
+                        if (id === 4) {
+                            // 如果是Alipay支付写入Alipay的支付页面
+                            document.body.innerHTML += ret.data;
+                            document.forms['alipaysubmit'].submit();
+                        } else {
+                            window.location.href = '/payment/' + ret.data;
+                        }
+                        if (ret.status === 'fail') {
+                            return false;
+                        }
+                    },
+                    error: function () {
+                        $("#charge_msg").show().html("{{trans('home.error_response')}}");
+                    },
+                });
+            } else if (paymentType === 3) {
+                if (charge_coupon === '') {
+                    $("#charge_msg").show().html("{{trans('home.coupon_not_empty')}}");
+                    $("#charge_coupon").focus();
+                    return false;
                 }
-            });
+
+                $.ajax({
+                    type: "POST",
+                    url: '/charge',
+                    data: {_token: '{{csrf_token()}}', coupon_sn: charge_coupon},
+                    beforeSend: function () {
+                        $("#charge_msg").show().html("{{trans('home.recharging')}}");
+                    },
+                    success: function (ret) {
+                        if (ret.status === 'fail') {
+                            $("#charge_msg").show().html(ret.message);
+                            return false;
+                        }
+
+                        $("#charge_modal").modal("hide");
+                        window.location.reload();
+                    },
+                    error: function () {
+                        $("#charge_msg").show().html("{{trans('home.error_response')}}");
+                    },
+                });
+            }
         }
 
 	</script>

+ 1 - 1
routes/api.php

@@ -1,9 +1,9 @@
 <?php
 
 Route::group(['namespace' => 'Api'], function(){
-	Route::resource('yzy', 'YzyController');
 	Route::resource('alipay', 'AlipayController');
 	Route::resource('f2fpay', 'F2fpayController');
+	Route::resource('payjs','PayJsController');
 
 	// 定制客户端
 	Route::any('login', 'LoginController@login');

+ 6 - 3
routes/web.php

@@ -2,7 +2,7 @@
 
 Route::get('s/{code}', 'SubscribeController@getSubscribeByCode'); // 节点订阅地址
 
-Route::group(['middleware' => ['isForbidden', 'affiliate']], function(){
+Route::group(['middleware' => ['isForbidden', 'affiliate', 'isMaintenance']], function(){
 	Route::get('lang/{locale}', 'AuthController@switchLang'); // 语言切换
 	Route::any('login', 'AuthController@login')->middleware('isSecurity'); // 登录
 	Route::get('logout', 'AuthController@logout'); // 退出
@@ -17,8 +17,9 @@ Route::group(['middleware' => ['isForbidden', 'affiliate']], function(){
 	Route::get('makeVmessId', 'Controller@makeVmessId'); // 生成VmessId
 	Route::get('makeSecurityCode', 'Controller@makeSecurityCode'); // 生成网站安全码
 });
+Route::any('admin/login', 'AuthController@login')->middleware('isForbidden','isSecurity'); // 登录
 
-Route::group(['middleware' => ['isForbidden', 'isLogin', 'isAdmin']], function(){
+Route::group(['middleware' => ['isForbidden','isAdminLogin', 'isAdmin']], function(){
 	Route::get('admin', 'AdminController@index'); // 后台首页
 	Route::get('admin/userList', 'AdminController@userList'); // 账号列表
 	Route::any('admin/addUser', 'AdminController@addUser'); // 添加账号
@@ -31,6 +32,8 @@ Route::group(['middleware' => ['isForbidden', 'isLogin', 'isAdmin']], function()
 	Route::any('admin/editNode', 'AdminController@editNode'); // 编辑节点
 	Route::post('admin/delNode', 'AdminController@delNode'); // 删除节点
 	Route::get('admin/nodeMonitor/{id}', 'AdminController@nodeMonitor'); // 节点流量监控
+	Route::post('admin/pingNode', 'AdminController@pingNode'); // 节点ping测速
+	Route::get('admin/nodePingLog', 'AdminController@nodePingLog'); //节点Ping测速日志
 	Route::get('admin/articleList', 'AdminController@articleList'); // 文章列表
 	Route::any('admin/addArticle', 'AdminController@addArticle'); // 添加文章
 	Route::any('admin/editArticle', 'AdminController@editArticle'); // 编辑文章
@@ -109,7 +112,7 @@ Route::group(['middleware' => ['isForbidden', 'isLogin', 'isAdmin']], function()
 	Route::get('admin/makePort', 'AdminController@makePort'); // 生成端口
 });
 
-Route::group(['middleware' => ['isForbidden', 'isLogin']], function(){
+Route::group(['middleware' => ['isForbidden', 'isMaintenance', 'isLogin']], function(){
 	Route::any('/', 'UserController@index'); // 用户首页
 	Route::any('article', 'UserController@article'); // 文章详情
 	Route::post('exchangeSubscribe', 'UserController@exchangeSubscribe'); // 更换节点订阅地址

+ 28 - 7
sql/db.sql

@@ -97,6 +97,21 @@ CREATE TABLE `ss_node_online_log` (
   INDEX `idx_node_id` (`node_id`) USING BTREE
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='节点在线信息';
 
+-- ----------------------------
+-- Table structure for `ss_node_ping`
+-- ----------------------------
+CREATE TABLE `ss_node_ping` (
+  `id` INT(11) NOT NULL AUTO_INCREMENT,
+  `node_id` INT(11) NOT NULL DEFAULT '0' COMMENT '对应节点id',
+  `ct` INT(11) NOT NULL DEFAULT '0' COMMENT '电信',
+  `cu` INT(11) NOT NULL DEFAULT '0' COMMENT '联通',
+  `cm` INT(11) NOT NULL DEFAULT '0' COMMENT '移动',
+  `hk` INT(11) NOT NULL DEFAULT '0' COMMENT '香港',
+  `created_at` datetime NOT NULL,
+  `updated_at` datetime NOT NULL,
+  PRIMARY KEY (`id`),
+  INDEX `idx_node_id` (`node_id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='节点ping信息表';
 
 -- ----------------------------
 -- Table structure for `ss_node_label`
@@ -115,7 +130,8 @@ CREATE TABLE `ss_node_label` (
 -- ----------------------------
 CREATE TABLE `user` (
   `id` int(11) NOT NULL AUTO_INCREMENT,
-  `username` varchar(128) NOT NULL DEFAULT '' COMMENT '用户名',
+  `username` text NOT NULL DEFAULT '' COMMENT '昵称',
+  `email` varchar(128) NOT NULL DEFAULT '' COMMENT '用户名',
   `password` varchar(64) NOT NULL DEFAULT '' COMMENT '密码',
   `port` int(11) NOT NULL DEFAULT '0' COMMENT '代理端口',
   `passwd` varchar(16) NOT NULL DEFAULT '' COMMENT '代理密码',
@@ -154,7 +170,7 @@ CREATE TABLE `user` (
   `created_at` datetime DEFAULT NULL,
   `updated_at` datetime DEFAULT NULL,
   PRIMARY KEY (`id`),
-  UNIQUE INDEX `unq_username` (`username`),
+  UNIQUE INDEX `unq_email` (`email`),
   INDEX `idx_search` (`enable`, `status`, `port`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户';
 
@@ -162,8 +178,8 @@ CREATE TABLE `user` (
 LOCK TABLES `user` WRITE;
 /*!40000 ALTER TABLE `user` DISABLE KEYS */;
 
-INSERT INTO `user` (`id`, `username`, `password`, `port`, `passwd`, `vmess_id`, `transfer_enable`, `u`, `d`, `t`, `enable`, `method`, `protocol`, `obfs`, `obfs_param`, `wechat`, `qq`, `usage`, `pay_way`, `balance`, `enable_time`, `expire_time`, `remark`, `is_admin`, `reg_ip`, `status`, `created_at`, `updated_at`)
-VALUES (1,'test@test.com','$2y$10$ryMdx5ejvCSdjvZVZAPpOuxHrsAUY8FEINUATy6RCck6j9EeHhPfq',10000,'@123', 'c6effafd-6046-7a84-376e-b0429751c304', 1099511627776,0,0,0,1,'aes-256-cfb','origin','plain',0,'','',1,3,0.00,'2017-01-01','2099-01-01',NULL,1,'127.0.0.1',1,now(),now());
+INSERT INTO `user` (`id`, `username`, `email`, `password`, `port`, `passwd`, `vmess_id`, `transfer_enable`, `u`, `d`, `t`, `enable`, `method`, `protocol`, `obfs`, `obfs_param`, `wechat`, `qq`, `usage`, `pay_way`, `balance`, `enable_time`, `expire_time`, `remark`, `is_admin`, `reg_ip`, `status`, `created_at`, `updated_at`)
+VALUES (1,'管理员','test@test.com','$2y$10$ryMdx5ejvCSdjvZVZAPpOuxHrsAUY8FEINUATy6RCck6j9EeHhPfq',10000,'@123', 'c6effafd-6046-7a84-376e-b0429751c304', 1099511627776,0,0,0,1,'aes-256-cfb','origin','plain',0,'','',1,3,0.00,'2017-01-01','2099-01-01',NULL,1,'127.0.0.1',1,now(),now());
 
 /*!40000 ALTER TABLE `user` ENABLE KEYS */;
 UNLOCK TABLES;
@@ -377,7 +393,11 @@ INSERT INTO `config` VALUES ('95', 'google_captcha_secret', '');
 INSERT INTO `config` VALUES ('96', 'user_invite_days', 7);
 INSERT INTO `config` VALUES ('97', 'admin_invite_days', 7);
 INSERT INTO `config` VALUES ('98', 'admin_email', '');
-
+INSERT INTO `config` VALUES ('99', 'payjs_mch_id', '');
+INSERT INTO `config` VALUES ('100', 'payjs_key', '');
+insert into `config` VALUES ('101', 'maintenance_mode', '0');
+insert into `config` VALUES ('102', 'maintenance_time', '');
+insert into `config` VALUES ('103', 'maintenance_content', '');
 
 -- ----------------------------
 -- Table structure for `article`
@@ -464,7 +484,7 @@ CREATE TABLE `verify` (
 -- ----------------------------
 CREATE TABLE `verify_code` (
   `id` int(11) NOT NULL AUTO_INCREMENT,
-  `username` varchar(128) NOT NULL COMMENT '用户邮箱',
+  `address` varchar(128) NOT NULL COMMENT '用户邮箱',
   `code` char(6) NOT NULL COMMENT '验证码',
   `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态:0-未使用、1-已使用、2-已失效',
   `created_at` datetime DEFAULT NULL COMMENT '创建时间',
@@ -545,7 +565,8 @@ CREATE TABLE `coupon` (
   `created_at` datetime DEFAULT NULL COMMENT '创建时间',
   `updated_at` datetime DEFAULT NULL COMMENT '最后更新时间',
   `deleted_at` datetime NULL DEFAULT NULL COMMENT '删除时间',
-  PRIMARY KEY (`id`)
+  PRIMARY KEY (`id`),
+  UNIQUE INDEX `unq_sn` (`sn`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='优惠券';
 
 

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