加入系統資訊頁面,加入全域js物件

This commit is contained in:
kroutony 2020-02-22 21:44:22 +08:00
parent 57fedd69d4
commit 6b0c761f85
23 changed files with 570 additions and 2 deletions

View File

@ -0,0 +1,25 @@
<?php
namespace App\Http\Controllers\Admin\Menu\SystemStatus\Children;
use App\Http\Controllers\Admin\Menu\BaseMenuItemController;
use Gate;
use Illuminate\Http\Request;
class GateAbilitiesMenuItemController extends BaseMenuItemController
{
public function __construct()
{
$this->name = 'adminMenu.items.systemStatus.gateAbilities';
$this->slug = 'gates';
$this->iconClasses = 'nav-icon icon-wrench';
}
public function handle(Request $request)
{
$gates = Gate::abilities();
return view('admin.menu.systemStatus.gates')->with(compact('gates'));
}
}

View File

@ -0,0 +1,39 @@
<?php
namespace App\Http\Controllers\Admin\Menu\SystemStatus\Children;
use App\Http\Controllers\Admin\Menu\BaseMenuItemController;
use Illuminate\Http\Request;
use Route;
class RouteListMenuItemController extends BaseMenuItemController
{
public function __construct()
{
$this->name = 'adminMenu.items.systemStatus.routes';
$this->slug = 'routes';
$this->iconClasses = 'nav-icon icon-wrench';
}
public function handle(Request $request)
{
$routes = Route::getRoutes()->getRoutes();
$routes = collect($routes)->map(function($route){
/** @var \Illuminate\Routing\Route $route */
$action = explode('@', $route->getActionName());
return [
'methods' => $route->methods(),
'uri' => $route->uri(),
'name' => $route->getName(),
'action' => [
'controller' => isset($action[0]) ? $action[0] : '',
'method' => isset($action[1]) ? $action[1] : '',
],
'middlewares' => $route->middleware(),
];
})->all();
return view('admin.menu.systemStatus.routes')->with(compact('routes'));
}
}

View File

@ -0,0 +1,118 @@
<?php
namespace App\Http\Controllers\Admin\Menu\SystemStatus\Children;
use App\Http\Controllers\Admin\Menu\BaseMenuItemController;
use Illuminate\Http\Request;
use Redis;
use Cache;
use DB;
use Arr;
class SystemMenuItemController extends BaseMenuItemController
{
public function __construct()
{
$this->name = 'adminMenu.items.systemStatus.system';
$this->slug = 'system';
$this->iconClasses = 'nav-icon icon-wrench';
}
public function handle(Request $request)
{
$systemInfo = collect([
[
'name' => 'OS',
'value' => php_uname('s') . ' ' . php_uname('r'),
],
[
'name' => 'OS Version',
'value' => php_uname('v'),
],
[
'name' => 'Server',
'value' => $_SERVER['SERVER_SOFTWARE']
],
[
'name' => 'Timezone',
'value' => date_default_timezone_get()
],
[
'name' => 'PHP Version',
'value' => phpversion()
],
[
'name' => 'PHP Post Max Size',
'value' => ini_get('post_max_size')
],
[
'name' => 'PHP Upload Max Filesize',
'value' => ini_get('upload_max_filesize')
],
[
'name' => 'PHP Max Execution Time',
'value' => ini_get('max_execution_time')
],
[
'name' => 'PHP Max Input Vars',
'value' => ini_get('max_input_vars')
],
[
'name' => 'PHP Memory Limit',
'value' => ini_get('memory_limit')
],
[
'name' => 'PHP Xdebug Enabled',
'value' => function_exists('xdebug_get_code_coverage')
]
]);
$systemInfo->push([
'name' => 'DBMS',
'value'=> DB::getDriverName(),
])->push([
'name' => 'DB',
'value'=> DB::getDatabaseName(),
]);
if(DB::getDriverName() == 'mysql') {
$query = DB::raw("SHOW VARIABLES LIKE 'version'");
$version = Arr::first(DB::select($query));
if($version) {
$systemInfo->push([
'name' => 'DB Version',
'value' => $version->Value
]);
}
}
$systemInfo->push([
'name' => 'Cache',
'value'=> Cache::getDefaultDriver(),
])->push([
'name' => 'Cache Time',
'value'=> Cache::getDefaultCacheTime(),
]);
if(Cache::getDefaultDriver() == 'redis') {
$redisStatus = false;
try {
$redisConfig = config('database.redis.default');
$redis = Redis::connect($redisConfig['host'],$redisConfig['port']);
$redisStatus = true;
} catch(\Exception $e){ }
$systemInfo->push([
'name' => 'Redis Connected',
'value' => $redisStatus
]);
}
return view('admin.menu.systemStatus.system', ['systemInfo' => $systemInfo->all()]);
}
}

