diff --git a/README.en.md b/README.en.md index fa2312d5eb9794aeeaff57355433a03740de8f21..40d1f3d33bdb78f8e79aba9a1f04ee97af743e57 100644 --- a/README.en.md +++ b/README.en.md @@ -3,11 +3,13 @@ #### Description laravel+vue-element-admin -![版本历史记录](public/demo/版本历史记录.png) +![Home](public/demo/home.png) -![西班牙语](public/demo/西班牙语.png) +![Version history](public/demo/版本历史记录.png) -![请求日志统计](public/demo/请求日志统计.png) +![Spanish](public/demo/西班牙语.png) + +![Request log statistics](public/demo/请求日志统计.png) #### Software Architecture Software architecture description diff --git a/README.md b/README.md index 4aa5f6f7b4281447f3395d0bf8e60a9bd35bf17d..f434200595854810534f5528ba2462ba3b41c084 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,8 @@ #### 介绍 laravel+vue-element-admin +![首页](public/demo/home.png) + ![版本历史记录](public/demo/版本历史记录.png) ![西班牙语](public/demo/西班牙语.png) diff --git a/app/Helper/functions.php b/app/Helper/functions.php index 981d5da6bc746dec752a4a0b65801e9e036e01e6..b3fcbbd783c1840ed83209927d31b79cc92c4631 100644 --- a/app/Helper/functions.php +++ b/app/Helper/functions.php @@ -1,4 +1,17 @@ 0, + // 空闲磁盘 + 'free' => 0, + // 已使用的磁盘 + 'used' => 0, + // 磁盘占用率 + 'usage_ratio' => 0, + + // 单位符 + 'unit_symbol' => 'G', + ]; + + /** + * 获取磁盘相关数据 + * + * @return array + */ + public function getDisk() + { + if ( is_windows() ) { //windows服务器 + // 总磁盘(kb -> k -> M -> G) + $this->disk['total'] = round(disk_total_space("C:") / 1024 / 1024 / 1024, 2); + $this->disk['free'] = round(disk_free_space("C:") / 1024 / 1024 / 1024, 2); + $this->disk['used'] = round($this->disk['total'] - $this->disk['free'], 2); + $this->disk['usage_ratio'] = round(round($this->disk['free'] / $this->disk['total'], 4) * 100, 2); + } else { + //获取磁盘占用率 + $fp = popen('df -lh | grep -E "^(/)"', "r"); + $rs = fread($fp, 1024); + pclose($fp); + $rs = preg_replace('/\s{2,}/', ' ', $rs); //把多个空格换成 “_” + $hd = explode(" ", $rs); + $this->disk['total'] = trim($hd[1], 'G');//可用空间G + $this->disk['used'] = trim($hd[2], 'G');//可用空间G + $this->disk['free'] = trim($hd[3], 'G');//可用空间G + $this->disk['usage_ratio'] = trim($hd[4], '%');//已使用百分比 + } + return $this->disk; + } + + // 内存 + private $memory = [ + // 总内存 + 'total' => 0, + // 空闲内存 + 'free' => 0, + // 已使用的内存 + 'used' => 0, + // 内存占用率 + 'usage_ratio' => 0, + // 单位符 + 'unit_symbol' => 'M', + ]; + + /** + * 获取内存相关数据 + * + * @return array + */ + public function getMemory() + { + if ( is_windows() ) { // windows服务器 + $path = $this->getMemoryUsageVbsPathByWindows(); + exec("cscript -nologo $path", $usage); + $memory = my_json_decode($usage[0], true); + + $this->memory['total'] = round($memory['TotalVisibleMemorySize'] / 1024, 2); + $this->memory['free'] = round($memory['FreePhysicalMemory'] / 1024, 2); + $this->memory['used'] = round($this->memory['total'] - $this->memory['free'], 2); + $this->memory['usage_ratio'] = round(round($this->memory['used'] / $this->memory['total'], 4) * 100, 2); + } else { + //内存使用率 + $fp = popen('top -b -n 2 | grep -E "(Mem)"', "r"); + $rs = fread($fp, 1024); + $sys_info = explode("\n", $rs); + var_dump('进入 Liunx,待测试 --- 内存'); + var_dump($sys_info); + $mem_info = explode(",", $sys_info[2]); //内存占有量 数组 + $this->memory['total'] = trim(trim($mem_info[0], 'KiB Mem : '), ' total'); + $this->memory['used'] = trim(trim($mem_info[2], 'used')); + $this->memory['buffer_cache'] = trim(trim($mem_info[3], 'buff/cache')); + $this->memory['free'] = trim(trim($mem_info[1], 'free')); + $this->memory['usage_ratio'] = round($this->memory['used'] / intval($this->memory['total']), 4) * 100; //百分比 + } + return $this->memory; + } + + // Cpu + private $cpu = [ + // 总Cpu + 'total' => 0, + // 空闲Cpu + 'free' => 0, + // 已使用的Cpu + 'used' => 0, + // Cpu占用率 + 'usage_ratio' => 0, + ]; + + /** + * 获取Cpu相关数据 + * + * @return array + */ + public function getCpu() + { + if ( is_windows() ) { // windows服务器 + // WINDOWS的CPU是极为不准确的。 + $this->cpu['usage_ratio'] = (float)$this->getCpuUsage(); + } else { + //获取CPU使用率以及内存使用率 + $fp = popen('top -b -n 2 | grep -E "(Cpu)"', "r"); + $rs = fread($fp, 1024); + $sys_info = explode("\n", $rs); + $this->cpu['usage_ratio'] = (float)trim(current(explode(',', trim($sys_info[0], '%Cpu(s): '))), 'us'); //百分比; + } + return $this->cpu; + } + + /** + * 获得总内存及可用物理内存JSON vbs文件生成函数 + * + * @return string 返回vbs文件路径 + */ + private function getMemoryUsageVbsPathByWindows() + { + return $this->getFilePath('memory_usage.vbs', "On Error Resume Next + Set objWMI = GetObject(\"winmgmts:\\\\.\\root\cimv2\") + Set colOS = objWMI.InstancesOf(\"Win32_OperatingSystem\") + For Each objOS in colOS + Wscript.Echo(\"{\"\"TotalVisibleMemorySize\"\":\" & objOS.TotalVisibleMemorySize & \",\"\"FreePhysicalMemory\"\":\" & objOS.FreePhysicalMemory & \"}\") + Next"); + } + + /** + * 判断指定路径下指定文件是否存在,如不存在则创建 + * + * @param string $fileName 文件名 + * @param string $content 文件内容 + * + * @return string 返回文件路径 + */ + private function getFilePath($fileName, $content) + { + $path = dirname(__FILE__) . "\\$fileName"; + if ( !file_exists($path) ) { + file_put_contents($path, $content); + } + return $path; + } + + /** + * 获得CPU使用率 + * + * @return Number + */ + private function getCpuUsage() + { + $path = $this->getCupUsageVbsPathByWindows(); + exec("cscript -nologo $path", $usage); + return $usage[0]; + } + + /** + * 获得cpu使用率vbs文件生成函数 + * + * @return string 返回vbs文件路径 + */ + private function getCupUsageVbsPathByWindows() + { + return $this->getFilePath('cpu_usage.vbs', "On Error Resume Next + Set objProc = GetObject(\"winmgmts:\\\\.\\root\cimv2:win32_processor='cpu0'\") + WScript.Echo(objProc.LoadPercentage)"); + } +} diff --git a/app/Modules/Admin/Http/Controllers/IndexController.php b/app/Modules/Admin/Http/Controllers/IndexController.php index 59d9697f0804f7d81a0d4ddabcb339a601de22e3..a46eab31581f48930c6befe06e2969cae8638571 100644 --- a/app/Modules/Admin/Http/Controllers/IndexController.php +++ b/app/Modules/Admin/Http/Controllers/IndexController.php @@ -65,4 +65,14 @@ class IndexController extends BaseController { return $this->successJson($this->service->versionLogs()); } + + /** + * 获取服务器状态 + * + * @return \Illuminate\Http\JsonResponse + */ + public function getServerStatus() + { + return $this->successJson($this->service->getServerStatus()); + } } diff --git a/app/Modules/Admin/Resources/vue-element-admin/api/indexs.js b/app/Modules/Admin/Resources/vue-element-admin/api/indexs.js index ba853a43860127da18c806a7c187d1cff0276d31..44a4d46ab5d6a13a9d6dadca224fa21689021a77 100644 --- a/app/Modules/Admin/Resources/vue-element-admin/api/indexs.js +++ b/app/Modules/Admin/Resources/vue-element-admin/api/indexs.js @@ -25,12 +25,18 @@ export function updateAdmin(data) { }) } - // 版本历史记录 -export function versionLogs(data) { +export function versionLogs() { return request({ url: '/versionLogs', method: 'get', - data, + }) +} + +// 服务器状态 +export function getServerStatus() { + return request({ + url: '/getServerStatus', + method: 'get', }) } diff --git a/app/Modules/Admin/Resources/vue-element-admin/views/admins/components/detail.vue b/app/Modules/Admin/Resources/vue-element-admin/views/admins/components/detail.vue index 1446b2201c63dff832bbe59af92a044e1e17cff7..3dd7968343c07764529260fbb155c3ad9bfcf501 100644 --- a/app/Modules/Admin/Resources/vue-element-admin/views/admins/components/detail.vue +++ b/app/Modules/Admin/Resources/vue-element-admin/views/admins/components/detail.vue @@ -56,14 +56,17 @@ - - {{ role.role_name }} - + + + + 超管无需设置角色 @@ -164,14 +167,6 @@ const res = await getRolesSelect(); this.roles = res.data; }, - // 管理员授权角色 - selectRoles(index, role_id){ - if (this.form.role_ids.indexOf(role_id) == -1){ - this.form.role_ids.push(role_id); - }else{ - this.form.role_ids.splice(this.form.role_ids.indexOf(role_id), 1); - } - }, toggleShow() { this.show = !this.show }, diff --git a/app/Modules/Admin/Resources/vue-element-admin/views/dashboard/admin/components/PieChart.vue b/app/Modules/Admin/Resources/vue-element-admin/views/dashboard/admin/components/PieChart.vue index 4d2ef32a5cf2bac3818596ad54ed2956afd8ab67..3865f8e3d846c4e8616a47e38335f93b3e3fad35 100644 --- a/app/Modules/Admin/Resources/vue-element-admin/views/dashboard/admin/components/PieChart.vue +++ b/app/Modules/Admin/Resources/vue-element-admin/views/dashboard/admin/components/PieChart.vue @@ -1,79 +1,125 @@ diff --git a/app/Modules/Admin/Resources/vue-element-admin/views/dashboard/admin/index.vue b/app/Modules/Admin/Resources/vue-element-admin/views/dashboard/admin/index.vue index 0c5c40d89a72e388afacd319af3edabc2e3c6d9c..f2821edab1ef18ab08c40cb80ba3cff1d3688e1c 100644 --- a/app/Modules/Admin/Resources/vue-element-admin/views/dashboard/admin/index.vue +++ b/app/Modules/Admin/Resources/vue-element-admin/views/dashboard/admin/index.vue @@ -4,35 +4,88 @@ - - -
- -
+ +

