This commit is contained in:
v2board 2022-12-19 13:50:52 +08:00
commit c8f3684312
25 changed files with 162 additions and 107 deletions

View File

@ -57,6 +57,7 @@ class V2boardUpdate extends Command
} catch (\Exception $e) {
}
}
$this->info('更新完毕,请重新启动队列服务。');
\Artisan::call('horizon:terminate');
$this->info('更新完毕,队列服务已重启,你无需进行任何操作。');
}
}

View File

@ -15,6 +15,12 @@ class RouteController extends Controller
public function fetch(Request $request)
{
$routes = ServerRoute::get();
// TODO: remove on 1.8.0
foreach ($routes as $k => $route) {
$array = json_decode($route->match, true);
if (is_array($array)) $routes[$k]['match'] = $array;
}
// TODO: remove on 1.8.0
return [
'data' => $routes
];
@ -24,10 +30,19 @@ class RouteController extends Controller
{
$params = $request->validate([
'remarks' => 'required',
'match' => 'required',
'action' => 'required',
'match' => 'required|array',
'action' => 'required|in:block,dns',
'action_value' => 'nullable'
], [
'remarks.required' => '备注不能为空',
'match.required' => '匹配值不能为空',
'action.required' => '动作类型不能为空',
'action.in' => '动作类型参数有误'
]);
$params['match'] = array_filter($params['match']);
// TODO: remove on 1.8.0
$params['match'] = json_encode($params['match']);
// TODO: remove on 1.8.0
if ($request->input('id')) {
try {
$route = ServerRoute::find($request->input('id'));

View File

@ -25,9 +25,9 @@ class ThemeController extends Controller
{
$themeConfigs = [];
foreach ($this->themes as $theme) {
$themeConfigFile = $this->path . "{$theme}/config.php";
$themeConfigFile = $this->path . "{$theme}/config.json";
if (!File::exists($themeConfigFile)) continue;
$themeConfig = include($themeConfigFile);
$themeConfig = json_decode(File::get($themeConfigFile), true);
if (!isset($themeConfig['configs']) || !is_array($themeConfig)) continue;
$themeConfigs[$theme] = $themeConfig;
if (config("theme.{$theme}")) continue;
@ -60,9 +60,10 @@ class ThemeController extends Controller
]);
$payload['config'] = json_decode(base64_decode($payload['config']), true);
if (!$payload['config'] || !is_array($payload['config'])) abort(500, '参数有误');
$themeConfigFile = public_path("theme/{$payload['name']}/config.php");
$themeConfigFile = public_path("theme/{$payload['name']}/config.json");
if (!File::exists($themeConfigFile)) abort(500, '主题不存在');
$themeConfig = include($themeConfigFile);
$themeConfig = json_decode(File::get($themeConfigFile), true);
if (!isset($themeConfig['configs']) || !is_array($themeConfig)) abort(500, '主题配置文件有误');
$validateFields = array_column($themeConfig['configs'], 'field_name');
$config = [];
foreach ($validateFields as $validateField) {

View File

@ -71,6 +71,15 @@ class Surfboard
$config = str_replace('$subs_domain', $subsDomain, $config);
$config = str_replace('$proxies', $proxies, $config);
$config = str_replace('$proxy_group', rtrim($proxyGroup, ', '), $config);
$upload = round($user['u'] / (1024*1024*1024), 2);
$download = round($user['d'] / (1024*1024*1024), 2);
$useTraffic = $upload + $download;
$totalTraffic = round($user['transfer_enable'] / (1024*1024*1024), 2);
$expireDate = $user['expired_at'] === NULL ? '长期有效' : date('Y-m-d H:i:s', $user['expired_at']);
$subscribeInfo = "title={$appName}订阅信息, content=上传流量:{$upload}GB\\n下载流量{$download}GB\\n剩余流量{$useTraffic}GB\\n套餐流量{$totalTraffic}GB\\n到期时间{$expireDate}";
$config = str_replace('$subscribe_info', $subscribeInfo, $config);
return $config;
}

View File

@ -72,6 +72,15 @@ class Surge
$config = str_replace('$subs_domain', $subsDomain, $config);
$config = str_replace('$proxies', $proxies, $config);
$config = str_replace('$proxy_group', rtrim($proxyGroup, ', '), $config);
$upload = round($user['u'] / (1024*1024*1024), 2);
$download = round($user['d'] / (1024*1024*1024), 2);
$useTraffic = $upload + $download;
$totalTraffic = round($user['transfer_enable'] / (1024*1024*1024), 2);
$expireDate = $user['expired_at'] === NULL ? '长期有效' : date('Y-m-d H:i:s', $user['expired_at']);
$subscribeInfo = "title={$appName}订阅信息, content=上传流量:{$upload}GB\\n下载流量{$download}GB\\n剩余流量{$useTraffic}GB\\n套餐流量{$totalTraffic}GB\\n到期时间{$expireDate}";
$config = str_replace('$subscribe_info', $subscribeInfo, $config);
return $config;
}

View File

@ -6,6 +6,7 @@ use App\Http\Controllers\Controller;
use App\Http\Requests\User\UserTransfer;
use App\Http\Requests\User\UserUpdate;
use App\Http\Requests\User\UserChangePassword;
use App\Services\AuthService;
use App\Services\UserService;
use App\Utils\CacheKey;
use Illuminate\Http\Request;
@ -18,6 +19,30 @@ use Illuminate\Support\Facades\Cache;
class UserController extends Controller
{
public function getActiveSession(Request $request)
{
$user = User::find($request->user['id']);
if (!$user) {
abort(500, __('The user does not exist'));
}
$authService = new AuthService($user);
return response([
'data' => $authService->getSessions()
]);
}
public function removeActiveSession(Request $request)
{
$user = User::find($request->user['id']);
if (!$user) {
abort(500, __('The user does not exist'));
}
$authService = new AuthService($user);
return response([
'data' => $authService->delSession($request->input('session_id'))
]);
}
public function checkLogin(Request $request)
{
$data = [

View File

@ -21,11 +21,12 @@ class UserRoute
$router->get ('/checkLogin', 'User\\UserController@checkLogin');
$router->post('/transfer', 'User\\UserController@transfer');
$router->post('/getQuickLoginUrl', 'User\\UserController@getQuickLoginUrl');
$router->get ('/getActiveSession', 'User\\UserController@getActiveSession');
$router->post('/removeActiveSession', 'User\\UserController@removeActiveSession');
// Order
$router->post('/order/save', 'User\\OrderController@save');
$router->post('/order/checkout', 'User\\OrderController@checkout');
$router->get ('/order/check', 'User\\OrderController@check');
$router->get ('/order/details', 'User\\OrderController@detail'); // TODO: 1.7.0 remove
$router->get ('/order/detail', 'User\\OrderController@detail');
$router->get ('/order/fetch', 'User\\OrderController@fetch');
$router->get ('/order/getPaymentMethod', 'User\\OrderController@getPaymentMethod');

View File

@ -14,7 +14,7 @@ class AuthService
{
private $user;
public function __construct($user)
public function __construct(User $user)
{
$this->user = $user;
}
@ -76,10 +76,23 @@ class AuthService
$cacheKey,
$sessions
)) return false;
return true;
}
public function getSessions()
{
return (array)Cache::get(CacheKey::get("USER_SESSIONS", $this->user->id), []);
}
public function delSession($sessionId)
{
$cacheKey = CacheKey::get("USER_SESSIONS", $this->user->id);
$sessions = (array)Cache::get($cacheKey, []);
unset($sessions[$sessionId]);
if (!Cache::put(
$cacheKey,
$sessions
)) return false;
return true;
}
}

View File

@ -221,7 +221,14 @@ class ServerService
public function getRoutes(array $routeIds)
{
return ServerRoute::select(['id', 'match', 'action', 'action_value'])->whereIn('id', $routeIds)->get();
$routes = ServerRoute::select(['id', 'match', 'action', 'action_value'])->whereIn('id', $routeIds)->get();
// TODO: remove on 1.8.0
foreach ($routes as $k => $route) {
$array = json_decode($route->match, true);
if (is_array($array)) $routes[$k]['match'] = $array;
}
// TODO: remove on 1.8.0
return $routes;
}
public function getServer($serverId, $serverType)

View File

@ -18,9 +18,10 @@ class ThemeService
public function init()
{
$themeConfigFile = $this->path . "{$this->theme}/config.php";
if (!File::exists($themeConfigFile)) return;
$themeConfig = include($themeConfigFile);
$themeConfigFile = $this->path . "{$this->theme}/config.json";
if (!File::exists($themeConfigFile)) abort(500, "{$this->theme}主题不存在");
$themeConfig = json_decode(File::get($themeConfigFile), true);
if (!isset($themeConfig['configs']) || !is_array($themeConfig)) abort(500, "{$this->theme}主题配置文件有误");
$configs = $themeConfig['configs'];
$data = [];
foreach ($configs as $config) {

View File

@ -237,5 +237,5 @@ return [
| The only modification by laravel config
|
*/
'version' => '1.7.2'
'version' => '1.7.2.1671294313058'
];

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,49 @@
{
"name": "v2board",
"description": "v2board",
"version": "1.7.2",
"images": "https://images.unsplash.com/photo-1515405295579-ba7b45403062?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2160&q=80",
"configs": [{
"label": "主题色",
"placeholder": "请选择主题颜色",
"field_name": "theme_color",
"field_type": "select",
"select_options": {
"default": "默认(蓝色)",
"green": "奶绿色",
"black": "黑色",
"darkblue": "暗蓝色"
},
"default_value": "default"
}, {
"label": "背景",
"placeholder": "请输入背景图片URL",
"field_name": "background_url",
"field_type": "input"
}, {
"label": "边栏风格",
"placeholder": "请选择边栏风格",
"field_name": "theme_sidebar",
"field_type": "select",
"select_options": {
"light": "亮",
"dark": "暗"
},
"default_value": "light"
}, {
"label": "顶部风格",
"placeholder": "请选择顶部风格",
"field_name": "theme_header",
"field_type": "select",
"select_options": {
"light": "亮",
"dark": "暗"
},
"default_value": "dark"
}, {
"label": "自定义页脚HTML",
"placeholder": "可以实现客服JS代码的加入等",
"field_name": "custom_html",
"field_type": "textarea"
}]
}

View File

@ -1,53 +0,0 @@
<?php
return [
'name' => 'V2board',
'description' => 'V2board默认主题',
'version' => '1.5.6',
'images' => 'https://images.unsplash.com/photo-1515405295579-ba7b45403062?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2160&q=80',
'configs' => [
[
'label' => '主题色', // 标签
'placeholder' => '请选择主题颜色', // 描述
'field_name' => 'theme_color', // 字段名 作为数据key使用
'field_type' => 'select', // 字段类型: select,input,switch
'select_options' => [ // 当字段类型为select时有效
'default' => '默认(蓝色)',
'green' => '奶绿色',
'black' => '黑色',
'darkblue' => '暗蓝色',
],
'default_value' => 'default' // 字段默认值,将会在首次进行初始化
], [
'label' => '背景',
'placeholder' => '请输入背景图片URL',
'field_name' => 'background_url',
'field_type' => 'input'
], [
'label' => '边栏风格',
'placeholder' => '请选择边栏风格',
'field_name' => 'theme_sidebar',
'field_type' => 'select',
'select_options' => [
'light' => '亮',
'dark' => '暗'
],
'default_value' => 'light'
], [
'label' => '顶部风格',
'placeholder' => '请选择顶部风格',
'field_name' => 'theme_header',
'field_type' => 'select',
'select_options' => [
'light' => '亮',
'dark' => '暗'
],
'default_value' => 'dark'
], [
'label' => '自定义页脚HTML',
'placeholder' => '可以实现客服JS代码的加入等',
'field_name' => 'custom_html',
'field_type' => 'textarea'
]
]
];

View File

@ -59,19 +59,6 @@
<script src="/theme/{{$theme}}/assets/vendors.async.js?v={{$version}}"></script>
<script src="/theme/{{$theme}}/assets/components.async.js?v={{$version}}"></script>
<script src="/theme/{{$theme}}/assets/umi.js?v={{$version}}"></script>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-P1E9Z5LRRK"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag('js', new Date());
gtag('config', 'G-P1E9Z5LRRK');
</script>
@if (file_exists(public_path("/theme/{$theme}/assets/custom.js")))
<script src="/theme/{{$theme}}/assets/custom.js?v={{$version}}"></script>
@endif

View File

@ -9,19 +9,16 @@
- Laravel
## Demo
[Demo](https://v2board.com)
[Demo](https://demo.v2board.com)
## Document
[Click](https://docs.v2board.com)
[Click](https://v2board.com)
## Sponsors
Thanks to the open source project license provided by [Jetbrains](https://www.jetbrains.com/)
## Community
Telegram Channel: [@v2board](https://t.me/v2board)
Telegram Group: [@v2board_official](https://t.me/v2board_official)
🔔Telegram Channel: [@v2board](https://t.me/v2board)
## How to Feedback
We have closed issues due to too much invalid feedback, you can give us your feedback in the following way.
- Contact us through Community
- Fork Dev branch commit pull request
Follow the template in the issue to submit your question correctly, and we will have someone follow up with you.

View File

@ -12,6 +12,9 @@ test-timeout = 5
internet-test-url = http://bing.com
proxy-test-url = http://bing.com
[Panel]
SubscribeInfo = $subscribe_info, style=info
# Surfboard 的服务器和策略组配置方式与 Surge 类似, 可以参考 Surge 的规则配置手册: https://manual.nssurge.com/
[Proxy]

View File

@ -36,6 +36,9 @@ hide-crashlytics-request = true
use-keyword-filter = false
hide-udp = false
[Panel]
SubscribeInfo = $subscribe_info, style=info
# -----------------------------
# Surge 的几种策略配置规范,请参考 https://manual.nssurge.com/policy/proxy.html
# 不同的代理策略有*很多*可选参数,请参考上方连接的 Parameters 一段,根据需求自行添加参数。

View File

@ -31,19 +31,6 @@
<script src="/assets/admin/vendors.async.js?v={{$version}}"></script>
<script src="/assets/admin/components.async.js?v={{$version}}"></script>
<script src="/assets/admin/umi.js?v={{$version}}"></script>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-P1E9Z5LRRK"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag('js', new Date());
gtag('config', 'G-P1E9Z5LRRK');
</script>
</body>
</html>