Browse Source

简化url

兔姬桑 4 năm trước cách đây
mục cha
commit
7b6acf1351
30 tập tin đã thay đổi với 607 bổ sung657 xóa
  1. 1 1
      app/Http/Controllers/Admin/SensitiveWordsController.php
  2. 1 1
      app/Http/Controllers/Admin/ShopController.php
  3. 0 443
      app/Http/Controllers/AdminController.php
  4. 467 0
      app/Http/Controllers/NodeController.php
  5. 1 1
      app/Http/Controllers/UserController.php
  6. 1 1
      resources/views/admin/config/sensitiveWordsList.blade.php
  7. 2 2
      resources/views/admin/coupon/addCoupon.blade.php
  8. 5 5
      resources/views/admin/coupon/couponList.blade.php
  9. 2 2
      resources/views/admin/index.blade.php
  10. 28 30
      resources/views/admin/layouts.blade.php
  11. 2 2
      resources/views/admin/logs/nodePingLog.blade.php
  12. 2 2
      resources/views/admin/marketing/emailList.blade.php
  13. 3 3
      resources/views/admin/marketing/pushList.blade.php
  14. 3 3
      resources/views/admin/node/nodeInfo.blade.php
  15. 6 6
      resources/views/admin/node/nodeList.blade.php
  16. 1 1
      resources/views/admin/rule/assignNode.blade.php
  17. 2 2
      resources/views/admin/rule/ruleGroupInfo.blade.php
  18. 4 4
      resources/views/admin/rule/ruleGroupList.blade.php
  19. 5 5
      resources/views/admin/rule/ruleList.blade.php
  20. 3 3
      resources/views/admin/rule/ruleLogList.blade.php
  21. 0 78
      resources/views/admin/sensitiveWords/addSensitiveWords.blade.php
  22. 2 2
      resources/views/admin/shop/goodsInfo.blade.php
  23. 5 5
      resources/views/admin/shop/goodsList.blade.php
  24. 4 4
      resources/views/admin/subscribe/subscribeList.blade.php
  25. 3 3
      resources/views/admin/ticket/addTicket.blade.php
  26. 4 4
      resources/views/admin/ticket/replyTicket.blade.php
  27. 4 4
      resources/views/admin/ticket/ticketList.blade.php
  28. 1 1
      resources/views/admin/user/export.blade.php
  29. 3 3
      resources/views/user/ticketList.blade.php
  30. 42 36
      routes/web.php

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

@@ -20,7 +20,7 @@ class SensitiveWordsController extends Controller {
 	public function sensitiveWordsList() {
 		$view['list'] = SensitiveWords::query()->orderByDesc('id')->paginate(15);
 
-		return Response::view('admin.sensitiveWords.sensitiveWordsList', $view);
+		return Response::view('admin.config.sensitiveWordsList', $view);
 	}
 
 	// 添加敏感词

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

@@ -182,7 +182,7 @@ class ShopController extends Controller {
 				DB::rollBack();
 			}
 
-			return Redirect::to('shop/editGoods/'.$id);
+			return Redirect::to('shop/edit/'.$id);
 		}else{
 			$goods = Goods::query()->whereId($id)->first();
 

+ 0 - 443
app/Http/Controllers/AdminController.php

@@ -4,7 +4,6 @@ namespace App\Http\Controllers;
 
 use App\Components\Helpers;
 use App\Components\IPIP;
-use App\Components\NetworkDetection;
 use App\Components\PushNotification;
 use App\Components\QQWry;
 use App\Models\Article;
@@ -19,13 +18,9 @@ use App\Models\ReferralApply;
 use App\Models\ReferralLog;
 use App\Models\SsConfig;
 use App\Models\SsNode;
-use App\Models\SsNodeInfo;
 use App\Models\SsNodeIp;
 use App\Models\SsNodeLabel;
-use App\Models\SsNodeOnlineLog;
-use App\Models\SsNodePing;
 use App\Models\SsNodeTrafficDaily;
-use App\Models\SsNodeTrafficHourly;
 use App\Models\User;
 use App\Models\UserBanLog;
 use App\Models\UserCreditLog;
@@ -473,444 +468,6 @@ class AdminController extends Controller {
 		}
 	}
 
