Parcourir la source

1.用户30日内的流量走势图
2.修改用户个人信息
3.用户首页

zhangjiangbin il y a 8 ans
Parent
commit
beb16f1194

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

@@ -1011,4 +1011,14 @@ TXT;
 
         return Response::json(['status' => 'success', 'data' => '', 'message' => '操作成功']);
     }
+
+    // 启用、禁用自定义端口
+    public function enableUserRandPort(Request $request)
+    {
+        $value = intval($request->get('value'));
+
+        Config::where('id', 2)->update(['value' => $value]);
+
+        return Response::json(['status' => 'success', 'data' => '', 'message' => '操作成功']);
+    }
 }

+ 128 - 20
app/Http/Controllers/UserController.php

@@ -2,6 +2,7 @@
 
 namespace App\Http\Controllers;
 
+use App\Http\Models\Article;
 use App\Http\Models\SsNode;
 use App\Http\Models\SsNodeInfo;
 use App\Http\Models\SsNodeOnlineLog;
@@ -15,7 +16,24 @@ class UserController extends BaseController
 {
     public function index(Request $request)
     {
-        return Response::view('user/index');
+        if (!$request->session()->has('user')) {
+            return Redirect::to('login');
+        }
+
+        $view['articleList'] = Article::orderBy('sort', 'desc')->orderBy('id', 'desc')->limit(5)->get();
+        $view['info'] = $request->session()->get('user');
+
+        return Response::view('user/index', $view);
+    }
+
+    // 公告详情
+    public function article(Request $request)
+    {
+        $id = $request->get('id');
+
+        $view['info'] = Article::where('id', $id)->first();
+
+        return Response::view('user/article', $view);
     }
 
     // 修改个人资料
@@ -30,29 +48,84 @@ class UserController extends BaseController
         if ($request->method() == 'POST') {
             $old_password = $request->get('old_password');
             $new_password = $request->get('new_password');
+            $port = trim($request->get('port'));
+            $passwd = trim($request->get('passwd'));
+            $method = $request->get('method');
+            $protocol = $request->get('protocol');
+            $obfs = $request->get('obfs');
+
+            // 修改密码
+            if (!empty($old_password) && !empty($new_password)) {
+                $old_password = md5(trim($old_password));
+                $new_password = md5(trim($new_password));
+
+                $user = User::where('id', $user['id'])->first();
+                if ($user->password != $old_password) {
+                    $request->session()->flash('errorMsg', '旧密码错误,请重新输入');
+
+                    return Redirect::to('user/profile#tab_1');
+                } else if ($user->password == $new_password) {
+                    $request->session()->flash('errorMsg', '新密码不可与旧密码一样,请重新输入');
+
+                    return Redirect::to('user/profile#tab_1');
+                }
+
+                $ret = User::where('id', $user['id'])->update(['password' => $new_password]);
+                if (!$ret) {
+                    $request->session()->flash('errorMsg', '修改失败');
+
+                    return Redirect::to('user/profile#tab_1');
+                } else {
+                    $request->session()->flash('successMsg', '修改成功');
+
+                    return Redirect::to('user/profile#tab_1');
+                }
+            }
 
-            $old_password = md5(trim($old_password));
-            $new_password = md5(trim($new_password));
+            // 修改SS信息
+            if (empty($port)) {
+                $request->session()->flash('errorMsg', '端口不能为空');
 
-            $user = User::where('id', $user['id'])->first();
-            if ($user->password != $old_password) {
-                $request->session()->flash('errorMsg', '旧密码错误,请重新输入');
-                return Redirect::back();
-            } else if ($user->password == $new_password) {
-                $request->session()->flash('errorMsg', '新密码不可与旧密码一样,请重新输入');
-                return Redirect::back();
+                return Redirect::to('user/profile#tab_2');
             }
 
-            $ret = User::where('id', $user['id'])->update(['password' => $new_password]);
+            if (empty($passwd)) {
+                $request->session()->flash('errorMsg', '密码不能为空');
+
+                return Redirect::to('user/profile#tab_2');
+            }
+
+            $data = [
+                //'port' => $port,
+                'passwd' => $passwd,
+                'method' => $method,
+                'protocol' => $protocol,
+                'obfs' => $obfs
+            ];
+
+            $ret = User::where('id', $user['id'])->update($data);
             if (!$ret) {
                 $request->session()->flash('errorMsg', '修改失败');
-                return Redirect::back();
+
+                return Redirect::to('user/profile#tab_2');
             } else {
+                // 更新session
+                $user = User::where('id', $user['id'])->first()->toArray();
+                $request->session()->remove('user');
+                $request->session()->put('user', $user);
+
                 $request->session()->flash('successMsg', '修改成功');
-                return Redirect::back();
+
+                return Redirect::to('user/profile#tab_2');
             }
         } else {
-            return Response::view('user/profile');
+            // 加密方式、协议、混淆
+            $view['method_list'] =  $this->methodList();
+            $view['protocol_list'] =  $this->protocolList();
+            $view['obfs_list'] =  $this->obfsList();
+            $view['info'] = User::where('id', $user['id'])->first();
+
+            return Response::view('user/profile', $view);
         }
     }
 
@@ -63,6 +136,8 @@ class UserController extends BaseController
             return Redirect::to('login');
         }
 
