12 Commits

Author SHA1 Message Date
wolfcode
e4ae29fed2 fix(admin): update password hashing method- Replace password function with password_hash for secure password storage- Use PASSWORD_DEFAULT algorithm for hashing
- Improve password security in admin controller

Signed-off-by: wolfcode <wolfcode@88.com>
2025-06-28 10:15:07 +08:00
wolfcode
c82e1c8ea3 fix(curd): improve form element rendering and validation
- Add length validation for images form type
- Update radio and checkbox view generation to use correct syntax- Improve select option view generation with more accurate conditions
2025-06-25 18:55:43 +08:00
wolfcode
3f718beacb fix(admin): update password hashing method-Replace custom password function with PHP's built-in password_hash
- Improve password security in admin controller
2025-06-23 11:24:27 +08:00
wolfcode
af44a9e7b8 🚀 Layui v2.11.3 2025-06-19 09:40:41 +08:00
wolfcode
4ed8237a00 refactor(auth): upgrade password hashing to PHP's password_hash
- Replace custom password hashing function with PHP's built-in password_hash
- Update password verification to use password_verify
- Adjust database schema to accommodate new password hash length
- Modify installation and login controllers to use new hashing method
2025-06-18 11:51:12 +08:00
wolfcode
216ca6e697 fix(install): update PDO extension check to pdo_mysql
- Change extension check from PDO to pdo_mysql for MySQL database support
- Improve error message for better user understanding
2025-06-12 15:21:35 +08:00
wolfcode
969a7a5ce5 fix(easy-admin): try-catch onInitElemStyle and hide theme switch on mobile
- Add try-catch block around onInitElemStyle function to handle potential errors
- Hide theme switch option on mobile devices to improve user experience
2025-06-09 14:37:58 +08:00
wolfcode
5593a20009 feat(layuimini): improve menu rendering and add keyboard event handling
- Add border-radius to layuimini-logo for rounded corners
- Implement Enter key event handling for login button- Enhance miniMenu rendering logic for better menu display
2025-06-04 11:14:55 +08:00
wolfcode
8a33a4fed3 fix(easy-admin): improve select component rendering and initialization
- Update select component initialization to properly set selected values
- Modify search value comparison to use loose equality for broader compatibility
- Enhance xmSelect rendering with pre-selected values
2025-05-20 10:22:50 +08:00
wolfcode
a4e8a86045 🚀 Layui v2.11.2 2025-05-19 18:30:34 +08:00
wolfcode
61e622d2ad refactor(controller): instantiate model class instead of assigning model name
- Change {{modelFilename}}::class to new {{modelFilename}}() in controller constructor- This modification allows direct access to model properties and methods
2025-05-14 12:32:02 +08:00
wolfcode
1b3265aeb5 feat(menu): add toggle buttons for menu folding and unfolding
- Add a new button for toggling menu folding and unfolding
- Implement functionality to fold and unfold all menu items
- Update button text and icon based on current state (folded/unfolded)
2025-05-13 14:06:20 +08:00
18 changed files with 113 additions and 34 deletions

View File

