后台客户端页面

This commit is contained in:
cyq 2023-07-27 12:17:11 +08:00
parent 12c4fa076b
commit 2fcb368848
12 changed files with 232 additions and 116 deletions

View File

@ -0,0 +1,70 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use App\Models\Client;
use Illuminate\View\View;
class ClientController extends Controller
{
/**
* Display a listing of the clients.
*
* @return View
*/
public function index(): View
{
$clients = Client::all();
$count = $clients->count();
return view('admin.clients.index', ['clients' => $clients, 'count' => $count]);
}
public function create(Request $request): View
{
return view('admin.clients.create');
}
public function edit(Client $client): View
{
return view('admin.clients.edit', ['client' => $client]);
}
public function store(Request $request): RedirectResponse
{
$request->validate([
'name' => 'required|max:80',
'arch' => 'required|max:30',
'url' => 'required',
'author' => 'required|max:30',
]);
$request_data = $request->toArray();
Client::create($request_data);
return redirect()->route('admin.clients.index')->with('success', '创建成功');
}
public function update(Request $request, Client $client)
{
$request->validate([
'name' => 'required|max:80',
'arch' => 'required|max:30',
'url' => 'required',
'author' => 'required|max:30',
]);
$data = $request->all();
$client->update($data);
return redirect()->route('admin.clients.index')->with('success', '客户端更新成功');
}
public function destroy(Client $client)
{
$client->delete();
return redirect()->route('admin.clients.index')->with('success', '客户端删除成功');
}
}

View File

@ -0,0 +1,17 @@
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\Client;
use Illuminate\Http\JsonResponse;
class ClientController extends Controller
{
public function index(): JsonResponse
{
$clients = Client::all();
return $this->success($clients);
}
}

15
app/Models/Client.php Normal file
View File

@ -0,0 +1,15 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Client extends Model
{
protected $fillable = [
'name',
'arch',
'url',
'author',
];
}

View File

@ -0,0 +1,31 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('clients', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('arch');
$table->string('url');
$table->string('author');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('clients');
}
};

BIN
dump.rdb Normal file

Binary file not shown.

View File

@ -6,6 +6,7 @@
<tr>
<th>名称</th>
<th>架构</th>
<th>作者</th>
<th>下载</th>
</tr>
</thead>
@ -14,6 +15,7 @@
<tr v-for="i in items">
<td>{{ i.name }}</td>
<td>{{ i.arch }}</td>
<td>{{ i.author }}</td>
<td>
<a :href="i.url">下载</a>
</td>
@ -24,119 +26,11 @@
<script setup>
import { ref } from "vue";
import http from '../plugins/http'
const version = [
{
name: "Windows Frpc",
arch: "amd64",
url: "https://download.muhanfrp.cn/frp_0.46.1_windows_amd64.zip",
},
{
name: "Windows Frpc",
arch: "i386",
url: "https://download.muhanfrp.cn/frp_0.46.1_windows_386.zip",
},
{
name: "Linux Frpc i386",
arch: "i386",
url: "https://download.muhanfrp.cn/frp_0.46.1_linux_386.tar.gz",
},
{
name: "Linux Frpc amd64",
arch: "amd64",
url: "https://download.muhanfrp.cn/frp_0.46.1_linux_amd64.tar.gz",
},
{
name: "Linux Frpc arm32",
arch: "arm32",
url: "https://download.muhanfrp.cn/frp_0.46.1_linux_arm32.tar.gz",
},
{
name: "Linux Frpc arm64",
arch: "arm64",
url: "https://download.muhanfrp.cn/frp_0.46.1_linux_arm64.tar.gz",
},
{
name: "Darwin Frpc amd64",
arch: "amd64",
url: "https://download.muhanfrp.cn/frp_0.46.1_darwin_amd64.tar.gz",
},
{
name: "Darwin Frpc arm64",
arch: "arm64",
url: "https://download.muhanfrp.cn/frp_0.46.1_darwin_arm64.tar.gz",
},
{
name: "Freebsd Frpc i386",
arch: "i386",
url: "https://download.muhanfrp.cn/frp_0.46.1_freebsd_386.tar.gz",
},
{
name: "Freebsd Frpc arm64",
arch: "arm64",
url: "https://download.muhanfrp.cn/frp_0.46.1_freebsd_amd64.tar.gz",
},
{
name: "Mips Frpc i386",
arch: "i386",
url: "https://download.muhanfrp.cn/frp_0.46.1_linux_mips.tar.gz",
},
{
name: "Mips Frpc amd64",
arch: "amd64",
url: "https://download.muhanfrp.cn/frp_0.46.1_linux_mips64.tar.gz",
},
{
name: "Mipsle Frpc i386",
arch: "i386",
url: "https://download.muhanfrp.cn/frp_0.46.1_linux_mipsle.tar.gz",
},
{
name: "Mipsle Frpc amd64",
arch: "amd64",
url: "https://download.muhanfrp.cn/frp_0.46.1_linux_mips64le.tar.gz",
},
{
name: "Riscv Frpc amd64",
arch: "amd64",
url: "https://download.muhanfrp.cn/frp_0.46.1_linux_riscv64.tar.gz",
},
{
name: "android-v0.39.1.1 Frpc 图形客户端",
arch: "android",
url: "https://download.muhanfrp.cn/frpc_android-v0.39.1.1.apk",
},
{
name: "android-v0.31.2 Frpc 图形客户端",
arch: "android",
url: "https://download.muhanfrp.cn/FRP.apk",
},
{
name: "Termux 客户端 ",
arch: "android",
url: "https://download.muhanfrp.cn/com.termux_118.apk",
},
{
name: "Windows PortIO_Python 图形客户端",
arch: "86-64",
url: "https://download.muhanfrp.cn/PortIO_Client.zip"
},
{
name: "Windows PortIO_Client_CLI_Python 命令行图形客户端",
arch: "86-64",
url: "https://download.muhanfrp.cn/PortIO_Client_CLI.exe",
},
{
name: "Windows PortIO_Pascal 图形客户端",
arch: "86-64",
url: "https://download.muhanfrp.cn/pioc_windows_x86_64.zip",
},
{
name: "Linux PortIO_Pascal 图形客户端",
arch: "86-64",
url: "https://download.muhanfrp.cn/pioc_linux_x86_64.tar.gz",
},
];
const items = ref([])
const items = ref(version);
http.get('clients').then((res) => {
items.value = res.data
})
</script>