+        $user = $request->session()->get('user');
+
         $nodeList = SsNode::paginate(10);
         foreach ($nodeList as &$node) {
             // 在线人数
@@ -77,6 +152,40 @@ class UserController extends BaseController
             // 负载
             $node_info = SsNodeInfo::where('node_id', $node->id)->orderBy('id', 'desc')->first();
             $node->load = empty($node_info->load) ? 0 : $node_info->load;
+
+            // 生成ssr scheme
+            $ssr_str = '';
+            $ssr_str .= $node->server . ':' . $user['port'];
+            $ssr_str .= ':' . $user['protocol'] . ':' . $user['method'];
+            $ssr_str .= ':' . $user['obfs'] . ':' . base64_encode($user['passwd']);
+            $ssr_str .= '/?obfsparam=' . $user['obfs_param'];
+            $ssr_str .= '&=protoparam' . $user['protocol_param'];
+            $ssr_str .= '&remarks=' . base64_encode('VPN');
+            $ssr_str = $this->base64url_encode($ssr_str);
+            $ssr_scheme = 'ssr://' . $ssr_str;
+
+            // 生成ss scheme
+            $ss_str = '';
+            $ss_str .= $user['method']. ':' . $user['passwd'] . '@';
+            $ss_str .= $node->server . ':' . $user['port'];
+            $ss_str = $this->base64url_encode($ss_str) . '#' . 'VPN';
+            $ss_scheme = 'ss://' . $ss_str;
+
+            // 生成文本配置信息
+            $txt = <<<TXT
+服务器:{$node->server}
+端口:{$user['port']}
+密码:{$user['passwd']}
+加密方式:{$user['method']}
+协议:{$user['protocol']}
+协议参数:{$user['protocol_param']}
+混淆:{$user['obfs']}
+混淆参数:{$user['obfs_param']}
+TXT;
+
+            $node->txt = $txt;
+            $node->ssr_scheme = $ssr_scheme;
+            $node->ss_scheme = $ss_scheme;
         }
 
         $view['nodeList'] = $nodeList;
@@ -93,14 +202,13 @@ class UserController extends BaseController
 
         $user = $request->session()->get('user');
 
-        $trafficLogList = UserTrafficLog::with(['User', 'SsNode'])->where('user_id', $user['id'])->orderBy('id', 'desc')->paginate(20);
-        foreach ($trafficLogList as &$trafficLog) {
-            $trafficLog->u = $this->flowAutoShow($trafficLog->u);
-            $trafficLog->d = $this->flowAutoShow($trafficLog->d);
-            $trafficLog->log_time = date('Y-m-d H:i:s', $trafficLog->log_time);
+        // 30天内的流量
+        $trafficList = \DB::select("SELECT date(from_unixtime(log_time)) AS dd, SUM(u) AS u, SUM(d) AS d FROM `user_traffic_log` WHERE `user_id` = {$user['id']} GROUP BY `dd`");
+        foreach ($trafficList as $key => &$val) {
+            $val->total = ($val->u + $val->d) / (1024 * 1024); // 以M为单位
         }
 
-        $view['trafficLogList'] = $trafficLogList;
+        $view['trafficList'] = $trafficList;
 
         return Response::view('user/trafficLog', $view);
     }

+ 24 - 0
app/Http/Models/Article.php

@@ -0,0 +1,24 @@
+<?php
+
+namespace App\Http\Models;
+
+use Illuminate\Database\Eloquent\Model;
+
+/**
+ * 文章
+ * Class Node
+ * @package App\Http\Models
+ */
+class Article extends Model
+{
+    protected $table = 'article';
+    protected $primaryKey = 'id';
+    public $timestamps = false;
+    protected $fillable = [
+        'title',
+        'content',
+        'is_del',
+        'sort'
+    ];
+
+}

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

@@ -36,7 +36,7 @@
                                 <tbody>
                                     @foreach ($nodeList as $node)
                                         <tr>
-                                            <td> {{$node->name}} </td>
+                                            <td> {{$node->name}} @if ($node->compatible) <span class="label label-warning"> 兼容SS </span> @endif </td>
                                             <td>
                                                 <a class="btn btn-sm green btn-outline" data-toggle="modal" href="#txt_{{$node->id}}"> 文本 </a>
                                                 <a class="btn btn-sm green btn-outline" data-toggle="modal" href="#json_{{$node->id}}"> JSON </a>

+ 0 - 1
resources/views/admin/monitor.blade.php