View File

@ -0,0 +1,20 @@
<?php
namespace App\Http\Controllers\Admin\Menu\SystemStatus;
use App\Http\Controllers\Admin\Menu\BaseMenuItemController;
class SystemStatusMenuItemController extends BaseMenuItemController
{
public function __construct()
{
$this->name = 'adminMenu.items.systemStatus.systemStatus';
$this->slug = 'system-status';
$this->permissions = ['admin manage system status'];
$this->iconClasses = 'nav-icon icon-wrench';
}
}

View File

@ -0,0 +1,49 @@
<?php
namespace App\Services;
use Auth;
use App\Product;
/**
* 提供資料給前端js使用
*
* Class AppJsObjectService
* @package App\Services
*/
class AppJsObjectService
{
public function get()
{
$option = app('Option');
$siteState = app('SiteState');
$obj = [
'locale' => app()->getLocale(),
'csrfToken' => csrf_token(),
'user' => null,
'options' => [
'googleApiKey' => $option->google_api_key,
'fbAppId' => $option->fb_app_id,
],
'translations' => [
],
'methods' => new \stdClass,
'utils' => new \stdClass
];
if(Auth::check()) {
$user = Auth::user();
$obj['user'] = [
'id' => $user->id,
'apiToken' => $user->api_token
];
}
if($siteState->isAdminArea) {
$obj['admin']['translations'] = [
'dataTables' => trans('datatables'),
];
}
return $obj;
}
}

View File

@ -17,6 +17,15 @@ return [
Menu\Options\Children\DevelopmentMenuItemController::class, Menu\Options\Children\DevelopmentMenuItemController::class,
] ]
], ],
[
'type' => 'item',
'controller' => Menu\SystemStatus\SystemStatusMenuItemController::class,
'children' => [
Menu\SystemStatus\Children\SystemMenuItemController::class,
Menu\SystemStatus\Children\RouteListMenuItemController::class,
Menu\SystemStatus\Children\GateAbilitiesMenuItemController::class,
]
],
], ],
// 設定的項目 // 設定的項目
'options' => [ 'options' => [

View File

@ -37,6 +37,12 @@ return [
'displayName' => 'adminManageOptionsDevelopment', 'displayName' => 'adminManageOptionsDevelopment',
'assignTo' => [] 'assignTo' => []
], ],
[
//管理系統狀態
'name' => 'admin manage system status',
'displayName' => 'adminManageSystemStatus',
'assignTo' => []
],
], ],
// 預設的設定值 // 預設的設定值
'options' => [ 'options' => [

View File

@ -2,7 +2,5 @@
return [ return [
'en' => 'English', 'en' => 'English',
'zh-tw' => '繁體中文', 'zh-tw' => '繁體中文',
'zh-cn' => '简体中文',
'ja' => '日本語',
'ko' => '한국어' 'ko' => '한국어'
]; ];

View File

@ -21,6 +21,8 @@ import 'perfect-scrollbar';
import '@coreui/coreui'; import '@coreui/coreui';
import 'chart.js'; import 'chart.js';
import '@coreui/coreui-plugin-chartjs-custom-tooltips'; import '@coreui/coreui-plugin-chartjs-custom-tooltips';
import 'datatables.net-bs4';
import 'datatables.net-responsive-bs4';
try { try {

View File

@ -0,0 +1,13 @@
$(function(){
//路由表表格套用datatable
app.utils.dataTable('.table.routes', {
paginate: false,
responsive: true,
});
//Gate Ability表格套用datatable
app.utils.dataTable('.table.gate-abilities', {
paginate: false,
responsive: true,
});
});

View File

@ -1,4 +1,14 @@
import {dataTable} from "./utils/datatable";
$('.logout-btn').on('click', e => { $('.logout-btn').on('click', e => {
e.preventDefault() e.preventDefault()
$('#logout-form').submit() $('#logout-form').submit()
}) })
/**
* 第三方工具
*/
app.utils = {
dataTable: dataTable,
}

5
resources/js/utils/datatable.js vendored Normal file
View File

@ -0,0 +1,5 @@
export const dataTable = function(ele, options = {}){
return $(ele).dataTable(Object.assign({}, {
language: app.admin.translations.dataTables
}, options));
};

View File

@ -7,5 +7,11 @@ return array(
'development' => 'Development', 'development' => 'Development',
'platform' => 'Platform', 'platform' => 'Platform',
], ],
'systemStatus' => [
'systemStatus' => 'System Status',
'routes' => 'Route List',
'system' => 'System',
'gateAbilities' => 'Gate Abilities',
]
], ],
); );