View File

@ -0,0 +1,19 @@
<x-app-layout>
<h3 class="mb-3">创建客户端</h3>
<form action="{{ route('admin.clients.store') }}" method="post">
@csrf
<label for="name" class="form-label">名称</label>
<input type="text" name="name" id="name" placeholder="名称" class="form-control mb-3" required>
<label for="name" class="form-label">架构</label>
<input type="text" name="arch" id="arch" placeholder="架构" class="form-control mb-3" required>
<label for="name" class="form-label">下载链接</label>
<input type="text" name="url" id="url" placeholder="下载链接" class="form-control mb-3" required>
<label for="name" class="form-label">作者</label>
<input type="text" name="author" id="author" placeholder="作者" class="form-control mb-3" required>
<button class="btn btn-primary" type="submit">创建</button>
</form>
</x-app-layout>

View File

@ -0,0 +1,20 @@
<x-app-layout>
<h3 class="mb-3">编辑客户端</h3>
<form action="{{ route('admin.clients.update', $client->id) }}" method="post">
@csrf
@method('PUT')
<label for="name" class="form-label">名称</label>
<input type="text" name="name" id="name" placeholder="名称" class="form-control mb-3" required value="{{ $client->name }}">
<label for="name" class="form-label">架构</label>
<input type="text" name="arch" id="arch" placeholder="架构" class="form-control mb-3" required value="{{ $client->arch }}">
<label for="name" class="form-label">下载链接</label>
<input type="text" name="url" id="url" placeholder="下载链接" class="form-control mb-3" required value="{{ $client->url }}">
<label for="name" class="form-label">作者</label>
<input type="text" name="author" id="author" placeholder="作者" class="form-control mb-3" required value="{{ $client->author }}">
<button class="btn btn-primary" type="submit">保存更改</button>
</form>
</x-app-layout>

View File

@ -0,0 +1,45 @@
<x-app-layout>
<h3>客户端</h3>
<a href="{{ route('admin.clients.create') }}">新建客户端</a>
<div class="alert alert-primary mt-3" role="alert">
总计: {{ $count }}
</div>
<table class="mt-3 table table-hover text-center table-bordered" style="vertical-align: middle">
<thead>
<tr>
<th>ID</th>
<th>名称</th>
<th>架构</th>
<th>下载链接</th>
<th>操作</th>
</tr>
</thead>
<tbody>
@foreach ($clients as $client)
<tr>
<td>{{ $client->id }}</td>
<td>{{ $client->name }}</td>
<td>{{ $client->arch }}</td>
<td>
<a target="_blank" href="{{ $client->url }}">{{ $client->url }}</a>
</td>
<td>
<a href="{{ route('admin.clients.edit', ['client' => $client]) }}"
class="btn btn-sm btn-primary mb-2">编辑</a>
<form action="{{ route('admin.clients.destroy', ['client' => $client]) }}" method="POST"
onsubmit="return confirm('真的要删除吗?')">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-sm btn-danger">删除</button>
</form>
</td>
</tr>
@endforeach
</tbody>
</table>
</x-app-layout>

View File

@ -39,6 +39,9 @@
<li class="nav-item">
<a class="nav-link" href="{{ route('admin.servers.index') }}">服务器</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ route('admin.clients.index') }}">客户端</a>
</li>
</ul>
<ul class="navbar-nav ml-auto mb-2 mb-lg-0">
<li class="nav-item">

View File

@ -2,11 +2,9 @@
use App\Http\Controllers\Admin\TunnelController;
use App\Http\Controllers\Admin\IndexController;
use App\Http\Controllers\Admin\ReplyController;
use App\Http\Controllers\Admin\ReviewController;
use App\Http\Controllers\Admin\ServerController;
use App\Http\Controllers\Admin\UserController;
use App\Http\Controllers\Admin\WorkOrderController;
use App\Http\Controllers\Admin\ClientController;
use Illuminate\Support\Facades\Route;
Route::withoutMiddleware('auth:admin')->group(function() {
@ -21,6 +19,7 @@
Route::resource('users', UserController::class);
Route::resource('servers', ServerController::class);
Route::resource('tunnels', TunnelController::class);
Route::resource('clients', ClientController::class);
Route::get('/logout', [IndexController::class, 'logout'])->name('logout');

View File

@ -9,6 +9,7 @@
use App\Http\Controllers\Api\TicketController;
use App\Http\Controllers\Api\TrafficController;
use App\Http\Controllers\Application\UserController as ApplicationUserController;
use App\Http\Controllers\Api\ClientController;
Route::prefix('tunnel')->name('api.tunnel.')->group(function () {
Route::post('/handler/{key}', [PortManagerController::class, 'handler'])->name('handler');
@ -21,6 +22,8 @@
Route::post('tunnels/{tunnel}/close', [TunnelController::class, 'close']);
Route::apiResource('servers', ServerController::class);
Route::apiResource('clients', ClientController::class);
Route::get('traffic', [TrafficController::class, 'free']);
Route::post('traffic', [TrafficController::class, 'sign']);