@@ -69,7 +69,6 @@
                                         [{{$key + 1}}, {{$vo->total}}],
                                     @endforeach
                                 ];
-
                             @endforeach
                         @endif
 

+ 26 - 2
resources/views/admin/system.blade.php

@@ -34,9 +34,17 @@
                         <form action="#" method="post" class="form-horizontal" onsubmit="return do_submit();">
                             <div class="portlet-body">
                                 <div class="form-group">
-                                    <label for="username" class="col-md-2 control-label">随机端口</label>
+                                    <label for="is_rand_port" class="col-md-2 control-label">随机端口</label>
                                     <div class="col-md-6">
                                         <input type="checkbox" class="make-switch" @if($is_rand_port) checked @endif id="is_rand_port" data-on-color="success" data-off-color="danger" data-on-text="启用" data-off-text="关闭">
+                                        <span class="help-block"> 添加账号时随机生成端口 </span>
+                                    </div>
+                                </div>
+                                <div class="form-group">
+                                    <label for="is_user_rand_port" class="col-md-2 control-label">自定义端口</label>
+                                    <div class="col-md-6">
+                                        <input type="checkbox" class="make-switch" @if($is_user_rand_port) checked @endif id="is_user_rand_port" data-on-color="success" data-off-color="danger" data-on-text="启用" data-off-text="关闭">
+                                        <span class="help-block"> 用户可以自定义一个端口 </span>
                                     </div>
                                 </div>
                             </div>
@@ -55,12 +63,13 @@
     <script src="/assets/global/plugins/bootstrap-switch/js/bootstrap-switch.min.js" type="text/javascript"></script>
 
     <script type="text/javascript">
+        // 启用、禁用随机端口
         $('#is_rand_port').on({
             'switchChange.bootstrapSwitch': function(event, state) {
                 var is_rand_port = 0;
 
                 if (state) {
-                    var is_rand_port = 1;
+                    is_rand_port = 1;
                 }
 
                 $.post("{{url('admin/enableRandPort')}}", {_token:'{{csrf_token()}}', value:is_rand_port}, function (ret) {
@@ -68,5 +77,20 @@
                 });
             }
         });
+
+        // 启用、禁用自定义端口
+        $('#is_user_rand_port').on({
+            'switchChange.bootstrapSwitch': function(event, state) {
+                var is_user_rand_port = 0;
+
+                if (state) {
+                    is_user_rand_port = 1;
+                }
+
+                $.post("{{url('admin/enableUserRandPort')}}", {_token:'{{csrf_token()}}', value:is_user_rand_port}, function (ret) {
+                    console.log(ret);
+                });
+            }
+        });
     </script>
 @endsection

+ 56 - 0
resources/views/user/article.blade.php

@@ -0,0 +1,56 @@
+@extends('user.layouts')
+
+@section('title', '控制面板')
+@section('content')
+    <!-- BEGIN CONTENT BODY -->
+    <div class="page-content">
+        <!-- BEGIN PAGE BREADCRUMB -->
+        <ul class="page-breadcrumb breadcrumb">
+            <li>
+                <a href="{{url('user')}}">用户中心</a>
+                <i class="fa fa-circle"></i>
+            </li>
+            <li>
+                <a href="javascript:;">系统公告</a>
+            </li>
+        </ul>
+        <!-- END PAGE BREADCRUMB -->
+        <div class="row">
+            <div class="col-md-12">
+                <!-- BEGIN PORTLET -->
+                <div class="portlet light bordered">
+                    <div class="portlet-title tabbable-line">
+                        <div class="caption caption-md">
+                            <i class="icon-globe theme-font hide"></i>
+                            <span class="caption-subject font-blue-madison bold uppercase">系统公告</span>
+                        </div>
+                    </div>
+                    <div class="portlet-body">
+                        <!--BEGIN TABS-->
+                        <div class="tab-content">
+                            {{$info->content}}
+                        </div>
+                        <!--END TABS-->
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <!-- END CONTENT BODY -->
+@endsection
+@section('script')
+    <script src="/assets/global/plugins/counterup/jquery.waypoints.min.js" type="text/javascript"></script>
+    <script src="/assets/global/plugins/counterup/jquery.counterup.min.js" type="text/javascript"></script>
+    <script src="/assets/global/plugins/jquery-knob/js/jquery.knob.js" type="text/javascript"></script>
+
+    <script>
+        $(function() {
+            $(".knob").knob({
+                'readOnly':true,
+                'angleoffset':0,
+                'width':150,
+                'height':150,
+            });
+        });
+    </script>
+@endsection

+ 27 - 82
resources/views/user/index.blade.php

@@ -28,76 +28,24 @@
                             <div class="tab-pane active">
                                 <div class="scroller" style="height: 170px;" data-always-visible="1" data-rail-visible1="0" data-handle-color="#D7DCE2">
                                     <ul class="feeds">