服务器状态信息

+ + + +
+ CPU使用率(%) +

+ windows系统,CPU获取极为不准确! +

+
+ +
+
+ + +
+ 磁盘使用率(G) +

+ 共计: + {{ server_data.disk_info.total }} G +

+
+ +
+
+ + +
+ 内存使用率(MB) +

+ 共计: + {{ server_data.memory_info.total }} MB +

+
+ +
- - -
+ + + +
+ 技能 +
-
+
+ + + +
+ 版本历史记录 +
- +
- + + + +
+ 请求日志统计 +
+ +
+
+
+ + @@ -44,7 +97,8 @@ import BoxCard from './components/BoxCard'; import Chart from './components/LineMarker'; import Timeline from './components/Timeline'; - import {statistics, versionLogs} from "@/api/indexs"; + import PieChart from './components/PieChart'; + import {statistics, versionLogs, getServerStatus} from "@/api/indexs"; const lineChartData = { newVisitis: { @@ -74,7 +128,15 @@ BarChart, BoxCard, Chart, - Timeline + Timeline, + PieChart, + }, + // 监听 + watch: { + //当 属性的值发生改变时会执行下面的代码 + server_data: function (newValue, oldValue) { + this.server_data = newValue; + }, }, data() { return { @@ -82,17 +144,26 @@ skill:[], // 技能组 data:{}, version_logs: [], // 版本记录 + server_data: {}, // 服务器状态信息 } }, created() { console.log('index-created'); + // 首页 - 统计信息 this.statistics(); + // 版本记录 this.versionLogs(); + + // 服务器状态信息 + setTimeout(() => { + this.getServerStatus(); + this.timedRequestServerStatus(); + }, 3000); }, methods: { - // 统计信息 + // 首页 - 统计信息 async statistics() { this.listLoading = true; const {data} = await statistics(); @@ -113,6 +184,19 @@ const {data} = await versionLogs(); this.version_logs = data; }, + // 服务器状态信息 + async getServerStatus(){ + const {data} = await getServerStatus(); + this.server_data = data; + console.log(this.server_data); + }, + // 定时:服务器状态信息 + timedRequestServerStatus(){ + // 定时多少秒触发一次:默认60秒【服务器状态信息】 + window.setInterval(() => { + setTimeout(this.getServerStatus, 0); + }, 1000 * 60); + }, handleSetLineChartData(type) { this.lineChartData = lineChartData[type]; }, @@ -126,6 +210,10 @@ background-color: rgb(240, 242, 245); position: relative; + .el-row{ + margin-bottom:30px; + } + .github-corner { position: absolute; top: 0px; diff --git a/app/Modules/Admin/Routes/web.php b/app/Modules/Admin/Routes/web.php index 786801e49036208a359928db02b96ec90394e0f7..e3ebfbfe72c90b06171d20ecbccf4210c48ee07c 100644 --- a/app/Modules/Admin/Routes/web.php +++ b/app/Modules/Admin/Routes/web.php @@ -40,6 +40,8 @@ Route::prefix('admin')->group(function() { Route::get('logsStatistics', 'IndexController@logsStatistics'); // 版本的历史记录 Route::get('versionLogs', 'IndexController@versionLogs'); + // 获取服务器状态 + Route::get('getServerStatus', 'IndexController@getServerStatus'); // 月份表列表 Route::get('get_month_lists', 'IndexController@getMonthList'); // 文件上传 diff --git a/app/Modules/Admin/Services/IndexService.php b/app/Modules/Admin/Services/IndexService.php index 21ac641b6980324cd3a5872ba89ff4a995eb3a02..de0693c8646f2e90ef9a17aa9ef797566fb79f62 100644 --- a/app/Modules/Admin/Services/IndexService.php +++ b/app/Modules/Admin/Services/IndexService.php @@ -2,6 +2,7 @@ namespace App\Modules\Admin\Services; +use App\Library\SystemInfo; use App\Modules\Admin\Entities\Article\Article; use App\Modules\Admin\Entities\Log\AdminLog; use App\Modules\Admin\Entities\Rabc\Admin; @@ -159,6 +160,70 @@ class IndexService extends BaseService */ public function versionLogs() { - return Version::getInstance()->select('version_name', 'version_number', 'version_content', 'publish_date')->orderBy('version_sort', 'ASC')->orderBy('version_id', 'ASC')->get(); + return Version::getInstance()->select('version_name', 'version_number', 'version_content', 'publish_date')->orderBy('version_sort', 'DESC')->orderBy('publish_date', 'DESC')->orderBy('version_id', 'ASC')->get(); + } + + /** + * 获取服务器状态信息 + * + * @return array + */ + public function getServerStatus() + { + $systemInfo = new SystemInfo; + $disk_info = $systemInfo->getDisk(); + $disk = [ + 'chart_legend' => ['used', 'free'], + 'chart_series' => [ + [ + 'name' => 'used', + 'value' => $disk_info['used'], + ], + [ + 'name' => 'free', + 'value' => $disk_info['free'], + ], + ], + ]; + + + $memory_info = $systemInfo->getMemory(); + $memory = [ + 'chart_legend' => ['used', 'free'], + 'chart_series' => [ + [ + 'name' => 'used', + 'value' => $memory_info['used'], + ], + [ + 'name' => 'free', + 'value' => $memory_info['free'], + ], + ], + ]; + + $cpu_info = $systemInfo->getCpu(); + $cpu = [ + 'chart_legend' => ['used', 'free'], + 'chart_series' => [ + [ + 'name' => 'used', + 'value' => $cpu_info['usage_ratio'], + ], + [ + 'name' => 'free', + 'value' => 100 - $cpu_info['usage_ratio'], + ], + ], + ]; + return [ + 'php_os' => PHP_OS, // 服务器系统 + 'system' => is_windows() ? 1 : 0, // 1.windows;0.Linux + 'disk' => $disk, // chart数据 + 'disk_info' => $disk_info, // 默认数据 + 'memory' => $memory, + 'memory_info' => $memory_info, // 默认数据 + 'cpu' => $cpu, + ]; } } diff --git a/public/demo/home.png b/public/demo/home.png new file mode 100644 index 0000000000000000000000000000000000000000..17be322f5dfa6317d7682c37b1ba0eadefdfe5da Binary files /dev/null and b/public/demo/home.png differ