-	// 节点列表
-	public function nodeList(Request $request) {
-		if($request->isMethod('POST')){
-			$id = $request->input('id');
-			$node = SsNode::query()->whereId($id)->first();
-			// 使用DDNS的node先通过gethostbyname获取ipv4地址
-			if($node->is_ddns){
-				$ip = gethostbyname($node->server);
-				if(strcmp($ip, $node->server) != 0){
-					$node->ip = $ip;
-				}else{
-					return Response::json(['status' => 'fail', 'title' => 'IP获取错误', 'message' => $node->name.'IP获取失败']);
-				}
-			}
-			$data[0] = NetworkDetection::networkCheck($node->ip, true); //ICMP
-			$data[1] = NetworkDetection::networkCheck($node->ip, false, $node->single? $node->port : null); //TCP
-
-			return Response::json(['status' => 'success', 'title' => '['.$node->name.']阻断信息', 'message' => $data]);
-		}else{
-			$status = $request->input('status');
-
-			$query = SsNode::query();
-
-			if(isset($status)){
-				$query->whereStatus($status);
-			}
-
-			$nodeList = $query->orderByDesc('status')->orderBy('id')->paginate(15)->appends($request->except('page'));
-			foreach($nodeList as $node){
-				// 在线人数
-				$online_log = SsNodeOnlineLog::query()
-				                             ->whereNodeId($node->id)
-				                             ->where('log_time', '>=', strtotime("-5 minutes"))
-				                             ->orderByDesc('id')
-				                             ->first();
-				$node->online_users = empty($online_log)? 0 : $online_log->online_user;
-
-				// 已产生流量
-				$totalTraffic = SsNodeTrafficDaily::query()->whereNodeId($node->id)->sum('total');
-				$node->transfer = flowAutoShow($totalTraffic);
-
-				// 负载(10分钟以内)
-				$node_info = SsNodeInfo::query()
-				                       ->whereNodeId($node->id)
-				                       ->where('log_time', '>=', strtotime("-10 minutes"))
-				                       ->orderByDesc('id')
-				                       ->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);
-			}
-
-			$view['nodeList'] = $nodeList;
-		}
-
-		return Response::view('admin.node.nodeList', $view);
-	}
-
-	// 添加节点
-	public function addNode(Request $request) {
-		if($request->isMethod('POST')){
-			$validator = $this->nodeValidation($request);
-			if($validator){
-				return $validator;
-			}
-
-			// TODO:判断是否已存在绑定了相同域名的节点,提示是否要强制替换,或者不提示之前强制将其他节点的绑定域名置为空,然后发起域名绑定请求,或者请求进入队列
-			try{
-				DB::beginTransaction();
-
-				$node = new SsNode();
-				$node->type = $request->input('type');
-				$node->name = $request->input('name');
-				$node->country_code = $request->input('country_code');
-				$node->server = $request->input('server');
-				$node->ip = $request->input('ip');
-				$node->ipv6 = $request->input('ipv6');
-				$node->relay_server = $request->input('relay_server');
-				$node->relay_port = $request->input('relay_port');
-				$node->level = $request->input('level');
-				$node->speed_limit = $request->input('speed_limit');
-				$node->client_limit = $request->input('client_limit');
-				$node->description = $request->input('description');
-				$node->method = $request->input('method');
-				$node->protocol = $request->input('protocol');
-				$node->protocol_param = $request->input('protocol_param');
-				$node->obfs = $request->input('obfs');
-				$node->obfs_param = $request->input('obfs_param');
-				$node->traffic_rate = $request->input('traffic_rate');
-				$node->is_subscribe = intval($request->input('is_subscribe'));
-				$node->is_ddns = intval($request->input('is_ddns'));
-				$node->is_relay = intval($request->input('is_relay'));
-				$node->is_udp = intval($request->input('is_udp'));
-				$node->ssh_port = $request->input('ssh_port');
-				$node->detection_type = $request->input('detection_type');
-				$node->compatible = intval($request->input('compatible'));
-				$node->single = intval($request->input('single'));
-				$node->port = $request->input('port');
-				$node->passwd = $request->input('passwd');
-				$node->sort = $request->input('sort');
-				$node->status = intval($request->input('status'));
-				$node->v2_alter_id = $request->input('v2_alter_id');
-				$node->v2_port = $request->input('v2_port');
-				$node->v2_method = $request->input('v2_method');
-				$node->v2_net = $request->input('v2_net');
-				$node->v2_type = $request->input('v2_type');
-				$node->v2_host = $request->input('v2_host');
-				$node->v2_path = $request->input('v2_path');
-				$node->v2_tls = intval($request->input('v2_tls'));
-				$node->v2_tls_insecure = intval($request->input('v2_tls_insecure'));
-				$node->v2_tls_insecure_ciphers = intval($request->input('v2_tls_insecure_ciphers'));
-				$node->save();
-
-				DB::commit();
-				// 生成节点标签
-				$this->makeNodeLabels($node->id, $request->input('labels'));
-
-				return Response::json(['status' => 'success', 'message' => '添加成功']);
-			}catch(Exception $e){
-				DB::rollBack();
-				Log::error('添加节点信息异常:'.$e->getMessage());
-
-				return Response::json(['status' => 'fail', 'message' => '添加失败:'.$e->getMessage()]);
-			}
-		}else{
-			$view['method_list'] = Helpers::methodList();
-			$view['protocol_list'] = Helpers::protocolList();
-			$view['obfs_list'] = Helpers::obfsList();
-			$view['country_list'] = Country::query()->orderBy('code')->get();
-			$view['level_list'] = Level::query()->orderBy('level')->get();
-			$view['label_list'] = Label::query()->orderByDesc('sort')->orderBy('id')->get();
-
-			return Response::view('admin.node.nodeInfo', $view);
-		}
-	}
-
-	// 节点信息验证
-	private function nodeValidation(Request $request) {
-		if($request->input('server')){
-			$domain = $request->input('server');
-			$domain = explode('.', $domain);
-			$domainSuffix = end($domain); // 取得域名后缀
-
-			if(!in_array($domainSuffix, \config('domains'))){
-				return Response::json(['status' => 'fail', 'message' => '绑定域名不合法']);
-			}
-		}
-
-		$validator = Validator::make($request->all(), [
-			'type'                    => 'required|between:1,3',
-			'name'                    => 'required',
-			'country_code'            => 'required',
-			'server'                  => 'required_if:is_ddns,1',
-			'ssh_port'                => 'numeric|between:0,65535',
-			'traffic_rate'            => 'required|numeric|min:0',
-			'level'                   => 'required|numeric|between:0,255',
-			'speed_limit'             => 'required|numeric|min:0',
-			'client_limit'            => 'required|numeric|min:0',
-			'port'                    => 'numeric|between:0,65535',
-			'ip'                      => 'ipv4',
-			'ipv6'                    => 'nullable|ipv6',
-			'relay_server'            => 'required_if:is_relay,1',
-			'relay_port'              => 'required_if:is_relay,1|numeric|between:0,65535',
-			'method'                  => 'required_if:type,1',
-			'protocol'                => 'required_if:type,1',
-			'obfs'                    => 'required_if:type,1',
-			'is_subscribe'            => 'boolean',
-			'is_ddns'                 => 'boolean',
-			'is_relay'                => 'boolean',
-			'is_udp'                  => 'boolean',
-			'detection_type'          => 'between:0,3',
-			'compatible'              => 'boolean',
-			'single'                  => 'boolean',
-			'sort'                    => 'required|numeric|between:0,255',
-			'status'                  => 'boolean',
-			'v2_alter_id'             => 'required_if:type,2|numeric|between:0,65535',
-			'v2_port'                 => 'required_if:type,2|numeric|between:0,65535',
-			'v2_method'               => 'required_if:type,2',
-			'v2_net'                  => 'required_if:type,2',
-			'v2_type'                 => 'required_if:type,2',
-			'v2_tls'                  => 'boolean',
-			'v2_tls_insecure'         => 'required_if:v2_tls,1|boolean',
-			'v2_tls_insecure_ciphers' => 'required_if:v2_tls,1|boolean'
-		], [
-			'server.required_unless' => '开启DDNS, 域名不能为空',
-		]);
-
-		if($validator->fails()){
-			return Response::json(['status' => 'fail', 'message' => $validator->errors()->all()]);
-		}
-		return false;
-	}
-
-	// 生成节点标签
-	private function makeNodeLabels($nodeId, $labels) {
-		// 先删除所有该节点的标签
-		SsNodeLabel::query()->whereNodeId($nodeId)->delete();
-
-		if(!empty($labels) && is_array($labels)){
-			foreach($labels as $label){
-				$nodeLabel = new SsNodeLabel();
-				$nodeLabel->node_id = $nodeId;
-				$nodeLabel->label_id = $label;
-				$nodeLabel->save();
-			}
-		}
-	}
-
-	// 编辑节点
-	public function editNode(Request $request) {
-		$id = $request->input('id');
-
-		if($request->isMethod('POST')){
-			$validator = $this->nodeValidation($request);
-			if($validator){
-				return $validator;
-			}
-
-			try{
-				DB::beginTransaction();
-
-				$data = [
-					'type'                    => $request->input('type'),
-					'name'                    => $request->input('name'),
-					'country_code'            => $request->input('country_code'),
-					'server'                  => $request->input('server'),
-					'ip'                      => $request->input('ip'),
-					'ipv6'                    => $request->input('ipv6'),
-					'relay_server'            => $request->input('relay_server'),
-					'relay_port'              => $request->input('relay_port'),
-					'level'                   => $request->input('level'),
-					'speed_limit'             => $request->input('speed_limit'),
-					'client_limit'            => $request->input('client_limit'),
-					'description'             => $request->input('description'),
-					'method'                  => $request->input('method'),
-					'protocol'                => $request->input('protocol'),
-					'protocol_param'          => $request->input('protocol_param'),
-					'obfs'                    => $request->input('obfs'),
-					'obfs_param'              => $request->input('obfs_param'),
-					'traffic_rate'            => $request->input('traffic_rate'),
-					'is_subscribe'            => intval($request->input('is_subscribe')),
-					'is_ddns'                 => intval($request->input('is_ddns')),
-					'is_relay'                => intval($request->input('is_relay')),
-					'is_udp'                  => intval($request->input('is_udp')),
-					'ssh_port'                => $request->input('ssh_port'),
-					'detection_type'          => $request->input('detection_type'),
-					'compatible'              => intval($request->input('compatible')),
-					'single'                  => intval($request->input('single')),
-					'port'                    => $request->input('port'),
-					'passwd'                  => $request->input('passwd'),
-					'sort'                    => $request->input('sort'),
-					'status'                  => intval($request->input('status')),
-					'v2_alter_id'             => $request->input('v2_alter_id'),
-					'v2_port'                 => $request->input('v2_port'),
-					'v2_method'               => $request->input('v2_method'),
-					'v2_net'                  => $request->input('v2_net'),
-					'v2_type'                 => $request->input('v2_type'),
-					'v2_host'                 => $request->input('v2_host'),
-					'v2_path'                 => $request->input('v2_path'),
-					'v2_tls'                  => intval($request->input('v2_tls')),
-					'v2_tls_insecure'         => intval($request->input('v2_tls_insecure')),
-					'v2_tls_insecure_ciphers' => intval($request->input('v2_tls_insecure_ciphers'))
-				];
-
-				// 生成节点标签
-				$this->makeNodeLabels($id, $request->input('labels'));
-
-				SsNode::query()->whereId($id)->update($data);
-				// TODO:更新节点绑定的域名DNS(将节点IP更新到域名DNS 的A记录)
-
-				DB::commit();
-
-				return Response::json(['status' => 'success', 'message' => '编辑成功']);
-			}catch(Exception $e){
-				DB::rollBack();
-				Log::error('编辑节点信息异常:'.$e->getMessage());
-
-				return Response::json(['status' => 'fail', 'message' => '编辑失败:'.$e->getMessage()]);
-			}
-		}else{
-			$node = SsNode::query()->with(['label'])->whereId($id)->first();
-			if($node){
-				$node->labels = $node->label->pluck('label_id');
-			}
-
-			$view['node'] = $node;
-			$view['method_list'] = Helpers::methodList();
-			$view['protocol_list'] = Helpers::protocolList();
-			$view['obfs_list'] = Helpers::obfsList();
-			$view['country_list'] = Country::query()->orderBy('code')->get();
-			$view['level_list'] = Level::query()->orderBy('level')->get();
-			$view['label_list'] = Label::query()->orderByDesc('sort')->orderBy('id')->get();
-
-			return view('admin.node.nodeInfo', $view)->with(compact('node'));
-		}
-	}
-
-	// 删除节点
-	public function delNode(Request $request) {
-		$id = $request->input('id');
-
-		$node = SsNode::query()->whereId($id)->first();
-		if(!$node){
-			return Response::json(['status' => 'fail', 'data' => '', 'message' => '节点不存在,请重试']);
-		}
-
-		try{
-			DB::beginTransaction();
-			// 删除分组关联、节点标签、节点相关日志
-			SsNode::query()->whereId($id)->delete();
-			SsNodeLabel::query()->whereNodeId($id)->delete();
-			SsNodeInfo::query()->whereNodeId($id)->delete();
-			SsNodeOnlineLog::query()->whereNodeId($id)->delete();
-			SsNodeTrafficDaily::query()->whereNodeId($id)->delete();
-			SsNodeTrafficHourly::query()->whereNodeId($id)->delete();
-			SsNodePing::query()->whereNodeId($id)->delete();
-			UserTrafficDaily::query()->whereNodeId($id)->delete();
-			UserTrafficHourly::query()->whereNodeId($id)->delete();
-			UserTrafficLog::query()->whereNodeId($id)->delete();
-
-			DB::commit();
-
-			return Response::json(['status' => 'success', 'data' => '', 'message' => '删除成功']);
-		}catch(Exception $e){
-			DB::rollBack();
-			Log::error('删除节点信息异常:'.$e->getMessage());
-
-			return Response::json(['status' => 'fail', 'data' => '', 'message' => '删除失败:'.$e->getMessage()]);
-		}
-	}
-
-	// 节点流量监控
-	public function nodeMonitor($node_id) {
-		$node = SsNode::query()->whereId($node_id)->orderByDesc('sort')->first();
-		if(!$node){
-			Session::flash('errorMsg', '节点不存在,请重试');
-
-			return Redirect::back();
-		}
-
-		// 查看流量
-		$dailyData = [];
-		$hourlyData = [];
-
-		// 节点一个月内的流量
-		$nodeTrafficDaily = SsNodeTrafficDaily::query()
-		                                      ->with(['info'])
-		                                      ->whereNodeId($node->id)
-		                                      ->where('created_at', '>=', date('Y-m', time()))
-		                                      ->orderBy('created_at')
-		                                      ->pluck('total')
-		                                      ->toArray();
-		$dailyTotal = date('d', time()) - 1;//今天不算,减一
-		$dailyCount = count($nodeTrafficDaily);
-		for($x = 0; $x < ($dailyTotal - $dailyCount); $x++){
-			$dailyData[$x] = 0;
-		}
-		for($x = ($dailyTotal - $dailyCount); $x < $dailyTotal; $x++){
-			$dailyData[$x] = round($nodeTrafficDaily[$x - ($dailyTotal - $dailyCount)] / GB, 3);
-		}
-
-		// 节点一天内的流量
-		$nodeTrafficHourly = SsNodeTrafficHourly::query()
-		                                        ->with(['info'])
-		                                        ->whereNodeId($node->id)
-		                                        ->where('created_at', '>=', date('Y-m-d', time()))
-		                                        ->orderBy('created_at')
-		                                        ->pluck('total')
-		                                        ->toArray();
-		$hourlyTotal = date('H', time());
-		$hourlyCount = count($nodeTrafficHourly);
-		for($x = 0; $x < ($hourlyTotal - $hourlyCount); $x++){
-			$hourlyData[$x] = 0;
-		}
-		for($x = ($hourlyTotal - $hourlyCount); $x < $hourlyTotal; $x++){
-			$hourlyData[$x] = round($nodeTrafficHourly[$x - ($hourlyTotal - $hourlyCount)] / GB, 3);
-		}
-
-		$view['trafficDaily'] = ['nodeName' => $node->name, 'dailyData' => json_encode($dailyData)];
-
-		$view['trafficHourly'] = ['nodeName' => $node->name, 'hourlyData' => json_encode($hourlyData)];
-
-
-		// 本月天数数据
-		$monthDays = [];
-		for($i = 1; $i <= date("d"); $i++){
-			$monthDays[] = $i;
-		}
-		// 本日小时数据
-		$dayHours = [];
-		for($i = 1; $i <= date("H"); $i++){
-			$dayHours[] = $i;
-		}
-
-		$view['nodeName'] = $node->name;
-		$view['nodeServer'] = $node->server;
-		$view['monthDays'] = json_encode($monthDays);
-		$view['dayHours'] = json_encode($dayHours);
-
-		return Response::view('admin.node.nodeMonitor', $view);
-	}
-
-	// Ping节点延迟
-	public function pingNode(Request $request) {
-		$node = SsNode::query()->whereId($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访问失败']);
-		}
-	}
-
-	// Ping节点延迟日志
-	public function nodePingLog(Request $request) {
-
-		$node_id = $request->input('nodeId');
-		$query = SsNodePing::query();
-		if(isset($node_id)){
-			$query->whereNodeId($node_id);
-		}
-
-		$view['nodeList'] = SsNode::query()->orderBy('id')->get();
-		$view['pingLogs'] = $query->orderBy('id')->paginate(15)->appends($request->except('page'));
-
-		return Response::view('admin.logs.nodePingLog', $view);
-	}
-
 	// 文章列表
 	public function articleList(Request $request) {
 		$view['list'] = Article::query()->orderByDesc('sort')->paginate(15)->appends($request->except('page'));

+ 467 - 0
app/Http/Controllers/NodeController.php

@@ -0,0 +1,467 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Components\Helpers;
+use App\Components\NetworkDetection;
+use App\Models\Country;
+use App\Models\Label;
+use App\Models\Level;
+use App\Models\SsNode;
+use App\Models\SsNodeInfo;
+use App\Models\SsNodeLabel;
+use App\Models\SsNodeOnlineLog;
+use App\Models\SsNodePing;
+use App\Models\SsNodeTrafficDaily;
+use App\Models\SsNodeTrafficHourly;
+use App\Models\UserTrafficDaily;
+use App\Models\UserTrafficHourly;
+use App\Models\UserTrafficLog;
+use DB;
+use Exception;
+use Illuminate\Http\Request;
+use Log;
+use Redirect;
+use Response;
+use Session;
+use Validator;
+
+class NodeController extends Controller {
+	// 节点列表
+	public function nodeList(Request $request) {
+		if($request->isMethod('POST')){
+			$id = $request->input('id');
+			$node = SsNode::query()->whereId($id)->first();
+			// 使用DDNS的node先获取ipv4地址
+			if($node->is_ddns){
+				$ip = gethostbyname($node->server);
+				if(strcmp($ip, $node->server) != 0){
+					$node->ip = $ip;
+				}else{
+					return Response::json(['status' => 'fail', 'title' => 'IP获取错误', 'message' => $node->name.'IP获取失败']);
+				}
+			}
+			$data[0] = NetworkDetection::networkCheck($node->ip, true); //ICMP
+			$data[1] = NetworkDetection::networkCheck($node->ip, false, $node->single? $node->port : null); //TCP
+
+			return Response::json(['status' => 'success', 'title' => '['.$node->name.']阻断信息', 'message' => $data]);
+		}else{
+			$status = $request->input('status');
+
+			$query = SsNode::query();
+
+			if(isset($status)){
+				$query->whereStatus($status);
+			}
+
+			$nodeList = $query->orderByDesc('status')->orderBy('id')->paginate(15)->appends($request->except('page'));
+			foreach($nodeList as $node){
+				// 在线人数
+				$online_log = SsNodeOnlineLog::query()
+				                             ->whereNodeId($node->id)
+				                             ->where('log_time', '>=', strtotime("-5 minutes"))
+				                             ->orderByDesc('id')
+				                             ->first();
+				$node->online_users = empty($online_log)? 0 : $online_log->online_user;
+
+				// 已产生流量
+				$totalTraffic = SsNodeTrafficDaily::query()->whereNodeId($node->id)->sum('total');
+				$node->transfer = flowAutoShow($totalTraffic);
+
+				// 负载(10分钟以内)
+				$node_info = SsNodeInfo::query()
+				                       ->whereNodeId($node->id)
+				                       ->where('log_time', '>=', strtotime("-10 minutes"))
+				                       ->orderByDesc('id')
+				                       ->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);
+			}
+
+			$view['nodeList'] = $nodeList;
+		}
+
+		return Response::view('admin.node.nodeList', $view);
+	}
+
+	// 添加节点
+	public function addNode(Request $request) {
+		if($request->isMethod('POST')){
+			$validator = $this->nodeValidation($request);
+			if($validator){
+				return $validator;
+			}
+
+			// TODO:判断是否已存在绑定了相同域名的节点,提示是否要强制替换,或者不提示之前强制将其他节点的绑定域名置为空,然后发起域名绑定请求,或者请求进入队列
+			try{
+				DB::beginTransaction();
+
+				$node = new SsNode();
+				$node->type = $request->input('type');
+				$node->name = $request->input('name');
+				$node->country_code = $request->input('country_code');
+				$node->server = $request->input('server');
+				$node->ip = $request->input('ip');
+				$node->ipv6 = $request->input('ipv6');
+				$node->relay_server = $request->input('relay_server');
+				$node->relay_port = $request->input('relay_port');
+				$node->level = $request->input('level');
+				$node->speed_limit = $request->input('speed_limit');
+				$node->client_limit = $request->input('client_limit');
+				$node->description = $request->input('description');
+				$node->method = $request->input('method');
+				$node->protocol = $request->input('protocol');
+				$node->protocol_param = $request->input('protocol_param');
+				$node->obfs = $request->input('obfs');
+				$node->obfs_param = $request->input('obfs_param');
+				$node->traffic_rate = $request->input('traffic_rate');
+				$node->is_subscribe = intval($request->input('is_subscribe'));
+				$node->is_ddns = intval($request->input('is_ddns'));
+				$node->is_relay = intval($request->input('is_relay'));
+				$node->is_udp = intval($request->input('is_udp'));
+				$node->ssh_port = $request->input('ssh_port');
+				$node->detection_type = $request->input('detection_type');
+				$node->compatible = intval($request->input('compatible'));
+				$node->single = intval($request->input('single'));
+				$node->port = $request->input('port');
+				$node->passwd = $request->input('passwd');
+				$node->sort = $request->input('sort');
+				$node->status = intval($request->input('status'));
+				$node->v2_alter_id = $request->input('v2_alter_id');
+				$node->v2_port = $request->input('v2_port');
+				$node->v2_method = $request->input('v2_method');
+				$node->v2_net = $request->input('v2_net');
+				$node->v2_type = $request->input('v2_type');
+				$node->v2_host = $request->input('v2_host');
+				$node->v2_path = $request->input('v2_path');
+				$node->v2_tls = intval($request->input('v2_tls'));
+				$node->v2_tls_insecure = intval($request->input('v2_tls_insecure'));
+				$node->v2_tls_insecure_ciphers = intval($request->input('v2_tls_insecure_ciphers'));
+				$node->save();
+
+				DB::commit();
+				// 生成节点标签
+				$this->makeLabels($node->id, $request->input('labels'));
+
+				return Response::json(['status' => 'success', 'message' => '添加成功']);
+			}catch(Exception $e){
+				DB::rollBack();
+				Log::error('添加节点信息异常:'.$e->getMessage());
+
+				return Response::json(['status' => 'fail', 'message' => '添加失败:'.$e->getMessage()]);
+			}
+		}else{
+			$view['method_list'] = Helpers::methodList();
+			$view['protocol_list'] = Helpers::protocolList();
+			$view['obfs_list'] = Helpers::obfsList();
+			$view['country_list'] = Country::query()->orderBy('code')->get();
+			$view['level_list'] = Level::query()->orderBy('level')->get();
+			$view['label_list'] = Label::query()->orderByDesc('sort')->orderBy('id')->get();
+
+			return Response::view('admin.node.nodeInfo', $view);
+		}
+	}
+
+	// 节点信息验证
+	private function nodeValidation(Request $request) {
+		if($request->input('server')){
+			$domain = $request->input('server');
+			$domain = explode('.', $domain);
+			$domainSuffix = end($domain); // 取得域名后缀
+
+			if(!in_array($domainSuffix, config('domains'))){
+				return Response::json(['status' => 'fail', 'message' => '绑定域名不合法']);
+			}
+		}
+
+		$validator = Validator::make($request->all(), [
+			'type'                    => 'required|between:1,3',
+			'name'                    => 'required',
+			'country_code'            => 'required',
+			'server'                  => 'required_if:is_ddns,1',
+			'ssh_port'                => 'numeric|between:0,65535',
+			'traffic_rate'            => 'required|numeric|min:0',
+			'level'                   => 'required|numeric|between:0,255',
+			'speed_limit'             => 'required|numeric|min:0',
+			'client_limit'            => 'required|numeric|min:0',
+			'port'                    => 'numeric|between:0,65535',
+			'ip'                      => 'ipv4',
+			'ipv6'                    => 'nullable|ipv6',
+			'relay_server'            => 'required_if:is_relay,1',
+			'relay_port'              => 'required_if:is_relay,1|numeric|between:0,65535',
+			'method'                  => 'required_if:type,1',
+			'protocol'                => 'required_if:type,1',
+			'obfs'                    => 'required_if:type,1',
+			'is_subscribe'            => 'boolean',
+			'is_ddns'                 => 'boolean',
+			'is_relay'                => 'boolean',
+			'is_udp'                  => 'boolean',
+			'detection_type'          => 'between:0,3',
+			'compatible'              => 'boolean',
+			'single'                  => 'boolean',
+			'sort'                    => 'required|numeric|between:0,255',
+			'status'                  => 'boolean',
+			'v2_alter_id'             => 'required_if:type,2|numeric|between:0,65535',
+			'v2_port'                 => 'required_if:type,2|numeric|between:0,65535',
+			'v2_method'               => 'required_if:type,2',
+			'v2_net'                  => 'required_if:type,2',
+			'v2_type'                 => 'required_if:type,2',
+			'v2_tls'                  => 'boolean',
+			'v2_tls_insecure'         => 'required_if:v2_tls,1|boolean',
+			'v2_tls_insecure_ciphers' => 'required_if:v2_tls,1|boolean'
+		], [
+			'server.required_unless' => '开启DDNS, 域名不能为空',
+		]);
+
+		if($validator->fails()){
+			return Response::json(['status' => 'fail', 'message' => $validator->errors()->all()]);
+		}
+		return false;
+	}
+
+	// 生成节点标签
+	private function makeLabels($nodeId, $labels) {
+		// 先删除所有该节点的标签
+		SsNodeLabel::query()->whereNodeId($nodeId)->delete();
+
+		if(!empty($labels) && is_array($labels)){
+			foreach($labels as $label){
+				$nodeLabel = new SsNodeLabel();
+				$nodeLabel->node_id = $nodeId;
+				$nodeLabel->label_id = $label;
+				$nodeLabel->save();
+			}
+		}
+	}
+
+	// 编辑节点
+	public function editNode(Request $request) {
+		$id = $request->input('id');
+
+		if($request->isMethod('POST')){
+			$validator = $this->nodeValidation($request);
+			if($validator){
+				return $validator;
+			}
+
+			try{
+				DB::beginTransaction();
+
+				$data = [
+					'type'                    => $request->input('type'),
+					'name'                    => $request->input('name'),
+					'country_code'            => $request->input('country_code'),
+					'server'                  => $request->input('server'),
+					'ip'                      => $request->input('ip'),
+					'ipv6'                    => $request->input('ipv6'),
+					'relay_server'            => $request->input('relay_server'),
+					'relay_port'              => $request->input('relay_port'),
+					'level'                   => $request->input('level'),
+					'speed_limit'             => $request->input('speed_limit'),
+					'client_limit'            => $request->input('client_limit'),
+					'description'             => $request->input('description'),
+					'method'                  => $request->input('method'),
+					'protocol'                => $request->input('protocol'),
+					'protocol_param'          => $request->input('protocol_param'),
+					'obfs'                    => $request->input('obfs'),
+					'obfs_param'              => $request->input('obfs_param'),
+					'traffic_rate'            => $request->input('traffic_rate'),
+					'is_subscribe'            => intval($request->input('is_subscribe')),
+					'is_ddns'                 => intval($request->input('is_ddns')),
+					'is_relay'                => intval($request->input('is_relay')),
+					'is_udp'                  => intval($request->input('is_udp')),
+					'ssh_port'                => $request->input('ssh_port'),
+					'detection_type'          => $request->input('detection_type'),
+					'compatible'              => intval($request->input('compatible')),
+					'single'                  => intval($request->input('single')),
+					'port'                    => $request->input('port'),
+					'passwd'                  => $request->input('passwd'),
+					'sort'                    => $request->input('sort'),
+					'status'                  => intval($request->input('status')),
+					'v2_alter_id'             => $request->input('v2_alter_id'),
+					'v2_port'                 => $request->input('v2_port'),
+					'v2_method'               => $request->input('v2_method'),
+					'v2_net'                  => $request->input('v2_net'),
+					'v2_type'                 => $request->input('v2_type'),
+					'v2_host'                 => $request->input('v2_host'),
+					'v2_path'                 => $request->input('v2_path'),
+					'v2_tls'                  => intval($request->input('v2_tls')),
+					'v2_tls_insecure'         => intval($request->input('v2_tls_insecure')),
+					'v2_tls_insecure_ciphers' => intval($request->input('v2_tls_insecure_ciphers'))
+				];
+
+				// 生成节点标签
+				$this->makeLabels($id, $request->input('labels'));
+
+				SsNode::query()->whereId($id)->update($data);
+				// TODO:更新节点绑定的域名DNS(将节点IP更新到域名DNS 的A记录)
+
+				DB::commit();
+
+				return Response::json(['status' => 'success', 'message' => '编辑成功']);
+			}catch(Exception $e){
+				DB::rollBack();
+				Log::error('编辑节点信息异常:'.$e->getMessage());
+
+				return Response::json(['status' => 'fail', 'message' => '编辑失败:'.$e->getMessage()]);
+			}
+		}else{
+			$node = SsNode::query()->with(['label'])->whereId($id)->first();
+			if($node){
+				$node->labels = $node->label->pluck('label_id');
+			}
+
+			$view['node'] = $node;
+			$view['method_list'] = Helpers::methodList();
+			$view['protocol_list'] = Helpers::protocolList();
+			$view['obfs_list'] = Helpers::obfsList();
+			$view['country_list'] = Country::query()->orderBy('code')->get();
+			$view['level_list'] = Level::query()->orderBy('level')->get();
+			$view['label_list'] = Label::query()->orderByDesc('sort')->orderBy('id')->get();
+
+			return view('admin.node.nodeInfo', $view)->with(compact('node'));
+		}
+	}
+
+	// 删除节点
+	public function delNode(Request $request) {
+		$id = $request->input('id');
+
+		$node = SsNode::query()->whereId($id)->first();
+		if(!$node){
+			return Response::json(['status' => 'fail', 'data' => '', 'message' => '节点不存在,请重试']);
+		}
+
+		try{
+			DB::beginTransaction();
+			// 删除分组关联、节点标签、节点相关日志
+			SsNode::query()->whereId($id)->delete();
+			SsNodeLabel::query()->whereNodeId($id)->delete();
+			SsNodeInfo::query()->whereNodeId($id)->delete();
+			SsNodeOnlineLog::query()->whereNodeId($id)->delete();
+			SsNodeTrafficDaily::query()->whereNodeId($id)->delete();
+			SsNodeTrafficHourly::query()->whereNodeId($id)->delete();
+			SsNodePing::query()->whereNodeId($id)->delete();
+			UserTrafficDaily::query()->whereNodeId($id)->delete();
+			UserTrafficHourly::query()->whereNodeId($id)->delete();
+			UserTrafficLog::query()->whereNodeId($id)->delete();
+
+			DB::commit();
+
+			return Response::json(['status' => 'success', 'data' => '', 'message' => '删除成功']);
+		}catch(Exception $e){
+			DB::rollBack();
+			Log::error('删除节点信息异常:'.$e->getMessage());
+
+			return Response::json(['status' => 'fail', 'data' => '', 'message' => '删除失败:'.$e->getMessage()]);
+		}
+	}
+
+	// 节点流量监控
+	public function nodeMonitor($node_id) {
+		$node = SsNode::query()->whereId($node_id)->orderByDesc('sort')->first();
+		if(!$node){
+			Session::flash('errorMsg', '节点不存在,请重试');
+
+			return Redirect::back();
+		}
+
+		// 查看流量
+		$dailyData = [];
+		$hourlyData = [];
+
+		// 节点一个月内的流量
+		$nodeTrafficDaily = SsNodeTrafficDaily::query()
+		                                      ->with(['info'])
+		                                      ->whereNodeId($node->id)
+		                                      ->where('created_at', '>=', date('Y-m', time()))
+		                                      ->orderBy('created_at')
+		                                      ->pluck('total')
+		                                      ->toArray();
+		$dailyTotal = date('d', time()) - 1;//今天不算,减一
+		$dailyCount = count($nodeTrafficDaily);
+		for($x = 0; $x < ($dailyTotal - $dailyCount); $x++){
+			$dailyData[$x] = 0;
+		}
+		for($x = ($dailyTotal - $dailyCount); $x < $dailyTotal; $x++){
+			$dailyData[$x] = round($nodeTrafficDaily[$x - ($dailyTotal - $dailyCount)] / GB, 3);
+		}
+
+		// 节点一天内的流量
+		$nodeTrafficHourly = SsNodeTrafficHourly::query()
+		                                        ->with(['info'])
+		                                        ->whereNodeId($node->id)
+		                                        ->where('created_at', '>=', date('Y-m-d', time()))
+		                                        ->orderBy('created_at')
+		                                        ->pluck('total')
+		                                        ->toArray();
+		$hourlyTotal = date('H', time());
+		$hourlyCount = count($nodeTrafficHourly);
+		for($x = 0; $x < ($hourlyTotal - $hourlyCount); $x++){
+			$hourlyData[$x] = 0;
+		}
+		for($x = ($hourlyTotal - $hourlyCount); $x < $hourlyTotal; $x++){
+			$hourlyData[$x] = round($nodeTrafficHourly[$x - ($hourlyTotal - $hourlyCount)] / GB, 3);
+		}
+
+		$view['trafficDaily'] = ['nodeName' => $node->name, 'dailyData' => json_encode($dailyData)];
+
+		$view['trafficHourly'] = ['nodeName' => $node->name, 'hourlyData' => json_encode($hourlyData)];
+
+
+		// 本月天数数据
+		$monthDays = [];
+		for($i = 1; $i <= date("d"); $i++){
+			$monthDays[] = $i;
+		}
+		// 本日小时数据
+		$dayHours = [];
+		for($i = 1; $i <= date("H"); $i++){
+			$dayHours[] = $i;
+		}
+
+		$view['nodeName'] = $node->name;
+		$view['nodeServer'] = $node->server;
+		$view['monthDays'] = json_encode($monthDays);
+		$view['dayHours'] = json_encode($dayHours);
+
+		return Response::view('admin.node.nodeMonitor', $view);
+	}
+
+	// Ping节点延迟
+	public function pingNode(Request $request) {
+		$node = SsNode::query()->whereId($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访问失败']);
+		}
+	}
+
+	// Ping节点延迟日志
+	public function pingLog(Request $request) {
+
+		$node_id = $request->input('nodeId');
+		$query = SsNodePing::query();
+		if(isset($node_id)){
+			$query->whereNodeId($node_id);
+		}
+
+		$view['nodeList'] = SsNode::query()->orderBy('id')->get();
+		$view['pingLogs'] = $query->orderBy('id')->paginate(15)->appends($request->except('page'));
+
+		return Response::view('admin.logs.nodePingLog', $view);
+	}
+}

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

@@ -369,7 +369,7 @@ class UserController extends Controller {
 	}
 
 	// 添加工单
-	public function addTicket(Request $request) {
+	public function createTicket(Request $request) {
 		$title = $request->input('title');
 		$content = clean($request->input('content'));
 		$content = str_replace("eval", "", str_replace("atob", "", $content));

+ 1 - 1
resources/views/admin/sensitiveWords/sensitiveWordsList.blade.php → resources/views/admin/config/sensitiveWordsList.blade.php

@@ -133,7 +133,7 @@
 				confirmButtonText: '确定',
 			}).then((result) => {
 				if (result.value) {
-					$.post("/sensitiveWords/del", {id: id, _token: '{{csrf_token()}}'}, function (ret) {
+					$.post("/sensitiveWords/delete", {id: id, _token: '{{csrf_token()}}'}, function (ret) {
 						if (ret.status === 'success') {
 							swal.fire({title: ret.message, type: 'success', timer: 1000, showConfirmButton: false})
 								.then(() => window.location.reload())

+ 2 - 2
resources/views/admin/coupon/addCoupon.blade.php

@@ -15,7 +15,7 @@
 			<div class="panel-heading">
 				<h1 class="panel-title">生成卡券</h1>
 				<div class="panel-actions">
-					<a href="{{url('/coupon/couponList')}}" class="btn btn-danger">返 回</a>
+					<a href="{{url('/coupon/list')}}" class="btn btn-danger">返 回</a>
 				</div>
 			</div>
 			@if (Session::has('successMsg'))
@@ -33,7 +33,7 @@
 				</div>
 			@endif
 			<div class="panel-body">
-				<form action="{{url('/coupon/addCoupon')}}" method="post" enctype="multipart/form-data" class="form-horizontal" role="form">
+				<form action="{{url('/coupon/add')}}" method="post" enctype="multipart/form-data" class="form-horizontal" role="form">
 					{{csrf_field()}}
 					<div class="form-group row">
 						<label class="col-md-2 col-form-label" for="name">卡券名称</label>

+ 5 - 5
resources/views/admin/coupon/couponList.blade.php

@@ -9,7 +9,7 @@
 				<h1 class="panel-title">卡券列表</h1>
 				<div class="panel-actions btn-group">
 					<button class="btn btn-info" onclick="exportCoupon()"><i class="icon wb-code"></i>批量导出</button>
-					<a href="{{url('/coupon/addCoupon')}}" class="btn btn-primary"><i class="icon wb-plus"></i>生成</a>
+					<a href="{{url('/coupon/add')}}" class="btn btn-primary"><i class="icon wb-plus"></i>生成</a>
 				</div>
 			</div>
 			<div class="panel-body">
@@ -35,7 +35,7 @@
 					</div>
 					<div class="form-group col-lg-3 col-sm-4 btn-group">
 						<button class="btn btn-primary" onclick="Search()">搜 索</button>
-						<a href="{{url('/coupon/couponList')}}" class="btn btn-danger">重 置</a>
+						<a href="{{url('/coupon/list')}}" class="btn btn-danger">重 置</a>
 					</div>
 				</div>
 				<table class="text-md-center" data-toggle="table" data-mobile-responsive="true">
@@ -134,7 +134,7 @@
 
 		// 搜索
 		function Search() {
-			window.location.href = '/coupon/couponList' + '?sn=' + $("#sn").val() + '&type=' + $("#type").val() + '&status=' + $("#status").val();
+			window.location.href = '/coupon/list' + '?sn=' + $("#sn").val() + '&type=' + $("#type").val() + '&status=' + $("#status").val();
 		}
 
 		// 批量导出卡券
@@ -148,7 +148,7 @@
 				confirmButtonText: '{{trans('home.ticket_confirm')}}',
 			}).then((result) => {
 				if (result.value) {
-					window.location.href = '/coupon/exportCoupon';
+					window.location.href = '/coupon/export';
 				}
 			});
 		}
@@ -164,7 +164,7 @@
 				confirmButtonText: '{{trans('home.ticket_confirm')}}',
 			}).then((result) => {
 				if (result.value) {
-					$.post("/coupon/delCoupon", {id: id, _token: '{{csrf_token()}}'}, function (ret) {
+					$.post("/coupon/delete", {id: id, _token: '{{csrf_token()}}'}, function (ret) {
 						if (ret.status === 'success') {
 							swal.fire({title: ret.message, type: 'success', timer: 1000, showConfirmButton: false})
 								.then(() => window.location.reload())

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

@@ -110,7 +110,7 @@
 				</a>
 			</div>
 			<div class="col-xl-3 col-md-6 info-panel">
-				<a href="/admin/nodeList" class="card card-shadow">
+				<a href="/node/list" class="card card-shadow">
 					<div class="card-block bg-white">
 						<button type="button" class="btn btn-floating btn-sm btn-primary">
 							<i class="icon md-cloud"></i>
@@ -123,7 +123,7 @@
 				</a>
 			</div>
 			<div class="col-xl-3 col-md-6 info-panel">
-				<a href="/admin/nodeList?status=0" class="card card-shadow">
+				<a href="/node/list?status=0" class="card card-shadow">
 					<div class="card-block bg-white">
 						<button type="button" class="btn btn-floating btn-sm btn-info">
 							<i class="icon md-cloud-off"></i>

+ 28 - 30
resources/views/admin/layouts.blade.php

@@ -135,32 +135,30 @@
 							<span class="site-menu-title">余额变动</span>
 						</a>
 					</li>
-					<li class="site-menu-item {{in_array(Request::path(), ['subscribe/subscribeList']) ? 'active open' : ''}}">
-						<a href="/subscribe/subscribeList" class="animsition-link">
+					<li class="site-menu-item {{in_array(Request::path(), ['subscribe/list']) ? 'active open' : ''}}">
+						<a href="/subscribe/list" class="animsition-link">
 							<span class="site-menu-title">订阅管理</span>
 						</a>
 					</li>
 				</ul>
 			</li>
-			<li class="site-menu-item has-sub {{in_array(Request::path(), ['ticket/ticketList', 'ticket/addTicket','ticket/replyTicket', 'admin/articleList', 'admin/addArticle', 'admin/editArticle', 'marketing/pushList', 'marketing/emailList']) ? 'active open' : ''}}">
+			<li class="site-menu-item has-sub {{in_array(Request::path(), ['ticket/list', 'ticket/add','ticket/reply', 'admin/articleList', 'admin/addArticle', 'admin/editArticle', 'marketing/push', 'marketing/email']) ? 'active open' : ''}}">
 				<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\Models\Ticket::query()->whereStatus(0)->count() > 0 )
 						<div class="site-menu-badge">
-							<span
-									class="badge badge-pill badge-success">{{\App\Models\Ticket::query()->whereStatus(0)->count()}}</span>
+							<span class="badge badge-pill badge-success">{{\App\Models\Ticket::query()->whereStatus(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">
+					<li class="site-menu-item {{in_array(Request::path(), ['ticket/list', 'ticket/add','ticket/reply']) ? 'active open' : ''}}">
+						<a href="/ticket/list" class="animsition-link">
 							<span class="site-menu-title">服务工单</span>
 							@if(\App\Models\Ticket::query()->whereStatus(0)->count() > 0 )
 								<div class="site-menu-label">
-									<span
-											class="badge badge-danger badge-round mr-25">{{\App\Models\Ticket::query()->whereStatus(0)->count()}}</span>
+									<span class="badge badge-danger badge-round mr-25">{{\App\Models\Ticket::query()->whereStatus(0)->count()}}</span>
 								</div>
 							@endif
 						</a>
@@ -170,72 +168,72 @@
 							<span class="site-menu-title">文章管理</span>
 						</a>
 					</li>
-					<li class="site-menu-item {{in_array(Request::path(), ['marketing/pushList']) ? 'active open' : ''}}">
-						<a href="/marketing/pushList" class="animsition-link">
+					<li class="site-menu-item {{in_array(Request::path(), ['marketing/push']) ? 'active open' : ''}}">
+						<a href="/marketing/push" class="animsition-link">
 							<span class="site-menu-title">消息推送</span>
 						</a>
 					</li>
-					<li class="site-menu-item {{in_array(Request::path(), ['marketing/emailList']) ? 'active open' : ''}}">
-						<a href="/marketing/emailList" class="animsition-link">
+					<li class="site-menu-item {{in_array(Request::path(), ['marketing/email']) ? 'active open' : ''}}">
+						<a href="/marketing/email" class="animsition-link">
 							<span class="site-menu-title">邮件群发</span>
 						</a>
 					</li>
 				</ul>
 			</li>
-			<li class="site-menu-item has-sub {{in_array(Request::path(), ['admin/nodeList', 'admin/addNode', 'admin/editNode', 'admin/nodeMonitor', 'admin/nodePingLog']) ? 'active open' : ''}}">
+			<li class="site-menu-item has-sub {{in_array(Request::path(), ['node/list', 'node/add', 'node/edit', 'node/monitor', 'node/pingLog']) ? '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>
 				</a>
 				<ul class="site-menu-sub">
-					<li class="site-menu-item {{in_array(Request::path(), ['admin/nodeList', 'admin/addNode', 'admin/editNode', 'admin/nodeMonitor']) ? 'active open' : ''}}">
-						<a href="/admin/nodeList" class="animsition-link">
+					<li class="site-menu-item {{in_array(Request::path(), ['node/list', 'node/add', 'node/edit', 'node/monitor']) ? 'active open' : ''}}">
+						<a href="/node/list" class="animsition-link">
 							<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">
+					<li class="site-menu-item {{in_array(Request::path(), ['node/pingLog']) ? 'active open' : ''}}">
+						<a href="/node/pingLog">
 							<span class="site-menu-title">测速日志</span>
 						</a>
 					</li>
 				</ul>
 			</li>
-			<li class="site-menu-item has-sub {{in_array(Request::path(), ['rule/ruleList', 'rule/addRule', 'rule/editRule', 'rule/ruleGroupList', 'rule/addRuleGroup', 'rule/editRuleGroup', 'rule/assignNode', 'rule/ruleLogList']) ? 'active open' : ''}}">
+			<li class="site-menu-item has-sub {{in_array(Request::path(), ['rule/list', 'rule/add', 'rule/edit', 'rule/group/list', 'rule/group/add', 'rule/group/edit', 'rule/group/assign', 'rule/log']) ? 'active open' : ''}}">
 				<a href="javascript:void(0)">
 					<i class="site-menu-icon wb-eye" aria-hidden="true"></i>
 					<span class="site-menu-title">审计规则</span>
 				</a>
 				<ul class="site-menu-sub">
-					<li class="site-menu-item {{in_array(Request::path(), ['rule/ruleList', 'rule/addRule', 'rule/editRule']) ? 'active open' : ''}}">
-						<a href="/rule/ruleList" class="animsition-link">
+					<li class="site-menu-item {{in_array(Request::path(), ['rule/list', 'rule/add', 'rule/edit']) ? 'active open' : ''}}">
+						<a href="/rule/list" class="animsition-link">
 							<span class="site-menu-title">规则列表</span>
 						</a>
 					</li>
-					<li class="site-menu-item {{in_array(Request::path(), ['rule/ruleGroupList', 'rule/addRuleGroup', 'rule/editRuleGroup', 'rule/assignNode']) ? 'active open' : ''}}">
-						<a href="/rule/ruleGroupList">
+					<li class="site-menu-item {{in_array(Request::path(), ['rule/group/list', 'rule/group/add', 'rule/group/edit', 'rule/group/assign']) ? 'active open' : ''}}">
+						<a href="/rule/group/list">
 							<span class="site-menu-title">规则分组</span>
 						</a>
 					</li>
-					<li class="site-menu-item {{in_array(Request::path(), ['rule/ruleLogList']) ? 'active open' : ''}}">
-						<a href="/rule/ruleLogList">
+					<li class="site-menu-item {{in_array(Request::path(), ['rule/log']) ? 'active open' : ''}}">
+						<a href="/rule/log">
 							<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' : ''}}">
+			<li class="site-menu-item has-sub {{in_array(Request::path(), ['shop/list', 'shop/add', 'shop/edit', 'coupon/list', 'coupon/add','admin/orderList']) ? 'active open' : ''}}">
 				<a href="javascript:void(0)">
 					<i class="site-menu-icon wb-shopping-cart" aria-hidden="true"></i>
 					<span class="site-menu-title">商品系统</span>
 				</a>
 				<ul class="site-menu-sub">
-					<li class="site-menu-item {{in_array(Request::path(), ['shop/goodsList', 'shop/addGoods', 'shop/editGoods']) ? 'active open' : ''}}">
-						<a href="/shop/goodsList" class="animsition-link">
+					<li class="site-menu-item {{in_array(Request::path(), ['shop/list', 'shop/add', 'shop/edit']) ? 'active open' : ''}}">
+						<a href="/shop/list" class="animsition-link">
 							<span class="site-menu-title">商品管理</span>
 						</a>
 					</li>
-					<li class="site-menu-item {{in_array(Request::path(), ['coupon/couponList', 'coupon/addCoupon']) ? 'active open' : ''}}">
-						<a href="/coupon/couponList" class="animsition-link">
+					<li class="site-menu-item {{in_array(Request::path(), ['coupon/list', 'coupon/add']) ? 'active open' : ''}}">
+						<a href="/coupon/list" class="animsition-link">
 							<span class="site-menu-title">卡券管理</span>
 						</a>
 					</li>

+ 2 - 2
resources/views/admin/logs/nodePingLog.blade.php

@@ -21,7 +21,7 @@
 					</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>
+						<a href="/node/pingLog" class="btn btn-danger">重 置</a>
 					</div>
 				</div>
 				<table class="text-md-center" data-toggle="table" data-mobile-responsive="true">
@@ -74,7 +74,7 @@
 	<script type="text/javascript">
 		// 搜索
 		function Search() {
-			window.location.href = '/admin/nodePingLog?&nodeId=' + $("#nodeId option:selected").val();
+			window.location.href = '/node/pingLog?&nodeId=' + $("#nodeId option:selected").val();
 		}
 	</script>
 @endsection

+ 2 - 2
resources/views/admin/marketing/emailList.blade.php

@@ -23,7 +23,7 @@
 					</div>
 					<div class="form-group col-lg-3 col-sm-6 btn-group">
 						<button class="btn btn-primary" onclick="Search()">搜 索</button>
-						<a href="/marketing/emailList" class="btn btn-danger">重 置</a>
+						<a href="/marketing/email" class="btn btn-danger">重 置</a>
 					</div>
 				</div>
 				<table class="text-md-center" data-toggle="table" data-mobile-responsive="true">
@@ -81,7 +81,7 @@
 		}
 
 		function Search() {
-			window.location.href = "/marketing/emailList?status=" + $("#status option:selected").val();
+			window.location.href = "/marketing/email?status=" + $("#status option:selected").val();
 		}
 	</script>
 @endsection

+ 3 - 3
resources/views/admin/marketing/pushList.blade.php

@@ -27,7 +27,7 @@
 					</div>
 					<div class="form-group col-lg-2 col-sm-6 btn-group">
 						<button class="btn btn-primary" onclick="Search()">搜 索</button>
-						<a href="/marketing/pushList" class="btn btn-danger">重 置</a>
+						<a href="/marketing/push" class="btn btn-danger">重 置</a>
 					</div>
 				</div>
 				<div class="alert alert-info alert-dismissible" role="alert">
@@ -141,7 +141,7 @@
 			}
 
 			$.ajax({
-				url: '/marketing/addPushMarketing',
+				url: '/marketing/add',
 				type: "POST",
 				data: {_token: '{{csrf_token()}}', title: title, content: $("#content").val()},
 				beforeSend: function () {
@@ -170,7 +170,7 @@
 		});
 
 		function Search() {
-			window.location.href = "/marketing/pushList?status=" + $("#status").val();
+			window.location.href = "/marketing/push?status=" + $("#status").val();
 		}
 	</script>
 @endsection

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

@@ -22,7 +22,7 @@
 				<strong>注意:</strong> 添加节点后自动生成的<code>ID</code>,即为该节点部署ShadowsocksR Python版后端时<code>usermysql.json</code>中的<code>node_id</code>的值,同时也是部署V2Ray后端时的<code>nodeId</code>的值;
 			</div>
 			<div class="panel-body">
-				<form action=@isset($node){{url('/admin/editNode')}} @else {{url('/admin/addNode')}} @endisset method="post" enctype="multipart/form-data" class="form-horizontal" onsubmit="return Submit()">
+				<form action=@isset($node){{url('/node/edit')}} @else {{url('/node/add')}} @endisset method="post" enctype="multipart/form-data" class="form-horizontal" onsubmit="return Submit()">
 					<div class="row">
 						<div class="col-lg-6">
 							<div class="example-wrap">
@@ -473,7 +473,7 @@
 		function Submit() {
 			$.ajax({
 				type: "POST",
-				url: @isset($node) "/admin/editNode" @else "/admin/addNode" @endisset,
+				url: @isset($node) "/node/edit" @else "/node/add" @endisset,
 				async: false,
 				data: {
 					_token: '{{csrf_token()}}',
@@ -524,7 +524,7 @@
 				success: function (ret) {
 					if (ret.status === 'success') {
 						swal.fire({title: ret.message, type: 'success', timer: 1000, showConfirmButton: false})
-							.then(() => window.location.href = '/admin/nodeList')
+							.then(() => window.location.href = '/node/list')
 					} else {
 						swal.fire({
 							title: '[错误 | Error]',

+ 6 - 6
resources/views/admin/node/nodeList.blade.php

@@ -13,7 +13,7 @@
 			<div class="panel-heading">
 				<h3 class="panel-title">节点列表</h3>
 				<div class="panel-actions">
-					<a href="/admin/addNode" class="btn btn-primary"><i class="icon wb-plus"></i> 添加节点</a>
+					<a href="/node/add" class="btn btn-primary"><i class="icon wb-plus"></i> 添加节点</a>
 				</div>
 			</div>
 			<div class="panel-body">
@@ -67,11 +67,11 @@
 												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)}}"
+									<a href="/node/edit?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
+									<a href="/node/monitor/{{$node->id}}" class="btn btn-primary"><i
 												class="icon wb-stats-bars"></i></a>
 								</div>
 							</td>
@@ -104,7 +104,7 @@
 		function testNode(id) {
 			$.ajax({
 				type: "POST",
-				url: '/admin/nodeList',
+				url: '/node/list',
 				data: {_token: '{{csrf_token()}}', id: id},
 				beforeSend: function () {
 					$("#node" + id).removeClass("wb-signal").addClass("wb-loop icon-spin");
@@ -131,7 +131,7 @@
 		function pingNode(id) {
 			$.ajax({
 				type: "POST",
-				url: '/admin/pingNode',
+				url: '/node/ping',
 				data: {_token: '{{csrf_token()}}', id: id},
 				beforeSend: function () {
 					$("#ping" + id).removeClass("wb-order").addClass("wb-loop icon-spin");
@@ -164,7 +164,7 @@
 				confirmButtonText: '{{trans('home.ticket_confirm')}}',
 			}).then((result) => {
 				if (result.value) {
-					$.post("/admin/delNode", {id: id, _token: '{{csrf_token()}}'}, function (ret) {
+					$.post("/node/delete", {id: id, _token: '{{csrf_token()}}'}, function (ret) {
 						if (ret.status === 'success') {
 							swal.fire({title: ret.message, type: 'success', timer: 1000, showConfirmButton: false})
 								.then(() => window.location.reload())

+ 1 - 1
resources/views/admin/rule/assignNode.blade.php

@@ -27,7 +27,7 @@
 				</div>
 			@endif
 			<div class="panel-body">
-				<form action={{url('/rule/assignNode')}} method="post" enctype="multipart/form-data" class="form-horizontal">
+				<form action={{url('/rule/group/assign')}} method="post" enctype="multipart/form-data" class="form-horizontal">
 					<input name="id" value="{{$ruleGroup->id}}" required hidden/>
 					@csrf
 					<div class="form-group row">

+ 2 - 2
resources/views/admin/rule/ruleGroupInfo.blade.php

@@ -8,7 +8,7 @@
 			<div class="panel-heading">
 				<h2 class="panel-title">@isset($ruleGroup)编辑@else添加@endisset规则分组</h2>
 				<div class="panel-actions">
-					<a href="/rule/ruleGroupList" class="btn btn-danger">返 回</a>
+					<a href="/rule/group/list" class="btn btn-danger">返 回</a>
 				</div>
 			</div>
 			@if (Session::has('successMsg'))
@@ -30,7 +30,7 @@
 				</div>
 			@endif
 			<div class="panel-body">
-				<form action=@isset($ruleGroup){{url('/rule/editRuleGroup')}}@else{{url('/rule/addRuleGroup')}}@endisset method="post" enctype="multipart/form-data" class="form-horizontal">
+				<form action=@isset($ruleGroup){{url('/rule/group/edit')}}@else{{url('/rule/group/add')}}@endisset method="post" enctype="multipart/form-data" class="form-horizontal">
 					@isset($ruleGroup)<input name="id" value="{{$ruleGroup->id}}" hidden/>@endisset
 					@csrf
 					<div class="form-group row">

+ 4 - 4
resources/views/admin/rule/ruleGroupList.blade.php

@@ -8,7 +8,7 @@
 			<div class="panel-heading">
 				<h2 class="panel-title">规则分组</h2>
 				<div class="panel-actions">
-					<a href="/rule/addRuleGroup" class="btn btn-outline-primary">
+					<a href="/rule/group/add" class="btn btn-outline-primary">
 						<i class="icon wb-plus" aria-hidden="true"></i>添加分组
 					</a>
 				</div>
@@ -31,10 +31,10 @@
 							<td> {!! $ruleGroup->type_label !!} </td>
 							<td>
 								<div class="btn-group">
-									<a href="/rule/assignNode?id={{$ruleGroup->id}}" class="btn btn-sm btn-outline-primary">
+									<a href="/rule/group/assign?id={{$ruleGroup->id}}" class="btn btn-sm btn-outline-primary">
 										<i class="icon wb-plus" aria-hidden="true"></i>分配节点
 									</a>
-									<a href="/rule/editRuleGroup?id={{$ruleGroup->id}}" class="btn btn-sm btn-outline-primary">
+									<a href="/rule/group/edit?id={{$ruleGroup->id}}" class="btn btn-sm btn-outline-primary">
 										<i class="icon wb-edit"></i>编辑
 									</a>
 									<button onclick="delRuleGroup('{{$ruleGroup->id}}', '{{$ruleGroup->name}}')" class="btn btn-sm btn-outline-danger">
@@ -77,7 +77,7 @@
 				confirmButtonText: '{{trans('home.ticket_confirm')}}',
 			}).then((result) => {
 				if (result.value) {
-					$.post("/rule/delRuleGroup/" + id, {_token: '{{csrf_token()}}'}, function (ret) {
+					$.post("/rule/group/delete/" + id, {_token: '{{csrf_token()}}'}, function (ret) {
 						if (ret.status === 'success') {
 							swal.fire({title: ret.message, type: 'success', timer: 1000, showConfirmButton: false})
 								.then(() => window.location.reload())

+ 5 - 5
resources/views/admin/rule/ruleList.blade.php

@@ -26,7 +26,7 @@
 						</select>
 					</div>
 					<div class="form-group col-xxl-1 col-lg-3 col-md-3 col-4">
-						<a href="/rule/ruleList" class="btn btn-danger">重 置</a>
+						<a href="/rule/list" class="btn btn-danger">重 置</a>
 					</div>
 				</div>
 				<table class="text-md-center" data-toggle="table" data-mobile-responsive="true">
@@ -133,7 +133,7 @@
 	<script type="text/javascript">
 		// 添加规则
 		function addRule() {
-			$.post("/rule/addRule", {
+			$.post("/rule/add", {
 				_token: '{{csrf_token()}}',
 				type: $("#add_type").val(),
 				name: $("#name").val(),
@@ -150,7 +150,7 @@
 
 		// 编辑规则
 		function editRule(id) {
-			$.post("/rule/editRule", {
+			$.post("/rule/edit", {
 				_token: '{{csrf_token()}}',
 				id: id,
 				rule_name: $('#rule_name_' + id).val(),
@@ -176,7 +176,7 @@
 				confirmButtonText: '{{trans('home.ticket_confirm')}}',
 			}).then((result) => {
 				if (result.value) {
-					$.post("/rule/delRule/" + id, {_token: '{{csrf_token()}}'}, function (ret) {
+					$.post("/rule/delete/" + id, {_token: '{{csrf_token()}}'}, function (ret) {
 						if (ret.status === 'success') {
 							swal.fire({title: ret.message, type: 'success', timer: 1000, showConfirmButton: false})
 								.then(() => window.location.reload())
@@ -198,7 +198,7 @@
 
 		// 搜索
 		function Search() {
-			window.location.href = '/rule/ruleList?type=' + $("#type").val();
+			window.location.href = '/rule/list?type=' + $("#type").val();
 		}
 	</script>
 @endsection

+ 3 - 3
resources/views/admin/rule/ruleLogList.blade.php

@@ -40,7 +40,7 @@
 					</div>
 					<div class="form-group col-xxl-1 col-lg-3 col-md-3 col-4 btn-group">
 						<button class="btn btn-primary" onclick="Search()">搜 索</button>
-						<a href="/rule/ruleLogList" class="btn btn-danger">重 置</a>
+						<a href="/rule/log" class="btn btn-danger">重 置</a>
 					</div>
 				</div>
 				<table class="text-md-center" data-toggle="table" data-mobile-responsive="true">
@@ -91,7 +91,7 @@
 	<script type="text/javascript">
 		// 搜索
 		function Search() {
-			window.location.href = '/rule/ruleLogList?uid=' + $("#uid").val() + '&username=' + $("#username").val() + '&node_id=' + $("#node_id option:selected").val() + '&rule_id=' + $("#rule_id option:selected").val();
+			window.location.href = '/rule/log?uid=' + $("#uid").val() + '&username=' + $("#username").val() + '&node_id=' + $("#node_id option:selected").val() + '&rule_id=' + $("#rule_id option:selected").val();
 		}
 
 		// 清除所有记录
@@ -105,7 +105,7 @@
 				confirmButtonText: '{{trans('home.ticket_confirm')}}',
 			}).then((result) => {
 				if (result.value) {
-					$.post("/rule/clearLog", {_token: '{{csrf_token()}}'}, function (ret) {
+					$.post("/rule/clear", {_token: '{{csrf_token()}}'}, function (ret) {
 						if (ret.status === 'success') {
 							swal.fire({title: ret.message, type: 'success', timer: 1000, showConfirmButton: false})
 								.then(() => window.location.reload())

+ 0 - 78
resources/views/admin/sensitiveWords/addSensitiveWords.blade.php

@@ -1,78 +0,0 @@
-@extends('admin.layouts')
-@section('content')
-	<div class="page-content container">
-		<div class="panel">
-			<div class="panel-heading">
-				<h2 class="panel-title">添加敏感词</h2>
-			</div>
-			@if (Session::has('errorMsg'))
-				<div class="alert alert-danger">
-					<button class="close" data-dismiss="alert" aria-label="Close"><span
-								aria-hidden="true">&times;</span><span class="sr-only">{{trans('home.close')}}</span>
-					</button>
-					<strong>错误:</strong> {{Session::get('errorMsg')}}
-				</div>
-			@endif
-			<div class="panel-body">
-				<form action="#" method="post" enctype="multipart/form-data" class="form-horizontal" role="form"
-						onsubmit="return Submit()">
-					<div class="form-group row">
-						<label class="col-form-label col-md-2">敏感词</label>
-						<div class="col-md-5">
-							<input type="text" class="form-control" name="words" id="words" required/>
-						</div>
-					</div>
-					<div class="form-actions">
-						<button type="submit" class="btn btn-success">提 交</button>
-					</div>
-				</form>
-			</div>
-		</div>
-	</div>
-
-	<div id="charge_modal" class="modal fade" aria-labelledby="charge_modal" role="dialog" tabindex="-1"
-			aria-hidden="true">
-		<div class="modal-dialog modal-simple modal-center">
-			<div class="modal-content">
-				<div class="modal-header">
-					<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
-								aria-hidden="true">×</span></button>
-					<h4 class="modal-title"> {{trans('home.ticket_table_new_button')}} </h4>
-				</div>
-				<div class="modal-body">
-					<input type="text" name="title" id="title" placeholder="{{trans('home.ticket_table_title')}}"
-							class="form-control mb-20"/>
-					<textarea name="content" id="content" placeholder="{{trans('home.ticket_table_new_desc')}}"
-							class="form-control mb-20" rows="4"></textarea>
-				</div>
-				<div class="modal-footer">
-					<button data-dismiss="modal"
-							class="btn btn-danger"> {{trans('home.ticket_table_new_cancel')}} </button>
-					<button class="btn btn-primary"
-							onclick="addTicket()"> {{trans('home.ticket_table_new_yes')}} </button>
-				</div>
-			</div>
-		</div>
-	</div>
-@endsection
-@section('script')
-	<script type="text/javascript">
-		// ajax同步提交
-		function Submit() {
-			$.ajax({
-				type: "POST",
-				url: "/admin/addSensitiveWords",
-				async: false,
-				data: {_token: '{{csrf_token()}}', words: $('#words').val()},
-				dataType: 'json',
-				success: function (ret) {
-					swal.fire({title: ret.message, timer: 1000, showConfirmButton: false,})
-						.then(() => {
-							window.location.href = '/admin/sensitiveWordsList';
-						})
-				}
-			});
-			return false;
-		}
-	</script>
-@endsection

+ 2 - 2
resources/views/admin/shop/goodsInfo.blade.php

@@ -19,7 +19,7 @@
 					@isset($goods) 编辑商品 @else 添加商品 @endisset
 				</h1>
 				<div class="panel-actions">
-					<a href="{{url('/shop/goodsList')}}" class="btn btn-danger">返 回</a>
+					<a href="{{url('/shop/list')}}" class="btn btn-danger">返 回</a>
 				</div>
 			</div>
 			@if (Session::has('successMsg'))
@@ -39,7 +39,7 @@
 				</div>
 			@endif
 			<div class="panel-body">
-				<form action=@isset($goods){{url('/shop/editGoods/'.$goods->id)}} @else {{url('/shop/addGoods')}} @endisset"" method="post" enctype="multipart/form-data" class="form-horizontal" role="form">
+				<form action=@isset($goods){{url('/shop/edit/'.$goods->id)}} @else {{url('/shop/add')}} @endisset"" method="post" enctype="multipart/form-data" class="form-horizontal" role="form">
 					{{csrf_field()}}
 					<label>
 						<input name="id" hidden/>

+ 5 - 5
resources/views/admin/shop/goodsList.blade.php

@@ -8,7 +8,7 @@
 			<div class="panel-heading">
 				<h1 class="panel-title"><i class="icon wb-shopping-cart" aria-hidden="true"></i>商品列表</h1>
 				<div class="panel-actions">
-					<a href="/shop/addGoods" class="btn btn-primary"><i class="icon wb-plus"></i>添加商品</a>
+					<a href="/shop/add" class="btn btn-primary"><i class="icon wb-plus"></i>添加商品</a>
 				</div>
 			</div>
 			<div class="panel-body">
@@ -29,7 +29,7 @@
 					</div>
 					<div class="form-group col-lg-2 col-sm-4 btn-group">
 						<button class="btn btn-primary" onclick="Search()">搜 索</button>
-						<a href="/shop/goodsList" class="btn btn-danger">重 置</a>
+						<a href="/shop/list" class="btn btn-danger">重 置</a>
 					</div>
 				</div>
 				<table class="text-md-center" data-toggle="table" data-mobile-responsive="true">
@@ -90,7 +90,7 @@
 							</td>
 							<td>
 								<div class="btn-group">
-									<a href="/shop/editGoods/{{$goods->id}}" class="btn btn-primary"><i
+									<a href="/shop/edit/{{$goods->id}}" class="btn btn-primary"><i
 												class="icon wb-edit"></i></a>
 									<button class="btn btn-danger"
 											onclick="delGoods('{{$goods->id}}','{{$goods->name}}')"><i
@@ -129,7 +129,7 @@
 
 		// 搜索
 		function Search() {
-			window.location.href = '/shop/goodsList?type=' + $("#type option:selected").val() + '&status=' + $("#status option:selected").val();
+			window.location.href = '/shop/list?type=' + $("#type option:selected").val() + '&status=' + $("#status option:selected").val();
 		}
 
 		// 删除商品
@@ -143,7 +143,7 @@
 				confirmButtonText: '确定',
 			}).then((result) => {
 				if (result.value) {
-					$.post("/shop/delGoods", {id: id, _token: '{{csrf_token()}}'}, function (ret) {
+					$.post("/shop/delete", {id: id, _token: '{{csrf_token()}}'}, function (ret) {
 						swal.fire({title: ret.message, type: 'success', timer: 1000, showConfirmButton: false,})
 							.then(() => {
 								window.location.reload();

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

@@ -27,7 +27,7 @@
 					</div>
 					<div class="form-group col-lg-2 col-sm-6 btn-group">
 						<button class="btn btn-primary" onclick="Search()">搜 索</button>
-						<a href="/subscribe/subscribeList" class="btn btn-danger">重 置</a>
+						<a href="/subscribe/list" class="btn btn-danger">重 置</a>
 					</div>
 				</div>
 				<table class="text-md-center" data-toggle="table" data-mobile-responsive="true">
@@ -57,7 +57,7 @@
 							</td>
 							<td> {{$subscribe->code}} </td>
 							<td>
-								<a href="/subscribe/subscribeLog?id={{$subscribe->id}}"
+								<a href="/subscribe/log?id={{$subscribe->id}}"
 										target="_blank">{{$subscribe->times}}</a>
 							</td>
 							<td> {{$subscribe->updated_at}} </td>
@@ -114,12 +114,12 @@
 
 		// 搜索
 		function Search() {
-			window.location.href = '/subscribe/subscribeList' + '?user_id=' + $("#user_id").val() + '&email=' + $("#email").val() + '&status=' + $("#status option:selected").val();
+			window.location.href = '/subscribe/list' + '?user_id=' + $("#user_id").val() + '&email=' + $("#email").val() + '&status=' + $("#status option:selected").val();
 		}
 
 		// 启用禁用用户的订阅
 		function setSubscribeStatus(id, status) {
-			$.post("/subscribe/setSubscribeStatus", {
+			$.post("/subscribe/set", {
 				_token: '{{csrf_token()}}',
 				id: id,
 				status: status

+ 3 - 3
resources/views/admin/ticket/addTicket.blade.php

@@ -14,7 +14,7 @@
 				<h1 class="panel-title cyan-600"><i class="icon wb-add"></i>发起工单</h1>
 			</div>
 			<div class="panel-body">
-				<form action="/ticket/addTicket" method="post" enctype="multipart/form-data" class="form-horizontal"
+				<form action="/ticket/add" method="post" enctype="multipart/form-data" class="form-horizontal"
 						onsubmit="return Submit()">
 					<div class="form-body">
 						<div class="form-group">
@@ -57,7 +57,7 @@
 		function Submit() {
 			$.ajax({
 				type: "POST",
-				url: "/ticket/addTicket",
+				url: "/ticket/add",
 				async: false,
 				data: {
 					_token: '{{csrf_token()}}',
@@ -68,7 +68,7 @@
 				dataType: 'json',
 				success: function (ret) {
 					swal.fire({title: ret.message, type: 'success', timer: 1000})
-						.then(() => window.location.href = '/ticket/ticketList');
+						.then(() => window.location.href = '/ticket/list');
 				}
 			});
 			return false;

+ 4 - 4
resources/views/admin/ticket/replyTicket.blade.php

@@ -9,7 +9,7 @@
 				<h1 class="panel-title cyan-600"><i class="icon wb-help-circle"></i> {{$ticket->title}} </h1>
 				@if($ticket->status != 2)
 					<div class="panel-actions">
-						<a href="/ticket/ticketList" class="btn btn-default">返 回</a>
+						<a href="/ticket/list" class="btn btn-default">返 回</a>
 						<button class="btn btn-danger" onclick="closeTicket()"> {{trans('home.ticket_close')}} </button>
 					</div>
 				@endif
@@ -113,7 +113,7 @@
 				if (result.value) {
 					$.ajax({
 						type: "POST",
-						url: "/ticket/closeTicket",
+						url: "/ticket/close",
 						async: true,
 						data: {_token: '{{csrf_token()}}', id: '{{$ticket->id}}'},
 						dataType: 'json',
@@ -123,7 +123,7 @@
 								type: 'success',
 								timer: 1000,
 								showConfirmButton: false
-							}).then(() => window.location.href = '/ticket/ticketList')
+							}).then(() => window.location.href = '/ticket/list')
 						},
 						error: function () {
 							swal.fire("未知错误!请通知客服!")
@@ -150,7 +150,7 @@
 				confirmButtonText: '{{trans('home.ticket_confirm')}}',
 			}).then((result) => {
 				if (result.value) {
-					$.post("/ticket/replyTicket", {
+					$.post("/ticket/reply", {
 						_token: '{{csrf_token()}}',
 						id: '{{$ticket->id}}',
 						content: content

+ 4 - 4
resources/views/admin/ticket/ticketList.blade.php

@@ -8,7 +8,7 @@
 			<div class="panel-heading">
 				<h3 class="panel-title">工单列表</h3>
 				<div class="panel-actions">
-					<a href="/ticket/addTicket" class="btn btn-primary btn-animate btn-animate-side">
+					<a href="/ticket/add" class="btn btn-primary btn-animate btn-animate-side">
 						<span><i class="icon wb-plus" aria-hidden="true"></i> {{trans('home.ticket_table_new_button')}}
 						</span>
 					</a>
@@ -22,7 +22,7 @@
 					</div>
 					<div class="form-group col-lg-2 col-sm-6 btn-group">
 						<button class="btn btn-primary" onclick="Search()">搜 索</button>
-						<a href="/ticket/ticketList" class="btn btn-danger">重 置</a>
+						<a href="/ticket/list" class="btn btn-danger">重 置</a>
 					</div>
 				</div>
 				<table class="text-md-center" data-toggle="table" data-mobile-responsive="true">
@@ -48,7 +48,7 @@
 							</td>
 
 							<td>
-								<a href="/ticket/replyTicket?id={{$ticket->id}}" target="_blank">{{$ticket->title}}</a>
+								<a href="/ticket/reply?id={{$ticket->id}}" target="_blank">{{$ticket->title}}</a>
 							</td>
 							<td>
 								{!!$ticket->status_label!!}
@@ -88,7 +88,7 @@
 
 		// 搜索
 		function Search() {
-			window.location.href = '/ticket/ticketList?email=' + $("#email").val();
+			window.location.href = '/ticket/list?email=' + $("#email").val();
 		}
 	</script>
 @endsection

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

@@ -26,7 +26,7 @@
 						<tr>
 							<td>{{$loop->iteration}}</td>
 							<td>
-								<a href="/admin/editNode?id={{$node->id}}" target="_blank"> {{$node->name}} </a>
+								<a href="/node/edit?id={{$node->id}}" target="_blank"> {{$node->name}} </a>
 							</td>
 							<td>
 								@if($node->compatible) <span class="label label-info">兼</span> @endif

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

@@ -132,7 +132,7 @@
 					<button type="button" data-dismiss="modal"
 							class="btn btn-danger"> {{trans('home.ticket_cancel')}} </button>
 					<button type="button" data-dismiss="modal" class="btn btn-success"
-							onclick="addTicket()"> {{trans('home.ticket_confirm')}} </button>
+							onclick="createTicket()"> {{trans('home.ticket_confirm')}} </button>
 				</div>
 			</div>
 		</div>
@@ -141,7 +141,7 @@
 @section('script')
 	<script type="text/javascript">
 		// 发起工单
-		function addTicket() {
+		function createTicket() {
 			const title = $('#title').val();
 			const content = $('#content').val();
 
@@ -163,7 +163,7 @@
 				confirmButtonText: '{{trans('home.ticket_confirm')}}',
 			}).then((result) => {
 				if (result.value) {
-					$.post("/addTicket", {
+					$.post("/createTicket", {
 						_token: '{{csrf_token()}}',
 						title: title,
 						content: content

+ 42 - 36
routes/web.php

@@ -28,13 +28,6 @@ Route::group(['middleware' => ['isForbidden', 'isAdminLogin', 'isAdmin']], funct
 		Route::post('delUser', 'AdminController@delUser'); // 删除账号
 		Route::post('batchAddUsers', 'AdminController@batchAddUsers'); // 批量生成账号
 		Route::get('exportSSJson', 'AdminController@exportSSJson'); // 导出原版SS的json配置信息
-		Route::any('nodeList', 'AdminController@nodeList'); // 节点列表
-		Route::any('addNode', 'AdminController@addNode'); // 添加节点
-		Route::any('editNode', 'AdminController@editNode'); // 编辑节点
-		Route::post('delNode', 'AdminController@delNode'); // 删除节点
-		Route::get('nodeMonitor/{id}', 'AdminController@nodeMonitor'); // 节点流量监控
-		Route::post('pingNode', 'AdminController@pingNode'); // 节点ping测速
-		Route::get('nodePingLog', 'AdminController@nodePingLog'); //节点Ping测速日志
 		Route::get('articleList', 'AdminController@articleList'); // 文章列表
 		Route::any('addArticle', 'AdminController@addArticle'); // 添加文章
 		Route::any('editArticle', 'AdminController@editArticle'); // 编辑文章
@@ -83,38 +76,49 @@ Route::group(['middleware' => ['isForbidden', 'isAdminLogin', 'isAdmin']], funct
 			Route::get('userRebateList', 'AffiliateController@userRebateList'); // 返利流水记录
 		});
 	});
+	Route::group(['prefix' => 'node'], function() {
+		Route::any('list', 'NodeController@nodeList'); // 节点列表
+		Route::any('add', 'NodeController@addNode'); // 添加节点
+		Route::any('edit', 'NodeController@editNode'); // 编辑节点
+		Route::post('delete', 'NodeController@delNode'); // 删除节点
+		Route::get('monitor/{id}', 'NodeController@nodeMonitor'); // 节点流量监控
+		Route::post('ping', 'NodeController@pingNode'); // 节点ping测速
+		Route::get('pingLog', 'NodeController@pingLog'); //节点Ping测速日志
+	});
 
 	Route::group(['namespace' => 'Admin'], function() {
 		Route::group(['prefix' => 'ticket'], function() {
-			Route::get('ticketList', 'TicketController@ticketList'); // 工单列表
-			Route::any('replyTicket', 'TicketController@replyTicket'); // 回复工单
-			Route::post('closeTicket', 'TicketController@closeTicket'); // 关闭工单
+			Route::get('list', 'TicketController@ticketList'); // 工单列表
+			// Todo: 创建工单
+			// Route::post('create', 'TicketController@createTicket'); // 创建工单
+			Route::post('close', 'TicketController@closeTicket'); // 关闭工单
+			Route::any('reply', 'TicketController@replyTicket'); // 回复工单
 		});
 
 		Route::group(['prefix' => 'coupon'], function() {
-			Route::any('couponList', 'CouponController@couponList'); // 优惠券列表
-			Route::any('addCoupon', 'CouponController@addCoupon'); // 添加优惠券
-			Route::post('delCoupon', 'CouponController@delCoupon'); // 删除优惠券
-			Route::get('exportCoupon', 'CouponController@exportCoupon'); // 导出优惠券
+			Route::any('list', 'CouponController@couponList'); // 优惠券列表
+			Route::any('add', 'CouponController@addCoupon'); // 添加优惠券
+			Route::post('delete', 'CouponController@delCoupon'); // 删除优惠券
+			Route::get('export', 'CouponController@exportCoupon'); // 导出优惠券
 		});
 
 		Route::group(['prefix' => 'shop'], function() {
-			Route::any('goodsList', 'ShopController@goodsList'); // 商品列表
-			Route::any('addGoods', 'ShopController@addGoods'); // 添加商品
-			Route::any('editGoods/{id}', 'ShopController@editGoods'); // 编辑商品
-			Route::post('delGoods', 'ShopController@delGoods'); // 删除商品
+			Route::any('list', 'ShopController@goodsList'); // 商品列表
+			Route::any('add', 'ShopController@addGoods'); // 添加商品
+			Route::any('edit/{id}', 'ShopController@editGoods'); // 编辑商品
+			Route::post('delete', 'ShopController@delGoods'); // 删除商品
 		});
 
 		Route::group(['prefix' => 'subscribe'], function() {
-			Route::get('subscribeList', 'SubscribeController@subscribeList'); // 订阅码列表
-			Route::get('subscribeLog', 'SubscribeController@subscribeLog'); // 订阅码记录
-			Route::post('setSubscribeStatus', 'SubscribeController@setSubscribeStatus'); // 启用禁用用户的订阅
+			Route::get('list', 'SubscribeController@subscribeList'); // 订阅码列表
+			Route::get('log', 'SubscribeController@subscribeLog'); // 订阅码记录
+			Route::post('set', 'SubscribeController@setSubscribeStatus'); // 启用禁用用户的订阅
 		});
 
 		Route::group(['prefix' => 'marketing'], function() {
-			Route::get("emailList", "MarketingController@emailList"); // 邮件消息列表
-			Route::get("pushList", "MarketingController@pushList"); // 推送消息列表
-			Route::post("addPushMarketing", "MarketingController@addPushMarketing"); // 推送消息
+			Route::get("email", "MarketingController@emailList"); // 邮件消息列表
+			Route::get("push", "MarketingController@pushList"); // 推送消息列表
+			Route::post("add", "MarketingController@addPushMarketing"); // 推送消息
 		});
 
 		Route::group(['prefix' => 'sensitiveWords'], function() {
@@ -134,17 +138,19 @@ Route::group(['middleware' => ['isForbidden', 'isAdminLogin', 'isAdmin']], funct
 
 		// 节点审计规则相关
 		Route::group(['prefix' => 'rule'], function() {
-			Route::get('ruleList', 'RuleController@ruleList'); // 审计规则列表
-			Route::post('addRule', 'RuleController@addRule'); // 添加审计规则
-			Route::post('editRule', 'RuleController@editRule'); // 删除审计规则
-			Route::post('delRule/{id}', 'RuleController@delRule'); // 删除审计规则
-			Route::get('ruleGroupList', 'RuleController@ruleGroupList'); // 审计规则分组列表
-			Route::any('addRuleGroup', 'RuleController@addRuleGroup'); // 添加审计规则分组
-			Route::any('editRuleGroup', 'RuleController@editRuleGroup'); // 编辑审计规则分组
-			Route::post('delRuleGroup/{id}', 'RuleController@delRuleGroup'); // 删除审计规则分组
-			Route::any('assignNode', 'RuleController@assignNode'); // 规则分组关联节点
-			Route::get('ruleLogList', 'RuleController@ruleLogList'); // 用户触发审计规则日志
-			Route::post('clearLog', 'RuleController@clearLog'); // 清除所有审计触发日志
+			Route::get('list', 'RuleController@ruleList'); // 审计规则列表
+			Route::post('add', 'RuleController@addRule'); // 添加审计规则
+			Route::post('edit', 'RuleController@editRule'); // 删除审计规则
+			Route::post('delete/{id}', 'RuleController@delRule'); // 删除审计规则
+			Route::group(['prefix' => 'group'], function() {
+				Route::get('list', 'RuleController@ruleGroupList'); // 审计规则分组列表
+				Route::any('add', 'RuleController@addRuleGroup'); // 添加审计规则分组
+				Route::any('edit', 'RuleController@editRuleGroup'); // 编辑审计规则分组
+				Route::post('delete/{id}', 'RuleController@delRuleGroup'); // 删除审计规则分组
+				Route::any('assign', 'RuleController@assignNode'); // 规则分组关联节点
+			});
+			Route::get('log', 'RuleController@ruleLogList'); // 用户触发审计规则日志
+			Route::post('clear', 'RuleController@clearLog'); // 清除所有审计触发日志
 		});
 	});
 
@@ -160,7 +166,7 @@ Route::group(['middleware' => ['isForbidden', 'isMaintenance', 'isLogin']], func
 	Route::post('checkIn', 'UserController@checkIn'); // 签到
 	Route::get('services', 'UserController@services'); // 商品列表
 	Route::get('tickets', 'UserController@ticketList'); // 工单
-	Route::post('addTicket', 'UserController@addTicket'); // 快速添加工单
+	Route::post('createTicket', 'UserController@createTicket'); // 快速添加工单
 	Route::any('replyTicket', 'UserController@replyTicket'); // 回复工单
 	Route::post('closeTicket', 'UserController@closeTicket'); // 关闭工单
 	Route::get('invoices', 'UserController@invoices'); // 订单列表