-                                        <li>
-                                            <div class="col1">
-                                                <div class="cont">
-                                                    <div class="cont-col1">
-                                                        <div class="label label-sm label-success">
-                                                            <i class="fa fa-bell-o"></i>
+                                        @if (!$articleList->isEmpty())
+                                            @foreach($articleList as $article)
+                                                <li>
+                                                    <div class="col1">
+                                                        <div class="cont">
+                                                            <div class="cont-col1">
+                                                                <div class="label label-sm label-success">
+                                                                    <i class="fa fa-bell-o"></i>
+                                                                </div>
+                                                            </div>
+                                                            <div class="cont-col2">
+                                                                <div class="desc"> <a href="{{url('user/article?id=') . $article->id}}" target="_blank">{{$article->title}}</a> </div>
+                                                            </div>
                                                         </div>
                                                     </div>
-                                                    <div class="cont-col2">
-                                                        <div class="desc"> 节点全部切换为SSR,请注意更改客户端配置信息 </div>
-                                                    </div>
-                                                </div>
-                                            </div>
-                                        </li>
-                                        <li>
-                                            <div class="col1">
-                                                <div class="cont">
-                                                    <div class="cont-col1">
-                                                        <div class="label label-sm label-default">
-                                                            <i class="fa fa-bullhorn"></i>
-                                                        </div>
-                                                    </div>
-                                                    <div class="cont-col2">
-                                                        <div class="desc"> 促销:200G流量包,原价50元现在只要35元,有效期180天 </div>
-                                                    </div>
-                                                </div>
-                                            </div>
-                                        </li>
-                                        <li>
-                                            <div class="col1">
-                                                <div class="cont">
-                                                    <div class="cont-col1">
-                                                        <div class="label label-sm label-info">
-                                                            <i class="fa fa-bullhorn"></i>
-                                                        </div>
-                                                    </div>
-                                                    <div class="cont-col2">
-                                                        <div class="desc"> 新节点:新上架新加坡节点,白银以上会员可见  </div>
-                                                    </div>
-                                                </div>
-                                            </div>
-                                        </li>
-                                        <li>
-                                            <div class="col1">
-                                                <div class="cont">
-                                                    <div class="cont-col1">
-                                                        <div class="label label-sm label-default">
-                                                            <i class="fa fa-bullhorn"></i>
-                                                        </div>
-                                                    </div>
-                                                    <div class="cont-col2">
-                                                        <div class="desc"> 新节点:新上架白俄罗斯节点,白银以上会员可见 </div>
-                                                    </div>
-                                                </div>
-                                            </div>
-                                        </li>
-                                        <li>
-                                            <div class="col1">
-                                                <div class="cont">
-                                                    <div class="cont-col1">
-                                                        <div class="label label-sm label-info">
-                                                            <i class="fa fa-bullhorn"></i>
-                                                        </div>
-                                                    </div>
-                                                    <div class="cont-col2">
-                                                        <div class="desc"> 新节点:新上架新西兰节点,白银以上会员可见  </div>
-                                                    </div>
-                                                </div>
-                                            </div>
-                                        </li>
+                                                </li>
+                                            @endforeach
+                                        @endif
                                     </ul>
                                 </div>
                             </div>
@@ -123,32 +71,31 @@
                                         等级:普通会员
                                     </li>
                                     <li class="list-group-item">
-                                        端口:10222
-                                        <span class="badge badge-warning"><a href="#">修改</a></span>
+                                        端口:{{$info['port']}}
                                     </li>
                                     <li class="list-group-item">
-                                        加密方式:aes-192-ctr
-                                        <span class="badge badge-warning"><a href="#">修改</a></span>
+                                        加密方式:{{$info['method']}}
+                                        <span class="badge badge-warning"><a href="{{url('user/profile#tab_2')}}">修改</a></span>
                                     </li>
                                     <li class="list-group-item">
-                                        连接密码:@123
-                                        <span class="badge badge-warning"><a href="#">修改</a></span>
+                                        连接密码:{{$info['passwd']}}
+                                        <span class="badge badge-warning"><a href="{{url('user/profile#tab_2')}}">修改</a></span>
                                     </li>
                                     <li class="list-group-item">
-                                        协议:orgin
-                                        <span class="badge badge-warning"><a href="#">修改</a></span>
+                                        协议:{{$info['protocol']}}
+                                        <span class="badge badge-warning"><a href="{{url('user/profile#tab_2')}}">修改</a></span>
                                     </li>
                                     <li class="list-group-item">
-                                        混淆:plain
-                                        <span class="badge badge-warning"><a href="#">修改</a></span>
+                                        混淆:{{$info['obfs']}}
+                                        <span class="badge badge-warning"><a href="{{url('user/profile#tab_2')}}">修改</a></span>
                                     </li>
