24 Commits

Author SHA1 Message Date
wolfcode
3e329a4ea3 fix(install): update ea_system_admin insert statement
- Add missing column for 'status' in ea_system_admin insert statement
- Set 'status' column to 1 for the admin user
2024-11-13 16:30:15 +08:00
wolfcode
f015a90b89 style(layuimini): remove redundant CSS rules for nav more icons- Removed specific margin-top rules for .layuimini-menu-left and .layuimini-menu-left-zoom classes
- Kept the general rule for .layuimini-menu-left .layui-nav .layui-nav-mored and .layuimini-menu-left .layui-nav-itemed > a .layui-nav-more
2024-11-12 17:21:04 +08:00
wolfcode
75c668b966 feat(auth): 新增谷歌验证码登录 implement Google Authenticator support for two-factor authentication
- Add Google Authenticator integration for enhanced login security-Update admin edit page to include login type selection
- Modify login process to support two-factor authentication
- Add new database fields for login type and GA secret
- Update client-side JavaScript to handle GA code input and validation
2024-11-12 10:51:48 +08:00
wolfcode
f3e5a041d1 feat(ueditor): add custom upload service and other enhancements
- Add custom upload service support
- Implement server response preparation function
- Enable loading config from server
- Add content import button to toolbar
- Update image alignment buttons order
- Add tip error function for better error handling
- Remove unused comments and simplify configuration options
2024-11-11 11:22:47 +08:00
wolfcode
3b219cfe7f feat(install): add official website tutorial and common questions links
- Add links to the official website tutorial and common questions in the installation page
- Update the logo image style for better visual presentation
2024-11-04 11:53:39 +08:00
wolfcode
ed99fe79fd feat(admin): 快捷操作支持翻页滚动显示 and optimize UI for better user experience
- Add swiper plugin support for carousel functionality
- Optimize UI for better user experience by using swiper
- Update index.js to support swiper initialization
- Modify welcome.html to include swiper HTML structure
- Adjust welcome.css for better styling of swiper elements
2024-10-29 17:24:54 +08:00
wolfcode
846b8ffafc feat(easy-admin): update window open URL for new tab button
- Change the URL for the "New tab open" button to use the iframe's content URL
- Add fallback to current window URL if iframe content URL cannot be accessed
- Improve user experience by opening the correct URL in a new tab

Signed-off-by: wolfcode <37436228+wolf-leo@users.noreply.github.com>
2024-10-28 18:26:26 +08:00
wolfcode
47ef5d9f10 feat(auth): 改用 zTree 替换 layui 的 tree 组件 use zTree for node authorization
- Replace layui tree with zTree for better performance and flexibility
- Update auth.js to use zTree for node rendering and checking
- Add zTree CSS and JS files to project

Signed-off-by: wolfcode <37436228+wolf-leo@users.noreply.github.com>
2024-10-28 16:35:06 +08:00
wolfcode
70ec12f406 feat(admin): 新增搜索表单多选功能 add xmSelect plugin support for multiple selection
- Add xmSelect case handling in AdminController for 'in' operation
- Include xmSelect.js in admin layout
- Update easy-admin.js to support xmSelect initialization and data binding
- Modify goods.js to demonstrate xmSelect usage with simulated data
- Adjust public.css for better styling of xmSelect elements

Signed-off-by: wolfcode <37436228+wolf-leo@users.noreply.github.com>
2024-10-25 11:44:19 +08:00
wolfcode
e15b56ecc9 Update composer.json 2024-10-24 09:37:09 +08:00
wolfcode
af275e1c6a fix(install): check for .env file existence before installation
- Add a check for the presence of the .env file in the root directory
- Update the index method to redirect to the admin page with a default value

Signed-off-by: wolfcode <37436228+wolf-leo@users.noreply.github.com>
2024-10-23 10:27:06 +08:00
wolfcode
20d4038159 Update public.css 2024-10-22 16:08:23 +08:00
wolfcode
475a1ef84d refactor(admin): update login.js to include jQuery dependency
- Add jQuery as a dependency in the define function
- Update the function parameters to include jQuery ($)

Signed-off-by: wolfcode <37436228+wolf-leo@users.noreply.github.com>
2024-10-22 14:43:50 +08:00
wolfcode
9307e724a9 refactor(SystemLogService): optimize detectTable method and improve code quality
- Remove unnecessary return type annotation in instance method
- Add type hint for SystemLogService instance
- Use variable for cache key to improve code readability
- Update cache key name for consistency

Signed-off-by: wolfcode <37436228+wolf-leo@users.noreply.github.com>
2024-10-22 11:54:59 +08:00
wolfcode
6616e96724 perf(middleware): optimize system log middleware for performance
- Remove redundant code for checking ignoreLog property
- Consolidate logic to check ignoreLog property in a single location
- Improve readability and maintainability of the code

Signed-off-by: wolfcode <37436228+wolf-leo@users.noreply.github.com>
2024-10-22 11:31:06 +08:00
wolfcode
963febc15c feat(admin): 新增弹框是否允许在新标签页中打开 add option to open iframe in new tab
- Add 'iframe_open_top' configuration to admin site settings
- Implement functionality to open iframe in new tab if configured
- Update admin layout to include new configuration option
- Modify easy-admin.js to support new tab opening for iframes

Signed-off-by: wolfcode <37436228+wolf-leo@users.noreply.github.com>
2024-10-21 16:27:48 +08:00
wolfcode
f78edd2fd5 refactor(css): simplify table styles and remove redundant code
- Remove duplicate styles for .layui-table-tool
- Delete unused styles for .layui-table-view and .layui-table-box
- Simplify border styles for light and dark themes- Remove unnecessary padding and positioning styles- Improve readability of table header text

Signed-off-by: wolfcode <37436228+wolf-leo@users.noreply.github.com>
2024-10-16 22:21:20 +08:00
wolfcode
83aa399f95 feat(easy-admin): prevent rapid form submission
Add a mechanism to handle quick consecutive form submissions by displaying a message when a user tries to submit the form before the previous submission is completed. This
update introduces a wait period during which subsequent submissions are prevented,
enhancing the user experience and preventing potential errors.

Signed-off-by: wolfcode <37436228+wolf-leo@users.noreply.github.com>
2024-10-16 11:05:26 +08:00
wolfcode
3096aa8985 🚀Layui v2.9.18 2024-10-15 11:08:50 +08:00
wolfcode
c7f7ca9af7 Update README.md 2024-10-14 18:00:48 +08:00
wolfcode
352484c69e fix(layout): adjust column layout for better responsiveness
Changed the column layout in both goods add and edit pages to ensure better responsiveness across different screen sizes. The left column is now fixed at 5 units, while the right column is set to 12 units for improved flexibility on smaller screens.

Signed-off-by: wolfcode <37436228+wolf-leo@users.noreply.github.com>
2024-10-14 17:31:51 +08:00
wolfcode
dfe15f7e88 feat(admin): 新增过滤不需要记录后台日志的方法 add ignoreLog property to exclude log recording for specific actions
- Add 'ignoreLog' property to the Log controller to specify actions that should not be logged
- Implement logic in SystemLog middleware to check if the current action is in the ignoreLog list
- Skip logging for actions listed in ignoreLog, improving performance and reducing log clutter

Signed-off-by: wolfcode <37436228+wolf-leo@users.noreply.github.com>
2024-10-12 17:21:56 +08:00
wolfcode
4d7365921e chore(deps): bump wolf-leo/phplogviewer from 0.08.0 to 0.10.0
Update the wolf-leo/phplogviewer package from version 0.08.0 to 0.10.0 in composer.json.
This update may include new features, bug fixes, and performance improvements in the PHP log viewer library.

- Update wolf-leo/phplogviewer from ^0.08.0 to ^0.10.0 in composer.json
- Modify return type of System\Log\record() method to Json|string for improved type hinting

Signed-off-by: wolfcode <37436228+wolf-leo@users.noreply.github.com>
2024-10-12 14:00:14 +08:00
wolfcode
d613f3c26f Update composer.json 2024-10-10 15:01:51 +08:00
60 changed files with 57606 additions and 31981 deletions

View File

