Prechádzať zdrojové kódy

2.4.0 phase 2: 完成对VNet管理缺失的补全

兔姬桑 4 rokov pred
rodič
commit
3a548fa1d6
37 zmenil súbory, kde vykonal 409 pridanie a 241 odobranie
  1. 2 2
      app/Components/PushNotification.php
  2. 2 2
      app/Console/Commands/AutoJob.php
  3. 1 1
      app/Console/Commands/AutoPingNode.php
  4. 1 6
      app/Console/Commands/updateCoupon.php
  5. 1 1
      app/Http/Controllers/Admin/MarketingController.php
  6. 1 1
      app/Http/Controllers/Admin/ShopController.php
  7. 12 8
      app/Http/Controllers/AdminController.php
  8. 1 1
      app/Http/Controllers/AuthController.php
  9. 2 2
      app/Http/Controllers/Gateway/BitpayX.php
  10. 1 1
      app/Http/Controllers/Gateway/PayPal.php
  11. 41 113
      app/Http/Controllers/NodeController.php
  12. 1 1
      app/Http/Controllers/User/SubscribeController.php
  13. 2 2
      app/Http/Controllers/UserController.php
  14. 1 1
      app/Http/Middleware/isForbidden.php
  15. 10 18
      app/Jobs/VNet/addUser.php
  16. 8 11
      app/Jobs/VNet/delUser.php
  17. 8 11
      app/Jobs/VNet/editUser.php
  18. 49 31
      app/Jobs/VNet/reloadNode.php
  19. 25 1
      app/Models/Node.php
  20. 1 1
      app/Models/User.php
  21. 1 1
      app/Models/UserSubscribeLog.php
  22. 64 0
      app/Observers/NodeObserver.php
  23. 28 0
      app/Observers/RuleGroupObserver.php
  24. 30 0
      app/Observers/UserGroupObserver.php
  25. 4 2
      app/Observers/UserObserver.php
  26. 9 0
      app/Providers/AppServiceProvider.php
  27. 42 0
      app/Services/NodeService.php
  28. 1 1
      app/Services/OrderService.php
  29. 1 1
      app/helpers.php
  30. 1 0
      composer.json
  31. 3 4
      resources/views/admin/logs/onlineIPMonitor.blade.php
  32. 1 1
      resources/views/admin/node/nodeInfo.blade.php
  33. 41 4
      resources/views/admin/node/nodeList.blade.php
  34. 1 1
      resources/views/auth/layouts.blade.php
  35. 3 2
      routes/web.php
  36. 6 6
      sql/db.sql
  37. 3 3
      sql/mod/20200807.sql

+ 2 - 2
app/Components/PushNotification.php

@@ -41,7 +41,7 @@ class PushNotification {
 			return false;
 		}
 		// 发送错误
-		Log::debug('ServerChan消息推送异常:'.var_export($request, true));
+		Log::error('ServerChan消息推送异常:'.var_export($request, true));
 		return false;
 	}
 
@@ -68,7 +68,7 @@ class PushNotification {
 			return false;
 		}
 		// 发送错误
-		Log::debug('Bark消息推送异常:'.var_export($request, true));
+		Log::error('Bark消息推送异常:'.var_export($request, true));
 		return false;
 	}
 }

+ 2 - 2
app/Console/Commands/AutoJob.php