@@ -109,7 +109,7 @@ class Index extends AdminController
try {
$save = $row->save([
'password' => password($post['password']),
'password' => password_hash($post['password'], PASSWORD_DEFAULT),
]);
}catch (Exception $e) {
$this->error('保存失败');

View File

@@ -53,7 +53,7 @@ class Login extends AdminController
if (empty($admin)) {
$this->error('用户不存在');
}
if (password($post['password']) != $admin->password) {
if (!password_verify($post['password'], $admin->password)) {
$this->error('密码输入有误');
}
if ($admin->status == 0) {

View File

@@ -24,7 +24,7 @@ class Goods extends AdminController
public function __construct(App $app)
{
parent::__construct($app);
self::$model = MallGoods::class;
self::$model = new MallGoods();
$this->assign('cate', MallCate::column('title', 'id'));
}

View File

@@ -63,7 +63,7 @@ class Admin extends AdminController
$rule = [];
$this->validate($post, $rule);
if (empty($post['password'])) $post['password'] = '123456';
$post['password'] = password($post['password']);
$post['password'] = password_hash($post['password'],PASSWORD_DEFAULT);
try {
$save = self::$model::create($post);
}catch (\Exception $e) {
@@ -114,7 +114,7 @@ class Admin extends AdminController
}
try {
$save = $row->save([
'password' => password($post['password']),
'password' => password_hash($post['password'], PASSWORD_DEFAULT),
]);
}catch (\Exception $e) {
$this->error('保存失败');

View File

@@ -1217,6 +1217,7 @@ class BuildCurd
} elseif ($val['formType'] == 'images') {
$templateFile = "view{$this->DS}module{$this->DS}images";
$define = $val['define'] ?? '|';
if (strlen($define) > 5) $define = '|';
} elseif ($val['formType'] == 'file') {
$templateFile = "view{$this->DS}module{$this->DS}file";
} elseif ($val['formType'] == 'files') {
@@ -1234,12 +1235,12 @@ class BuildCurd
} elseif ($val['formType'] == 'radio') {
$templateFile = "view{$this->DS}module{$this->DS}radio";
if (!empty($val['define'])) {
$define = $this->buildRadioView($field, '{in name="k" value="' . $val['default'] . '"}checked=""{/in}');
$define = $this->buildRadioView($field, '');
}
} elseif ($val['formType'] == 'checkbox') {
$templateFile = "view{$this->DS}module{$this->DS}checkbox";
if (!empty($val['define'])) {
$define = $this->buildCheckboxView($field, '{in name="k" value="' . $val['default'] . '"}checked=""{/in}');
$define = $this->buildCheckboxView($field, '');
}
} elseif ($val['formType'] == 'select') {
$templateFile = "view{$this->DS}module{$this->DS}select";
@@ -1308,19 +1309,19 @@ class BuildCurd
} elseif ($val['formType'] == 'radio') {
$templateFile = "view{$this->DS}module{$this->DS}radio";
if (!empty($val['define'])) {
$define = $this->buildRadioView($field, '{in name="k" value="$row.' . $field . '"}checked=""{/in}');
$define = $this->buildRadioView($field, '{if in_array($k, $row.' . $field . ')}checked{/if}');
}
} elseif ($val['formType'] == 'checkbox') {
$templateFile = "view{$this->DS}module{$this->DS}checkbox";
if (!empty($val['define'])) {
$define = $this->buildCheckboxView($field, '{in name="k" value="$row.' . $field . '"}checked=""{/in}');
$define = $this->buildCheckboxView($field, '{if in_array($k, $row.' . $field . ')}checked{/if}');
}
} elseif ($val['formType'] == 'select') {
$templateFile = "view{$this->DS}module{$this->DS}select";
if (isset($val['bindRelation'])) {
$define = $this->buildOptionView($field, '{in name="k" value="$row.' . $field . '"}selected=""{/in}');
$define = $this->buildOptionView($field, '{if $row.' . $field . '==$k}selected{/if}');
} elseif (!empty($val['define'])) {
$define = $this->buildOptionView($field, '{in name="k" value="$row.' . $field . '"}selected=""{/in}');
$define = $this->buildOptionView($field, '{if $row.' . $field . '==$k}selected{/if}');
}
} elseif ($field == 'remark' || $val['formType'] == 'textarea') {
$templateFile = "view{$this->DS}module{$this->DS}textarea";

View File

@@ -16,7 +16,7 @@ class {{controllerName}} extends AdminController
public function __construct(App $app)
{
parent::__construct($app);
self::$model = {{modelFilename}}::class;
self::$model = new {{modelFilename}}();
$notes = self::$model::$notes;
{{constructRelation}}
$this->notes =$notes;

View File

@@ -38,7 +38,7 @@
<li class="layui-nav-item mobile layui-hide-xs" lay-unselect>
<a href="javascript:;" data-check-screen="full"><i class="fa fa-arrows-alt"></i></a>
</li>
<li class="layui-nav-item" lay-unselect>
<li class="layui-nav-item mobile layui-hide-xs" lay-unselect>
<div class="layui-form ws-header-theme" lay-filter="header-theme">
<input type="checkbox" name="theme-mode" lay-filter="header-theme-mode" lay-skin="switch">
<div lay-checkbox>

View File

@@ -20,4 +20,5 @@
<button class="layui-btn layui-btn-sm layuimini-btn-primary" data-treetable-refresh><i class="fa fa-refresh"></i></button>
<button class="layui-btn layui-btn-normal layui-btn-sm {if !auth('system.menu/add')}layui-hide{/if}" data-open="system.menu/add" data-title="添加"><i class="fa fa-plus"></i> 添加</button>
<button class="layui-btn layui-btn-sm layui-btn-danger {if !auth('system.menu/delete')}layui-hide{/if}" data-url="system.menu/delete" data-treetable-delete="currentTableRenderId"><i class="fa fa-trash-o"></i> 删除</button>
<button class="layui-btn layui-btn-sm" type="button" data-treetable-arrow data-arrow="up"><i class="fa fa-arrow-up"></i> 一键折叠</button>
</script>

View File

@@ -24,8 +24,8 @@ class Install extends BaseController
$errorInfo = '已安装系统,如需重新安装请删除文件:/config/install/lock/install.lock或者删除 /install 路由';
}elseif (version_compare(phpversion(), '8.1.0', '<')) {
$errorInfo = 'PHP版本不能小于8.1.0';
}elseif (!extension_loaded("PDO")) {
$errorInfo = '当前未开启PDO,无法进行安装';
}elseif (!extension_loaded("pdo_mysql")) {
$errorInfo = '当前未开启pdo_mysql,无法进行安装';
}
if (!is_file(root_path() . '.env')) {
$errorInfo = '.env 文件不存在,请先配置 .env 文件';
@@ -105,12 +105,12 @@ class Install extends BaseController
foreach ($sqlArray as $sql) {
$pdo->query($sql);
}
$_password = password($password);
$tableName = 'system_admin';
$update = [
$hashedPassword = password_hash($password, PASSWORD_DEFAULT);
$tableName = 'system_admin';
$update = [
'username' => $username,
'head_img' => '/static/admin/images/head.jpg',
'password' => $_password,
'password' => $hashedPassword,
'create_time' => time(),
'update_time' => time()
];

View File

@@ -88,7 +88,7 @@ CREATE TABLE `ea_system_admin`
`auth_ids` varchar(255) DEFAULT NULL COMMENT '角色权限ID',
`head_img` varchar(255) DEFAULT NULL COMMENT '头像',
`username` varchar(50) NOT NULL DEFAULT '' COMMENT '用户登录名',
`password` char(40) NOT NULL DEFAULT '' COMMENT '用户登录密码',
`password` varchar(255) NOT NULL DEFAULT '' COMMENT '用户登录密码',
`phone` varchar(16) DEFAULT NULL COMMENT '联系手机号',
`remark` varchar(255) DEFAULT '' COMMENT '备注说明',
`login_num` bigint(20) unsigned DEFAULT '0' COMMENT '登录次数',

View File

@@ -27,6 +27,12 @@ define(["jquery", "easy-admin"], function ($, ea) {
}
});
document.addEventListener('keydown', function (event) {
if (event.key === 'Enter' || event.keyCode === 13) {
$('.login-btn').trigger('click')
}
});
$('.login-tip').on('click', function () {
$('.icon-nocheck').click();
});

View File

@@ -121,6 +121,22 @@ define(["jquery", "easy-admin", "treetable", "iconPickerFa", "autocomplete"], fu
return false;
});
$('body').on('click', '[data-treetable-arrow]', function () {
const $icon = $(this).find('i');
const $textNode = $icon[0].nextSibling;
if ($icon.hasClass('fa-arrow-up')) {
treetable.foldAll(init.table_elem);
$icon.removeClass('fa-arrow-up').addClass('fa-arrow-down');
$textNode.textContent = ' 一键展开';
$(this).attr('data-arrow', 'down');
} else {
treetable.expandAll(init.table_elem);
$icon.removeClass('fa-arrow-down').addClass('fa-arrow-up');
$textNode.textContent = ' 一键折叠';
$(this).attr('data-arrow', 'up');
}
})
ea.table.listenSwitch({filter: 'status', url: init.modify_url});
ea.table.listenEdit(init, 'currentTable', init.table_render_id, true);

View File

@@ -154,4 +154,46 @@ function prettyFormat(str) {
return ''
}
return "<pre>" + result + "</pre>"
}
}
if (self === top) {
console.group('温馨提示');
console.log(`%c
▄▄ ▄▄
▀███▀▀▀███ ██ ▀███ ██ ▄█▄▀▄██▄
██ ▀█ ▄██▄ ██ ██ ██
██ █ ▄█▀██▄ ▄██▀█████▀ ▀██▀ ▄█▀██▄ ▄█▀▀███ ▀████████▄█████▄ ▀███ ▀████████▄ ▀██▄ ▄▄█
██████ ██ ██ ██ ▀▀ ██ ▄█ ▄█ ▀██ ▄██ ██ ██ ██ ██ ██ ██ ██ ▄█████▄
██ █ ▄▄█████ ▀█████▄ ██ ▄█ ████████ ███ ██ ██ ██ ██ ██ ██ ██ ██ ▀███
██ ▄██ ██ █▄ ██ ███ █▀ ██ ▀██ ██ ██ ██ ██ ██ ██ ██ ██ ▀██
▄██████████████▀██▄██████▀ ▄█ ▄███▄ ▄████▄ ▀████▀███▄████ ████ ████▄████▄████ ████▄███████
▄█
██▀
%c
官方网站https://easyadmin8.top
官方文档https://edocs.easyadmin8.top
问答社区https://meta.easyadmin8.top
%c重要事情说3遍
%c
常见问题https://easyadmin8.top/guide/question.html
常见问题https://easyadmin8.top/guide/question.html
常见问题https://easyadmin8.top/guide/question.html
%c遇到问题先把 DEBUG 模式打开然后把错误信息找出来当不能解决的时候再去社区提问或者QQ群交流
`,
"color:#4290f7;font-weight:bold;font-size:10px;",
"color:#5672cd;",
"color:#ff5722;font-weight:bold;font-size:1rem;",
"color:#5672cd;",
"color:#ff5722;font-weight:bold;font-size:1rem;background:#f9de97;",
);
console.groupEnd();
}

View File

@@ -2,13 +2,16 @@ define(["jquery", "tableSelect", "miniTheme", "xmSelect", "lazyload"], function
//切换日夜模式
window.onInitElemStyle = function () {
miniTheme.renderElemStyle();
$('iframe').each(function (index, iframe) {
if (typeof iframe.contentWindow.onInitElemStyle == "function") {
iframe.contentWindow.onInitElemStyle();
}
});
miniTheme.changeThemeMainColor();
try {
miniTheme.renderElemStyle();
$('iframe').each(function (index, iframe) {
if (typeof iframe.contentWindow.onInitElemStyle == "function") {
iframe.contentWindow.onInitElemStyle();
}
});
miniTheme.changeThemeMainColor();
} catch (e) {
}
};
window.onInitElemStyle();
@@ -373,7 +376,7 @@ define(["jquery", "tableSelect", "miniTheme", "xmSelect", "lazyload"], function
var selectHtml = '';
$.each(d.selectList, function (sI, sV) {
var selected = '';
if (sI === d.searchValue) {
if (sI == d.searchValue) {
selected = 'selected=""';
}
selectHtml += '<option value="' + sI + '" ' + selected + '>' + sV + '</option>/n';
@@ -396,7 +399,7 @@ define(["jquery", "tableSelect", "miniTheme", "xmSelect", "lazyload"], function
formHtml += '\t<div class="layui-form-item layui-inline">\n' +
'<label class="layui-form-label">' + d.title + '</label>\n' +
'<div class="layui-input-inline">\n' +
'<div id="c-' + d.fieldAlias + '" class="tableSearch-xmSelect xmSelect-' + d.fieldAlias + '" name="' + d.fieldAlias + '" data-search-op="' + d.searchOp + '"></div>\n' +
'<div id="c-' + d.fieldAlias + '" class="tableSearch-xmSelect xmSelect-' + d.fieldAlias + '" name="' + d.fieldAlias + '" data-search-op="' + d.searchOp + '" data-search-value="' + d.searchValue + '"></div>\n' +
'</div>\n' +
'</div>';
init.xmSelectList[d.fieldAlias] = d.selectList
@@ -874,8 +877,10 @@ define(["jquery", "tableSelect", "miniTheme", "xmSelect", "lazyload"], function
listenTableSearch: function (tableId) {
if (Object.keys(init.xmSelectList).length > 0) {
$.each(init.xmSelectList, function (index, value) {
let xmSearchValue = $('#c-' + index).data('search-value') || [];
if (!Array.isArray(xmSearchValue)) xmSearchValue = (xmSearchValue.toString()).split(',')
const keysArray = Object.keys(value).map((key) => {
return {name: value[key], value: key}
return {name: value[key], value: key, selected: xmSearchValue.indexOf(key) !== -1}
})
init.xmSelectModel[index] = xmSelect.render({
el: '.xmSelect-' + index, language: 'zn', data: keysArray, name: index,

View File

@@ -83,6 +83,7 @@
display: inline-block;
height: 40px;
vertical-align: middle;
border-radius: 50%;
}
.layui-layout-admin .layuimini-logo h1 {

View File

@@ -94,7 +94,14 @@ define(["jquery"], function ($) {
renderLeftMenu :function(leftMenus,options){
options = options || {};
var me = this ;
var leftMenusHtml = me.each(leftMenus || [],function (idx,leftMenu) { // 左侧菜单遍历
let _i = 0
// 左侧菜单遍历
var leftMenusHtml = me.each(leftMenus || [],function (idx,leftMenu) {
$(leftMenu).each(function (index, child) {
options.childOpenClass = ''
if (child.child && child.child.length && _i === 0) options.childOpenClass = ' layui-nav-itemed'
_i++
})
var children = me.renderChildrenMenu(leftMenu.child, { childOpenClass:options.childOpenClass });
var leftMenuHtml = me.compileMenu({
href:leftMenu.href,

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long