@@ -39,7 +39,13 @@
> EasyAdmin8 使用 Composer 来管理项目依赖。因此,在使用 EasyAdmin8 之前,请确保你的机器已经安装了 Composer。
### 通过git下载安装包composer安装依赖包
### 通过一键安装命令
```
if [ -f /usr/bin/curl ];then curl -sSO https://easyadmin8.top/auto-install-EasyAdmin8.sh;else wget -O auto-install-EasyAdmin8.sh https://easyadmin8.top/auto-install-EasyAdmin8.sh;fi;bash auto-install-EasyAdmin8.sh
```
### 通过`git`下载安装包,`composer`安装依赖包
```
1.下载安装包

View File

@@ -36,11 +36,9 @@ class Index extends AdminController
$mysqlVersion = Db::query("select version() as version")[0]['version'] ?? '未知';
$phpVersion = phpversion();
$versions = compact('tpVersion', 'mysqlVersion', 'phpVersion');
$quicks = SystemQuick::field('id,title,icon,href')
->where(['status' => 1])
->order('sort', 'desc')
->limit(8)
->select();
$quick_list = SystemQuick::field('id,title,icon,href')
->where(['status' => 1])->order('sort', 'desc')->limit(50)->select()->toArray();
$quicks = array_chunk($quick_list, 8);
$this->assign(compact('quicks', 'versions'));
return $this->fetch();
}
@@ -55,7 +53,7 @@ class Index extends AdminController
*/
public function editAdmin(Request $request): string
{
$id = $this->adminUid;
$id = $this->adminUid;
$row = (new SystemAdmin())
->withoutField('password')
->find($id);
@@ -66,15 +64,20 @@ class Index extends AdminController
$rule = [];
$this->validate($post, $rule);
try {
$save = $row
->allowField(['head_img', 'phone', 'remark', 'update_time'])
->save($post);
}catch (Exception $e) {
$login_type = $post['login_type'] ?? 1;
if ($login_type == 2) {
$ga_secret = (new SystemAdmin())->where('id', $id)->value('ga_secret');
if (empty($ga_secret)) $this->error('请先绑定谷歌验证器');
}
$save = $row->allowField(['head_img', 'phone', 'remark', 'update_time', 'login_type'])->save($post);
}catch (\PDOException $e) {
$this->error('保存失败');
}
$save ? $this->success('保存成功') : $this->error('保存失败');
}
$this->assign('row', $row);
$notes = (new SystemAdmin())->notes;
$this->assign('notes', $notes);
return $this->fetch();
}
@@ -82,13 +85,10 @@ class Index extends AdminController
* 修改密码
* @param Request $request
* @return string
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
public function editPassword(Request $request): string
{
$id = $this->adminUid;
$id = $this->adminUid;
$row = (new SystemAdmin())
->withoutField('password')
->find($id);
@@ -124,4 +124,37 @@ class Index extends AdminController
return $this->fetch();
}
/**
* 设置谷歌验证码
* @param Request $request
* @return string
* @throws Exception
*/
public function set2fa(Request $request): string
{
$id = $this->adminUid;
$row = (new SystemAdmin())->withoutField('password')->find($id);
if (!$row) $this->error('用户信息不存在');
// You can see: https://gitee.com/wolf-code/authenticator
$ga = new \Wolfcode\Authenticator\google\PHPGangstaGoogleAuthenticator();
if (!$request->isAjax()) {
$old_secret = $row->ga_secret;
$secret = $ga->createSecret(32);
$ga_title = $this->isDemo ? 'EasyAdmin8演示环境' : '可自定义修改显示标题';
$dataUri = $ga->getQRCode($ga_title, $secret)->getDataUri();
$this->assign(compact('row', 'dataUri', 'old_secret', 'secret'));
return $this->fetch();
}
$this->isDemo && $this->error('演示环境下不允许修改');
$post = $request->post();
$ga_secret = $post['ga_secret'] ?? '';
$ga_code = $post['ga_code'] ?? '';
if (empty($ga_code)) $this->error('请输入验证码');
if (!$ga->verifyCode($ga_secret, $ga_code)) $this->error('验证码错误');
$row->ga_secret = $ga_secret;
$row->login_type = 2;
$row->save();
$this->success('操作成功');
}
}

View File

@@ -56,6 +56,11 @@ class Login extends AdminController
if ($admin->status == 0) {
$this->error('账号已被禁用');
}
if ($admin->login_type == 2) {
if (empty($post['ga_code'])) $this->error('请输入谷歌验证码', ['is_ga_code' => true]);
$ga = new \Wolfcode\Authenticator\google\PHPGangstaGoogleAuthenticator();
if (!$ga->verifyCode($admin->ga_secret, $post['ga_code'])) $this->error('谷歌验证码错误');;
}
$admin->login_num += 1;
$admin->save();
$admin = $admin->toArray();

View File

@@ -22,6 +22,7 @@ use think\response\Json;
*/
class Log extends AdminController
{
protected array $ignoreLog = ['record'];
public function __construct(App $app)
{
@@ -98,7 +99,7 @@ class Log extends AdminController
/**
* @NodeAnnotation(title="框架日志")
*/
public function record(): string
public function record(): Json|string
{
return (new \Wolfcode\PhpLogviewer\thinkphp\LogViewer())->fetch();
}

View File

@@ -7,9 +7,11 @@ use app\admin\service\annotation\NodeAnnotation;
use app\admin\service\SystemLogService;
use app\common\traits\JumpTrait;
use app\Request;
use ReflectionClass;
use Closure;
use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\Common\Annotations\DocParser;
use ReflectionException;
class SystemLog
{
@@ -26,9 +28,13 @@ class SystemLog
'mobile',
];
/**
* @throws ReflectionException
*/
public function handle(Request $request, Closure $next)
{
$params = $request->param();
$response = $next($request);
$params = $request->param();
if (isset($params['s'])) unset($params['s']);
foreach ($params as $key => $val) {
in_array($key, $this->sensitiveParams) && $params[$key] = "***********";
@@ -39,9 +45,9 @@ class SystemLog
if (env('APP_DEBUG')) {
trace(['url' => $url, 'method' => $method, 'params' => $params,], 'requestDebugInfo');
}
$response = $next($request);
if ($request->isAjax()) {
if (in_array($method, ['post', 'put', 'delete'])) {
$title = '';
try {
$pathInfo = $request->pathinfo();
@@ -53,7 +59,10 @@ class SystemLog
if ($_name && $_controller && $_action) {
$className = "app\admin\controller\\{$_name}\\{$_controller}";
$reflectionClass = new \ReflectionClass($className);
$parser = new DocParser();
$properties = $reflectionClass->getDefaultProperties();
$ignoreLog = $properties['ignoreLog'] ?? [];
if (in_array($_action, $ignoreLog)) return $response;
$parser = new DocParser();
$parser->setIgnoreNotImportedAnnotations(true);
$reader = new AnnotationReader($parser);
$controllerAnnotation = $reader->getClassAnnotation($reflectionClass, ControllerAnnotation::class);

View File

@@ -10,6 +10,13 @@ class SystemAdmin extends TimeModel
protected $deleteTime = 'delete_time';
public array $notes = [
'login_type' => [
1 => '密码登录',
2 => '密码 + 谷歌验证码登录'
],
];
public function getAuthList()
{
$list = (new SystemAuth())

View File

@@ -44,14 +44,13 @@ class SystemLogService
$this->tablePrefix = Config::get('database.connections.mysql.prefix');
$this->tableSuffix = date('Ym', time());
$this->tableName = "{$this->tablePrefix}system_log_{$this->tableSuffix}";
return $this;
}
/**
* 获取实例对象
* @return SystemLogService|object
* @return SystemLogService
*/
public static function instance()
public static function instance(): SystemLogService
{
if (is_null(self::$instance)) {
self::$instance = new static();
@@ -85,15 +84,16 @@ class SystemLogService
*/
public function detectTable(): bool
{
$_key = "system_log_{$this->tableName}_table";
// 手动删除日志表时候 记得清除缓存
$isset = Cache::get("systemLog{$this->tableName}Table");
$isset = Cache::get($_key);
if ($isset) return true;
$check = Db::query("show tables like '{$this->tableName}'");
if (empty($check)) {
$sql = $this->getCreateSql();
Db::execute($sql);
}
Cache::set("system_log_{$this->tableName}_table", !empty($check));
Cache::set($_key, !empty($check));
return true;
}

View File

@@ -30,6 +30,15 @@
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">登录方式</label>
<div class="layui-input-block">
{foreach notes.login_type as $key=>$val}
<input type="radio" name="login_type" lay-skin="primary" title="{$val}" value="{$key}" lay-filter="loginType-filter" {if $key==$row.login_type}checked=""{/if}>
{/foreach}
</div>
</div>
<div class="layui-form-item layui-form-text">
<label class="layui-form-label">备注信息</label>
<div class="layui-input-block">

View File

@@ -0,0 +1,45 @@
<div class="layuimini-container">
<form id="app-form" class="layui-form layuimini-form" autocomplete="off">
{if $old_secret}
<div class="layui-card">
<div class="layui-card-header">提示</div>
<div class="layui-card-body">
当前账号已经绑定过了 谷歌验证码 ,如果重新保存将替换
</div>
</div>
{/if}
<div class="layui-form-item">
<label class="layui-form-label required">验证秘钥</label>
<div class="layui-input-block">
<input type="text" name="ga_secret" class="layui-input" value="{$secret}" readonly disabled>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label required">二维码</label>
<div class="layui-input-block">
<img src="{$dataUri}" alt="二维码" style="width: 200px;height: 200px">
<div class="layui-text layui-font-cyan layui-font-12">
使用&nbsp;
<a href="https://2fas.com" target="_blank"><span class="layui-text layui-font-blue">2FAS</span></a>
&nbsp;或者&nbsp;
<a href="https://cn.bing.com/search?q=Google+Authenticator" target="_blank"><span class="layui-text layui-font-blue">Google Authenticator</span></a>
&nbsp;APP 扫描二维码 输入验证码 进行绑定
</div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label required">谷歌验证码</label>
<div class="layui-input-block">
<input type="text" name="ga_code" class="layui-input" maxlength="6" lay-verify="required" placeholder="扫描二维码,输入验证码" value="">
</div>
</div>
<div class=" hr-line">
</div>
<div class="layui-form-item text-center">
<button type="submit" class="layui-btn layui-btn-normal layui-btn-sm" lay-submit>确认</button>
<button type="reset" class="layui-btn layui-btn-primary layui-btn-sm">重置</button>
</div>
</form>
</div>

View File

@@ -69,16 +69,27 @@
<div class="layui-card-body">
<div class="welcome-module">
<div class="layui-row layui-col-space10">
<div class="swiper mySwiper">
<div class="swiper-wrapper">
{foreach $quicks as $value}
{foreach $quicks as $vo}
<div class="layui-col-xs3 layuimini-qiuck-module">
<a layuimini-content-href="{:url($vo['href'])}" data-title="{$vo['title']}">
<i class="{$vo['icon']|raw}"></i>
<cite>{$vo['title']}</cite>
</a>
<div class="swiper-slide">
{foreach $value as $vo}
<div class="layui-col-xs3 layuimini-qiuck-module">
<a layuimini-content-href="{:url($vo['href'])}" data-title="{$vo['title']}">
<i class="{$vo['icon']|raw}"></i>
<cite>{$vo['title']}</cite>
</a>
</div>
{/foreach}
</div>
{/foreach}
</div>
</div>
{/foreach}
<div class="swiper-pagination"></div>
</div>
</div>
</div>

View File

@@ -21,10 +21,12 @@
IS_SUPER_ADMIN: "{$isSuperAdmin|default='false'}",
VERSION: "{$version|default='1.0.0'}",
CSRF_TOKEN: "{:token()}",
ADMIN_UPLOAD_URL: "{$adminUploadUrl|DEFAULT=''}",
EDITOR_TYPE: "{$adminEditor|default='ueditor'}",
ADMIN_UPLOAD_URL: "{$adminUploadUrl|default=''}",
IFRAME_OPEN_TOP: "{$iframeOpenTop|default=0}",
EDITOR_TYPE: "{$adminEditor|default='wangEditor'}",
};
</script>
<script src="/static/plugs/xmSelect/xm-select.js" charset="utf-8"></script>
<script src="/static/plugs/layui-v2.x/layui.js" charset="utf-8"></script>
<script src="/static/plugs/require-2.3.6/require.js" charset="utf-8"></script>
<script src="/static/config-admin.js?v={$version}" charset="utf-8"></script>

View File

@@ -22,6 +22,11 @@
<span class="bind-password icon icon-4"></span>
</div>
<div class="item layui-hide" id="gaCode">
<span class="icon icon-3"></span>
<input type="text" name="ga_code" placeholder="谷歌验证码" maxlength="6">
</div>
{if $captcha == 1}
<div id="validatePanel" class="item" style="width: 137px;">
<input type="text" name="captcha" placeholder="请输入验证码" maxlength="4">

View File

@@ -2,7 +2,7 @@
<form id="app-form" class="layui-form layuimini-form layui-form-pane">
<div class="layui-row">
<div class="layui-col-xl5 layui-col-lg5 layui-col-md5 layui-col-sm5 layui-col-xs5">
<div class="layui-col-xl5 layui-col-lg5 layui-col-md12 layui-col-sm12 layui-col-xs12">
<!-- 可以使用该方式 推荐写法-->
<div class="layui-form-item">
<label class="layui-form-label">商品分类</label>
@@ -89,7 +89,7 @@
</div>
</div>
</div>
<div class="layui-col-xl7 layui-col-lg7 layui-col-md7 layui-col-sm7 layui-col-xs7">
<div class="layui-col-xl7 layui-col-lg7 layui-col-md12 layui-col-sm12 layui-col-xs12">
<div class="layui-form-item layui-form-text">
<label class="layui-form-label">商品描述</label>
<div class="layui-input-block">

View File

@@ -2,7 +2,7 @@
<form id="app-form" class="layui-form layuimini-form layui-form-pane">
<div class="layui-row">
<div class="layui-col-xl5 layui-col-lg5 layui-col-md5 layui-col-sm5 layui-col-xs5">
<div class="layui-col-xl5 layui-col-lg5 layui-col-md12 layui-col-sm12 layui-col-xs12">
<!-- 可以使用该方式 推荐写法-->
<div class="layui-form-item">
<label class="layui-form-label">商品分类</label>
@@ -89,7 +89,7 @@
</div>
</div>
</div>
<div class="layui-col-xl7 layui-col-lg7 layui-col-md7 layui-col-sm7 layui-col-xs7">
<div class="layui-col-xl7 layui-col-lg7 layui-col-md12 layui-col-sm12 layui-col-xs12">
<div class="layui-form-item layui-form-text">
<label class="layui-form-label">商品描述</label>
<div class="layui-input-block">

View File

@@ -1,4 +1,11 @@
<link rel="stylesheet" href="/static/plugs/zTree/fontawesome.css">
<link rel="stylesheet" href="/static/plugs/zTree/zTreeStyle.css?v={$version}">
<script src='/static/plugs/jquery-3.4.1/jquery-3.4.1.min.js'></script>
<script src='/static/plugs/zTree/jquery.ztree.core.js'></script>
<script src='/static/plugs/zTree/jquery.ztree.excheck.js'></script>
<div class="layuimini-container">
<form id="app-form" class="layui-form layuimini-form">
<div class="layui-form-item">
@@ -10,8 +17,8 @@
<div class="layui-form-item">
<label class="layui-form-label required">分配节点</label>
<div class="layui-input-block">
<div id="node_ids" class="demo-tree-more"></div>
<div class="layui-input-block" id="zTree">
<ul id="tree" class="ztree"></ul>
</div>
</div>
@@ -24,4 +31,4 @@
</div>
</form>
</div>
</div>

View File

@@ -54,6 +54,15 @@
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">新标签页窗口</label>
<div class="layui-input-block">
<input type="radio" name="iframe_open_top" value="0" title="不允许" {if 1!=sysConfig('site','iframe_open_top')}checked{/if}>
<input type="radio" name="iframe_open_top" value="1" title="允许" {if 1==sysConfig('site','iframe_open_top')}checked{/if}>
<br>
<tip>是否允许弹框在新标签页打开。</tip>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">默认编辑器</label>

View File

@@ -190,6 +190,9 @@ class AdminController extends BaseController
case '%*':
$where[] = [$key, 'LIKE', "%{$val}"];
break;
case 'in':
$where[] = [$key, 'IN', $val];
break;
case 'range':
[$beginTime, $endTime] = explode(' - ', $val);
$where[] = [$key, '>=', strtotime($beginTime)];
@@ -240,6 +243,7 @@ class AdminController extends BaseController
'version' => env('APP_DEBUG') ? time() : ConfigService::getVersion(),
'adminUploadUrl' => url('ajax/upload', [], false),
'adminEditor' => sysConfig('site', 'editor_type') ?: 'wangEditor',
'iframeOpenTop' => sysConfig('site', 'iframe_open_top') ?: 0,
];
View::assign($data);
}

View File

@@ -14,6 +14,6 @@ class Index extends BaseController
public function index(): Redirect
{
// 这是项目首页 系统默认跳转后台页面
return redirect('/' . Env::get('EASYADMIN.ADMIN', false));
return redirect('/' . Env::get('EASYADMIN.ADMIN', 'admin'));
}
}

View File

@@ -27,6 +27,9 @@ class Install extends BaseController
}elseif (!extension_loaded("PDO")) {
$errorInfo = '当前未开启PDO无法进行安装';
}
if (!is_file(root_path() . '.env')) {
$errorInfo = '.env 文件不存在,请先配置 .env 文件';
}
if (!$request->isAjax()) {
$currentHost = '://';
$result = compact('errorInfo', 'currentHost', 'isInstall');

View File

@@ -37,7 +37,8 @@
"qiniu/php-sdk": "v7.11.0",
"ext-mysqli": "*",
"ext-pdo": "*",
"wolf-leo/phplogviewer": "^0.05.0"
"wolf-leo/phplogviewer": "^0.11.3",
"wolfcode/authenticator": "^0.0.3"
},
"require-dev": {
"symfony/var-dumper": ">=4.2",

View File

@@ -97,6 +97,8 @@ CREATE TABLE `ea_system_admin`
`create_time` int(11) DEFAULT NULL COMMENT '创建时间',
`update_time` int(11) DEFAULT NULL COMMENT '更新时间',
`delete_time` int(11) DEFAULT NULL COMMENT '删除时间',
`login_type` tinyint unsigned NOT NULL DEFAULT '1' COMMENT '登录方式',
`ga_secret` varchar(32) NOT NULL DEFAULT '' COMMENT '谷歌验证码秘钥',
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`) USING BTREE,
KEY `phone` (`phone`)
@@ -106,7 +108,7 @@ CREATE TABLE `ea_system_admin`
-- Records of ea_system_admin
-- ----------------------------
INSERT INTO `ea_system_admin`
VALUES ('1', null, '/static/admin/images/head.jpg', 'admin', 'a33b679d5581a8692988ec9f92ad2d6a2259eaa7', 'admin', 'admin', '0', '0', '1', '1589454169', '1589476815', null);
VALUES ('1', null, '/static/admin/images/head.jpg', 'admin', 'a33b679d5581a8692988ec9f92ad2d6a2259eaa7', 'admin', 'admin', '0', '0', '1', '1589454169', '1589476815', null,1,'');
-- ----------------------------
-- Table structure for ea_system_auth