@@ -91,8 +91,8 @@ class AutoJob extends Command {
 	private function blockSubscribe(): void {
 		if(sysConfig('is_subscribe_ban')){
 			$pastSubLogs = UserSubscribeLog::where('request_time', '>=', date("Y-m-d H:i:s", strtotime("-1 days")))
-			                               ->groupBy('subscribe_id')
-			                               ->selectRaw('count(*) as total, subscribe_id')
+			                               ->groupBy('user_subscribe_id')
+			                               ->selectRaw('count(*) as total, user_subscribe_id')
 			                               ->get();
 			foreach($pastSubLogs as $log){
 				if($log->total >= sysConfig('subscribe_ban_times')){

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

@@ -38,7 +38,7 @@ class AutoPingNode extends Command {
 			$obj->hk = (int) $result['HongKong']['time'];// 香港
 			$obj->save();
 		}else{
-			Log::info("【".$ip."】Ping测速获取失败");
+			Log::error("【".$ip."】Ping测速获取失败");
 		}
 
 	}

+ 1 - 6
app/Console/Commands/updateCoupon.php

@@ -10,12 +10,7 @@ class updateCoupon extends Command {
 	protected $signature = 'updateCoupon';
 	protected $description = '修改原版Coupon至新版';
 
-
-	public function __construct() {
-		parent::__construct();
-	}
-
-	public function handle() {
+	public function handle(): void {
 		Log::info('----------------------------【优惠券转换】开始----------------------------');
 		$coupons = Coupon::withTrashed()->get();
 		foreach($coupons as $coupon){

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

@@ -84,7 +84,7 @@ class MarketingController extends Controller {
 
 			return Response::json(['status' => 'success', 'message' => '推送成功']);
 		}catch(Exception $e){
-			Log::info('PushBear消息推送失败:'.$e->getMessage());
+			Log::error('PushBear消息推送失败:'.$e->getMessage());
 
 			DB::rollBack();
 

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

@@ -108,7 +108,7 @@ class ShopController extends Controller {
 			return Redirect::back()->with('successMsg', '添加成功');
 		}catch(Exception $e){
 			DB::rollBack();
-			Log::info('添加商品信息异常:'.$e->getMessage());
+			Log::error('添加商品信息异常:'.$e->getMessage());
 
 			return Redirect::back()->withInput()->withErrors('添加失败');
 		}

+ 12 - 8
app/Http/Controllers/AdminController.php

@@ -1482,7 +1482,8 @@ class AdminController extends Controller {
 		$nodeId = $request->input('nodeId');
 		$userId = $request->input('id');
 
-		$query = NodeOnlineUserIp::with(['node:id,name', 'user:id,name'])->where('created_at', '>=', strtotime("-2 minutes"));
+		$query = NodeOnlineUserIp::with(['node:id,name', 'user:id,email'])
+		                         ->where('created_at', '>=', strtotime("-2 minutes"));
 
 		if(isset($ip)){
 			$query->whereIp($ip);
@@ -1512,16 +1513,19 @@ class AdminController extends Controller {
 			});
 		}
 
-		$list = $query->groupBy('user_id', 'node_id')->latest();
-		foreach($list as $vo){
+		$onlineIPLogs = $query->groupBy('user_id', 'node_id')
+		                      ->latest()
+		                      ->paginate(20)
+		                      ->appends($request->except('page'));
+		foreach($onlineIPLogs as $log){
 			// 跳过上报多IP的
-			if($vo->ip == null || strpos($vo->ip, ',') === true){
+			if($log->ip == null || strpos($log->ip, ',') !== false){
 				continue;
 			}
-			$ipInfo = QQWry::ip($vo->ip);
+			$ipInfo = QQWry::ip($log->ip);
 			if(isset($ipInfo['error'])){
 				// 用IPIP的库再试一下
-				$ipip = IPIP::ip($vo->ip);
+				$ipip = IPIP::ip($log->ip);
 				$ipInfo = [
 					'country'  => $ipip['country_name'],
 					'province' => $ipip['region_name'],
@@ -1529,10 +1533,10 @@ class AdminController extends Controller {
 				];
 			}
 
-			$vo->ipInfo = $ipInfo['country'].' '.$ipInfo['province'].' '.$ipInfo['city'];
+			$log->ipInfo = $ipInfo['country'].' '.$ipInfo['province'].' '.$ipInfo['city'];
 		}
 
-		$view['list'] = $list->paginate(20)->appends($request->except('page'));
+		$view['list'] = $onlineIPLogs;
 		$view['nodeList'] = Node::whereStatus(1)->orderByDesc('sort')->latest()->get();
 
 		return Response::view('admin.logs.onlineIPMonitor', $view);

+ 1 - 1
app/Http/Controllers/AuthController.php

@@ -285,7 +285,7 @@ class AuthController extends Controller {
 
 				// 校验邀请码合法性
 				if($code){
-					if($Invite::whereCode($code)->whereStatus(0)->doesntExist()){
+					if(Invite::whereCode($code)->whereStatus(0)->doesntExist()){
 						return Redirect::back()
 						               ->withInput($request->except(['code']))
 						               ->withErrors(trans('auth.code_error'));

+ 2 - 2
app/Http/Controllers/Gateway/BitpayX.php

@@ -33,7 +33,7 @@ class BitpayX extends AbstractPayment {
 			return Response::json(['status' => 'success', 'url' => $result['payment_url'], 'message' => '创建订单成功!']);
 		}
 
-		Log::error(var_export($result, true));
+		Log::error('创建订单错误:'.var_export($result, true));
 		return Response::json(['status' => 'fail', 'message' => '创建订单失败!'.$result['error']]);
 	}
 
@@ -63,7 +63,7 @@ class BitpayX extends AbstractPayment {
 			$request = $client->post('orders', ['body' => json_encode($data)]);
 		}
 		if($request->getStatusCode() !== 200){
-			Log::debug('BitPayX请求支付错误:'.var_export($request, true));
+			Log::error('BitPayX请求支付错误:'.var_export($request, true));
 		}
 
 		return json_decode($request->getBody(), true);

+ 1 - 1
app/Http/Controllers/Gateway/PayPal.php

@@ -56,7 +56,7 @@ class PayPal extends AbstractPayment {
 		try{
 			$response = $this->provider->setExpressCheckout($data);
 			if(!$response['paypal_link']){
-				Log::error(var_export($response, true));
+				Log::error('Paypal处理错误:'.var_export($response, true));
 
 				return Response::json(['status' => 'fail', 'message' => '创建订单失败,请使用其他方式或通知管理员!']);
 			}

+ 41 - 113
app/Http/Controllers/NodeController.php

@@ -4,24 +4,15 @@ namespace App\Http\Controllers;
 
 use App\Components\Helpers;
 use App\Components\NetworkDetection;
+use App\Jobs\VNet\reloadNode;
 use App\Models\Country;
 use App\Models\Label;
 use App\Models\Level;
 use App\Models\Node;
 use App\Models\NodeAuth;
 use App\Models\NodeCertificate;
-use App\Models\NodeDailyDataFlow;
-use App\Models\NodeHeartBeat;
-use App\Models\NodeHourlyDataFlow;
-use App\Models\NodeLabel;
-use App\Models\NodeOnlineLog;
 use App\Models\NodePing;
-use App\Models\NodeRule;
-use App\Models\RuleGroup;
-use App\Models\UserDailyDataFlow;
-use App\Models\UserDataFlowLog;
-use App\Models\UserGroup;
-use App\Models\UserHourlyDataFlow;
+use App\Services\NodeService;
 use DB;
 use Exception;
 use Illuminate\Http\JsonResponse;
@@ -37,27 +28,26 @@ class NodeController extends Controller {
 	public function nodeList(Request $request): \Illuminate\Http\Response {
 		$status = $request->input('status');
 
-		$query = Node::query();
+		$query = Node::with(['onlineLogs', 'dailyDataFlows']);
 
 		if(isset($status)){
 			$query->whereStatus($status);
 		}
 
-		$nodeList = $query->orderByDesc('status')->orderBy('id')->paginate(15)->appends($request->except('page'));
+		$nodeList = $query->orderByDesc('sort')->orderBy('id')->paginate(15)->appends($request->except('page'));
 		foreach($nodeList as $node){
 			// 在线人数
-			$online_log = NodeOnlineLog::whereNodeId($node->id)
-			                           ->where('log_time', '>=', strtotime("-5 minutes"))
-			                           ->latest('log_time')
-			                           ->first();
+			$online_log = $node->onlineLogs()
+			                   ->where('log_time', '>=', strtotime("-5 minutes"))
+			                   ->latest('log_time')
+			                   ->first();
 			$node->online_users = empty($online_log)? 0 : $online_log->online_user;
 
 			// 已产生流量
-			$totalTraffic = NodeDailyDataFlow::whereNodeId($node->id)->sum('total');
-			$node->transfer = flowAutoShow($totalTraffic);
+			$node->transfer = flowAutoShow($node->dailyDataFlows()->sum('total'));
 
 			// 负载(10分钟以内)
-			$node_info = $node->nodeHeartBeat()->recently()->first();
+			$node_info = $node->heartBeats()->recently()->first();
 			$node->isOnline = empty($node_info) || empty($node_info->load)? 0 : 1;
 			$node->load = $node->isOnline? $node_info->load : '离线';
 			$node->uptime = empty($node_info)? 0 : seconds2time($node_info->uptime);
@@ -68,8 +58,7 @@ class NodeController extends Controller {
 		return Response::view('admin.node.nodeList', $view);
 	}
 
-	public function checkNode(Request $request): JsonResponse {
-		$id = $request->input('id');
+	public function checkNode($id): JsonResponse {
 		$node = Node::find($id);
 		// 使用DDNS的node先获取ipv4地址
 		if($node->is_ddns){
@@ -142,8 +131,7 @@ class NodeController extends Controller {
 
 				DB::commit();
 				// 生成节点标签
-				$this->makeLabels($node->id, $request->input('labels'));
-				$this->getNodeGeo($node->id);
+				(new NodeService())->makeLabels($node->id, $request->input('labels'));
 
 				return Response::json(['status' => 'success', 'message' => '添加成功']);
 			}catch(Exception $e){
@@ -220,49 +208,21 @@ class NodeController extends Controller {
 		return false;
 	}
 
-	// 生成节点标签
-	private function makeLabels($nodeId, $labels): void {
-		// 先删除所有该节点的标签
-		NodeLabel::whereNodeId($nodeId)->delete();
-
-		if(!empty($labels) && is_array($labels)){
-			foreach($labels as $label){
-				$nodeLabel = new NodeLabel();
-				$nodeLabel->node_id = $nodeId;
-				$nodeLabel->label_id = $label;
-				$nodeLabel->save();
-			}
-		}
-	}
-
-	// 获取节点地理位置
-	private function getNodeGeo($id): bool {
-		$nodes = Node::whereStatus(1);
-		if($id){
-			$nodes = $nodes->whereId($id)->get();
-		}else{
-			$nodes = $nodes->get();
-		}
-		$result = 0;
-		foreach($nodes as $node){
-			$data = getIPInfo($node->is_ddns == 1? gethostbyname($node->server) : $node->ip);
-			if($data){
-				if($node->update(['geo' => $data['latitude'].','.$data['longitude']])){
-					$result++;
-				}
-			}
-		}
-		return $result;
-	}
-
 	// 刷新节点地理位置
 	public function refreshGeo(Request $request): JsonResponse {
-		if($this->getNodeGeo($request->input('id', 0))){
+		if((new NodeService())->getNodeGeo($request->input('id', 0))){
 			return Response::json(['status' => 'success', 'message' => '获取地理位置更新成功!']);
 		}
 		return Response::json(['status' => 'fail', 'message' => '获取地理位置更新失败!']);
 	}
 
+	// 重载节点
+	public function reload($id): JsonResponse {
+		if(reloadNode::dispatchNow(Node::whereId($id)->get())){
+			return Response::json(['status' => 'success', 'message' => '重载成功!']);
+		}
+		return Response::json(['status' => 'fail', 'message' => '重载失败!']);
+	}
 
 	// 编辑节点
 	public function editNode(Request $request) {
@@ -274,10 +234,14 @@ class NodeController extends Controller {
 				return $validator;
 			}
 
+			$node = Node::find($id);
+
 			try{
 				DB::beginTransaction();
+				// 生成节点标签
+				(new NodeService())->makeLabels($node->id, $request->input('labels'));
 
-				$data = [
+				$node->update([
 					'type'           => $request->input('type'),
 					'name'           => $request->input('name'),
 					'country_code'   => $request->input('country_code'),
@@ -317,16 +281,10 @@ class NodeController extends Controller {
 					'v2_path'        => $request->input('v2_path'),
 					'v2_tls'         => (int) $request->input('v2_tls'),
 					'tls_provider'   => $request->input('tls_provider')
-				];
-
-				// 生成节点标签
-				$this->makeLabels($id, $request->input('labels'));
-
-				Node::whereId($id)->update($data);
+				]);
 				// TODO:更新节点绑定的域名DNS(将节点IP更新到域名DNS 的A记录)
 
 				DB::commit();
-				$this->getNodeGeo($id);
 
 				return Response::json(['status' => 'success', 'message' => '编辑成功']);
 			}catch(Exception $e){
@@ -335,18 +293,18 @@ class NodeController extends Controller {
 
 				return Response::json(['status' => 'fail', 'message' => '编辑失败:'.$e->getMessage()]);
 			}
-		}else{
-			$view['node'] = Node::with('labels')->find($id);
-			$view['methodList'] = Helpers::methodList();
-			$view['protocolList'] = Helpers::protocolList();
-			$view['obfsList'] = Helpers::obfsList();
-			$view['countryList'] = Country::orderBy('code')->get();
-			$view['levelList'] = Level::orderBy('level')->get();
-			$view['labelList'] = Label::orderByDesc('sort')->orderBy('id')->get();
-			$view['dvList'] = NodeCertificate::orderBy('id')->get();
-
-			return Response::view('admin.node.nodeInfo', $view);
 		}
+
+		$view['node'] = Node::with('labels')->find($id);
+		$view['methodList'] = Helpers::methodList();
+		$view['protocolList'] = Helpers::protocolList();
+		$view['obfsList'] = Helpers::obfsList();
+		$view['countryList'] = Country::orderBy('code')->get();
+		$view['levelList'] = Level::orderBy('level')->get();
+		$view['labelList'] = Label::orderByDesc('sort')->orderBy('id')->get();
+		$view['dvList'] = NodeCertificate::orderBy('id')->get();
+
+		return Response::view('admin.node.nodeInfo', $view);
 	}
 
 	// 删除节点
@@ -360,35 +318,7 @@ class NodeController extends Controller {
 
 		try{
 			DB::beginTransaction();
-			// 删除分组关联、节点标签、节点相关日志
-			Node::whereId($id)->delete();
-			NodeLabel::whereNodeId($id)->delete();
-			NodeHeartBeat::whereNodeId($id)->delete();
-			NodeOnlineLog::whereNodeId($id)->delete();
-			NodeDailyDataFlow::whereNodeId($id)->delete();
-			NodeHourlyDataFlow::whereNodeId($id)->delete();
-			NodePing::whereNodeId($id)->delete();
-			UserDailyDataFlow::whereNodeId($id)->delete();
-			UserHourlyDataFlow::whereNodeId($id)->delete();
-			UserDataFlowLog::whereNodeId($id)->delete();
-			NodeAuth::whereNodeId($id)->delete();
-			NodeRule::whereNodeId($id)->delete();
-			foreach(RuleGroup::all() as $ruleGroup){
-				$nodes = $ruleGroup->nodes;
-				if($nodes && in_array($id, $nodes, true)){
-					$ruleGroup->nodes = array_merge(array_diff($nodes, [$id]));
-					$ruleGroup->save();
-				}
-			}
-
-			foreach(UserGroup::all() as $userGroup){
-				$nodes = $userGroup->nodes;
-				if($nodes && in_array($id, $nodes, true)){
-					$userGroup->nodes = array_merge(array_diff($nodes, [$id]));
-					$userGroup->save();
-				}
-			}
-
+			$node->delete();
 			DB::commit();
 
 			return Response::json(['status' => 'success', 'message' => '删除成功']);
@@ -402,8 +332,7 @@ class NodeController extends Controller {
 
 	// 节点流量监控
 	public function nodeMonitor(Request $request) {
-		$node_id = $request->input('id');
-		$node = Node::find($node_id);
+		$node = Node::find($request->input('id'));
 		if(!$node){
 			Session::flash('errorMsg', '节点不存在,请重试');
 
@@ -418,8 +347,8 @@ class NodeController extends Controller {
 	}
 
 	// Ping节点延迟
-	public function pingNode(Request $request): ?JsonResponse {
-		$node = Node::find($request->input('id'));
+	public function pingNode($id): ?JsonResponse {
+		$node = Node::find($id);
 		if(!$node){
 			return Response::json(['status' => 'fail', 'message' => '节点不存在,请重试']);
 		}
@@ -509,7 +438,6 @@ class NodeController extends Controller {
 		foreach($DvList as $Dv){
 			if($Dv->key && $Dv->pem){
 				$DvInfo = openssl_x509_parse($Dv->pem);
-				//dd($DvInfo);
 				$Dv->issuer = $DvInfo['issuer']['O'];
 				$Dv->from = $DvInfo['validFrom_time_t']? date('Y-m-d', $DvInfo['validFrom_time_t']) : null;
 				$Dv->to = $DvInfo['validTo']? date('Y-m-d', $DvInfo['validTo_time_t']) : null;

+ 1 - 1
app/Http/Controllers/User/SubscribeController.php

@@ -154,7 +154,7 @@ class SubscribeController extends Controller {
 	// 写入订阅访问日志
 	private function subscribeLog($subscribeId, $ip, $headers): void {
 		$log = new UserSubscribeLog();
-		$log->subscribe_id = $subscribeId;
+		$log->user_subscribe_id = $subscribeId;
 		$log->request_ip = $ip;
 		$log->request_time = date('Y-m-d H:i:s');
 		$log->request_header = $headers;

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

@@ -548,7 +548,7 @@ class UserController extends Controller {
 		}catch(Exception $e){
 			DB::rollBack();
 
-			Log::info("更换订阅地址异常:".$e->getMessage());
+			Log::error("更换订阅地址异常:".$e->getMessage());
 
 			return Response::json(['status' => 'fail', 'message' => '更换失败'.$e->getMessage()]);
 		}
@@ -606,7 +606,7 @@ class UserController extends Controller {
 
 			return Response::json(['status' => 'success', 'message' => '充值成功']);
 		}catch(Exception $e){
-			Log::error($e);
+			Log::error('卡劵充值错误:'.$e->getMessage());
 			DB::rollBack();
 
 			return Response::json(['status' => 'fail', 'message' => '充值失败']);

+ 1 - 1
app/Http/Middleware/isForbidden.php

@@ -27,7 +27,7 @@ class isForbidden {
 		}
 
 		// 拒绝通过订阅链接域名访问网站,防止网站被探测
-		if(true === strpos(sysConfig('subscribe_domain'), $request->getHost())
+		if(false !== strpos(sysConfig('subscribe_domain'), $request->getHost())
 		   && !str_contains(sysConfig('subscribe_domain'), sysConfig('website_url'))){
 			Log::info("识别到通过订阅链接访问,强制跳转至百度(".getClientIp().")");
 

+ 10 - 18
app/Jobs/VNet/addUser.php

@@ -13,46 +13,38 @@ use Illuminate\Queue\SerializesModels;
 class addUser implements ShouldQueue {
 	use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
 
-	private static $data;
-	private static $url;
+	private $data;
 	private $nodes;
 
-	public function __construct(User $users, $nodes) {
+	public function __construct($userIds, $nodes) {
 		$this->nodes = $nodes;
-		if($users->count() > 1){
-			self::$url = '/api/v2/user/add/list';
-		}else{
-			self::$url = '/api/user/add';
-		}
 		$data = [];
-		foreach($users as $user){
+		foreach(User::findMany($userIds) as $user){
 			$data[] = [
 				'uid'         => $user->id,
 				'port'        => $user->port,
 				'passwd'      => $user->passwd,
 				'speed_limit' => $user->speed_limit,
-				'enable'      => $user->enable,
+				'enable'      => $user->enable
 			];
 		}
-		self::$data = $data;
+
+		$this->data = $data;
 	}
 
 	public function handle(): void {
 		foreach($this->nodes as $node){
-			self::send(($node->server?: $node->ip).':'.$node->push_port, $node->auth->secret);
+			$this->send(($node->server?: $node->ip).':'.$node->push_port, $node->auth->secret);
 		}
 	}
 
-	private static function send($host, $secret): void {
+	private function send($host, $secret): void {
 		$client = new Client([
 			'base_uri' => $host,
 			'timeout'  => 15,
-			'headers'  => [
-				'secret'       => $secret,
-				'content-type' => 'application/json'
-			]
+			'headers'  => ['secret' => $secret]
 		]);
 
-		$client->post(self::$url, ['body' => json_encode(self::$data)]);
+		$client->post('api/v2/user/add/list', ['json' => $this->data]);
 	}
 }

+ 8 - 11
app/Jobs/VNet/delUser.php

@@ -12,34 +12,31 @@ use Illuminate\Queue\SerializesModels;
 class delUser implements ShouldQueue {
 	use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
 
-	private static $userIds;
+	private $userIds;
 	private $nodes;
 
 	public function __construct($userIds, $nodes) {
-		self::$userIds = $userIds;
+		$this->userIds = $userIds;
 		$this->nodes = $nodes;
 	}
 
 	public function handle(): void {
 		foreach($this->nodes as $node){
-			self::send(($node->server?: $node->ip).':'.$node->push_port, $node->auth->secret);
+			$this->send(($node->server?: $node->ip).':'.$node->push_port, $node->auth->secret);
 		}
 	}
 
-	private static function send($host, $secret): void {
+	private function send($host, $secret): void {
 		$client = new Client([
 			'base_uri' => $host,
 			'timeout'  => 15,
-			'headers'  => [
-				'secret'       => $secret,
-				'content-type' => 'application/json'
-			]
+			'headers'  => ['secret' => $secret]
 		]);
 
-		if(is_array(self::$userIds)){
-			$client->post('/api/v2/user/del/list', ['body' => json_encode(self::$userIds)]);
+		if(is_array($this->userIds)){
+			$client->post('api/v2/user/del/list', ['json' => $this->userIds]);
 		}else{
-			$client->post('/api/user/del/'.self::$userIds);
+			$client->post('api/user/del/'.$this->userIds);
 		}
 	}
 }

+ 8 - 11
app/Jobs/VNet/editUser.php

@@ -13,36 +13,33 @@ use Illuminate\Queue\SerializesModels;
 class editUser implements ShouldQueue {
 	use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
 
-	private static $data;
+	private $data;
 	private $nodes;
 
 	public function __construct(User $user, $nodes) {
 		$this->nodes = $nodes;
-		self::$data = [
+		$this->data = [
 			'uid'         => $user->id,
-			'port'        => $user->port,
+			'port'        => (int) $user->port,
 			'passwd'      => $user->passwd,
 			'speed_limit' => $user->speed_limit,
-			'enable'      => $user->enable,
+			'enable'      => (int) $user->enable
 		];
 	}
 
 	public function handle(): void {
 		foreach($this->nodes as $node){
-			self::send(($node->server?: $node->ip).':'.$node->push_port, $node->auth->secret);
+			$this->send(($node->server?: $node->ip).':'.$node->push_port, $node->auth->secret);
 		}
 	}
 
-	private static function send($host, $secret): void {
+	private function send($host, $secret): void {
 		$client = new Client([
 			'base_uri' => $host,
 			'timeout'  => 15,
-			'headers'  => [
-				'secret'       => $secret,
-				'content-type' => 'application/json'
-			]
+			'headers'  => ['secret' => $secret]
 		]);
 
-		$client->post('/api/user/edit', ['body' => json_encode(self::$data)]);
+		$client->post('api/user/edit', ['json' => $this->data]);
 	}
 }

+ 49 - 31
app/Jobs/VNet/reloadNode.php

@@ -2,52 +2,70 @@
 
 namespace App\Jobs\VNet;
 
-use App\Models\Node;
 use GuzzleHttp\Client;
 use Illuminate\Bus\Queueable;
 use Illuminate\Contracts\Queue\ShouldQueue;
 use Illuminate\Foundation\Bus\Dispatchable;
 use Illuminate\Queue\InteractsWithQueue;
 use Illuminate\Queue\SerializesModels;
+use Log;
 
 class reloadNode implements ShouldQueue {
 	use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
 
-	private static $host;
-	private static $secret;
-	private static $data;
-
-	public function __construct(Node $node) {
-		self::$host = ($node->server?: $node->ip).':'.$node->push_port;
-		self::$secret = $node->auth->secret;
-		self::$data = [
-			'id'           => $node->id,
-			'method'       => $node->method,
-			'protocol'     => $node->protocol,
-			'obfs'         => $node->obfs,
-			'obfs_param'   => $node->obfs_param?: '',
-			'is_udp'       => $node->is_udp,
-			'speed_limit'  => $node->speed_limit,
-			'client_limit' => $node->client_limit,
-			'single'       => $node->single,
-			'port'         => (string) $node->port,
-			'passwd'       => $node->passwd?: '',
-			'push_port'    => $node->push_port,
-			'secret'       => $node->auth->secret,
-			'redirect_url' => sysConfig('redirect_url')
-		];
+	private $nodes;
+
+	public function __construct($nodes) {
+		$this->nodes = $nodes;
+	}
+
+	public function handle(): bool {
+		$allSuccess = true;
+		foreach($this->nodes as $node){
+			$ret = $this->send(($node->server?: $node->ip).':'.$node->push_port, $node->auth->secret, [
+				'id'             => $node->id,
+				'port'           => (string) $node->port,
+				'passwd'         => $node->passwd?: '',
+				'method'         => $node->method,
+				'protocol'       => $node->protocol,
+				'obfs'           => $node->obfs,
+				'protocol_param' => $node->protocol_param,
+				'obfs_param'     => $node->obfs_param?: '',
+				'push_port'      => $node->push_port,
+				'single'         => $node->single,
+				'secret'         => $node->auth->secret,
+				//			'is_udp'         => $node->is_udp,
+				//			'speed_limit'    => $node->speed_limit,
+				//			'client_limit'   => $node->client_limit,
+				//			'redirect_url'   => (string) sysConfig('redirect_url')
+			]);
+
+			if(!$ret){
+				$allSuccess = false;
+			}
+		}
+
+		return $allSuccess;
 	}
 
-	public function handle(): void {
+	public function send($host, $secret, $data): bool {
 		$client = new Client([
-			'base_uri' => self::$host,
+			'base_uri' => $host,
 			'timeout'  => 15,
-			'headers'  => [
-				'secret'       => self::$secret,
-				'content-type' => 'application/json'
-			]
+			'headers'  => ['secret' => $secret]
 		]);
 
-		$client->post('/api/v2/node/reload', ['body' => json_encode(self::$data)]);
+		$ret = $client->post('api/v2/node/reload', ['json' => $data]);
+		if($ret->getStatusCode() == 200){
+			$message = json_decode($ret->getBody(), true);
+			if(array_key_exists('success', $message) && array_key_exists('content', $message)){
+				if($message['success']){
+					return true;
+				}
+				Log::error('重载节点失败:'.$host.' 反馈:'.$message['content']);
+			}
+		}
+		Log::error('重载节点失败url: '.$host);
+		return false;
 	}
 }

+ 25 - 1
app/Models/Node.php

@@ -17,10 +17,34 @@ class Node extends Model {
 		return $this->hasMany(NodeLabel::class);
 	}
 
-	public function nodeHeartBeat(): HasMany {
+	public function heartBeats(): HasMany {
 		return $this->hasMany(NodeHeartBeat::class);
 	}
 
+	public function onlineLogs(): HasMany {
+		return $this->hasMany(NodeOnlineLog::class);
+	}
+
+	public function pingLogs(): HasMany {
+		return $this->hasMany(NodePing::class);
+	}
+
+	public function dailyDataFlows(): HasMany {
+		return $this->hasMany(NodeDailyDataFlow::class);
+	}
+
+	public function hourlyDataFlows(): HasMany {
+		return $this->hasMany(NodeHourlyDataFlow::class);
+	}
+
+	public function rules(): hasMany {
+		return $this->hasMany(NodeRule::class);
+	}
+
+	public function ruleGroup(): hasOne {
+		return $this->hasOne(RuleGroupNode::class);
+	}
+
 	public function auth(): HasOne {
 		return $this->hasOne(NodeAuth::class);
 	}

+ 1 - 1
app/Models/User.php

@@ -38,7 +38,7 @@ class User extends Authenticatable {
 	}
 
 	public function commissionLogs(): HasMany {
-		return $this->hasMany(ReferralLog::class,'inviter_id');
+		return $this->hasMany(ReferralLog::class, 'inviter_id');
 	}
 
 	public function ruleLogs(): HasMany {

+ 1 - 1
app/Models/UserSubscribeLog.php

@@ -19,6 +19,6 @@ class UserSubscribeLog extends Model {
 	}
 
 	public function user(): HasOneThrough {
-		return $this->hasOneThrough(User::class, UserSubscribe::class, 'id', 'id', 'subscribe_id', 'user_id');
+		return $this->hasOneThrough(User::class, UserSubscribe::class, 'id', 'id', 'user_subscribe_id', 'user_id');
 	}
 }

+ 64 - 0
app/Observers/NodeObserver.php

@@ -0,0 +1,64 @@
+<?php
+
+namespace App\Observers;
+
+use App\Jobs\VNet\reloadNode;
+use App\Models\Node;
+use App\Models\NodeAuth;
+use App\Models\RuleGroup;
+use App\Models\UserGroup;
+use App\Services\NodeService;
+use Log;
+
+class NodeObserver {
+	public function saved(Node $node): void {
+		(new NodeService())->getNodeGeo($node->id);
+	}
+
+	public function created(Node $node): void {
+		$auth = new NodeAuth();
+		$auth->node_id = $node->id;
+		$auth->key = makeRandStr(16);
+		$auth->secret = makeRandStr(8);
+		if(!$auth->save()){
+			Log::error('节点生成-自动生成授权时出现错误,请稍后自行生成授权!');
+		}
+	}
+
+	public function updated(Node $node): void {
+		if($node->type == 4){
+			reloadNode::dispatch(Node::whereType(4)->whereId($node->id)->get());
+		}
+	}
+
+	public function deleted(Node $node): void {
+		// 删除分组关联、节点标签、节点相关日志
+		$node->labels()->delete();
+		$node->heartBeats()->delete();
+		$node->onlineLogs()->delete();
+		$node->pingLogs()->delete();
+		$node->dailyDataFlows()->delete();
+		$node->hourlyDataFlows()->delete();
+		$node->rules()->delete();
+		$node->ruleGroup()->delete();
+		$node->auth()->delete();
+
+		// 断开审计规则分组节点联系
+		foreach(RuleGroup::all() as $ruleGroup){
+			$nodes = $ruleGroup->nodes;
+			if($nodes && in_array($node->id, $nodes, true)){
+				$ruleGroup->nodes = array_merge(array_diff($nodes, [$node->id]));
+				$ruleGroup->save();
+			}
+		}
+
+		// 断开用户分组控制节点联系
+		foreach(UserGroup::all() as $userGroup){
+			$nodes = $userGroup->nodes;
+			if($nodes && in_array($node->id, $nodes, true)){
+				$userGroup->nodes = array_merge(array_diff($nodes, [$node->id]));
+				$userGroup->save();
+			}
+		}
+	}
+}

+ 28 - 0
app/Observers/RuleGroupObserver.php

@@ -0,0 +1,28 @@
+<?php
+
+namespace App\Observers;
+
+use App\Jobs\VNet\reloadNode;
+use App\Models\Node;
+use App\Models\RuleGroup;
+use Arr;
+
+class RuleGroupObserver {
+	public function updated(RuleGroup $ruleGroup): void {
+		$changes = $ruleGroup->getChanges();
+		if(Arr::exists($changes, 'type') || Arr::exists($changes, 'rules')){
+			$nodes = Node::whereType(4)->whereIn('id', $ruleGroup->nodes)->get();
+			if($nodes){
+				reloadNode::dispatch($nodes);
+			}
+		}elseif(Arr::exists($changes, 'nodes')){
+			$nodes = Node::whereType(4)
+			             ->whereIn('id',
+				             array_diff($ruleGroup->nodes, json_decode($ruleGroup->getOriginal('nodes'), true)))
+			             ->get();
+			if($nodes){
+				reloadNode::dispatch($nodes);
+			}
+		}
+	}
+}

+ 30 - 0
app/Observers/UserGroupObserver.php

@@ -0,0 +1,30 @@
+<?php
+
+namespace App\Observers;
+
+use App\Jobs\VNet\reloadNode;
+use App\Models\Node;
+use App\Models\UserGroup;
+use Arr;
+
+class UserGroupObserver {
+	public function created(UserGroup $userGroup): void {
+		$nodes = Node::whereType(4)->whereIn('id', $userGroup->nodes)->get();
+		if($nodes){
+			reloadNode::dispatch($nodes);
+		}
+	}
+
+	public function updated(UserGroup $userGroup): void {
+		$changes = $userGroup->getChanges();
+		if(Arr::exists($changes, 'nodes')){
+			$nodes = Node::whereType(4)
+			             ->whereIn('id',
+				             array_diff($userGroup->nodes, json_decode($userGroup->getOriginal('nodes'), true)))
+			             ->get();
+			if($nodes){
+				reloadNode::dispatch($nodes);
+			}
+		}
+	}
+}

+ 4 - 2
app/Observers/UserObserver.php

@@ -16,7 +16,7 @@ class UserObserver {
 	public function created(User $user): void {
 		$allowNodes = Node::userAllowNodes($user->group_id, $user->level)->whereType(4)->get();
 		if($allowNodes){
-			addUser::dispatch($user, $allowNodes);
+			addUser::dispatch($user->id, $allowNodes);
 		}
 	}
 
@@ -24,7 +24,9 @@ class UserObserver {
 		$changes = $user->getChanges();
 		$allowNodes = Node::userAllowNodes($user->group_id, $user->level)->whereType(4)->get();
 		if($allowNodes
-		   && Arr::exists($changes, 'port')
+		   && Arr::exists($changes, 'level')
+		   || Arr::exists($changes, 'group_id')
+		   || Arr::exists($changes, 'port')
 		   || Arr::exists($changes, 'passwd')
 		   || Arr::exists($changes, 'speed_limit')
 		   || Arr::exists($changes, 'enable')){

+ 9 - 0
app/Providers/AppServiceProvider.php

@@ -2,9 +2,15 @@
 
 namespace App\Providers;
 
+use App\Models\Node;
 use App\Models\Order;
+use App\Models\RuleGroup;
 use App\Models\User;
+use App\Models\UserGroup;
+use App\Observers\NodeObserver;
 use App\Observers\OrderObserver;
+use App\Observers\RuleGroupObserver;
+use App\Observers\UserGroupObserver;
 use App\Observers\UserObserver;
 use Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider;
 use Illuminate\Support\ServiceProvider;
@@ -34,7 +40,10 @@ class AppServiceProvider extends ServiceProvider {
 			URL::forceScheme('https');
 		}
 
+		Node::observe(NodeObserver::class);
 		Order::observe(OrderObserver::class);
+		RuleGroup::observe(RuleGroupObserver::class);
+		UserGroup::observe(UserGroupObserver::class);
 		User::observe(UserObserver::class);
 	}
 }

+ 42 - 0
app/Services/NodeService.php

@@ -0,0 +1,42 @@
+<?php
+
+namespace App\Services;
+
+use App\Models\Node;
+use App\Models\NodeLabel;
+
+class NodeService {
+	public function getNodeGeo($id = false): int {
+		if($id){
+			$nodes = Node::whereStatus(1)->whereId($id)->get();
+		}else{
+			$nodes = Node::whereStatus(1)->get();
+		}
+
+		$result = 0;
+		foreach($nodes as $node){
+			$data = getIPInfo($node->is_ddns? gethostbyname($node->server) : $node->ip);
+			if($data){
+				if(Node::whereId($node->id)->update(['geo' => $data['latitude'].','.$data['longitude']])){
+					$result++;
+				}
+			}
+		}
+		return $result;
+	}
+
+	// 生成节点标签
+	public function makeLabels($nodeId, $labels): void {
+		// 先删除所有该节点的标签
+		NodeLabel::whereNodeId($nodeId)->delete();
+
+		if(!empty($labels) && is_array($labels)){
+			foreach($labels as $label){
+				$nodeLabel = new NodeLabel();
+				$nodeLabel->node_id = $nodeId;
+				$nodeLabel->label_id = $label;
+				$nodeLabel->save();
+			}
+		}
+	}
+}

+ 1 - 1
app/Services/OrderService.php

@@ -50,7 +50,7 @@ class OrderService {
 				$this->setCommissionExpense(self::$user);// 返利
 				break;
 			default:
-				Log::info('【处理订单】出现错误-未知套餐类型');
+				Log::error('【处理订单】出现错误-未知套餐类型');
 		}
 
 		return true;

+ 1 - 1
app/helpers.php

@@ -172,7 +172,7 @@ if(!function_exists('getIPInfo')){
 			return $message;
 		}
 
-		Log::debug('解析IPv6异常:'.$ip.PHP_EOL.var_export($request, true));
+		Log::error('解析IPv6异常:'.$ip.PHP_EOL.var_export($request, true));
 		return false;
 	}
 }

+ 1 - 0
composer.json

@@ -10,6 +10,7 @@
   "require": {
 	"php": "^7.2",
 	"ext-json": "*",
+	"ext-openssl": "*",
 	"barryvdh/laravel-ide-helper": "^2.7",
 	"fideloper/proxy": "^4.3",
 	"guzzlehttp/guzzle": "^6",

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

@@ -62,7 +62,7 @@
 							<td>{{$vo->node ? $vo->node->name : '【节点已删除】'}}</td>
 							<td>{{$vo->user ? $vo->user->email : '【用户已删除】'}}</td>
 							<td>
-								@if (strpos($vo->ip, ',') === true)
+								@if (strpos($vo->ip, ',') !== false)
 									@foreach (explode(',', $vo->ip) as $ip)
 										<a href="https://www.ipip.net/ip/{{$ip}}.html" target="_blank">{{$ip}}</a>
 									@endforeach
@@ -70,7 +70,7 @@
 									<a href="https://www.ipip.net/ip/{{$vo->ip}}.html" target="_blank">{{$vo->ip}}</a>
 								@endif
 							</td>
-							<td>{{strpos($vo->ip, ',') === true? '':$vo->ipInfo}}</td>
+							<td>{{strpos($vo->ip, ',') !== false? '':$vo->ipInfo}}</td>
 							<td>{{date('Y-m-d H:i:s',$vo->created_at)}}</td>
 						</tr>
 					@endforeach
@@ -94,8 +94,7 @@
 @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 src="/assets/global/vendor/bootstrap-table/extensions/mobile/bootstrap-table-mobile.min.js" type="text/javascript"></script>
 	<script src="/assets/custom/Plugin/clipboardjs/clipboard.min.js" type="text/javascript"></script>
 	<script type="text/javascript">
 		//回车检测

+ 1 - 1
resources/views/admin/node/nodeInfo.blade.php

@@ -544,7 +544,7 @@
 				success: function (ret) {
 					if (ret.status === 'success') {
 						swal.fire({title: ret.message, type: 'success', timer: 1000, showConfirmButton: false})
-							.then(() => window.location.href = '/node')
+							.then(() => window.location.reload())
 					} else {
 						swal.fire({
 							title: '[错误 | Error]',

+ 41 - 4
resources/views/admin/node/nodeList.blade.php

@@ -66,6 +66,11 @@
 							</td>
 							<td>
 								<div class="btn-group">
+									@if($node->type === 4)
+										<button type="button" onclick="reload('{{$node->id}}')" class="btn btn-primary">
+											<i id="reload{{$node->id}}" class="icon wb-reload"></i>
+										</button>
+									@endif
 									<button type="button" onclick="refreshGeo('{{$node->id}}')" class="btn btn-primary">
 										<i id="geo{{$node->id}}" class="icon wb-map"></i>
 									</button>
@@ -114,8 +119,8 @@
 		function checkNode(id) {
 			$.ajax({
 				type: "POST",
-				url: '/node/check',
-				data: {_token: '{{csrf_token()}}', id: id},
+				url: '/node/check/' + id,
+				data: {_token: '{{csrf_token()}}'},
 				beforeSend: function () {
 					$("#node" + id).removeClass("wb-signal").addClass("wb-loop icon-spin");
 				},
@@ -141,8 +146,8 @@
 		function pingNode(id) {
 			$.ajax({
 				type: "POST",
-				url: '/node/ping',
-				data: {_token: '{{csrf_token()}}', id: id},
+				url: '/node/ping/' + id,
+				data: {_token: '{{csrf_token()}}'},
 				beforeSend: function () {
 					$("#ping" + id).removeClass("wb-order").addClass("wb-loop icon-spin");
 				},
@@ -163,6 +168,38 @@
 			});
 		}
 
+		// 发送节点重载请求
+		function reload(id) {
+			swal.fire({
+				text: '确定重载节点?',
+				type: 'question',
+				showCancelButton: true,
+				cancelButtonText: '{{trans('home.ticket_close')}}',
+				confirmButtonText: '{{trans('home.ticket_confirm')}}',
+			}).then((result) => {
+				if (result.value) {
+					$.ajax({
+						type: "post",
+						url: '/node/reload/' + id,
+						data: {_token: '{{csrf_token()}}'},
+						beforeSend: function () {
+							$("#reload" + id).removeClass("wb-reload").addClass("wb-loop icon-spin");
+						},
+						success: function (ret) {
+							if (ret.status === 'success') {
+								swal.fire({type: 'info', title: ret.message, showConfirmButton: false})
+							} else {
+								swal.fire({title: ret.message, type: "error"})
+							}
+						},
+						complete: function () {
+							$("#reload" + id).removeClass("wb-loop icon-spin").addClass("wb-reload");
+						}
+					});
+				}
+			})
+		}
+
 		// 刷新节点地理信息
 		function refreshGeo(id) {
 			$.ajax({

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

@@ -47,7 +47,7 @@
                                             browser. Please
 <a href="http://browsehappy.com/" target="_blank">upgrade your browser</a> to improve your experience.</p>
 <![endif]-->
-@if(Agent::isMobile() && Agent::is('iOS') && strpos(Agent::getUserAgent(), 'MicroMessenger') !== FALSE)
+@if(Agent::isMobile() && Agent::is('iOS') && strpos(Agent::getUserAgent(), 'MicroMessenger') !== false)
 	<style type="text/css">
         .cover-up {
             opacity: 0.1;

+ 3 - 2
routes/web.php

@@ -84,10 +84,11 @@ Route::group(['middleware' => ['isForbidden', 'isAdminLogin', 'isAdmin']], funct
 		Route::any('edit', 'NodeController@editNode'); // 编辑节点
 		Route::post('delete', 'NodeController@delNode'); // 删除节点
 		Route::get('monitor', 'NodeController@nodeMonitor'); // 节点流量监控
-		Route::post('check', 'NodeController@checkNode'); // 节点阻断检测
-		Route::post('ping', 'NodeController@pingNode'); // 节点ping测速
+		Route::post('check/{id}', 'NodeController@checkNode'); // 节点阻断检测
+		Route::post('ping/{id}', 'NodeController@pingNode'); // 节点ping测速
 		Route::get('pingLog', 'NodeController@pingLog'); //节点Ping测速日志
 		Route::get('refreshGeo', 'NodeController@refreshGeo'); //更新节点
+		Route::post('reload/{id}', 'NodeController@reload'); //更新节点
 		// 节点Api授权相关
 		Route::group(['prefix' => 'auth'], function() {
 			Route::get('/', 'NodeController@authList'); // 节点授权列表

+ 6 - 6
sql/db.sql

@@ -996,13 +996,13 @@ VALUES ('1', '1', 'SsXa1', Now(), Now());
 -- ----------------------------
 CREATE TABLE `user_subscribe_log`
 (
-    `id`             INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
-    `subscribe_id`   INT(10) UNSIGNED NOT NULL COMMENT '对应user_subscribe的id',
-    `request_ip`     CHAR(45) DEFAULT NULL COMMENT '请求IP',
-    `request_time`   DATETIME         NOT NULL COMMENT '请求时间',
-    `request_header` TEXT COMMENT '请求头部信息',
+    `id`                INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+    `user_subscribe_id` INT(10) UNSIGNED NOT NULL COMMENT '对应user_subscribe的id',
+    `request_ip`        CHAR(45) DEFAULT NULL COMMENT '请求IP',
+    `request_time`      DATETIME         NOT NULL COMMENT '请求时间',
+    `request_header`    TEXT COMMENT '请求头部信息',
     PRIMARY KEY (`id`),
-    INDEX `subscribe_id` (`subscribe_id`)
+    INDEX `user_subscribe_id` (`user_subscribe_id`)
 ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT ='用户订阅访问日志';
 
 

+ 3 - 3
sql/mod/20200807.sql

@@ -108,12 +108,12 @@ ALTER TABLE `order`
     ADD PRIMARY KEY (`id`);
 
 ALTER TABLE `user_subscribe_log`
-    CHANGE `sid` `subscribe_id` INT(10) UNSIGNED NOT NULL COMMENT '对应user_subscribe的id',
+    CHANGE `sid` `user_subscribe_id` INT(10) UNSIGNED NOT NULL COMMENT '对应user_subscribe的id',
     DROP INDEX `sid`,
-    ADD INDEX `subscribe_id` (`subscribe_id`);
+    ADD INDEX `user_subscribe_id` (`user_subscribe_id`);
 
 ALTER TABLE `user_baned_log`
     CHANGE `minutes` `time` INT(10) UNSIGNED NOT NULL DEFAULT '0' COMMENT '封禁账号时长,单位分钟';
 
 ALTER TABLE `payment`
-    CHANGE `oid` `order_id` INT(10) UNSIGNED NOT NULL COMMENT '本地订单ID';
+    CHANGE `oid` `order_id` INT(10) UNSIGNED NOT NULL COMMENT '本地订单ID';