mirror of
https://github.com/v2board/v2board.git
synced 2024-11-10 09:39:10 +08:00
update: add vless
This commit is contained in:
parent
1a30aa30ad
commit
4c865d0262
117
app/Http/Controllers/V1/Admin/Server/VlessController.php
Normal file
117
app/Http/Controllers/V1/Admin/Server/VlessController.php
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\V1\Admin\Server;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\ServerVless;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use ParagonIE_Sodium_Compat as SodiumCompat;
|
||||||
|
|
||||||
|
class VlessController extends Controller
|
||||||
|
{
|
||||||
|
public function save(Request $request)
|
||||||
|
{
|
||||||
|
$params = $request->validate([
|
||||||
|
'group_id' => 'required',
|
||||||
|
'route_id' => 'nullable|array',
|
||||||
|
'name' => 'required',
|
||||||
|
'parent_id' => 'nullable|integer',
|
||||||
|
'host' => 'required',
|
||||||
|
'port' => 'required',
|
||||||
|
'server_port' => 'required',
|
||||||
|
'tls' => 'required|in:0,1',
|
||||||
|
'tls_settings' => 'nullable|array',
|
||||||
|
'flow' => 'nullable',
|
||||||
|
'network' => 'required',
|
||||||
|
'network_settings' => 'nullable|array',
|
||||||
|
'tags' => 'nullable|array',
|
||||||
|
'rate' => 'required',
|
||||||
|
'show' => 'nullable|in:0,1',
|
||||||
|
'sort' => 'nullable'
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ((int)$params['tls_settings']['reality']) {
|
||||||
|
$keyPair = SodiumCompat::crypto_box_keypair();
|
||||||
|
if (!isset($params['tls_settings']['public_key'])) {
|
||||||
|
$params['tls_settings']['public_key'] = base64_encode(SodiumCompat::crypto_box_publickey($keyPair));
|
||||||
|
}
|
||||||
|
if (!isset($params['tls_settings']['private_key'])) {
|
||||||
|
$params['tls_settings']['private_key'] = base64_encode(SodiumCompat::crypto_box_secretkey($keyPair));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->input('id')) {
|
||||||
|
$server = ServerVless::find($request->input('id'));
|
||||||
|
if (!$server) {
|
||||||
|
abort(500, '服务器不存在');
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
$server->update($params);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
abort(500, '保存失败');
|
||||||
|
}
|
||||||
|
return response([
|
||||||
|
'data' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ServerVless::create($params)) {
|
||||||
|
abort(500, '创建失败');
|
||||||
|
}
|
||||||
|
|
||||||
|
return response([
|
||||||
|
'data' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function drop(Request $request)
|
||||||
|
{
|
||||||
|
if ($request->input('id')) {
|
||||||
|
$server = ServerVless::find($request->input('id'));
|
||||||
|
if (!$server) {
|
||||||
|
abort(500, '节点ID不存在');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return response([
|
||||||
|
'data' => $server->delete()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(Request $request)
|
||||||
|
{
|
||||||
|
$params = $request->validate([
|
||||||
|
'show' => 'nullable|in:0,1',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$server = ServerVless::find($request->input('id'));
|
||||||
|
|
||||||
|
if (!$server) {
|
||||||
|
abort(500, '该服务器不存在');
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
$server->update($params);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
abort(500, '保存失败');
|
||||||
|
}
|
||||||
|
|
||||||
|
return response([
|
||||||
|
'data' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function copy(Request $request)
|
||||||
|
{
|
||||||
|
$server = ServerVless::find($request->input('id'));
|
||||||
|
$server->show = 0;
|
||||||
|
if (!$server) {
|
||||||
|
abort(500, '服务器不存在');
|
||||||
|
}
|
||||||
|
if (!ServerVless::create($server->toArray())) {
|
||||||
|
abort(500, '复制失败');
|
||||||
|
}
|
||||||
|
|
||||||
|
return response([
|
||||||
|
'data' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
@ -36,43 +36,42 @@ class AdminRoute
|
|||||||
$router->group([
|
$router->group([
|
||||||
'prefix' => 'server/trojan'
|
'prefix' => 'server/trojan'
|
||||||
], function ($router) {
|
], function ($router) {
|
||||||
$router->get ('fetch', 'V1\\Admin\\Server\\TrojanController@fetch');
|
|
||||||
$router->post('save', 'V1\\Admin\\Server\\TrojanController@save');
|
$router->post('save', 'V1\\Admin\\Server\\TrojanController@save');
|
||||||
$router->post('drop', 'V1\\Admin\\Server\\TrojanController@drop');
|
$router->post('drop', 'V1\\Admin\\Server\\TrojanController@drop');
|
||||||
$router->post('update', 'V1\\Admin\\Server\\TrojanController@update');
|
$router->post('update', 'V1\\Admin\\Server\\TrojanController@update');
|
||||||
$router->post('copy', 'V1\\Admin\\Server\\TrojanController@copy');
|
$router->post('copy', 'V1\\Admin\\Server\\TrojanController@copy');
|
||||||
$router->post('sort', 'V1\\Admin\\Server\\TrojanController@sort');
|
|
||||||
$router->post('viewConfig', 'V1\\Admin\\Server\\TrojanController@viewConfig');
|
|
||||||
});
|
});
|
||||||
$router->group([
|
$router->group([
|
||||||
'prefix' => 'server/vmess'
|
'prefix' => 'server/vmess'
|
||||||
], function ($router) {
|
], function ($router) {
|
||||||
$router->get ('fetch', 'V1\\Admin\\Server\\VmessController@fetch');
|
|
||||||
$router->post('save', 'V1\\Admin\\Server\\VmessController@save');
|
$router->post('save', 'V1\\Admin\\Server\\VmessController@save');
|
||||||
$router->post('drop', 'V1\\Admin\\Server\\VmessController@drop');
|
$router->post('drop', 'V1\\Admin\\Server\\VmessController@drop');
|
||||||
$router->post('update', 'V1\\Admin\\Server\\VmessController@update');
|
$router->post('update', 'V1\\Admin\\Server\\VmessController@update');
|
||||||
$router->post('copy', 'V1\\Admin\\Server\\VmessController@copy');
|
$router->post('copy', 'V1\\Admin\\Server\\VmessController@copy');
|
||||||
$router->post('sort', 'V1\\Admin\\Server\\VmessController@sort');
|
|
||||||
});
|
});
|
||||||
$router->group([
|
$router->group([
|
||||||
'prefix' => 'server/shadowsocks'
|
'prefix' => 'server/shadowsocks'
|
||||||
], function ($router) {
|
], function ($router) {
|
||||||
$router->get ('fetch', 'V1\\Admin\\Server\\ShadowsocksController@fetch');
|
|
||||||
$router->post('save', 'V1\\Admin\\Server\\ShadowsocksController@save');
|
$router->post('save', 'V1\\Admin\\Server\\ShadowsocksController@save');
|
||||||
$router->post('drop', 'V1\\Admin\\Server\\ShadowsocksController@drop');
|
$router->post('drop', 'V1\\Admin\\Server\\ShadowsocksController@drop');
|
||||||
$router->post('update', 'V1\\Admin\\Server\\ShadowsocksController@update');
|
$router->post('update', 'V1\\Admin\\Server\\ShadowsocksController@update');
|
||||||
$router->post('copy', 'V1\\Admin\\Server\\ShadowsocksController@copy');
|
$router->post('copy', 'V1\\Admin\\Server\\ShadowsocksController@copy');
|
||||||
$router->post('sort', 'V1\\Admin\\Server\\ShadowsocksController@sort');
|
|
||||||
});
|
});
|
||||||
$router->group([
|
$router->group([
|
||||||
'prefix' => 'server/hysteria'
|
'prefix' => 'server/hysteria'
|
||||||
], function ($router) {
|
], function ($router) {
|
||||||
$router->get ('fetch', 'V1\\Admin\\Server\\HysteriaController@fetch');
|
|
||||||
$router->post('save', 'V1\\Admin\\Server\\HysteriaController@save');
|
$router->post('save', 'V1\\Admin\\Server\\HysteriaController@save');
|
||||||
$router->post('drop', 'V1\\Admin\\Server\\HysteriaController@drop');
|
$router->post('drop', 'V1\\Admin\\Server\\HysteriaController@drop');
|
||||||
$router->post('update', 'V1\\Admin\\Server\\HysteriaController@update');
|
$router->post('update', 'V1\\Admin\\Server\\HysteriaController@update');
|
||||||
$router->post('copy', 'V1\\Admin\\Server\\HysteriaController@copy');
|
$router->post('copy', 'V1\\Admin\\Server\\HysteriaController@copy');
|
||||||
$router->post('sort', 'V1\\Admin\\Server\\HysteriaController@sort');
|
});
|
||||||
|
$router->group([
|
||||||
|
'prefix' => 'server/vless'
|
||||||
|
], function ($router) {
|
||||||
|
$router->post('save', 'V1\\Admin\\Server\\VlessController@save');
|
||||||
|
$router->post('drop', 'V1\\Admin\\Server\\VlessController@drop');
|
||||||
|
$router->post('update', 'V1\\Admin\\Server\\VlessController@update');
|
||||||
|
$router->post('copy', 'V1\\Admin\\Server\\VlessController@copy');
|
||||||
});
|
});
|
||||||
// Order
|
// Order
|
||||||
$router->get ('/order/fetch', 'V1\\Admin\\OrderController@fetch');
|
$router->get ('/order/fetch', 'V1\\Admin\\OrderController@fetch');
|
||||||
|
21
app/Models/ServerVless.php
Executable file
21
app/Models/ServerVless.php
Executable file
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class ServerVless extends Model
|
||||||
|
{
|
||||||
|
protected $table = 'v2_server_vless';
|
||||||
|
protected $dateFormat = 'U';
|
||||||
|
protected $guarded = ['id'];
|
||||||
|
protected $casts = [
|
||||||
|
'created_at' => 'timestamp',
|
||||||
|
'updated_at' => 'timestamp',
|
||||||
|
'group_id' => 'array',
|
||||||
|
'route_id' => 'array',
|
||||||
|
'tls_settings' => 'array',
|
||||||
|
'network_settings' => 'array',
|
||||||
|
'tags' => 'array'
|
||||||
|
];
|
||||||
|
}
|
@ -6,6 +6,7 @@ use App\Models\ServerHysteria;
|
|||||||
use App\Models\ServerLog;
|
use App\Models\ServerLog;
|
||||||
use App\Models\ServerRoute;
|
use App\Models\ServerRoute;
|
||||||
use App\Models\ServerShadowsocks;
|
use App\Models\ServerShadowsocks;
|
||||||
|
use App\Models\ServerVless;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use App\Models\ServerVmess;
|
use App\Models\ServerVmess;
|
||||||
use App\Models\ServerTrojan;
|
use App\Models\ServerTrojan;
|
||||||
@ -15,6 +16,29 @@ use Illuminate\Support\Facades\Cache;
|
|||||||
|
|
||||||
class ServerService
|
class ServerService
|
||||||
{
|
{
|
||||||
|
public function getAvailableVless(User $user):array
|
||||||
|
{
|
||||||
|
$servers = [];
|
||||||
|
$model = ServerVless::orderBy('sort', 'ASC');
|
||||||
|
$server = $model->get();
|
||||||
|
foreach ($server as $key => $v) {
|
||||||
|
if (!$v['show']) continue;
|
||||||
|
$server[$key]['type'] = 'vless';
|
||||||
|
if (!in_array($user->group_id, $server[$key]['group_id'])) continue;
|
||||||
|
if (strpos($server[$key]['port'], '-') !== false) {
|
||||||
|
$server[$key]['port'] = Helper::randomPort($server[$key]['port']);
|
||||||
|
}
|
||||||
|
if ($server[$key]['parent_id']) {
|
||||||
|
$server[$key]['last_check_at'] = Cache::get(CacheKey::get('SERVER_VLESS_LAST_CHECK_AT', $server[$key]['parent_id']));
|
||||||
|
} else {
|
||||||
|
$server[$key]['last_check_at'] = Cache::get(CacheKey::get('SERVER_VLESS_LAST_CHECK_AT', $server[$key]['id']));
|
||||||
|
}
|
||||||
|
$servers[] = $server[$key]->toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return $servers;
|
||||||
|
}
|
||||||
|
|
||||||
public function getAvailableVmess(User $user):array
|
public function getAvailableVmess(User $user):array
|
||||||
{
|
{
|
||||||
@ -113,7 +137,8 @@ class ServerService
|
|||||||
$this->getAvailableShadowsocks($user),
|
$this->getAvailableShadowsocks($user),
|
||||||
$this->getAvailableVmess($user),
|
$this->getAvailableVmess($user),
|
||||||
$this->getAvailableTrojan($user),
|
$this->getAvailableTrojan($user),
|
||||||
$this->getAvailableHysteria($user)
|
$this->getAvailableHysteria($user),
|
||||||
|
$this->getAvailableVless($user)
|
||||||
);
|
);
|
||||||
$tmp = array_column($servers, 'sort');
|
$tmp = array_column($servers, 'sort');
|
||||||
array_multisort($tmp, SORT_ASC, $servers);
|
array_multisort($tmp, SORT_ASC, $servers);
|
||||||
@ -196,6 +221,17 @@ class ServerService
|
|||||||
return $servers;
|
return $servers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getAllVLess()
|
||||||
|
{
|
||||||
|
$servers = ServerVless::orderBy('sort', 'ASC')
|
||||||
|
->get()
|
||||||
|
->toArray();
|
||||||
|
foreach ($servers as $k => $v) {
|
||||||
|
$servers[$k]['type'] = 'vless';
|
||||||
|
}
|
||||||
|
return $servers;
|
||||||
|
}
|
||||||
|
|
||||||
public function getAllTrojan()
|
public function getAllTrojan()
|
||||||
{
|
{
|
||||||
$servers = ServerTrojan::orderBy('sort', 'ASC')
|
$servers = ServerTrojan::orderBy('sort', 'ASC')
|
||||||
@ -241,7 +277,8 @@ class ServerService
|
|||||||
$this->getAllShadowsocks(),
|
$this->getAllShadowsocks(),
|
||||||
$this->getAllVMess(),
|
$this->getAllVMess(),
|
||||||
$this->getAllTrojan(),
|
$this->getAllTrojan(),
|
||||||
$this->getAllHysteria()
|
$this->getAllHysteria(),
|
||||||
|
$this->getAllVLess()
|
||||||
);
|
);
|
||||||
$this->mergeData($servers);
|
$this->mergeData($servers);
|
||||||
$tmp = array_column($servers, 'sort');
|
$tmp = array_column($servers, 'sort');
|
||||||
@ -272,6 +309,8 @@ class ServerService
|
|||||||
return ServerTrojan::find($serverId);
|
return ServerTrojan::find($serverId);
|
||||||
case 'hysteria':
|
case 'hysteria':
|
||||||
return ServerHysteria::find($serverId);
|
return ServerHysteria::find($serverId);
|
||||||
|
case 'vless':
|
||||||
|
return ServerVless::find($serverId);
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,9 @@ class CacheKey
|
|||||||
'SERVER_HYSTERIA_ONLINE_USER' => 'hysteria节点在线用户',
|
'SERVER_HYSTERIA_ONLINE_USER' => 'hysteria节点在线用户',
|
||||||
'SERVER_HYSTERIA_LAST_CHECK_AT' => 'hysteria节点最后检查时间',
|
'SERVER_HYSTERIA_LAST_CHECK_AT' => 'hysteria节点最后检查时间',
|
||||||
'SERVER_HYSTERIA_LAST_PUSH_AT' => 'hysteria节点最后推送时间',
|
'SERVER_HYSTERIA_LAST_PUSH_AT' => 'hysteria节点最后推送时间',
|
||||||
|
'SERVER_VLESS_ONLINE_USER' => 'vless节点在线用户',
|
||||||
|
'SERVER_VLESS_LAST_CHECK_AT' => 'vless节点最后检查时间',
|
||||||
|
'SERVER_VLESS_LAST_PUSH_AT' => 'vless节点最后推送时间',
|
||||||
'TEMP_TOKEN' => '临时令牌',
|
'TEMP_TOKEN' => '临时令牌',
|
||||||
'LAST_SEND_EMAIL_REMIND_TRAFFIC' => '最后发送流量邮件提醒',
|
'LAST_SEND_EMAIL_REMIND_TRAFFIC' => '最后发送流量邮件提醒',
|
||||||
'SCHEDULE_LAST_CHECK_AT' => '计划任务最后检查时间',
|
'SCHEDULE_LAST_CHECK_AT' => '计划任务最后检查时间',
|
||||||
|
@ -23,7 +23,8 @@
|
|||||||
"linfo/linfo": "^4.0",
|
"linfo/linfo": "^4.0",
|
||||||
"php-curl-class/php-curl-class": "^8.6",
|
"php-curl-class/php-curl-class": "^8.6",
|
||||||
"stripe/stripe-php": "^7.36.1",
|
"stripe/stripe-php": "^7.36.1",
|
||||||
"symfony/yaml": "^4.3"
|
"symfony/yaml": "^4.3",
|
||||||
|
"paragonie/sodium_compat": "^1.20"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"facade/ignition": "^2.3.6",
|
"facade/ignition": "^2.3.6",
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
-- Adminer 4.7.7 MySQL dump
|
-- Adminer 4.8.1 MySQL 5.7.29 dump
|
||||||
|
|
||||||
SET NAMES utf8;
|
SET NAMES utf8;
|
||||||
SET time_zone = '+00:00';
|
SET time_zone = '+00:00';
|
||||||
@ -84,7 +84,7 @@ CREATE TABLE `v2_knowledge` (
|
|||||||
DROP TABLE IF EXISTS `v2_log`;
|
DROP TABLE IF EXISTS `v2_log`;
|
||||||
CREATE TABLE `v2_log` (
|
CREATE TABLE `v2_log` (
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
`title` varchar(255) NOT NULL,
|
`title` text NOT NULL,
|
||||||
`level` varchar(11) DEFAULT NULL,
|
`level` varchar(11) DEFAULT NULL,
|
||||||
`host` varchar(255) DEFAULT NULL,
|
`host` varchar(255) DEFAULT NULL,
|
||||||
`uri` varchar(255) NOT NULL,
|
`uri` varchar(255) NOT NULL,
|
||||||
@ -294,6 +294,31 @@ CREATE TABLE `v2_server_trojan` (
|
|||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='trojan伺服器表';
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='trojan伺服器表';
|
||||||
|
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `v2_server_vless`;
|
||||||
|
CREATE TABLE `v2_server_vless` (
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`group_id` text NOT NULL,
|
||||||
|
`route_id` text,
|
||||||
|
`name` varchar(255) NOT NULL,
|
||||||
|
`parent_id` int(11) DEFAULT NULL,
|
||||||
|
`host` varchar(255) NOT NULL,
|
||||||
|
`port` int(11) NOT NULL,
|
||||||
|
`server_port` int(11) NOT NULL,
|
||||||
|
`tls` tinyint(1) NOT NULL,
|
||||||
|
`tls_settings` text,
|
||||||
|
`flow` varchar(11) DEFAULT NULL,
|
||||||
|
`network` varchar(11) NOT NULL,
|
||||||
|
`network_settings` text,
|
||||||
|
`tags` text,
|
||||||
|
`rate` varchar(11) NOT NULL,
|
||||||
|
`show` tinyint(1) NOT NULL DEFAULT '0',
|
||||||
|
`sort` int(11) DEFAULT NULL,
|
||||||
|
`created_at` int(11) NOT NULL,
|
||||||
|
`updated_at` int(11) NOT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `v2_server_vmess`;
|
DROP TABLE IF EXISTS `v2_server_vmess`;
|
||||||
CREATE TABLE `v2_server_vmess` (
|
CREATE TABLE `v2_server_vmess` (
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
@ -444,4 +469,4 @@ CREATE TABLE `v2_user` (
|
|||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
|
||||||
-- 2023-05-23 17:01:12
|
-- 2023-07-17 07:38:59
|
||||||
|
@ -684,3 +684,29 @@ CREATE TABLE `v2_log` (
|
|||||||
`updated_at` int(11) NOT NULL,
|
`updated_at` int(11) NOT NULL,
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
|
||||||
|
ALTER TABLE `v2_log`
|
||||||
|
CHANGE `title` `title` text COLLATE 'utf8mb4_general_ci' NOT NULL AFTER `id`;
|
||||||
|
|
||||||
|
CREATE TABLE `v2_server_vless` (
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`group_id` text NOT NULL,
|
||||||
|
`route_id` text,
|
||||||
|
`name` varchar(255) NOT NULL,
|
||||||
|
`parent_id` int(11) DEFAULT NULL,
|
||||||
|
`host` varchar(255) NOT NULL,
|
||||||
|
`port` int(11) NOT NULL,
|
||||||
|
`server_port` int(11) NOT NULL,
|
||||||
|
`tls` tinyint(1) NOT NULL,
|
||||||
|
`tls_settings` text,
|
||||||
|
`flow` varchar(11) DEFAULT NULL,
|
||||||
|
`network` varchar(11) NOT NULL,
|
||||||
|
`network_settings` text,
|
||||||
|
`tags` text,
|
||||||
|
`rate` varchar(11) NOT NULL,
|
||||||
|
`show` tinyint(1) NOT NULL DEFAULT '0',
|
||||||
|
`sort` int(11) DEFAULT NULL,
|
||||||
|
`created_at` int(11) NOT NULL,
|
||||||
|
`updated_at` int(11) NOT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
2
public/assets/admin/umi.js
vendored
2
public/assets/admin/umi.js
vendored
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user