View File

@@ -134,6 +134,12 @@ html.dark, body {
color: #a29c9c;
}
.layui-form-item xm-select {
min-height: 30px !important;
line-height: 30px !important;
margin: 0 !important;
}
/** 按钮背景色 */
.layuimini-container .layuimini-btn-primary {
color: #fff;
@@ -253,36 +259,10 @@ table样式
.layuimini-container .layui-table-tool {
background-color: #ffffff;
border-bottom: none !important;
padding: 10px;
padding-bottom: 15px !important;
}
.dark .layuimini-container .layui-table-tool {
background-color: var(--lay-color-bg-1);
border-bottom: none !important;
padding-bottom: 15px !important;
}
.layuimini-container .layui-table-view {
border: none !important;
}
.layuimini-container .layui-table-box {
border-width: 1px;
border-style: solid;
border-color: #e6e6e6;
}
.dark .layuimini-container .layui-table-box {
border-width: 1px;
border-style: solid;
border-color: #363636;
}
.layuimini-container .layui-table-page, .layui-table-total {
border-width: 0px 0 0;
}
.layuimini-container .layui-table-box .layui-table-header th {
font-weight: bold !important;
color: #565656 !important;
@@ -329,10 +309,6 @@ table样式
padding: 0;
}
/**
按钮
*/
.layuimini-container .layui-btn-success {
color: #fff;
background-color: #4bb368;
@@ -360,14 +336,6 @@ table样式
font-size: 16px;
}
.layuimini-container .layui-table-tool-self {
right: 0px;
}
.layuimini-container .layui-table-tool {
padding: 10px 0px;
}
/**
弹出层样式
*/
@@ -513,6 +481,18 @@ table样式
.form-search .layui-input-inline input, .form-search .layui-input-inline select {
width: 100% !important;
}
.tableSelect {
margin: 5px !important;
min-width: auto !important;
left: 1px !important;
right: 1px !important;
}
.tableSelect img {
object-fit: cover;
height: 100%;
}
}
/**

View File

@@ -32,7 +32,7 @@
.layuimini-qiuck-module a i {
display: inline-block;
width: 100%;
width: 80%;
height: 60px;
line-height: 60px;
text-align: center;

View File

@@ -1,4 +1,4 @@
define(["jquery", "easy-admin", "echarts", "echarts-theme", "miniAdmin", "miniTab"], function ($, ea, echarts, undefined, miniAdmin, miniTab) {
define(["jquery", "easy-admin", "echarts", "echarts-theme", "miniAdmin", "miniTab", "swiper"], function ($, ea, echarts, undefined, miniAdmin, miniTab) {
return {
index: function () {
@@ -50,6 +50,14 @@ define(["jquery", "easy-admin", "echarts", "echarts-theme", "miniAdmin", "miniTa
},
welcome: function () {
miniTab.listen();
new Swiper('.mySwiper', {
pagination: {
el: '.swiper-pagination',
clickable: true,
},
})
/**
* 查看公告信息
**/
@@ -156,10 +164,22 @@ define(["jquery", "easy-admin", "echarts", "echarts-theme", "miniAdmin", "miniTa
})
},
editAdmin: function () {
let form = layui.form
form.on('radio(loginType-filter)', function (data) {
let elem = data.elem
let value = elem.value
if (value === '2') {
let width = screen.width < 768 ? '85%' : '60%'
ea.open('绑定谷歌验证码', ea.url('index/set2fa'), width, '75%')
}
});
ea.listen();
},
editPassword: function () {
ea.listen();
}
},
set2fa: function () {
ea.listen();
},
};
});