-                                    <li class="list-group-item"> 最后使用:2017-2-2 12:12:12
+                                    <li class="list-group-item"> 最后使用:{{empty($info['t']) ? '未使用' : date('Y-m-d H:i:s', $info['t'])}}
                                     </li>
                                 </ul>
                             </div>
                             <div class="col-md-5" style="text-align: center;">
                                 <h3> 流量 </h3>
-                                <input class="knob" value="35" title="可用流量:1000G">
+                                <input class="knob" value="35" title="可用流量:{{$info['transfer_enable']}}">
                             </div>
                         </div>
                     </div>
@@ -159,8 +106,6 @@
     <!-- END CONTENT BODY -->
 @endsection
 @section('script')
-    <script src="/assets/global/plugins/counterup/jquery.waypoints.min.js" type="text/javascript"></script>
-    <script src="/assets/global/plugins/counterup/jquery.counterup.min.js" type="text/javascript"></script>
     <script src="/assets/global/plugins/jquery-knob/js/jquery.knob.js" type="text/javascript"></script>
 
     <script>

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

@@ -65,7 +65,8 @@
                                             <td> <span class="label label-info"> {{$node->protocol}} </span> </td>
                                             <td> <span class="label label-info"> {{$node->obfs}} </span> </td>
                                             <td>
-                                                <button type="button" class="btn btn-sm blue btn-outline" onclick="">查看配置</button>
+                                                <a class="btn btn-sm green btn-outline" data-toggle="modal" href="#txt_{{$node->id}}"> 查看配置 </a>
+                                                <a class="btn btn-sm green btn-outline" data-toggle="modal" href="#qrcode_{{$node->id}}"> 二维码 </a>
                                             </td>
                                         </tr>
                                     @endforeach
@@ -83,6 +84,51 @@
                                 </div>
                             </div>
                         </div>
+
+                        @foreach ($nodeList as $node)
+                            <div class="modal fade draggable-modal" id="txt_{{$node->id}}" tabindex="-1" role="basic" aria-hidden="true">
+                                <div class="modal-dialog">
+                                    <div class="modal-content">
+                                        <div class="modal-header">
+                                            <button type="button" class="close" data-dismiss="modal" aria-hidden="true"></button>
+                                            <h4 class="modal-title">配置信息</h4>
+                                        </div>
+                                        <div class="modal-body">
+                                            <textarea class="form-control" rows="10" onclick="this.focus();this.select()" readonly="readonly"> {{$node->txt}} </textarea>
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="modal fade" id="qrcode_{{$node->id}}" tabindex="-1" role="dialog" aria-hidden="true">
+                                <div class="modal-dialog @if(!$node->compatible) modal-sm @endif">
+                                    <div class="modal-content">
+                                        <div class="modal-header">
+                                            <button type="button" class="close" data-dismiss="modal" aria-hidden="true"></button>
+                                            <h4 class="modal-title">请使用客户端扫描二维码</h4>
+                                        </div>
+                                        <div class="modal-body">
+                                            <div class="row">
+                                                @if ($node->compatible)
+                                                    <div class="col-md-6">
+                                                        <div style="font-size:16px;text-align:center;padding-bottom:10px;"><span>SSR</span></div>
+                                                        <div id="qrcode_ssr_img_{{$node->id}}"></div>
+                                                    </div>
+                                                    <div class="col-md-6">
+                                                        <div style="font-size:16px;text-align:center;padding-bottom:10px;"><span>SS</span></div>
+                                                        <div id="qrcode_ss_img_{{$node->id}}"></div>
+                                                    </div>
+                                                @else
+                                                    <div class="col-md-12">
+                                                        <div style="font-size:16px;text-align:center;padding-bottom:10px;"><span>SSR</span></div>
+                                                        <div id="qrcode_ssr_img_{{$node->id}}"></div>
+                                                    </div>
+                                                @endif
+                                            </div>
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                        @endforeach
                     </div>
                 </div>
                 <!-- END EXAMPLE TABLE PORTLET-->
@@ -93,6 +139,34 @@
     <!-- END CONTENT BODY -->
 @endsection
 @section('script')
+    <script src="/assets/global/plugins/jquery-qrcode/jquery.qrcode.min.js" type="text/javascript"></script>
+    <script src="/assets/global/plugins/jquery-ui/jquery-ui.min.js" type="text/javascript"></script>
     <script src="/assets/global/plugins/bootbox/bootbox.min.js" type="text/javascript"></script>
 
+    <script type="text/javascript">
+        var UIModals = function () {
+            var n = function () {
+                @foreach($nodeList as $node)
+                    $("#txt_{{$node->id}}").draggable({handle: ".modal-header"});
+                    $("#qrcode_{{$node->id}}").draggable({handle: ".modal-header"});
+                @endforeach
+            };
+
+            return {
+                init: function () {
+                    n()
+                }
+            }
+        }();
+
+        jQuery(document).ready(function () {
+            UIModals.init()
+        });
+
+        // 循环输出节点scheme用于生成二维码
+        @foreach ($nodeList as $node)
+            $('#qrcode_ssr_img_{{$node->id}}').qrcode("{{$node->ssr_scheme}}");
+            $('#qrcode_ss_img_{{$node->id}}').qrcode("{{$node->ss_scheme}}");
+        @endforeach
+    </script>
 @endsection