View File

@ -0,0 +1,26 @@
<?php
return array (
'processing' => 'Processing...',
'search' => 'Search:',
'lengthMenu' => 'Display _MENU_ items',
'info' => 'Showing _START_ to _END_ on _TOTAL_ items',
'infoEmpty' => 'Showing empty items',
'infoFiltered' => '(filter of _MAX_ total items)',
'infoPostFix' => '',
'loadingRecords' => 'Loading...',
'zeroRecords' => 'No item to display',
'emptyTable' => 'Table is empty',
'paginate' =>
array (
'first' => 'First',
'previous' => 'Previous',
'next' => 'Next',
'last' => 'Last',
),
'aria' =>
array (
'sortAscending' => ': activate to sort the column in ascending order',
'sortDescending' => ': activate to sort the column in descending order',
),
);

View File

@ -0,0 +1,26 @@
<?php
return array (
'processing' => '處理中...',
'search' => '查詢:',
'lengthMenu' => '顯示 _MENU_ 筆資料',
'info' => '顯示第 _START_ 至 _END_ 筆資料,共 _TOTAL_ 筆',
'infoEmpty' => '顯示 0 筆資料',
'infoFiltered' => '(從 _MAX_ 筆資料中過濾)',
'infoPostFix' => '',
'loadingRecords' => '載入中...',
'zeroRecords' => '查無資料',
'emptyTable' => '無資料',
'paginate' =>
array (
'first' => '第一頁',
'previous' => '上一頁',
'next' => '下一頁',
'last' => '最後一頁',
),
'aria' =>
array (
'sortAscending' => ': 將資料以正序排序',
'sortDescending' => ': 將資料以倒序排序',
),
);

View File

@ -0,0 +1,50 @@
//Boostrap函式庫
@import "../bootstrap";
body.system-status {
&.routes {
table.routes {
font-size: 1.1em;
@include media-breakpoint-down(lg) {
font-size: 1em;
}
@include media-breakpoint-down(md) {
font-size: .9em;
}
&.collapsed {
.dtr-data {
word-break: break-all;
.badge {
white-space: unset;
}
}
}
td {
&.uri {
* {
color: #baffc6;
}
}
&.action {
word-break: break-all;
}
&.middleware {
.badge {
margin-right: 2px;
font-size: .9em;
}
}
}
}
}
&.system {
table.system {
font-size: 1.1em;
}
}
&.gates {
table {
font-size: 1.2em;
}
}
}

View File

@ -7,6 +7,9 @@
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}"> <meta name="csrf-token" content="{{ csrf_token() }}">
@section('admin-app-head-scripts')
@include('components.head.appJsObject')
@show
@stack('admin-app-head-scripts') @stack('admin-app-head-scripts')
@section('admin-app-styles') @section('admin-app-styles')

View File

@ -0,0 +1,36 @@
@extends('admin.layouts.app')
@section('title', 'Gate Abilities')
@push('admin-app-scripts')
<script src="{{ asset('js/admin/page/system-status.js') }}"></script>
@endpush
@push('admin-app-styles')
<link href="{{ asset('css/admin/page/system-status.css') }}" rel="stylesheet">
@endpush
@section('admin-page-content')
<div class="row">
<div class="col">
<h1>Gate Abilities</h1>
</div>
</div>
<div class="row">
<div class="col">
<table class="table table-dark table-striped table-hover gate-abilities">
<thead>
<th>Ability</th>
</thead>
<tbody>
@foreach($gates as $ability => $gate)
<tr>
<td>{{ $ability }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
@endsection

View File

@ -0,0 +1,85 @@
@extends('admin.layouts.app')
@section('title', 'Route List')
@push('admin-app-scripts')
<script src="{{ asset('js/admin/page/system-status.js') }}"></script>
@endpush
@push('admin-app-styles')
<link href="{{ asset('css/admin/page/system-status.css') }}" rel="stylesheet">
@endpush
@section('admin-page-content')
<div class="row">
<div class="col">
<h1>Route List</h1>
</div>
</div>
<div class="row">
<div class="col">
<table class="table table-sm table-dark table-striped table-hover routes">
<thead>
<tr>
<th class="method desktop tablet-l tablet-p mobile-l mobile-p" data-priority="1">Method</th>
<th class="uri desktop tablet-l tablet-p mobile-l mobile-p" data-priority="1">URI</th>
<th class="name desktop tablet-l tablet-p" data-priority="3">Name</th>
<th class="action desktop tablet-l" data-priority="4">Action</th>
<th class="middleware desktop" data-priority="5">Middleware</th>
</tr>
</thead>
<tbody>
@foreach($routes as $route)
<tr>
<td class="method">
{!!
collect($route['methods'])
->map(function($method){
$badgeType = '';
switch(strtolower($method)) {
case 'get':
$badgeType = 'success';
break;
case 'post':
$badgeType = 'primary';
break;
case 'put':
case 'patch':
$badgeType = 'warning';
break;
case 'delete':
$badgeType = 'danger';
break;
}
return app('Html')->bs()->badge($method, $badgeType);
})
->join('<br>')
!!}
</td>
<td class="uri">
@if(in_array('GET', $route['methods']))
<a href="/{{ ltrim( $route['uri'], '/') }}" class="font-weight-bold text-break" target="_blank">{{ $route['uri'] }}</a>
@else
<span class="font-weight-bold text-break">{{ $route['uri'] }}</span>
@endif
</td>
<td class="name">{{ $route['name'] }}</td>
<td class="action">
<span class="controller text-break">{{ $route['action']['controller'] }}</span>@<span class="method text-info text-break">{{ $route['action']['method'] }}</span>
</td>
<td class="middleware">
{!!
collect($route['middlewares'])
->map(function($name){
return app('Html')->bs()->badge($name, 'secondary');
})
->join('')
!!}
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
@endsection

View File

@ -0,0 +1,33 @@
@extends('admin.layouts.app')
@section('title', 'System Status')
@push('admin-app-scripts')
<script src="{{ asset('js/admin/page/system-status.js') }}"></script>
@endpush
@push('admin-app-styles')
<link href="{{ asset('css/admin/page/system-status.css') }}" rel="stylesheet">
@endpush
@section('admin-page-content')
<div class="row">
<div class="col">
<h1>System Status</h1>
</div>
</div>
<div class="row">
<div class="col">
<table class="table table-striped table-hover table-dark table-sm system table-bordered">
<tbody>
@foreach($systemInfo as $info)
<tr>
<th>{{ $info['name'] }}</th>
<td class="value text-break">{{ $info['value'] }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
@endsection

View File

@ -0,0 +1,4 @@
@inject('js', App\Services\AppJsObjectService)
<script>
var app = @json($js->get());
</script>

View File

@ -12,6 +12,9 @@
@endif @endif
@yield('head-meta') @yield('head-meta')
@section('app-head-scripts')
@include('components.head.appJsObject')
@show
@stack('app-head-scripts') @stack('app-head-scripts')
@section('app-styles') @section('app-styles')

2
webpack.mix.js vendored
View File

@ -21,6 +21,8 @@ mix.js('resources/js/app.js', publicJsDir)
mix.sass('resources/sass/app.scss', publicCssDir); mix.sass('resources/sass/app.scss', publicCssDir);
mix.js('resources/js/admin/app.js', publicAdminJsDir) mix.js('resources/js/admin/app.js', publicAdminJsDir)
.js('resources/js/admin/page/system-status.js', publicAdminJsDir + '/page')
mix.sass('resources/sass/admin/lib.scss', publicAdminCssDir) mix.sass('resources/sass/admin/lib.scss', publicAdminCssDir)
.sass('resources/sass/admin/app.scss', publicAdminCssDir) .sass('resources/sass/admin/app.scss', publicAdminCssDir)
.sass('resources/sass/admin/page/system-status.scss', publicAdminCssDir + '/page')