View File

@@ -1,4 +1,4 @@
define(["easy-admin"], function (ea) {
define(["jquery", "easy-admin"], function ($, ea) {
return {
index: function () {
@@ -39,6 +39,12 @@ define(["easy-admin"], function (ea) {
window.location = ea.url('index');
})
}, function (res) {
let data = res.data
if (data.is_ga_code) {
let elem = $('#gaCode')
elem.removeClass('layui-hide');
elem.find('input').focus()
}
ea.msg.error(res.msg, function () {
$('#refreshCaptcha').trigger("click");
});

View File

@@ -42,6 +42,14 @@ define(["jquery", "easy-admin"], function ($, ea) {
{field: 'virtual_sales', width: 100, title: '虚拟销量'},
{field: 'sales', width: 80, title: '销量'},
{field: 'status', title: '状态', width: 85, selectList: {0: '禁用', 1: '启用'}, templet: ea.table.switch},
// 演示多选,实际数据库并无 status2 字段,搜索后会报错
{
field: 'status2', title: '演示多选', width: 105, search: 'xmSelect', selectList: {1: '模拟选项1', 2: '模拟选项2', 3: '模拟选项3', 4: '模拟选项4', 5: '模拟选项5'},
searchOp: 'in', templet: function (res) {
// 根据自己实际项目进行输出
return res?.status2 || '模拟数据'
}
},
{field: 'create_time', minWidth: 80, title: '创建时间', search: 'range'},
{
width: 250,

View File

@@ -1,89 +1,107 @@
define(["jquery", "easy-admin"], function ($, ea) {
var init = {
table_elem: '#currentTable',
table_render_id: 'currentTableRenderId',
index_url: 'system.auth/index',
add_url: 'system.auth/add',
edit_url: 'system.auth/edit',
delete_url: 'system.auth/delete',
export_url: 'system.auth/export',
modify_url: 'system.auth/modify',
authorize_url: 'system.auth/authorize',
};
var init = {
table_elem: '#currentTable',
table_render_id: 'currentTableRenderId',
index_url: 'system.auth/index',
add_url: 'system.auth/add',
edit_url: 'system.auth/edit',
delete_url: 'system.auth/delete',
export_url: 'system.auth/export',
modify_url: 'system.auth/modify',
authorize_url: 'system.auth/authorize',
};
return {
return {
index: function () {
ea.table.render({
init: init,
cols: [[
{type: "checkbox"},
{field: 'id', width: 80, title: 'ID', searchOp: '='},
{field: 'sort', width: 80, title: '排序', edit: 'text'},
{field: 'title', minWidth: 80, title: '权限名称'},
{field: 'remark', minWidth: 80, title: '备注信息'},
{field: 'status', title: '状态', width: 85, search: 'select', selectList: {0: '禁用', 1: '启用'}, templet: ea.table.switch},
{field: 'create_time', minWidth: 80, title: '创建时间', search: 'range'},
{
width: 250,
title: '操作',
templet: ea.table.tool,
operat: [
'edit',
[{
text: '授权',
url: init.authorize_url,
method: 'open',
auth: 'authorize',
class: 'layui-btn layui-btn-normal layui-btn-xs',
}],
'delete'
]
}
]],
});
ea.listen();
},
add: function () {
ea.listen();
},
edit: function () {
ea.listen();
},
authorize: function () {
var tree = layui.tree;
ea.request.get(
{
url: window.location.href,
}, function (res) {
res.data = res.data || [];
tree.render({
elem: '#node_ids',
data: res.data,
showCheckbox: true,
id: 'nodeDataId',
});
}
);
ea.listen(function (data) {
var checkedData = tree.getChecked('nodeDataId');
var ids = [];
$.each(checkedData, function (i, v) {
ids.push(v.id);
if (v.children !== undefined && v.children.length > 0) {
$.each(v.children, function (ii, vv) {
ids.push(vv.id);
});
}
index: function () {
ea.table.render({
init: init,
cols: [[
{type: "checkbox"},
{field: 'id', width: 80, title: 'ID', searchOp: '='},
{field: 'sort', width: 80, title: '排序', edit: 'text'},
{field: 'title', minWidth: 80, title: '权限名称'},
{field: 'remark', minWidth: 80, title: '备注信息'},
{field: 'status', title: '状态', width: 85, search: 'select', selectList: {0: '禁用', 1: '启用'}, templet: ea.table.switch},
{field: 'create_time', minWidth: 80, title: '创建时间', search: 'range'},
{
width: 250,
title: '操作',
templet: ea.table.tool,
operat: [
'edit',
[{
text: '授权',
url: init.authorize_url,
method: 'open',
auth: 'authorize',
class: 'layui-btn layui-btn-normal layui-btn-xs',
}],
'delete'
]
}
]],
});
data.node = JSON.stringify(ids);
return data;
});
ea.listen();
},
add: function () {
ea.listen();
},
edit: function () {
ea.listen();
},
authorize: function () {
let setting = {
check: {
enable: true,
chkStyle: "checkbox",
},
view: {
showIcon: true,
showLine: true,
selectedMulti: false,
dblClickExpand: false
}, callback: {
onClick: function (e, treeId, treeNode, clickFlag) {
treeObj.checkNode(treeNode, !treeNode.checked, true);
}
}
};
let treeObj
let treeData = []
ea.request.get({url: window.location.href}, function (res) {
res.data = res.data || [];
$.each(res.data, function (index, value) {
treeData[index] = []
treeData[index].id = value.id
treeData[index].name = value.title
treeData[index].pId = 0
treeData[index].open = true
let children = value.children
treeData[index]['children'] = []
$.each(children, function (idx, val) {
treeData[index]['children'].push({id: val.id, name: val.title, checked: val.checked, pId: value.id})
})
})
$.fn.zTree.init($("#tree"), setting, treeData);
treeObj = $.fn.zTree.getZTreeObj("tree");
}
);
ea.listen(function (data) {
let checkedData = treeObj.getCheckedNodes();
let ids = []
for (var i = 0; i < checkedData.length; i++) {
ids.push(checkedData[i].id)
}
data.node = JSON.stringify(ids);
return data;
});
}
}
};
});
}
)

View File

@@ -21,6 +21,7 @@ require.config({
"iconPickerFa": ["plugs/lay-module/iconPicker/iconPickerFa"],
"autocomplete": ["plugs/lay-module/autocomplete/autocomplete"],
"vue": ["plugs/vue-2.6.10/vue.min"],
"swiper": ["plugs/swiper/swiper-bundle.min"],
}
});

View File

@@ -19,9 +19,13 @@ define(["jquery", "tableSelect"], function ($, tableSelect) {
table_render_id: 'currentTableRenderId',
upload_url: 'ajax/upload',
upload_exts: 'doc|gif|ico|icon|jpg|mp3|mp4|p12|pem|png|rar',
csrf_token: window.CONFIG.CSRF_TOKEN
csrf_token: window.CONFIG.CSRF_TOKEN,
wait_submit: false,
xmSelectList: {},
xmSelectModel: {},
};
var admin = {
config: {
shade: [0.02, '#000'],
@@ -112,6 +116,7 @@ define(["jquery", "tableSelect"], function ($, tableSelect) {
// @todo 刷新csrf-token
let token = data.responseJSON ? data.responseJSON.__token__ : ''
init.csrf_token = token
init.wait_submit = false
}
});
}
@@ -367,6 +372,15 @@ define(["jquery", "tableSelect"], function ($, tableSelect) {
'</div>\n' +
'</div>';
break;
case 'xmSelect':
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>\n' +
'</div>';
init.xmSelectList[d.fieldAlias] = d.selectList
break;
case 'range':
d.searchOp = 'range';
formHtml += '\t<div class="layui-form-item layui-inline">\n' +
@@ -820,6 +834,17 @@ define(["jquery", "tableSelect"], function ($, tableSelect) {
return value;
},
listenTableSearch: function (tableId) {
if (Object.keys(init.xmSelectList).length > 0) {
$.each(init.xmSelectList, function (index, value) {
const keysArray = Object.keys(value).map((key) => {
return {name: value[key], value: key}
})
init.xmSelectModel[index] = xmSelect.render({
el: '.xmSelect-' + index, language: 'zn', data: keysArray, name: index,
filterable: true, paging: true, pageSize: 10, theme: {color: '#16b777'}, toolbar: {show: true},
})
})
}
form.on('submit(' + tableId + '_filter)', function (data) {
var dataField = data.field;
var formatFilter = {},
@@ -974,6 +999,22 @@ define(["jquery", "tableSelect"], function ($, tableSelect) {
before: function () {
},
success: function (layero, index) {
if (window.CONFIG.IFRAME_OPEN_TOP == '1') {
let iframeUrl = ``
try {
let iframeId = $('iframe:eq(0)').attr('id')
let iframe = document.getElementById(iframeId)
iframeUrl = iframe.contentWindow.location.href
} catch (e) {
iframeUrl = location.href
}
let _winTopBtn = `
<span class="_winTopBtn layui-btn layui-btn-primary layui-btn-xs"
style="position: absolute;top: 14px;right: 120px;color: #fff;border-color: #fff;" onclick="window.open('${iframeUrl}')">
新标签页打开
</span>`
$('.layui-layer-iframe').append(_winTopBtn)
}
},
end: function () {
index = null
@@ -1144,6 +1185,11 @@ define(["jquery", "tableSelect"], function ($, tableSelect) {
if (tableId === undefined || tableId === '' || tableId == null) {
tableId = init.table_render_id;
}
if (Object.keys(init.xmSelectModel).length > 0) {
$.each(init.xmSelectModel, function (index, value) {
init.xmSelectModel[index].setValue([])
})
}
table.reload(tableId, {
page: {
curr: 1
@@ -1365,6 +1411,10 @@ define(["jquery", "tableSelect"], function ($, tableSelect) {
url = admin.url(url);
}
form.on('submit(' + filter + ')', function (data) {
if (init.wait_submit) {
layer.msg('你点击太快了', {icon: 16, shade: 0.3, shadeClose: false, time: 1000})
return false
}
var dataField = data.field;
var editorList = document.querySelectorAll(".editor");
// 富文本数据处理
@@ -1392,6 +1442,7 @@ define(["jquery", "tableSelect"], function ($, tableSelect) {
if (typeof preposeCallback === 'function') {
dataField = preposeCallback(dataField);
}
init.wait_submit = true
admin.api.form(url, dataField, ok, no, ex, refresh);
return false;
});

View File

@@ -700,14 +700,6 @@
margin-top: -6px !important;
}
.layuimini-menu-left .layui-nav .layui-nav-mored,.layuimini-menu-left .layui-nav-itemed>a .layui-nav-more{
margin-top: -9px!important;
}
.layuimini-menu-left-zoom.layui-nav .layui-nav-mored,.layuimini-menu-left-zoom.layui-nav-itemed>a .layui-nav-more{
margin-top: -9px!important;
}
.layuimini-menu-left .layui-nav-more:before,.layuimini-menu-left-zoom .layui-nav-more:before {
content: "\e61a";
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -10,14 +10,8 @@
**************************提示********************************/
(function () {
/**
* 编辑器资源文件根路径。它所表示的含义是以编辑器实例化页面为当前路径指向编辑器资源文件即dialog等文件夹的路径。
* 鉴于很多同学在使用编辑器的时候出现的种种路径问题,此处强烈建议大家使用"相对于网站根目录的相对路径"进行配置。
* "相对于网站根目录的相对路径"也就是以斜杠开头的形如"/myProject/ueditor/"这样的路径。
* 如果站点中有多个不在同一层级的页面需要实例化编辑器且引用了同一UEditor的时候此处的URL可能不适用于每个页面的编辑器。
* 因此UEditor提供了针对不同页面的编辑器可单独配置的根路径具体来说在需要实例化编辑器的页面最顶部写上如下代码即可。当然需要令此处的URL等于对应的配置。
* window.UEDITOR_HOME_URL = "/xxxx/xxxx/";
*/
// 资源文件根路径,如果你的页面不是放在根目录下,请注意修改这个路径
// 通常情况下这个可以配置成静态资源CDN的地址
window.UEDITOR_HOME_URL = "/static/plugs/ueditor/";
var URL, CORS_URL;
if (window.UEDITOR_HOME_URL) {
@@ -29,6 +23,8 @@
} else {
URL = getUEBasePath();
}
// 需要能跨域的静态资源请求,主要用户弹窗页面等静态资源
// 通常情况下这个可以配置成静态资源CDN的地址
if (window.UEDITOR_CORS_URL) {
CORS_URL = window.UEDITOR_CORS_URL;
} else if (window.__msRoot) {
@@ -38,6 +34,7 @@
} else {
CORS_URL = getUEBasePath();
}
/**
* 配置项主体。注意此处所有涉及到路径的配置别遗漏URL变量。
*/
@@ -53,10 +50,19 @@
// 服务器统一请求接口路径
serverUrl: "/" + (window.CONFIG.ADMIN || 'admin') + "/ajax/uploadUEditor",
// 从服务器获取配置
loadConfigFromServer: true,
// 服务器统一请求头信息,会在所有请求中带上该信息
serverHeaders: {
// 'Authorization': 'Bearer xxx'
},
// 服务器返回参数统一转换方法,可以在这里统一处理返回参数
serverResponsePrepare: function (res) {
// console.log('serverResponsePrepare', res);
return res;
},
//工具栏上的所有的功能按钮和下拉框可以在new编辑器的实例时选择自己需要的重新定义
toolbars: [
@@ -114,8 +120,8 @@
"|",
"imagenone", // 图片默认
"imageleft", // 图片左浮动
"imageright", // 图片右浮动
"imagecenter", // 图片居中
"imageright", // 图片右浮动
"|",
"simpleupload", // 单图上传
"insertimage", // 多图上传
@@ -154,12 +160,15 @@
"print", // 打印
"preview", // 预览
"searchreplace", // 查询替换
"|",
"contentimport",
"help", // 帮助
]
]
// 自定义工具栏按钮点击,返回 true 表示已经处理点击,会阻止默认事件
, toolbarCallback: function (cmd, editor) {
// console.log('toolbarCallback',cmd, editor);
// switch(cmd){
// case 'insertimage':
// editor.execCommand('insertHtml', '<p><img src="xxxxx" /></p>');
@@ -176,6 +185,33 @@
// }
}
// 自定义上传功能
, uploadServiceEnable: false
// 自定义上传函数,需要在这个函数中实现自定义上传逻辑
// type 上传类型image 图片video 视频audio 音频attachment 附件
// file 文件对象
// callback 回调函数,需要在上传完成后调用 callback.success、callback.error、callback.progress
// option 上传配置,其他一些未来扩展配置
, uploadServiceUpload: function(type, file, callback, option ) {
console.log('uploadServiceUpload', type, file, callback, option);
// var i = 0;
// var call = function(){
// i++;
// if(i > 3){
// callback.success({
// "state": "SUCCESS",
// "url": "https://ms-assets.modstart.com/demo/modstart.jpg",
// })
// return;
// }
// setTimeout(function(){
// callback.progress(0.3 * i);
// call();
// },500);
// }
// call();
}
// 插入图片自定义配置
, imageConfig: {
// 禁止本地上传
@@ -316,7 +352,8 @@
// 是否开启初始化时即全屏,默认关闭
, fullscreen: false
//,imagePopup:true //图片操作的浮层开关,默认打开
// 图片操作的浮层开关,默认打开
//,imagePopup:true
// 自动同步编辑器要提交的数据
//,autoSyncData:true
@@ -359,17 +396,8 @@
// 提交到后台的数据是否包含整个html字符串
, allHtmlEnabled: false
//insertorderedlist
//有序列表的下拉配置,值留空时支持多语言自动识别,若配置值,则以此值为准
//,'insertorderedlist':{
// //自定的样式
// 'num':'1,2,3...',
// 'num1':'1),2),3)...',
// 'num2':'(1),(2),(3)...',
// 'cn':'一,二,三....',
// 'cn1':'一),二),三)....',
// 'cn2':'(一),(二),(三)....',
// //系统自带
// 'decimal' : '' , //'1,2,3...'
// 'lower-alpha' : '' , // 'a,b,c...'
// 'lower-roman' : '' , //'i,ii,iii...'
@@ -380,8 +408,6 @@
//insertunorderedlist
//无序列表的下拉配置,值留空时支持多语言自动识别,若配置值,则以此值为准
//,insertunorderedlist : { //自定的样式
// 'dash' :'— 破折号', //-破折号
// 'dot':' 。 小圆圈', //系统自带
// 'circle' : '', // '○ 小圆圈'
// 'disc' : '', // '● 小圆点'
// 'square' : '' //'■ 小方块'
@@ -465,6 +491,12 @@
"forecolor", // 字体颜色
// "shadowcolor", // 字体阴影
"backcolor", // 背景色
"imagenone",
"imageleft",
"imagecenter",
"imageright",
"insertimage",
"formula",
// "justifyleft", // 居左对齐
// "justifycenter", // 居中对齐
// "justifyright", // 居右对齐
@@ -513,19 +545,19 @@
// 是否自动长高,默认true
, autoHeightEnabled: true
//scaleEnabled
//是否可以拉伸长高,默认true(当开启时,自动长高失效)
// 是否可以拉伸长高默认true(当开启时,自动长高失效)
//,scaleEnabled:false
//,minFrameWidth:800 //编辑器拖动时最小宽度,默认800
//,minFrameHeight:220 //编辑器拖动时最小高度,默认220
//autoFloatEnabled
//是否保持toolbar的位置不动,默认true
//,autoFloatEnabled:true
//浮动时工具栏距离浏览器顶部的高度,用于某些具有固定头部的页面
//,topOffset:30
//编辑器底部距离工具栏高度(如果参数大于等于编辑器高度,则设置无效)
//,toolbarTopOffset:400
// 编辑器最小高度,默认220
, minFrameHeight: 220
// 是否保持toolbar的位置不动,默认true
, autoFloatEnabled: true
// 浮动时工具栏距离浏览器顶部的高度,用于某些具有固定头部的页面
, topOffset: 0
// 编辑器底部距离工具栏高度(如果参数大于等于编辑器高度,则设置无效)
, toolbarTopOffset: 0
//设置远程图片是否抓取到本地保存
, catchRemoteImageEnable: true //设置是否抓取远程图片
@@ -595,7 +627,15 @@
// 允许进入编辑器的 div 标签自动变成 p 标签
, allowDivTransToP: true
// 默认产出的数据中的color自动从rgb格式变成16进制格式
, rgb2Hex: true
, rgb2Hex: true,
tipError: function (msg, param) {
if (window && window.MS && window.MS.dialog) {
window.MS.dialog.tipError(msg);
} else {
alert(msg);
}
}
};
function getUEBasePath(docUrl, confUrl) {
@@ -651,4 +691,4 @@
window.UE = {
getUEBasePath: getUEBasePath
};
})();
})();

File diff suppressed because one or more lines are too long

6110
public/static/plugs/zTree/fontawesome.css vendored Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 601 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 580 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 570 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 762 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 399 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 710 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 432 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 534 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 529 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 467 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 381 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,652 @@
/*
* JQuery zTree excheck
* v3.5.48
* http://treejs.cn/
*
* Copyright (c) 2010 Hunter.z
*
* Licensed same as jquery - MIT License
* http://www.opensource.org/licenses/mit-license.php
*
* Date: 2020-11-21
*/
(function ($) {
//default consts of excheck
var _consts = {
event: {
CHECK: "ztree_check"
},
id: {
CHECK: "_check"
},
checkbox: {
STYLE: "checkbox",
DEFAULT: "chk",
DISABLED: "disable",
FALSE: "false",
TRUE: "true",
FULL: "full",
PART: "part",
FOCUS: "focus"
},
radio: {
STYLE: "radio",
TYPE_ALL: "all",
TYPE_LEVEL: "level"
}
},
//default setting of excheck
_setting = {
check: {
enable: false,
autoCheckTrigger: false,
chkStyle: _consts.checkbox.STYLE,
nocheckInherit: false,
chkDisabledInherit: false,
radioType: _consts.radio.TYPE_LEVEL,
chkboxType: {
"Y": "ps",
"N": "ps"
}
},
data: {
key: {
checked: "checked"
}
},
callback: {
beforeCheck: null,
onCheck: null
}
},
//default root of excheck
_initRoot = function (setting) {
var r = data.getRoot(setting);
r.radioCheckedList = [];
},
//default cache of excheck
_initCache = function (treeId) {
},
//default bind event of excheck
_bindEvent = function (setting) {
var o = setting.treeObj,
c = consts.event;
o.bind(c.CHECK, function (event, srcEvent, treeId, node) {
event.srcEvent = srcEvent;
tools.apply(setting.callback.onCheck, [event, treeId, node]);
});
},
_unbindEvent = function (setting) {
var o = setting.treeObj,
c = consts.event;
o.unbind(c.CHECK);
},
//default event proxy of excheck
_eventProxy = function (e) {
var target = e.target,
setting = data.getSetting(e.data.treeId),
tId = "", node = null,
nodeEventType = "", treeEventType = "",
nodeEventCallback = null, treeEventCallback = null;
if (tools.eqs(e.type, "mouseover")) {
if (setting.check.enable && tools.eqs(target.tagName, "span") && target.getAttribute("treeNode" + consts.id.CHECK) !== null) {
tId = tools.getNodeMainDom(target).id;
nodeEventType = "mouseoverCheck";
}
} else if (tools.eqs(e.type, "mouseout")) {
if (setting.check.enable && tools.eqs(target.tagName, "span") && target.getAttribute("treeNode" + consts.id.CHECK) !== null) {
tId = tools.getNodeMainDom(target).id;
nodeEventType = "mouseoutCheck";
}
} else if (tools.eqs(e.type, "click")) {
if (setting.check.enable && tools.eqs(target.tagName, "span") && target.getAttribute("treeNode" + consts.id.CHECK) !== null) {
tId = tools.getNodeMainDom(target).id;
nodeEventType = "checkNode";
}
}
if (tId.length > 0) {
node = data.getNodeCache(setting, tId);
switch (nodeEventType) {
case "checkNode" :
nodeEventCallback = _handler.onCheckNode;
break;
case "mouseoverCheck" :
nodeEventCallback = _handler.onMouseoverCheck;
break;
case "mouseoutCheck" :
nodeEventCallback = _handler.onMouseoutCheck;
break;
}
}
var proxyResult = {
stop: nodeEventType === "checkNode",
node: node,
nodeEventType: nodeEventType,
nodeEventCallback: nodeEventCallback,
treeEventType: treeEventType,
treeEventCallback: treeEventCallback
};
return proxyResult
},
//default init node of excheck
_initNode = function (setting, level, n, parentNode, isFirstNode, isLastNode, openFlag) {
if (!n) return;
var checked = data.nodeChecked(setting, n);
n.checkedOld = checked;
if (typeof n.nocheck == "string") n.nocheck = tools.eqs(n.nocheck, "true");
n.nocheck = !!n.nocheck || (setting.check.nocheckInherit && parentNode && !!parentNode.nocheck);
if (typeof n.chkDisabled == "string") n.chkDisabled = tools.eqs(n.chkDisabled, "true");
n.chkDisabled = !!n.chkDisabled || (setting.check.chkDisabledInherit && parentNode && !!parentNode.chkDisabled);
if (typeof n.halfCheck == "string") n.halfCheck = tools.eqs(n.halfCheck, "true");
n.halfCheck = !!n.halfCheck;
n.check_Child_State = -1;
n.check_Focus = false;
n.getCheckStatus = function () {
return data.getCheckStatus(setting, n);
};
if (setting.check.chkStyle == consts.radio.STYLE && setting.check.radioType == consts.radio.TYPE_ALL && checked) {
var r = data.getRoot(setting);
r.radioCheckedList.push(n);
}
},
//add dom for check
_beforeA = function (setting, node, html) {
if (setting.check.enable) {
data.makeChkFlag(setting, node);
html.push("<span ID='", node.tId, consts.id.CHECK, "' class='", view.makeChkClass(setting, node), "' treeNode", consts.id.CHECK, (node.nocheck === true ? " style='display:none;'" : ""), "></span>");
}
},
//update zTreeObj, add method of check
_zTreeTools = function (setting, zTreeTools) {
zTreeTools.checkNode = function (node, checked, checkTypeFlag, callbackFlag) {
var nodeChecked = data.nodeChecked(setting, node);
if (node.chkDisabled === true) return;
if (checked !== true && checked !== false) {
checked = !nodeChecked;
}
callbackFlag = !!callbackFlag;
if (nodeChecked === checked && !checkTypeFlag) {
return;
} else if (callbackFlag && tools.apply(this.setting.callback.beforeCheck, [this.setting.treeId, node], true) == false) {
return;
}
if (tools.uCanDo(this.setting) && this.setting.check.enable && node.nocheck !== true) {
data.nodeChecked(setting, node, checked);
var checkObj = $$(node, consts.id.CHECK, this.setting);
if (checkTypeFlag || this.setting.check.chkStyle === consts.radio.STYLE) view.checkNodeRelation(this.setting, node);
view.setChkClass(this.setting, checkObj, node);
view.repairParentChkClassWithSelf(this.setting, node);
if (callbackFlag) {
this.setting.treeObj.trigger(consts.event.CHECK, [null, this.setting.treeId, node]);
}
}
}
zTreeTools.checkAllNodes = function (checked) {
view.repairAllChk(this.setting, !!checked);
}
zTreeTools.getCheckedNodes = function (checked) {
checked = (checked !== false);
var children = data.nodeChildren(setting, data.getRoot(this.setting));
return data.getTreeCheckedNodes(this.setting, children, checked);
}
zTreeTools.getChangeCheckedNodes = function () {
var children = data.nodeChildren(setting, data.getRoot(this.setting));
return data.getTreeChangeCheckedNodes(this.setting, children);
}
zTreeTools.setChkDisabled = function (node, disabled, inheritParent, inheritChildren) {
disabled = !!disabled;
inheritParent = !!inheritParent;
inheritChildren = !!inheritChildren;
view.repairSonChkDisabled(this.setting, node, disabled, inheritChildren);
view.repairParentChkDisabled(this.setting, node.getParentNode(), disabled, inheritParent);
}
var _updateNode = zTreeTools.updateNode;
zTreeTools.updateNode = function (node, checkTypeFlag) {
if (_updateNode) _updateNode.apply(zTreeTools, arguments);
if (!node || !this.setting.check.enable) return;
var nObj = $$(node, this.setting);
if (nObj.get(0) && tools.uCanDo(this.setting)) {
var checkObj = $$(node, consts.id.CHECK, this.setting);
if (checkTypeFlag == true || this.setting.check.chkStyle === consts.radio.STYLE) view.checkNodeRelation(this.setting, node);
view.setChkClass(this.setting, checkObj, node);
view.repairParentChkClassWithSelf(this.setting, node);
}
}
},
//method of operate data
_data = {
getRadioCheckedList: function (setting) {
var checkedList = data.getRoot(setting).radioCheckedList;
for (var i = 0, j = checkedList.length; i < j; i++) {
if (!data.getNodeCache(setting, checkedList[i].tId)) {
checkedList.splice(i, 1);
i--;
j--;
}
}
return checkedList;
},
getCheckStatus: function (setting, node) {
if (!setting.check.enable || node.nocheck || node.chkDisabled) return null;
var checked = data.nodeChecked(setting, node),
r = {
checked: checked,
half: node.halfCheck ? node.halfCheck : (setting.check.chkStyle == consts.radio.STYLE ? (node.check_Child_State === 2) : (checked ? (node.check_Child_State > -1 && node.check_Child_State < 2) : (node.check_Child_State > 0)))
};
return r;
},
getTreeCheckedNodes: function (setting, nodes, checked, results) {
if (!nodes) return [];
var onlyOne = (checked && setting.check.chkStyle == consts.radio.STYLE && setting.check.radioType == consts.radio.TYPE_ALL);
results = !results ? [] : results;
for (var i = 0, l = nodes.length; i < l; i++) {
var node = nodes[i];
var children = data.nodeChildren(setting, node);
var nodeChecked = data.nodeChecked(setting, node);
if (node.nocheck !== true && node.chkDisabled !== true && nodeChecked == checked) {
results.push(node);
if (onlyOne) {
break;
}
}
data.getTreeCheckedNodes(setting, children, checked, results);
if (onlyOne && results.length > 0) {
break;
}
}
return results;
},
getTreeChangeCheckedNodes: function (setting, nodes, results) {
if (!nodes) return [];
results = !results ? [] : results;
for (var i = 0, l = nodes.length; i < l; i++) {
var node = nodes[i];
var children = data.nodeChildren(setting, node);
var nodeChecked = data.nodeChecked(setting, node);
if (node.nocheck !== true && node.chkDisabled !== true && nodeChecked != node.checkedOld) {
results.push(node);
}
data.getTreeChangeCheckedNodes(setting, children, results);
}
return results;
},
makeChkFlag: function (setting, node) {
if (!node) return;
var chkFlag = -1;
var children = data.nodeChildren(setting, node);
if (children) {
for (var i = 0, l = children.length; i < l; i++) {
var cNode = children[i];
var nodeChecked = data.nodeChecked(setting, cNode);
var tmp = -1;
if (setting.check.chkStyle == consts.radio.STYLE) {
if (cNode.nocheck === true || cNode.chkDisabled === true) {
tmp = cNode.check_Child_State;
} else if (cNode.halfCheck === true) {
tmp = 2;
} else if (nodeChecked) {
tmp = 2;
} else {
tmp = cNode.check_Child_State > 0 ? 2 : 0;
}
if (tmp == 2) {
chkFlag = 2;
break;
} else if (tmp == 0) {
chkFlag = 0;
}
} else if (setting.check.chkStyle == consts.checkbox.STYLE) {
if (cNode.nocheck === true || cNode.chkDisabled === true) {
tmp = cNode.check_Child_State;
} else if (cNode.halfCheck === true) {
tmp = 1;
} else if (nodeChecked) {
tmp = (cNode.check_Child_State === -1 || cNode.check_Child_State === 2) ? 2 : 1;
} else {
tmp = (cNode.check_Child_State > 0) ? 1 : 0;
}
if (tmp === 1) {
chkFlag = 1;
break;
} else if (tmp === 2 && chkFlag > -1 && i > 0 && tmp !== chkFlag) {
chkFlag = 1;
break;
} else if (chkFlag === 2 && tmp > -1 && tmp < 2) {
chkFlag = 1;
break;
} else if (tmp > -1) {
chkFlag = tmp;
}
}
}
}
node.check_Child_State = chkFlag;
}
},
//method of event proxy
_event = {},
//method of event handler
_handler = {
onCheckNode: function (event, node) {
if (node.chkDisabled === true) return false;
var setting = data.getSetting(event.data.treeId);
if (tools.apply(setting.callback.beforeCheck, [setting.treeId, node], true) == false) return true;
var nodeChecked = data.nodeChecked(setting, node);
data.nodeChecked(setting, node, !nodeChecked);
view.checkNodeRelation(setting, node);
var checkObj = $$(node, consts.id.CHECK, setting);
view.setChkClass(setting, checkObj, node);
view.repairParentChkClassWithSelf(setting, node);
setting.treeObj.trigger(consts.event.CHECK, [event, setting.treeId, node]);
return true;
},
onMouseoverCheck: function (event, node) {
if (node.chkDisabled === true) return false;
var setting = data.getSetting(event.data.treeId),
checkObj = $$(node, consts.id.CHECK, setting);
node.check_Focus = true;
view.setChkClass(setting, checkObj, node);
return true;
},
onMouseoutCheck: function (event, node) {
if (node.chkDisabled === true) return false;
var setting = data.getSetting(event.data.treeId),
checkObj = $$(node, consts.id.CHECK, setting);
node.check_Focus = false;
view.setChkClass(setting, checkObj, node);
return true;
}
},
//method of tools for zTree
_tools = {},
//method of operate ztree dom
_view = {
checkNodeRelation: function (setting, node) {
var pNode, i, l,
r = consts.radio;
var nodeChecked = data.nodeChecked(setting, node);
if (setting.check.chkStyle == r.STYLE) {
var checkedList = data.getRadioCheckedList(setting);
if (nodeChecked) {
if (setting.check.radioType == r.TYPE_ALL) {
for (i = checkedList.length - 1; i >= 0; i--) {
pNode = checkedList[i];
var pNodeChecked = data.nodeChecked(setting, pNode);
if (pNodeChecked && pNode != node) {
data.nodeChecked(setting, pNode, false);
checkedList.splice(i, 1);
view.setChkClass(setting, $$(pNode, consts.id.CHECK, setting), pNode);
if (pNode.parentTId != node.parentTId) {
view.repairParentChkClassWithSelf(setting, pNode);
}
}
}
checkedList.push(node);
} else {
var parentNode = (node.parentTId) ? node.getParentNode() : data.getRoot(setting);
var children = data.nodeChildren(setting, parentNode);
for (i = 0, l = children.length; i < l; i++) {
pNode = children[i];
var pNodeChecked = data.nodeChecked(setting, pNode);
if (pNodeChecked && pNode != node) {
data.nodeChecked(setting, pNode, false);
view.setChkClass(setting, $$(pNode, consts.id.CHECK, setting), pNode);
}
}
}
} else if (setting.check.radioType == r.TYPE_ALL) {
for (i = 0, l = checkedList.length; i < l; i++) {
if (node == checkedList[i]) {
checkedList.splice(i, 1);
break;
}
}
}
} else {
var children = data.nodeChildren(setting, node);
if (nodeChecked && (!children || children.length == 0 || setting.check.chkboxType.Y.indexOf("s") > -1)) {
view.setSonNodeCheckBox(setting, node, true);
}
if (!nodeChecked && (!children || children.length == 0 || setting.check.chkboxType.N.indexOf("s") > -1)) {
view.setSonNodeCheckBox(setting, node, false);
}
if (nodeChecked && setting.check.chkboxType.Y.indexOf("p") > -1) {
view.setParentNodeCheckBox(setting, node, true);
}
if (!nodeChecked && setting.check.chkboxType.N.indexOf("p") > -1) {
view.setParentNodeCheckBox(setting, node, false);
}
}
},
makeChkClass: function (setting, node) {
var c = consts.checkbox, r = consts.radio,
fullStyle = "";
var nodeChecked = data.nodeChecked(setting, node);
if (node.chkDisabled === true) {
fullStyle = c.DISABLED;
} else if (node.halfCheck) {
fullStyle = c.PART;
} else if (setting.check.chkStyle == r.STYLE) {
fullStyle = (node.check_Child_State < 1) ? c.FULL : c.PART;
} else {
fullStyle = nodeChecked ? ((node.check_Child_State === 2 || node.check_Child_State === -1) ? c.FULL : c.PART) : ((node.check_Child_State < 1) ? c.FULL : c.PART);
}
var chkName = setting.check.chkStyle + "_" + (nodeChecked ? c.TRUE : c.FALSE) + "_" + fullStyle;
chkName = (node.check_Focus && node.chkDisabled !== true) ? chkName + "_" + c.FOCUS : chkName;
return consts.className.BUTTON + " " + c.DEFAULT + " " + chkName;
},
repairAllChk: function (setting, checked) {
if (setting.check.enable && setting.check.chkStyle === consts.checkbox.STYLE) {
var root = data.getRoot(setting);
var children = data.nodeChildren(setting, root);
for (var i = 0, l = children.length; i < l; i++) {
var node = children[i];
if (node.nocheck !== true && node.chkDisabled !== true) {
data.nodeChecked(setting, node, checked);
}
view.setSonNodeCheckBox(setting, node, checked);
}
}
},
repairChkClass: function (setting, node) {
if (!node) return;
data.makeChkFlag(setting, node);
if (node.nocheck !== true) {
var checkObj = $$(node, consts.id.CHECK, setting);
view.setChkClass(setting, checkObj, node);
}
},
repairParentChkClass: function (setting, node) {
if (!node || !node.parentTId) return;
var pNode = node.getParentNode();
view.repairChkClass(setting, pNode);
view.repairParentChkClass(setting, pNode);
},
repairParentChkClassWithSelf: function (setting, node) {
if (!node) return;
var children = data.nodeChildren(setting, node);
if (children && children.length > 0) {
view.repairParentChkClass(setting, children[0]);
} else {
view.repairParentChkClass(setting, node);
}
},
repairSonChkDisabled: function (setting, node, chkDisabled, inherit) {
if (!node) return;
if (node.chkDisabled != chkDisabled) {
node.chkDisabled = chkDisabled;
}
view.repairChkClass(setting, node);
var children = data.nodeChildren(setting, node);
if (children && inherit) {
for (var i = 0, l = children.length; i < l; i++) {
var sNode = children[i];
view.repairSonChkDisabled(setting, sNode, chkDisabled, inherit);
}
}
},
repairParentChkDisabled: function (setting, node, chkDisabled, inherit) {
if (!node) return;
if (node.chkDisabled != chkDisabled && inherit) {
node.chkDisabled = chkDisabled;
}
view.repairChkClass(setting, node);
view.repairParentChkDisabled(setting, node.getParentNode(), chkDisabled, inherit);
},
setChkClass: function (setting, obj, node) {
if (!obj) return;
if (node.nocheck === true) {
obj.hide();
} else {
obj.show();
}
obj.attr('class', view.makeChkClass(setting, node));
},
setParentNodeCheckBox: function (setting, node, value, srcNode) {
var checkObj = $$(node, consts.id.CHECK, setting);
if (!srcNode) srcNode = node;
data.makeChkFlag(setting, node);
if (node.nocheck !== true && node.chkDisabled !== true) {
data.nodeChecked(setting, node, value);
view.setChkClass(setting, checkObj, node);
if (setting.check.autoCheckTrigger && node != srcNode) {
setting.treeObj.trigger(consts.event.CHECK, [null, setting.treeId, node]);
}
}
if (node.parentTId) {
var pSign = true;
if (!value) {
var pNodes = data.nodeChildren(setting, node.getParentNode());
for (var i = 0, l = pNodes.length; i < l; i++) {
var pNode = pNodes[i];
var nodeChecked = data.nodeChecked(setting, pNode);
if ((pNode.nocheck !== true && pNode.chkDisabled !== true && nodeChecked)
|| ((pNode.nocheck === true || pNode.chkDisabled === true) && pNode.check_Child_State > 0)) {
pSign = false;
break;
}
}
}
if (pSign) {
view.setParentNodeCheckBox(setting, node.getParentNode(), value, srcNode);
}
}
},
setSonNodeCheckBox: function (setting, node, value, srcNode) {
if (!node) return;
var checkObj = $$(node, consts.id.CHECK, setting);
if (!srcNode) srcNode = node;
var hasDisable = false;
var children = data.nodeChildren(setting, node);
if (children) {
for (var i = 0, l = children.length; i < l; i++) {
var sNode = children[i];
view.setSonNodeCheckBox(setting, sNode, value, srcNode);
if (sNode.chkDisabled === true) hasDisable = true;
}
}
if (node != data.getRoot(setting) && node.chkDisabled !== true) {
if (hasDisable && node.nocheck !== true) {
data.makeChkFlag(setting, node);
}
if (node.nocheck !== true && node.chkDisabled !== true) {
data.nodeChecked(setting, node, value);
if (!hasDisable) node.check_Child_State = (children && children.length > 0) ? (value ? 2 : 0) : -1;
} else {
node.check_Child_State = -1;
}
view.setChkClass(setting, checkObj, node);
if (setting.check.autoCheckTrigger && node != srcNode && node.nocheck !== true && node.chkDisabled !== true) {
setting.treeObj.trigger(consts.event.CHECK, [null, setting.treeId, node]);
}
}
}
},
_z = {
tools: _tools,
view: _view,
event: _event,
data: _data
};
$.extend(true, $.fn.zTree.consts, _consts);
$.extend(true, $.fn.zTree._z, _z);
var zt = $.fn.zTree,
tools = zt._z.tools,
consts = zt.consts,
view = zt._z.view,
data = zt._z.data,
event = zt._z.event,
$$ = tools.$;
data.nodeChecked = function (setting, node, newChecked) {
if (!node) {
return false;
}
var key = setting.data.key.checked;
if (typeof newChecked !== 'undefined') {
if (typeof newChecked === "string") {
newChecked = tools.eqs(newChecked, "true");
}
newChecked = !!newChecked;
node[key] = newChecked;
} else if (typeof node[key] == "string"){
node[key] = tools.eqs(node[key], "true");
} else {
node[key] = !!node[key];
}
return node[key];
};
data.exSetting(_setting);
data.addInitBind(_bindEvent);
data.addInitUnBind(_unbindEvent);
data.addInitCache(_initCache);
data.addInitNode(_initNode);
data.addInitProxy(_eventProxy, true);
data.addInitRoot(_initRoot);
data.addBeforeA(_beforeA);
data.addZTreeTools(_zTreeTools);
var _createNodes = view.createNodes;
view.createNodes = function (setting, level, nodes, parentNode, index) {
if (_createNodes) _createNodes.apply(view, arguments);
if (!nodes) return;
view.repairParentChkClassWithSelf(setting, parentNode);
}
var _removeNode = view.removeNode;
view.removeNode = function (setting, node) {
var parentNode = node.getParentNode();
if (_removeNode) _removeNode.apply(view, arguments);
if (!node || !parentNode) return;
view.repairChkClass(setting, parentNode);
view.repairParentChkClass(setting, parentNode);
}
var _appendNodes = view.appendNodes;
view.appendNodes = function (setting, level, nodes, parentNode, index, initFlag, openFlag) {
var html = "";
if (_appendNodes) {
html = _appendNodes.apply(view, arguments);
}
if (parentNode) {
data.makeChkFlag(setting, parentNode);
}
return html;
}
})(jQuery);

Binary file not shown.

View File

@@ -0,0 +1,250 @@
/**
* @author zhixin wen <wenzhixin2010@gmail.com>
* version: 1.2.0
* https://github.com/wenzhixin/font-awesome-zTree
*/
.ztree * {
font-size: 14px;
font-family: inherit;
}
.ztree .fa, .ztree .fab, .ztree .fad, .ztree .fal, .ztree .far, .ztree .fas {
font-family: "Font Awesome 5 Free";
}
.ztree .ztree-search {
margin: 5px;
}
.ztree .ztree-search input {
padding: 5px 10px;
}
.ztree .ztree-search .search-clear {
padding: 5px 10px;
font-size: 12px;
line-height: 1;
}
.ztree li ul {
position: relative;
background: none;
margin-left: 12px;
padding-left: 0;
}
.ztree li ul.line {
background: none;
}
.ztree li ul::before {
content: "";
display: block;
width: 0;
position: absolute;
top: 0;
bottom: 0;
left: 0;
border-left: 1px dotted #ccc;
}
.ztree li li {
position: relative;
padding-left: 9px;
line-height: inherit;
}
.ztree li li::before {
content: "";
display: block;
width: 10px;
height: 0;
border-top: 1px dotted #ccc;
position: absolute;
top: 13px;
left: 0;
}
.ztree li .noline_open + a + ul li::before {
border-top: none;
}
.ztree li .noline_open + a + ul::before {
border-left: none;
}
.ztree li span.node_name {
margin-right: 6px;
}
.ztree li span.button[class$=Page] {
width: 15px;
}
.ztree li span.button::before {
display: block;
line-height: 26px;
text-align: center;
}
.ztree li span.button.roots_docu, .ztree li span.button.center_docu, .ztree li span.button.bottom_docu {
position: relative;
height: 26px;
padding: 0;
}
.ztree li span.button.roots_docu::before, .ztree li span.button.center_docu::before, .ztree li span.button.bottom_docu::before {
content: "";
display: block;
width: 18px;
height: 0;
border-top: 1px dotted #ccc;
position: absolute;
top: 13px;
left: 0;
}
.ztree li span.button.root_open::before, .ztree li span.button.roots_open::before, .ztree li span.button.center_open::before, .ztree li span.button.bottom_open::before, .ztree li span.button.noline_open::before {
content: "\f146";
color: #3c8dbc;
}
.ztree li span.button.root_close::before, .ztree li span.button.roots_close::before, .ztree li span.button.center_close::before, .ztree li span.button.bottom_close::before, .ztree li span.button.noline_close::before {
content: "\f0fe";
color: #3c8dbc;
}
.ztree li span.button.chk {
color: #6b6b6b;
}
.ztree li span.button.chk[class$=focus]::before {
font-weight: bold;
}
.ztree li span.button.chk[class$=disable] {
color: #ccc;
}
.ztree li span.button.chk.checkbox_true_full::before, .ztree li span.button.chk.checkbox_true_disable::before, .ztree li span.button.chk.checkbox_true_full_focus::before {
content: "\f14a";
font-weight: normal !important;
color: #16b777;
}
.ztree li span.button.chk.checkbox_false_full::before, .ztree li span.button.chk.checkbox_false_disable::before, .ztree li span.button.chk.checkbox_false_full_focus::before {
content: "\f0c8";
font-weight: normal !important;
}
.ztree li span.button.chk.checkbox_true_part::before, .ztree li span.button.chk.checkbox_true_part_focus::before, .ztree li span.button.chk.checkbox_false_part::before, .ztree li span.button.chk.checkbox_false_part_focus::before {
content: "\f146";
font-weight: bold !important;
color: #16B777;
}
.ztree li span.button.chk.radio_true_full::before, .ztree li span.button.chk.radio_true_disable::before, .ztree li span.button.chk.radio_true_full_focus::before {
content: "\f058";
font-weight: normal !important;
}
.ztree li span.button.chk.radio_false_full::before, .ztree li span.button.chk.radio_false_disable::before, .ztree li span.button.chk.radio_false_full_focus::before {
content: "\f111";
font-weight: normal !important;
}
.ztree li span.button.chk.radio_true_part::before, .ztree li span.button.chk.radio_true_part_focus::before, .ztree li span.button.chk.radio_false_part::before, .ztree li span.button.chk.radio_false_part_focus::before {
content: "\f192";
font-weight: normal !important;
}
.ztree li span.button.ico_open::before {
content: "\f07c";
}
.ztree li span.button.ico_close::before {
content: "\f07b";
}
.ztree li span.button.ico_docu::before {
content: "\f15b";
}
.ztree li span.button.add::before {
content: "\f067";
}
.ztree li span.button.edit::before {
content: "\f044";
}
.ztree li span.button.remove::before {
content: "\f2ed";
}
.ztree li span.button.fa_history_ico_open::before, .ztree li span.button.fa_history_ico_close::before, .ztree li span.button.fa_history_ico_docu::before {
font-weight: bold !important;
content: "\f1da";
}
.ztree li span.button.fa_tasks_ico_open::before {
font-weight: bold !important;
content: "\f233";
}
.ztree li span.button.firstPage::before {
content: "\f100";
}
.ztree li span.button.prevPage::before {
content: "\f053";
}
.ztree li span.button.nextPage::before {
content: "\f054";
}
.ztree li span.button.lastPage::before {
content: "\f101";
}
.ztree li a span.button[style="width:0px;height:0px;"]::before, .ztree li a span.button[style^=background]::before {
content: "";
}
.ztree li a.curSelectedNode, .ztree li a.tmpTargetNode_inner {
height: 26px;
}
.ztree li > a {
height: 26px;
line-height: 26px;
}
.ztree li > span {
height: 26px;
}
.ztree li:last-child::before {
height: auto;
top: 13px;
bottom: 0;
}
.ztree li span.button.switch,
.ztree li span.button.chk,
.ztree li a span.button,
.ztree li span.button[class$=Page] {
position: relative;
width: 21px;
height: 26px;
background: none;
background-position: center center !important;
padding: 2px 0;
vertical-align: middle;
display: inline-block;
font: normal normal normal 15px/1 "Font Awesome 5 Free";
text-rendering: auto;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

View File

@@ -10,10 +10,22 @@
<link rel="stylesheet" href="/static/common/css/insatll.css?v={:time()}" media="all">
</head>
<body>
<h1><img src="/static/common/images/logo-1.png"></h1>
<h1><img src="/static/common/images/logo-1.png" alt="" style="width: 100px;height: 100px;"></h1>
<h2>安装 EasyAdmin8 后台系统</h2>
<div class="content">
<form class="layui-form layui-form-pane" action="">
<div class="layui-card">
<blockquote class="layui-elem-quote layui-font-green" style="text-align: left;padding: 5px 10px;">
<div class="layui-row">
<div class="layui-col-lg6 layui-col-xl6 layui-col-xs6 layui-col-sm6 layui-col-xs6">
官网教程:<a href="https://EasyAdmin8.top?spm=001.3e3c9d.29f459" target="_blank" class="layui-font-blue">EasyAdmin8.top</a>
</div>
<div class="layui-col-lg6 layui-col-xl6 layui-col-xs6 layui-col-sm6 layui-col-xs6">
常见问题:<a href="https://EasyAdmin8.top/guide/question.html?spm=001.3e3c9d.29f460" target="_blank" class="layui-font-blue">Question</a>
</div>
</div>
</blockquote>
</div>
{if $errorInfo}
<div class="error">
{$errorInfo}