Procházet zdrojové kódy

Merge branch 'master' into master

胖虎 před 8 roky
rodič
revize
ef821c1e4d
70 změnil soubory, kde provedl 1515 přidání a 500 odebrání
  1. 1 1
      app/Console/Commands/AutoBanUserJob.php
  2. 55 0
      app/Console/Commands/AutoClearLogJob.php
  3. 8 17
      app/Console/Commands/AutoDecGoodsTrafficJob.php
  4. 1 1
      app/Console/Commands/AutoDisableExpireUserJob.php
  5. 1 1
      app/Console/Commands/AutoReopenUserJob.php
  6. 19 2
      app/Console/Commands/AutoResetUserTrafficJob.php
  7. 2 2
      app/Console/Commands/AutoStatisticsNodeDailyTrafficJob.php
  8. 2 2
      app/Console/Commands/AutoStatisticsNodeHourlyTrafficJob.php
  9. 2 2
      app/Console/Commands/AutoStatisticsUserDailyTrafficJob.php
  10. 2 2
      app/Console/Commands/AutoStatisticsUserHourlyTrafficJob.php
  11. 1 1
      app/Console/Commands/UserExpireWarningJob.php
  12. 1 1
      app/Console/Commands/UserTrafficWarningJob.php
  13. 5 3
      app/Console/Kernel.php
  14. 249 148
      app/Http/Controllers/AdminController.php
  15. 7 2
      app/Http/Controllers/CouponController.php
  16. 21 0
      app/Http/Controllers/DonateController.php
  17. 13 0
      app/Http/Controllers/RegisterController.php
  18. 14 4
      app/Http/Controllers/ShopController.php
  19. 9 7
      app/Http/Controllers/SubscribeController.php
  20. 39 20
      app/Http/Controllers/UserController.php
  21. 4 0
      app/Http/Models/OrderGoods.php
  22. 1 0
      app/Http/Models/SsNodeInfo.php
  23. 1 0
      app/Http/Models/SsNodeOnlineLog.php
  24. binární
      public/assets/images/country/be.png
  25. binární
      public/assets/images/country/bg.png
  26. binární
      public/assets/images/country/co.png
  27. binární
      public/assets/images/country/fi.png
  28. binární
      public/assets/images/country/is.png
  29. binární
      public/assets/images/country/ke.png
  30. binární
      public/assets/images/country/lt.png
  31. binární
      public/assets/images/country/lu.png
  32. binární
      public/assets/images/country/mm.png
  33. binární
      public/assets/images/country/mo.png
  34. binární
      public/assets/images/country/za.png
  35. binární
      public/assets/images/donate.jpeg
  36. 67 27
      readme.md
  37. 1 15
      resources/views/admin/addUser.blade.php
  38. 1 1
      resources/views/admin/applyDetail.blade.php
  39. 34 0
      resources/views/admin/donate.blade.php
  40. 85 4
      resources/views/admin/editUser.blade.php
  41. 5 5
      resources/views/admin/import.blade.php
  42. 5 5
      resources/views/admin/index.blade.php
  43. 13 1
      resources/views/admin/inviteList.blade.php
  44. 27 6
      resources/views/admin/layouts.blade.php
  45. 23 1
      resources/views/admin/system.blade.php
  46. 112 0
      resources/views/admin/userBalanceLogList.blade.php
  47. 1 0
      resources/views/register.blade.php
  48. 6 0
      resources/views/serverStatus/css/bootstrap-theme.min.css
  49. 6 0
      resources/views/serverStatus/css/bootstrap.min.css
  50. 55 0
      resources/views/serverStatus/css/light.css
  51. binární
      resources/views/serverStatus/favicon.ico
  52. binární
      resources/views/serverStatus/img/light.png
  53. 77 0
      resources/views/serverStatus/index.html
  54. 6 0
      resources/views/serverStatus/js/bootstrap.min.js
  55. 3 0
      resources/views/serverStatus/js/jquery-1.10.2.min.js
  56. 383 0
      resources/views/serverStatus/js/serverstatus.js
  57. 2 0
      resources/views/serverStatus/json/.gitignore
  58. 1 1
      resources/views/shop/editGoods.blade.php
  59. 1 1
      resources/views/user/addOrder.blade.php
  60. 3 182
      resources/views/user/goodsList.blade.php
  61. 1 1
      resources/views/user/index.blade.php
  62. 1 1
      resources/views/user/invite.blade.php
  63. 4 0
      routes/web.php
  64. binární
      server/serverStatus.zip
  65. 41 31
      sql/db.sql
  66. 26 2
      sql/update/20171129.sql
  67. 29 0
      sql/update/20171130.sql
  68. 27 0
      sql/update/20171201.sql
  69. 6 0
      sql/update/20171202.sql
  70. 5 0
      sql/update/20171204.sql

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

