2
0
mirror of https://github.com/acepanel/panel.git synced 2026-02-04 12:40:25 +08:00

特性:发布 20221130 版本

This commit is contained in:
耗子
2022-11-30 22:15:32 +08:00
parent 699562d504
commit 329f58da4b
24 changed files with 334 additions and 254 deletions

View File

@@ -1,30 +0,0 @@
<?php
/**
* 耗子Linux面板 - 数据库控制器
* @author 耗子
*/
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class DatabasesController extends Controller
{
public function get_mysql_list()
{
$password = Db::table('setting')->where('name', 'mysql_root_password')->value('value');
$db_raw = trim(shell_exec("/www/server/mysql/bin/mysql -u root -p".$password." -e \"SHOW DATABASES;\""));
$res['code'] = 0;
$res['msg'] = 'success';
$db = explode("\n", $db_raw);
foreach ($db as $key => $value) {
if ($value == 'Database' || $value == 'information_schema' || $value == 'mysql' || $value == 'performance_schema' || $value == 'sys') {
unset($db[$key]);
} else {
$res['data'][] = $value;
}
}
return response()->json($res);
}
}

View File

@@ -31,23 +31,6 @@ class InfosController extends Controller
"icon" => "layui-icon-website",
"jump" => "website/list"
),
array(
"name" => "database",
"title" => "数据库",
"icon" => "layui-icon-template-1",
"list" => array(
array(
"name" => "mysql",
"title" => "MySQL",
"jump" => "database/mysql"
),
array(
"name" => "postgresql",
"title" => "PostgreSQL",
"jump" => "database/postgresql"
)
)
),
array(
"name" => "monitor",
"title" => "监控",

View File

@@ -15,6 +15,7 @@ use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Http;
use Illuminate\Validation\ValidationException;
class PluginsController extends Controller
@@ -28,7 +29,7 @@ class PluginsController extends Controller
{
$data['code'] = 0;
$data['msg'] = 'success';
$data['data'] = $this->pluginList(false);
$data['data'] = $this->pluginList();
foreach ($data['data'] as $k => $v) {
// 获取首页显示状态
$shows = Plugin::query()->pluck('show', 'slug');
@@ -73,34 +74,28 @@ class PluginsController extends Controller
'slug' => 'required|max:255',
]);
$slug = $credentials['slug'];
} catch (Exception $e) {
} catch (ValidationException $e) {
return response()->json(['code' => 1, 'msg' => $e->getMessage()]);
}
// 通过slug获取插件信息
$pluginList = $this->pluginList();
// 循环插件列表查找对应的插件信息
$plugin_check = false;
$plugin_data = [];
$pluginCheck = false;
$pluginData = [];
foreach ($pluginList as $v) {
if ($v['slug'] == $slug) {
$plugin_data = $v;
$plugin_check = true;
$pluginData = $v;
$pluginCheck = true;
}
}
// 判断插件是否存在
if (!$plugin_check) {
if (!$pluginCheck) {
return response()->json(['code' => 1, 'msg' => '插件不存在']);
}
// 判断有无任务记录
$task_check = Task::query()->where('name', '安装'.$plugin_data['name'])->first();
if ($task_check) {
$data['code'] = 1;
$data['msg'] = '此插件已存在安装记录,请先删除!';
return response()->json($data);
}
// 判断插件是否已经安装
$installed = Task::query()->where('slug', $slug)->first();
$installed = isset(PLUGINS[$slug]);
if ($installed) {
$data['code'] = 1;
$data['msg'] = '请不要重复安装!';
@@ -109,10 +104,10 @@ class PluginsController extends Controller
// 入库等待安装
$task = new Task();
$task->name = '安装'.$plugin_data['name'];
$task->shell = $plugin_data['install'];
$task->name = '安装 '.$pluginData['name'];
$task->shell = $pluginData['install'];
$task->status = 'waiting';
$task->log = '/tmp/'.$plugin_data['slug'].'.log';
$task->log = '/tmp/'.$pluginData['slug'].'.log';
$task->save();
// 塞入队列
ProcessShell::dispatch($task->id)->delay(1);
@@ -136,32 +131,25 @@ class PluginsController extends Controller
'slug' => 'required|max:255',
]);
$slug = $credentials['slug'];
} catch (Exception $e) {
} catch (ValidationException $e) {
return response()->json(['code' => 1, 'msg' => $e->getMessage()]);
}
// 通过slug获取插件信息
$pluginList = $this->pluginList();
// 循环插件列表查找对应的插件信息
$plugin_check = false;
$plugin_data = [];
$pluginCheck = false;
$pluginData = [];
foreach ($pluginList as $v) {
if ($v['slug'] == $slug) {
$plugin_data = $v;
$plugin_check = true;
$pluginData = $v;
$pluginCheck = true;
}
}
// 判断插件是否存在
if (!$plugin_check) {
return response()->json(['code' => 1, 'msg' => '插件不存在']);
}
// 判断有无任务记录
$task_check = Task::query()->where('name', '卸载'.$plugin_data['name'])->first();
if ($task_check) {
$data['code'] = 1;
$data['msg'] = '此插件已存在卸载记录,请先删除!';
return response()->json($data);
// 判断插件是否存在
if (!$pluginCheck) {
return response()->json(['code' => 1, 'msg' => '插件不存在']);
}
// 判断是否是操作openresty
@@ -173,10 +161,67 @@ class PluginsController extends Controller
// 入库等待卸载
$task = new Task();
$task->name = '卸载'.$plugin_data['name'];
$task->shell = $plugin_data['uninstall'];
$task->name = '卸载 '.$pluginData['name'];
$task->shell = $pluginData['uninstall'];
$task->status = 'waiting';
$task->log = '/tmp/'.$plugin_data['slug'].'.log';
$task->log = '/tmp/'.$pluginData['slug'].'.log';
$task->save();
// 塞入队列
ProcessShell::dispatch($task->id)->delay(1);
$res['code'] = 0;
$res['msg'] = 'success';
$res['data'] = '任务添加成功';
return response()->json($res);
}
/**
* 更新插件
*/
public function update(Request $request): JsonResponse
{
// 消毒
try {
$credentials = $this->validate($request, [
'slug' => 'required|max:255',
]);
$slug = $credentials['slug'];
} catch (ValidationException $e) {
return response()->json(['code' => 1, 'msg' => $e->getMessage()]);
}
// 通过slug获取插件信息
$pluginList = $this->pluginList();
// 循环插件列表查找对应的插件信息
$pluginCheck = false;
$pluginData = [];
foreach ($pluginList as $v) {
if ($v['slug'] == $slug) {
$pluginData = $v;
$pluginCheck = true;
break;
}
}
// 判断插件是否存在
if (!$pluginCheck) {
return response()->json(['code' => 1, 'msg' => '插件不存在']);
}
// 判断插件是否已经安装
$installed = isset(PLUGINS[$slug]);
if (!$installed) {
$data['code'] = 1;
$data['msg'] = '插件未安装!';
return response()->json($data);
}
// 入库等待更新
$task = new Task();
$task->name = '更新 '.$pluginData['name'];
$task->shell = $pluginData['update'];
$task->status = 'waiting';
$task->log = '/tmp/'.$pluginData['slug'].'.log';
$task->save();
// 塞入队列
ProcessShell::dispatch($task->id)->delay(1);
@@ -229,10 +274,18 @@ class PluginsController extends Controller
]);
$slug = $credentials['slug'];
$show = $credentials['show'];
} catch (Exception $e) {
} catch (ValidationException $e) {
return response()->json(['code' => 1, 'msg' => $e->getMessage()]);
}
// 判断插件是否已经安装
$installed = isset(PLUGINS[$slug]);
if (!$installed) {
$data['code'] = 1;
$data['msg'] = '插件未安装!';
return response()->json($data);
}
Plugin::query()->where('slug', $slug)->update(['show' => $show]);
$res['code'] = 0;
$res['msg'] = 'success';

View File

@@ -15,24 +15,18 @@ class SettingsController extends Controller
{
/**
* 获取面板设置
* @param Request $request
* @return JsonResponse
*/
public function get(Request $request)
public function get(): JsonResponse
{
$settings = Setting::query()->get()->toArray();
foreach ($settings as $setting) {
$res['data'][$setting['name']] = $setting['value'];
}
if (!empty($settings)) {
$res['code'] = 0;
$res['msg'] = 'success';
} else {
$res['code'] = 1;
$res['msg'] = '面板设置获取失败';
$res['data'] = null;
}
$settings = Setting::all();
// 隐藏字段
$settings->makeHidden('id');
$settings->makeHidden('created_at');
$settings->makeHidden('updated_at');
$res['code'] = 0;
$res['msg'] = 'success';
$res['data'] = $settings->pluck('value', 'name');
return response()->json($res);
}
@@ -47,16 +41,9 @@ class SettingsController extends Controller
$settings = $request->all();
// 将数据入库
foreach ($settings as $key => $value) {
if ($key == 'access_token' || $key == 'username' || $key == 'password') {
if ($key == 'access_token') {
continue;
}
if ($key == 'mysql_root_password') {
$old_mysql_password = Setting::query()->where('name', 'mysql_root_password')->value('value');
if ($old_mysql_password != $value) {
shell_exec('mysql -uroot -p'.$old_mysql_password.' -e "ALTER USER \'root\'@\'localhost\' IDENTIFIED BY \''.$value.'\';"');
shell_exec('mysql -uroot -p'.$old_mysql_password.' -e "flush privileges;"');
}
}
Setting::query()->where('name', $key)->update(['value' => $value]);
}
$res['code'] = 0;

View File

@@ -23,7 +23,7 @@ class TasksController extends Controller
$task = Task::query()->where('status', 'running')->orWhere('status', 'waiting')->first();
$res['code'] = 0;
$res['msg'] = 'success';
if ($task) {
if (empty($task)) {
$res['data'] = false;
} else {
$res['data'] = true;

View File

@@ -29,7 +29,7 @@ class UsersController extends Controller
} catch (ValidationException $e) {
return response()->json([
'code' => 1,
'msg' => '参数错误',
'msg' => '参数错误'.$e->getMessage(),
'errors' => $e->errors()
], 422);
}

View File

@@ -9,10 +9,8 @@ namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\Website;
use App\Models\Setting;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Illuminate\Validation\ValidationException;
class WebsitesController extends Controller
@@ -23,9 +21,9 @@ class WebsitesController extends Controller
*/
public function getList(): JsonResponse
{
$website_lists = Website::query()->get();
$websiteList = Website::query()->get();
// 判空
if ($website_lists->isEmpty()) {
if ($websiteList->isEmpty()) {
return response()->json([
'code' => 0,
'msg' => '无数据',
@@ -35,7 +33,7 @@ class WebsitesController extends Controller
return response()->json([
'code' => 0,
'msg' => '获取成功',
'data' => $website_lists
'data' => $websiteList
]);
}
@@ -58,15 +56,31 @@ class WebsitesController extends Controller
'db_type' => 'required_if:db,true|max:10',
'db_name' => 'required_if:db,true|max:255',
'db_username' => 'required_if:db,true|max:255',
'db_password' => 'required_if:db,true|max:255',
'db_password' => ['required_if:db,true', 'regex:/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*(_|[^\w])).+$/', 'min:8'],
]);
} catch (ValidationException $e) {
return response()->json([
'code' => 1,
'msg' => '参数错误',
'msg' => '参数错误'.$e->getMessage(),
'errors' => $e->errors()
], 200);
}
// 禁止添加重复网站
$website = Website::query()->where('name', $credentials['name'])->first();
if ($website) {
return response()->json([
'code' => 1,
'msg' => '网站已存在'
]);
}
// 禁止phpmyadmin作为名称
if ($credentials['name'] == 'phpmyadmin') {
return response()->json([
'code' => 1,
'msg' => '该名称为保留名称,请更换'
]);
}
// path为空时设置默认值
if (empty($credentials['path'])) {
$credentials['path'] = '/www/wwwroot/'.$credentials['name'];
@@ -228,20 +242,34 @@ EOF;
/**
* 获取网站全局设置
* @return
* @return JsonResponse
*/
public function get_website_default_settings()
public function getDefaultSettings(): JsonResponse
{
return '待开发功能';
$index = @file_get_contents('/www/server/nginx/html/index.html') ? file_get_contents('/www/server/nginx/html/index.html') : '';
$stop = @file_get_contents('/www/server/nginx/html/stop.html') ? file_get_contents('/www/server/nginx/html/stop.html') : '';
$res['code'] = 0;
$res['msg'] = 'success';
$res['data'] = [
'index' => $index,
'stop' => $stop,
];
return response()->json($res);
}
/**
* 保存网站全局设置
* @return
* @return JsonResponse
*/
public function save_website_default_settings()
public function saveDefaultSettings(): JsonResponse
{
return '待开发功能';
$index = request()->input('index');
$stop = request()->input('stop');
file_put_contents('/www/server/nginx/html/index.html', $index);
file_put_contents('/www/server/nginx/html/stop.html', $stop);
$res['code'] = 0;
$res['msg'] = 'success';
return response()->json($res);
}
/**

View File

@@ -1,6 +1,6 @@
<?php
return [
'name' => '耗子Linux面板',
'version' => '20221121',
'version' => '20221130',
'plugin_dir' => '/www/panel/plugins',
];

View File

@@ -2,7 +2,7 @@
/**
* Name: OpenResty插件控制器
* Author:耗子
* Date: 2022-11-21
* Date: 2022-11-30
*/
namespace Plugins\Openresty\Controllers;
@@ -11,15 +11,16 @@ namespace Plugins\Openresty\Controllers;
use App\Http\Controllers\Controller;
// HTTP
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Request;
// Filesystem
use Illuminate\Filesystem\Filesystem;
class OpenrestyController extends Controller
{
public function status()
public function status(): JsonResponse
{
$command = 'systemctl status nginx';
$result = shell_exec($command);
@@ -35,7 +36,7 @@ class OpenrestyController extends Controller
return response()->json($res);
}
public function restart()
public function restart(): JsonResponse
{
$command = 'nginx -t 2>&1';
$result = shell_exec($command);
@@ -50,15 +51,12 @@ class OpenrestyController extends Controller
}
$command2 = 'systemctl restart nginx';
$result2 = shell_exec($command2);
if (str_contains($result2, 'done')) {
$res['data'] = 'OpenResty已重启';
return response()->json($res);
}
shell_exec($command2);
$res['data'] = 'OpenResty已重启';
return response()->json($res);
}
public function reload()
public function reload(): JsonResponse
{
$command = 'nginx -t 2>&1';
$result = shell_exec($command);
@@ -72,17 +70,12 @@ class OpenrestyController extends Controller
}
$command2 = 'systemctl reload nginx';
$result2 = shell_exec($command2);
if (str_contains($result2, 'done')) {
$res['data'] = 'OpenResty已重载';
} else {
$res['msg'] = 'error';
$res['data'] = 'OpenResty重载失败';
}
shell_exec($command2);
$res['data'] = 'OpenResty已重载';
return response()->json($res);
}
public function getConfig()
public function getConfig(): JsonResponse
{
$res['code'] = 0;
$res['msg'] = 'success';
@@ -90,12 +83,12 @@ class OpenrestyController extends Controller
return response()->json($res);
}
public function saveConfig()
public function saveConfig(Request $request): JsonResponse
{
$res['code'] = 0;
$res['msg'] = 'success';
// 获取配置内容
$config = Request::post('config');
$config = $request->input('config');
// 备份一份旧配置
$old_config = file_get_contents('/www/server/nginx/conf/nginx.conf');
// 写入配置
@@ -118,7 +111,7 @@ class OpenrestyController extends Controller
}
}
public function load()
public function load(): JsonResponse
{
$raw_status = HTTP::get('http://127.0.0.1/nginx_status')->body();
@@ -158,7 +151,7 @@ class OpenrestyController extends Controller
return response()->json($res);
}
public function errorLog()
public function errorLog(): JsonResponse
{
$res['code'] = 0;
$res['msg'] = 'success';
@@ -170,7 +163,7 @@ class OpenrestyController extends Controller
return response()->json($res);
}
public function cleanErrorLog()
public function cleanErrorLog(): JsonResponse
{
$res['code'] = 0;
$res['msg'] = 'success';

View File

@@ -1,5 +1,5 @@
{
"name": "OpenResty-1.21.4",
"name": "OpenResty",
"slug": "openresty",
"version": "1.21.4.1"
}

View File

@@ -1,7 +1,7 @@
<!--
Name: Openresty管理器
Author: 耗子
Date: 2022-11-21
Date: 2022-11-30
-->
<title>OpenResty</title>
<div class="layui-fluid" id="component-tabs">
@@ -96,7 +96,8 @@ Date: 2022-11-21
console.log('耗子Linux面板OpenResty错误日志获取失败接口返回' + result);
$('#openresty-error-log').text('OpenResty错误日志获取失败请刷新重试');
code({
title: 'error.log'
elem: '#openresty-error-log'
, title: 'error.log'
, encode: true
, about: false
@@ -105,7 +106,8 @@ Date: 2022-11-21
}
$('#openresty-error-log').text(result.data);
code({
title: 'error.log'
elem: '#openresty-error-log'
, title: 'error.log'
, encode: true
, about: false
@@ -201,8 +203,8 @@ Date: 2022-11-21
layer.alert(result.data);
return false;
}
layer.alert('OpenResty重启成功');
admin.events.refresh();
layer.alert('OpenResty重启成功');
}
, error: function (xhr, status, error) {
console.log('耗子Linux面板ajax请求出错错误' + error)

View File

@@ -1,2 +0,0 @@
<title>数据库 - MySQL</title>
<h1 style="text-align: center; padding-top: 20px;">管理正在开发中!</h1>

View File

@@ -1,2 +0,0 @@
<title>数据库 - PostgreSQL</title>
<h1 style="text-align: center; padding-top: 20px;">管理正在开发中!</h1>

View File

@@ -1,7 +1,7 @@
<!--
Name: 主页模板
Author: 耗子
Date: 2022-10-14
Date: 2022-11-30
-->
<div class="layui-fluid">
<div class="layui-row layui-col-space15">
@@ -84,7 +84,7 @@ Date: 2022-10-14
<ul class="layui-row layui-col-space10 layui-this">
<script type="text/html" template lay-url="/api/panel/info/getHomePlugins">
@{{# layui.each(d.data, function(index, item){ }}
<li class="layui-col-xs2">
<li class="layui-col-xs4 layui-col-md2 layui-col-sm4">
<a lay-href="/plugin/@{{ item.slug }}">
<i class="layui-icon layui-icon-engine"></i>
<cite>@{{ item.name }}</cite>
@@ -146,7 +146,7 @@ Date: 2022-10-14
</div>
<div class="layui-card-body layui-text layadmin-text">
<blockquote class="layui-elem-quote">
<p>暂时没想好写什么,啦啦啦</p>
<p>这是一个全新的项目,欢迎您的使用。如果遇到问题/Bug请前往交流反馈QQ群<a href="https://jq.qq.com/?_wv=1027&amp;k=I1oJKSTH">12370907</a> 反馈给我,我们共同让她变得更完美</p>
</blockquote>
</div>
</div>

View File

@@ -20,7 +20,7 @@
// `=---=' //
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //
// 佛祖保佑 永无Bug 永不宕机 //
// Name耗子Linux面板 Author耗子 Date2022-11-21 //
// Name耗子Linux面板 Author耗子 Date2022-11-30 //
////////////////////////////////////////////////////////////////////
-->
@@ -47,12 +47,12 @@
}).use('index', function () {
let layer = layui.layer, admin = layui.admin, $ = layui.jquery;
layer.ready(function () {
admin.popup({
/*admin.popup({
content: '当前面板为公测版本,如遇到问题请联系耗子反馈!</br>QQ: 823374000'
, area: '380px'
, shade: false
, offset: 't'
});
});*/
});
});
</script>

View File

@@ -2,26 +2,26 @@
<div class="layui-fluid">
<div class="layui-card">
<!--<div class="layui-form layui-card-header layuiadmin-card-header-auto" lay-filter="store-form">
<!--<div class="layui-form layui-card-header layuiadmin-card-header-auto" lay-filter="plugin-form">
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label">搜索</label>
<div class="layui-input-block">
<input type="text" name="store_search" placeholder="请输入关键词如php" autocomplete="off"
<input type="text" name="plugin_search" placeholder="请输入关键词如php" autocomplete="off"
class="layui-input">
</div>
</div>
<div class="layui-inline">
<button class="layui-btn layuiadmin-btn-order" lay-submit lay-filter="store-search-submit">
<button class="layui-btn layuiadmin-btn-order" lay-submit lay-filter="plugin-search-submit">
<i class="layui-icon layui-icon-search layuiadmin-button-btn"></i>
</button>
</div>
</div>
</div>-->
<div class="layui-card-body">
<table id="panel-store" lay-filter="panel-store"></table>
<table id="panel-plugin" lay-filter="panel-plugin"></table>
<!-- 操作按钮模板 -->
<script type="text/html" id="store-control-tpl">
<script type="text/html" id="panel-plugin-control">
@{{# if(d.control.installed == true && d.control.allow_uninstall == true){ }}
@{{# if(d.control.update == true){ }}
<a class="layui-btn layui-btn-xs" lay-event="update">更新</a>
@@ -59,16 +59,16 @@
, admin = layui.admin;
table.render({
elem: '#panel-store'
elem: '#panel-plugin'
, url: '/api/panel/plugin/getList'
, cols: [[
{field: 'slug', hide: true, title: 'Slug', sort: true}
, {field: 'name', width: '10%', title: '插件名'}
, {field: 'describe', width: '48%', title: '描述'}
, {field: 'name', width: '13%', title: '插件名'}
, {field: 'describe', width: '42%', title: '描述'}
, {field: 'install_version', width: '12%', title: '已装版本'}
, {field: 'version', width: '12%', title: '最新版本'}
, {field: 'show', title: '首页显示', width: 90, templet: '#plugin-show', unresize: true}
, {field: 'control', title: '操作', templet: '#store-control-tpl', fixed: 'right', align: 'center'}
, {field: 'control', title: '操作', templet: '#panel-plugin-control', fixed: 'right', align: 'left'}
]]
, page: false
, text: '耗子Linux面板数据加载出现异常'
@@ -77,8 +77,8 @@
}
});
//工具条
table.on('tool(panel-store)', function (obj) {
// 工具条
table.on('tool(panel-plugin)', function (obj) {
let data = obj.data;
if (obj.event === 'open') {
location.hash = '/plugin/' + data.slug;
@@ -93,11 +93,10 @@
}
, success: function (res) {
if (res.code === 0) {
table.reload('panel-plugin');
layer.msg('安装:' + data.name + ' 成功加入任务队列', {
icon: 1,
time: 1000
}, function () {
location.reload();
});
} else {
layer.msg(res.msg, {icon: 2, time: 1000});
@@ -119,8 +118,10 @@
}
, success: function (res) {
if (res.code === 0) {
layer.msg('卸载:' + data.name + ' 成功!', {icon: 1, time: 1000}, function () {
location.reload();
table.reload('panel-plugin');
layer.msg('卸载:' + data.name + ' 成功加入任务队列', {
icon: 1,
time: 1000
});
} else {
layer.msg(res.msg, {icon: 2, time: 1000});
@@ -142,11 +143,10 @@
}
, success: function (res) {
if (res.code === 0) {
layer.msg('安装:' + data.name + ' 成功加入任务队列', {
table.reload('panel-plugin');
layer.msg('升级:' + data.name + ' 成功加入任务队列', {
icon: 1,
time: 1000
}, function () {
location.reload();
});
} else {
layer.msg(res.msg, {icon: 2, time: 1000});
@@ -184,14 +184,14 @@
}
});
});
/*form.render(null, 'store-form');
/*form.render(null, 'plugin-form');
//搜索
form.on('submit(store-search-submit)', function (data) {
form.on('submit(plugin-search-submit)', function (data) {
var field = data.field;
//执行重载
table.reload('store-search-submit', {
table.reload('plugin-search-submit', {
where: field
});
});*/

View File

@@ -19,13 +19,6 @@ Date: 2022-10-14
</div>
<div class="layui-form-mid layui-word-aux">修改面板的显示名称</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label" style="font-size: 13px;">MySQL密码</label>
<div class="layui-input-inline">
<input type="text" name="mysql_root_password" value="获取中ing..." class="layui-input" disabled/>
</div>
<div class="layui-form-mid layui-word-aux">修改MySQL的root密码</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn" lay-submit lay-filter="panel_setting_submit">确认修改</button>
@@ -43,12 +36,8 @@ Date: 2022-10-14
layui.define(['form', 'upload'], function () {
var $ = layui.$
, layer = layui.layer
, laytpl = layui.laytpl
, setter = layui.setter
, view = layui.view
, admin = layui.admin
, form = layui.form
, upload = layui.upload;
, form = layui.form;
// 渲染表单
form.render();
@@ -73,32 +62,6 @@ Date: 2022-10-14
}
});
//自定义验证
form.verify({
name: function (value, item) { //value表单的值、item表单的DOM对象
if (!new RegExp("^[a-zA-Z0-9_\u4e00-\u9fa5\\s·]+$").test(value)) {
return '用户名不能有特殊字符';
}
if (/(^\_)|(\__)|(\_+$)/.test(value)) {
return '用户名首尾不能出现下划线\'_\'';
}
if (/^\d+\d+\d$/.test(value)) {
return '用户名不能全为数字';
}
}
, pass: [
/^[\S]{6,12}$/
, '密码必须6到12位且不能出现空格'
]
//确认密码
, repass: function (value) {
if (value !== $('#LAY_password').val()) {
return '两次密码输入不一致';
}
}
});
// 面板设置
form.on('submit(panel_setting_submit)', function (obj) {
// 提交修改

View File

@@ -22,7 +22,7 @@ Date: 2022-10-09
<script type="text/html" template lay-url="/api/panel/task/getListRunning"
lay-done="layui.data.done(d);">
@{{# if(d.data != ""){ }}
<blockquote class="layui-elem-quote">安装 @{{ d.data.name }}</blockquote>
<blockquote class="layui-elem-quote">@{{ d.data.name }}</blockquote>
<pre id="plugin-install-log" class="layui-code">
日志获取中...
</pre>
@@ -50,10 +50,11 @@ Date: 2022-10-09
<script>
var install_plugin_timer;
function render_plugin_install_log(d) {
let admin = layui.admin
,$ = layui.$
,code = layui.code;
, $ = layui.$
, code = layui.code;
admin.req({
url: "/api/panel/task/getTaskLog?name=" + d.data.name
, method: 'get'
@@ -62,7 +63,8 @@ Date: 2022-10-09
console.log('耗子Linux面板实时安装日志获取失败接口返回' + result);
$('#plugin-install-log').html('实时安装日志获取失败,请刷新重试!');
code({
title: 'install.log'
elem: '#plugin-install-log'
, title: 'install.log'
, encode: true
, about: false
@@ -71,7 +73,8 @@ Date: 2022-10-09
}
$('#plugin-install-log').html(result.data);
code({
title: 'install.log'
elem: '#plugin-install-log'
, title: 'install.log'
, encode: true
, about: false
@@ -82,6 +85,7 @@ Date: 2022-10-09
}
})
}
layui.data.done = function (d) {
// 判断是否有任务
if (d.data.name) {
@@ -98,7 +102,6 @@ Date: 2022-10-09
layui.use(['admin', 'table', 'jquery'], function () {
var $ = layui.$
, form = layui.form
, table = layui.table
, admin = layui.admin;
@@ -118,12 +121,18 @@ Date: 2022-10-09
table.render({
elem: '#panel-task-finished'
,id: 'panel-task-finished-table'
, id: 'panel-task-finished-table'
, url: '/api/panel/task/getListFinished'
, cols: [[
{field: 'slug', hide: true, title: 'Slug', sort: true}
, {field: 'name', width: '80%', title: '任务名'}
, {field: 'control', title: '操作', templet: '#panel-task-finished-control-tpl', fixed: 'right', align: 'center'}
, {
field: 'control',
title: '操作',
templet: '#panel-task-finished-control-tpl',
fixed: 'right',
align: 'center'
}
]]
, page: false
, text: '耗子Linux面板数据加载出现异常'
@@ -132,7 +141,7 @@ Date: 2022-10-09
}
});
//工具条
// 工具条
table.on('tool(panel-task-finished)', function (obj) {
let data = obj.data;
if (obj.event === 'remove') {

View File

@@ -144,13 +144,14 @@ Date: 2022-11-21
layer.msg('新网站添加失败,请刷新重试!')
return false;
}
table.reload('website-list');
layer.alert('新网站添加成功!', {
icon: 1
, title: '提示'
, btn: ['确定']
, yes: function (index) {
layer.close(index);
location.reload();
layer.closeAll();
//location.reload();
}
});
}

View File

@@ -0,0 +1,81 @@
<!--
Name: 网站 - 全局设置
Author: 耗子
Date: 2022-11-30
-->
<script type="text/html" template lay-url="/api/panel/website/getDefaultSettings" lay-done="layui.data.sendParams(d.params)">
<div class="layui-tab">
<ul class="layui-tab-title">
<li class="layui-this">默认页</li>
<li>停止页</li>
</ul>
<div class="layui-tab-content">
<div class="layui-tab-item layui-show">
<!-- 默认页 -->
<blockquote class="layui-elem-quote layui-quote-nm">
设置站点未找到时的提示页面。
</blockquote>
<div id="index-editor" style="height: -webkit-fill-available;">@{{ d.data.index }}</div>
</div>
<div class="layui-tab-item">
<!-- 停止页 -->
<blockquote class="layui-elem-quote layui-quote-nm">
设置站点停止时的提示页面。
</blockquote>
<div id="stop-editor" style="height: -webkit-fill-available;">@{{ d.data.stop }}</div>
</div>
</div>
</div>
<div class="layui-footer">
<button id="save-website-default-settings" class="layui-btn">保存设置</button>
</div>
</script>
<script>
let indexEditor = '';
let stopEditor = '';
layui.data.sendParams = function(params) {
layui.use(['admin', 'form', 'laydate', 'code'], function () {
var $ = layui.$
, admin = layui.admin
, element = layui.element
, layer = layui.layer
, laydate = layui.laydate
, code = layui.code;
indexEditor = ace.edit("index-editor", {
mode: "ace/mode/html",
selectionStyle: "text"
});
stopEditor = ace.edit("stop-editor", {
mode: "ace/mode/html",
selectionStyle: "text"
});
$('#save-website-default-settings').click(function () {
layer.load(2);
admin.req({
url: '/api/panel/website/saveDefaultSettings'
, type: 'post'
, data: {
index: indexEditor.getValue(),
stop: stopEditor.getValue()
}
, success: function (res) {
layer.closeAll('loading');
if (res.code === 0) {
layer.msg('保存成功', {icon: 1});
setTimeout(function () {
admin.render();
}, 1000);
} else {
layer.msg(res.msg, {icon: 2});
}
}
, error: function (xhr, status, error) {
console.log('耗子Linux面板ajax请求出错错误' + error);
}
});
});
});
};
</script>

View File

@@ -1,7 +1,7 @@
<!--
Name: 网站 - 编辑
Author: 耗子
Date: 2022-11-21
Date: 2022-11-28
-->
<script type="text/html" template lay-done="layui.data.sendParams(d.params)">
<div class="layui-tab">
@@ -182,7 +182,7 @@ Date: 2022-11-21
<div class="layui-tab-item">
<!-- 访问日志 -->
<button id="clean-site-log" class="layui-btn">清空日志</button>
<pre class="layui-code" lay-options="{about: '@{{ d.params.config.name }}.log'}">@{{ d.params.config.log }}</pre>
<pre id="website-log" class="layui-code" lay-options="{about: '@{{ d.params.config.name }}.log'}">@{{ d.params.config.log }}</pre>
</div>
</div>
</div>
@@ -200,7 +200,7 @@ Date: 2022-11-21
, element = layui.element
, layer = layui.layer
, laydate = layui.laydate
, table = layui.table
, code = layui.code
, form = layui.form;
console.log(params);
form.render();
@@ -212,8 +212,9 @@ Date: 2022-11-21
mode: "ace/mode/nginx",
selectionStyle: "text"
});
layui.code({
encode: true
code({
elem: '#website-log'
, encode: true
, about: false
});
@@ -301,6 +302,11 @@ Date: 2022-11-21
}
});
});
// 重载配置
$('#site-config-restore').click(function (){
layer.msg('待开发功能!', {icon: 2});
})
});
};
</script>

View File

@@ -1,7 +1,7 @@
<!--
Name: 网站 - 列表
Author: 耗子
Date: 2022-11-21
Date: 2022-11-28
-->
<title>网站</title>
<div class="layui-fluid">
@@ -15,8 +15,8 @@ Date: 2022-11-21
<!-- 顶部工具栏 -->
<script type="text/html" id="website-list-bar">
<div class="layui-btn-container">
<button class="layui-btn layui-btn-sm" lay-event="add_website">添加网站</button>
<!--<button class="layui-btn layui-btn-sm" lay-event="edit_default_settings">全局设置</button>-->
<button class="layui-btn layui-btn-sm" lay-event="website_add">添加网站</button>
<button class="layui-btn layui-btn-sm" lay-event="website_default_settings">全局设置</button>
</div>
</script>
<!-- 右侧网站设置和删除网站 -->
@@ -31,6 +31,10 @@ Date: 2022-11-21
value="@{{ d.status }}" data-website-name="@{{ d.name }}"
@{{ d.status== 1 ? 'checked' : '' }} />
</script>
<!-- 网站SSL状态 -->
<script type="text/html" id="website-ssl">
@{{ d.ssl == 1 ? '已开启' : '未开启' }}
</script>
</div>
</div>
</div>
@@ -77,7 +81,7 @@ Date: 2022-11-21
, {field: 'run', title: '运行', width: 100, templet: '#website-run', unresize: true}
, {field: 'path', title: '目录', width: 250}
, {field: 'php', title: 'PHP', width: 60}
, {field: 'ssl', title: 'SSL', width: 110}
, {field: 'ssl', title: 'SSL', width: 110, templet: '#website-ssl'}
, {field: 'note', title: '备注', edit: 'textarea'}
, {fixed: 'right', title: '操作', toolbar: '#website-setting', width: 150}
]]
@@ -90,7 +94,7 @@ Date: 2022-11-21
// 头工具栏事件
table.on('toolbar(website-list)', function (obj) {
console.log(obj);
if (obj.event === 'add_website') {
if (obj.event === 'website_add') {
admin.popup({
title: '添加网站'
, area: ['70%', '60%']
@@ -104,22 +108,22 @@ Date: 2022-11-21
});
}
});
} else if (obj.event === 'edit_default_settings') {
layer.open({
type: 2
, title: '全局设置'
, content: 'website/edit_default_settings'
, area: ['500px', '500px']
, btn: ['确定', '取消']
, yes: function (index, layero) {
var iframeWin = window[layero.find('iframe')[0]['name']];
iframeWin.submitForm();
} else if (obj.event === 'website_default_settings') {
admin.popup({
title: '全局设置'
, area: ['70%', '60%']
, id: 'LAY-popup-website-add'
, success: function (layer, index) {
view(this.id).render('website/default_settings', {
}).done(function () {
form.render(null, 'LAY-popup-website-default-settings');
});
}
});
}
});
//行工具事件
// 行工具事件
table.on('tool(website-list)', function (obj) {
console.log(obj);
let data = obj.data;
@@ -156,7 +160,7 @@ Date: 2022-11-21
, success: function (result) {
if (result.code !== 0) {
console.log('耗子Linux面板网站设置获取失败接口返回' + result);
layui.alert('网站设置获取失败!');
layer.alert('网站设置获取失败!');
return false;
}
config = result.data;
@@ -217,6 +221,7 @@ Date: 2022-11-21
let run = obj.elem.checked ? 1 : 0;
console.log(website_name); //当前行数据
layer.msg('待开发功能!', {icon: 2});
});
});

View File

@@ -71,6 +71,8 @@ Route::prefix('panel')->group(function () {
// 网站
Route::middleware('auth:sanctum')->prefix('website')->group(function () {
// 获取网站列表
Route::get('getDefaultSettings', [WebsitesController::class, 'getDefaultSettings']);
Route::post('saveDefaultSettings', [WebsitesController::class, 'saveDefaultSettings']);
Route::get('getList', [WebsitesController::class, 'getList']);
Route::post('add', [WebsitesController::class, 'add']);
Route::post('delete', [WebsitesController::class, 'delete']);
@@ -123,6 +125,7 @@ Route::prefix('panel')->group(function () {
Route::get('getList', [PluginsController::class, 'getList']);
Route::post('install', [PluginsController::class, 'install']);
Route::post('uninstall', [PluginsController::class, 'uninstall']);
Route::post('update', [PluginsController::class, 'update']);
Route::post('setShowHome', [PluginsController::class, 'setShowHome']);
});
// 设置

View File

@@ -30,7 +30,7 @@ Route::prefix('panel/views')->group(function () {
// 网站
Route::prefix('website')->group(function () {
//全局设置
Route::view('default_setting', 'website.default_settings');
Route::view('default_settings', 'website.default_settings');
// 列表
Route::view('list', 'website.list');
// 添加