改进
This commit is contained in:
parent
7f5bd004a2
commit
fe04c15a07
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Console;
|
namespace App\Console;
|
||||||
|
|
||||||
|
use App\Jobs\Cost;
|
||||||
use Illuminate\Console\Scheduling\Schedule;
|
use Illuminate\Console\Scheduling\Schedule;
|
||||||
use App\Http\Controllers\Admin\ServerController;
|
use App\Http\Controllers\Admin\ServerController;
|
||||||
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
||||||
@ -17,7 +18,7 @@ protected function schedule(Schedule $schedule): void
|
|||||||
(new ServerController())->checkServer();
|
(new ServerController())->checkServer();
|
||||||
})->everyMinute()->name('FrpServer')->withoutOverlapping()->onOneServer();
|
})->everyMinute()->name('FrpServer')->withoutOverlapping()->onOneServer();
|
||||||
|
|
||||||
// $schedule->job(new Cost())->hourly()->name('FrpServerCost')->withoutOverlapping()->onOneServer();
|
$schedule->job(new Cost())->hourly()->name('FrpServerCost')->withoutOverlapping()->onOneServer();
|
||||||
|
|
||||||
// every three days
|
// every three days
|
||||||
// $schedule->job(new ReviewWebsiteJob())->daily()->name('reviewWebsiteJob')->withoutOverlapping()->onOneServer();
|
// $schedule->job(new ReviewWebsiteJob())->daily()->name('reviewWebsiteJob')->withoutOverlapping()->onOneServer();
|
||||||
|
@ -34,6 +34,12 @@ public function handler(Request $request, $key)
|
|||||||
return $this->failed('此服务器暂时不接受新的连接。');
|
return $this->failed('此服务器暂时不接受新的连接。');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// cache
|
||||||
|
$cache_key = 'frpTunnel_data_' . $request->input('content')['proxy_name'] . '_lock';
|
||||||
|
if (Cache::has($cache_key)) {
|
||||||
|
return $this->failed('此隧道正在被操作,请稍后再试。');
|
||||||
|
}
|
||||||
|
|
||||||
// Search tunnel
|
// Search tunnel
|
||||||
$host = Tunnel::where('client_token', $request->input('content')['proxy_name'])->where('server_id', $server->id)->first();
|
$host = Tunnel::where('client_token', $request->input('content')['proxy_name'])->where('server_id', $server->id)->first();
|
||||||
if (is_null($host)) {
|
if (is_null($host)) {
|
||||||
|
@ -2,12 +2,14 @@
|
|||||||
|
|
||||||
namespace App\Http\Controllers\Api;
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
|
||||||
use App\Http\Requests\TunnelRequest;
|
|
||||||
use App\Models\Server;
|
use App\Models\Server;
|
||||||
use App\Models\Tunnel;
|
use App\Models\Tunnel;
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Http\Requests\TunnelRequest;
|
||||||
|
use App\Support\Frp;
|
||||||
|
use Illuminate\Support\Facades\Cache;
|
||||||
|
|
||||||
class TunnelController extends Controller
|
class TunnelController extends Controller
|
||||||
{
|
{
|
||||||
@ -150,7 +152,21 @@ public function store(Request $request)
|
|||||||
public function show(TunnelRequest $tunnelRequest, Tunnel $tunnel)
|
public function show(TunnelRequest $tunnelRequest, Tunnel $tunnel)
|
||||||
{
|
{
|
||||||
unset($tunnelRequest);
|
unset($tunnelRequest);
|
||||||
|
|
||||||
|
$tunnel->load('server');
|
||||||
|
|
||||||
$tunnel['config'] = $tunnel->getConfig();
|
$tunnel['config'] = $tunnel->getConfig();
|
||||||
|
|
||||||
|
$frp = new Frp($tunnel->server);
|
||||||
|
$traffic = $frp->traffic($tunnel->client_token) ?? [];
|
||||||
|
|
||||||
|
if (!$traffic) {
|
||||||
|
$traffic = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$tunnel['traffic'] = $traffic;
|
||||||
|
|
||||||
return $this->success($tunnel);
|
return $this->success($tunnel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ public function index(Request $request)
|
|||||||
return view('spa');
|
return view('spa');
|
||||||
}
|
}
|
||||||
|
|
||||||
return view('index');
|
return redirect()->route('login');
|
||||||
|
// return view('index');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers;
|
|
||||||
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
|
|
||||||
class SpaController extends Controller
|
|
||||||
{
|
|
||||||
public function __invoke(Request $request)
|
|
||||||
{
|
|
||||||
// return view('spa');
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
namespace App\Jobs;
|
namespace App\Jobs;
|
||||||
|
|
||||||
use App\Models\Host;
|
|
||||||
use App\Models\Server;
|
use App\Models\Server;
|
||||||
use Illuminate\Bus\Queueable;
|
use Illuminate\Bus\Queueable;
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
@ -10,30 +9,23 @@
|
|||||||
use Illuminate\Queue\InteractsWithQueue;
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
use Illuminate\Queue\SerializesModels;
|
use Illuminate\Queue\SerializesModels;
|
||||||
use Illuminate\Support\Facades\Cache;
|
use Illuminate\Support\Facades\Cache;
|
||||||
use Illuminate\Support\Facades\Http;
|
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
class Cost implements ShouldQueue
|
class Cost implements ShouldQueue
|
||||||
{
|
{
|
||||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
|
||||||
private $http;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute the job.
|
* Execute the job.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function handle_old()
|
public function handle()
|
||||||
{
|
{
|
||||||
$this->http = Http::remote('remote')->asForm();
|
Server::with('tunnels')->where('status', 'up')->chunk(100, function ($servers) {
|
||||||
|
|
||||||
Server::with('hosts')->where('status', 'up')->whereNot('price_per_gb', 0)->chunk(100, function ($servers) {
|
|
||||||
foreach ($servers as $server) {
|
foreach ($servers as $server) {
|
||||||
// $ServerCheckJob = new ServerCheckJob($server->id);
|
|
||||||
// $ServerCheckJob->handle();
|
|
||||||
|
|
||||||
foreach ($server->hosts as $host) {
|
foreach ($server->tunnels as $host) {
|
||||||
$host->load('user');
|
$host->load('user');
|
||||||
|
|
||||||
Log::debug('------------');
|
Log::debug('------------');
|
||||||
@ -41,15 +33,11 @@ public function handle_old()
|
|||||||
Log::debug('属于用户: ' . $host->user->name);
|
Log::debug('属于用户: ' . $host->user->name);
|
||||||
|
|
||||||
$cache_key = 'frpTunnel_data_' . $host->client_token;
|
$cache_key = 'frpTunnel_data_' . $host->client_token;
|
||||||
// $tunnel = 'frp_user_' . $host->client_token;
|
|
||||||
// $tunnel_user_id = Cache::get($tunnel);
|
|
||||||
$tunnel_data = Cache::get($cache_key, null);
|
$tunnel_data = Cache::get($cache_key, null);
|
||||||
|
|
||||||
if (!is_null($tunnel_data)) {
|
if (!is_null($tunnel_data)) {
|
||||||
$traffic = ($tunnel_data['today_traffic_in'] ?? 0) + ($tunnel_data['today_traffic_out'] ?? 0);
|
$traffic = ($tunnel_data['today_traffic_in'] ?? 0) + ($tunnel_data['today_traffic_out'] ?? 0);
|
||||||
|
|
||||||
// $traffic = 1073741824 * 10;
|
|
||||||
|
|
||||||
Log::debug('本次使用的流量: ' . round($traffic / 1024 / 1024 / 1024, 2) ?? 0);
|
Log::debug('本次使用的流量: ' . round($traffic / 1024 / 1024 / 1024, 2) ?? 0);
|
||||||
|
|
||||||
$day = date('d');
|
$day = date('d');
|
||||||
@ -63,7 +51,6 @@ public function handle_old()
|
|||||||
|
|
||||||
$used_traffic_gb = round($used_traffic / 1024 / 1024 / 1024, 2);
|
$used_traffic_gb = round($used_traffic / 1024 / 1024 / 1024, 2);
|
||||||
|
|
||||||
// Log::debug('上次使用的流量: ' . $used_traffic);
|
|
||||||
Log::debug('上次使用的流量 GB: ' . $used_traffic_gb);
|
Log::debug('上次使用的流量 GB: ' . $used_traffic_gb);
|
||||||
|
|
||||||
$used_traffic = $traffic - $used_traffic;
|
$used_traffic = $traffic - $used_traffic;
|
||||||
@ -73,47 +60,11 @@ public function handle_old()
|
|||||||
|
|
||||||
$left_traffic = 0;
|
$left_traffic = 0;
|
||||||
|
|
||||||
if ($host->user->free_traffic > 0) {
|
|
||||||
Log::debug('开始扣除免费流量时的 used_traffic: ' . round($used_traffic / 1024 / 1024 / 1024, 2));
|
|
||||||
|
|
||||||
$user_free_traffic = round($host->user->free_traffic * 1024 * 1024 * 1024, 2);
|
|
||||||
|
|
||||||
Log::debug('用户免费流量: ' . round($user_free_traffic / 1024 / 1024 / 1024, 2));
|
|
||||||
|
|
||||||
// $used_traffic -= $user_free_traffic;
|
|
||||||
// $used_traffic = abs($used_traffic);
|
|
||||||
|
|
||||||
Log::debug('扣除免费流量时的 used_traffic: ' . $used_traffic / 1024 / 1024 / 1024);
|
|
||||||
|
|
||||||
// 获取剩余
|
|
||||||
$left_traffic = $user_free_traffic - $used_traffic;
|
|
||||||
|
|
||||||
Log::debug('计算后剩余的免费流量: ' . $left_traffic / 1024 / 1024 / 1024);
|
|
||||||
|
|
||||||
// 保存
|
|
||||||
|
|
||||||
if ($left_traffic < 0) {
|
|
||||||
$left_traffic = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 保留两位小数
|
|
||||||
$left_traffic = round($left_traffic / 1024 / 1024 / 1024, 2);
|
|
||||||
|
|
||||||
$host->user->free_traffic = $left_traffic;
|
|
||||||
$host->user->save();
|
|
||||||
}
|
|
||||||
|
|
||||||
$used_traffic = abs($used_traffic);
|
$used_traffic = abs($used_traffic);
|
||||||
|
|
||||||
Log::debug('实际用量:' . $used_traffic / 1024 / 1024 / 1024);
|
Log::debug('实际用量:' . $used_traffic / 1024 / 1024 / 1024);
|
||||||
|
|
||||||
// $used_traffic -= $server->free_traffic * 1024 * 1024 * 1024;
|
|
||||||
// // $used_traffic = abs($used_traffic);
|
|
||||||
|
|
||||||
// Log::debug('服务器免费流量: ' . $server->free_traffic * 1024 * 1024 * 1024);
|
|
||||||
|
|
||||||
// Log::debug('使用的流量(减去服务器免费流量): ' . $used_traffic);
|
|
||||||
|
|
||||||
if ($used_traffic > 0 && $left_traffic == 0) {
|
if ($used_traffic > 0 && $left_traffic == 0) {
|
||||||
Log::debug('此时 used_traffic: ' . $used_traffic);
|
Log::debug('此时 used_traffic: ' . $used_traffic);
|
||||||
|
|
||||||
@ -124,24 +75,10 @@ public function handle_old()
|
|||||||
|
|
||||||
$gb = round($traffic, 2);
|
$gb = round($traffic, 2);
|
||||||
|
|
||||||
// 计算价格
|
Log::debug('此时 traffic: ' . $traffic);
|
||||||
$cost = $traffic * $host->server->price_per_gb;
|
|
||||||
$cost = abs($cost);
|
|
||||||
|
|
||||||
// 记录到日志
|
// lock for update
|
||||||
// if local
|
$host->user->balance -= $traffic * $host->user->cost;
|
||||||
// if (config('app.env') == 'local') {
|
|
||||||
Log::debug('计费:' . $host->server->name . ' ' . $host->name . ' ' . $gb . 'GB ' . $cost . ' 的 CNY 消耗');
|
|
||||||
// }
|
|
||||||
|
|
||||||
// 如果计费金额大于 0,则扣费
|
|
||||||
if ($cost > 0) {
|
|
||||||
// 发送扣费请求
|
|
||||||
$this->http->post('hosts/' . $host->host_id . '/cost', [
|
|
||||||
'amount' => $cost,
|
|
||||||
'description' => $host->name . ' 的 ' . $gb . ' GB 流量费用。',
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,6 +56,9 @@ public function close()
|
|||||||
$cache_key = 'frpTunnel_data_' . $this->client_token;
|
$cache_key = 'frpTunnel_data_' . $this->client_token;
|
||||||
Cache::forget($cache_key);
|
Cache::forget($cache_key);
|
||||||
|
|
||||||
|
$cache_key = 'frpTunnel_data_' . $this->client_token . '_lock';
|
||||||
|
Cache::put($cache_key, 1, 30);
|
||||||
|
|
||||||
$this->run_id = null;
|
$this->run_id = null;
|
||||||
$this->saveQuietly();
|
$this->saveQuietly();
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ class User extends Authenticatable
|
|||||||
'name',
|
'name',
|
||||||
'email',
|
'email',
|
||||||
'password',
|
'password',
|
||||||
'auth_code'
|
'traffic'
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -17,6 +17,9 @@ public function up(): void
|
|||||||
$table->string('email')->unique();
|
$table->string('email')->unique();
|
||||||
$table->timestamp('email_verified_at')->nullable();
|
$table->timestamp('email_verified_at')->nullable();
|
||||||
$table->string('password');
|
$table->string('password');
|
||||||
|
|
||||||
|
$table->bigInteger('traffic')->default(0)->comment('流量');
|
||||||
|
|
||||||
$table->rememberToken();
|
$table->rememberToken();
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
});
|
});
|
||||||
|
@ -1,24 +1,24 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<h1>Index</h1>
|
<h1>欢迎</h1>
|
||||||
<p>Index page</p>
|
|
||||||
<p>Current time: {{ time }}</p>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div class="mt-3">
|
||||||
<p>用户名: {{ user.name }}</p>
|
<p>用户名: {{ user.name }}</p>
|
||||||
|
<p>剩余流量: {{ user.traffic }}GB</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import http from '../plugins/http'
|
import http from '../plugins/http'
|
||||||
const time = ref(new Date().toLocaleTimeString());
|
|
||||||
|
|
||||||
|
|
||||||
const user = ref({
|
const user = ref({
|
||||||
name: 'loading...'
|
name: 'loading...',
|
||||||
|
traffic: ''
|
||||||
})
|
})
|
||||||
|
|
||||||
http.get('user').then((res) => {
|
http.get('user').then((res) => {
|
||||||
@ -26,9 +26,4 @@ http.get('user').then((res) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
http.get('tunnels').then((res) => {
|
|
||||||
console.log(res.data)
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
<template>
|
|
||||||
<h1>您名下的隧道</h1>
|
|
||||||
</template>
|
|
@ -9,9 +9,9 @@
|
|||||||
<th scope="col">协议</th>
|
<th scope="col">协议</th>
|
||||||
<th scope="col">本地地址</th>
|
<th scope="col">本地地址</th>
|
||||||
<th scope="col">远程端口/域名</th>
|
<th scope="col">远程端口/域名</th>
|
||||||
<th scope="col">连接数</th>
|
<!-- <th scope="col">连接数</th>
|
||||||
<th scope="col">下载流量</th>
|
<th scope="col">下载流量</th>
|
||||||
<th scope="col">上载流量</th>
|
<th scope="col">上载流量</th> -->
|
||||||
<th scope="col">服务器</th>
|
<th scope="col">服务器</th>
|
||||||
<th scope="col">状态</th>
|
<th scope="col">状态</th>
|
||||||
</tr>
|
</tr>
|
||||||
@ -52,9 +52,9 @@
|
|||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td>0</td>
|
<!-- <td>0</td>
|
||||||
<td>0.000 Bytes</td>
|
|
||||||
<td>0.000 Bytes</td>
|
<td>0.000 Bytes</td>
|
||||||
|
<td>0.000 Bytes</td> -->
|
||||||
|
|
||||||
<td>{{ tunnel.server.name }}</td>
|
<td>{{ tunnel.server.name }}</td>
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<div v-show="chart" id="chart" style="height: 400px"></div>
|
<div id="chart" style="height: 400px"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
@ -16,6 +16,10 @@
|
|||||||
</pre>
|
</pre>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- <div v-if="tunnel.tunnel">
|
||||||
|
|
||||||
|
</div> -->
|
||||||
|
|
||||||
<div v-if="tunnel.run_id" class="mb-3">
|
<div v-if="tunnel.run_id" class="mb-3">
|
||||||
<h2>强制下线</h2>
|
<h2>强制下线</h2>
|
||||||
<button class="btn btn-primary" @click="kickTunnel()">强制下线</button>
|
<button class="btn btn-primary" @click="kickTunnel()">强制下线</button>
|
||||||
@ -34,6 +38,7 @@ import { onMounted, onUnmounted, ref } from "vue";
|
|||||||
import http from "../../plugins/http";
|
import http from "../../plugins/http";
|
||||||
import router from "../../plugins/router";
|
import router from "../../plugins/router";
|
||||||
import * as echarts from "echarts";
|
import * as echarts from "echarts";
|
||||||
|
import Humanize from 'humanize-plus'
|
||||||
const showChart = ref(false);
|
const showChart = ref(false);
|
||||||
let chart = undefined;
|
let chart = undefined;
|
||||||
|
|
||||||
@ -128,11 +133,13 @@ let chartOptions = {
|
|||||||
|
|
||||||
function initChart() {
|
function initChart() {
|
||||||
let chartDom = document.getElementById("chart");
|
let chartDom = document.getElementById("chart");
|
||||||
|
|
||||||
chart = echarts.init(chartDom, {
|
chart = echarts.init(chartDom, {
|
||||||
backgroundColor: "transparent",
|
backgroundColor: "transparent",
|
||||||
renderer: "svg",
|
renderer: "svg",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
chartOptions && chart.setOption(chartOptions);
|
chartOptions && chart.setOption(chartOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,7 +154,9 @@ function deleteTunnel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function kickTunnel() {
|
function kickTunnel() {
|
||||||
http.post(`/tunnels/${tunnel_id}/close`);
|
http.post(`/tunnels/${tunnel_id}/close`).then(() => {
|
||||||
|
refresh();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function refresh() {
|
function refresh() {
|
||||||
@ -160,8 +169,12 @@ function refresh() {
|
|||||||
// console.log(res.data);
|
// console.log(res.data);
|
||||||
|
|
||||||
if (res.data.traffic) {
|
if (res.data.traffic) {
|
||||||
|
|
||||||
|
console.log(res.data.traffic)
|
||||||
|
console.log(showChart.value)
|
||||||
|
|
||||||
if (!showChart.value) {
|
if (!showChart.value) {
|
||||||
// initChart()
|
initChart()
|
||||||
showChart.value = true;
|
showChart.value = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
function updateTraffic(userId, input) {
|
function updateTraffic(userId, input) {
|
||||||
const url = '/users/' + userId
|
const url = '/admin/users/' + userId
|
||||||
// xml http request
|
// xml http request
|
||||||
const xhr = new XMLHttpRequest();
|
const xhr = new XMLHttpRequest();
|
||||||
xhr.open('PATCH', url);
|
xhr.open('PATCH', url);
|
||||||
|
Loading…
Reference in New Issue
Block a user