+ 49 - 34
resources/views/user/profile.blade.php

@@ -10,7 +10,7 @@
         <!-- BEGIN PAGE BREADCRUMB -->
         <ul class="page-breadcrumb breadcrumb">
             <li>
-                <a href="{{url('admin/profile')}}">个人资料</a>
+                <a href="{{url('user/profile')}}">个人资料</a>
                 <i class="fa fa-circle"></i>
             </li>
         </ul>
@@ -30,36 +30,6 @@
                         <strong>错误:</strong> {{Session::get('errorMsg')}}
                     </div>
                 @endif
-                <!-- BEGIN PROFILE SIDEBAR -->
-                <div class="profile-sidebar">
-                    <!-- PORTLET MAIN -->
-                    <div class="portlet light profile-sidebar-portlet bordered">
-                        <!-- SIDEBAR USERPIC -->
-                        <div class="profile-userpic">
-                            <img src="/assets/images/avatar.jpg" class="img-responsive" alt=""> </div>
-                        <!-- END SIDEBAR USERPIC -->
-                        <!-- SIDEBAR USER TITLE -->
-                        <div class="profile-usertitle">
-                            <div class="profile-usertitle-name"> {{Session::get('user')['username']}} </div>
-                            <div class="profile-usertitle-job"> 普通会员 </div>
-                        </div>
-                        <!-- END SIDEBAR USER TITLE -->
-                        <!-- SIDEBAR MENU -->
-                        <div class="profile-usermenu">
-                            <!--
-                            <ul class="nav">
-                                <li class="active">
-                                    <a href="javascript:;">
-                                        <i class="icon-user"></i> 个人资料 </a>
-                                </li>
-                            </ul>
-                            -->
-                        </div>
-                        <!-- END MENU -->
-                    </div>
-                    <!-- END PORTLET MAIN -->
-                </div>
-                <!-- END BEGIN PROFILE SIDEBAR -->
                 <!-- BEGIN PROFILE CONTENT -->
                 <div class="profile-content">
                     <div class="row">
@@ -68,13 +38,15 @@
                                 <div class="portlet-title tabbable-line">
                                     <ul class="nav nav-tabs">
                                         <li class="active">
-                                            <a href="#tab_1" data-toggle="tab">修改密码</a>
+                                            <a href="#tab_1" data-toggle="tab">登录密码</a>
+                                        </li>
+                                        <li>
+                                            <a href="#tab_2" data-toggle="tab">SS信息</a>
                                         </li>
                                     </ul>
                                 </div>
                                 <div class="portlet-body">
                                     <div class="tab-content">
-                                        <!-- CHANGE PASSWORD TAB -->
                                         <div class="tab-pane active" id="tab_1">
                                             <form action="{{url('user/profile')}}" method="post" enctype="multipart/form-data" class="form-bordered">
                                                 <div class="form-group">
@@ -95,7 +67,50 @@
                                                 </div>
                                             </form>
                                         </div>
-                                        <!-- END CHANGE PASSWORD TAB -->
+                                        <div class="tab-pane" id="tab_2">
+                                            <form action="{{url('user/profile')}}" method="post" enctype="multipart/form-data" class="form-bordered">
+                                                <div class="form-group">
+                                                    <label class="control-label"> 端口 </label>
+                                                    <input type="text" class="form-control" name="port" value="{{$info->port}}" id="port" readonly />
+                                                    <input type="hidden" name="_token" value="{{csrf_token()}}" />
+                                                </div>
+                                                <div class="form-group">
+                                                    <label class="control-label"> 连接密码 </label>
+                                                    <input type="text" class="form-control" name="passwd" value="{{$info->passwd}}" id="passwd" required />
+                                                </div>
+                                                <div class="form-group">
+                                                    <label class="control-label"> 加密方式 </label>
+                                                    <select class="form-control" name="method" id="method">
+                                                        @foreach ($method_list as $method)
+                                                            <option value="{{$method->name}}" @if($method->name == $info->method) selected @endif>{{$method->name}}</option>
+                                                        @endforeach
+                                                    </select>
+                                                </div>
+                                                <div class="form-group">
+                                                    <label class="control-label"> 协议 </label>
+                                                    <select class="form-control" name="protocol" id="protocol">
+                                                        @foreach ($protocol_list as $protocol)
+                                                            <option value="{{$protocol->name}}" @if($protocol->name == $info->protocol) selected @endif>{{$protocol->name}}</option>
+                                                        @endforeach
+                                                    </select>
+                                                </div>
+                                                <div class="form-group">
+                                                    <label class="control-label"> 混淆 </label>
+                                                    <select class="form-control" name="obfs" id="obfs">
+                                                        @foreach ($obfs_list as $obfs)
+                                                            <option value="{{$obfs->name}}" @if($obfs->name == $info->obfs) selected @endif>{{$obfs->name}}</option>
+                                                        @endforeach
+                                                    </select>
+                                                </div>
+                                                <div class="form-actions">
+                                                    <div class="row">
+                                                        <div class=" col-md-4">
+                                                            <button type="submit" class="btn green"> 提 交 </button>
+                                                        </div>
+                                                    </div>
+                                                </div>
+                                            </form>
+                                        </div>
                                     </div>
                                 </div>
                             </div>