@@ -12,7 +12,7 @@ use Log;
 class AutoBanUserJob extends Command
 {
     protected $signature = 'command:autoBanUserJob';
-    protected $description = '自动封禁账号';
+    protected $description = '自动封禁用户';
 
     protected static $config;
 

+ 55 - 0
app/Console/Commands/AutoClearLogJob.php

@@ -0,0 +1,55 @@
+<?php
+
+namespace App\Console\Commands;
+
+use App\Http\Models\SsNodeInfo;
+use App\Http\Models\SsNodeOnlineLog;
+use App\Http\Models\SsNodeTrafficHourly;
+use App\Http\Models\UserTrafficLog;
+use Illuminate\Console\Command;
+use App\Http\Models\Config;
+use App\Http\Models\UserTrafficHourly;
+use Log;
+
+class AutoClearLogJob extends Command
+{
+    protected $signature = 'command:autoClearLogJob';
+    protected $description = '自动清除日志';
+
+    protected static $config;
+
+    public function __construct()
+    {
+        parent::__construct();
+
+        $config = Config::query()->get();
+        $data = [];
+        foreach ($config as $vo) {
+            $data[$vo->name] = $vo->value;
+        }
+
+        self::$config = $data;
+    }
+
+    public function handle()
+    {
+        if (self::$config['is_clear_log']) {
+            // 自动清除12小时以前的节点负载信息日志
+            SsNodeInfo::query()->where('log_time', '<=', strtotime(date('Y-m-d H:i:s', strtotime("-12 hours"))))->delete();
+
+            // 自动清除1小时以前的节点负载信息日志
+            SsNodeOnlineLog::query()->where('log_time', '<=', strtotime(date('Y-m-d H:i:s', strtotime("-60 minutes"))))->delete();
+
+            // 自动清除30天以前的用户流量日志
+            UserTrafficLog::query()->where('log_time', '<=', strtotime(date('Y-m-d H:i:s', strtotime("-30 days"))))->delete();
+
+            // 自动清除10天以前的用户每小时流量数据日志
+            UserTrafficHourly::query()->where('created_at', '<=', date('Y-m-d H:i:s', strtotime('-10 days')))->delete();
+
+            // 自动清除10天以前的节点每小时流量数据日志
+            SsNodeTrafficHourly::query()->where('created_at', '<=', date('Y-m-d H:i:s', strtotime('-10 days')))->delete();
+        }
+
+        Log::info('定时任务:' . $this->description);
+    }
+}

+ 8 - 17
app/Console/Commands/AutoDecGoodsTrafficJob.php

@@ -3,7 +3,6 @@
 namespace App\Console\Commands;
 
 use Illuminate\Console\Command;
-use App\Http\Models\Goods;
 use App\Http\Models\OrderGoods;
 use App\Http\Models\User;
 use Log;
@@ -20,28 +19,20 @@ class AutoDecGoodsTrafficJob extends Command
 
     public function handle()
     {
-        $orderGoods = OrderGoods::query()->where('is_expire', 0)->get();
+        $orderGoods = OrderGoods::query()->with(['user', 'goods'])->where('is_expire', 0)->get();
         foreach ($orderGoods as $og) {
-            $goods = Goods::query()->where('id', $og->goods_id)->first();
-            if (empty($goods)) {
+            if (empty($og->goods) || $og->goods->is_del || empty($og->user)) {
                 continue;
             }
 
-            if (date("Y-m-d H:i:s", strtotime("-" . $goods->days . " days")) >= $og->created_at) {
-                $u = User::query()->where('id', $og->user_id)->first();
-                if (empty($u)) {
-                    continue;
+            // 到期自动处理
+            if (date("Y-m-d H:i:s", strtotime("-" . $og->goods->days . " days")) >= $og->created_at) {
+                if ($og->user->transfer_enable - $og->traffic * 1048576 <= 0) {
+                    User::query()->where('id', $og->user_id)->update(['transfer_enable' => 0]);
+                } else {
+                    User::query()->where('id', $og->user_id)->decrement('transfer_enable', $og->traffic * 1048576);
                 }
 
-                // 流量包到期自动扣总流量
-                //if ($goods->type == 1) {
-                    if ($u->transfer_enable - $goods->traffic * 1048576 <= 0) {
-                        User::query()->where('id', $og->user_id)->update(['transfer_enable' => 0]);
-                    } else {
-                        User::query()->where('id', $og->user_id)->decrement('transfer_enable', $goods->traffic * 1048576);
-                    }
-                //}
-
                 OrderGoods::query()->where('id', $og->id)->update(['is_expire' => 1]);
             }
         }

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

@@ -9,7 +9,7 @@ use Log;
 class autoDisableExpireUserJob extends Command
 {
     protected $signature = 'command:autoDisableExpireUserJob';
-    protected $description = '用户到期自动禁用';
+    protected $description = '自动禁用到期用户';
 
     public function __construct()
     {

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

@@ -10,7 +10,7 @@ use Log;
 class AutoReopenUserJob extends Command
 {
     protected $signature = 'command:autoReopenUserJob';
-    protected $description = '自动解封账号';
+    protected $description = '自动解封用户';
 
     public function __construct()
     {

+ 19 - 2
app/Console/Commands/AutoResetUserTrafficJob.php

@@ -2,6 +2,7 @@
 
 namespace App\Console\Commands;
 
+use App\Http\Models\OrderGoods;
 use Illuminate\Console\Command;
 use App\Http\Models\Config;
 use App\Http\Models\User;
@@ -30,8 +31,24 @@ class AutoResetUserTrafficJob extends Command
     public function handle()
     {
         if (self::$config['reset_traffic']) {
-            $user_ids = User::query()->where('pay_way', '<>', 0)->select(['id'])->get();
-            User::query()->whereIn('id', $user_ids)->update(['u' => 0, 'd' => 0]);
+            $userList = User::query()->where('status', '>=', 0)->where('enable', 1)->get();
+            foreach ($userList as $user) {
+                if (empty($user->traffic_reset_day)) {
+                    continue;
+                }
+
+                // 取出这个用户最后购买的有效套餐
+                $orderGoods = OrderGoods::query()->with(['goods' => function($q) { $q->where('type', 2); }])->where('user_id', $user->id)->where('is_expire', 0)->orderBy('id', 'desc')->first();
+                if (empty($orderGoods) || empty($orderGoods->goods)) {
+                    continue;
+                }
+
+                if ($user->traffic_reset_day == abs(date('d')) && date('m') == date('m', strtotime($orderGoods->created_at))) {
+                    continue;
+                }
+
+                User::query()->where('id', $user->id)->update(['u' => 0, 'd' => 0]);
+            }
         }
 
         Log::info('定时任务:' . $this->description);

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

@@ -11,7 +11,7 @@ use Log;
 class AutoStatisticsNodeDailyTrafficJob extends Command
 {
     protected $signature = 'command:autoStatisticsNodeDailyTrafficJob';
-    protected $description = '节点每日流量自动统计';
+    protected $description = '自动统计节点每日流量';
 
     public function __construct()
     {
@@ -20,7 +20,7 @@ class AutoStatisticsNodeDailyTrafficJob extends Command
 
     public function handle()
     {
-        $nodeList = SsNode::query()->where('status', 1)->get();
+        $nodeList = SsNode::query()->where('status', 1)->orderBy('id', 'asc')->get();
         foreach ($nodeList as $node) {
             $this->statisticsByNode($node->id);
         }

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

@@ -11,7 +11,7 @@ use Log;
 class AutoStatisticsNodeHourlyTrafficJob extends Command
 {
     protected $signature = 'command:autoStatisticsNodeHourlyTrafficJob';
-    protected $description = '节点每小时流量自动统计';
+    protected $description = '自动统计节点每小时流量';
 
     public function __construct()
     {
@@ -20,7 +20,7 @@ class AutoStatisticsNodeHourlyTrafficJob extends Command
 
     public function handle()
     {
-        $nodeList = SsNode::query()->where('status', 1)->get();
+        $nodeList = SsNode::query()->where('status', 1)->orderBy('id', 'asc')->get();
         foreach ($nodeList as $node) {
             $this->statisticsByNode($node->id);
         }

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

@@ -12,7 +12,7 @@ use Log;
 class AutoStatisticsUserDailyTrafficJob extends Command
 {
     protected $signature = 'command:autoStatisticsUserDailyTrafficJob';
-    protected $description = '用户每日流量自动统计';
+    protected $description = '自动统计用户每日流量';
 
     public function __construct()
     {
@@ -27,7 +27,7 @@ class AutoStatisticsUserDailyTrafficJob extends Command
             $this->statisticsByNode($user->id);
 
             // 统计每个节点产生的流量
-            $nodeList = SsNode::query()->get();
+            $nodeList = SsNode::query()->where('status', 1)->orderBy('id', 'asc')->get();
             foreach ($nodeList as $node) {
                 $this->statisticsByNode($user->id, $node->id);
             }

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

@@ -12,7 +12,7 @@ use Log;
 class AutoStatisticsUserHourlyTrafficJob extends Command
 {
     protected $signature = 'command:autoStatisticsUserHourlyTrafficJob';
-    protected $description = '用户每小时流量自动统计';
+    protected $description = '自动统计用户每小时流量';
 
     public function __construct()
     {
@@ -27,7 +27,7 @@ class AutoStatisticsUserHourlyTrafficJob extends Command
             $this->statisticsByNode($user->id);
 
             // 统计每个节点产生的流量
-            $nodeList = SsNode::query()->get();
+            $nodeList = SsNode::query()->where('status', 1)->orderBy('id', 'asc')->get();
             foreach ($nodeList as $node) {
                 $this->statisticsByNode($user->id, $node->id);
             }

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

@@ -13,7 +13,7 @@ use Log;
 class UserExpireWarningJob extends Command
 {
     protected $signature = 'command:userExpireWarningJob';
-    protected $description = '用户到期自动发邮件提醒';
+    protected $description = '自动发邮件提醒用户临近到期';
 
     protected static $config;
 

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

@@ -13,7 +13,7 @@ use Log;
 class UserTrafficWarningJob extends Command
 {
     protected $signature = 'command:userTrafficWarningJob';
-    protected $description = '用户流量警告自动发邮件提醒';
+    protected $description = '自动发邮件提醒用户流量超过警告阈值';
 
     protected static $config;
 

+ 5 - 3
app/Console/Kernel.php

@@ -14,11 +14,12 @@ class Kernel extends ConsoleKernel
      */
     protected $commands = [
         \App\Console\Commands\AutoBanUserJob::class,
+        \App\Console\Commands\AutoClearLogJob::class,
         \App\Console\Commands\AutoDecGoodsTrafficJob::class,
         \App\Console\Commands\AutoDisableExpireUserJob::class,
         \App\Console\Commands\AutoExpireCouponJob::class,
         \App\Console\Commands\AutoExpireInviteJob::class,
-        //\App\Console\Commands\AutoGetLocationInfoJob::class,
+        \App\Console\Commands\AutoGetLocationInfoJob::class,
         \App\Console\Commands\AutoReopenUserJob::class,
         \App\Console\Commands\AutoResetUserTrafficJob::class,
         \App\Console\Commands\AutoStatisticsNodeDailyTrafficJob::class,
@@ -37,14 +38,15 @@ class Kernel extends ConsoleKernel
      */
     protected function schedule(Schedule $schedule)
     {
-        $schedule->command('command:autoBanUserJob')->everyThirtyMinutes();
+        $schedule->command('command:autoBanUserJob')->everyTenMinutes();
+        $schedule->command('command:autoClearLogJob')->everyThirtyMinutes();
         $schedule->command('command:autoDecGoodsTrafficJob')->everyTenMinutes();
         $schedule->command('command:autoDisableExpireUserJob')->everyMinute();
         $schedule->command('command:autoExpireCouponJob')->everyThirtyMinutes();
         $schedule->command('command:autoExpireInviteJob')->everyThirtyMinutes();
         //$schedule->command('command:autoGetLocationInfoJob')->everyMinute();
         $schedule->command('command:autoReopenUserJob')->everyMinute();
-        $schedule->command('command:autoResetUserTrafficJob')->monthly();
+        $schedule->command('command:autoResetUserTrafficJob')->everyFiveMinutes();
         $schedule->command('command:autoStatisticsNodeDailyTrafficJob')->dailyAt('04:30');
         $schedule->command('command:autoStatisticsNodeHourlyTrafficJob')->hourly();
         $schedule->command('command:autoStatisticsUserDailyTrafficJob')->dailyAt('03:00');

+ 249 - 148
app/Http/Controllers/AdminController.php

@@ -20,11 +20,13 @@ use App\Http\Models\SsNodeOnlineLog;
 use App\Http\Models\SsNodeTrafficDaily;
 use App\Http\Models\SsNodeTrafficHourly;
 use App\Http\Models\User;
+use App\Http\Models\UserBalanceLog;
 use App\Http\Models\UserSubscribe;
 use App\Http\Models\UserSubscribeLog;
 use App\Http\Models\UserTrafficDaily;
 use App\Http\Models\UserTrafficHourly;
 use App\Http\Models\UserTrafficLog;
+use Maatwebsite\Excel\Facades\Excel;
 use Illuminate\Http\Request;
 use Redirect;
 use Response;
@@ -42,18 +44,18 @@ class AdminController extends Controller
     public function index(Request $request)
     {
         $past = strtotime(date('Y-m-d', strtotime("-" . self::$config['expire_days'] . " days")));
-        $online = time() - 1800;
+        $online = time() - 120;
 
         $view['userCount'] = User::query()->count();
         $view['activeUserCount'] = User::query()->where('t', '>=', $past)->count();
         $view['onlineUserCount'] = User::query()->where('t', '>=', $online)->count();
         $view['nodeCount'] = SsNode::query()->count();
-        $flowCount = UserTrafficLog::query()->sum('u') + UserTrafficLog::query()->sum('d');
+        $flowCount = SsNodeTrafficDaily::query()->where('created_at', '>=', date('Y-m-d 00:00:00', strtotime("-30 days")))->sum('total');
         $flowCount = $this->flowAutoShow($flowCount);
         $view['flowCount'] = $flowCount;
-        $view['totalBalance'] = User::query()->sum('balance');
-        $view['totalWaitRefAmount'] = ReferralLog::query()->whereIn('status', [0, 1])->sum('ref_amount');
-        $view['totalRefAmount'] = ReferralApply::query()->where('status', 2)->sum('amount');
+        $view['totalBalance'] = User::query()->sum('balance') / 100;
+        $view['totalWaitRefAmount'] = ReferralLog::query()->whereIn('status', [0, 1])->sum('ref_amount') / 100;
+        $view['totalRefAmount'] = ReferralApply::query()->where('status', 2)->sum('amount') / 100;
         $view['expireWarningUserCount'] = User::query()->where('expire_time', '<=', date('Y-m-d', strtotime("+" . self::$config['expire_days'] . " days")))->where('enable', 1)->count();
 
         return Response::view('admin/index', $view);
@@ -143,8 +145,6 @@ class AdminController extends Controller
             $qq = $request->get('qq');
             $usage = $request->get('usage');
             $pay_way = $request->get('pay_way');
-            $balance = $request->get('balance');
-            $score = $request->get('score');
             $enable_time = $request->get('enable_time');
             $expire_time = $request->get('expire_time');
             $remark = $request->get('remark');
@@ -166,31 +166,31 @@ class AdminController extends Controller
             }
 
             $ret = User::query()->create([
-                'username' => $username,
-                'password' => $password,
-                'port' => $port,
-                'passwd' => empty($passwd) ? $this->makeRandStr() : $passwd, // SS密码为空时生成默认密码
+                'username'        => $username,
+                'password'        => $password,
+                'port'            => $port,
+                'passwd'          => empty($passwd) ? $this->makeRandStr() : $passwd, // SS密码为空时生成默认密码
                 'transfer_enable' => $this->toGB($transfer_enable),
-                'enable' => $enable,
-                'method' => $method,
-                'custom_method' => $method,
-                'protocol' => $protocol,
-                'protocol_param' => $protocol_param,
-                'obfs' => $obfs,
-                'obfs_param' => $obfs_param,
-                'gender' => $gender,
-                'wechat' => $wechat,
-                'qq' => $qq,
-                'usage' => $usage,
-                'pay_way' => $pay_way,
-                'balance' => $balance,
-                'score' => $score,
-                'enable_time' => empty($enable_time) ? date('Y-m-d') : $enable_time,
-                'expire_time' => empty($expire_time) ? date('Y-m-d', strtotime("+365 days")) : $expire_time,
-                'remark' => $remark,
-                'level' => $level,
-                'is_admin' => $is_admin,
-                'reg_ip' => $request->getClientIp()
+                'enable'          => $enable,
+                'method'          => $method,
+                'custom_method'   => $method,
+                'protocol'        => $protocol,
+                'protocol_param'  => $protocol_param,
+                'obfs'            => $obfs,
+                'obfs_param'      => $obfs_param,
+                'gender'          => $gender,
+                'wechat'          => $wechat,
+                'qq'              => $qq,
+                'usage'           => $usage,
+                'pay_way'         => $pay_way,
+                'balance'         => 0,
+                'score'           => 0,
+                'enable_time'     => empty($enable_time) ? date('Y-m-d') : $enable_time,
+                'expire_time'     => empty($expire_time) ? date('Y-m-d', strtotime("+365 days")) : $expire_time,
+                'remark'          => $remark,
+                'level'           => $level,
+                'is_admin'        => $is_admin,
+                'reg_ip'          => $request->getClientIp()
             ]);
 
             if ($ret) {
@@ -237,8 +237,6 @@ class AdminController extends Controller
             $qq = $request->get('qq');
             $usage = $request->get('usage');
             $pay_way = $request->get('pay_way');
-            $balance = $request->get('balance');
-            $score = $request->get('score');
             $status = $request->get('status');
             $enable_time = $request->get('enable_time');
             $expire_time = $request->get('expire_time');
@@ -247,32 +245,30 @@ class AdminController extends Controller
             $is_admin = $request->get('is_admin');
 
             $data = [
-                'username' => $username,
-                'port' => $port,
-                'passwd' => $passwd,
-                'transfer_enable' => $this->toGB($transfer_enable),
-                'enable' => $enable,
-                'method' => $method,
-                'custom_method' => $method,
-                'protocol' => $protocol,
-                'protocol_param' => $protocol_param,
-                'obfs' => $obfs,
-                'obfs_param' => $obfs_param,
-                'speed_limit_per_con' => $speed_limit_per_con,
+                'username'             => $username,
+                'port'                 => $port,
+                'passwd'               => $passwd,
+                'transfer_enable'      => $this->toGB($transfer_enable),
+                'enable'               => $status < 0 ? 0 : $enable, // 如果禁止登陆则同时禁用SSR
+                'method'               => $method,
+                'custom_method'        => $method,
+                'protocol'             => $protocol,
+                'protocol_param'       => $protocol_param,
+                'obfs'                 => $obfs,
+                'obfs_param'           => $obfs_param,
+                'speed_limit_per_con'  => $speed_limit_per_con,
                 'speed_limit_per_user' => $speed_limit_per_user,
-                'gender' => $gender,
-                'wechat' => $wechat,
-                'qq' => $qq,
-                'usage' => $usage,
-                'pay_way' => $pay_way,
-                'balance' => $balance,
-                'score' => $score,
-                'status' => $status,
-                'enable_time' => empty($enable_time) ? date('Y-m-d') : $enable_time,
-                'expire_time' => empty($expire_time) ? date('Y-m-d', strtotime("+365 days")) : $expire_time,
-                'remark' => $remark,
-                'level' => $level,
-                'is_admin' => $is_admin
+                'gender'               => $gender,
+                'wechat'               => $wechat,
+                'qq'                   => $qq,
+                'usage'                => $usage,
+                'pay_way'              => $pay_way,
+                'status'               => $status,
+                'enable_time'          => empty($enable_time) ? date('Y-m-d') : $enable_time,
+                'expire_time'          => empty($expire_time) ? date('Y-m-d', strtotime("+365 days")) : $expire_time,
+                'remark'               => $remark,
+                'level'                => $level,
+                'is_admin'             => $is_admin
             ];
 
             if (!empty($password)) {
@@ -289,6 +285,7 @@ class AdminController extends Controller
             $user = User::query()->where('id', $id)->first();
             if (!empty($user)) {
                 $user->transfer_enable = $this->flowToGB($user->transfer_enable);
+                $user->balance = $user->balance / 100;
             }
 
             $view['user'] = $user;
@@ -373,37 +370,37 @@ class AdminController extends Controller
             $status = $request->get('status');
 
             $node = SsNode::query()->create([
-                'name' => $name,
-                'group_id' => $group_id,
-                'country_code' => $country_code,
-                'server' => $server,
-                'desc' => $desc,
-                'method' => $method,
-                'custom_method' => $method,
-                'protocol' => $protocol,
-                'protocol_param' => $protocol_param,
-                'obfs' => $obfs,
-                'obfs_param' => $obfs_param,
-                'traffic_rate' => $traffic_rate,
-                'bandwidth' => $bandwidth,
-                'traffic' => $traffic,
-                'monitor_url' => $monitor_url,
-                'compatible' => $compatible,
-                'single' => $single,
-                'single_force' => $single ? $single_force : 0,
-                'single_port' => $single ? $single_port : '',
-                'single_passwd' => $single ? $single_passwd : '',
-                'single_method' => $single ? $single_method : '',
+                'name'            => $name,
+                'group_id'        => $group_id,
+                'country_code'    => $country_code,
+                'server'          => $server,
+                'desc'            => $desc,
+                'method'          => $method,
+                'custom_method'   => $method,
+                'protocol'        => $protocol,
+                'protocol_param'  => $protocol_param,
+                'obfs'            => $obfs,
+                'obfs_param'      => $obfs_param,
+                'traffic_rate'    => $traffic_rate,
+                'bandwidth'       => $bandwidth,
+                'traffic'         => $traffic,
+                'monitor_url'     => $monitor_url,
+                'compatible'      => $compatible,
+                'single'          => $single,
+                'single_force'    => $single ? $single_force : 0,
+                'single_port'     => $single ? $single_port : '',
+                'single_passwd'   => $single ? $single_passwd : '',
+                'single_method'   => $single ? $single_method : '',
                 'single_protocol' => $single ? $single_protocol : '',
-                'sort' => $sort,
-                'status' => $status,
+                'sort'            => $sort,
+                'status'          => $status,
             ]);
 
             // 建立分组关联
             if ($group_id) {
                 SsGroupNode::query()->create([
                     'group_id' => $group_id,
-                    'node_id' => $node->id
+                    'node_id'  => $node->id
                 ]);
             }
 
@@ -452,30 +449,30 @@ class AdminController extends Controller
             $status = $request->get('status');
 
             $data = [
-                'name' => $name,
-                'group_id' => $group_id,
-                'country_code' => $country_code,
-                'server' => $server,
-                'desc' => $desc,
-                'method' => $method,
-                'custom_method' => $method,
-                'protocol' => $protocol,
-                'protocol_param' => $protocol_param,
-                'obfs' => $obfs,
-                'obfs_param' => $obfs_param,
-                'traffic_rate' => $traffic_rate,
-                'bandwidth' => $bandwidth,
-                'traffic' => $traffic,
-                'monitor_url' => $monitor_url,
-                'compatible' => $compatible,
-                'single' => $single,
-                'single_force' => $single ? $single_force : 0,
-                'single_port' => $single ? $single_port : '',
-                'single_passwd' => $single ? $single_passwd : '',
-                'single_method' => $single ? $single_method : '',
+                'name'            => $name,
+                'group_id'        => $group_id,
+                'country_code'    => $country_code,
+                'server'          => $server,
+                'desc'            => $desc,
+                'method'          => $method,
+                'custom_method'   => $method,
+                'protocol'        => $protocol,
+                'protocol_param'  => $protocol_param,
+                'obfs'            => $obfs,
+                'obfs_param'      => $obfs_param,
+                'traffic_rate'    => $traffic_rate,
+                'bandwidth'       => $bandwidth,
+                'traffic'         => $traffic,
+                'monitor_url'     => $monitor_url,
+                'compatible'      => $compatible,
+                'single'          => $single,
+                'single_force'    => $single ? $single_force : 0,
+                'single_port'     => $single ? $single_port : '',
+                'single_passwd'   => $single ? $single_passwd : '',
+                'single_method'   => $single ? $single_method : '',
                 'single_protocol' => $single ? $single_protocol : '',
-                'sort' => $sort,
-                'status' => $status
+                'sort'            => $sort,
+                'status'          => $status
             ];
 
             $ret = SsNode::query()->where('id', $id)->update($data);
@@ -487,7 +484,7 @@ class AdminController extends Controller
 
                     SsGroupNode::query()->create([
                         'group_id' => $group_id,
-                        'node_id' => $id
+                        'node_id'  => $id
                     ]);
                 }
 
@@ -560,12 +557,12 @@ class AdminController extends Controller
         }
 
         $view['trafficDaily'] = [
-            'nodeName' => $node->name,
+            'nodeName'  => $node->name,
             'dailyData' => "'" . implode("','", $dailyData) . "'"
         ];
 
         $view['trafficHourly'] = [
-            'nodeName' => $node->name,
+            'nodeName'   => $node->name,
             'hourlyData' => "'" . implode("','", $hourlyData) . "'"
         ];
 
@@ -602,12 +599,12 @@ class AdminController extends Controller
             $sort = $request->get('sort');
 
             Article::query()->create([
-                'title' => $title,
-                'type' => $type,
-                'author' => $author,
+                'title'   => $title,
+                'type'    => $type,
+                'author'  => $author,
                 'content' => $content,
-                'is_del' => 0,
-                'sort' => $sort
+                'is_del'  => 0,
+                'sort'    => $sort
             ]);
 
             return Response::json(['status' => 'success', 'data' => '', 'message' => '添加成功']);
@@ -628,11 +625,11 @@ class AdminController extends Controller
             $content = $request->get('content');
 
             $data = [
-                'title' => $title,
-                'type' => $type,
-                'author' => $author,
+                'title'   => $title,
+                'type'    => $type,
+                'author'  => $author,
                 'content' => $content,
-                'sort' => $sort
+                'sort'    => $sort
             ];
 
             $ret = Article::query()->where('id', $id)->update($data);
@@ -683,7 +680,7 @@ class AdminController extends Controller
             $level = $request->get('level');
 
             SsGroup::query()->create([
-                'name' => $name,
+                'name'  => $name,
                 'level' => $level
             ]);
 
@@ -704,7 +701,7 @@ class AdminController extends Controller
             $level = $request->get('level');
 
             $data = [
-                'name' => $name,
+                'name'  => $name,
                 'level' => $level
             ];
 
@@ -856,18 +853,18 @@ class AdminController extends Controller
             $data = [];
             foreach ($content->port_password as $port => $passwd) {
                 $data[] = [
-                    'd' => 0,
-                    'enable' => 1,
-                    'method' => $method,
-                    'obfs' => $obfs,
-                    'obfs_param' => empty($obfs_param) ? "" : $obfs_param,
-                    'passwd' => $passwd,
-                    'port' => $port,
-                    'protocol' => $protocol,
-                    'protocol_param' => empty($protocol_param) ? "" : $protocol_param,
+                    'd'               => 0,
+                    'enable'          => 1,
+                    'method'          => $method,
+                    'obfs'            => $obfs,
+                    'obfs_param'      => empty($obfs_param) ? "" : $obfs_param,
+                    'passwd'          => $passwd,
+                    'port'            => $port,
+                    'protocol'        => $protocol,
+                    'protocol_param'  => empty($protocol_param) ? "" : $protocol_param,
                     'transfer_enable' => $this->toGB($transfer_enable),
-                    'u' => 0,
-                    'user' => date('Ymd') . '_IMPORT_' . $port,
+                    'u'               => 0,
+                    'user'            => date('Ymd') . '_IMPORT_' . $port,
                 ];
             }
 
@@ -1006,19 +1003,19 @@ class AdminController extends Controller
         $nodeList = SsNode::query()->paginate(10)->appends($request->except('page'));
         foreach ($nodeList as &$node) {
             // 生成ssr scheme
-            $obfs_param = $node->single ? '' : base64_encode($user->obfs_param);
-            $protocol_param = $node->single ? base64_encode($user->port . ':' . $user->passwd) : base64_encode($user->protocol_param);
+            $obfs_param = $node->single ? '' : $user->obfs_param;
+            $protocol_param = $node->single ? $user->port . ':' . $user->passwd : $user->protocol_param;
 
             $ssr_str = '';
             $ssr_str .= $node->server . ':' . ($node->single ? $node->single_port : $user->port);
             $ssr_str .= ':' . ($node->single ? $node->single_protocol : $user->protocol) . ':' . ($node->single ? $node->single_method : $user->method);
-            $ssr_str .= ':' . ($node->single ? 'tls1.2_ticket_auth' : $user->obfs) . ':' . ($node->single ? base64_encode($node->single_passwd) : base64_encode($user->passwd));
-            $ssr_str .= '/?obfsparam=' . $obfs_param;
-            $ssr_str .= '&protoparam=' . $protocol_param;
-            $ssr_str .= '&remarks=' . base64_encode($node->name);
-            $ssr_str .= '&group=' . base64_encode('节点');
-            //$ssr_str .= '&udpport=0';
-            //$ssr_str .= '&uot=0';
+            $ssr_str .= ':' . ($node->single ? 'tls1.2_ticket_auth' : $user->obfs) . ':' . ($node->single ? $this->base64url_encode($node->single_passwd) : $this->base64url_encode($user->passwd));
+            $ssr_str .= '/?obfsparam=' . $this->base64url_encode($obfs_param);
+            $ssr_str .= '&protoparam=' . $this->base64url_encode($protocol_param);
+            $ssr_str .= '&remarks=' . $this->base64url_encode($node->name);
+            $ssr_str .= '&group=' . $this->base64url_encode('节点');
+            $ssr_str .= '&udpport=0';
+            $ssr_str .= '&uot=0';
             $ssr_str = $this->base64url_encode($ssr_str);
             $ssr_scheme = 'ssr://' . $ssr_str;
 
@@ -1035,7 +1032,7 @@ class AdminController extends Controller
             $txt .= "密码:" . ($node->single ? $node->single_passwd : $user->passwd) . "\r\n";
             $txt .= "加密方法:" . ($node->single ? $node->single_method : $user->method) . "\r\n";
             $txt .= "协议:" . ($node->single ? $node->single_protocol : $user->protocol) . "\r\n";
-            $txt .= "协议参数:" . ($node->single ? $user->port.':'.$user->passwd : $user->protocol_param) . "\r\n";
+            $txt .= "协议参数:" . ($node->single ? $user->port . ':' . $user->passwd : $user->protocol_param) . "\r\n";
             $txt .= "混淆方式:" . ($node->single ? 'tls1.2_ticket_auth' : $user->obfs) . "\r\n";
             $txt .= "混淆参数:" . ($node->single ? '' : $user->obfs_param) . "\r\n";
             $txt .= "本地端口:1080\r\n路由:绕过局域网及中国大陆地址";
@@ -1122,12 +1119,12 @@ class AdminController extends Controller
             }
 
             $trafficDaily[$node->id] = [
-                'nodeName' => $node->name,
+                'nodeName'  => $node->name,
                 'dailyData' => "'" . implode("','", $dailyData) . "'"
             ];
 
             $trafficHourly[$node->id] = [
-                'nodeName' => $node->name,
+                'nodeName'   => $node->name,
                 'hourlyData' => "'" . implode("','", $hourlyData) . "'"
             ];
         }
@@ -1165,10 +1162,10 @@ class AdminController extends Controller
             }
 
             SsConfig::query()->create([
-                'name' => $name,
-                'type' => $type,
+                'name'       => $name,
+                'type'       => $type,
                 'is_default' => $is_default,
-                'sort' => $sort
+                'sort'       => $sort
             ]);
 
             return Response::json(['status' => 'success', 'data' => '', 'message' => '添加成功']);
@@ -1275,7 +1272,7 @@ class AdminController extends Controller
             }
 
             Level::query()->create([
-                'level' => $level,
+                'level'      => $level,
                 'level_name' => $level_name
             ]);
 
@@ -1560,7 +1557,7 @@ class AdminController extends Controller
     // 邀请码列表
     public function inviteList(Request $request)
     {
-        $view['inviteList'] = Invite::query()->with(['generator', 'user'])->orderBy('id', 'desc')->paginate(10)->appends($request->except('page'));
+        $view['inviteList'] = Invite::query()->with(['generator', 'user'])->orderBy('status', 'asc')->orderBy('id', 'desc')->paginate(10)->appends($request->except('page'));
 
         return Response::view('admin/inviteList', $view);
     }
@@ -1574,7 +1571,7 @@ class AdminController extends Controller
             $obj = new Invite();
             $obj->uid = $user['id'];
             $obj->fuid = 0;
-            $obj->code = strtoupper(substr(md5(microtime() . $this->makeRandStr(6)), 8, 16));
+            $obj->code = strtoupper(substr(md5(microtime() . $this->makeRandStr(6)), 8, 12));
             $obj->status = 0;
             $obj->dateline = date('Y-m-d H:i:s', strtotime("+ 7days"));
             $obj->save();
@@ -1583,6 +1580,29 @@ class AdminController extends Controller
         return Response::json(['status' => 'success', 'data' => '', 'message' => '生成成功']);
     }
 
+    // 导出邀请码
+    public function exportInvite(Request $request)
+    {
+        $inviteList = Invite::query()->where('status', 0)->orderBy('id', 'asc')->get();
+
+        $filename = '邀请码' . date('Ymd');
+        Excel::create($filename, function($excel) use($inviteList) {
+            $excel->sheet('邀请码', function($sheet) use($inviteList) {
+                $sheet->row(1, array(
+                    '邀请码', '有效期'
+                ));
+
+                if (!$inviteList->isEmpty()) {
+                    foreach ($inviteList as $k => $vo) {
+                        $sheet->row($k + 2, array(
+                            $vo->code, $vo->dateline
+                        ));
+                    }
+                }
+            });
+        })->export('xls');
+    }
+
     // 提现申请列表
     public function applyList(Request $request)
     {
@@ -1600,6 +1620,12 @@ class AdminController extends Controller
         }
 
         $list = $query->orderBy('id', 'desc')->paginate(10)->appends($request->except('page'));
+        if (!empty($list)) {
+            foreach ($list as $vo) {
+                $vo->amount = $vo->amount / 100;
+            }
+        }
+
         $view['applyList'] = $list;
 
         return Response::view('admin/applyList', $view);
@@ -1613,12 +1639,15 @@ class AdminController extends Controller
         $list = [];
         $apply = ReferralApply::query()->where('id', $id)->with('user')->first();
         if ($apply && $apply->link_logs) {
+            $apply->amount = $apply->amount / 100;
             $link_logs = explode(',', $apply->link_logs);
             $list = ReferralLog::query()->whereIn('id', $link_logs)->with('user')->paginate(10);
         }
 
         foreach ($list as &$vo) {
             $vo->goods = OrderGoods::query()->where('oid', $vo->order_id)->with('goods')->first();
+            $vo->amount = $vo->amount / 100;
+            $vo->ref_amount = $vo->ref_amount / 100;
         }
 
         $view['info'] = $apply;
@@ -1658,6 +1687,7 @@ class AdminController extends Controller
         return Response::json(['status' => 'success', 'data' => '', 'message' => '操作成功']);
     }
 
+
     /**
      * 以某用户登录
      * @param  Request $req 请求
@@ -1674,3 +1704,74 @@ class AdminController extends Controller
         return ['errcode'=>0,'errmsg'=>"成功!"];
     }
 }
+
+    // 操作用户余额
+    public function handleUserBalance(Request $request)
+    {
+        if ($request->method() == 'POST') {
+            $user_id = $request->get('user_id');
+            $amount = $request->get('amount');
+
+            if (empty($user_id) || empty($amount)) {
+                return Response::json(['status' => 'fail', 'data' => '', 'message' => '充值异常']);
+            }
+
+            try {
+                $user = User::query()->where('id', $user_id)->first();
+                $amount = $amount * 100;
+
+                // 写入余额变动日志
+                $userBalanceLog = new UserBalanceLog();
+                $userBalanceLog->user_id = $user_id;
+                $userBalanceLog->order_id = 0;
+                $userBalanceLog->before = $user->balance;
+                $userBalanceLog->after = $user->balance + $amount;
+                $userBalanceLog->amount = $amount;
+                $userBalanceLog->desc = '后台手动充值';
+                $userBalanceLog->created_at = date('Y-m-d H:i:s');
+                $userBalanceLog->save();
+
+                // 加减余额
+                if ($amount < 0) {
+                    $user->decrement('balance', abs($amount));
+                } else {
+                    $user->increment('balance', abs($amount));
+                }
+
+                return Response::json(['status' => 'success', 'data' => '', 'message' => '充值成功']);
+            } catch (\Exception $e) {
+                return Response::json(['status' => 'fail', 'data' => '', 'message' => '充值失败:' . $e->getMessage()]);
+            }
+        } else {
+            return Response::view('admin/handleUserBalance');
+        }
+    }
+
+    // 用户余额变动日志
+    public function userBalanceLogList(Request $request)
+    {
+        $username = trim($request->get('username'));
+
+        $query = UserBalanceLog::query()->with(['user'])->orderBy('id', 'desc');
+
+        if ($username) {
+            $query->whereHas('user', function ($q) use ($username) {
+                $q->where('username', 'like', '%' . $username . '%');
+            });
+        }
+
+        $list = $query->paginate(10);
+        if (!empty($list)) {
+            foreach ($list as &$vo) {
+                $vo->before = $vo->before / 100;
+                $vo->after = $vo->after / 100;
+                $vo->amount = $vo->amount / 100;
+            }
+        }
+
+        $view['list'] = $list;
+
+        return Response::view('admin/userBalanceLogList', $view);
+    }
+}
+

+ 7 - 2
app/Http/Controllers/CouponController.php

@@ -27,7 +27,12 @@ class CouponController extends Controller
     // 优惠券列表
     public function couponList(Request $request)
     {
-        $view['couponList'] = Coupon::query()->where('is_del', 0)->orderBy('id', 'desc')->paginate(10);
+        $couponList = Coupon::query()->where('is_del', 0)->orderBy('id', 'desc')->paginate(10);
+        foreach ($couponList as $coupon) {
+            $coupon->amount = $coupon->amount / 100;
+        }
+
+        $view['couponList'] = $couponList;
 
         return Response::view('coupon/couponList', $view);
     }
@@ -76,7 +81,7 @@ class CouponController extends Controller
                     $obj->logo = $logo;
                     $obj->type = $type;
                     $obj->usage = $usage;
-                    $obj->amount = empty($amount) ? 0 : $amount;
+                    $obj->amount = empty($amount) ? 0 : $amount * 100;
                     $obj->discount = empty($discount) ? 0 : $discount / 10;
                     $obj->available_start = strtotime(date('Y-m-d 0:0:0', strtotime($available_start)));
                     $obj->available_end = strtotime(date('Y-m-d 23:59:59', strtotime($available_end)));

+ 21 - 0
app/Http/Controllers/DonateController.php

@@ -0,0 +1,21 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use Illuminate\Http\Request;
+use Response;
+
+class DonateController extends BaseController
+{
+    protected static $config;
+
+    function __construct()
+    {
+        self::$config = $this->systemConfig();
+    }
+
+    public function donate(Request $request)
+    {
+        return Response::view('admin/donate');
+    }
+}

+ 13 - 0
app/Http/Controllers/RegisterController.php

@@ -38,8 +38,19 @@ class RegisterController extends Controller
             $repassword = trim($request->get('repassword'));
             $captcha = trim($request->get('captcha'));
             $code = trim($request->get('code'));
+            $register_token = $request->get('register_token');
             $aff = intval($request->get('aff', 0));
 
+            // 预防重复提交
+            $session_register_token = $request->session()->get('register_token');
+            if (empty($register_token) || $register_token != $session_register_token) {
+                $request->session()->flash('errorMsg', '请勿重复请求,刷新一下页面再试试');
+
+                return Redirect::back()->withInput();
+            } else {
+                $request->session()->forget('register_token');
+            }
+
             if (empty($username)) {
                 $request->session()->flash('errorMsg', '请输入用户名');
 
@@ -174,6 +185,8 @@ class RegisterController extends Controller
 
             return Redirect::to('login');
         } else {
+            $request->session()->put('register_token', $this->makeRandStr(16));
+
             $view['is_captcha'] = self::$config['is_captcha'];
             $view['is_register'] = self::$config['is_register'];
             $view['is_invite_register'] = self::$config['is_invite_register'];

+ 14 - 4
app/Http/Controllers/ShopController.php

@@ -24,7 +24,12 @@ class ShopController extends Controller
     // 商品列表
     public function goodsList(Request $request)
     {
-        $view['goodsList'] = Goods::query()->where('is_del', 0)->orderBy('id', 'desc')->paginate(10);
+        $goodsList = Goods::query()->where('is_del', 0)->orderBy('id', 'desc')->paginate(10);
+        foreach ($goodsList as $goods) {
+            $goods->price = $goods->price / 100;
+        }
+
+        $view['goodsList'] = $goodsList;
 
         return Response::view('shop/goodsList', $view);
     }
@@ -63,7 +68,7 @@ class ShopController extends Controller
             $obj->desc = $desc;
             $obj->logo = $logo;
             $obj->traffic = $traffic;
-            $obj->price = $price;
+            $obj->price = $price * 100; // 单位分
             $obj->score = $score;
             $obj->type = $type;
             $obj->days = $days;
@@ -118,7 +123,7 @@ class ShopController extends Controller
                 'desc'    => $desc,
                 'logo'    => $logo,
                 'traffic' => $traffic,
-                'price'   => $price,
+                'price'   => $price * 100, // 单位分
                 'score'   => $score,
                 'type'    => $type,
                 'days'    => $days,
@@ -133,7 +138,12 @@ class ShopController extends Controller
 
             return Redirect::to('shop/editGoods?id=' . $id);
         } else {
-            $view['goods'] = Goods::query()->where('id', $id)->first();
+            $goods = Goods::query()->where('id', $id)->first();
+            if (!empty($goods)) {
+                $goods->price = $goods->price / 100;
+            }
+
+            $view['goods'] = $goods;
 
             return Response::view('shop/editGoods', $view);
         }

+ 9 - 7
app/Http/Controllers/SubscribeController.php

@@ -64,18 +64,20 @@ class SubscribeController extends Controller
         $nodeList = SsNode::query()->where('status', 1)->whereIn('id', $node_ids)->get();
         $scheme = self::$config['subscribe_max'] > 0 ? 'MAX=' . self::$config['subscribe_max'] . "\n" : '';
         foreach ($nodeList as $node) {
-            $obfs_param = $node->single ? '' : base64_encode($user->obfs_param);
-            $protocol_param = $node->single ? base64_encode($user->port . ':' . $user->passwd) : base64_encode($user->protocol_param);
+            $obfs_param = $node->single ? '' : $user->obfs_param;
+            $protocol_param = $node->single ? $user->port . ':' . $user->passwd : $user->protocol_param;
 
             // 生成ssr scheme
             $ssr_str = '';
             $ssr_str .= $node->server . ':' . ($node->single ? $node->single_port : $user->port);
             $ssr_str .= ':' . ($node->single ? $node->single_protocol : $user->protocol) . ':' . ($node->single ? $node->single_method : $user->method);
-            $ssr_str .= ':' . ($node->single ? 'tls1.2_ticket_auth' : $user->obfs) . ':' . base64_encode($user->passwd);
-            $ssr_str .= '/?obfsparam=' . $obfs_param;
-            $ssr_str .= '&protoparam=' . $protocol_param;
-            $ssr_str .= '&remarks=' . base64_encode($node->name);
-            $ssr_str .= '&group=' . base64_encode('VPN');
+            $ssr_str .= ':' . ($node->single ? 'tls1.2_ticket_auth' : $user->obfs) . ':' . $this->base64url_encode($user->passwd);
+            $ssr_str .= '/?obfsparam=' . $this->base64url_encode($obfs_param);
+            $ssr_str .= '&protoparam=' . $this->base64url_encode($protocol_param);
+            $ssr_str .= '&remarks=' . $this->base64url_encode($node->name);
+            $ssr_str .= '&group=' . $this->base64url_encode('VPN');
+            $ssr_str .= '&udpport=0';
+            $ssr_str .= '&uot=0';
             $ssr_str = $this->base64url_encode($ssr_str);
             $scheme .= 'ssr://' . $ssr_str . "\n";
         }

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

@@ -50,6 +50,7 @@ class UserController extends Controller
         $user->usedTransfer = $this->flowAutoShow($user->u + $user->d);
         $user->usedPercent = $user->transfer_enable > 0 ? round(($user->u + $user->d) / $user->transfer_enable, 2) : 1;
         $user->levelName = Level::query()->where('level', $user['level'])->first()['level_name'];
+        $user->balance = $user->balance / 100;
         $view['info'] = $user->toArray();
         $view['notice'] = Article::query()->where('type', 2)->where('is_del', 0)->orderBy('id', 'desc')->first();
         $view['articleList'] = Article::query()->where('type', 1)->where('is_del', 0)->orderBy('sort', 'desc')->orderBy('id', 'desc')->paginate(5);
@@ -73,19 +74,19 @@ class UserController extends Controller
 
         foreach ($nodeList as &$node) {
             // 生成ssr scheme
-            $obfs_param = $node->single ? '' : base64_encode($user->obfs_param);
-            $protocol_param = $node->single ? base64_encode($user->port . ':' . $user->passwd) : base64_encode($user->protocol_param);
+            $obfs_param = $node->single ? '' : $user->obfs_param;
+            $protocol_param = $node->single ? $user->port . ':' . $user->passwd : $user->protocol_param;
 
             $ssr_str = '';
             $ssr_str .= $node->server . ':' . ($node->single ? $node->single_port : $user->port);
             $ssr_str .= ':' . ($node->single ? $node->single_protocol : $user->protocol) . ':' . ($node->single ? $node->single_method : $user->method);
-            $ssr_str .= ':' . ($node->single ? 'tls1.2_ticket_auth' : $user->obfs) . ':' . ($node->single ? base64_encode($node->single_passwd) : base64_encode($user->passwd));
-            $ssr_str .= '/?obfsparam=' . $obfs_param;
-            $ssr_str .= '&protoparam=' . $protocol_param;
-            $ssr_str .= '&remarks=' . base64_encode($node->name);
-            $ssr_str .= '&group=' . base64_encode('节点');
-            //$ssr_str .= '&udpport=0';
-            //$ssr_str .= '&uot=0';
+            $ssr_str .= ':' . ($node->single ? 'tls1.2_ticket_auth' : $user->obfs) . ':' . ($node->single ? $this->base64url_encode($node->single_passwd) : $this->base64url_encode($user->passwd));
+            $ssr_str .= '/?obfsparam=' . $this->base64url_encode($obfs_param);
+            $ssr_str .= '&protoparam=' . $this->base64url_encode($protocol_param);
+            $ssr_str .= '&remarks=' . $this->base64url_encode($node->name);
+            $ssr_str .= '&group=' . $this->base64url_encode('节点');
+            $ssr_str .= '&udpport=0';
+            $ssr_str .= '&uot=0';
             $ssr_str = $this->base64url_encode($ssr_str);
             $ssr_scheme = 'ssr://' . $ssr_str;
 
@@ -249,7 +250,13 @@ class UserController extends Controller
     // 商品列表
     public function goodsList(Request $request)
     {
-        $view['goodsList'] = Goods::query()->where('status', 1)->where('is_del', 0)->paginate(10)->appends($request->except('page'));
+        $goodsList = Goods::query()->where('status', 1)->where('is_del', 0)->paginate(10)->appends($request->except('page'));
+        foreach ($goodsList as $goods) {
+            $goods->price = $goods->price / 100;
+            $goods->traffic = $this->flowAutoShow($goods->traffic * 1048576);
+        }
+
+        $view['goodsList'] = $goodsList;
 
         return Response::view('user/goodsList', $view);
     }
@@ -275,6 +282,7 @@ class UserController extends Controller
                 foreach ($order->goodsList as &$goods) {
                     $g = Goods::query()->where('id', $goods->goods_id)->first();
                     $goods->goods_name = empty($g) ? '【该商品已删除】' : $g->name;
+                    $goods->price = $goods->price / 100;
                 }
             }
         }
@@ -363,7 +371,7 @@ class UserController extends Controller
 
         // 已生成的邀请码数量
         $num = Invite::query()->where('uid', $user['id'])->count();
-
+        
         $view['num'] = self::$config['invite_num'] - $num <= 0 ? 0 : self::$config['invite_num'] - $num; // 还可以生成的邀请码数量
         $view['inviteList'] = Invite::query()->where('uid', $user['id'])->with(['generator', 'user'])->paginate(10); // 邀请码列表
 
@@ -681,7 +689,7 @@ class UserController extends Controller
 
         $data = [
             'type'     => $coupon->type,
-            'amount'   => $coupon->amount,
+            'amount'   => $coupon->amount / 100,
             'discount' => $coupon->discount
         ];
 
@@ -761,8 +769,8 @@ class UserController extends Controller
                 $userBalanceLogObj->order_id = $order->oid;
                 $userBalanceLogObj->before = $user->balance;
                 $userBalanceLogObj->after = $user->balance - $totalPrice;
-                $userBalanceLogObj->balance = $totalPrice;
-                $userBalanceLogObj->desc = '购买流量包';
+                $userBalanceLogObj->amount = -1 * $totalPrice;
+                $userBalanceLogObj->desc = '购买服务:' . $goods->name;
                 $userBalanceLogObj->created_at = date('Y-m-d H:i:s');
                 $userBalanceLogObj->save();
 
@@ -784,8 +792,9 @@ class UserController extends Controller
                 // 把商品的流量加到账号上
                 User::query()->where('id', $user['id'])->increment('transfer_enable', $goods->traffic * 1048576);
 
-                // 将商品的有效期加到账号上
-                User::query()->where('id', $user['id'])->update(['expire_time' => date('Y-m-d H:i:s', strtotime("+" . $goods->days . " days")), 'enable' => 1]);
+                // 将商品的有效期和流量自动重置日期加到账号上
+                $traffic_reset_day = $goods->type == 2 ? (in_array(date('d'), [29, 30, 31]) ? 28 : abs(date('d'))) : 0;
+                User::query()->where('id', $user['id'])->update(['traffic_reset_day' => $traffic_reset_day, 'expire_time' => date('Y-m-d H:i:s', strtotime("+" . $goods->days . " days")), 'enable' => 1]);
 
                 // 写入返利日志
                 if ($user->referral_uid) {
@@ -815,6 +824,8 @@ class UserController extends Controller
                 return Redirect::to('user/goodsList');
             }
 
+            $goods->price = $goods->price / 100;
+            $goods->traffic = $this->flowAutoShow($goods->traffic * 1048576);
             $view['goods'] = $goods;
 
             return Response::view('user/addOrder', $view);
@@ -873,11 +884,19 @@ class UserController extends Controller
         $view['referral_traffic'] = $this->flowAutoShow(self::$config['referral_traffic'] * 1048576);
         $view['referral_percent'] = self::$config['referral_percent'];
         $view['referral_money'] = self::$config['referral_money'];
-        $view['referralLogList'] = ReferralLog::query()->where('ref_user_id', $user['id'])->with('user')->paginate();
-        $view['totalAmount'] = ReferralLog::query()->where('ref_user_id', $user['id'])->sum('ref_amount');
-        $view['canAmount'] = ReferralLog::query()->where('ref_user_id', $user['id'])->where('status', 0)->sum('ref_amount');
+        $view['totalAmount'] = ReferralLog::query()->where('ref_user_id', $user['id'])->sum('ref_amount') / 100;
+        $view['canAmount'] = ReferralLog::query()->where('ref_user_id', $user['id'])->where('status', 0)->sum('ref_amount') / 100;
         $view['link'] = self::$config['website_url'] . '/register?aff=' . $user['id'];
 
+        $referralLogList = ReferralLog::query()->where('ref_user_id', $user['id'])->with('user')->paginate(10);
+        if (!empty($referralLogList)) {
+            foreach ($referralLogList as &$referral) {
+                $referral->amount = $referral->amount / 100;
+                $referral->ref_amount = $referral->ref_amount / 100;
+            }
+        }
+        $view['referralLogList'] = $referralLogList;
+
         return Response::view('user/referral', $view);
     }
 
@@ -894,7 +913,7 @@ class UserController extends Controller
 
         // 校验可以提现金额是否超过系统设置的阀值
         $ref_amount = ReferralLog::query()->where('ref_user_id', $user['id'])->where('status', 0)->sum('ref_amount');
-        if ($ref_amount < self::$config['referral_money']) {
+        if ($ref_amount / 100 < self::$config['referral_money']) {
             return Response::json(['status' => 'fail', 'data' => '', 'message' => '申请失败:满' . self::$config['referral_money'] . '元才可以提现,继续努力吧']);
         }
 

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

@@ -24,6 +24,10 @@ class OrderGoods extends Model
         'is_expire'
     ];
 
+    function user() {
+        return $this->hasOne(User::class, 'id', 'user_id');
+    }
+
     function goods() {
         return $this->hasOne(Goods::class, 'id', 'goods_id');
     }

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

@@ -13,6 +13,7 @@ class SsNodeInfo extends Model
 {
     protected $table = 'ss_node_info';
     protected $primaryKey = 'id';
+    public $timestamps = false;
     protected $fillable = [
         'node_id',
         'uptime',

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

@@ -13,6 +13,7 @@ class SsNodeOnlineLog extends Model
 {
     protected $table = 'ss_node_online_log';
     protected $primaryKey = 'id';
+    public $timestamps = false;
     protected $fillable = [
         'node_id',
         'online_user',

binární
public/assets/images/country/be.png


binární
public/assets/images/country/bg.png


binární
public/assets/images/country/co.png


binární
public/assets/images/country/fi.png


binární
public/assets/images/country/is.png


binární
public/assets/images/country/ke.png


binární
public/assets/images/country/lt.png


binární
public/assets/images/country/lu.png


binární
public/assets/images/country/mm.png


binární
public/assets/images/country/mo.png


binární
public/assets/images/country/za.png


binární
public/assets/images/donate.jpeg


+ 67 - 27
readme.md

@@ -1,3 +1,10 @@
+## 演示站(已挂)
+````
+http://www.ssrpanel.com
+用户名:admin
+密码:123456
+````
+
 ## 安装步骤
 #### 环境要求
 ````
@@ -16,17 +23,10 @@ PHP必须开启gd、fileinfo组件
 telegram频道:https://t.me/ssrpanel
 telegram群组:https://t.me/chatssrpanel
 本人未实名微信小号:dxstx77 (请勿任何转账、红包行为)
-严禁在TG群里喧哗,只聊VPS、技术不扯淡,更别刷屏惹众怒,否则踢3天,两次机会,第三次被踢你永远进不来,我都记得谁谁谁
-````
-
-## 演示站(已挂,求打赏)
-````
-http://www.ssrpanel.com
-用户名:admin
-密码:123456
+严禁在TG群里喧哗、谈论政治、发色情信息,只聊技术不扯淡,更别刷屏惹众怒,否则踢3天,两次机会,第三次被踢你永远进不来,我都记得谁谁谁
 ````
 
-![VPS推荐](https://github.com/ssrpanel/ssrpanel/wiki/VPS%E6%8E%A8%E8%8D%90)
+[VPS推荐](https://github.com/ssrpanel/ssrpanel/wiki/VPS%E6%8E%A8%E8%8D%90)
 ````
 部署面板必须得用到VPS
 强烈推荐使用1G以上内存的KVM架构的VPS
@@ -42,7 +42,7 @@ http://www.ssrpanel.com
 ````
 ![打赏作者](https://github.com/ssrpanel/ssrpanel/blob/master/public/assets/images/donate.jpeg?raw=true)
 
-### 打赏名单
+#### 打赏名单
 |昵称|金额|
 |:-------|--------:| 
 |Law-杰|¥10| 
@@ -56,7 +56,7 @@ http://www.ssrpanel.com
 |Royal|¥25|
 |bingo|¥8|
 |Eason|¥10|
-|【要求匿名】|¥150|
+|【要求匿名】|¥270|
 |暮风|¥20|
 |huigeer|¥10|
 |真想悠哉|¥88|
@@ -67,6 +67,8 @@ http://www.ssrpanel.com
 |Sherl|¥48|
 |小孑、|¥20|
 |曾健|¥10|
+|Lojbk|¥10|
+|Denny Wei|¥100|
 
 
 这些捐赠的用途:
@@ -88,7 +90,7 @@ mysql 创建一个数据库,然后自行导入sql\db.sql
 config\database.php 中的mysql选项自行配置数据库
 ````
 
-#### 配置一下
+#### 其次配置一下运行环境
 ````
 cd ssrpanel/
 php composer.phar install
@@ -97,7 +99,7 @@ chown -R www:www storage/
 chmod -R 777 storage/
 ````
 
-#### NGINX配置文件加入
+#### 然后NGINX配置文件加入
 ````
 location / {
     try_files $uri $uri/ /index.php$is_args$args;
@@ -131,16 +133,44 @@ service php-fpm restart
 编辑crontab
 crontab -e
 
-然后加入如下(请自行修改ssrpanel路径)
+然后加入如下(请自行修改ssrpanel路径):
+(表示每分钟都执行定时任务,具体什么任务什么时候执行程序里已经定义了,请不要乱改,否则流量统计数据可能出错)
 * * * * * php /home/wwwroot/ssrpanel/artisan schedule:run >> /dev/null 2>&1
 ````
 
-#### 发送邮件配置
+## 邮件配置
+###### SMTP
 ````
-config\mail.php 修改其中的配置
+编辑 config\mail.php
+
+请自行配置如下内容
+'driver' => 'smtp',
+'host' => 'smtp.exmail.qq.com',
+'port' => 465,
+'from' => [
+    'address' => '[email protected]',
+    'name' => 'SSRPanel',
+],
+'encryption' => 'ssl',
+'username' => '[email protected]',
+'password' => 'xxxxxx',
+````
+
+###### Mailgun
+````
+编辑 config\mail.php
+将 driver 值改为 mailgun
+
+编辑 config/services.php
+
+请自行配置如下内容
+'mailgun' => [
+    'domain' => 'mailgun发件域名',
+    'secret' => 'mailgun上申请到的secret',
+],
 ````
 
-## 日志分析(目前仅支持单机单节点)
+## 日志分析(仅支持单机单节点)
 ````
 找到SSR服务端所在的ssserver.log文件
 进入ssrpanel所在目录,建立一个软连接,并授权
@@ -177,7 +207,6 @@ chmod a+x fix_git.sh && sh fix_git.sh
 
 如果本地自行改了文件,想用回原版代码,请先备份好 config/database.php,然后执行以下命令:
 chmod a+x update.sh && sh update.sh
-
 ````
 
 ## 网卡流量监控一键脚本
@@ -237,15 +266,26 @@ vim user-config.json
 
 ````
 
-## 致敬
+## 校时
 ````
-@breakwa11
-@glzjin
-@orvice
-@ToyoDAdoubi
-@91yun
+如果架构是“一面板机-一数据库机-多节点机”,请务必保持各个服务器之间的时间一致,否则会影响节点在线数的准确性和单端口多用户功能的正常使用。
+推荐统一使用CST时间并安装校时服务:
+vim /etc/sysconfig/clock 把值改为 Asia/Shanghai
+cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
+
+重启一下服务器,然后:
+yum install ntp
+ntpdate cn.pool.ntp.org
 ````
 
+## 致敬
+- [@breakwa11](https://github.com/breakwa11)
+- [@glzjin](https://github.com/esdeathlove)
+- [@orvice](https://github.com/orvice)
+- [@ToyoDAdoubi](https://github.com/ToyoDAdoubi)
+- [@91yun](https://github.com/91yun)
+- [@Akkariiin](https://github.com/shadowsocksrr)
+
 ## 说明
 ````
 1.多节点账号管理面板
@@ -254,17 +294,17 @@ vim user-config.json
 4.内含简单的购物、优惠券、流量兑换、邀请码、推广返利&提现、文章管理、工单等模块
 5.节点支持分组,不同级别的用户可以看到不同级别分组的节点
 6.SS配置转SSR配置,轻松一键导入SS账号
-7.流量日志、单机单节点日志分析功能,知道用户最近都看了哪些网站
+7.流量日志、单机单节点日志分析功能
 8.强大的定时任务
 9.所有邮件投递都有记录
-10.账号临近到期、流量不够都会自动发邮件提醒,自动禁用到期、流量异常的账号
+10.账号临近到期、流量不够都会自动发邮件提醒,自动禁用到期、流量异常的账号,自动清除日志
 11.后台一键添加加密方式、混淆、协议、等级
 12.强大的后台一键配置功能
 13.屏蔽常见爬虫
 14.支持单端口多用户
 15.账号、节点24小时和近30天内的流量监控
 16.支持节点订阅功能,可一键封禁账号订阅地址
-17.引入serverStatus,可以在线实时查看节点的实时流量信息
+17.美观的国家图标
 ````
 
 ## 预览

+ 1 - 15
resources/views/admin/addUser.blade.php

@@ -106,18 +106,6 @@
                                                     </select>
                                                 </div>
                                             </div>
-                                            <div class="form-group">
-                                                <label for="balance" class="col-md-3 control-label">余额</label>
-                                                <div class="col-md-8">
-                                                    <input type="text" class="form-control" name="balance" value="0" id="balance" placeholder="" required>
-                                                </div>
-                                            </div>
-                                            <div class="form-group">
-                                                <label for="score" class="col-md-3 control-label">积分</label>
-                                                <div class="col-md-8">
-                                                    <input type="text" class="form-control" name="score" value="0" id="score" placeholder="" required>
-                                                </div>
-                                            </div>
                                             <div class="form-group">
                                                 <label class="col-md-3 control-label">有效期</label>
                                                 <div class="col-md-8">
@@ -327,8 +315,6 @@
             var password = $('#password').val();
             var usage = $("input:radio[name='usage']:checked").val();
             var pay_way = $("input:radio[name='pay_way']:checked").val();
-            var balance = $('#balance').val();
-            var score = $('#score').val();
             var enable_time = $('#enable_time').val();
             var expire_time = $('#expire_time').val();
             var gender = $('#gender').val();
@@ -354,7 +340,7 @@
                 type: "POST",
                 url: "{{url('admin/addUser')}}",
                 async: false,
-                data: {_token:_token, username: username, password:password, usage:usage, pay_way:pay_way, balance:balance, score:score, enable_time:enable_time, expire_time:expire_time, gender:gender, wechat:wechat, qq:qq, is_admin:is_admin, remark:remark, level:level, port:port, passwd:passwd, method:method, custom_method:custom_method, transfer_enable:transfer_enable, enable:enable, protocol:protocol, protocol_param:protocol_param, obfs:obfs, obfs_param:obfs_param, speed_limit_per_con:speed_limit_per_con, speed_limit_per_user:speed_limit_per_user},
+                data: {_token:_token, username: username, password:password, usage:usage, pay_way:pay_way, enable_time:enable_time, expire_time:expire_time, gender:gender, wechat:wechat, qq:qq, is_admin:is_admin, remark:remark, level:level, port:port, passwd:passwd, method:method, custom_method:custom_method, transfer_enable:transfer_enable, enable:enable, protocol:protocol, protocol_param:protocol_param, obfs:obfs, obfs_param:obfs_param, speed_limit_per_con:speed_limit_per_con, speed_limit_per_user:speed_limit_per_user},
                 dataType: 'json',
                 success: function (ret) {
                     layer.msg(ret.message, {time:1000}, function() {

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

@@ -89,7 +89,7 @@
                         </div>
                         <div class="row">
                             <div class="col-md-4 col-sm-4">
-                                <div class="dataTables_info" role="status" aria-live="polite">共 {{$list->total()}} 个申请</div>
+                                <div class="dataTables_info" role="status" aria-live="polite">本申请共涉及 {{$list->total()}} 单</div>
                             </div>
                             <div class="col-md-8 col-sm-8">
                                 <div class="dataTables_paginate paging_bootstrap_full_number pull-right">

+ 34 - 0
resources/views/admin/donate.blade.php

@@ -0,0 +1,34 @@
+@extends('admin.layouts')
+
+@section('css')
+    <link href="/assets/global/plugins/bootstrap-datepicker/css/bootstrap-datepicker3.min.css" rel="stylesheet" type="text/css" />
+@endsection
+@section('title', '控制面板')
+@section('content')
+    <!-- BEGIN CONTENT BODY -->
+    <div class="page-content">
+        <!-- BEGIN PAGE BASE CONTENT -->
+        <div class="row">
+            <div class="col-md-12">
+                <div class="portlet light bordered">
+                    <div class="portlet-body">
+                        <div class="row">
+                            <p>本程序免费、开源、无版权,要是觉得还不错,请打赏一下支持作者持续开发</p>
+                            <p>感恩的心,感谢有你</p>
+                            <p>Telegram频道:<a href="" target="_blank">https://t.me/ssrpanel</a></p>
+                            <p>Telegram群组:<a href="" target="_blank">https://t.me/chatssrpanel</a></p>
+                            <a href="https://github.com/ssrpanel/ssrpanel" target="_blank"><img src="{{asset('assets/images/donate.jpeg')}}" /></a>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <!-- END PAGE BASE CONTENT -->
+    </div>
+    <!-- END CONTENT BODY -->
+@endsection
+@section('script')
+    <script type="text/javascript">
+        //
+    </script>
+@endsection

+ 85 - 4
resources/views/admin/editUser.blade.php

@@ -114,16 +114,28 @@
                                             </div>
                                             <div class="form-group">
                                                 <label for="balance" class="col-md-3 control-label">余额</label>
-                                                <div class="col-md-8">
-                                                    <input type="text" class="form-control" name="balance" value="{{$user->balance}}" id="balance" placeholder="" required>
+                                                <div class="col-md-5">
+                                                    <p class="form-control-static"> {{$user->balance}} </p>
+                                                </div>
+                                                <div class="col-md-3">
+                                                    <div style="float:right;">
+                                                        <button type="button" class="btn btn-sm btn-danger" data-toggle="modal" data-target="#handle_user_balance">充值</button>
+                                                    </div>
                                                 </div>
                                             </div>
+                                            <!--
                                             <div class="form-group">
                                                 <label for="score" class="col-md-3 control-label">积分</label>
-                                                <div class="col-md-8">
-                                                    <input type="text" class="form-control" name="score" value="{{$user->score}}" id="score" placeholder="" required>
+                                                <div class="col-md-5">
+                                                    <p class="form-control-static"> {{$user->score}} </p>
+                                                </div>
+                                                <div class="col-md-3">
+                                                    <div style="float:right;">
+                                                        <button type="button" class="btn btn-sm btn-danger">操作</button>
+                                                    </div>
                                                 </div>
                                             </div>
+                                            -->
                                             <div class="form-group">
                                                 <label class="col-md-3 control-label">有效期</label>
                                                 <div class="col-md-8">
@@ -312,6 +324,37 @@
                     <!-- END FORM-->
                 </div>
             </div>
+
+            <!-- 余额充值 -->
+            <div id="handle_user_balance" class="modal fade" tabindex="-1" data-focus-on="input:first" data-backdrop="static" data-keyboard="false">
+                <div class="modal-dialog" style="width:300px;">
+                    <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="alert alert-danger" style="display: none;" id="msg"></div>
+                            <!-- BEGIN FORM-->
+                            <form action="#" method="post" class="form-horizontal">
+                                <div class="form-body">
+                                    <div class="form-group">
+                                        <label for="amount" class="col-md-4 control-label"> 充值金额 </label>
+                                        <div class="col-md-8">
+                                            <input type="text" class="form-control" name="amount" id="amount" placeholder="填入负值则会扣余额" onkeydown="if(event.keyCode==13){return false;}">
+                                        </div>
+                                    </div>
+                                </div>
+                            </form>
+                            <!-- END FORM-->
+                        </div>
+                        <div class="modal-footer">
+                            <button type="button" data-dismiss="modal" class="btn dark btn-outline">关闭</button>
+                            <button type="button" class="btn red btn-outline" onclick="return handleUserBalance();">充值</button>
+                        </div>
+                    </div>
+                </div>
+            </div>
         </div>
         <!-- END PAGE BASE CONTENT -->
     </div>
@@ -411,5 +454,43 @@
                 $("#passwd").val(ret);
             });
         }
+
+        // 余额充值
+        function handleUserBalance() {
+            var amount = $("#amount").val();
+            var reg = /^(\-?)\d+(\.\d+)?$/; //只可以是正负数字
+
+            if (amount == '' || amount == 0 || !reg.test(amount)) {
+                $("#msg").show().html("请输入充值金额");
+                $("#name").focus();
+                return false;
+            }
+
+            $.ajax({
+                url:'{{url('admin/handleUserBalance')}}',
+                type:"POST",
+                data:{_token:'{{csrf_token()}}', user_id:'{{Request::get('id')}}', amount:amount},
+                beforeSend:function(){
+                    $("#msg").show().html("充值中...");
+                },
+                success:function(ret){
+                    if (ret.status == 'fail') {
+                        $("#msg").show().html(ret.message);
+                        return false;
+                    } else {
+                        layer.msg(ret.message, {time:1000}, function() {
+                            if (ret.status == 'success') {
+                                $("#handle_user_balance").modal("hide");
+                                window.location.reload();
+                            }
+                        });
+                    }
+                },
+                error:function(){
+                    $("#msg").show().html("请求错误,请重试");
+                },
+                complete:function(){}
+            });
+        }
     </script>
 @endsection

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

@@ -40,8 +40,8 @@
                         <form action="{{url('admin/import')}}" method="post" enctype="multipart/form-data" class="form-horizontal form-bordered">
                             <div class="form-body">
                                 <div class="form-group">
-                                    <label class="control-label col-md-3"> JSON文件 </label>
-                                    <div class="col-md-3">
+                                    <label class="control-label col-md-2"> JSON文件 </label>
+                                    <div class="col-md-6">
                                         <div class="fileinput fileinput-new" data-provides="fileinput">
                                             <div class="input-group input-large">
                                                 <div class="form-control uneditable-input input-fixed input-medium" data-trigger="fileinput">
@@ -60,10 +60,10 @@
                                     </div>
                                 </div>
                             </div>
-                            <div class="form-actions">
+                            <div class="form-actions left">
                                 <div class="row">
-                                    <div class="col-md-offset-4 col-md-9">
-                                        <button type="submit" class="btn green"> 导 入 </button>
+                                    <div class="col-md-offset-2">
+                                        <button type="submit" class="btn green"> 导入 </button>
                                     </div>
                                 </div>
                             </div>

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

@@ -21,7 +21,7 @@
                             <h3 class="font-green-soft">
                                 <span data-counter="counterup" data-value="{{$userCount}}"></span>
                             </h3>
-                            <small>账号</small>
+                            <small>用户</small>
                         </div>
                         <div class="icon">
                             <i class="icon-users"></i>
@@ -36,7 +36,7 @@
                             <h3 class="font-green-sharp">
                                 <span data-counter="counterup" data-value="{{$activeUserCount}}">0</span>
                             </h3>
-                            <small>活跃账号</small>
+                            <small>活跃用户</small>
                         </div>
                         <div class="icon">
                             <i class="icon-user"></i>
@@ -51,7 +51,7 @@
                             <h3 class="font-green-sharp">
                                 <span data-counter="counterup" data-value="{{$onlineUserCount}}">0</span>
                             </h3>
-                            <small>当前在线数量</small>
+                            <small>当前在线</small>
                         </div>
                         <div class="icon">
                             <i class="icon-user"></i>
@@ -96,7 +96,7 @@
                     <div class="display">
                         <div class="number">
                             <h3 class="font-blue-sharp"> {{$flowCount}} </h3>
-                            <small>消耗流量</small>
+                            <small>30日内消耗流量</small>
                         </div>
                         <div class="icon">
                             <i class="icon-speedometer"></i>
@@ -111,7 +111,7 @@
                             <h3 class="font-red">
                                 ¥<span data-counter="counterup" data-value="{{$totalBalance}}"></span>
                             </h3>
-                            <small>盈利</small>
+                            <small>总余额</small>
                         </div>
                         <div class="icon">
                             <i class="icon-diamond"></i>

+ 13 - 1
resources/views/admin/inviteList.blade.php

@@ -41,6 +41,13 @@
                             <div class="caption">
                                 <span class="caption-subject font-dark bold uppercase">邀请码列表</span>
                             </div>
+                            <div class="actions">
+                                <div class="btn-group btn-group-devided" data-toggle="buttons">
+                                    <button class="btn sbold blue" onclick="exportInvite()"> 批量导出
+                                        <i class="fa fa-download"></i>
+                                    </button>
+                                </div>
+                            </div>
                         </div>
                         <div class="portlet-body">
                             <div class="table-scrollable table-scrollable-borderless">
@@ -64,7 +71,7 @@
                                             @foreach($inviteList as $invite)
                                                 <tr>
                                                     <td> {{$invite->id}} </td>
-                                                    <td> <a href="{{url('register?code='.$invite->code)}}" target="_blank">{{$invite->code}}</a> </td>
+                                                    <td> <a href="{{url('register?aff='.Session::get('user')['id'].'&code='.$invite->code)}}" target="_blank">{{$invite->code}}</a> </td>
                                                     <td> {{$invite->dateline}} </td>
                                                     <td> {{empty($invite->generator) ? '【账号已删除】' : $invite->generator->username}} </td>
                                                     <td> {{empty($invite->user) ? '' : $invite->user->username}} </td>
@@ -127,5 +134,10 @@
 
             return false;
         }
+
+        // 导出邀请码
+        function exportInvite() {
+            window.location.href = '{{url('admin/exportInvite')}}';
+        }
     </script>
 @endsection

+ 27 - 6
resources/views/admin/layouts.blade.php

@@ -111,12 +111,6 @@
                         <span class="selected"></span>
                     </a>
                 </li>
-                <li class="nav-item start {{in_array(Request::getRequestUri(), ['/admin/userList', '/admin/addUser']) ? 'active open' : ''}}">
-                    <a href="{{url('admin/userList')}}" class="nav-link nav-toggle">
-                        <i class="icon-users"></i>
-                        <span class="title">账号管理</span>
-                    </a>
-                </li>
                 <li class="nav-item {{Request::getRequestUri() == '/admin/inviteList' ? 'active open' : ''}}">
                     <a href="{{url('admin/inviteList')}}" class="nav-link nav-toggle">
                         <i class="icon-puzzle"></i>
@@ -168,6 +162,27 @@
                         </li>
                     </ul>
                 </li>
+                <li class="nav-item {{in_array(Request::getRequestUri(), ['/admin/userList', '/admin/addUser', '/admin/editUser', '/admin/userBalanceLogList']) ? 'active open' : ''}}">
+                    <a href="javascript:;" class="nav-link nav-toggle">
+                        <i class="icon-users"></i>
+                        <span class="title">账号管理</span>
+                        <span class="arrow"></span>
+                    </a>
+                    <ul class="sub-menu">
+                        <li class="nav-item {{in_array(Request::getRequestUri(), ['/admin/userList', '/admin/addUser', '/admin/editUser']) ? 'active open' : ''}}">
+                            <a href="{{url('admin/userList')}}" class="nav-link ">
+                                <i class="icon-user"></i>
+                                <span class="title">账号列表</span>
+                            </a>
+                        </li>
+                        <li class="nav-item {{Request::getRequestUri() == '/admin/userBalanceLogList' ? 'active open' : ''}}">
+                            <a href="{{url('admin/userBalanceLogList')}}" class="nav-link ">
+                                <i class="icon-credit-card"></i>
+                                <span class="title">余额变动日志</span>
+                            </a>
+                        </li>
+                    </ul>
+                </li>
                 <li class="nav-item {{in_array(Request::getRequestUri(), ['/admin/nodeList', '/admin/addNode', '/admin/editNode', '/admin/groupList', '/admin/addGroup', '/admin/editGroup']) ? 'active open' : ''}}">
                     <a href="javascript:;" class="nav-link nav-toggle">
                         <i class="icon-layers"></i>
@@ -255,6 +270,12 @@
                         </li>
                     </ul>
                 </li>
+                <li class="nav-item {{in_array(Request::getRequestUri(), ['/admin/donate']) ? 'active open' : ''}}">
+                    <a href="{{url('admin/donate')}}" class="nav-link nav-toggle">
+                        <i class="icon-question"></i>
+                        <span class="title">捐赠</span>
+                    </a>
+                </li>
             </ul>
             <!-- END SIDEBAR MENU -->
         </div>

+ 23 - 1
resources/views/admin/system.blade.php

@@ -242,6 +242,17 @@
                                                             </div>
                                                         </div>
                                                     </div>
+                                                    <div class="form-group">
+                                                        <div class="col-md-6">
+                                                            <label for="is_clear_log" class="col-md-3 control-label">自动清除日志</label>
+                                                            <div class="col-md-9">
+                                                                <input type="checkbox" class="make-switch" @if($is_clear_log) checked @endif id="is_clear_log" data-on-color="success" data-off-color="danger" data-on-text="启用" data-off-text="关闭">
+                                                                <span class="help-block"> 启用后自动清除无用日志(推荐) </span>
+                                                            </div>
+                                                        </div>
+                                                        <div class="col-md-6">
+                                                        </div>
+                                                    </div>
                                                 </div>
                                             </form>
                                         </div>
@@ -350,7 +361,7 @@
                                                             <label for="reset_traffic" class="col-md-3 control-label">流量自动重置</label>
                                                             <div class="col-md-9">
                                                                 <input type="checkbox" class="make-switch" @if($reset_traffic) checked @endif id="reset_traffic" data-on-color="success" data-off-color="danger" data-on-text="启用" data-off-text="关闭">
-                                                                <span class="help-block"> 每月1日自动重置账号可用流量 </span>
+                                                                <span class="help-block"> 账号会按其购买套餐的日期自动重置账号可用流量 </span>
                                                             </div>
                                                         </div>
                                                         <div class="col-md-6">
@@ -862,6 +873,17 @@
             }
         });
 
+        // 启用、禁用随机端口
+        $('#is_clear_log').on({
+            'switchChange.bootstrapSwitch': function(event, state) {
+                var is_clear_log = state ? 1 : 0;
+
+                $.post("{{url('admin/setConfig')}}", {_token:'{{csrf_token()}}', name:'is_clear_log', value:is_clear_log}, function (ret) {
+                    console.log(ret);
+                });
+            }
+        });
+
         // 启用、禁用流量自动重置
         $('#reset_traffic').on({
             'switchChange.bootstrapSwitch': function(event, state) {

+ 112 - 0
resources/views/admin/userBalanceLogList.blade.php

@@ -0,0 +1,112 @@
+@extends('admin.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 -->
+    <div class="page-content">
+        <!-- BEGIN PAGE BREADCRUMB -->
+        <ul class="page-breadcrumb breadcrumb">
+            <li>
+                <a href="{{url('admin')}}">账号管理</a>
+                <i class="fa fa-circle"></i>
+            </li>
+            <li>
+                <a href="{{url('admin/userBalanceLogList')}}">余额变动日志</a>
+            </li>
+        </ul>
+        <!-- END PAGE BREADCRUMB -->
+        <!-- BEGIN PAGE BASE CONTENT -->
+        <div class="row">
+            <div class="col-md-12">
+                <!-- BEGIN EXAMPLE TABLE PORTLET-->
+                <div class="portlet light 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>
+                    </div>
+                    <div class="portlet-body">
+                        <div class="row">
+                            <div class="col-md-2 col-sm-2">
+                                <input type="text" class="col-md-4 form-control input-sm" name="username" value="{{Request::get('username')}}" id="username" placeholder="用户名" onkeydown="if(event.keyCode==13){do_search();}">
+                            </div>
+                            <div class="col-md-2 col-sm-2">
+                                <button type="button" class="btn btn-sm blue" onclick="do_search();">查询</button>
+                                <button type="button" class="btn btn-sm grey" onclick="do_reset();">重置</button>
+                            </div>
+                        </div>
+                        <div class="table-scrollable">
+                            <table class="table table-striped table-bordered table-hover table-checkable order-column">
+                                <thead>
+                                <tr>
+                                    <th> ID </th>
+                                    <th> 用户 </th>
+                                    <th> 订单ID </th>
+                                    <th> 操作前余额 </th>
+                                    <th> 发生金额 </th>
+                                    <th> 操作后金额 </th>
+                                    <th> 描述 </th>
+                                    <th> 操作时间 </th>
+                                </tr>
+                                </thead>
+                                <tbody>
+                                    @if($list->isEmpty())
+                                        <tr>
+                                            <td colspan="8">暂无数据</td>
+                                        </tr>
+                                    @else
+                                        @foreach($list as $vo)
+                                            <tr class="odd gradeX">
+                                                <td> {{$vo->id}} </td>
+                                                <td> {{empty($vo->user) ? '【用户已删除】' : $vo->user->username}} </td>
+                                                <td> {{$vo->order_id}} </td>
+                                                <td> {{$vo->before}} </td>
+                                                <td> {{$vo->amount}} </td>
+                                                <td> {{$vo->after}} </td>
+                                                <td> {{$vo->desc}} </td>
+                                                <td> {{$vo->created_at}} </td>
+                                            </tr>
+                                        @endforeach
+                                    @endif
+                                </tbody>
+                            </table>
+                        </div>
+                        <div class="row">
+                            <div class="col-md-4 col-sm-4">
+                                <div class="dataTables_info" role="status" aria-live="polite">共 {{$list->total()}} 条记录</div>
+                            </div>
+                            <div class="col-md-8 col-sm-8">
+                                <div class="dataTables_paginate paging_bootstrap_full_number pull-right">
+                                    {{ $list->links() }}
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+                <!-- END EXAMPLE TABLE PORTLET-->
+            </div>
+        </div>
+        <!-- END PAGE BASE CONTENT -->
+    </div>
+    <!-- END CONTENT BODY -->
+@endsection
+@section('script')
+    <script type="text/javascript">
+        // 搜索
+        function do_search() {
+            var username = $("#username").val();
+
+            window.location.href = '{{url('admin/userBalanceLogList')}}' + '?username=' + username;
+        }
+
+        // 重置
+        function do_reset() {
+            window.location.href = '{{url('admin/userBalanceLogList')}}';
+        }
+    </script>
+@endsection

+ 1 - 0
resources/views/register.blade.php

@@ -49,6 +49,7 @@
             <div class="form-group">
                 <label class="control-label visible-ie8 visible-ie9">用户名</label>
                 <input class="form-control placeholder-no-fix" type="text" autocomplete="off" placeholder="请输入邮箱" name="username" value="{{Request::old('username')}}" required />
+                <input type="hidden" name="register_token" value="{{Session::get('register_token')}}" />
                 <input type="hidden" name="_token" value="{{csrf_token()}}" />
                 <input type="hidden" name="aff" value="{{Request::get('aff')}}" />
             </div>

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 6 - 0
resources/views/serverStatus/css/bootstrap-theme.min.css


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 6 - 0
resources/views/serverStatus/css/bootstrap.min.css


+ 55 - 0
resources/views/serverStatus/css/light.css

@@ -0,0 +1,55 @@
+body { font-family:Molengo,"Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; background: #ebebeb url('../img/light.png'); }
+.announcement { color: #777; border-bottom: solid 3px #d0d0d0; background-color: #fff; padding: 10px 10px; text-align: center; transition: 0.3s; }
+.announcement:hover { border-bottom: solid 3px #159e83; transition: 0.3s; }
+.announcement p { display: inline-block;font-size: 15px;margin: 0;line-height: 1;text-indent: 5px; }
+.announcement i { display: inline-block;font-size: 15px;margin: 0;line-height: 1;color: #444; }
+.navbar { min-height: 50px; }
+.navbar-top { background-color: #4a4a4a !important; border-bottom: 6px solid #159e83; -moz-box-shadow: 0 -4px 0 rgba(0,0,0,.1); box-shadow: 0 6px 0 rgba(0,0,0,.1); }
+.navbar-brand { color: #fff; padding: 10px; font-size: 20px; }
+.dropdown .dropdown-toggle { padding-bottom: 10px; padding-top: 10px; }
+.navbar-inverse .navbar-brand { color: #fff; padding: 15px 20px 10px; font-size: 20px; }
+.content { background: #ffffff; padding: 20px; border: 1px #cecece solid; -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, .1); -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, .1); box-shadow: 0 1px 10px rgba(0, 0, 0, .1); margin-bottom: 20px; margin-top: 20px; }
+.table { background: #ffffff; margin-bottom: 0; border-collapse: collapse; border-radius: 3px; }
+.table th, .table td { text-align: center; }
+.table-striped tbody > tr.even > td, .table-striped tbody > tr.even > th { background-color: #F9F9F9; }
+.table-striped tbody > tr.odd > td, .table-striped tbody > tr.odd > th { background-color: #FFF; }
+.progress { margin-bottom: 0; }
+.progress-bar { color: #000; }
+.table-hover > tbody > tr:hover > td { background: #E6E6E6; }
+tr.even.expandRow > :hover { background: #F9F9F9 !important; }
+tr.odd.expandRow > :hover { background: #FFF !important; }
+.expandRow > td { padding: 0 !important; border-top: 0px !important; }
+#cpu, #ram, #hdd, #network, #traffic { min-width: 55px; max-width: 100px; }
+
+@media only screen and (max-width: 992px) {
+	#location, tr td:nth-child(4)		{ display:none; visibility:hidden; }
+}
+@media only screen and (max-width: 720px) {
+	#type, tr td:nth-child(3)			{ display:none; visibility:hidden; }
+	#location, tr td:nth-child(4)		{ display:none; visibility:hidden; }
+	#uptime, tr td:nth-child(5)			{ display:none; visibility:hidden; }
+}
+@media only screen and (max-width: 600px) {
+	#type, tr td:nth-child(3)			{ display:none; visibility:hidden; }
+	#location, tr td:nth-child(4)		{ display:none; visibility:hidden; }
+	#uptime, tr td:nth-child(5)			{ display:none; visibility:hidden; }
+	#load, tr td:nth-child(6)			{ display:none; visibility:hidden; }
+}
+@media only screen and (max-width: 533px) {
+	#type, tr td:nth-child(3)			{ display:none; visibility:hidden; }
+	#location, tr td:nth-child(4)		{ display:none; visibility:hidden; }
+	#uptime, tr td:nth-child(5)			{ display:none; visibility:hidden; }
+	#traffic, tr td:nth-child(8)		{ display:none; visibility:hidden; }
+	#load, tr td:nth-child(6)			{ display:none; visibility:hidden; }
+}
+@media only screen and (max-width: 450px) {
+	body								{ font-size: 10px; }
+	.content 							{ padding: 0; }
+	#name, tr td:nth-child(2)			{ min-width: 20px; max-width: 60px; text-overflow: ellipsis; white-space: nowrap; overflow: hidden; }
+	#type, tr td:nth-child(3)			{ display:none; visibility:hidden; }
+	#location, tr td:nth-child(4)		{ display:none; visibility:hidden; }
+	#uptime, tr td:nth-child(5)			{ display:none; visibility:hidden; }
+	#traffic, tr td:nth-child(8)		{ display:none; visibility:hidden; }
+	#hdd, tr td:nth-child(11)		{ display:none; visibility:hidden; }
+	#cpu, #ram { min-width: 20px; max-width: 40px; }
+}

binární
resources/views/serverStatus/favicon.ico


binární
resources/views/serverStatus/img/light.png


+ 77 - 0
resources/views/serverStatus/index.html

@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<html lang="zh">
+	<head>
+		<title>逗比云监控</title>
+		<meta charset="utf-8">
+		<meta http-equiv="X-UA-Compatible" content="IE=edge">
+		<meta name="viewport" content="width=device-width, initial-scale=1.0">
+		<link rel="stylesheet" href="css/bootstrap.min.css">
+		<link rel="stylesheet" href="css/bootstrap-theme.min.css">
+		<link href="//fonts.cat.net/css?family=Molengo"rel="stylesheet">
+		<link rel="stylesheet" href="css/light.css">
+		<style>
+			body {
+				padding-top: 70px;
+				padding-bottom: 30px;
+			}
+		</style>
+	</head>
+	<body>
+		<div role="navigation" class="navbar navbar-inverse navbar-fixed-top navbar-top">
+			<div class="navbar-inner">
+				<div class="container">
+					<div class="navbar-header">
+						<a href="#" class="navbar-brand">逗比云监控</a>
+					</div>
+				</div>
+			</div>
+		</div>
+		
+		<div class="container announcement">
+		<p>逗比云监控演示 / 自建<a target="_blank" href="https://doub.io/sszhfx/">免费SS节点</a> 监控站 —— <a target="_blank" href="https://doub.io">逗比根据地</a></p>
+		</div>
+		
+		<div class="container content">
+			<div id="loading-notice">
+				<div class="progress progress-striped center-block active" style="width: 50%;">
+					<div class="progress-bar progress-bar-warning" style="width: 99%;">加载中...</div>
+				</div>
+				<div style="text-align: center;">
+					如果出现此消息,请确保您已启用JavaScript ! <br />否则云监控主服务(服务端) 未启动或已关闭.
+				</div>
+				<br />
+			</div>
+			<table class="table table-striped table-condensed table-hover">
+				<thead>
+				<tr>
+					<th id="status4" class="center-block">IPv4</th>
+					<th id="name">节点名</th>
+					<th id="type">虚拟化</th>
+					<th id="location">位置</th>
+					<th id="uptime">在线时间</th>
+					<th id="load">负载</th>
+					<th id="network">网络(B/s) ↓|↑</th>
+					<th id="traffic">流量(B) ↓|↑</th>
+					<th id="cpu">CPU</th>
+					<th id="ram">内存</th>
+					<th id="hdd">硬盘</th>
+				</tr>
+				</thead>
+				<tbody id="servers">
+				<!-- Servers here \o/ -->
+				</tbody>
+			</table>
+			<br />
+			<div id="updated" style="margin-left: 5px;">Updating...</div>
+		</div>
+
+		<div class="container">
+			<p style="text-align: center; font-size: 10px;">
+				<a href="https://github.com/ToyoDAdoubi/ServerStatus-Toyo">ServerStatus-Toyo</a> 基于 <a href="https://github.com/tenyue/ServerStatus">ServerStatus中文版</a>
+			</p>
+		</div>
+		<script src="js/jquery-1.10.2.min.js"></script>
+		<script src="js/bootstrap.min.js"></script>
+		<script src="js/serverstatus.js"></script>
+	</body>
+</html>

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 6 - 0
resources/views/serverStatus/js/bootstrap.min.js


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 3 - 0
resources/views/serverStatus/js/jquery-1.10.2.min.js


+ 383 - 0
resources/views/serverStatus/js/serverstatus.js

@@ -0,0 +1,383 @@
+// serverstatus.js
+var error = 0;
+var d = 0;
+var server_status = new Array();
+
+function timeSince(date) {
+	if(date == 0)
+		return "从未.";
+
+	var seconds = Math.floor((new Date() - date) / 1000);
+	var interval = Math.floor(seconds / 31536000);
+
+	if (interval > 1)
+		return interval + " 年前.";
+	interval = Math.floor(seconds / 2592000);
+	if (interval > 1)
+		return interval + " 月前.";
+	interval = Math.floor(seconds / 86400);
+	if (interval > 1)
+		return interval + " 日前.";
+	interval = Math.floor(seconds / 3600);
+	if (interval > 1)
+		return interval + " 小时前.";
+	interval = Math.floor(seconds / 60);
+	if (interval > 1)
+		return interval + " 分钟前.";
+	/*if(Math.floor(seconds) >= 5)
+		return Math.floor(seconds) + " seconds";*/
+	else
+		return "几秒前.";
+}
+
+function bytesToSize(bytes, precision, si)
+{
+	var ret;
+	si = typeof si !== 'undefined' ? si : 0;
+	if(si != 0) {
+		var kilobyte = 1000;
+		var megabyte = kilobyte * 1000;
+		var gigabyte = megabyte * 1000;
+		var terabyte = gigabyte * 1000;
+	} else {
+		var kilobyte = 1024;
+		var megabyte = kilobyte * 1024;
+		var gigabyte = megabyte * 1024;
+		var terabyte = gigabyte * 1024;
+	}
+
+	if ((bytes >= 0) && (bytes < kilobyte)) {
+		return bytes + ' B';
+
+	} else if ((bytes >= kilobyte) && (bytes < megabyte)) {
+		ret = (bytes / kilobyte).toFixed(precision) + ' K';
+
+	} else if ((bytes >= megabyte) && (bytes < gigabyte)) {
+		ret = (bytes / megabyte).toFixed(precision) + ' M';
+
+	} else if ((bytes >= gigabyte) && (bytes < terabyte)) {
+		ret = (bytes / gigabyte).toFixed(precision) + ' G';
+
+	} else if (bytes >= terabyte) {
+		ret = (bytes / terabyte).toFixed(precision) + ' T';
+
+	} else {
+		return bytes + ' B';
+	}
+	if(si != 0) {
+		return ret + 'B';
+	} else {
+		return ret + 'iB';
+	}
+}
+
+function uptime() {
+	$.getJSON("json/stats.json", function(result) {
+		$("#loading-notice").remove();
+		if(result.reload)
+			setTimeout(function() { location.reload(true) }, 1000);
+
+		for (var i = 0; i < result.servers.length; i++) {
+			var TableRow = $("#servers tr#r" + i);
+			var ExpandRow = $("#servers #rt" + i);
+			var hack; // fuck CSS for making me do this
+			if(i%2) hack="odd"; else hack="even";
+			if (!TableRow.length) {
+				$("#servers").append(
+					"<tr id=\"r" + i + "\" data-toggle=\"collapse\" data-target=\"#rt" + i + "\" class=\"accordion-toggle " + hack + "\">" +
+						"<td id=\"online4\"><div class=\"progress\"><div style=\"width: 100%;\" class=\"progress-bar progress-bar-warning\"><small>加载中</small></div></div></td>" +
+						"<td id=\"name\">加载中</td>" +
+						"<td id=\"type\">加载中</td>" +
+						"<!-- td id=\"host\">加载中</td -->" +
+						"<td id=\"location\">加载中</td>" +
+						"<td id=\"uptime\">加载中</td>" +
+						"<td id=\"load\">加载中</td>" +
+						"<td id=\"network\">加载中</td>" +
+						"<td id=\"traffic\">加载中</td>" +
+						"<td id=\"cpu\"><div class=\"progress progress-striped active\"><div style=\"width: 100%;\" class=\"progress-bar progress-bar-warning\"><small>加载中</small></div></div></td>" +
+						"<td id=\"memory\"><div class=\"progress progress-striped active\"><div style=\"width: 100%;\" class=\"progress-bar progress-bar-warning\"><small>加载中</small></div></div></td>" +
+						"<td id=\"hdd\"><div class=\"progress progress-striped active\"><div style=\"width: 100%;\" class=\"progress-bar progress-bar-warning\"><small>加载中</small></div></div></td>" +
+					"</tr>" +
+					"<tr class=\"expandRow " + hack + "\"><td colspan=\"12\"><div class=\"accordian-body collapse\" id=\"rt" + i + "\">" +
+						"<div id=\"expand_mem\">加载中</div>" +
+						"<div id=\"expand_swap\">加载中</div>" +
+						"<div id=\"expand_hdd\">加载中</div>" +
+						"<div id=\"expand_custom\">加载中</div>" +
+					"</div></td></tr>"
+				);
+				TableRow = $("#servers tr#r" + i);
+				ExpandRow = $("#servers #rt" + i);
+				server_status[i] = true;
+			}
+			TableRow = TableRow[0];
+			if(error) {
+				TableRow.setAttribute("data-target", "#rt" + i);
+				server_status[i] = true;
+			}
+
+			// Online4
+			if (result.servers[i].online4) {
+				TableRow.children["online4"].children[0].children[0].className = "progress-bar progress-bar-success";
+				TableRow.children["online4"].children[0].children[0].innerHTML = "<small>开启</small>";
+			} else {
+				TableRow.children["online4"].children[0].children[0].className = "progress-bar progress-bar-danger";
+				TableRow.children["online4"].children[0].children[0].innerHTML = "<small>关闭</small>";
+			}
+
+			// Online6
+			//if (result.servers[i].online6) {
+			//	TableRow.children["online6"].children[0].children[0].className = "progress-bar progress-bar-success";
+			//	TableRow.children["online6"].children[0].children[0].innerHTML = "<small>开启</small>";
+			//} else {
+			//	TableRow.children["online6"].children[0].children[0].className = "progress-bar progress-bar-danger";
+			//	TableRow.children["online6"].children[0].children[0].innerHTML = "<small>关闭</small>";
+			//}
+
+			// Name
+			TableRow.children["name"].innerHTML = result.servers[i].name;
+
+			// Type
+			TableRow.children["type"].innerHTML = result.servers[i].type;
+
+			// Host
+			//TableRow.children["host"].innerHTML = result.servers[i].host;
+
+			// Location
+			TableRow.children["location"].innerHTML = result.servers[i].location;
+			if (!result.servers[i].online4 && !result.servers[i].online6) {
+				if (server_status[i]) {
+					TableRow.children["uptime"].innerHTML = "–";
+					TableRow.children["load"].innerHTML = "–";
+					TableRow.children["network"].innerHTML = "–";
+					TableRow.children["traffic"].innerHTML = "–";
+					TableRow.children["cpu"].children[0].children[0].className = "progress-bar progress-bar-danger";
+					TableRow.children["cpu"].children[0].children[0].style.width = "100%";
+					TableRow.children["cpu"].children[0].children[0].innerHTML = "<small>关闭</small>";
+					TableRow.children["memory"].children[0].children[0].className = "progress-bar progress-bar-danger";
+					TableRow.children["memory"].children[0].children[0].style.width = "100%";
+					TableRow.children["memory"].children[0].children[0].innerHTML = "<small>关闭</small>";
+					TableRow.children["hdd"].children[0].children[0].className = "progress-bar progress-bar-danger";
+					TableRow.children["hdd"].children[0].children[0].style.width = "100%";
+					TableRow.children["hdd"].children[0].children[0].innerHTML = "<small>关闭</small>";
+					if(ExpandRow.hasClass("in")) {
+						ExpandRow.collapse("hide");
+					}
+					TableRow.setAttribute("data-target", "");
+					server_status[i] = false;
+				}
+			} else {
+				if (!server_status[i]) {
+					TableRow.setAttribute("data-target", "#rt" + i);
+					server_status[i] = true;
+				}
+
+				// Uptime
+				TableRow.children["uptime"].innerHTML = result.servers[i].uptime;
+
+				// Load
+				if(result.servers[i].load == -1) {
+					TableRow.children["load"].innerHTML = "–";
+				} else {
+					TableRow.children["load"].innerHTML = result.servers[i].load;
+				}
+
+				// Network
+				var netstr = "";
+				if(result.servers[i].network_rx < 1000)
+					netstr += result.servers[i].network_rx.toFixed(0) + "B";
+				else if(result.servers[i].network_rx < 1000*1000)
+					netstr += (result.servers[i].network_rx/1000).toFixed(0) + "K";
+				else
+					netstr += (result.servers[i].network_rx/1000/1000).toFixed(1) + "M";
+				netstr += " | "
+				if(result.servers[i].network_tx < 1000)
+					netstr += result.servers[i].network_tx.toFixed(0) + "B";
+				else if(result.servers[i].network_tx < 1000*1000)
+					netstr += (result.servers[i].network_tx/1000).toFixed(0) + "K";
+				else
+					netstr += (result.servers[i].network_tx/1000/1000).toFixed(1) + "M";
+				TableRow.children["network"].innerHTML = netstr;
+
+				//Traffic
+				var trafficstr = "";
+				if(result.servers[i].network_in < 1024)
+					trafficstr += result.servers[i].network_in.toFixed(0) + "B";
+				else if(result.servers[i].network_in < 1024*1024)
+					trafficstr += (result.servers[i].network_in/1024).toFixed(0) + "K";
+				else if(result.servers[i].network_in < 1024*1024*1024)
+					trafficstr += (result.servers[i].network_in/1024/1024).toFixed(1) + "M";
+				else if(result.servers[i].network_in < 1024*1024*1024*1024)
+					trafficstr += (result.servers[i].network_in/1024/1024/1024).toFixed(2) + "G";
+				else
+					trafficstr += (result.servers[i].network_in/1024/1024/1024/1024).toFixed(2) + "T";
+				trafficstr += " | "
+				if(result.servers[i].network_out < 1024)
+					trafficstr += result.servers[i].network_out.toFixed(0) + "B";
+				else if(result.servers[i].network_out < 1024*1024)
+					trafficstr += (result.servers[i].network_out/1024).toFixed(0) + "K";
+				else if(result.servers[i].network_out < 1024*1024*1024)
+					trafficstr += (result.servers[i].network_out/1024/1024).toFixed(1) + "M";
+				else if(result.servers[i].network_out < 1024*1024*1024*1024)
+					trafficstr += (result.servers[i].network_out/1024/1024/1024).toFixed(2) + "G";
+				else
+					trafficstr += (result.servers[i].network_out/1024/1024/1024/1024).toFixed(2) + "T";
+				TableRow.children["traffic"].innerHTML = trafficstr;
+
+				// CPU
+				if (result.servers[i].cpu >= 90)
+					TableRow.children["cpu"].children[0].children[0].className = "progress-bar progress-bar-danger";
+				else if (result.servers[i].cpu >= 80)
+					TableRow.children["cpu"].children[0].children[0].className = "progress-bar progress-bar-warning";
+				else
+					TableRow.children["cpu"].children[0].children[0].className = "progress-bar progress-bar-success";
+				TableRow.children["cpu"].children[0].children[0].style.width = result.servers[i].cpu + "%";
+				TableRow.children["cpu"].children[0].children[0].innerHTML = result.servers[i].cpu + "%";
+
+				// Memory
+				var Mem = ((result.servers[i].memory_used/result.servers[i].memory_total)*100.0).toFixed(0);
+				if (Mem >= 90)
+					TableRow.children["memory"].children[0].children[0].className = "progress-bar progress-bar-danger";
+				else if (Mem >= 80)
+					TableRow.children["memory"].children[0].children[0].className = "progress-bar progress-bar-warning";
+				else
+					TableRow.children["memory"].children[0].children[0].className = "progress-bar progress-bar-success";
+				TableRow.children["memory"].children[0].children[0].style.width = Mem + "%";
+				TableRow.children["memory"].children[0].children[0].innerHTML = Mem + "%";
+				ExpandRow[0].children["expand_mem"].innerHTML = "内存信息: " + bytesToSize(result.servers[i].memory_used*1024, 2) + " / " + bytesToSize(result.servers[i].memory_total*1024, 2);
+				// Swap
+				ExpandRow[0].children["expand_swap"].innerHTML = "交换分区: " + bytesToSize(result.servers[i].swap_used*1024, 2) + " / " + bytesToSize(result.servers[i].swap_total*1024, 2);
+
+				// HDD
+				var HDD = ((result.servers[i].hdd_used/result.servers[i].hdd_total)*100.0).toFixed(0);
+				if (HDD >= 90)
+					TableRow.children["hdd"].children[0].children[0].className = "progress-bar progress-bar-danger";
+				else if (HDD >= 80)
+					TableRow.children["hdd"].children[0].children[0].className = "progress-bar progress-bar-warning";
+				else
+					TableRow.children["hdd"].children[0].children[0].className = "progress-bar progress-bar-success";
+				TableRow.children["hdd"].children[0].children[0].style.width = HDD + "%";
+				TableRow.children["hdd"].children[0].children[0].innerHTML = HDD + "%";
+				ExpandRow[0].children["expand_hdd"].innerHTML = "硬盘信息: " + bytesToSize(result.servers[i].hdd_used*1024*1024, 2) + " / " + bytesToSize(result.servers[i].hdd_total*1024*1024, 2);
+
+				// Custom
+				if (result.servers[i].custom) {
+					ExpandRow[0].children["expand_custom"].innerHTML = result.servers[i].custom
+				} else {
+					ExpandRow[0].children["expand_custom"].innerHTML = ""
+				}
+			}
+		};
+
+		d = new Date(result.updated*1000);
+		error = 0;
+	}).fail(function(update_error) {
+		if (!error) {
+			$("#servers > tr.accordion-toggle").each(function(i) {
+				var TableRow = $("#servers tr#r" + i)[0];
+				var ExpandRow = $("#servers #rt" + i);
+				TableRow.children["online4"].children[0].children[0].className = "progress-bar progress-bar-error";
+				TableRow.children["online4"].children[0].children[0].innerHTML = "<small>错误</small>";
+				//TableRow.children["online6"].children[0].children[0].className = "progress-bar progress-bar-error";
+				//TableRow.children["online6"].children[0].children[0].innerHTML = "<small>错误</small>";
+				TableRow.children["uptime"].innerHTML = "<div class=\"progress progress-striped active\"><div style=\"width: 100%;\" class=\"progress-bar progress-bar-error\"><small>错误</small></div></div>";
+				TableRow.children["load"].innerHTML = "<div class=\"progress progress-striped active\"><div style=\"width: 100%;\" class=\"progress-bar progress-bar-error\"><small>错误</small></div></div>";
+				TableRow.children["network"].innerHTML = "<div class=\"progress progress-striped active\"><div style=\"width: 100%;\" class=\"progress-bar progress-bar-error\"><small>错误</small></div></div>";
+				TableRow.children["traffic"].innerHTML = "<div class=\"progress progress-striped active\"><div style=\"width: 100%;\" class=\"progress-bar progress-bar-error\"><small>错误</small></div></div>";
+				TableRow.children["cpu"].children[0].children[0].className = "progress-bar progress-bar-error";
+				TableRow.children["cpu"].children[0].children[0].style.width = "100%";
+				TableRow.children["cpu"].children[0].children[0].innerHTML = "<small>错误</small>";
+				TableRow.children["memory"].children[0].children[0].className = "progress-bar progress-bar-error";
+				TableRow.children["memory"].children[0].children[0].style.width = "100%";
+				TableRow.children["memory"].children[0].children[0].innerHTML = "<small>错误</small>";
+				TableRow.children["hdd"].children[0].children[0].className = "progress-bar progress-bar-error";
+				TableRow.children["hdd"].children[0].children[0].style.width = "100%";
+				TableRow.children["hdd"].children[0].children[0].innerHTML = "<small>错误</small>";
+				if(ExpandRow.hasClass("in")) {
+					ExpandRow.collapse("hide");
+				}
+				TableRow.setAttribute("data-target", "");
+				server_status[i] = false;
+			});
+		}
+		error = 1;
+		$("#updated").html("更新错误.");
+	});
+}
+
+function updateTime() {
+	if (!error)
+		$("#updated").html("最后更新: " + timeSince(d));
+}
+
+uptime();
+updateTime();
+setInterval(uptime, 2000);
+setInterval(updateTime, 500);
+
+
+// styleswitcher.js
+function setActiveStyleSheet(title) {
+	var i, a, main;
+	for(i=0; (a = document.getElementsByTagName("link")[i]); i++) {
+		if(a.getAttribute("rel").indexOf("style") != -1 && a.getAttribute("title")) {
+			a.disabled = true;
+			if(a.getAttribute("title") == title) a.disabled = false;
+		}
+	}
+}
+
+function getActiveStyleSheet() {
+	var i, a;
+	for(i=0; (a = document.getElementsByTagName("link")[i]); i++) {
+		if(a.getAttribute("rel").indexOf("style") != -1 && a.getAttribute("title") && !a.disabled)
+			return a.getAttribute("title");
+	}
+	return null;
+}
+
+function getPreferredStyleSheet() {
+	var i, a;
+	for(i=0; (a = document.getElementsByTagName("link")[i]); i++) {
+		if(a.getAttribute("rel").indexOf("style") != -1	&& a.getAttribute("rel").indexOf("alt") == -1 && a.getAttribute("title"))
+			return a.getAttribute("title");
+	}
+return null;
+}
+
+function createCookie(name,value,days) {
+	if (days) {
+		var date = new Date();
+		date.setTime(date.getTime()+(days*24*60*60*1000));
+		var expires = "; expires="+date.toGMTString();
+	}
+	else expires = "";
+	document.cookie = name+"="+value+expires+"; path=/";
+}
+
+function readCookie(name) {
+	var nameEQ = name + "=";
+	var ca = document.cookie.split(';');
+	for(var i=0;i < ca.length;i++) {
+		var c = ca[i];
+		while (c.charAt(0)==' ')
+			c = c.substring(1,c.length);
+		if (c.indexOf(nameEQ) == 0)
+			return c.substring(nameEQ.length,c.length);
+	}
+	return null;
+}
+
+window.onload = function(e) {
+	var cookie = readCookie("style");
+	var title = cookie ? cookie : getPreferredStyleSheet();
+	setActiveStyleSheet(title);
+}
+
+window.onunload = function(e) {
+	var title = getActiveStyleSheet();
+	createCookie("style", title, 365);
+}
+
+var cookie = readCookie("style");
+var title = cookie ? cookie : getPreferredStyleSheet();
+setActiveStyleSheet(title);

+ 2 - 0
resources/views/serverStatus/json/.gitignore

@@ -0,0 +1,2 @@
+stats.json
+stats.json~

+ 1 - 1
resources/views/shop/editGoods.blade.php

@@ -14,7 +14,7 @@
                 <i class="fa fa-circle"></i>
             </li>
             <li>
-                <a href="{{url('shop/editGoods')}}">编辑商品</a>
+                <a href="{{url('shop/editGoods?id=' . Request::get('id'))}}">编辑商品</a>
             </li>
         </ul>
         <!-- END PAGE BREADCRUMB -->

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

@@ -36,7 +36,7 @@
                         <tr>
                             <td style="padding: 10px;">
                                 <h2>{{$goods->name}}</h2>
-                                <p> 内含流量 {{$goods->traffic}} MiB <br> 有效期 {{$goods->days}}天,到期后自动扣除 </p>
+                                <p> 内含流量 {{$goods->traffic}}(有效期 {{$goods->days}}天) </p>
                             </td>
                             <td class="text-center"> ¥{{$goods->price}} </td>
                             <td class="text-center"> x 1 </td>

+ 3 - 182
resources/views/user/goodsList.blade.php

@@ -17,187 +17,6 @@
         <!-- BEGIN PAGE BASE CONTENT -->
         <div class="row">
             <div class="col-md-12">
-                <!--
-                <div class="portlet light bordered">
-                    <div class="portlet-title">
-                        <div class="caption">
-                            <span class="caption-subject bold uppercase"> 流量套餐 </span>
-                        </div>
-                        <div class="actions"></div>
-                    </div>
-                    <div class="portlet-body">
-                        <div class="pricing-content-1">
-                            <div class="row">
-                                <div class="col-md-3">
-                                    <div class="price-column-container border-active">
-                                        <div class="price-table-head bg-blue">
-                                            <h2 class="no-margin">月付套餐</h2>
-                                        </div>
-                                        <div class="arrow-down border-top-blue"></div>
-                                        <div class="price-table-pricing">
-                                            <h3><sup class="price-sign">¥</sup>28</h3>
-                                        </div>
-                                        <div class="price-table-content">
-                                            <div class="row mobile-padding">
-                                                <div class="col-xs-3 text-right mobile-padding">
-                                                    <i class="icon-drawer"></i>
-                                                </div>
-                                                <div class="col-xs-9 text-left mobile-padding">15G/月</div>
-                                            </div>
-                                            <div class="row mobile-padding">
-                                                <div class="col-xs-3 text-right mobile-padding">
-                                                    <i class="icon-screen-smartphone"></i>
-                                                </div>
-                                                <div class="col-xs-9 text-left mobile-padding">支持多设备</div>
-                                            </div>
-                                            <div class="row mobile-padding">
-                                                <div class="col-xs-3 text-right mobile-padding">
-                                                    <i class="icon-refresh"></i>
-                                                </div>
-                                                <div class="col-xs-9 text-left mobile-padding">会员专属高速节点</div>
-                                            </div>
-                                            <div class="row mobile-padding">
-                                                <div class="col-xs-3 text-right mobile-padding">
-                                                    <i class="icon-refresh"></i>
-                                                </div>
-                                                <div class="col-xs-9 text-left mobile-padding">每月1日流量重置</div>
-                                            </div>
-                                        </div>
-                                        <div class="arrow-down arrow-grey"></div>
-                                        <div class="price-table-footer">
-                                            <button type="button" class="btn grey-salsa btn-outline sbold uppercase price-button"> 购 买 </button>
-                                        </div>
-                                    </div>
-                                </div>
-                                <div class="col-md-3">
-                                    <div class="price-column-container border-active">
-                                        <div class="price-table-head bg-red">
-                                            <h2 class="no-margin">季付套餐</h2>
-                                        </div>
-                                        <div class="arrow-down border-top-red"></div>
-                                        <div class="price-table-pricing">
-                                            <h3><sup class="price-sign">¥</sup>78</h3>
-                                        </div>
-                                        <div class="price-table-content">
-                                            <div class="row mobile-padding">
-                                                <div class="col-xs-3 text-right mobile-padding">
-                                                    <i class="icon-drawer"></i>
-                                                </div>
-                                                <div class="col-xs-9 text-left mobile-padding">25G/月</div>
-                                            </div>
-                                            <div class="row mobile-padding">
-                                                <div class="col-xs-3 text-right mobile-padding">
-                                                    <i class="icon-screen-smartphone"></i>
-                                                </div>
-                                                <div class="col-xs-9 text-left mobile-padding">支持多设备</div>
-                                            </div>
-                                            <div class="row mobile-padding">
-                                                <div class="col-xs-3 text-right mobile-padding">
-                                                    <i class="icon-refresh"></i>
-                                                </div>
-                                                <div class="col-xs-9 text-left mobile-padding">会员专属高速节点</div>
-                                            </div>
-                                            <div class="row mobile-padding">
-                                                <div class="col-xs-3 text-right mobile-padding">
-                                                    <i class="icon-refresh"></i>
-                                                </div>
-                                                <div class="col-xs-9 text-left mobile-padding">每月1日流量重置</div>
-                                            </div>
-                                        </div>
-                                        <div class="arrow-down arrow-grey"></div>
-                                        <div class="price-table-footer">
-                                            <button type="button" class="btn grey-salsa btn-outline price-button sbold uppercase"> 购 买 </button>
-                                        </div>
-                                    </div>
-                                </div>
-                                <div class="col-md-3">
-                                    <div class="price-column-container border-active">
-                                        <div class="price-table-head bg-green">
-                                            <h2 class="no-margin">半年付套餐</h2>
-                                        </div>
-                                        <div class="arrow-down border-top-green"></div>
-                                        <div class="price-table-pricing">
-                                            <h3><sup class="price-sign">¥</sup>168</h3>
-                                            <div class="price-ribbon">热门</div>
-                                        </div>
-                                        <div class="price-table-content">
-                                            <div class="row mobile-padding">
-                                                <div class="col-xs-3 text-right mobile-padding">
-                                                    <i class="icon-drawer"></i>
-                                                </div>
-                                                <div class="col-xs-9 text-left mobile-padding">50G/月</div>
-                                            </div>
-                                            <div class="row mobile-padding">
-                                                <div class="col-xs-3 text-right mobile-padding">
-                                                    <i class="icon-screen-smartphone"></i>
-                                                </div>
-                                                <div class="col-xs-9 text-left mobile-padding">支持多设备</div>
-                                            </div>
-                                            <div class="row mobile-padding">
-                                                <div class="col-xs-3 text-right mobile-padding">
-                                                    <i class="icon-refresh"></i>
-                                                </div>
-                                                <div class="col-xs-9 text-left mobile-padding">会员专属高速节点</div>
-                                            </div>
-                                            <div class="row mobile-padding">
-                                                <div class="col-xs-3 text-right mobile-padding">
-                                                    <i class="icon-refresh"></i>
-                                                </div>
-                                                <div class="col-xs-9 text-left mobile-padding">每月1日流量重置</div>
-                                            </div>
-                                        </div>
-                                        <div class="arrow-down arrow-grey"></div>
-                                        <div class="price-table-footer">
-                                            <button type="button" class="btn green price-button sbold uppercase"> 购 买 </button>
-                                        </div>
-                                    </div>
-                                </div>
-                                <div class="col-md-3">
-                                    <div class="price-column-container border-active">
-                                        <div class="price-table-head bg-purple">
-                                            <h2 class="no-margin">年付套餐</h2>
-                                        </div>
-                                        <div class="arrow-down border-top-purple"></div>
-                                        <div class="price-table-pricing">
-                                            <h3><sup class="price-sign">¥</sup>320</h3>
-                                        </div>
-                                        <div class="price-table-content">
-                                            <div class="row mobile-padding">
-                                                <div class="col-xs-3 text-right mobile-padding">
-                                                    <i class="icon-drawer"></i>
-                                                </div>
-                                                <div class="col-xs-9 text-left mobile-padding">50G/月</div>
-                                            </div>
-                                            <div class="row mobile-padding">
-                                                <div class="col-xs-3 text-right mobile-padding">
-                                                    <i class="icon-screen-smartphone"></i>
-                                                </div>
-                                                <div class="col-xs-9 text-left mobile-padding">支持多设备</div>
-                                            </div>
-                                            <div class="row mobile-padding">
-                                                <div class="col-xs-3 text-right mobile-padding">
-                                                    <i class="icon-refresh"></i>
-                                                </div>
-                                                <div class="col-xs-9 text-left mobile-padding">会员专属高速节点</div>
-                                            </div>
-                                            <div class="row mobile-padding">
-                                                <div class="col-xs-3 text-right mobile-padding">
-                                                    <i class="icon-refresh"></i>
-                                                </div>
-                                                <div class="col-xs-9 text-left mobile-padding">每月1日流量重置</div>
-                                            </div>
-                                        </div>
-                                        <div class="arrow-down arrow-grey"></div>
-                                        <div class="price-table-footer">
-                                            <button type="button" class="btn grey-salsa btn-outline price-button sbold uppercase"> 购 买 </button>
-                                        </div>
-                                    </div>
-                                </div>
-                            </div>
-                        </div>
-                    </div>
-                </div>
-                -->
                 <div class="portlet light bordered">
                     <div class="portlet-title">
                         <div class="caption font-dark">
@@ -211,6 +30,7 @@
                                 <tr>
                                     <th style="text-align: center;"> 名称 </th>
                                     <th style="text-align: center;"> 内含流量 </th>
+                                    <th style="text-align: center;"> 有效期 </th>
                                     <th style="text-align: center;"> 售价 </th>
                                     <!--<th> 所需积分 </th>-->
                                     <th> </th>
@@ -228,7 +48,8 @@
                                                 <!--@if($goods->logo) <a href="{{$goods->logo}}" class="fancybox"><img src="{{$goods->logo}}"/></a> @endif -->
                                                 {{$goods->name}}
                                             </td>
-                                            <td style="text-align: center;"> {{$goods->traffic}} MiB </td>
+                                            <td style="text-align: center;"> {{$goods->traffic}} </td>
+                                            <td style="text-align: center;"> {{$goods->days}} 天 </td>
                                             <td style="text-align: center;"> ¥{{$goods->price}} </td>
                                             <!--<td> {{$goods->score}} </td>-->
                                             <td style="text-align: center;">

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

@@ -47,7 +47,7 @@
         <div class="row">
             <div class="col-md-8">
                 <div class="alert alert-danger">
-                    <strong>结算比例:</strong> 1表示用100M就结算100M,0.1表示用100M结算10M,5表示用100M结算500M,越是优质节点则比例越高
+                    <strong>结算比例:</strong> 1表示用100M就结算100M,0.1表示用100M结算10M,5表示用100M结算500M。
                     <button class="btn btn-sm red" onclick="subscribe()"> 订阅节点 </button>
                 </div>
                 <div class="row widget-row">

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

@@ -55,7 +55,7 @@
                                             @foreach($inviteList as $key => $invite)
                                                 <tr>
                                                     <td> {{$key + 1}} </td>
-                                                    <td> <a href="{{url('register?code='.$invite->code)}}" target="_blank">{{$invite->code}}</a> </td>
+                                                    <td> <a href="{{url('register?aff='.Session::get('user')['id'].'&code='.$invite->code)}}" target="_blank">{{$invite->code}}</a> </td>
                                                     <td> {{$invite->dateline}} </td>
                                                     <td> {{empty($invite->user) ? '' : $invite->user->username}} </td>
                                                     <td>

+ 4 - 0
routes/web.php

@@ -36,6 +36,7 @@ Route::group(['middleware' => ['user', 'admin']], function() {
     Route::post('ticket/closeTicket', 'TicketController@closeTicket'); // 关闭工单
     Route::get('admin/inviteList', 'AdminController@inviteList'); // 邀请码列表
     Route::post('admin/makeInvite', 'AdminController@makeInvite'); // 生成邀请码
+    Route::get('admin/exportInvite', 'AdminController@exportInvite'); // 导出邀请码
     Route::get('admin/applyList', 'AdminController@applyList'); // 提现申请管理
     Route::get('admin/applyDetail', 'AdminController@applyDetail'); // 提现申请管理
     Route::post('admin/setApplyStatus', 'AdminController@setApplyStatus'); // 设置提现申请状态
@@ -63,6 +64,8 @@ Route::group(['middleware' => ['user', 'admin']], function() {
     Route::post('admin/setReferralPercent', 'AdminController@setReferralPercent'); // 设置返利比例
     Route::post('admin/setQrcode', 'AdminController@setQrcode'); // 设置充值二维码
     Route::post('admin/resetUserTraffic', 'AdminController@resetUserTraffic'); // 重置用户流量
+    Route::post('admin/handleUserBalance', 'AdminController@handleUserBalance'); // 余额充值
+    Route::get('admin/userBalanceLogList', 'AdminController@userBalanceLogList'); // 余额变动日志
     Route::get('admin/makePasswd', 'AdminController@makePasswd'); // 获取随机密码
     Route::get('admin/download', 'AdminController@download'); // 下载转换过的JSON配置
     Route::any('shop/goodsList', 'ShopController@goodsList'); // 商品列表
@@ -75,6 +78,7 @@ Route::group(['middleware' => ['user', 'admin']], function() {
     Route::get('coupon/exportCoupon', 'CouponController@exportCoupon'); // 导出优惠券
     Route::get('emailLog/logList', 'EmailLogController@logList'); // 邮件发送日志
     Route::post("admin/loginas","AdminController@loginas");
+    Route::get('admin/donate', 'DonateController@donate'); // 捐赠
 });
 
 Route::group(['middleware' => ['user']], function() {

binární
server/serverStatus.zip


+ 41 - 31
sql/db.sql

@@ -64,9 +64,8 @@ CREATE TABLE `ss_node_info` (
   `uptime` float NOT NULL COMMENT '更新时间',
   `load` varchar(32) NOT NULL COMMENT '负载',
   `log_time` int(11) NOT NULL COMMENT '记录时间',
-  `created_at` datetime NOT NULL,
-  `updated_at` datetime NOT NULL,
-  PRIMARY KEY (`id`)
+  PRIMARY KEY (`id`),
+  KEY `idx_node_id` (`node_id`) USING BTREE
 ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='节点负载信息';
 
 
@@ -78,10 +77,8 @@ CREATE TABLE `ss_node_online_log` (
   `node_id` int(11) NOT NULL COMMENT '节点ID',
   `online_user` int(11) NOT NULL COMMENT '在线用户数',
   `log_time` int(11) NOT NULL COMMENT '记录时间',
-  `created_at` datetime NOT NULL,
-  `updated_at` datetime NOT NULL,
   PRIMARY KEY (`id`),
-  KEY `idx_online` (`node_id`,`log_time`)
+  KEY `idx_node_id` (`node_id`) USING BTREE
 ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='节点在线信息';
 
 
@@ -112,7 +109,7 @@ CREATE TABLE `user` (
   `qq` varchar(20) DEFAULT '' COMMENT 'QQ',
   `usage` tinyint(4) NOT NULL DEFAULT '4' COMMENT '用途:1-手机、2-电脑、3-路由器、4-其他',
   `pay_way` tinyint(4) NOT NULL DEFAULT '0' COMMENT '付费方式:0-免费、1-月付、2-半年付、3-年付',
-  `balance` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '余额',
+  `balance` int(11) NOT NULL DEFAULT '0' COMMENT '余额,单位分',
   `score` int(11) NOT NULL DEFAULT '0' COMMENT '积分',
   `enable_time` date DEFAULT NULL COMMENT '开通日期',
   `expire_time` date NOT NULL DEFAULT '2099-01-01' COMMENT '过期时间',
@@ -121,8 +118,9 @@ CREATE TABLE `user` (
   `level` tinyint(4) NOT NULL DEFAULT '1' COMMENT '等级:可定义名称',
   `is_admin` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否管理员:0-否、1-是',
   `reg_ip` varchar(20) NOT NULL DEFAULT '127.0.0.1' COMMENT '注册IP',
-  `last_login` int(11) NOT NULL DEFAULT '0' COMMENT '最后一次登录时间',
+  `last_login` int(11) NOT NULL DEFAULT '0' COMMENT '最后登录时间',
   `referral_uid` int(11) NOT NULL DEFAULT '0' COMMENT '邀请人',
+  `traffic_reset_day` tinyint(4) NOT NULL DEFAULT '0' COMMENT '流量自动重置日,0表示不重置',
   `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态:-1-禁用、0-未激活、1-正常',
   `created_at` datetime DEFAULT NULL,
   `updated_at` datetime DEFAULT NULL,
@@ -130,6 +128,7 @@ CREATE TABLE `user` (
   UNIQUE KEY `port` (`port`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
+
 LOCK TABLES `user` WRITE;
 /*!40000 ALTER TABLE `user` DISABLE KEYS */;
 
@@ -178,7 +177,8 @@ CREATE TABLE `user_traffic_log` (
   `log_time` int(11) NOT NULL COMMENT '记录时间',
   PRIMARY KEY (`id`),
   KEY `idx_user` (`user_id`),
-  KEY `idx_node` (`node_id`)
+  KEY `idx_node` (`node_id`),
+  KEY `idx_user_node` (`user_id`,`node_id`) USING BTREE
 ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
 
 
@@ -193,7 +193,7 @@ CREATE TABLE `ss_config` (
   `is_default` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否默认:0-不是、1-是',
   `sort` int(11) NOT NULL DEFAULT '0' COMMENT '排序:值越大排越前',
   `created_at` datetime DEFAULT NULL COMMENT '创建时间',
-  `updated_at` datetime DEFAULT NULL COMMENT '最后一次更新时间',
+  `updated_at` datetime DEFAULT NULL COMMENT '最后更新时间',
   PRIMARY KEY (`id`)
 ) ENGINE=MyISAM AUTO_INCREMENT=32 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
 
@@ -284,6 +284,7 @@ INSERT INTO `config` VALUES ('32', 'is_captcha', 0);
 INSERT INTO `config` VALUES ('33', 'is_traffic_ban', 1);
 INSERT INTO `config` VALUES ('34', 'traffic_ban_value', 10);
 INSERT INTO `config` VALUES ('35', 'traffic_ban_time', 60);
+INSERT INTO `config` VALUES ('36', 'is_clear_log', 1);
 
 
 -- ----------------------------
@@ -405,7 +406,6 @@ CREATE TABLE `goods` (
 ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='商品信息表';
 
 
-
 -- ----------------------------
 -- Table structure for `coupon`
 -- ----------------------------
@@ -450,13 +450,13 @@ CREATE TABLE `order` (
   `orderId` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '订单编号',
   `user_id` int(11) NOT NULL DEFAULT '0' COMMENT '操作人',
   `coupon_id` int(11) NOT NULL DEFAULT '0' COMMENT '优惠券ID',
-  `totalOriginalPrice` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '订单原始总价',
-  `totalPrice` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '订单总价',
+  `totalOriginalPrice` int(11) NOT NULL DEFAULT '0' COMMENT '订单原始总价,单位分',
+  `totalPrice` int(11) NOT NULL DEFAULT '0' COMMENT '订单总价,单位分',
   `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '订单状态:-1-已关闭、0-待支付、1-已支付待确认、2-已完成',
   `created_at` datetime DEFAULT NULL COMMENT '创建时间',
   `updated_at` datetime DEFAULT NULL COMMENT '最后更新时间',
   PRIMARY KEY (`oid`)
-) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='订单信息表';
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='订单信息表';
 
 
 -- ----------------------------
@@ -469,8 +469,8 @@ CREATE TABLE `order_goods` (
   `user_id` int(11) NOT NULL DEFAULT '0' COMMENT '用户ID',
   `goods_id` int(11) NOT NULL DEFAULT '0' COMMENT '商品ID',
   `num` int(11) NOT NULL DEFAULT '0' COMMENT '商品数量',
-  `original_price` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '商品原价',
-  `price` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '商品实际价格',
+  `original_price` int(11) NOT NULL DEFAULT '0' COMMENT '商品原价,单位分',
+  `price` int(11) NOT NULL DEFAULT '0' COMMENT '商品实际价格,单位分',
   `is_expire` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否已过期:0-未过期、1-已过期',
   `created_at` datetime DEFAULT NULL COMMENT '创建时间',
   `updated_at` datetime DEFAULT NULL COMMENT '最后更新时间',
@@ -528,10 +528,10 @@ CREATE TABLE `user_balance_log` (
   `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
   `user_id` int(11) NOT NULL DEFAULT '0' COMMENT '账号ID',
   `order_id` int(11) NOT NULL DEFAULT '0' COMMENT '订单ID',
-  `before` decimal(11,2) NOT NULL DEFAULT '0.00' COMMENT '发生前余额',
-  `after` decimal(11,2) NOT NULL DEFAULT '0.00' COMMENT '发生后余额',
-  `balance` decimal(11,2) NOT NULL DEFAULT '0.00' COMMENT '发生金额',
-  `desc` varchar(255) DEFAULT '' COMMENT '描述',
+  `before` int(11) NOT NULL DEFAULT '0' COMMENT '发生前余额,单位分',
+  `after` int(11) NOT NULL DEFAULT '0' COMMENT '发生后金额,单位分',
+  `amount` int(11) NOT NULL DEFAULT '0' COMMENT '发生金额,单位分',
+  `desc` varchar(255) DEFAULT '' COMMENT '操作描述',
   `created_at` datetime DEFAULT NULL COMMENT '创建时间',
   PRIMARY KEY (`id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
@@ -543,9 +543,9 @@ CREATE TABLE `user_balance_log` (
 CREATE TABLE `referral_apply` (
   `id` int(11) NOT NULL AUTO_INCREMENT,
   `user_id` int(11) NOT NULL DEFAULT '0' COMMENT '用户ID',
-  `before` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '操作前可提现金额',
-  `after` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '操作后可提现金额',
-  `amount` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '本次提现金额',
+  `before` int(11) NOT NULL DEFAULT '0' COMMENT '操作前可提现金额,单位分',
+  `after` int(11) NOT NULL DEFAULT '0' COMMENT '操作后可提现金额,单位分',
+  `amount` int(11) NOT NULL DEFAULT '0' COMMENT '本次提现金额,单位分',
   `link_logs` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '关联返利日志ID,例如:1,3,4',
   `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态:-1-驳回、0-待审核、1-审核通过待打款、2-已打款',
   `created_at` datetime DEFAULT NULL COMMENT '创建时间',
@@ -562,13 +562,13 @@ CREATE TABLE `referral_log` (
   `user_id` int(11) NOT NULL DEFAULT '0' COMMENT '用户ID',
   `ref_user_id` int(11) NOT NULL DEFAULT '0' COMMENT '推广人ID',
   `order_id` int(11) NOT NULL DEFAULT '0' COMMENT '关联订单ID',
-  `amount` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '消费金额',
+  `amount` int(11) NOT NULL DEFAULT '0' COMMENT '消费金额,单位分',
   `ref_amount` int(11) NOT NULL DEFAULT '0' COMMENT '返利金额',
   `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态:0-未提现、1-审核中、2-已提现',
   `created_at` datetime DEFAULT NULL COMMENT '创建时间',
-  `updated_at` datetime DEFAULT NULL COMMENT '最后一次更新时间',
+  `updated_at` datetime DEFAULT NULL COMMENT '最后更新时间',
   PRIMARY KEY (`id`)
-) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='消费返利日志';
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='消费返利日志';
 
 
 -- ----------------------------
@@ -627,7 +627,9 @@ CREATE TABLE `user_traffic_daily` (
   `traffic` varchar(255) DEFAULT '' COMMENT '总流量(带单位)',
   `created_at` datetime DEFAULT NULL COMMENT '创建时间',
   `updated_at` datetime DEFAULT NULL COMMENT '最后更新时间',
-  PRIMARY KEY (`id`)
+  PRIMARY KEY (`id`),
+  KEY `idx_user` (`user_id`) USING BTREE,
+  KEY `idx_user_node` (`user_id`,`node_id`) USING BTREE
 ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
 
 
@@ -644,7 +646,9 @@ CREATE TABLE `user_traffic_hourly` (
   `traffic` varchar(255) DEFAULT '' COMMENT '总流量(带单位)',
   `created_at` datetime DEFAULT NULL COMMENT '创建时间',
   `updated_at` datetime DEFAULT NULL COMMENT '最后更新时间',
-  PRIMARY KEY (`id`)
+  PRIMARY KEY (`id`),
+  KEY `idx_user` (`user_id`) USING BTREE,
+  KEY `idx_user_node` (`user_id`,`node_id`) USING BTREE
 ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
 
 
@@ -676,7 +680,7 @@ CREATE TABLE `ss_node_traffic_hourly` (
   `total` bigint(20) NOT NULL DEFAULT '0' COMMENT '总流量',
   `traffic` varchar(255) DEFAULT '' COMMENT '总流量(带单位)',
   `created_at` datetime DEFAULT NULL COMMENT '创建时间',
-  `updated_at` datetime DEFAULT NULL COMMENT '最后一起更新时间',
+  `updated_at` datetime DEFAULT NULL COMMENT '最后更新时间',
   PRIMARY KEY (`id`),
   KEY `idx_node_id` (`node_id`)
 ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
@@ -688,7 +692,7 @@ CREATE TABLE `ss_node_traffic_hourly` (
 CREATE TABLE `user_ban_log` (
   `id` int(11) NOT NULL AUTO_INCREMENT,
   `user_id` int(11) NOT NULL DEFAULT '0' COMMENT '用户ID',
-  `minutes` int(11) NOT NULL DEFAULT '0' COMMENT '封禁账号市场,单位分钟',
+  `minutes` int(11) NOT NULL DEFAULT '0' COMMENT '封禁账号时长,单位分钟',
   `desc` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '操作描述',
   `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态:0-未处理、1-已处理',
   `created_at` datetime DEFAULT NULL COMMENT ' 创建时间',
@@ -749,7 +753,13 @@ INSERT INTO `country` VALUES ('36', '波兰', 'pl');
 INSERT INTO `country` VALUES ('37', '哈萨克斯坦', 'kz');
 INSERT INTO `country` VALUES ('38', '乌克兰', 'ua');
 INSERT INTO `country` VALUES ('39', '罗马尼亚', 'ro');
-INSERT INTO `country` VALUES ('40', '阿拉伯联合酋长国', 'ae');
+INSERT INTO `country` VALUES ('40', '阿联酋', 'ae');
+INSERT INTO `country` VALUES ('41', '南非', 'za');
+INSERT INTO `country` VALUES ('42', '缅甸', 'mm');
+INSERT INTO `country` VALUES ('43', '冰岛', 'is');
+INSERT INTO `country` VALUES ('44', '芬兰', 'fi');
+INSERT INTO `country` VALUES ('45', '卢森堡', 'lu');
+INSERT INTO `country` VALUES ('46', '比利时', 'be');
 
 INSERT INTO `config` (`id`, `name`, `value`) VALUES (NULL, 'wepay_enabled', '0');
 INSERT INTO `config` (`id`, `name`, `value`) VALUES (NULL, 'alipay_enabled', '0');

+ 26 - 2
sql/update/20171129.sql

@@ -12,5 +12,29 @@ INSERT INTO `config` (`id`, `name`, `value`) VALUES (NULL, 'payment_wepay_phone'
 INSERT INTO `config` (`id`, `name`, `value`) VALUES (NULL, 'payment_alipay_phone', '');
 INSERT INTO `config` (`id`, `name`, `value`) VALUES (NULL, 'payment_qqpay_phone', '');
 
-CREATE TABLE `ssrpanel`.`user_payment` ( `id` INT NOT NULL AUTO_INCREMENT , `user_id` INT NOT NULL , `money` FLOAT NOT NULL , `status` INT NOT NULL , PRIMARY KEY (`id`),  `created_at` datetime NOT NULL,
-  `updated_at` datetime NOT NULL) ENGINE = InnoDB;
+CREATE TABLE `ssrpanel`.`user_payment` (
+  `id` INT NOT NULL AUTO_INCREMENT ,
+  `user_id` INT NOT NULL ,
+  `money` FLOAT NOT NULL ,
+  `status` INT NOT NULL ,
+  PRIMARY KEY (`id`),
+  `created_at` datetime NOT NULL,
+  `updated_at` datetime NOT NULL
+) ENGINE = InnoDB;
+
+INSERT INTO `country` VALUES ('40', '阿联酋', 'ae');
+INSERT INTO `country` VALUES ('41', '南非', 'za');
+INSERT INTO `country` VALUES ('42', '缅甸', 'mm');
+INSERT INTO `country` VALUES ('43', '冰岛', 'is');
+INSERT INTO `country` VALUES ('44', '芬兰', 'fi');
+INSERT INTO `country` VALUES ('45', '卢森堡', 'lu');
+INSERT INTO `country` VALUES ('46', '比利时', 'be');
+
+
+-- 用户余额字段由decimal改为int,数值变大一百倍
+ALTER TABLE `user` MODIFY `balance` int(11) NOT NULL DEFAULT '0' COMMENT '余额,单位分';
+UPDATE `user` SET balance = balance * 100;
+
+
+-- 用于余额日志表 balance 字段改 amount字段
+ALTER TABLE `user_balance_log` CHANGE `balance` `amount` int(11) NOT NULL DEFAULT '0' COMMENT '发生金额,单位分';

+ 29 - 0
sql/update/20171130.sql

@@ -1 +1,30 @@
+
 ALTER TABLE `user` ADD `rememberme_token` VARCHAR(256) NULL DEFAULT '' AFTER `passwd`;
+
+-- 日志表加索引,提升查询速度
+ALTER TABLE `user_traffic_log`
+ADD INDEX `idx_user_node` (`user_id`, `node_id`) USING BTREE ;
+
+ALTER TABLE `user_traffic_daily`
+ADD INDEX `idx_user` (`user_id`) USING BTREE ,
+ADD INDEX `idx_user_node` (`user_id`, `node_id`) USING BTREE ;
+
+ALTER TABLE `user_traffic_hourly`
+ADD INDEX `idx_user` (`user_id`) USING BTREE ,
+ADD INDEX `idx_user_node` (`user_id`, `node_id`) USING BTREE ;
+
+ALTER TABLE `ss_node_info`
+ADD INDEX `idx_node_id` (`node_id`) USING BTREE ;
+
+ALTER TABLE `ss_node_online_log`
+ADD INDEX `idx_node_id` (`node_id`) USING BTREE ;
+
+-- 去除节点负载信息表无用字段
+ALTER TABLE `ss_node_info`
+DROP COLUMN `created_at`,
+DROP COLUMN `updated_at`;
+
+-- 去除在线用户表无用字段
+ALTER TABLE `ss_node_online_log`
+DROP COLUMN `created_at`,
+DROP COLUMN `updated_at`;

+ 27 - 0
sql/update/20171201.sql

@@ -0,0 +1,27 @@
+-- 消费返利日志表字段类型调整
+ALTER TABLE `referral_log` MODIFY `amount` int(11) NOT NULL DEFAULT '0' COMMENT '消费金额,单位分';
+UPDATE `referral_log` SET `amount` = `amount` * 100;
+
+-- 消费提现申请表字段类型调整
+ALTER TABLE `referral_apply` MODIFY `before` int(11) NOT NULL DEFAULT '0' COMMENT '操作前可提现金额,单位分';
+UPDATE `referral_apply` SET `before` = `before` * 100;
+
+ALTER TABLE `referral_apply` MODIFY `after` int(11) NOT NULL DEFAULT '0' COMMENT '操作后可提现金额,单位分';
+UPDATE `referral_apply` SET `after` = `after` * 100;
+
+ALTER TABLE `referral_apply` MODIFY `amount` int(11) NOT NULL DEFAULT '0' COMMENT '本次提现金额,单位分';
+UPDATE `referral_apply` SET `amount` = `amount` * 100;
+
+-- 订单商品表字段类型调整
+ALTER TABLE `order_goods` MODIFY `original_price` int(11) NOT NULL DEFAULT '0' COMMENT '商品原价,单位分';
+UPDATE `order_goods` SET `original_price` = `original_price` * 100;
+
+ALTER TABLE `order_goods` MODIFY `price` int(11) NOT NULL DEFAULT '0' COMMENT '商品实际价格,单位分';
+UPDATE `order_goods` SET `price` = `price` * 100;
+
+-- 订单表字段类型调整
+ALTER TABLE `order` MODIFY `totalOriginalPrice` int(11) NOT NULL DEFAULT '0' COMMENT '订单原始总价,单位分';
+UPDATE `order` SET `totalOriginalPrice` = `totalOriginalPrice` * 100;
+
+ALTER TABLE `order` MODIFY `totalPrice` int(11) NOT NULL DEFAULT '0' COMMENT '订单总价,单位分';
+UPDATE `order` SET `totalPrice` = `totalPrice` * 100;

+ 6 - 0
sql/update/20171202.sql

@@ -0,0 +1,6 @@
+-- 加入流量重置日
+ALTER TABLE `user`
+ADD COLUMN `traffic_reset_day`  tinyint NOT NULL DEFAULT 0 COMMENT '流量自动重置日,0表示不重置' AFTER `referral_uid`;
+
+-- 加入 是否自动重置流量 配置
+INSERT INTO `config` VALUES ('36', 'is_clear_log', 1);

+ 5 - 0
sql/update/20171204.sql

@@ -0,0 +1,5 @@
+INSERT INTO `country` VALUES ('47', '保加利亚', 'bg');
+INSERT INTO `country` VALUES ('48', '立陶宛', 'lt');
+INSERT INTO `country` VALUES ('49', '哥伦比亚', 'co');
+INSERT INTO `country` VALUES ('50', '澳门', 'mo');
+INSERT INTO `country` VALUES ('51', '肯尼亚', 'ke');

Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů