fix: 修复字典bug、缓存默认使用file

This commit is contained in:
Ying
2022-11-29 11:42:55 +08:00
parent f19f236e9a
commit 1c0c886937
8 changed files with 126 additions and 108 deletions

View File

@@ -1,5 +1,3 @@
<div align="center">
<img src="https://www.swiftadmin.net/static/images/sademo/110400_6a5e130d_904542.png" width="98" height="98" />
</div>
@@ -15,18 +13,23 @@
`SWIFTADMIN` 是一款基于 webman + Layui 开发的 http 服务框架,提供了一个简单易用的(权限)后台管理系统,
拥有极简的封装扩展,特别适合中小企业和个人站长用于开发 web 站点或者 http 接口。支持路由、中间件、自动注入、多应用、 自定义进程、无需更改直接兼容现有 composer 项目组件等诸多特性。具有学习成本低、简单易用、超高性能、超高稳定性等特点。
拥有极简的封装扩展,特别适合中小企业和个人站长用于开发 web 站点或者 http 接口。支持路由、中间件、 多应用、 自定义进程、无需更改直接兼容现有 composer 项目组件等诸多特性。具有学习成本低、简单易用、超高性能、超高稳定性等特点。
<font color="#dd0000">为什么选择 SWIFTADMIN</font>
如果你熟悉ThinkPHP/Laravel/Yii2等框架那么你可以很快上手 SWIFTADMIN因为 SWIFTADMIN 是完全复用的这些框架的composer包。一样的代码写法性能却可以提升10 倍以上。
运行在PHPCLI模式之下他不是类似于SWOOLE异步协程的工作模式所以新手朋友不需要担心变量污染的问题也不需要担心第三方扩展包异步协程的问题只需要专注于业务开发即可。
### 软件架构
| 依赖 | 版本 | 说明 |
|-----|-----------|:----------------------------------|
| PHP | \>= 8.0 | 最低支持PHP8.0 |
| WebMan | \>= 1.4.3 | 基于1.4.3.不支持action-hook/auto-route |
| MySQL | \>= 5.7 | 最低 5.7,注意5.6版本无JSON字段会报错 |
| Layui | \>= 2.7 | 特殊开发版,无法直接用官网替换 |
| layui-form-design | \>= 1.0 | 表单设计器基于Sortable专为SAPHP框架开发 |
| Admin Theme | \>= 1.x | 专为本框架开发、封装超多功能、支持多种菜单布局 |
| 依赖 | 版本 | 说明 |
|-----|-----------|:----------------------------|
| PHP | \>= 8.0 | 最低支持PHP8.0 |
| WebMan | \>= 1.4.3 | 基于workerman强悍核心 |
| MySQL | \>= 5.7 | 最低 5.7,注意5.6版本无JSON字段会报错 |
| Layui | \>= 2.7 | 特殊封装版,无法直接用官网替换 |
| layui-form-design | \>= 1.0 | 表单设计器基于Sortable专为SAPHP框架开发 |
| Admin Theme | \>= 1.x | 专为本框架开发、封装超多功能、支持多种菜单布局 |
### 软件功能
@@ -65,9 +68,9 @@
```
<font color="#dd0000">2、Windows环境下启动开发服务</font>
```
1、执行Windows.bat 进行完整开发默认会监听app、config、plugin目录的PHP html的更改热加载
执行Windows.bat 进行完整开发默认会监听app、config、plugin目录的PHP html的更改热加载
```
2、Linux环境下启动开发服务
3、Linux环境下启动开发服务
```
执行命令php start.php start # 启动开发服务
执行命令php start.php stop # 停止开发服务
@@ -76,16 +79,32 @@
当前默认只有app、config文件夹下文件内容被修改后才会自动重启全局监听方案请参考开发文档
```
3、打开浏览器输入网址,访问项目
4、打开浏览器输入网址,访问项目
```
http://localhost:8787/index # 访问项目执行安装
```
4、安装完毕后访问后台URL登录系统
5、安装完毕后访问后台URL登录系统
```
http://localhost:8787/manage # 登录后台/生产环境下可自行修改后台地址
```
5、
### 常见问题
1、启动开发服务后访问项目报错 Server internal error
```
请检查是否安装了PHP扩展fileinfo opcache redis imagemagick exif一般这个错误是PHP扩展没有安装、或者Redis服务器安装后没启动
```
2、启动开发服务后访问项目报错 404 Not Found
```
请检查是否安装了Apache或者NGINX服务器一般这个错误是服务器没有安装、或者没有启动
```
3、启动服务器的时候报错PHP Fatal error: ....
```
首先在CMD终端或Linux终端执行命令php -v 查看 * 默认PHP版本 *如果版本低于8.0请升级PHP版本<br/>
然后使用命令php -m 查看 * 已安装的PHP扩展 *如果没有安装fileinfo opcache redis imagemagick exif请安装<br/>
一定要注意的是swiftadmin框架运行在webman核心上并且运行的时候默认调用的是当前操作系统默认的PHP环境变量的那个版本<br/>
如果是windows环境之前安装过PHP7.3那么安装PHP8之后需要修改系统环境变量才可以执行
```
### 反馈BUG

View File

@@ -392,7 +392,7 @@ class Index extends AdminController
$parse['CACHE_DRIVER'] = $post['cache_type'];
$parse['CACHE_HOSTNAME'] = $post['cache_host'];
$parse['CACHE_HOSTPORT'] = $post['cache_port'];
$parse['CACHE_SELECT'] = min($post['cache_select'], 1);
$parse['CACHE_SELECT'] = $post['cache_select'];
$parse['CACHE_USERNAME'] = $post['cache_user'];
$parse['CACHE_PASSWORD'] = $post['cache_pass'];
write_file($env, parse_array_ini($parse));

View File

@@ -329,7 +329,7 @@
// 获取用户id
var pageThat = layui.$(this),
_pageUrl = !status ? pageThat.attr('lay-edit') : pageThat.attr('lay-add');
pageThat.attr("disabled",true);
// 开始POST提交数据
layui.$.post(_pageUrl,
post.field, function(res){
@@ -338,6 +338,7 @@
// 关闭当前窗口
table.reload('lay-tableList');
layer.close(colletction.index);
pageThat.attr("disabled",true);
}
else {
layer.error(res.msg);
@@ -379,7 +380,6 @@
// 增加节点数据
post.field[event] = tree.getChecked('authTree', true);
// 开始POST提交数据
clickthis.attr("disabled", true);
layui.$.post("{:url('/system/admin/edit" + event + "')}",
post.field, function (res) {
if (res.code === 200) {
@@ -391,6 +391,7 @@
// 关闭当前窗口
layer.msg(res.msg);
layer.close(colletction.index);
clickthis.attr("disabled", true);
} else {
layer.error(res.msg);
}

View File

@@ -10,6 +10,17 @@
font-size: 16px;
}
#layui-dic_group {
padding-bottom: 25px;
}
#layui-dic_group .layui-table-view .layui-table {
width: 100%;
}
#layui-dic_group table thead tr:first-child i {
display: none;
}
@media screen and (max-width: 1200px){
.layui-table-tool-temp .layui-btn {
@@ -24,21 +35,8 @@
}
}
#layui_side_left {
padding-bottom: 25px;
}
#layui_side_left .layui-table-view .layui-table {
width: 100%;
}
#layui_side_left table thead tr:first-child i
{
display: none;
}
</style>
<div class="layui-col-md3">
<div class="layui-col-md4">
<div class="layui-fluid">
<div class="layui-card">
<div class="layui-card-header layadmin-card-header-auto" style="padding-bottom: 5px">
@@ -52,35 +50,20 @@
<i class="layui-icon layui-icon-edit"></i>{:__('修改')}
</button>
<!-- // 删除所有 -->
<button class="layui-btn icon-btn layui-btn-danger" lay-batch="lay-tree" data-url="{:url('/system/Dictionary/del')}" >
<button class="layui-btn icon-btn layui-btn-danger" lay-batch="" data-table="lay-tree" data-url="{:url('/system/Dictionary/del')}" >
<i class="layui-icon layui-icon-delete"></i>{:__('删除')}
</button>
</div>
</div>
<div class="layui-card-body" id="layui_side_left">
<!-- // 创建数据实例 -->
<table class="layui-table"
lay-data="{
url:'{:url('/system/Dictionary/index')}?pid=0',
toolbar: '#toolbar',
defaultToolbar: [],
limit: 20,
id:'lay-tree'}"
lay-filter="lay-tree" >
<thead>
<tr>
<th lay-data="{type:'radio'}"></th>
<th lay-data="{field:'name'}">{:__('字典名称')}</th>
</tr>
</thead>
</table>
<div class="layui-card-body" id="layui-dic_group">
<!-- // 创建字典组实例 -->
<table id="lay-tableGroup" lay-filter="lay-tableGroup"></table>
</div>
</div>
</div>
</div>
<div class="layui-col-md9" >
<div class="layui-col-md8" >
<!-- // 展示数据 -->
<div class="layui-fluid">
<div class="layui-card">
@@ -125,13 +108,13 @@
</div>
<!-- // 添加编辑数据 -->
<script type="text/html" id="editforms" >
<section id="editforms" class="layui-hide">
<div class="layui-fluid layui-bg-white">
<form class="layui-form layui-form-fixed" lay-filter="editforms">
<input type="text" name="id" hidden="">
<input type="text" class="pid" name="pid" value="{$pid}" hidden="">
<div class="layui-form-item">
<label class="layui-form-label"><font color="red">* </font>{:__('')}</label>
<label class="layui-form-label"><span style="color: red; ">* </span>{:__('字典名称')}</label>
<div class="layui-input-block">
<input name="name" placeholder="{:__('请输入字典名称')}" type="text" class="layui-input" lay-verify="required" />
</div>
@@ -160,12 +143,12 @@
<div class="layui-footer layui-form-item layui-center">
<button class="layui-btn layui-btn-primary" type="button" sa-event="closePageDialog" >{:__('取消')}</button>
<button class="layui-btn" lay-add="{:url('/system/Dictionary/add')}" lay-edit="{:url('/system/Dictionary/edit')}" lay-filter="submitPage"
lay-submit>{:__('提交')}</button>
<button class="layui-btn" lay-add="{:url('/system/Dictionary/add')}" lay-edit="{:url('/system/Dictionary/edit')}"
lay-filter="submitPage" lay-submit>{:__('提交')}</button>
</div>
</form>
</div>
</script>
</section>
<!-- // 列表编辑框 -->
<script type="text/html" id="tableBar">
@@ -178,15 +161,31 @@
<script>
layui.use(['admin','jquery','table','form'], function () {
var admin = layui.admin;
var jquery = layui.jquery;
var table = layui.table;
var form = layui.form;
let admin = layui.admin;
let $ = layui.jquery;
let table = layui.table;
let form = layui.form;
// 定义表格URL
var tableURL = "{:url('/system/Dictionary/index')}";
let tableURL = "{:url('/system/Dictionary/index')}";
// 字典类表格
let isClass = table.render({
elem: "#lay-tableGroup"
, url: tableURL + "?pid=0"
, toolbar: '#toolbar'
, defaultToolbar: []
, page: true
, limit: 18
, cols: [[
{type: 'radio', align: 'left', title: '{:__("ID")}'},
{field: 'name', align: 'center', title: '{:__("字典类型")}'},
{field: 'value', align: 'center', title: '{:__("字典值")}'},
]]
})
// 基础表格
var isTable = table.render({
let isTable = table.render({
elem: "#lay-tableList"
,url: tableURL
,page: true
@@ -197,72 +196,69 @@
{field: 'name', align: 'center', title: '{:__("字典项名称")}'},
{field: 'value', align: 'center', title: '{:__("字典值")}'},
{field: 'sort', align: 'center', width: 135, title: '{:__("排序号")}'},
{field: 'create_time', align: 'center', width: 160,title: '{:__("创建时间")}'},
{field: 'create_time', align: 'center', width: 180,title: '{:__("创建时间")}'},
{align: 'center', toolbar: '#tableBar',width: 250, title: '{:__("操作")}'},
]]
})
table.on('radio(lay-tree)', function(obj){
var data = table.checkStatus('lay-tree').data;
var ids = [];
table.on('radio(lay-tableGroup)', function(obj){
let data = table.checkStatus('lay-tableGroup').data;
let ids = [];
if (data.length) {
for (const key in data) {
ids.push(data[key].id);
}
var url = tableURL + '?pid=' + ids.join(',');
let url = tableURL + '?pid=' + ids.join(',');
table.reloadData('lay-tableList', {
url: url
});
// 获取最后点击
if (obj.checked === true) {
setLastPID(obj.data.id);
window.tableElem = obj;
$('#editforms').find('.pid').attr('value',obj.data.id);
}
}
});
// 全局回调函数
admin.callback.edit = function(clickthis,colletction,config) {
var status = true;
var data = table.checkStatus('lay-tree').data;
if (clickthis.attr('lay-open') === 'edit') {
let status = true;
let action = clickthis.attr('lay-open');
let data = table.checkStatus('lay-tableGroup').data;
if (action === 'edit') {
status = false;
form.val('editforms',data[0]);
}
form.on("submit(submitPage)",function(post){
var pageThat = jquery(this),
form.on("submit(submitPage)",function(post){
let pageThat = $(this),
_pageUrl = !status ? pageThat.attr('lay-edit') : pageThat.attr('lay-add');
post.field.pid = 0;
// 开始POST提交数据
pageThat.attr("disabled",true);
jquery.post(_pageUrl,
$.post(_pageUrl,
post.field, function(res){
if (res.code === 200) {
layer.msg(res.msg);
if (typeof window.tableElem !== 'undefined') {
window.tableElem.update(JSON.parse(JSON.stringify(post.field)))
} else {
table.reloadData('lay-tableGroup');
}
// 关闭当前窗口
table.reload('lay-tree');
layer.msg(res.msg);
layer.close(colletction.index);
pageThat.attr("disabled",true);
}
else {
layer.error(res.msg);
}
}, 'json');
pageThat.attr("disabled",false);
return false;
})
}
function setLastPID(pid) {
var html = jquery(jquery('#editforms').html());
html.find('.pid').attr('value',pid);
jquery('#editforms').html(html);
}
});
</script>

View File

@@ -31,6 +31,9 @@ class Admin extends Validate
'name.max' => '用户名不能超过12个字符',
'name.filters' => '用户名包含禁止注册字符',
'name.chsAlphaNum' => '用户名只能是汉字、字母和数字',
'pwd.require' => '密码不能为空',
'pwd.min' => '密码不能少于6个字符',
'pwd.max' => '密码不能超过64个字符',
];
// 测试验证场景

View File

@@ -396,7 +396,7 @@ INSERT INTO `__PREFIX__config` VALUES (18, 'auth_code', 0, NULL, 'string', 'wMRk
INSERT INTO `__PREFIX__config` VALUES (19, 'system_logs', 0, NULL, 'string', '0', '后台日志');
INSERT INTO `__PREFIX__config` VALUES (20, 'system_exception', 0, NULL, 'string', '0', '异常日志');
INSERT INTO `__PREFIX__config` VALUES (21, 'cache_status', 0, 'cache', 'string', '1', '缓存状态');
INSERT INTO `__PREFIX__config` VALUES (22, 'cache_type', 0, 'cache', 'string', 'redis', '缓存类型');
INSERT INTO `__PREFIX__config` VALUES (22, 'cache_type', 0, 'cache', 'string', 'file', '缓存类型');
INSERT INTO `__PREFIX__config` VALUES (23, 'cache_time', 0, 'cache', 'string', '6000', '缓存时间');
INSERT INTO `__PREFIX__config` VALUES (24, 'cache_host', 0, 'cache', 'string', '127.0.0.1', '服务器IP');
INSERT INTO `__PREFIX__config` VALUES (25, 'cache_port', 0, 'cache', 'string', '6379', '端口');

View File

@@ -13,20 +13,18 @@
*/
return [
'type' => 'redis', // or redis or redis_cluster
'handler' => Webman\Session\RedisSessionHandler::class,
'type' => getenv('CACHE_DRIVER') ?: 'file', // or redis or redis_cluster
'handler' => getenv('CACHE_DRIVER') == 'redis' ? Webman\Session\RedisSessionHandler::class : Webman\Session\FileSessionHandler::class,
'config' => [
'file' => [
'save_path' => runtime_path() . '/sessions',
],
'redis' => [
'host' => '127.0.0.1',
'port' => 6379,
'auth' => '',
'timeout' => 2,
'database' => getenv('CACHE_SELECT') ?? 0,
'prefix' => '',
'host' => getenv('CACHE_HOSTNAME') ?: '127.0.0.1',
'port' => getenv('CACHE_HOSTPORT') ?: 6379,
'database' => getenv('CACHE_SELECT') ?: 0,
'auth' => getenv('CACHE_PASSWORD') ?: '',
'prefix' => '', // session key prefix
],
'redis_cluster' => [
'host' => ['127.0.0.1:7000', '127.0.0.1:7001', '127.0.0.1:7001'],
@@ -35,7 +33,7 @@ return [
'prefix' => '',
]
],
'session_name' => 'SAPHPID',
'session_name' => 'SESSION_ID',
'auto_update_timestamp' => false,
'lifetime' => 7 * 24 * 60 * 60,
'cookie_lifetime' => 7 * 24 * 60 * 60,

View File

@@ -639,7 +639,7 @@ layui.define(['jquery', 'i18n', 'element', 'layer', 'form', 'rate', 'table', 'sl
auto: clickObject.data('auto') || undefined,
shadeClose: clickObject.data('shadeclose') || false,
scrollbar: clickObject.data('scrollbar') || undefined,
disableform: clickObject.data('disable') || false,
disableForm: clickObject.data('disable') || false,
callback: clickObject.attr('callback') || undefined,
iframeAuto: false
};
@@ -651,9 +651,9 @@ layui.define(['jquery', 'i18n', 'element', 'layer', 'form', 'rate', 'table', 'sl
options.type = 1;
options.url = $(options.url).html();
if (typeof tableThis !== 'undefined') {
let htmls = $(options.url);
$(htmls).find('*[data-disabled]').addClass('layui-disabled').attr('disabled', '');
options.url = htmls.prop("outerHTML");
let html_text = $(options.url);
$(html_text).find('*[data-disabled]').addClass('layui-disabled').attr('disabled', '');
options.url = html_text.prop("outerHTML");
}
}
@@ -691,7 +691,7 @@ layui.define(['jquery', 'i18n', 'element', 'layer', 'form', 'rate', 'table', 'sl
if (options.type <= 1) {
// 禁止滚动条
$(layero).children('.layui-layer-content').css('overflow', 'visible');
if (typeof tableThis !== 'undefined' && !options.disableform) {
if (typeof tableThis !== 'undefined' && !options.disableForm) {
form.val(options.id, tableThis.data);
}
@@ -734,6 +734,7 @@ layui.define(['jquery', 'i18n', 'element', 'layer', 'form', 'rate', 'table', 'sl
dataType: 'json',
data: post.field,
success: function (res) {
for (var elem in post.field) {
var lay = $(clickObject).parents("tr").find('*[data-field=' + elem + ']').find('*[lay-skin]');
if (lay.length !== 0) {
@@ -772,9 +773,7 @@ layui.define(['jquery', 'i18n', 'element', 'layer', 'form', 'rate', 'table', 'sl
return false;
})
}
}
})
}
@@ -1565,11 +1564,12 @@ layui.define(['jquery', 'i18n', 'element', 'layer', 'form', 'rate', 'table', 'sl
}
var _parent = that.data('reload') || false;
that.attr("disabled", true);
$.post(_url, data.field, function (res) {
if (res.code === 200) {
top.layer.msg(res.msg);
that.attr("disabled", true);
if (_close === undefined) {
admin.event.closeDialog(that);
}
@@ -1594,6 +1594,7 @@ layui.define(['jquery', 'i18n', 'element', 'layer', 'form', 'rate', 'table', 'sl
}, 'json');
// 延迟释放按钮
setTimeout(function (e) {
that.attr("disabled", false);
}, 2000);