+ 126 - 52
resources/views/user/trafficLog.blade.php

@@ -1,9 +1,8 @@
 @extends('user.layouts')
 
 @section('css')
-    <link href="/assets/global/plugins/datatables/datatables.min.css" rel="stylesheet" type="text/css" />
-    <link href="/assets/global/plugins/datatables/plugins/bootstrap/datatables.bootstrap.css" rel="stylesheet" type="text/css" />
 @endsection
+
 @section('title', '控制面板')
 @section('content')
     <!-- BEGIN CONTENT BODY -->
@@ -19,62 +18,17 @@
         <!-- BEGIN PAGE BASE CONTENT -->
         <div class="row">
             <div class="col-md-12">
-                <!-- BEGIN EXAMPLE TABLE PORTLET-->
-                <div class="portlet light bordered">
+                <div class="portlet light portlet-fit bordered">
                     <div class="portlet-title">
-                        <div class="caption font-dark">
-                            <i class="icon-speedometer font-dark"></i>
-                            <span class="caption-subject bold uppercase"> 流量日志</span>
+                        <div class="caption">
+                            <i class="icon-settings font-dark"></i>
+                            <span class="caption-subject font-dark sbold uppercase">流量日志</span>
                         </div>
                     </div>
                     <div class="portlet-body">
-                        <div class="table-scrollable">
-                            <table class="table table-striped table-bordered table-hover table-checkable order-column" id="sample_1">
-                                <thead>
-                                <tr>
-                                    <th> ID </th>
-                                    <th> 节点 </th>
-                                    <th> 流量比例 </th>
-                                    <th> 上传流量 </th>
-                                    <th> 下载流量 </th>
-                                    <th> 总流量 </th>
-                                    <th> 记录时间 </th>
-                                </tr>
-                                </thead>
-                                <tbody>
-                                    @if($trafficLogList->isEmpty())
-                                        <tr>
-                                            <td colspan="9">暂无数据</td>
-                                        </tr>
-                                    @else
-                                        @foreach($trafficLogList as $trafficLog)
-                                            <tr class="odd gradeX">
-                                                <td> {{$trafficLog->id}} </td>
-                                                <td> {{$trafficLog->ssnode->name}} </td>
-                                                <td> {{$trafficLog->rate}} </td>
-                                                <td> {{$trafficLog->u}} </td>
-                                                <td> {{$trafficLog->d}} </td>
-                                                <td> <span class="label label-danger"> {{$trafficLog->traffic}} </span> </td>
-                                                <td> {{$trafficLog->log_time}} </td>
-                                            </tr>
-                                        @endforeach
-                                    @endif
-                                </tbody>
-                            </table>
-                        </div>
-                        <div class="row">
-                            <div class="col-md-5 col-sm-5">
-                                <div class="dataTables_info" role="status" aria-live="polite">共 {{$trafficLogList->total()}} 条记录</div>
-                            </div>
-                            <div class="col-md-7 col-sm-7">
-                                <div class="dataTables_paginate paging_bootstrap_full_number pull-right">
-                                    {{ $trafficLogList->links() }}
-                                </div>
-                            </div>
-                        </div>
+                        <div id="chart" class="chart"> </div>
                     </div>
                 </div>
-                <!-- END EXAMPLE TABLE PORTLET-->
             </div>
         </div>
         <!-- END PAGE BASE CONTENT -->
@@ -82,6 +36,126 @@
     <!-- END CONTENT BODY -->
 @endsection
 @section('script')
+    <script src="/assets/global/plugins/flot/jquery.flot.min.js" type="text/javascript"></script>
+    <script src="/assets/global/plugins/jquery-ui/jquery-ui.min.js" type="text/javascript"></script>
     <script src="/assets/global/plugins/bootbox/bootbox.min.js" type="text/javascript"></script>
 
+    <script type="text/javascript">
+        var ChartsFlotcharts = function() {
+            return {
+                init: function() {
+                    App.addResizeHandler(function() {
+                        Charts.initPieCharts();
+                    });
+                },
+
+                initCharts: function() {
+                    if (!jQuery.plot) {
+                        return;
+                    }
+
+                    function chart() {
+                        if ($('#chart').size() != 1) {
+                            return;
+                        }
+
+                        var chartData = [
+                            @if (!empty($trafficList))
+                                @foreach ($trafficList as $key => $vo)
+                                    [{{$key + 1}}, {{$vo->total}}],
+                                @endforeach
+                            @endif
+                        ];
+
+                        var plot = $.plot($("#chart"), [
+                                {data: chartData, label: "30日流量走势", lines: {lineWidth: 1}, shadowSize: 0},
+                            ], {
+                                series: {
+                                    lines: {
+                                        show: true,
+                                        lineWidth: 2,
+                                        fill: true,
+                                        fillColor: {
+                                            colors: [{
+                                                opacity: 0.05
+                                            }, {
+                                                opacity: 0.01
+                                            }]
+                                        }
+                                    },
+                                    points: {
+                                        show: true,
+                                        radius: 3,
+                                        lineWidth: 1
+                                    },
+                                    shadowSize: 2
+                                },
+                                grid: {
+                                    hoverable: true,
+                                    clickable: true,
+                                    tickColor: "#eee",
+                                    borderColor: "#eee",
+                                    borderWidth: 1
+                                },
+                                colors: ["#d12610", "#37b7f3", "#52e136"],
+                                xaxis: {
+                                    ticks: 11,
+                                    tickDecimals: 0,
+                                    tickColor: "#eee",
+                                },
+                                yaxis: {
+                                    ticks: 11,
+                                    tickDecimals: 0,
+                                    tickColor: "#eee",
+                                }
+                            });
+
+
+                        function showTooltip(x, y, contents) {
+                            $('<div id="tooltip">' + contents + '</div>').css({
+                                position: 'absolute',
+                                display: 'none',
+                                top: y + 5,
+                                left: x + 15,
+                                border: '1px solid #333',
+                                padding: '4px',
+                                color: '#fff',
+                                'border-radius': '3px',
+                                'background-color': '#333',
+                                opacity: 0.80
+                            }).appendTo("body").fadeIn(200);
+                        }
+
+                        var previousPoint = null;
+                        $("#chart").bind("plothover", function(event, pos, item) {
+                            $("#x").text(pos.x.toFixed(2));
+                            $("#y").text(pos.y.toFixed(2));
+
+                            if (item) {
+                                if (previousPoint != item.dataIndex) {
+                                    previousPoint = item.dataIndex;
+
+                                    $("#tooltip").remove();
+                                    var x = item.datapoint[0].toFixed(2),
+                                        y = item.datapoint[1].toFixed(2);
+
+                                    showTooltip(item.pageX, item.pageY, item.series.label + ": " + y + 'M');
+                                }
+                            } else {
+                                $("#tooltip").remove();
+                                previousPoint = null;
+                            }
+                        });
+                    }
+
+                    chart();
+                }
+            };
+        }();
+
+        jQuery(document).ready(function() {
+            ChartsFlotcharts.init();
+            ChartsFlotcharts.initCharts();
+        });
+    </script>
 @endsection

+ 2 - 0
routes/web.php

@@ -27,10 +27,12 @@ Route::any('admin/profile', 'AdminController@profile'); // 修改个人信息
 Route::any('admin/analysis', 'AdminController@analysis'); // 日志分析
 Route::any('admin/system', 'AdminController@system'); // 系统设置
 Route::post('admin/enableRandPort', 'AdminController@enableRandPort'); // 启用、禁用随机端口
+Route::post('admin/enableUserRandPort', 'AdminController@enableUserRandPort'); // 启用、禁用自定义端口
 Route::get('makePasswd', 'AdminController@makePasswd'); // 获取随机密码
 Route::get('download', 'AdminController@download'); // 下载转换过的JSON配置
 
 Route::any('user', 'UserController@index'); // 用户首页
+Route::any('user/article', 'UserController@article'); // 文章详情
 Route::any('user/nodeList', 'UserController@nodeList'); // 节点列表
 Route::any('user/profile', 'UserController@profile'); // 修改个人信息
 Route::any('user/trafficLog', 'UserController@trafficLog'); // 流量日志

+ 17 - 1
sql/db.sql

@@ -208,9 +208,25 @@ CREATE TABLE `config` (
 ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
 
 -- ----------------------------
--- Records of onfig
+-- Records of config
 -- ----------------------------
 INSERT INTO `config` VALUES ('1', 'is_rand_port', 0);
+INSERT INTO `config` VALUES ('2', 'is_user_rand_port', 0);
+
+
+-- ----------------------------
+-- Table structure for `article`
+-- ----------------------------
+CREATE TABLE `article` (
+  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
+  `title` varchar(100) NOT NULL DEFAULT '' COMMENT '文章标题',
+  `content` text COMMENT '文章内容',
+  `is_del` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否删除',
+  `sort` int(11) NOT NULL DEFAULT '0' COMMENT '排序',
+  `created_at` datetime DEFAULT NULL,
+  `updated_at` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;