init
This commit is contained in:
42
.example.env
Normal file
42
.example.env
Normal file
@@ -0,0 +1,42 @@
|
||||
APP_DEBUG=true
|
||||
|
||||
[APP]
|
||||
DEFAULT_TIMEZONE=Asia/Shanghai
|
||||
|
||||
[DATABASE]
|
||||
TYPE=mysql
|
||||
HOSTNAME=127.0.0.1
|
||||
DATABASE=easyadmin8
|
||||
USERNAME=root
|
||||
PASSWORD=root
|
||||
HOSTPORT=3306
|
||||
CHARSET=utf8mb4
|
||||
DEBUG=true
|
||||
PREFIX=ea8_
|
||||
|
||||
[LANG]
|
||||
default_lang=zh-cn
|
||||
|
||||
# 后台配置项组
|
||||
[EASYADMIN]
|
||||
# 后台地址后缀名称
|
||||
ADMIN=admin
|
||||
|
||||
# 后台登录验证码开关
|
||||
CAPTCHA=false
|
||||
|
||||
# 是否为演示环境
|
||||
IS_DEMO=false
|
||||
|
||||
# CDN配置项组
|
||||
CDN=
|
||||
EXAMPLE=true
|
||||
|
||||
# 是否开启CSRF过滤
|
||||
IS_CSRF=false
|
||||
|
||||
# 静态文件路径前缀
|
||||
STATIC_PATH=/static
|
||||
|
||||
# OSS静态文件路径前缀
|
||||
OSS_STATIC_PREFIX=static_easyadmin
|
||||
3
.gitattributes
vendored
Normal file
3
.gitattributes
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
*.js linguist-language=PHP
|
||||
*.css linguist-language=PHP
|
||||
*.html linguist-language=PHP
|
||||
18
.gitignore
vendored
Normal file
18
.gitignore
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
/.idea
|
||||
/.vscode
|
||||
*.log
|
||||
.env
|
||||
config/install/lock/install.lock
|
||||
/public/upload
|
||||
/public/docs
|
||||
runtime/admin
|
||||
runtime/log
|
||||
runtime/session
|
||||
runtime/temp
|
||||
runtime/cache
|
||||
public/conf
|
||||
public/WowOss.exe
|
||||
app/index/controller/Test.php
|
||||
composer.phar
|
||||
app/test/
|
||||
vendor
|
||||
42
.travis.yml
Normal file
42
.travis.yml
Normal file
@@ -0,0 +1,42 @@
|
||||
sudo: false
|
||||
|
||||
language: php
|
||||
|
||||
branches:
|
||||
only:
|
||||
- stable
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.composer/cache
|
||||
|
||||
before_install:
|
||||
- composer self-update
|
||||
|
||||
install:
|
||||
- composer install --no-dev --no-interaction --ignore-platform-reqs
|
||||
- zip -r --exclude='*.git*' --exclude='*.zip' --exclude='*.travis.yml' ThinkPHP_Core.zip .
|
||||
- composer require --update-no-dev --no-interaction "topthink/think-image:^1.0"
|
||||
- composer require --update-no-dev --no-interaction "topthink/think-migration:^1.0"
|
||||
- composer require --update-no-dev --no-interaction "topthink/think-captcha:^1.0"
|
||||
- composer require --update-no-dev --no-interaction "topthink/think-mongo:^1.0"
|
||||
- composer require --update-no-dev --no-interaction "topthink/think-worker:^1.0"
|
||||
- composer require --update-no-dev --no-interaction "topthink/think-helper:^1.0"
|
||||
- composer require --update-no-dev --no-interaction "topthink/think-queue:^1.0"
|
||||
- composer require --update-no-dev --no-interaction "topthink/think-angular:^1.0"
|
||||
- composer require --dev --update-no-dev --no-interaction "topthink/think-testing:^1.0"
|
||||
- zip -r --exclude='*.git*' --exclude='*.zip' --exclude='*.travis.yml' ThinkPHP_Full.zip .
|
||||
|
||||
script:
|
||||
- php think unit
|
||||
|
||||
deploy:
|
||||
provider: releases
|
||||
api_key:
|
||||
secure: TSF6bnl2JYN72UQOORAJYL+CqIryP2gHVKt6grfveQ7d9rleAEoxlq6PWxbvTI4jZ5nrPpUcBUpWIJHNgVcs+bzLFtyh5THaLqm39uCgBbrW7M8rI26L8sBh/6nsdtGgdeQrO/cLu31QoTzbwuz1WfAVoCdCkOSZeXyT/CclH99qV6RYyQYqaD2wpRjrhA5O4fSsEkiPVuk0GaOogFlrQHx+C+lHnf6pa1KxEoN1A0UxxVfGX6K4y5g4WQDO5zT4bLeubkWOXK0G51XSvACDOZVIyLdjApaOFTwamPcD3S1tfvuxRWWvsCD5ljFvb2kSmx5BIBNwN80MzuBmrGIC27XLGOxyMerwKxB6DskNUO9PflKHDPI61DRq0FTy1fv70SFMSiAtUv9aJRT41NQh9iJJ0vC8dl+xcxrWIjU1GG6+l/ZcRqVx9V1VuGQsLKndGhja7SQ+X1slHl76fRq223sMOql7MFCd0vvvxVQ2V39CcFKao/LB1aPH3VhODDEyxwx6aXoTznvC/QPepgWsHOWQzKj9ftsgDbsNiyFlXL4cu8DWUty6rQy8zT2b4O8b1xjcwSUCsy+auEjBamzQkMJFNlZAIUrukL/NbUhQU37TAbwsFyz7X0E/u/VMle/nBCNAzgkMwAUjiHM6FqrKKBRWFbPrSIixjfjkCnrMEPw=
|
||||
file:
|
||||
- ThinkPHP_Core.zip
|
||||
- ThinkPHP_Full.zip
|
||||
skip_cleanup: true
|
||||
on:
|
||||
tags: true
|
||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 EasyAdmin
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
36
README.en.md
Normal file
36
README.en.md
Normal file
@@ -0,0 +1,36 @@
|
||||
# EasyAdmin8
|
||||
|
||||
#### Description
|
||||
{**When you're done, you can delete the content in this README and update the file with details for others getting started with your repository**}
|
||||
|
||||
#### Software Architecture
|
||||
Software architecture description
|
||||
|
||||
#### Installation
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
|
||||
#### Instructions
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
|
||||
#### Contribution
|
||||
|
||||
1. Fork the repository
|
||||
2. Create Feat_xxx branch
|
||||
3. Commit your code
|
||||
4. Create Pull Request
|
||||
|
||||
|
||||
#### Gitee Feature
|
||||
|
||||
1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
|
||||
2. Gitee blog [blog.gitee.com](https://blog.gitee.com)
|
||||
3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
|
||||
4. The most valuable open source project [GVP](https://gitee.com/gvp)
|
||||
5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
|
||||
6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
|
||||
92
README.md
92
README.md
@@ -1 +1,91 @@
|
||||
# easyAdmin8
|
||||
## 项目介绍
|
||||
|
||||
> `EasyAdmin8` 基于 [`EasyAdmin`](https://gitee.com/zhongshaofa/easyadmin) 的基础上更新 ThinkPHP 框架到 8.0 ,PHP 最低版本要求不低于 8.0
|
||||
>
|
||||
> ThinkPHP v8.0 和 layui v2.8.x 的快速开发的后台管理系统。
|
||||
|
||||
## 安装教程
|
||||
|
||||
> EasyAdmin8 使用 Composer 来管理项目依赖。因此,在使用 EasyAdmin8 之前,请确保你的机器已经安装了 Composer。
|
||||
|
||||
#### 通过 Composer 创建项目`建议`
|
||||
|
||||
`composer install`
|
||||
|
||||
#### 通过git下载安装包,composer安装依赖包
|
||||
|
||||
```
|
||||
1.下载安装包
|
||||
|
||||
git clone https://github.com/wolfcode-cn/easyAdmin8
|
||||
|
||||
或者
|
||||
|
||||
git clone https://gitee.com/wolf-code/easyAdmin8
|
||||
|
||||
2.安装依赖包(确保 PHP 版本 >= 8.0)
|
||||
|
||||
composer install
|
||||
|
||||
3. 拷贝 .example.env 文件重命名名为 .env
|
||||
|
||||
4.配置伪静态(以 Nginx 为例)
|
||||
|
||||
location / {
|
||||
if ( !-e $request_filename){
|
||||
rewrite ^/(.*)$ /index.php?s=$1 last;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## 项目特性
|
||||
|
||||
* 快速CURD命令行
|
||||
* 一键生成控制器、模型、视图、JS文件
|
||||
* 支持关联查询、字段设置等等
|
||||
* 基于`auth`的权限管理系统
|
||||
* 通过`注解方式`来实现`auth`权限节点管理
|
||||
* 具备一键更新`auth`权限节点,无需手动输入管理
|
||||
* 完善的后端权限验证以及前面页面按钮显示、隐藏控制
|
||||
* 完善的菜单管理
|
||||
* 分模块管理
|
||||
* 无限极菜单
|
||||
* 菜单编辑会提示`权限节点`
|
||||
* 完善的上传组件功能
|
||||
* 本地存储
|
||||
* 阿里云OSS`建议使用`
|
||||
* 腾讯云COS
|
||||
* 七牛云OSS
|
||||
* 完善的前端组件功能
|
||||
* 对layui的form表单重新封装,无需手动拼接数据请求
|
||||
* 简单好用的`图片、文件`上传组件
|
||||
* 简单好用的富文本编辑器`ckeditor`
|
||||
* 对弹出层进行再次封装,以极简的方式使用
|
||||
* 对table表格再次封装,在使用上更加舒服
|
||||
* 根据table的`cols`参数再次进行封装,提供接口实现`image`、`switch`、`list`等功能,再次基础上可以自己再次扩展
|
||||
* 根据table参数一键生成`搜索表单`,无需自己编写
|
||||
* 完善的后台操作日志
|
||||
* 记录用户的详细操作信息
|
||||
* 按月份进行`分表记录`
|
||||
* 一键部署静态资源到OSS上
|
||||
* 所有在`public\static`目录下的文件都可以一键部署
|
||||
* 一个配置项切换静态资源(oss/本地)
|
||||
* 上传文件记录管理
|
||||
* 后台路径自定义,防止别人找到对应的后台地址
|
||||
|
||||
## 免责声明
|
||||
|
||||
> 所有协议遵循 [`EasyAdmin`](https://gitee.com/zhongshaofa/easyadmin)
|
||||
>
|
||||
> 任何用户在使用 `EasyAdmin8` 后台框架前,请您仔细阅读并透彻理解本声明。您可以选择不使用`EasyAdmin8`后台框架,若您一旦使用`EasyAdmin8`后台框架,您的使用行为即被视为对本声明全部内容的认可和接受。
|
||||
|
||||
* `EasyAdmin8`后台框架是一款开源免费的后台快速开发框架 ,主要用于更便捷地开发后台管理;其尊重并保护所有用户的个人隐私权,不窃取任何用户计算机中的信息。更不具备用户数据存储等网络传输功能。
|
||||
* 您承诺秉着合法、合理的原则使用`EasyAdmin8`后台框架,不利用`EasyAdmin8`后台框架进行任何违法、侵害他人合法利益等恶意的行为,亦不将`EasyAdmin8`后台框架运用于任何违反我国法律法规的 Web 平台。
|
||||
* 任何单位或个人因下载使用`EasyAdmin8`后台框架而产生的任何意外、疏忽、合约毁坏、诽谤、版权或知识产权侵犯及其造成的损失 (包括但不限于直接、间接、附带或衍生的损失等),本开源项目不承担任何法律责任。
|
||||
* 用户明确并同意本声明条款列举的全部内容,对使用`EasyAdmin8`后台框架可能存在的风险和相关后果将完全由用户自行承担,本开源项目不承担任何法律责任。
|
||||
* 任何单位或个人在阅读本免责声明后,应在《MIT 开源许可证》所允许的范围内进行合法的发布、传播和使用`EasyAdmin8`后台框架等行为,若违反本免责声明条款或违反法律法规所造成的法律责任(包括但不限于民事赔偿和刑事责任),由违约者自行承担。
|
||||
* 如果本声明的任何部分被认为无效或不可执行,其余部分仍具有完全效力。不可执行的部分声明,并不构成我们放弃执行该声明的权利。
|
||||
* 本开源项目有权随时对本声明条款及附件内容进行单方面的变更,并以消息推送、网页公告等方式予以公布,公布后立即自动生效,无需另行单独通知;若您在本声明内容公告变更后继续使用的,表示您已充分阅读、理解并接受修改后的声明内容。
|
||||
|
||||
|
||||
1
app/.htaccess
Normal file
1
app/.htaccess
Normal file
@@ -0,0 +1 @@
|
||||
deny from all
|
||||
94
app/BaseController.php
Normal file
94
app/BaseController.php
Normal file
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace app;
|
||||
|
||||
use think\App;
|
||||
use think\exception\ValidateException;
|
||||
use think\Validate;
|
||||
|
||||
/**
|
||||
* 控制器基础类
|
||||
*/
|
||||
abstract class BaseController
|
||||
{
|
||||
/**
|
||||
* Request实例
|
||||
* @var \think\Request
|
||||
*/
|
||||
protected $request;
|
||||
|
||||
/**
|
||||
* 应用实例
|
||||
* @var \think\App
|
||||
*/
|
||||
protected $app;
|
||||
|
||||
/**
|
||||
* 是否批量验证
|
||||
* @var bool
|
||||
*/
|
||||
protected $batchValidate = false;
|
||||
|
||||
/**
|
||||
* 控制器中间件
|
||||
* @var array
|
||||
*/
|
||||
protected $middleware = [];
|
||||
|
||||
/**
|
||||
* 构造方法
|
||||
* @access public
|
||||
* @param App $app 应用对象
|
||||
*/
|
||||
public function __construct(App $app)
|
||||
{
|
||||
$this->app = $app;
|
||||
$this->request = $this->app->request;
|
||||
|
||||
// 控制器初始化
|
||||
$this->initialize();
|
||||
}
|
||||
|
||||
// 初始化
|
||||
protected function initialize()
|
||||
{}
|
||||
|
||||
/**
|
||||
* 验证数据
|
||||
* @access protected
|
||||
* @param array $data 数据
|
||||
* @param string|array $validate 验证器名或者验证规则数组
|
||||
* @param array $message 提示信息
|
||||
* @param bool $batch 是否批量验证
|
||||
* @return array|string|true
|
||||
* @throws ValidateException
|
||||
*/
|
||||
protected function validate(array $data, $validate, array $message = [], bool $batch = false)
|
||||
{
|
||||
if (is_array($validate)) {
|
||||
$v = new Validate();
|
||||
$v->rule($validate);
|
||||
} else {
|
||||
if (strpos($validate, '.')) {
|
||||
// 支持场景
|
||||
list($validate, $scene) = explode('.', $validate);
|
||||
}
|
||||
$class = false !== strpos($validate, '\\') ? $validate : $this->app->parseClass('validate', $validate);
|
||||
$v = new $class();
|
||||
if (!empty($scene)) {
|
||||
$v->scene($scene);
|
||||
}
|
||||
}
|
||||
|
||||
$v->message($message);
|
||||
|
||||
// 是否批量验证
|
||||
if ($batch || $this->batchValidate) {
|
||||
$v->batch(true);
|
||||
}
|
||||
|
||||
return $v->failException(true)->check($data);
|
||||
}
|
||||
|
||||
}
|
||||
58
app/ExceptionHandle.php
Normal file
58
app/ExceptionHandle.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
namespace app;
|
||||
|
||||
use think\db\exception\DataNotFoundException;
|
||||
use think\db\exception\ModelNotFoundException;
|
||||
use think\exception\Handle;
|
||||
use think\exception\HttpException;
|
||||
use think\exception\HttpResponseException;
|
||||
use think\exception\ValidateException;
|
||||
use think\Response;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* 应用异常处理类
|
||||
*/
|
||||
class ExceptionHandle extends Handle
|
||||
{
|
||||
/**
|
||||
* 不需要记录信息(日志)的异常类列表
|
||||
* @var array
|
||||
*/
|
||||
protected $ignoreReport = [
|
||||
HttpException::class,
|
||||
HttpResponseException::class,
|
||||
ModelNotFoundException::class,
|
||||
DataNotFoundException::class,
|
||||
ValidateException::class,
|
||||
];
|
||||
|
||||
/**
|
||||
* 记录异常信息(包括日志或者其它方式记录)
|
||||
*
|
||||
* @access public
|
||||
* @param Throwable $exception
|
||||
* @return void
|
||||
*/
|
||||
public function report(Throwable $exception): void
|
||||
{
|
||||
// 使用内置的方式记录异常日志
|
||||
parent::report($exception);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render an exception into an HTTP response.
|
||||
*
|
||||
* @access public
|
||||
* @param \think\Request $request
|
||||
* @param Throwable $e
|
||||
* @return Response
|
||||
*/
|
||||
public function render($request, Throwable $e): Response
|
||||
{
|
||||
// 添加自定义异常处理机制
|
||||
|
||||
// 其他错误交给系统处理
|
||||
return parent::render($request, $e);
|
||||
}
|
||||
}
|
||||
11
app/Request.php
Normal file
11
app/Request.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace app;
|
||||
|
||||
// 应用请求对象类
|
||||
class Request extends \think\Request
|
||||
{
|
||||
|
||||
protected $filter = ['htmlspecialchars'];
|
||||
|
||||
}
|
||||
28
app/admin/config/admin.php
Normal file
28
app/admin/config/admin.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
// 不需要验证登录的控制器
|
||||
'no_login_controller' => [
|
||||
'login',
|
||||
],
|
||||
|
||||
// 不需要验证登录的节点
|
||||
'no_login_node' => [
|
||||
'login/index',
|
||||
'login/out',
|
||||
],
|
||||
|
||||
// 不需要验证权限的控制器
|
||||
'no_auth_controller' => [
|
||||
'ajax',
|
||||
'login',
|
||||
'index',
|
||||
],
|
||||
|
||||
// 不需要验证权限的节点
|
||||
'no_auth_node' => [
|
||||
'login/index',
|
||||
'login/out',
|
||||
],
|
||||
];
|
||||
10
app/admin/config/app.php
Normal file
10
app/admin/config/app.php
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | 应用设置
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
use think\facade\Env;
|
||||
|
||||
return [
|
||||
|
||||
];
|
||||
10
app/admin/config/console.php
Normal file
10
app/admin/config/console.php
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | 控制台配置
|
||||
// +----------------------------------------------------------------------
|
||||
return [
|
||||
// 指令定义
|
||||
'commands' => [
|
||||
'alioss' => 'addons\alioss\command\Alioss',
|
||||
],
|
||||
];
|
||||
19
app/admin/config/route.php
Normal file
19
app/admin/config/route.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | 路由设置
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
return [
|
||||
|
||||
// 路由中间件
|
||||
'middleware' => [
|
||||
|
||||
// // 后台视图初始化
|
||||
// \app\admin\middleware\ViewInit::class,
|
||||
|
||||
// 检测用户是否登录
|
||||
// \app\admin\middleware\CheckAdmin::class,
|
||||
|
||||
|
||||
],
|
||||
];
|
||||
165
app/admin/controller/Ajax.php
Normal file
165
app/admin/controller/Ajax.php
Normal file
@@ -0,0 +1,165 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use app\admin\model\SystemUploadfile;
|
||||
use app\common\controller\AdminController;
|
||||
use app\common\service\MenuService;
|
||||
use app\admin\service\upload\Uploadfile;
|
||||
use think\db\exception\DataNotFoundException;
|
||||
use think\db\exception\DbException;
|
||||
use think\db\exception\ModelNotFoundException;
|
||||
use think\db\Query;
|
||||
use think\facade\Cache;
|
||||
use think\response\Json;
|
||||
|
||||
class Ajax extends AdminController
|
||||
{
|
||||
|
||||
/**
|
||||
* 初始化后台接口地址
|
||||
* @return Json
|
||||
* @throws DataNotFoundException
|
||||
* @throws DbException
|
||||
* @throws ModelNotFoundException
|
||||
*/
|
||||
public function initAdmin(): Json
|
||||
{
|
||||
$cacheData = Cache::get('initAdmin_' . session('admin.id'));
|
||||
if (!empty($cacheData)) {
|
||||
return json($cacheData);
|
||||
}
|
||||
$menuService = new MenuService(session('admin.id'));
|
||||
$data = [
|
||||
'logoInfo' => [
|
||||
'title' => sysconfig('site', 'logo_title'),
|
||||
'image' => sysconfig('site', 'logo_image'),
|
||||
'href' => __url('index/index'),
|
||||
],
|
||||
'homeInfo' => $menuService->getHomeInfo(),
|
||||
'menuInfo' => $menuService->getMenuTree(),
|
||||
];
|
||||
Cache::tag('initAdmin')->set('initAdmin_' . session('admin.id'), $data);
|
||||
return json($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理缓存接口
|
||||
*/
|
||||
public function clearCache()
|
||||
{
|
||||
Cache::clear();
|
||||
$this->success('清理缓存成功');
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传文件
|
||||
*/
|
||||
public function upload()
|
||||
{
|
||||
$this->checkPostRequest();
|
||||
$data = [
|
||||
'upload_type' => $this->request->post('upload_type'),
|
||||
'file' => $this->request->file('file'),
|
||||
];
|
||||
$uploadConfig = sysconfig('upload');
|
||||
empty($data['upload_type']) && $data['upload_type'] = $uploadConfig['upload_type'];
|
||||
$rule = [
|
||||
'upload_type|指定上传类型有误' => "in:{$uploadConfig['upload_allow_type']}",
|
||||
'file|文件' => "require|file|fileExt:{$uploadConfig['upload_allow_ext']}|fileSize:{$uploadConfig['upload_allow_size']}",
|
||||
];
|
||||
$this->validate($data, $rule);
|
||||
try {
|
||||
$upload = Uploadfile::instance()
|
||||
->setUploadType($data['upload_type'])
|
||||
->setUploadConfig($uploadConfig)
|
||||
->setFile($data['file'])
|
||||
->save();
|
||||
} catch (\Exception $e) {
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
if ($upload['save'] == true) {
|
||||
$this->success($upload['msg'], ['url' => $upload['url']]);
|
||||
} else {
|
||||
$this->error($upload['msg']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传图片至编辑器
|
||||
* @return Json
|
||||
*/
|
||||
public function uploadEditor(): Json
|
||||
{
|
||||
$this->checkPostRequest();
|
||||
$data = [
|
||||
'upload_type' => $this->request->post('upload_type'),
|
||||
'file' => $this->request->file('upload'),
|
||||
];
|
||||
$uploadConfig = sysconfig('upload');
|
||||
empty($data['upload_type']) && $data['upload_type'] = $uploadConfig['upload_type'];
|
||||
$rule = [
|
||||
'upload_type|指定上传类型有误' => "in:{$uploadConfig['upload_allow_type']}",
|
||||
'file|文件' => "require|file|fileExt:{$uploadConfig['upload_allow_ext']}|fileSize:{$uploadConfig['upload_allow_size']}",
|
||||
];
|
||||
$this->validate($data, $rule);
|
||||
try {
|
||||
$upload = Uploadfile::instance()
|
||||
->setUploadType($data['upload_type'])
|
||||
->setUploadConfig($uploadConfig)
|
||||
->setFile($data['file'])
|
||||
->save();
|
||||
} catch (\Exception $e) {
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
if ($upload['save'] == true) {
|
||||
return json([
|
||||
'error' => [
|
||||
'message' => '上传成功',
|
||||
'number' => 201,
|
||||
],
|
||||
'fileName' => '',
|
||||
'uploaded' => 1,
|
||||
'url' => $upload['url'],
|
||||
]);
|
||||
} else {
|
||||
$this->error($upload['msg']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取上传文件列表
|
||||
* @return Json
|
||||
* @throws DataNotFoundException
|
||||
* @throws DbException
|
||||
* @throws ModelNotFoundException
|
||||
*/
|
||||
public function getUploadFiles(): Json
|
||||
{
|
||||
$get = $this->request->get();
|
||||
$page = isset($get['page']) && !empty($get['page']) ? $get['page'] : 1;
|
||||
$limit = isset($get['limit']) && !empty($get['limit']) ? $get['limit'] : 10;
|
||||
$title = isset($get['title']) && !empty($get['title']) ? $get['title'] : null;
|
||||
$this->model = new SystemUploadfile();
|
||||
$count = $this->model
|
||||
->where(function (Query $query) use ($title) {
|
||||
!empty($title) && $query->where('original_name', 'like', "%{$title}%");
|
||||
})
|
||||
->count();
|
||||
$list = $this->model
|
||||
->where(function (Query $query) use ($title) {
|
||||
!empty($title) && $query->where('original_name', 'like', "%{$title}%");
|
||||
})
|
||||
->page($page, $limit)
|
||||
->order($this->sort)
|
||||
->select();
|
||||
$data = [
|
||||
'code' => 0,
|
||||
'msg' => '',
|
||||
'count' => $count,
|
||||
'data' => $list,
|
||||
];
|
||||
return json($data);
|
||||
}
|
||||
|
||||
}
|
||||
123
app/admin/controller/Index.php
Normal file
123
app/admin/controller/Index.php
Normal file
@@ -0,0 +1,123 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use app\admin\model\SystemAdmin;
|
||||
use app\admin\model\SystemQuick;
|
||||
use app\common\controller\AdminController;
|
||||
use Exception;
|
||||
use think\App;
|
||||
use think\db\exception\DataNotFoundException;
|
||||
use think\db\exception\DbException;
|
||||
use think\db\exception\ModelNotFoundException;
|
||||
use think\facade\Env;
|
||||
|
||||
class Index extends AdminController
|
||||
{
|
||||
|
||||
/**
|
||||
* 后台主页
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function index(): string
|
||||
{
|
||||
return $this->fetch('', [
|
||||
'admin' => session('admin'),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 后台欢迎页
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function welcome(): string
|
||||
{
|
||||
$quicks = SystemQuick::field('id,title,icon,href')
|
||||
->where(['status' => 1])
|
||||
->order('sort', 'desc')
|
||||
->limit(8)
|
||||
->select();
|
||||
$this->assign('quicks', $quicks);
|
||||
return $this->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改管理员信息
|
||||
* @return string
|
||||
* @throws DataNotFoundException
|
||||
* @throws DbException
|
||||
* @throws ModelNotFoundException
|
||||
*/
|
||||
public function editAdmin(): string
|
||||
{
|
||||
$id = session('admin.id');
|
||||
$row = (new SystemAdmin())
|
||||
->withoutField('password')
|
||||
->find($id);
|
||||
empty($row) && $this->error('用户信息不存在');
|
||||
if ($this->request->isPost()) {
|
||||
$post = $this->request->post();
|
||||
$this->isDemo && $this->error('演示环境下不允许修改');
|
||||
$rule = [];
|
||||
$this->validate($post, $rule);
|
||||
try {
|
||||
$save = $row
|
||||
->allowField(['head_img', 'phone', 'remark', 'update_time'])
|
||||
->save($post);
|
||||
} catch (Exception $e) {
|
||||
$this->error('保存失败');
|
||||
}
|
||||
$save ? $this->success('保存成功') : $this->error('保存失败');
|
||||
}
|
||||
$this->assign('row', $row);
|
||||
return $this->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改密码
|
||||
* @return string
|
||||
* @throws DataNotFoundException
|
||||
* @throws DbException
|
||||
* @throws ModelNotFoundException
|
||||
*/
|
||||
public function editPassword(): string
|
||||
{
|
||||
$id = session('admin.id');
|
||||
$row = (new SystemAdmin())
|
||||
->withoutField('password')
|
||||
->find($id);
|
||||
if (!$row) {
|
||||
$this->error('用户信息不存在');
|
||||
}
|
||||
if ($this->request->isPost()) {
|
||||
$post = $this->request->post();
|
||||
$this->isDemo && $this->error('演示环境下不允许修改');
|
||||
$rule = [
|
||||
'password|登录密码' => 'require',
|
||||
'password_again|确认密码' => 'require',
|
||||
];
|
||||
$this->validate($post, $rule);
|
||||
if ($post['password'] != $post['password_again']) {
|
||||
$this->error('两次密码输入不一致');
|
||||
}
|
||||
|
||||
try {
|
||||
$save = $row->save([
|
||||
'password' => password($post['password']),
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
$this->error('保存失败');
|
||||
}
|
||||
if ($save) {
|
||||
$this->success('保存成功');
|
||||
} else {
|
||||
$this->error('保存失败');
|
||||
}
|
||||
}
|
||||
$this->assign('row', $row);
|
||||
return $this->fetch();
|
||||
}
|
||||
|
||||
}
|
||||
88
app/admin/controller/Login.php
Normal file
88
app/admin/controller/Login.php
Normal file
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use app\admin\model\SystemAdmin;
|
||||
use app\common\controller\AdminController;
|
||||
use think\captcha\facade\Captcha;
|
||||
use think\facade\Env;
|
||||
use think\Response;
|
||||
|
||||
/**
|
||||
* Class Login
|
||||
* @package app\admin\controller
|
||||
*/
|
||||
class Login extends AdminController
|
||||
{
|
||||
|
||||
/**
|
||||
* 初始化方法
|
||||
*/
|
||||
public function initialize()
|
||||
{
|
||||
parent::initialize();
|
||||
$action = $this->request->action();
|
||||
if (!empty(session('admin')) && !in_array($action, ['out'])) {
|
||||
$adminModuleName = config('app.admin_alias_name');
|
||||
$this->success('已登录,无需再次登录', [], __url("@{$adminModuleName}"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户登录
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function index(): string
|
||||
{
|
||||
$captcha = Env::get('EASYADMIN.CAPTCHA', 1);
|
||||
if ($this->request->isPost()) {
|
||||
$post = $this->request->post();
|
||||
$rule = [
|
||||
'username|用户名' => 'require',
|
||||
'password|密码' => 'require',
|
||||
'keep_login|是否保持登录' => 'require',
|
||||
];
|
||||
$captcha == 1 && $rule['captcha|验证码'] = 'require|captcha';
|
||||
$this->validate($post, $rule);
|
||||
$admin = SystemAdmin::where(['username' => $post['username']])->find();
|
||||
if (empty($admin)) {
|
||||
$this->error('用户不存在');
|
||||
}
|
||||
if (password($post['password']) != $admin->password) {
|
||||
$this->error('密码输入有误');
|
||||
}
|
||||
if ($admin->status == 0) {
|
||||
$this->error('账号已被禁用');
|
||||
}
|
||||
$admin->login_num += 1;
|
||||
$admin->save();
|
||||
$admin = $admin->toArray();
|
||||
unset($admin['password']);
|
||||
$admin['expire_time'] = $post['keep_login'] == 1 ? true : time() + 7200;
|
||||
session('admin', $admin);
|
||||
$this->success('登录成功');
|
||||
}
|
||||
$this->assign('captcha', $captcha);
|
||||
$this->assign('demo', $this->isDemo);
|
||||
return $this->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户退出
|
||||
*/
|
||||
public function out()
|
||||
{
|
||||
session('admin', null);
|
||||
$this->success('退出登录成功');
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证码
|
||||
* @return Response
|
||||
*/
|
||||
public function captcha(): Response
|
||||
{
|
||||
return Captcha::create();
|
||||
}
|
||||
}
|
||||
28
app/admin/controller/mall/Cate.php
Normal file
28
app/admin/controller/mall/Cate.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\controller\mall;
|
||||
|
||||
use app\admin\model\MallCate;
|
||||
use app\admin\traits\Curd;
|
||||
use app\common\controller\AdminController;
|
||||
use app\admin\service\annotation\ControllerAnnotation;
|
||||
use app\admin\service\annotation\NodeAnotation;
|
||||
use think\App;
|
||||
|
||||
/**
|
||||
* Class Admin
|
||||
* @package app\admin\controller\system
|
||||
* @ControllerAnnotation(title="商品分类管理")
|
||||
*/
|
||||
class Cate extends AdminController
|
||||
{
|
||||
|
||||
use Curd;
|
||||
|
||||
public function __construct(App $app)
|
||||
{
|
||||
parent::__construct($app);
|
||||
$this->model = new MallCate();
|
||||
}
|
||||
|
||||
}
|
||||
85
app/admin/controller/mall/Goods.php
Normal file
85
app/admin/controller/mall/Goods.php
Normal file
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\controller\mall;
|
||||
|
||||
use app\admin\model\MallGoods;
|
||||
use app\admin\traits\Curd;
|
||||
use app\common\controller\AdminController;
|
||||
use app\admin\service\annotation\ControllerAnnotation;
|
||||
use app\admin\service\annotation\NodeAnotation;
|
||||
use think\App;
|
||||
|
||||
/**
|
||||
* Class Goods
|
||||
* @package app\admin\controller\mall
|
||||
* @ControllerAnnotation(title="商城商品管理")
|
||||
*/
|
||||
class Goods extends AdminController
|
||||
{
|
||||
|
||||
use Curd;
|
||||
|
||||
protected bool $relationSearch = true;
|
||||
|
||||
public function __construct(App $app)
|
||||
{
|
||||
parent::__construct($app);
|
||||
$this->model = new MallGoods();
|
||||
}
|
||||
|
||||
/**
|
||||
* @NodeAnotation(title="列表")
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
if ($this->request->isAjax()) {
|
||||
if (input('selectFields')) {
|
||||
return $this->selectList();
|
||||
}
|
||||
list($page, $limit, $where) = $this->buildTableParams();
|
||||
$count = $this->model
|
||||
->withJoin('cate', 'LEFT')
|
||||
->where($where)
|
||||
->count();
|
||||
$list = $this->model
|
||||
->withJoin('cate', 'LEFT')
|
||||
->where($where)
|
||||
->page($page, $limit)
|
||||
->order($this->sort)
|
||||
->select();
|
||||
$data = [
|
||||
'code' => 0,
|
||||
'msg' => '',
|
||||
'count' => $count,
|
||||
'data' => $list,
|
||||
];
|
||||
return json($data);
|
||||
}
|
||||
return $this->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* @NodeAnotation(title="入库")
|
||||
*/
|
||||
public function stock($id)
|
||||
{
|
||||
$row = $this->model->find($id);
|
||||
empty($row) && $this->error('数据不存在');
|
||||
if ($this->request->isPost()) {
|
||||
$post = $this->request->post();
|
||||
$rule = [];
|
||||
$this->validate($post, $rule);
|
||||
try {
|
||||
$post['total_stock'] = $row->total_stock + $post['stock'];
|
||||
$post['stock'] = $row->stock + $post['stock'];
|
||||
$save = $row->save($post);
|
||||
} catch (\Exception $e) {
|
||||
$this->error('保存失败');
|
||||
}
|
||||
$save ? $this->success('保存成功') : $this->error('保存失败');
|
||||
}
|
||||
$this->assign('row', $row);
|
||||
return $this->fetch();
|
||||
}
|
||||
|
||||
}
|
||||
200
app/admin/controller/system/Admin.php
Normal file
200
app/admin/controller/system/Admin.php
Normal file
@@ -0,0 +1,200 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\controller\system;
|
||||
|
||||
use app\admin\model\SystemAdmin;
|
||||
use app\admin\service\TriggerService;
|
||||
use app\common\constants\AdminConstant;
|
||||
use app\common\controller\AdminController;
|
||||
use app\admin\service\annotation\ControllerAnnotation;
|
||||
use app\admin\service\annotation\NodeAnotation;
|
||||
use think\App;
|
||||
|
||||
/**
|
||||
* Class Admin
|
||||
* @package app\admin\controller\system
|
||||
* @ControllerAnnotation(title="管理员管理")
|
||||
*/
|
||||
class Admin extends AdminController
|
||||
{
|
||||
|
||||
use \app\admin\traits\Curd;
|
||||
|
||||
protected array $sort = [
|
||||
'sort' => 'desc',
|
||||
'id' => 'desc',
|
||||
];
|
||||
|
||||
public function __construct(App $app)
|
||||
{
|
||||
parent::__construct($app);
|
||||
$this->model = new SystemAdmin();
|
||||
$this->assign('auth_list', $this->model->getAuthList());
|
||||
}
|
||||
|
||||
/**
|
||||
* @NodeAnotation(title="列表")
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
if ($this->request->isAjax()) {
|
||||
if (input('selectFields')) {
|
||||
return $this->selectList();
|
||||
}
|
||||
list($page, $limit, $where) = $this->buildTableParams();
|
||||
$count = $this->model
|
||||
->where($where)
|
||||
->count();
|
||||
$list = $this->model
|
||||
->withoutField('password')
|
||||
->where($where)
|
||||
->page($page, $limit)
|
||||
->order($this->sort)
|
||||
->select();
|
||||
$data = [
|
||||
'code' => 0,
|
||||
'msg' => '',
|
||||
'count' => $count,
|
||||
'data' => $list,
|
||||
];
|
||||
return json($data);
|
||||
}
|
||||
return $this->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* @NodeAnotation(title="添加")
|
||||
*/
|
||||
public function add()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$post = $this->request->post();
|
||||
$authIds = $this->request->post('auth_ids', []);
|
||||
$post['auth_ids'] = implode(',', array_keys($authIds));
|
||||
$rule = [];
|
||||
$this->validate($post, $rule);
|
||||
try {
|
||||
$save = $this->model->save($post);
|
||||
} catch (\Exception $e) {
|
||||
$this->error('保存失败');
|
||||
}
|
||||
$save ? $this->success('保存成功') : $this->error('保存失败');
|
||||
}
|
||||
return $this->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* @NodeAnotation(title="编辑")
|
||||
*/
|
||||
public function edit($id)
|
||||
{
|
||||
$row = $this->model->find($id);
|
||||
empty($row) && $this->error('数据不存在');
|
||||
if ($this->request->isPost()) {
|
||||
$post = $this->request->post();
|
||||
$authIds = $this->request->post('auth_ids', []);
|
||||
$post['auth_ids'] = implode(',', array_keys($authIds));
|
||||
$rule = [];
|
||||
$this->validate($post, $rule);
|
||||
if (isset($row['password'])) {
|
||||
unset($row['password']);
|
||||
}
|
||||
try {
|
||||
$save = $row->save($post);
|
||||
TriggerService::updateMenu($id);
|
||||
} catch (\Exception $e) {
|
||||
$this->error('保存失败');
|
||||
}
|
||||
$save ? $this->success('保存成功') : $this->error('保存失败');
|
||||
}
|
||||
$row->auth_ids = explode(',', $row->auth_ids ?: '');
|
||||
$this->assign('row', $row);
|
||||
return $this->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* @NodeAnotation(title="编辑")
|
||||
*/
|
||||
public function password($id)
|
||||
{
|
||||
$row = $this->model->find($id);
|
||||
empty($row) && $this->error('数据不存在');
|
||||
if ($this->request->isAjax()) {
|
||||
$post = $this->request->post();
|
||||
$rule = [
|
||||
'password|登录密码' => 'require',
|
||||
'password_again|确认密码' => 'require',
|
||||
];
|
||||
$this->validate($post, $rule);
|
||||
if ($post['password'] != $post['password_again']) {
|
||||
$this->error('两次密码输入不一致');
|
||||
}
|
||||
try {
|
||||
$save = $row->save([
|
||||
'password' => password($post['password']),
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
$this->error('保存失败');
|
||||
}
|
||||
$save ? $this->success('保存成功') : $this->error('保存失败');
|
||||
}
|
||||
$row->auth_ids = explode(',', $row->auth_ids);
|
||||
$this->assign('row', $row);
|
||||
return $this->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* @NodeAnotation(title="删除")
|
||||
*/
|
||||
public function delete($id)
|
||||
{
|
||||
$this->checkPostRequest();
|
||||
$row = $this->model->whereIn('id', $id)->select();
|
||||
$row->isEmpty() && $this->error('数据不存在');
|
||||
$id == AdminConstant::SUPER_ADMIN_ID && $this->error('超级管理员不允许修改');
|
||||
if (is_array($id)) {
|
||||
if (in_array(AdminConstant::SUPER_ADMIN_ID, $id)) {
|
||||
$this->error('超级管理员不允许修改');
|
||||
}
|
||||
}
|
||||
try {
|
||||
$save = $row->delete();
|
||||
} catch (\Exception $e) {
|
||||
$this->error('删除失败');
|
||||
}
|
||||
$save ? $this->success('删除成功') : $this->error('删除失败');
|
||||
}
|
||||
|
||||
/**
|
||||
* @NodeAnotation(title="属性修改")
|
||||
*/
|
||||
public function modify()
|
||||
{
|
||||
$this->checkPostRequest();
|
||||
$post = $this->request->post();
|
||||
$rule = [
|
||||
'id|ID' => 'require',
|
||||
'field|字段' => 'require',
|
||||
'value|值' => 'require',
|
||||
];
|
||||
$this->validate($post, $rule);
|
||||
if (!in_array($post['field'], $this->allowModifyFields)) {
|
||||
$this->error('该字段不允许修改:' . $post['field']);
|
||||
}
|
||||
if ($post['id'] == AdminConstant::SUPER_ADMIN_ID && $post['field'] == 'status') {
|
||||
$this->error('超级管理员状态不允许修改');
|
||||
}
|
||||
$row = $this->model->find($post['id']);
|
||||
empty($row) && $this->error('数据不存在');
|
||||
try {
|
||||
$row->save([
|
||||
$post['field'] => $post['value'],
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
$this->success('保存成功');
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
80
app/admin/controller/system/Auth.php
Normal file
80
app/admin/controller/system/Auth.php
Normal file
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\controller\system;
|
||||
|
||||
use app\admin\model\SystemAuth;
|
||||
use app\admin\model\SystemAuthNode;
|
||||
use app\admin\service\TriggerService;
|
||||
use app\common\controller\AdminController;
|
||||
use app\admin\service\annotation\ControllerAnnotation;
|
||||
use app\admin\service\annotation\NodeAnotation;
|
||||
use think\App;
|
||||
|
||||
/**
|
||||
* @ControllerAnnotation(title="角色权限管理")
|
||||
* Class Auth
|
||||
* @package app\admin\controller\system
|
||||
*/
|
||||
class Auth extends AdminController
|
||||
{
|
||||
|
||||
use \app\admin\traits\Curd;
|
||||
|
||||
protected array $sort = [
|
||||
'sort' => 'desc',
|
||||
'id' => 'desc',
|
||||
];
|
||||
|
||||
public function __construct(App $app)
|
||||
{
|
||||
parent::__construct($app);
|
||||
$this->model = new SystemAuth();
|
||||
}
|
||||
|
||||
/**
|
||||
* @NodeAnotation(title="授权")
|
||||
*/
|
||||
public function authorize($id)
|
||||
{
|
||||
$row = $this->model->find($id);
|
||||
empty($row) && $this->error('数据不存在');
|
||||
if ($this->request->isAjax()) {
|
||||
$list = $this->model->getAuthorizeNodeListByAdminId($id);
|
||||
$this->success('获取成功', $list);
|
||||
}
|
||||
$this->assign('row', $row);
|
||||
return $this->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* @NodeAnotation(title="授权保存")
|
||||
*/
|
||||
public function saveAuthorize()
|
||||
{
|
||||
$this->checkPostRequest();
|
||||
$id = $this->request->post('id');
|
||||
$node = $this->request->post('node', "[]");
|
||||
$node = json_decode($node, true);
|
||||
$row = $this->model->find($id);
|
||||
empty($row) && $this->error('数据不存在');
|
||||
try {
|
||||
$authNode = new SystemAuthNode();
|
||||
$authNode->where('auth_id', $id)->delete();
|
||||
if (!empty($node)) {
|
||||
$saveAll = [];
|
||||
foreach ($node as $vo) {
|
||||
$saveAll[] = [
|
||||
'auth_id' => $id,
|
||||
'node_id' => $vo,
|
||||
];
|
||||
}
|
||||
$authNode->saveAll($saveAll);
|
||||
}
|
||||
TriggerService::updateMenu();
|
||||
} catch (\Exception $e) {
|
||||
$this->error('保存失败');
|
||||
}
|
||||
$this->success('保存成功');
|
||||
}
|
||||
|
||||
}
|
||||
57
app/admin/controller/system/Config.php
Normal file
57
app/admin/controller/system/Config.php
Normal file
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\controller\system;
|
||||
|
||||
use app\admin\model\SystemConfig;
|
||||
use app\admin\service\TriggerService;
|
||||
use app\common\controller\AdminController;
|
||||
use app\admin\service\annotation\ControllerAnnotation;
|
||||
use app\admin\service\annotation\NodeAnotation;
|
||||
use think\App;
|
||||
|
||||
/**
|
||||
* Class Config
|
||||
* @package app\admin\controller\system
|
||||
* @ControllerAnnotation(title="系统配置管理")
|
||||
*/
|
||||
class Config extends AdminController
|
||||
{
|
||||
|
||||
public function __construct(App $app)
|
||||
{
|
||||
parent::__construct($app);
|
||||
$this->model = new SystemConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* @NodeAnotation(title="列表")
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return $this->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* @NodeAnotation(title="保存")
|
||||
*/
|
||||
public function save()
|
||||
{
|
||||
$this->checkPostRequest();
|
||||
$post = $this->request->post();
|
||||
try {
|
||||
foreach ($post as $key => $val) {
|
||||
$this->model
|
||||
->where('name', $key)
|
||||
->update([
|
||||
'value' => $val,
|
||||
]);
|
||||
}
|
||||
TriggerService::updateMenu();
|
||||
TriggerService::updateSysconfig();
|
||||
} catch (\Exception $e) {
|
||||
$this->error('保存失败');
|
||||
}
|
||||
$this->success('保存成功');
|
||||
}
|
||||
|
||||
}
|
||||
66
app/admin/controller/system/Log.php
Normal file
66
app/admin/controller/system/Log.php
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\controller\system;
|
||||
|
||||
use app\admin\model\SystemLog;
|
||||
use app\common\controller\AdminController;
|
||||
use app\admin\service\annotation\ControllerAnnotation;
|
||||
use app\admin\service\annotation\NodeAnotation;
|
||||
use think\App;
|
||||
|
||||
/**
|
||||
* @ControllerAnnotation(title="操作日志管理")
|
||||
* Class Auth
|
||||
* @package app\admin\controller\system
|
||||
*/
|
||||
class Log extends AdminController
|
||||
{
|
||||
|
||||
public function __construct(App $app)
|
||||
{
|
||||
parent::__construct($app);
|
||||
$this->model = new SystemLog();
|
||||
}
|
||||
|
||||
/**
|
||||
* @NodeAnotation(title="列表")
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
if ($this->request->isAjax()) {
|
||||
if (input('selectFields')) {
|
||||
return $this->selectList();
|
||||
}
|
||||
[$page, $limit, $where, $excludeFields] = $this->buildTableParams(['month']);
|
||||
|
||||
$month = (isset($excludeFields['month']) && !empty($excludeFields['month']))
|
||||
? date('Ym',strtotime($excludeFields['month']))
|
||||
: date('Ym');
|
||||
|
||||
// todo TP6框架有一个BUG,非模型名与表名不对应时(name属性自定义),withJoin生成的sql有问题
|
||||
|
||||
$count = $this->model
|
||||
->setMonth($month)
|
||||
->with('admin')
|
||||
->where($where)
|
||||
->select();
|
||||
$list = $this->model
|
||||
->setMonth($month)
|
||||
->with('admin')
|
||||
->where($where)
|
||||
->page($page, $limit)
|
||||
->order($this->sort)
|
||||
->select();
|
||||
|
||||
$data = [
|
||||
'code' => 0,
|
||||
'msg' => '',
|
||||
'count' => $count,
|
||||
'data' => $list,
|
||||
];
|
||||
return json($data);
|
||||
}
|
||||
return $this->fetch();
|
||||
}
|
||||
|
||||
}
|
||||
207
app/admin/controller/system/Menu.php
Normal file
207
app/admin/controller/system/Menu.php
Normal file
@@ -0,0 +1,207 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\controller\system;
|
||||
|
||||
use app\admin\model\SystemMenu;
|
||||
use app\admin\model\SystemNode;
|
||||
use app\admin\service\TriggerService;
|
||||
use app\admin\traits\Curd;
|
||||
use app\common\constants\MenuConstant;
|
||||
use app\admin\service\annotation\ControllerAnnotation;
|
||||
use app\admin\service\annotation\NodeAnotation;
|
||||
use app\common\controller\AdminController;
|
||||
use think\App;
|
||||
|
||||
/**
|
||||
* Class Menu
|
||||
* @package app\admin\controller\system
|
||||
* @ControllerAnnotation(title="菜单管理",auth=true)
|
||||
*/
|
||||
class Menu extends AdminController
|
||||
{
|
||||
|
||||
use Curd;
|
||||
|
||||
protected array $sort = [
|
||||
'sort' => 'desc',
|
||||
'id' => 'asc',
|
||||
];
|
||||
|
||||
public function __construct(App $app)
|
||||
{
|
||||
parent::__construct($app);
|
||||
$this->model = new SystemMenu();
|
||||
}
|
||||
|
||||
/**
|
||||
* @NodeAnotation(title="列表")
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
if ($this->request->isAjax()) {
|
||||
if (input('selectFields')) {
|
||||
return $this->selectList();
|
||||
}
|
||||
$count = $this->model->count();
|
||||
$list = $this->model->order($this->sort)->select();
|
||||
$data = [
|
||||
'code' => 0,
|
||||
'msg' => '',
|
||||
'count' => $count,
|
||||
'data' => $list,
|
||||
];
|
||||
return json($data);
|
||||
}
|
||||
return $this->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* @NodeAnotation(title="添加")
|
||||
*/
|
||||
public function add($id = null)
|
||||
{
|
||||
$homeId = $this->model->where(['pid' => MenuConstant::HOME_PID,])->value('id');
|
||||
if ($id == $homeId) {
|
||||
$this->error('首页不能添加子菜单');
|
||||
}
|
||||
if ($this->request->isPost()) {
|
||||
$post = $this->request->post();
|
||||
$rule = [
|
||||
'pid|上级菜单' => 'require',
|
||||
'title|菜单名称' => 'require',
|
||||
'icon|菜单图标' => 'require',
|
||||
];
|
||||
$this->validate($post, $rule);
|
||||
try {
|
||||
$save = $this->model->save($post);
|
||||
} catch (\Exception $e) {
|
||||
$this->error('保存失败');
|
||||
}
|
||||
if ($save) {
|
||||
TriggerService::updateMenu();
|
||||
$this->success('保存成功');
|
||||
} else {
|
||||
$this->error('保存失败');
|
||||
}
|
||||
}
|
||||
$pidMenuList = $this->model->getPidMenuList();
|
||||
$this->assign('id', $id);
|
||||
$this->assign('pidMenuList', $pidMenuList);
|
||||
return $this->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* @NodeAnotation(title="编辑")
|
||||
*/
|
||||
public function edit($id)
|
||||
{
|
||||
$row = $this->model->find($id);
|
||||
empty($row) && $this->error('数据不存在');
|
||||
if ($this->request->isPost()) {
|
||||
$post = $this->request->post();
|
||||
$rule = [
|
||||
'pid|上级菜单' => 'require',
|
||||
'title|菜单名称' => 'require',
|
||||
'icon|菜单图标' => 'require',
|
||||
];
|
||||
$this->validate($post, $rule);
|
||||
if ($row->pid == MenuConstant::HOME_PID) $post['pid'] = MenuConstant::HOME_PID;
|
||||
try {
|
||||
$save = $row->save($post);
|
||||
} catch (\Exception $e) {
|
||||
$this->error('保存失败');
|
||||
}
|
||||
if (!empty($save)) {
|
||||
TriggerService::updateMenu();
|
||||
$this->success('保存成功');
|
||||
} else {
|
||||
$this->error('保存失败');
|
||||
}
|
||||
}
|
||||
$pidMenuList = $this->model->getPidMenuList();
|
||||
$this->assign([
|
||||
'id' => $id,
|
||||
'pidMenuList' => $pidMenuList,
|
||||
'row' => $row,
|
||||
]);
|
||||
return $this->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* @NodeAnotation(title="删除")
|
||||
*/
|
||||
public function delete($id)
|
||||
{
|
||||
$this->checkPostRequest();
|
||||
$row = $this->model->whereIn('id', $id)->select();
|
||||
empty($row) && $this->error('数据不存在');
|
||||
try {
|
||||
$save = $row->delete();
|
||||
} catch (\Exception $e) {
|
||||
$this->error('删除失败');
|
||||
}
|
||||
if ($save) {
|
||||
TriggerService::updateMenu();
|
||||
$this->success('删除成功');
|
||||
} else {
|
||||
$this->error('删除失败');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @NodeAnotation(title="属性修改")
|
||||
*/
|
||||
public function modify()
|
||||
{
|
||||
$this->checkPostRequest();
|
||||
$post = $this->request->post();
|
||||
$rule = [
|
||||
'id|ID' => 'require',
|
||||
'field|字段' => 'require',
|
||||
'value|值' => 'require',
|
||||
];
|
||||
$this->validate($post, $rule);
|
||||
$row = $this->model->find($post['id']);
|
||||
if (!$row) {
|
||||
$this->error('数据不存在');
|
||||
}
|
||||
if (!in_array($post['field'], $this->allowModifyFields)) {
|
||||
$this->error('该字段不允许修改:' . $post['field']);
|
||||
}
|
||||
$homeId = $this->model
|
||||
->where([
|
||||
'pid' => MenuConstant::HOME_PID,
|
||||
])
|
||||
->value('id');
|
||||
if ($post['id'] == $homeId && $post['field'] == 'status') {
|
||||
$this->error('首页状态不允许关闭');
|
||||
}
|
||||
try {
|
||||
$row->save([
|
||||
$post['field'] => $post['value'],
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
TriggerService::updateMenu();
|
||||
$this->success('保存成功');
|
||||
}
|
||||
|
||||
/**
|
||||
* @NodeAnotation(title="添加菜单提示")
|
||||
*/
|
||||
public function getMenuTips()
|
||||
{
|
||||
$node = input('get.keywords');
|
||||
$list = SystemNode::whereLike('node', "%{$node}%")
|
||||
->field('node,title')
|
||||
->limit(10)
|
||||
->select();
|
||||
return json([
|
||||
'code' => 0,
|
||||
'content' => $list,
|
||||
'type' => 'success',
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
113
app/admin/controller/system/Node.php
Normal file
113
app/admin/controller/system/Node.php
Normal file
@@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\controller\system;
|
||||
|
||||
use app\admin\model\SystemNode;
|
||||
use app\admin\service\TriggerService;
|
||||
use app\common\controller\AdminController;
|
||||
use app\admin\service\annotation\ControllerAnnotation;
|
||||
use app\admin\service\annotation\NodeAnotation;
|
||||
use app\admin\service\NodeService;
|
||||
use think\App;
|
||||
|
||||
/**
|
||||
* @ControllerAnnotation(title="系统节点管理")
|
||||
* Class Node
|
||||
* @package app\admin\controller\system
|
||||
*/
|
||||
class Node extends AdminController
|
||||
{
|
||||
|
||||
use \app\admin\traits\Curd;
|
||||
|
||||
public function __construct(App $app)
|
||||
{
|
||||
parent::__construct($app);
|
||||
$this->model = new SystemNode();
|
||||
}
|
||||
|
||||
/**
|
||||
* @NodeAnotation(title="列表")
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
if ($this->request->isAjax()) {
|
||||
if (input('selectFields')) {
|
||||
return $this->selectList();
|
||||
}
|
||||
$count = $this->model
|
||||
->count();
|
||||
$list = $this->model
|
||||
->getNodeTreeList();
|
||||
$data = [
|
||||
'code' => 0,
|
||||
'msg' => '',
|
||||
'count' => $count,
|
||||
'data' => $list,
|
||||
];
|
||||
return json($data);
|
||||
}
|
||||
return $this->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* @NodeAnotation(title="系统节点更新")
|
||||
*/
|
||||
public function refreshNode($force = 0)
|
||||
{
|
||||
|
||||
$this->checkPostRequest();
|
||||
$nodeList = (new NodeService())->getNodelist();
|
||||
empty($nodeList) && $this->error('暂无需要更新的系统节点');
|
||||
$model = new SystemNode();
|
||||
|
||||
try {
|
||||
if ($force == 1) {
|
||||
$updateNodeList = $model->whereIn('node', array_column($nodeList, 'node'))->select();
|
||||
$formatNodeList = array_format_key($nodeList, 'node');
|
||||
foreach ($updateNodeList as $vo) {
|
||||
isset($formatNodeList[$vo['node']])
|
||||
&& $model->where('id', $vo['id'])->update([
|
||||
'title' => $formatNodeList[$vo['node']]['title'],
|
||||
'is_auth' => $formatNodeList[$vo['node']]['is_auth'],
|
||||
]);
|
||||
}
|
||||
}
|
||||
$existNodeList = $model->field('node,title,type,is_auth')->select();
|
||||
foreach ($nodeList as $key => $vo) {
|
||||
foreach ($existNodeList as $v) {
|
||||
if ($vo['node'] == $v->node) {
|
||||
unset($nodeList[$key]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
$model->saveAll($nodeList);
|
||||
TriggerService::updateNode();
|
||||
} catch (\Exception $e) {
|
||||
$this->error('节点更新失败');
|
||||
}
|
||||
$this->success('节点更新成功');
|
||||
}
|
||||
|
||||
/**
|
||||
* @NodeAnotation(title="清除失效节点")
|
||||
*/
|
||||
public function clearNode()
|
||||
{
|
||||
$this->checkPostRequest();
|
||||
$nodeList = (new NodeService())->getNodelist();
|
||||
$model = new SystemNode();
|
||||
try {
|
||||
$existNodeList = $model->field('id,node,title,type,is_auth')->select()->toArray();
|
||||
$formatNodeList = array_format_key($nodeList, 'node');
|
||||
foreach ($existNodeList as $vo) {
|
||||
!isset($formatNodeList[$vo['node']]) && $model->where('id', $vo['id'])->delete();
|
||||
}
|
||||
TriggerService::updateNode();
|
||||
} catch (\Exception $e) {
|
||||
$this->error('节点更新失败');
|
||||
}
|
||||
$this->success('节点更新成功');
|
||||
}
|
||||
}
|
||||
33
app/admin/controller/system/Quick.php
Normal file
33
app/admin/controller/system/Quick.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\controller\system;
|
||||
|
||||
|
||||
use app\admin\model\SystemQuick;
|
||||
use app\common\controller\AdminController;
|
||||
use app\admin\service\annotation\ControllerAnnotation;
|
||||
use app\admin\service\annotation\NodeAnotation;
|
||||
use think\App;
|
||||
|
||||
/**
|
||||
* @ControllerAnnotation(title="快捷入口管理")
|
||||
* Class Quick
|
||||
* @package app\admin\controller\system
|
||||
*/
|
||||
class Quick extends AdminController
|
||||
{
|
||||
|
||||
use \app\admin\traits\Curd;
|
||||
|
||||
protected array $sort = [
|
||||
'sort' => 'desc',
|
||||
'id' => 'desc',
|
||||
];
|
||||
|
||||
public function __construct(App $app)
|
||||
{
|
||||
parent::__construct($app);
|
||||
$this->model = new SystemQuick();
|
||||
}
|
||||
|
||||
}
|
||||
27
app/admin/controller/system/Uploadfile.php
Normal file
27
app/admin/controller/system/Uploadfile.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\controller\system;
|
||||
|
||||
use app\admin\model\SystemUploadfile;
|
||||
use app\common\controller\AdminController;
|
||||
use app\admin\service\annotation\ControllerAnnotation;
|
||||
use app\admin\service\annotation\NodeAnotation;
|
||||
use think\App;
|
||||
|
||||
/**
|
||||
* @ControllerAnnotation(title="上传文件管理")
|
||||
* Class Uploadfile
|
||||
* @package app\admin\controller\system
|
||||
*/
|
||||
class Uploadfile extends AdminController
|
||||
{
|
||||
|
||||
use \app\admin\traits\Curd;
|
||||
|
||||
public function __construct(App $app)
|
||||
{
|
||||
parent::__construct($app);
|
||||
$this->model = new SystemUploadfile();
|
||||
}
|
||||
|
||||
}
|
||||
21
app/admin/event.php
Normal file
21
app/admin/event.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
// 事件定义文件
|
||||
return [
|
||||
'bind' => [
|
||||
],
|
||||
|
||||
'listen' => [
|
||||
'AppInit' => [
|
||||
\app\admin\listener\ViewInitListener::class,
|
||||
],
|
||||
'HttpRun' => [
|
||||
\app\admin\listener\ViewInitListener::class,
|
||||
],
|
||||
'HttpEnd' => [],
|
||||
'LogLevel' => [],
|
||||
'LogWrite' => [],
|
||||
],
|
||||
|
||||
'subscribe' => [
|
||||
],
|
||||
];
|
||||
21
app/admin/middleware.php
Normal file
21
app/admin/middleware.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
// 全局中间件定义文件
|
||||
return [
|
||||
|
||||
// Session初始化
|
||||
\think\middleware\SessionInit::class,
|
||||
|
||||
// 系统操作日志
|
||||
\app\admin\middleware\SystemLog::class,
|
||||
|
||||
// Csrf安全校验
|
||||
\app\admin\middleware\CsrfMiddleware::class,
|
||||
|
||||
// 后台视图初始化
|
||||
// \app\admin\middleware\ViewInit::class,
|
||||
|
||||
// 检测用户是否登录
|
||||
// \app\admin\middleware\CheckAdmin::class,
|
||||
|
||||
|
||||
];
|
||||
57
app/admin/middleware/CheckAdmin.php
Normal file
57
app/admin/middleware/CheckAdmin.php
Normal file
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\middleware;
|
||||
|
||||
use app\common\service\AuthService;
|
||||
use think\Request;
|
||||
|
||||
/**
|
||||
* @deprecated 废弃,新版TP不支持在中间件获取控制器相关信息
|
||||
* 检测用户登录和节点权限
|
||||
* Class CheckAdmin
|
||||
* @package app\admin\middleware
|
||||
*/
|
||||
class CheckAdmin
|
||||
{
|
||||
|
||||
use \app\common\traits\JumpTrait;
|
||||
|
||||
public function handle(Request $request, \Closure $next)
|
||||
{
|
||||
$adminConfig = config('admin');
|
||||
$adminId = session('admin.id');
|
||||
$expireTime = session('admin.expire_time');
|
||||
/** @var AuthService $authService */
|
||||
$authService = app(AuthService::class, ['adminId' => $adminId]);
|
||||
$currentNode = $authService->getCurrentNode();
|
||||
$currentController = parse_name($request->controller());
|
||||
|
||||
// 验证登录
|
||||
if (!in_array($currentController, $adminConfig['no_login_controller']) &&
|
||||
!in_array($currentNode, $adminConfig['no_login_node'])) {
|
||||
empty($adminId) && $this->error('请先登录后台', [], __url('admin/login/index'));
|
||||
|
||||
// 判断是否登录过期
|
||||
if ($expireTime !== true && time() > $expireTime) {
|
||||
session('admin', null);
|
||||
$this->error('登录已过期,请重新登录', [], __url('admin/login/index'));
|
||||
}
|
||||
}
|
||||
|
||||
// 验证权限
|
||||
if (!in_array($currentController, $adminConfig['no_auth_controller']) &&
|
||||
!in_array($currentNode, $adminConfig['no_auth_node'])) {
|
||||
$check = $authService->checkNode($currentNode);
|
||||
!$check && $this->error('无权限访问');
|
||||
|
||||
// 判断是否为演示环境
|
||||
if(env('EASYADMIN.IS_DEMO', false) && $request->isPost()){
|
||||
$this->error('演示环境下不允许修改');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
}
|
||||
40
app/admin/middleware/CsrfMiddleware.php
Normal file
40
app/admin/middleware/CsrfMiddleware.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\middleware;
|
||||
|
||||
use app\Request;
|
||||
use CsrfVerify\drive\ThinkphpCache;
|
||||
use CsrfVerify\entity\CsrfVerifyEntity;
|
||||
use CsrfVerify\interfaces\CsrfVerifyInterface;
|
||||
use think\facade\Session;
|
||||
|
||||
class CsrfMiddleware
|
||||
{
|
||||
use \app\common\traits\JumpTrait;
|
||||
|
||||
public function handle(Request $request, \Closure $next)
|
||||
{
|
||||
if (env('EASYADMIN.IS_CSRF', true)) {
|
||||
if (in_array($request->method(), ['POST', 'DELETE'])) {
|
||||
// 跨域校验
|
||||
$refererUrl = $request->header('REFERER', null);
|
||||
$refererInfo = parse_url($refererUrl);
|
||||
$host = $request->host(true);
|
||||
if (!isset($refererInfo['host']) || $refererInfo['host'] != $host) {
|
||||
$this->error('当前请求不合法!');
|
||||
}
|
||||
|
||||
// CSRF校验
|
||||
// @todo 兼容CK编辑器上传功能
|
||||
$ckCsrfToken = $request->post('ckCsrfToken');
|
||||
$data = !empty($ckCsrfToken) ? ['__token__' => $ckCsrfToken] : [];
|
||||
$check = $request->checkToken('__token__', $data);
|
||||
if (!$check) {
|
||||
$this->error('请求验证失败,请重新刷新页面!');
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
67
app/admin/middleware/SystemLog.php
Normal file
67
app/admin/middleware/SystemLog.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\middleware;
|
||||
|
||||
use app\admin\service\SystemLogService;
|
||||
use app\Request;
|
||||
use app\admin\service\tool\CommonTool;
|
||||
use think\facade\Log;
|
||||
|
||||
/**
|
||||
* 系统操作日志中间件
|
||||
* Class SystemLog
|
||||
* @package app\admin\middleware
|
||||
*/
|
||||
class SystemLog
|
||||
{
|
||||
|
||||
/**
|
||||
* 敏感信息字段,日志记录时需要加密
|
||||
* @var array
|
||||
*/
|
||||
protected $sensitiveParams = [
|
||||
'password',
|
||||
'password_again',
|
||||
'phone',
|
||||
'mobile',
|
||||
];
|
||||
|
||||
public function handle(Request $request, \Closure $next)
|
||||
{
|
||||
$params = $request->param();
|
||||
if (isset($params['s'])) {
|
||||
unset($params['s']);
|
||||
}
|
||||
foreach ($params as $key => $val) {
|
||||
in_array($key, $this->sensitiveParams) && $params[$key] = "***********";
|
||||
}
|
||||
$method = strtolower($request->method());
|
||||
$url = $request->url();
|
||||
|
||||
trace([
|
||||
'url' => $url,
|
||||
'method' => $method,
|
||||
'params' => $params,
|
||||
],
|
||||
'requestDebugInfo'
|
||||
);
|
||||
|
||||
if ($request->isAjax()) {
|
||||
if (in_array($method, ['post', 'put', 'delete'])) {
|
||||
$ip = CommonTool::getRealIp();
|
||||
$data = [
|
||||
'admin_id' => session('admin.id'),
|
||||
'url' => $url,
|
||||
'method' => $method,
|
||||
'ip' => $ip,
|
||||
'content' => json_encode($params, JSON_UNESCAPED_UNICODE),
|
||||
'useragent' => $_SERVER['HTTP_USER_AGENT'],
|
||||
'create_time' => time(),
|
||||
];
|
||||
SystemLogService::instance()->save($data);
|
||||
}
|
||||
}
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
}
|
||||
47
app/admin/middleware/ViewInit.php
Normal file
47
app/admin/middleware/ViewInit.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\middleware;
|
||||
|
||||
use app\admin\service\ConfigService;
|
||||
use app\common\constants\AdminConstant;
|
||||
use think\App;
|
||||
use think\facade\Request;
|
||||
use think\facade\View;
|
||||
|
||||
/**
|
||||
* @deprecated 废弃,新版TP不支持在中间件获取控制器相关信息
|
||||
* Class ViewInit
|
||||
* @package app\admin\middleware
|
||||
*/
|
||||
class ViewInit
|
||||
{
|
||||
|
||||
public function handle(\app\Request $request, \Closure $next)
|
||||
{
|
||||
list($thisModule, $thisController, $thisAction) = [app('http')->getName(), Request::controller(), $request->action()];
|
||||
list($thisControllerArr, $jsPath) = [explode('.', $thisController), null];
|
||||
foreach ($thisControllerArr as $vo) {
|
||||
empty($jsPath) ? $jsPath = parse_name($vo) : $jsPath .= '/' . parse_name($vo);
|
||||
}
|
||||
$autoloadJs = file_exists(root_path('public')."static/{$thisModule}/js/{$jsPath}.js") ? true : false;
|
||||
$thisControllerJsPath = "{$thisModule}/js/{$jsPath}.js";
|
||||
$adminModuleName = config('app.admin_alias_name');
|
||||
$isSuperAdmin = session('admin.id') == AdminConstant::SUPER_ADMIN_ID ? true : false;
|
||||
$data = [
|
||||
'adminModuleName' => $adminModuleName,
|
||||
'thisController' => parse_name($thisController),
|
||||
'thisAction' => $thisAction,
|
||||
'thisRequest' => parse_name("{$thisModule}/{$thisController}/{$thisAction}"),
|
||||
'thisControllerJsPath' => "{$thisControllerJsPath}",
|
||||
'autoloadJs' => $autoloadJs,
|
||||
'isSuperAdmin' => $isSuperAdmin,
|
||||
'version' => env('APP_DEBUG') ? time() : ConfigService::getVersion(),
|
||||
];
|
||||
|
||||
View::assign($data);
|
||||
$request->adminModuleName = $adminModuleName;
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
13
app/admin/model/MallCate.php
Normal file
13
app/admin/model/MallCate.php
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\model;
|
||||
|
||||
|
||||
use app\common\model\TimeModel;
|
||||
|
||||
class MallCate extends TimeModel
|
||||
{
|
||||
|
||||
protected $deleteTime = 'delete_time';
|
||||
|
||||
}
|
||||
20
app/admin/model/MallGoods.php
Normal file
20
app/admin/model/MallGoods.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\model;
|
||||
|
||||
|
||||
use app\common\model\TimeModel;
|
||||
|
||||
class MallGoods extends TimeModel
|
||||
{
|
||||
|
||||
protected $table = "";
|
||||
|
||||
protected $deleteTime = 'delete_time';
|
||||
|
||||
public function cate()
|
||||
{
|
||||
return $this->belongsTo('app\admin\model\MallCate', 'cate_id', 'id');
|
||||
}
|
||||
|
||||
}
|
||||
21
app/admin/model/SystemAdmin.php
Normal file
21
app/admin/model/SystemAdmin.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\model;
|
||||
|
||||
|
||||
use app\common\model\TimeModel;
|
||||
|
||||
class SystemAdmin extends TimeModel
|
||||
{
|
||||
|
||||
protected $deleteTime = 'delete_time';
|
||||
|
||||
public function getAuthList()
|
||||
{
|
||||
$list = (new SystemAuth())
|
||||
->where('status', 1)
|
||||
->column('title', 'id');
|
||||
return $list;
|
||||
}
|
||||
|
||||
}
|
||||
53
app/admin/model/SystemAuth.php
Normal file
53
app/admin/model/SystemAuth.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\model;
|
||||
|
||||
use app\common\model\TimeModel;
|
||||
|
||||
class SystemAuth extends TimeModel
|
||||
{
|
||||
|
||||
protected $deleteTime = 'delete_time';
|
||||
|
||||
/**
|
||||
* 根据角色ID获取授权节点
|
||||
* @param $authId
|
||||
* @return array
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\DbException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
*/
|
||||
public function getAuthorizeNodeListByAdminId($authId)
|
||||
{
|
||||
$checkNodeList = (new SystemAuthNode())
|
||||
->where('auth_id', $authId)
|
||||
->column('node_id');
|
||||
$systemNode = new SystemNode();
|
||||
$nodelList = $systemNode
|
||||
->where('is_auth', 1)
|
||||
->field('id,node,title,type,is_auth')
|
||||
->select()
|
||||
->toArray();
|
||||
$newNodeList = [];
|
||||
foreach ($nodelList as $vo) {
|
||||
if ($vo['type'] == 1) {
|
||||
$vo = array_merge($vo, ['field' => 'node', 'spread' => true]);
|
||||
$vo['checked'] = false;
|
||||
$vo['title'] = "{$vo['title']}【{$vo['node']}】";
|
||||
$children = [];
|
||||
foreach ($nodelList as $v) {
|
||||
if ($v['type'] == 2 && strpos($v['node'], $vo['node'] . '/') !== false) {
|
||||
$v = array_merge($v, ['field' => 'node', 'spread' => true]);
|
||||
$v['checked'] = in_array($v['id'], $checkNodeList) ? true : false;
|
||||
$v['title'] = "{$v['title']}【{$v['node']}】";
|
||||
$children[] = $v;
|
||||
}
|
||||
}
|
||||
!empty($children) && $vo['children'] = $children;
|
||||
$newNodeList[] = $vo;
|
||||
}
|
||||
}
|
||||
return $newNodeList;
|
||||
}
|
||||
|
||||
}
|
||||
10
app/admin/model/SystemAuthNode.php
Normal file
10
app/admin/model/SystemAuthNode.php
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\model;
|
||||
|
||||
use app\common\model\TimeModel;
|
||||
|
||||
class SystemAuthNode extends TimeModel
|
||||
{
|
||||
|
||||
}
|
||||
10
app/admin/model/SystemConfig.php
Normal file
10
app/admin/model/SystemConfig.php
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\model;
|
||||
|
||||
use app\common\model\TimeModel;
|
||||
|
||||
class SystemConfig extends TimeModel
|
||||
{
|
||||
|
||||
}
|
||||
28
app/admin/model/SystemLog.php
Normal file
28
app/admin/model/SystemLog.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\model;
|
||||
|
||||
use app\common\model\TimeModel;
|
||||
|
||||
class SystemLog extends TimeModel
|
||||
{
|
||||
|
||||
public function __construct(array $data = [])
|
||||
{
|
||||
parent::__construct($data);
|
||||
$this->name = 'system_log_' . date('Ym');
|
||||
}
|
||||
|
||||
public function setMonth($month)
|
||||
{
|
||||
$this->name = 'system_log_' . $month;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function admin()
|
||||
{
|
||||
return $this->belongsTo('app\admin\model\SystemAdmin', 'admin_id', 'id');
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
58
app/admin/model/SystemMenu.php
Normal file
58
app/admin/model/SystemMenu.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\model;
|
||||
|
||||
use app\common\constants\MenuConstant;
|
||||
use app\common\model\TimeModel;
|
||||
|
||||
class SystemMenu extends TimeModel
|
||||
{
|
||||
|
||||
protected $deleteTime = 'delete_time';
|
||||
|
||||
public function getPidMenuList()
|
||||
{
|
||||
$list = $this->field('id,pid,title')
|
||||
->where([
|
||||
['pid', '<>', MenuConstant::HOME_PID],
|
||||
['status', '=', 1],
|
||||
])
|
||||
->select()
|
||||
->toArray();
|
||||
$pidMenuList = $this->buildPidMenu(0, $list);
|
||||
$pidMenuList = array_merge([[
|
||||
'id' => 0,
|
||||
'pid' => 0,
|
||||
'title' => '顶级菜单',
|
||||
]], $pidMenuList);
|
||||
return $pidMenuList;
|
||||
}
|
||||
|
||||
protected function buildPidMenu($pid, $list, $level = 0)
|
||||
{
|
||||
$newList = [];
|
||||
foreach ($list as $vo) {
|
||||
if ($vo['pid'] == $pid) {
|
||||
$level++;
|
||||
foreach ($newList as $v) {
|
||||
if ($vo['pid'] == $v['pid'] && isset($v['level'])) {
|
||||
$level = $v['level'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
$vo['level'] = $level;
|
||||
if ($level > 1) {
|
||||
$repeatString = " ";
|
||||
$markString = str_repeat("{$repeatString}├{$repeatString}", $level - 1);
|
||||
$vo['title'] = $markString . $vo['title'];
|
||||
}
|
||||
$newList[] = $vo;
|
||||
$childList = $this->buildPidMenu($vo['id'], $list, $level);
|
||||
!empty($childList) && $newList = array_merge($newList, $childList);
|
||||
}
|
||||
|
||||
}
|
||||
return $newList;
|
||||
}
|
||||
|
||||
}
|
||||
36
app/admin/model/SystemNode.php
Normal file
36
app/admin/model/SystemNode.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\model;
|
||||
|
||||
use app\common\model\TimeModel;
|
||||
|
||||
class SystemNode extends TimeModel
|
||||
{
|
||||
|
||||
public function getNodeTreeList()
|
||||
{
|
||||
$list = $this->select()->toArray();
|
||||
$list = $this->buildNodeTree($list);
|
||||
return $list;
|
||||
}
|
||||
|
||||
protected function buildNodeTree($list)
|
||||
{
|
||||
$newList = [];
|
||||
$repeatString = " ";
|
||||
foreach ($list as $vo) {
|
||||
if ($vo['type'] == 1) {
|
||||
$newList[] = $vo;
|
||||
foreach ($list as $v) {
|
||||
if ($v['type'] == 2 && strpos($v['node'], $vo['node'] . '/') !== false) {
|
||||
$v['node'] = "{$repeatString}├{$repeatString}" . $v['node'];
|
||||
$newList[] = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $newList;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
12
app/admin/model/SystemQuick.php
Normal file
12
app/admin/model/SystemQuick.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\model;
|
||||
|
||||
use app\common\model\TimeModel;
|
||||
|
||||
class SystemQuick extends TimeModel
|
||||
{
|
||||
|
||||
protected $deleteTime = 'delete_time';
|
||||
|
||||
}
|
||||
10
app/admin/model/SystemUploadfile.php
Normal file
10
app/admin/model/SystemUploadfile.php
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\model;
|
||||
|
||||
use app\common\model\TimeModel;
|
||||
|
||||
class SystemUploadfile extends TimeModel
|
||||
{
|
||||
|
||||
}
|
||||
21
app/admin/service/ConfigService.php
Normal file
21
app/admin/service/ConfigService.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\service;
|
||||
|
||||
use think\facade\Cache;
|
||||
|
||||
class ConfigService
|
||||
{
|
||||
|
||||
public static function getVersion()
|
||||
{
|
||||
$version = Cache('version');
|
||||
if (empty($version)) {
|
||||
$version = sysconfig('site', 'site_version');
|
||||
cache('site_version', $version);
|
||||
Cache::set('version', $version, 3600);
|
||||
}
|
||||
return $version;
|
||||
}
|
||||
|
||||
}
|
||||
24
app/admin/service/NodeService.php
Normal file
24
app/admin/service/NodeService.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\service;
|
||||
|
||||
|
||||
use app\admin\service\auth\Node;
|
||||
|
||||
class NodeService
|
||||
{
|
||||
|
||||
/**
|
||||
* 获取节点服务
|
||||
* @return array
|
||||
* @throws \Doctrine\Common\Annotations\AnnotationException
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
public function getNodelist()
|
||||
{
|
||||
$basePath = base_path() . 'admin' . DIRECTORY_SEPARATOR . 'controller';
|
||||
$baseNamespace = "app\admin\controller";
|
||||
$nodeList = (new Node($basePath, $baseNamespace))->getNodelist();
|
||||
return $nodeList;
|
||||
}
|
||||
}
|
||||
125
app/admin/service/SystemLogService.php
Normal file
125
app/admin/service/SystemLogService.php
Normal file
@@ -0,0 +1,125 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\service;
|
||||
|
||||
use think\facade\Db;
|
||||
use think\facade\Config;
|
||||
|
||||
/**
|
||||
* 系统日志表
|
||||
* Class SystemLogService
|
||||
* @package app\admin\service
|
||||
*/
|
||||
class SystemLogService
|
||||
{
|
||||
|
||||
/**
|
||||
* 当前实例
|
||||
* @var object
|
||||
*/
|
||||
protected static $instance;
|
||||
|
||||
/**
|
||||
* 表前缀
|
||||
* @var string
|
||||
*/
|
||||
protected $tablePrefix;
|
||||
|
||||
/**
|
||||
* 表后缀
|
||||
* @var string
|
||||
*/
|
||||
protected $tableSuffix;
|
||||
|
||||
/**
|
||||
* 表名
|
||||
* @var string
|
||||
*/
|
||||
protected $tableName;
|
||||
|
||||
/**
|
||||
* 构造方法
|
||||
* SystemLogService constructor.
|
||||
*/
|
||||
protected function __construct()
|
||||
{
|
||||
$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
|
||||
*/
|
||||
public static function instance()
|
||||
{
|
||||
if (is_null(self::$instance)) {
|
||||
self::$instance = new static();
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 保存数据
|
||||
* @param $data
|
||||
* @return bool|string
|
||||
*/
|
||||
public function save($data)
|
||||
{
|
||||
Db::startTrans();
|
||||
try {
|
||||
$this->detectTable();
|
||||
Db::table($this->tableName)->insert($data);
|
||||
Db::commit();
|
||||
} catch (\Exception $e) {
|
||||
Db::rollback();
|
||||
return $e->getMessage();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测数据表
|
||||
* @return bool
|
||||
*/
|
||||
protected function detectTable()
|
||||
{
|
||||
$check = Db::query("show tables like '{$this->tableName}'");
|
||||
if (empty($check)) {
|
||||
$sql = $this->getCreateSql();
|
||||
Db::execute($sql);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getAllTableList()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据后缀获取创建表的sql
|
||||
* @return string
|
||||
*/
|
||||
protected function getCreateSql()
|
||||
{
|
||||
return <<<EOT
|
||||
CREATE TABLE `{$this->tableName}` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
|
||||
`admin_id` int(10) unsigned DEFAULT '0' COMMENT '管理员ID',
|
||||
`url` varchar(1500) NOT NULL DEFAULT '' COMMENT '操作页面',
|
||||
`method` varchar(50) NOT NULL COMMENT '请求方法',
|
||||
`title` varchar(100) DEFAULT '' COMMENT '日志标题',
|
||||
`content` text NOT NULL COMMENT '内容',
|
||||
`ip` varchar(50) NOT NULL DEFAULT '' COMMENT 'IP',
|
||||
`useragent` varchar(255) DEFAULT '' COMMENT 'User-Agent',
|
||||
`create_time` int(10) DEFAULT NULL COMMENT '操作时间',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=630 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='后台操作日志表 - {$this->tableSuffix}';
|
||||
EOT;
|
||||
}
|
||||
|
||||
}
|
||||
50
app/admin/service/TriggerService.php
Normal file
50
app/admin/service/TriggerService.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\service;
|
||||
|
||||
use think\facade\Cache;
|
||||
|
||||
class TriggerService
|
||||
{
|
||||
|
||||
/**
|
||||
* 更新菜单缓存
|
||||
* @param null $adminId
|
||||
* @return bool
|
||||
*/
|
||||
public static function updateMenu($adminId = null)
|
||||
{
|
||||
if(empty($adminId)){
|
||||
Cache::tag('initAdmin')->clear();
|
||||
}else{
|
||||
Cache::delete('initAdmin_' . $adminId);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新节点缓存
|
||||
* @param null $adminId
|
||||
* @return bool
|
||||
*/
|
||||
public static function updateNode($adminId = null)
|
||||
{
|
||||
if(empty($adminId)){
|
||||
Cache::tag('authNode')->clear();
|
||||
}else{
|
||||
Cache::delete('allAuthNode_' . $adminId);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新系统设置缓存
|
||||
* @return bool
|
||||
*/
|
||||
public static function updateSysconfig()
|
||||
{
|
||||
Cache::tag('sysconfig')->clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
39
app/admin/service/annotation/ControllerAnnotation.php
Normal file
39
app/admin/service/annotation/ControllerAnnotation.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\service\annotation;
|
||||
|
||||
use Doctrine\Common\Annotations\Annotation\Attributes;
|
||||
use Doctrine\Common\Annotations\Annotation\Required;
|
||||
use Doctrine\Common\Annotations\Annotation\Target;
|
||||
|
||||
/**
|
||||
* Class ControllerAnnotation
|
||||
*
|
||||
* @Annotation
|
||||
* @Target("CLASS")
|
||||
* @Attributes({
|
||||
* @Attribute("title", type="string"),
|
||||
* })
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
final class ControllerAnnotation
|
||||
{
|
||||
|
||||
/**
|
||||
* Route group prefix for the controller
|
||||
*
|
||||
* @Required()
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $title = '';
|
||||
|
||||
/**
|
||||
* 是否开启权限控制
|
||||
* @Enum({true,false})
|
||||
* @var bool
|
||||
*/
|
||||
public $auth = true;
|
||||
|
||||
}
|
||||
33
app/admin/service/annotation/NodeAnotation.php
Normal file
33
app/admin/service/annotation/NodeAnotation.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\service\annotation;
|
||||
|
||||
use Doctrine\Common\Annotations\Annotation\Attributes;
|
||||
|
||||
/**
|
||||
* 创建节点注解类
|
||||
*
|
||||
* @Annotation
|
||||
* @Target({"METHOD","CLASS"})
|
||||
* @Attributes({
|
||||
* @Attribute("time", type = "int")
|
||||
* })
|
||||
*/
|
||||
final class NodeAnotation
|
||||
{
|
||||
|
||||
/**
|
||||
* 节点名称
|
||||
* @Required()
|
||||
* @var string
|
||||
*/
|
||||
public $title;
|
||||
|
||||
/**
|
||||
* 是否开启权限控制
|
||||
* @Enum({true,false})
|
||||
* @var bool
|
||||
*/
|
||||
public $auth = true;
|
||||
|
||||
}
|
||||
145
app/admin/service/auth/Node.php
Normal file
145
app/admin/service/auth/Node.php
Normal file
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\service\auth;
|
||||
|
||||
use Doctrine\Common\Annotations\AnnotationReader;
|
||||
use Doctrine\Common\Annotations\AnnotationRegistry;
|
||||
use Doctrine\Common\Annotations\DocParser;
|
||||
use app\admin\service\annotation\ControllerAnnotation;
|
||||
use app\admin\service\annotation\NodeAnotation;
|
||||
use app\admin\service\tool\CommonTool;
|
||||
|
||||
/**
|
||||
* 节点处理类
|
||||
* Class Node
|
||||
* @package EasyAdmin\auth
|
||||
*/
|
||||
class Node
|
||||
{
|
||||
|
||||
/**
|
||||
* @var string 当前文件夹
|
||||
*/
|
||||
protected $basePath;
|
||||
|
||||
/**
|
||||
* @var string 命名空间前缀
|
||||
*/
|
||||
protected $baseNamespace;
|
||||
|
||||
/**
|
||||
* 构造方法
|
||||
* Node constructor.
|
||||
* @param string $basePath 读取的文件夹
|
||||
* @param string $baseNamespace 读取的命名空间前缀
|
||||
*/
|
||||
public function __construct($basePath, $baseNamespace)
|
||||
{
|
||||
$this->basePath = $basePath;
|
||||
$this->baseNamespace = $baseNamespace;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有节点
|
||||
* @return array
|
||||
* @throws \Doctrine\Common\Annotations\AnnotationException
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
public function getNodelist()
|
||||
{
|
||||
list($nodeList, $controllerList) = [[], $this->getControllerList()];
|
||||
|
||||
if (!empty($controllerList)) {
|
||||
AnnotationRegistry::registerLoader('class_exists');
|
||||
$parser = new DocParser();
|
||||
$parser->setIgnoreNotImportedAnnotations(true);
|
||||
$reader = new AnnotationReader($parser);
|
||||
|
||||
foreach ($controllerList as $controllerFormat => $controller) {
|
||||
|
||||
// 获取类和方法的注释信息
|
||||
$reflectionClass = new \ReflectionClass($controller);
|
||||
$methods = $reflectionClass->getMethods();
|
||||
$actionList = [];
|
||||
|
||||
// 遍历读取所有方法的注释的参数信息
|
||||
foreach ($methods as $method) {
|
||||
// 读取NodeAnotation的注解
|
||||
$nodeAnnotation = $reader->getMethodAnnotation($method, NodeAnotation::class);
|
||||
if (!empty($nodeAnnotation) && !empty($nodeAnnotation->title)) {
|
||||
$actionTitle = !empty($nodeAnnotation) && !empty($nodeAnnotation->title) ? $nodeAnnotation->title : null;
|
||||
$actionAuth = !empty($nodeAnnotation) && !empty($nodeAnnotation->auth) ? $nodeAnnotation->auth : false;
|
||||
$actionList[] = [
|
||||
'node' => $controllerFormat . '/' . $method->name,
|
||||
'title' => $actionTitle,
|
||||
'is_auth' => $actionAuth,
|
||||
'type' => 2,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// 方法非空才读取控制器注解
|
||||
if (!empty($actionList)) {
|
||||
// 读取Controller的注解
|
||||
$controllerAnnotation = $reader->getClassAnnotation($reflectionClass, ControllerAnnotation::class);
|
||||
$controllerTitle = !empty($controllerAnnotation) && !empty($controllerAnnotation->title) ? $controllerAnnotation->title : null;
|
||||
$controllerAuth = !empty($controllerAnnotation) && !empty($controllerAnnotation->auth) ? $controllerAnnotation->auth : false;
|
||||
$nodeList[] = [
|
||||
'node' => $controllerFormat,
|
||||
'title' => $controllerTitle,
|
||||
'is_auth' => $controllerAuth,
|
||||
'type' => 1,
|
||||
];
|
||||
$nodeList = array_merge($nodeList, $actionList);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return $nodeList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有控制器
|
||||
* @return array
|
||||
*/
|
||||
public function getControllerList()
|
||||
{
|
||||
return $this->readControllerFiles($this->basePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* 遍历读取控制器文件
|
||||
* @param $path
|
||||
* @return array
|
||||
*/
|
||||
protected function readControllerFiles($path)
|
||||
{
|
||||
list($list, $temp_list, $dirExplode) = [[], scandir($path), explode($this->basePath, $path)];
|
||||
$middleDir = isset($dirExplode[1]) && !empty($dirExplode[1]) ? str_replace('/', '\\', substr($dirExplode[1], 1)) . "\\" : '';
|
||||
|
||||
foreach ($temp_list as $file) {
|
||||
// 排除根目录和没有开启注解的模块
|
||||
if ($file == ".." || $file == ".") {
|
||||
continue;
|
||||
}
|
||||
if (is_dir($path . DIRECTORY_SEPARATOR . $file)) {
|
||||
// 子文件夹,进行递归
|
||||
$childFiles = $this->readControllerFiles($path . DIRECTORY_SEPARATOR . $file);
|
||||
$list = array_merge($childFiles, $list);
|
||||
} else {
|
||||
// 判断是不是控制器
|
||||
$fileExplodeArray = explode('.', $file);
|
||||
if (count($fileExplodeArray) != 2 || end($fileExplodeArray) != 'php') {
|
||||
continue;
|
||||
}
|
||||
// 根目录下的文件
|
||||
$className = str_replace('.php', '', $file);
|
||||
$controllerFormat = str_replace('\\', '.', $middleDir) . CommonTool::humpToLine(lcfirst($className));
|
||||
$list[$controllerFormat] = "{$this->baseNamespace}\\{$middleDir}" . $className;
|
||||
}
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
|
||||
}
|
||||
165
app/admin/service/console/CliEcho.php
Normal file
165
app/admin/service/console/CliEcho.php
Normal file
@@ -0,0 +1,165 @@
|
||||
<?php
|
||||
|
||||
namespace EasyAdmin\console;
|
||||
|
||||
class CliEcho
|
||||
{
|
||||
|
||||
private $foreground_colors = [];
|
||||
|
||||
private $background_colors = [];
|
||||
|
||||
private static $foregroundColors = [
|
||||
'black' => '0;30',
|
||||
'dark_gray' => '1;30',
|
||||
'blue' => '0;34',
|
||||
'light_blue' => '1;34',
|
||||
'green' => '0;32',
|
||||
'light_green' => '1;32',
|
||||
'cyan' => '0;36',
|
||||
'light_cyan' => '1;36',
|
||||
'red' => '0;31',
|
||||
'light_red' => '1;31',
|
||||
'purple' => '0;35',
|
||||
'light_purple' => '1;35',
|
||||
'brown' => '0;33',
|
||||
'yellow' => '1;33',
|
||||
'light_gray' => '0;37',
|
||||
'white' => '1;37',
|
||||
];
|
||||
|
||||
private static $backgroundColors = [
|
||||
'black' => '40',
|
||||
'red' => '41',
|
||||
'green' => '42',
|
||||
'yellow' => '43',
|
||||
'blue' => '44',
|
||||
'magenta' => '45',
|
||||
'cyan' => '46',
|
||||
'light_gray' => '47',
|
||||
];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
// Set up shell colors
|
||||
$this->foreground_colors['black'] = '0;30';
|
||||
$this->foreground_colors['dark_gray'] = '1;30';
|
||||
$this->foreground_colors['blue'] = '0;34';
|
||||
$this->foreground_colors['light_blue'] = '1;34';
|
||||
$this->foreground_colors['green'] = '0;32';
|
||||
$this->foreground_colors['light_green'] = '1;32';
|
||||
$this->foreground_colors['cyan'] = '0;36';
|
||||
$this->foreground_colors['light_cyan'] = '1;36';
|
||||
$this->foreground_colors['red'] = '0;31';
|
||||
$this->foreground_colors['light_red'] = '1;31';
|
||||
$this->foreground_colors['purple'] = '0;35';
|
||||
$this->foreground_colors['light_purple'] = '1;35';
|
||||
$this->foreground_colors['brown'] = '0;33';
|
||||
$this->foreground_colors['yellow'] = '1;33';
|
||||
$this->foreground_colors['light_gray'] = '0;37';
|
||||
$this->foreground_colors['white'] = '1;37';
|
||||
$this->background_colors['black'] = '40';
|
||||
$this->background_colors['red'] = '41';
|
||||
$this->background_colors['green'] = '42';
|
||||
$this->background_colors['yellow'] = '43';
|
||||
$this->background_colors['blue'] = '44';
|
||||
$this->background_colors['magenta'] = '45';
|
||||
$this->background_colors['cyan'] = '46';
|
||||
$this->background_colors['light_gray'] = '47';
|
||||
}
|
||||
|
||||
// Returns colored string
|
||||
public function getColoredString($string, $foreground_color = null, $background_color = null, $new_line = false)
|
||||
{
|
||||
$colored_string = '';
|
||||
// Check if given foreground color found
|
||||
if (isset($this->foreground_colors[$foreground_color])) {
|
||||
$colored_string .= "\033[".$this->foreground_colors[$foreground_color].'m';
|
||||
}
|
||||
// Check if given background color found
|
||||
if (isset($this->background_colors[$background_color])) {
|
||||
$colored_string .= "\033[".$this->background_colors[$background_color].'m';
|
||||
}
|
||||
// Add string and end coloring
|
||||
$colored_string .= $string."\033[0m";
|
||||
return $new_line ? $colored_string.PHP_EOL : $colored_string;
|
||||
}
|
||||
|
||||
// Returns all foreground color names
|
||||
public function getForegroundColors()
|
||||
{
|
||||
return array_keys($this->foreground_colors);
|
||||
}
|
||||
|
||||
// Returns all background color names
|
||||
public function getBackgroundColors()
|
||||
{
|
||||
return array_keys($this->background_colors);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取带颜色的文字.
|
||||
*
|
||||
* @param string $string black|dark_gray|blue|light_blue|green|light_green|cyan|light_cyan|red|light_red|purple|brown|yellow|light_gray|white
|
||||
* @param string|null $foregroundColor 前景颜色 black|red|green|yellow|blue|magenta|cyan|light_gray
|
||||
* @param string|null $backgroundColor 背景颜色 同$foregroundColor
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function initColoredString(
|
||||
$string,
|
||||
$foregroundColor = null,
|
||||
$backgroundColor = null
|
||||
) {
|
||||
$coloredString = '';
|
||||
if (isset(static::$foregroundColors[$foregroundColor])) {
|
||||
$coloredString .= "\033[".static::$foregroundColors[$foregroundColor].'m';
|
||||
}
|
||||
if (isset(static::$backgroundColors[$backgroundColor])) {
|
||||
$coloredString .= "\033[".static::$backgroundColors[$backgroundColor].'m';
|
||||
}
|
||||
$coloredString .= $string."\033[0m";
|
||||
return $coloredString;
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出提示信息.
|
||||
*
|
||||
* @param $msg
|
||||
*/
|
||||
public static function notice($msg)
|
||||
{
|
||||
fwrite(STDOUT, self::initColoredString($msg, 'light_gray').PHP_EOL);
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出错误信息.
|
||||
*
|
||||
* @param $msg
|
||||
*/
|
||||
public static function error($msg)
|
||||
{
|
||||
fwrite(STDERR, self::initColoredString($msg, 'white','red').PHP_EOL);
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出警告信息.
|
||||
*
|
||||
* @param $msg
|
||||
*/
|
||||
public static function warn($msg)
|
||||
{
|
||||
fwrite(STDOUT, self::initColoredString($msg, 'red','yellow').PHP_EOL);
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出成功信息.
|
||||
*
|
||||
* @param $msg
|
||||
*/
|
||||
public static function success($msg)
|
||||
{
|
||||
fwrite(STDOUT, self::initColoredString($msg, 'light_cyan').PHP_EOL);
|
||||
}
|
||||
|
||||
}
|
||||
1460
app/admin/service/curd/BuildCurd.php
Normal file
1460
app/admin/service/curd/BuildCurd.php
Normal file
File diff suppressed because it is too large
Load Diff
8
app/admin/service/curd/exceptions/CurdException.php
Normal file
8
app/admin/service/curd/exceptions/CurdException.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace EasyAdmin\curd\exceptions;
|
||||
|
||||
class CurdException extends \Exception
|
||||
{
|
||||
|
||||
}
|
||||
8
app/admin/service/curd/exceptions/FileException.php
Normal file
8
app/admin/service/curd/exceptions/FileException.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace EasyAdmin\curd\exceptions;
|
||||
|
||||
class FileException extends \Exception
|
||||
{
|
||||
|
||||
}
|
||||
8
app/admin/service/curd/exceptions/TableException.php
Normal file
8
app/admin/service/curd/exceptions/TableException.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace EasyAdmin\curd\exceptions;
|
||||
|
||||
class TableException extends \Exception
|
||||
{
|
||||
|
||||
}
|
||||
27
app/admin/service/curd/templates/controller/controller.code
Normal file
27
app/admin/service/curd/templates/controller/controller.code
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace {{controllerNamespace}};
|
||||
|
||||
use app\common\controller\AdminController;
|
||||
use app\admin\service\annotation\ControllerAnnotation;
|
||||
use app\admin\service\annotation\NodeAnotation;
|
||||
use think\App;
|
||||
|
||||
/**
|
||||
* @ControllerAnnotation(title="{{controllerAnnotation}}")
|
||||
*/
|
||||
class {{controllerName}} extends AdminController
|
||||
{
|
||||
|
||||
use \app\admin\traits\Curd;
|
||||
|
||||
public function __construct(App $app)
|
||||
{
|
||||
parent::__construct($app);
|
||||
|
||||
$this->model = new {{modelFilename}}();
|
||||
{{selectList}}
|
||||
}
|
||||
|
||||
{{indexMethod}}
|
||||
}
|
||||
31
app/admin/service/curd/templates/controller/indexMethod.code
Normal file
31
app/admin/service/curd/templates/controller/indexMethod.code
Normal file
@@ -0,0 +1,31 @@
|
||||
|
||||
/**
|
||||
* @NodeAnotation(title="列表")
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
if ($this->request->isAjax()) {
|
||||
if (input('selectFields')) {
|
||||
return $this->selectList();
|
||||
}
|
||||
list($page, $limit, $where) = $this->buildTableParams();
|
||||
$count = $this->model
|
||||
{{relationIndexMethod}}
|
||||
->where($where)
|
||||
->count();
|
||||
$list = $this->model
|
||||
{{relationIndexMethod}}
|
||||
->where($where)
|
||||
->page($page, $limit)
|
||||
->order($this->sort)
|
||||
->select();
|
||||
$data = [
|
||||
'code' => 0,
|
||||
'msg' => '',
|
||||
'count' => $count,
|
||||
'data' => $list,
|
||||
];
|
||||
return json($data);
|
||||
}
|
||||
return $this->fetch();
|
||||
}
|
||||
2
app/admin/service/curd/templates/controller/select.code
Normal file
2
app/admin/service/curd/templates/controller/select.code
Normal file
@@ -0,0 +1,2 @@
|
||||
|
||||
$this->assign('{{name}}', $this->model->{{name}}());
|
||||
17
app/admin/service/curd/templates/model/model.code
Normal file
17
app/admin/service/curd/templates/model/model.code
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace {{modelNamespace}};
|
||||
|
||||
use app\common\model\TimeModel;
|
||||
|
||||
class {{modelName}} extends TimeModel
|
||||
{
|
||||
|
||||
protected $name = "{{table}}";
|
||||
|
||||
protected $deleteTime = {{deleteTime}};
|
||||
|
||||
{{relationList}}
|
||||
{{selectList}}
|
||||
|
||||
}
|
||||
5
app/admin/service/curd/templates/model/relation.code
Normal file
5
app/admin/service/curd/templates/model/relation.code
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
public function {{relationMethod}}()
|
||||
{
|
||||
return $this->belongsTo('{{relationModel}}', '{{foreignKey}}', '{{primaryKey}}');
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
|
||||
public function {{name}}()
|
||||
{
|
||||
return \app\admin\model\{{relation}}::column('{{values}}', 'id');
|
||||
}
|
||||
5
app/admin/service/curd/templates/model/select.code
Normal file
5
app/admin/service/curd/templates/model/select.code
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
public function {{name}}()
|
||||
{
|
||||
return {{values}};
|
||||
}
|
||||
34
app/admin/service/curd/templates/static/js.code
Normal file
34
app/admin/service/curd/templates/static/js.code
Normal file
@@ -0,0 +1,34 @@
|
||||
define(["jquery", "easy-admin"], function ($, ea) {
|
||||
|
||||
var init = {
|
||||
table_elem: '#currentTable',
|
||||
table_render_id: 'currentTableRenderId',
|
||||
index_url: '{{controllerUrl}}/index',
|
||||
add_url: '{{controllerUrl}}/add',
|
||||
edit_url: '{{controllerUrl}}/edit',
|
||||
delete_url: '{{controllerUrl}}/delete',
|
||||
export_url: '{{controllerUrl}}/export',
|
||||
modify_url: '{{controllerUrl}}/modify',
|
||||
};
|
||||
|
||||
var Controller = {
|
||||
|
||||
index: function () {
|
||||
ea.table.render({
|
||||
init: init,
|
||||
cols: [[
|
||||
{{indexCols}}
|
||||
]],
|
||||
});
|
||||
|
||||
ea.listen();
|
||||
},
|
||||
add: function () {
|
||||
ea.listen();
|
||||
},
|
||||
edit: function () {
|
||||
ea.listen();
|
||||
},
|
||||
};
|
||||
return Controller;
|
||||
});
|
||||
11
app/admin/service/curd/templates/view/form.code
Normal file
11
app/admin/service/curd/templates/view/form.code
Normal file
@@ -0,0 +1,11 @@
|
||||
<div class="layuimini-container">
|
||||
<form id="app-form" class="layui-form layuimini-form">
|
||||
{{formList}}
|
||||
<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>
|
||||
10
app/admin/service/curd/templates/view/index.code
Normal file
10
app/admin/service/curd/templates/view/index.code
Normal file
@@ -0,0 +1,10 @@
|
||||
<div class="layuimini-container">
|
||||
<div class="layuimini-main">
|
||||
<table id="currentTable" class="layui-table layui-hide"
|
||||
data-auth-add="{:auth('{{controllerUrl}}/add')}"
|
||||
data-auth-edit="{:auth('{{controllerUrl}}/edit')}"
|
||||
data-auth-delete="{:auth('{{controllerUrl}}/delete')}"
|
||||
lay-filter="currentTable">
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">{{comment}}</label>
|
||||
<div class="layui-input-block">
|
||||
{{define}}
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,3 @@
|
||||
{foreach ${{name}} as $k=>$v}
|
||||
<input type="checkbox" name="{{field}}[]" value="{$k}" lay-skin="primary" title="{$v}" {{select}}>
|
||||
{/foreach}
|
||||
7
app/admin/service/curd/templates/view/module/date.code
Normal file
7
app/admin/service/curd/templates/view/module/date.code
Normal file
@@ -0,0 +1,7 @@
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">{{comment}}</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="{{field}}" data-date="" data-date-type="{{define}}" class="layui-input" {{required}} placeholder="请输入{{comment}}" value="{{value}}">
|
||||
</div>
|
||||
</div>
|
||||
7
app/admin/service/curd/templates/view/module/editor.code
Normal file
7
app/admin/service/curd/templates/view/module/editor.code
Normal file
@@ -0,0 +1,7 @@
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">{{comment}}</label>
|
||||
<div class="layui-input-block">
|
||||
<textarea name="{{field}}" rows="20" class="layui-textarea editor" {{comment}} placeholder="请输入{{comment}}">{{value}}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
11
app/admin/service/curd/templates/view/module/file.code
Normal file
11
app/admin/service/curd/templates/view/module/file.code
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label required">{{comment}}</label>
|
||||
<div class="layui-input-block layuimini-upload">
|
||||
<input name="{{field}}" class="layui-input layui-col-xs6" {{required}} placeholder="请上传{{comment}}" value="{{value}}">
|
||||
<div class="layuimini-upload-btn">
|
||||
<span><a class="layui-btn" data-upload="{{field}}" data-upload-number="one" data-upload-exts="*" data-upload-icon="file"><i class="fa fa-upload"></i> 上传</a></span>
|
||||
<span><a class="layui-btn layui-btn-normal" id="select_{{field}}" data-upload-select="{{field}}" data-upload-number="one" data-upload-mimetype="*"><i class="fa fa-list"></i> 选择</a></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
11
app/admin/service/curd/templates/view/module/files.code
Normal file
11
app/admin/service/curd/templates/view/module/files.code
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label required">{{comment}}</label>
|
||||
<div class="layui-input-block layuimini-upload">
|
||||
<input name="{{field}}" class="layui-input layui-col-xs6" {{required}} placeholder="请上传{{comment}}" value="{{value}}">
|
||||
<div class="layuimini-upload-btn">
|
||||
<span><a class="layui-btn" data-upload="{{field}}" data-upload-number="more" data-upload-exts="*" data-upload-icon="file"><i class="fa fa-upload" data-upload-sign="{{define}}"></i> 上传</a></span>
|
||||
<span><a class="layui-btn layui-btn-normal" id="select_{{field}}" data-upload-select="{{field}}" data-upload-number="more" data-upload-mimetype="*" data-upload-sign="{{define}}"><i class="fa fa-list"></i> 选择</a></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
11
app/admin/service/curd/templates/view/module/image.code
Normal file
11
app/admin/service/curd/templates/view/module/image.code
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label required">{{comment}}</label>
|
||||
<div class="layui-input-block layuimini-upload">
|
||||
<input name="{{field}}" class="layui-input layui-col-xs6" {{required}} placeholder="请上传{{comment}}" value="{{value}}">
|
||||
<div class="layuimini-upload-btn">
|
||||
<span><a class="layui-btn" data-upload="{{field}}" data-upload-number="one" data-upload-exts="png|jpg|ico|jpeg" data-upload-icon="image"><i class="fa fa-upload"></i> 上传</a></span>
|
||||
<span><a class="layui-btn layui-btn-normal" id="select_{{field}}" data-upload-select="{{field}}" data-upload-number="one" data-upload-mimetype="image/*"><i class="fa fa-list"></i> 选择</a></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
11
app/admin/service/curd/templates/view/module/images.code
Normal file
11
app/admin/service/curd/templates/view/module/images.code
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label required">{{comment}}</label>
|
||||
<div class="layui-input-block layuimini-upload">
|
||||
<input name="{{field}}" class="layui-input layui-col-xs6" {{required}} placeholder="请上传{{comment}}" value="{{value}}">
|
||||
<div class="layuimini-upload-btn">
|
||||
<span><a class="layui-btn" data-upload="{{field}}" data-upload-number="more" data-upload-exts="png|jpg|ico|jpeg" data-upload-icon="image" data-upload-sign="{{define}}"><i class="fa fa-upload"></i> 上传</a></span>
|
||||
<span><a class="layui-btn layui-btn-normal" id="select_{{field}}" data-upload-select="{{field}}" data-upload-number="more" data-upload-mimetype="image/*" data-upload-sign="{{define}}"><i class="fa fa-list"></i> 选择</a></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
7
app/admin/service/curd/templates/view/module/input.code
Normal file
7
app/admin/service/curd/templates/view/module/input.code
Normal file
@@ -0,0 +1,7 @@
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">{{comment}}</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="{{field}}" class="layui-input" {{required}} placeholder="请输入{{comment}}" value="{{value}}">
|
||||
</div>
|
||||
</div>
|
||||
4
app/admin/service/curd/templates/view/module/option.code
Normal file
4
app/admin/service/curd/templates/view/module/option.code
Normal file
@@ -0,0 +1,4 @@
|
||||
<option value=''></option>
|
||||
{foreach ${{name}} as $k=>$v}
|
||||
<option value='{$k}' {{select}}>{$v}</option>
|
||||
{/foreach}
|
||||
7
app/admin/service/curd/templates/view/module/radio.code
Normal file
7
app/admin/service/curd/templates/view/module/radio.code
Normal file
@@ -0,0 +1,7 @@
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">{{comment}}</label>
|
||||
<div class="layui-input-block">
|
||||
{{define}}
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,3 @@
|
||||
{foreach ${{name}} as $k=>$v}
|
||||
<input type="radio" name="{{field}}" value="{$k}" title="{$v}" {{select}}>
|
||||
{/foreach}
|
||||
9
app/admin/service/curd/templates/view/module/select.code
Normal file
9
app/admin/service/curd/templates/view/module/select.code
Normal file
@@ -0,0 +1,9 @@
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">{{comment}}</label>
|
||||
<div class="layui-input-block">
|
||||
<select name="{{field}}" {{required}}>
|
||||
{{define}}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
<div class="layui-form-item layui-form-text">
|
||||
<label class="layui-form-label">{{comment}}</label>
|
||||
<div class="layui-input-block">
|
||||
<textarea name="{{field}}" class="layui-textarea" {{required}} placeholder="请输入{{comment}}">{{value}}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
97
app/admin/service/tool/CommonTool.php
Normal file
97
app/admin/service/tool/CommonTool.php
Normal file
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\service\tool;
|
||||
|
||||
class CommonTool
|
||||
{
|
||||
|
||||
/**
|
||||
* 下划线转驼峰
|
||||
* @param $str
|
||||
* @return null|string|string[]
|
||||
*/
|
||||
public static function lineToHump($str)
|
||||
{
|
||||
$str = preg_replace_callback('/([-_]+([a-z]{1}))/i', function ($matches) {
|
||||
return strtoupper($matches[2]);
|
||||
}, $str);
|
||||
return $str;
|
||||
}
|
||||
|
||||
/**
|
||||
* 驼峰转下划线
|
||||
* @param $str
|
||||
* @return null|string|string[]
|
||||
*/
|
||||
public static function humpToLine($str)
|
||||
{
|
||||
$str = preg_replace_callback('/([A-Z]{1})/', function ($matches) {
|
||||
return '_' . strtolower($matches[0]);
|
||||
}, $str);
|
||||
return $str;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取真实IP
|
||||
* @return mixed
|
||||
*/
|
||||
public static function getRealIp()
|
||||
{
|
||||
$ip = $_SERVER['REMOTE_ADDR'];
|
||||
if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && preg_match_all('#\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}#s', $_SERVER['HTTP_X_FORWARDED_FOR'], $matches)) {
|
||||
foreach ($matches[0] AS $xip) {
|
||||
if (!preg_match('#^(10|172\.16|192\.168)\.#', $xip)) {
|
||||
$ip = $xip;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} elseif (isset($_SERVER['HTTP_CLIENT_IP']) && preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $_SERVER['HTTP_CLIENT_IP'])) {
|
||||
$ip = $_SERVER['HTTP_CLIENT_IP'];
|
||||
} elseif (isset($_SERVER['HTTP_CF_CONNECTING_IP']) && preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $_SERVER['HTTP_CF_CONNECTING_IP'])) {
|
||||
$ip = $_SERVER['HTTP_CF_CONNECTING_IP'];
|
||||
} elseif (isset($_SERVER['HTTP_X_REAL_IP']) && preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $_SERVER['HTTP_X_REAL_IP'])) {
|
||||
$ip = $_SERVER['HTTP_X_REAL_IP'];
|
||||
}
|
||||
return $ip;
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取文件夹下的所有文件
|
||||
* @param $path
|
||||
* @param $basePath
|
||||
* @return array|mixed
|
||||
*/
|
||||
public static function readDirAllFiles($path, $basePath = '')
|
||||
{
|
||||
list($list, $temp_list) = [[], scandir($path)];
|
||||
empty($basePath) && $basePath = $path;
|
||||
foreach ($temp_list as $file) {
|
||||
if ($file != ".." && $file != ".") {
|
||||
if (is_dir($path . DIRECTORY_SEPARATOR . $file)) {
|
||||
$childFiles = self::readDirAllFiles($path . DIRECTORY_SEPARATOR . $file, $basePath);
|
||||
$list = array_merge($childFiles, $list);
|
||||
} else {
|
||||
$filePath = $path . DIRECTORY_SEPARATOR . $file;
|
||||
$fileName = str_replace($basePath . DIRECTORY_SEPARATOR, '', $filePath);
|
||||
$list[$fileName] = $filePath;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 模板值替换
|
||||
* @param $string
|
||||
* @param $array
|
||||
* @return mixed
|
||||
*/
|
||||
public static function replaceTemplate($string, $array)
|
||||
{
|
||||
foreach ($array as $key => $val) {
|
||||
$string = str_replace("{{" . $key . "}}", $val, $string);
|
||||
}
|
||||
return $string;
|
||||
}
|
||||
|
||||
}
|
||||
122
app/admin/service/upload/FileBase.php
Normal file
122
app/admin/service/upload/FileBase.php
Normal file
@@ -0,0 +1,122 @@
|
||||
<?php
|
||||
|
||||
|
||||
|
||||
namespace app\admin\service\upload;
|
||||
|
||||
|
||||
use think\facade\Filesystem;
|
||||
use think\File;
|
||||
|
||||
/**
|
||||
* 基类
|
||||
* Class Base
|
||||
* @package EasyAdmin\upload
|
||||
*/
|
||||
class FileBase
|
||||
{
|
||||
|
||||
/**
|
||||
* 上传配置
|
||||
* @var array
|
||||
*/
|
||||
protected $uploadConfig;
|
||||
|
||||
/**
|
||||
* 上传文件对象
|
||||
* @var object
|
||||
*/
|
||||
protected $file;
|
||||
|
||||
/**
|
||||
* 上传完成的文件路径
|
||||
* @var string
|
||||
*/
|
||||
protected $completeFilePath;
|
||||
|
||||
/**
|
||||
* 上传完成的文件的URL
|
||||
* @var string
|
||||
*/
|
||||
protected $completeFileUrl;
|
||||
|
||||
/**
|
||||
* 保存上传文件的数据表
|
||||
* @var string
|
||||
*/
|
||||
protected $tableName;
|
||||
|
||||
/**
|
||||
* 上传类型
|
||||
* @var string
|
||||
*/
|
||||
protected $uploadType = 'local';
|
||||
|
||||
/**
|
||||
* 设置上传方式
|
||||
* @param $value
|
||||
* @return $this
|
||||
*/
|
||||
public function setUploadType($value)
|
||||
{
|
||||
$this->uploadType = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置上传配置
|
||||
* @param $value
|
||||
* @return $this
|
||||
*/
|
||||
public function setUploadConfig($value)
|
||||
{
|
||||
$this->uploadConfig = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置上传配置
|
||||
* @param $value
|
||||
* @return $this
|
||||
*/
|
||||
public function setFile($value)
|
||||
{
|
||||
$this->file = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置保存文件数据表
|
||||
* @param $value
|
||||
* @return $this
|
||||
*/
|
||||
public function setTableName($value)
|
||||
{
|
||||
$this->tableName = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存文件
|
||||
*/
|
||||
public function save()
|
||||
{
|
||||
$this->completeFilePath = Filesystem::disk('public')->putFile('upload', $this->file, 'md5');
|
||||
$this->completeFileUrl = request()->domain() . '/' . str_replace(DIRECTORY_SEPARATOR, '/', $this->completeFilePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除保存在本地的文件
|
||||
* @return bool|string
|
||||
*/
|
||||
public function rmLocalSave()
|
||||
{
|
||||
try {
|
||||
$rm = unlink($this->completeFilePath);
|
||||
} catch (\Exception $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
return $rm;
|
||||
}
|
||||
|
||||
}
|
||||
130
app/admin/service/upload/Uploadfile.php
Normal file
130
app/admin/service/upload/Uploadfile.php
Normal file
@@ -0,0 +1,130 @@
|
||||
<?php
|
||||
|
||||
|
||||
|
||||
namespace app\admin\service\upload;
|
||||
|
||||
use app\admin\service\upload\driver\Alioss;
|
||||
use app\admin\service\upload\driver\Qnoss;
|
||||
use app\admin\service\upload\driver\Txcos;
|
||||
use app\admin\service\upload\driver\Local;
|
||||
use think\File;
|
||||
|
||||
/**
|
||||
* 上传组件
|
||||
* Class Uploadfile
|
||||
* @package EasyAdmin\upload
|
||||
*/
|
||||
class Uploadfile
|
||||
{
|
||||
|
||||
/**
|
||||
* 当前实例对象
|
||||
* @var object
|
||||
*/
|
||||
protected static $instance;
|
||||
|
||||
/**
|
||||
* 上传方式
|
||||
* @var string
|
||||
*/
|
||||
protected $uploadType = 'local';
|
||||
|
||||
/**
|
||||
* 上传配置文件
|
||||
* @var array
|
||||
*/
|
||||
protected $uploadConfig;
|
||||
|
||||
/**
|
||||
* 需要上传的文件对象
|
||||
* @var File
|
||||
*/
|
||||
protected $file;
|
||||
|
||||
/**
|
||||
* 保存上传文件的数据表
|
||||
* @var string
|
||||
*/
|
||||
protected $tableName = 'system_uploadfile';
|
||||
|
||||
/**
|
||||
* 获取对象实例
|
||||
* @return Uploadfile|object
|
||||
*/
|
||||
public static function instance()
|
||||
{
|
||||
if (is_null(self::$instance)) {
|
||||
self::$instance = new static();
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置上传对象
|
||||
* @param $value
|
||||
* @return $this
|
||||
*/
|
||||
public function setFile($value)
|
||||
{
|
||||
$this->file = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置上传文件
|
||||
* @param $value
|
||||
* @return $this
|
||||
*/
|
||||
public function setUploadConfig($value)
|
||||
{
|
||||
$this->uploadConfig = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置上传方式
|
||||
* @param $value
|
||||
* @return $this
|
||||
*/
|
||||
public function setUploadType($value)
|
||||
{
|
||||
$this->uploadType = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置保存数据表
|
||||
* @param $value
|
||||
* @return $this
|
||||
*/
|
||||
public function setTableName($value)
|
||||
{
|
||||
$this->tableName = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存文件
|
||||
* @return array|void
|
||||
*/
|
||||
public function save()
|
||||
{
|
||||
$obj = null;
|
||||
if ($this->uploadType == 'local') {
|
||||
$obj = new Local();
|
||||
} elseif ($this->uploadType == 'alioss') {
|
||||
$obj = new Alioss();
|
||||
} elseif ($this->uploadType == 'qnoss') {
|
||||
$obj = new Qnoss();
|
||||
} elseif ($this->uploadType == 'txcos') {
|
||||
$obj = new Txcos();
|
||||
}
|
||||
$save = $obj->setUploadConfig($this->uploadConfig)
|
||||
->setUploadType($this->uploadType)
|
||||
->setTableName($this->tableName)
|
||||
->setFile($this->file)
|
||||
->save();
|
||||
return $save;
|
||||
}
|
||||
}
|
||||
42
app/admin/service/upload/driver/Alioss.php
Normal file
42
app/admin/service/upload/driver/Alioss.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
|
||||
|
||||
namespace app\admin\service\upload\driver;
|
||||
|
||||
use app\admin\service\upload\FileBase;
|
||||
use app\admin\service\upload\trigger\SaveDb;
|
||||
use app\admin\service\upload\driver\alioss\Oss;
|
||||
|
||||
/**
|
||||
* 阿里云上传
|
||||
* Class Alioss
|
||||
* @package EasyAdmin\upload\driver
|
||||
*/
|
||||
class Alioss extends FileBase
|
||||
{
|
||||
|
||||
/**
|
||||
* 重写上传方法
|
||||
* @return array|void
|
||||
*/
|
||||
public function save()
|
||||
{
|
||||
parent::save();
|
||||
$upload = Oss::instance($this->uploadConfig)
|
||||
->save($this->completeFilePath, $this->completeFilePath);
|
||||
if ($upload['save'] == true) {
|
||||
SaveDb::trigger($this->tableName, [
|
||||
'upload_type' => $this->uploadType,
|
||||
'original_name' => $this->file->getOriginalName(),
|
||||
'mime_type' => $this->file->getOriginalMime(),
|
||||
'file_ext' => strtolower($this->file->getOriginalExtension()),
|
||||
'url' => $upload['url'],
|
||||
'create_time' => time(),
|
||||
]);
|
||||
}
|
||||
$this->rmLocalSave();
|
||||
return $upload;
|
||||
}
|
||||
|
||||
}
|
||||
40
app/admin/service/upload/driver/Local.php
Normal file
40
app/admin/service/upload/driver/Local.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
|
||||
|
||||
namespace app\admin\service\upload\driver;
|
||||
|
||||
use app\admin\service\upload\FileBase;
|
||||
use app\admin\service\upload\trigger\SaveDb;
|
||||
|
||||
/**
|
||||
* 本地上传
|
||||
* Class Local
|
||||
* @package EasyAdmin\upload\driver
|
||||
*/
|
||||
class Local extends FileBase
|
||||
{
|
||||
|
||||
/**
|
||||
* 重写上传方法
|
||||
* @return array|void
|
||||
*/
|
||||
public function save()
|
||||
{
|
||||
parent::save();
|
||||
SaveDb::trigger($this->tableName, [
|
||||
'upload_type' => $this->uploadType,
|
||||
'original_name' => $this->file->getOriginalName(),
|
||||
'mime_type' => $this->file->getOriginalMime(),
|
||||
'file_ext' => strtolower($this->file->getOriginalExtension()),
|
||||
'url' => $this->completeFileUrl,
|
||||
'create_time' => time(),
|
||||
]);
|
||||
return [
|
||||
'save' => true,
|
||||
'msg' => '上传成功',
|
||||
'url' => $this->completeFileUrl,
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
42
app/admin/service/upload/driver/Qnoss.php
Normal file
42
app/admin/service/upload/driver/Qnoss.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
|
||||
|
||||
namespace app\admin\service\upload\driver;
|
||||
|
||||
use app\admin\service\upload\driver\qnoss\Oss;
|
||||
use app\admin\service\upload\FileBase;
|
||||
use app\admin\service\upload\trigger\SaveDb;
|
||||
|
||||
/**
|
||||
* 七牛云上传
|
||||
* Class Qnoss
|
||||
* @package EasyAdmin\upload\driver
|
||||
*/
|
||||
class Qnoss extends FileBase
|
||||
{
|
||||
|
||||
/**
|
||||
* 重写上传方法
|
||||
* @return array|void
|
||||
*/
|
||||
public function save()
|
||||
{
|
||||
parent::save();
|
||||
$upload = Oss::instance($this->uploadConfig)
|
||||
->save($this->completeFilePath, $this->completeFilePath);
|
||||
if ($upload['save'] == true) {
|
||||
SaveDb::trigger($this->tableName, [
|
||||
'upload_type' => $this->uploadType,
|
||||
'original_name' => $this->file->getOriginalName(),
|
||||
'mime_type' => $this->file->getOriginalMime(),
|
||||
'file_ext' => strtolower($this->file->getOriginalExtension()),
|
||||
'url' => $upload['url'],
|
||||
'create_time' => time(),
|
||||
]);
|
||||
}
|
||||
$this->rmLocalSave();
|
||||
return $upload;
|
||||
}
|
||||
|
||||
}
|
||||
43
app/admin/service/upload/driver/Txcos.php
Normal file
43
app/admin/service/upload/driver/Txcos.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
|
||||
|
||||
namespace app\admin\service\upload\driver;
|
||||
|
||||
|
||||
use app\admin\service\upload\driver\txcos\Cos;
|
||||
use app\admin\service\upload\FileBase;
|
||||
use app\admin\service\upload\trigger\SaveDb;
|
||||
|
||||
/**
|
||||
* 腾讯云上传
|
||||
* Class Txcos
|
||||
* @package EasyAdmin\upload\driver
|
||||
*/
|
||||
class Txcos extends FileBase
|
||||
{
|
||||
|
||||
/**
|
||||
* 重写上传方法
|
||||
* @return array|void
|
||||
*/
|
||||
public function save()
|
||||
{
|
||||
parent::save();
|
||||
$upload = Cos::instance($this->uploadConfig)
|
||||
->save($this->completeFilePath, $this->completeFilePath);
|
||||
if ($upload['save'] == true) {
|
||||
SaveDb::trigger($this->tableName, [
|
||||
'upload_type' => $this->uploadType,
|
||||
'original_name' => $this->file->getOriginalName(),
|
||||
'mime_type' => $this->file->getOriginalMime(),
|
||||
'file_ext' => strtolower($this->file->getOriginalExtension()),
|
||||
'url' => $upload['url'],
|
||||
'create_time' => time(),
|
||||
]);
|
||||
}
|
||||
$this->rmLocalSave();
|
||||
return $upload;
|
||||
}
|
||||
|
||||
}
|
||||
70
app/admin/service/upload/driver/alioss/Oss.php
Normal file
70
app/admin/service/upload/driver/alioss/Oss.php
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
|
||||
|
||||
namespace app\admin\service\upload\driver\alioss;
|
||||
|
||||
use EasyAdmin\upload\interfaces\OssDriver;
|
||||
use OSS\Core\OssException;
|
||||
use OSS\OssClient;
|
||||
|
||||
class Oss implements OssDriver
|
||||
{
|
||||
|
||||
protected static $instance;
|
||||
|
||||
protected $accessKeyId;
|
||||
|
||||
protected $accessKeySecret;
|
||||
|
||||
protected $endpoint;
|
||||
|
||||
protected $bucket;
|
||||
|
||||
protected $domain;
|
||||
|
||||
protected $ossClient;
|
||||
|
||||
protected function __construct($config)
|
||||
{
|
||||
$this->accessKeyId = $config['alioss_access_key_id'];
|
||||
$this->accessKeySecret = $config['alioss_access_key_secret'];
|
||||
$this->endpoint = $config['alioss_endpoint'];
|
||||
$this->bucket = $config['alioss_bucket'];
|
||||
$this->domain = $config['alioss_domain'];
|
||||
$this->ossClient = new OssClient($this->accessKeyId, $this->accessKeySecret, $this->endpoint);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public static function instance($config)
|
||||
{
|
||||
if (is_null(self::$instance)) {
|
||||
self::$instance = new static($config);
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
public function save($objectName,$filePath)
|
||||
{
|
||||
try {
|
||||
$upload = $this->ossClient->uploadFile($this->bucket, $objectName, $filePath);
|
||||
} catch (OssException $e) {
|
||||
return [
|
||||
'save' => false,
|
||||
'msg' => $e->getMessage(),
|
||||
];
|
||||
}
|
||||
if (!isset($upload['info']['url'])) {
|
||||
return [
|
||||
'save' => false,
|
||||
'msg' => '保存失败',
|
||||
];
|
||||
}
|
||||
return [
|
||||
'save' => true,
|
||||
'msg' => '上传成功',
|
||||
'url' => $upload['info']['url'],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
64
app/admin/service/upload/driver/qnoss/Oss.php
Normal file
64
app/admin/service/upload/driver/qnoss/Oss.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
|
||||
|
||||
namespace app\admin\service\upload\driver\qnoss;
|
||||
|
||||
|
||||
use app\admin\service\upload\interfaces\OssDriver;
|
||||
use Qiniu\Auth;
|
||||
use Qiniu\Storage\UploadManager;
|
||||
|
||||
class Oss implements OssDriver
|
||||
{
|
||||
|
||||
protected static $instance;
|
||||
|
||||
protected $accessKey;
|
||||
|
||||
protected $secretKey;
|
||||
|
||||
protected $bucket;
|
||||
|
||||
protected $domain;
|
||||
|
||||
protected $auth;
|
||||
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->accessKey = $config['qnoss_access_key'];
|
||||
$this->secretKey = $config['qnoss_secret_key'];
|
||||
$this->bucket = $config['qnoss_bucket'];
|
||||
$this->domain = $config['qnoss_domain'];
|
||||
$this->auth = new Auth($this->accessKey, $this->secretKey);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public static function instance($config)
|
||||
{
|
||||
if (is_null(self::$instance)) {
|
||||
self::$instance = new static($config);
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
public function save($objectName, $filePath)
|
||||
{
|
||||
$token = $this->auth->uploadToken($this->bucket);
|
||||
$uploadMgr = new UploadManager();
|
||||
list($result, $error) = $uploadMgr->putFile($token, $objectName, $filePath);
|
||||
if ($error !== null) {
|
||||
return [
|
||||
'save' => false,
|
||||
'msg' => '保存失败',
|
||||
];
|
||||
} else {
|
||||
return [
|
||||
'save' => true,
|
||||
'msg' => '上传成功',
|
||||
'url' => $this->domain . '/' . $result['key'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
BIN
app/admin/service/upload/driver/txcos/Cos.php
Normal file
BIN
app/admin/service/upload/driver/txcos/Cos.php
Normal file
Binary file not shown.
12
app/admin/service/upload/interfaces/OssDriver.php
Normal file
12
app/admin/service/upload/interfaces/OssDriver.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
|
||||
|
||||
namespace app\admin\service\upload\interfaces;
|
||||
|
||||
interface OssDriver
|
||||
{
|
||||
|
||||
public function save($objectName,$filePath);
|
||||
|
||||
}
|
||||
31
app/admin/service/upload/trigger/SaveDb.php
Normal file
31
app/admin/service/upload/trigger/SaveDb.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
|
||||
|
||||
namespace app\admin\service\upload\trigger;
|
||||
|
||||
|
||||
use think\facade\Db;
|
||||
|
||||
/**
|
||||
* 保存到数据库
|
||||
* Class SaveDb
|
||||
* @package EasyAdmin\upload\trigger
|
||||
*/
|
||||
class SaveDb
|
||||
{
|
||||
|
||||
/**
|
||||
* 保存上传文件
|
||||
* @param $tableName
|
||||
* @param $data
|
||||
*/
|
||||
public static function trigger($tableName, $data)
|
||||
{
|
||||
if (isset($data['original_name'])) {
|
||||
$data['original_name'] = htmlspecialchars($data['original_name'], ENT_QUOTES);
|
||||
}
|
||||
Db::name($tableName)->save($data);
|
||||
}
|
||||
|
||||
}
|
||||
162
app/admin/traits/Curd.php
Normal file
162
app/admin/traits/Curd.php
Normal file
@@ -0,0 +1,162 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\traits;
|
||||
|
||||
use app\admin\service\annotation\NodeAnotation;
|
||||
use app\admin\service\tool\CommonTool;
|
||||
use jianyan\excel\Excel;
|
||||
use think\facade\Db;
|
||||
|
||||
/**
|
||||
* 后台CURD复用
|
||||
* Trait Curd
|
||||
* @package app\admin\traits
|
||||
*/
|
||||
trait Curd
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @NodeAnotation(title="列表")
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
if ($this->request->isAjax()) {
|
||||
if (input('selectFields')) {
|
||||
return $this->selectList();
|
||||
}
|
||||
list($page, $limit, $where) = $this->buildTableParams();
|
||||
$count = $this->model
|
||||
->where($where)
|
||||
->count();
|
||||
$list = $this->model
|
||||
->where($where)
|
||||
->page($page, $limit)
|
||||
->order($this->sort)
|
||||
->select();
|
||||
$data = [
|
||||
'code' => 0,
|
||||
'msg' => '',
|
||||
'count' => $count,
|
||||
'data' => $list,
|
||||
];
|
||||
return json($data);
|
||||
}
|
||||
return $this->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* @NodeAnotation(title="添加")
|
||||
*/
|
||||
public function add()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$post = $this->request->post();
|
||||
$rule = [];
|
||||
$this->validate($post, $rule);
|
||||
try {
|
||||
$save = $this->model->save($post);
|
||||
} catch (\Exception $e) {
|
||||
$this->error('保存失败:' . $e->getMessage());
|
||||
}
|
||||
$save ? $this->success('保存成功') : $this->error('保存失败');
|
||||
}
|
||||
return $this->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* @NodeAnotation(title="编辑")
|
||||
*/
|
||||
public function edit($id)
|
||||
{
|
||||
$row = $this->model->find($id);
|
||||
empty($row) && $this->error('数据不存在');
|
||||
if ($this->request->isPost()) {
|
||||
$post = $this->request->post();
|
||||
$rule = [];
|
||||
$this->validate($post, $rule);
|
||||
try {
|
||||
$save = $row->save($post);
|
||||
} catch (\Exception $e) {
|
||||
$this->error('保存失败');
|
||||
}
|
||||
$save ? $this->success('保存成功') : $this->error('保存失败');
|
||||
}
|
||||
$this->assign('row', $row);
|
||||
return $this->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* @NodeAnotation(title="删除")
|
||||
*/
|
||||
public function delete($id)
|
||||
{
|
||||
$this->checkPostRequest();
|
||||
$row = $this->model->whereIn('id', $id)->select();
|
||||
$row->isEmpty() && $this->error('数据不存在');
|
||||
try {
|
||||
$save = $row->delete();
|
||||
} catch (\Exception $e) {
|
||||
$this->error('删除失败');
|
||||
}
|
||||
$save ? $this->success('删除成功') : $this->error('删除失败');
|
||||
}
|
||||
|
||||
/**
|
||||
* @NodeAnotation(title="导出")
|
||||
*/
|
||||
public function export()
|
||||
{
|
||||
list($page, $limit, $where) = $this->buildTableParams();
|
||||
$tableName = $this->model->getName();
|
||||
$tableName = CommonTool::humpToLine(lcfirst($tableName));
|
||||
$prefix = config('database.connections.mysql.prefix');
|
||||
$dbList = Db::query("show full columns from {$prefix}{$tableName}");
|
||||
$header = [];
|
||||
foreach ($dbList as $vo) {
|
||||
$comment = !empty($vo['Comment']) ? $vo['Comment'] : $vo['Field'];
|
||||
if (!in_array($vo['Field'], $this->noExportFields)) {
|
||||
$header[] = [$comment, $vo['Field']];
|
||||
}
|
||||
}
|
||||
$list = $this->model
|
||||
->where($where)
|
||||
->limit(100000)
|
||||
->order('id', 'desc')
|
||||
->select()
|
||||
->toArray();
|
||||
$fileName = time();
|
||||
return Excel::exportData($list, $header, $fileName, 'xlsx');
|
||||
}
|
||||
|
||||
/**
|
||||
* @NodeAnotation(title="属性修改")
|
||||
*/
|
||||
public function modify()
|
||||
{
|
||||
$this->checkPostRequest();
|
||||
$post = $this->request->post();
|
||||
$rule = [
|
||||
'id|ID' => 'require',
|
||||
'field|字段' => 'require',
|
||||
'value|值' => 'require',
|
||||
];
|
||||
$this->validate($post, $rule);
|
||||
$row = $this->model->find($post['id']);
|
||||
if (!$row) {
|
||||
$this->error('数据不存在');
|
||||
}
|
||||
if (!in_array($post['field'], $this->allowModifyFields)) {
|
||||
$this->error('该字段不允许修改:' . $post['field']);
|
||||
}
|
||||
try {
|
||||
$row->save([
|
||||
$post['field'] => $post['value'],
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
$this->success('保存成功');
|
||||
}
|
||||
|
||||
}
|
||||
49
app/admin/view/index/edit_admin.html
Normal file
49
app/admin/view/index/edit_admin.html
Normal file
@@ -0,0 +1,49 @@
|
||||
<div class="layuimini-container">
|
||||
<div class="layuimini-main">
|
||||
|
||||
<form id="app-form" class="layui-form layuimini-form">
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label required">用户头像</label>
|
||||
<div class="layui-input-block layuimini-upload">
|
||||
<input name="head_img" class="layui-input layui-col-xs6" lay-reqtext="请上传用户头像" placeholder="请上传用户头像" value="{$row.head_img|default=''}">
|
||||
<div class="layuimini-upload-btn">
|
||||
<span><a class="layui-btn" data-upload="head_img" data-upload-number="one" data-upload-exts="png|jpg|ico|jpeg"><i class="fa fa-upload"></i> 上传</a></span>
|
||||
<span><a class="layui-btn layui-btn-normal" id="select_head_img" data-upload-select="head_img" data-upload-number="one"><i class="fa fa-list"></i> 选择</a></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label required">登录账户</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="username" class="layui-input" readonly value="{$row.username|default=''}">
|
||||
<tip>填写登录账户。</tip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">用户手机</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="phone" class="layui-input" lay-reqtext="请输入用户手机" placeholder="请输入用户手机" value="{$row.username|default=''}">
|
||||
<tip>填写用户手机。</tip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item layui-form-text">
|
||||
<label class="layui-form-label">备注信息</label>
|
||||
<div class="layui-input-block">
|
||||
<textarea name="remark" class="layui-textarea" placeholder="请输入备注信息">{$row.username|default=''}</textarea>
|
||||
</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>
|
||||
</div>
|
||||
38
app/admin/view/index/edit_password.html
Normal file
38
app/admin/view/index/edit_password.html
Normal file
@@ -0,0 +1,38 @@
|
||||
<div class="layuimini-container">
|
||||
<div class="layuimini-main">
|
||||
|
||||
<form id="app-form" class="layui-form layuimini-form">
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label required">登录账户</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="username" class="layui-input" readonly value="{$row.username|default=''}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">登录密码</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="password" name="password" class="layui-input" lay-verify="required" lay-reqtext="请输入登录密码" placeholder="请输入登录密码" value="">
|
||||
<tip>填写登录密码。</tip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">确认密码</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="password" name="password_again" class="layui-input" lay-verify="required" lay-reqtext="请输入确认密码" placeholder="请输入确认密码" value="">
|
||||
<tip>填写再次登录密码。</tip>
|
||||
</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>
|
||||
</div>
|
||||
110
app/admin/view/index/index.html
Normal file
110
app/admin/view/index/index.html
Normal file
@@ -0,0 +1,110 @@
|
||||
<link rel="stylesheet" href="__STATIC__/plugs/lay-module/layuimini/layuimini.css?v={:time()}" media="all">
|
||||
<link rel="stylesheet" href="__STATIC__/plugs/lay-module/layuimini/themes/default.css?v={:time()}" media="all">
|
||||
<style id="layuimini-bg-color">
|
||||
</style>
|
||||
<body class="layui-layout-body layuimini-all">
|
||||
<div class="layui-layout layui-layout-admin">
|
||||
|
||||
<div class="layui-header header">
|
||||
<div class="layui-logo layuimini-logo"></div>
|
||||
|
||||
<div class="layuimini-header-content">
|
||||
<a>
|
||||
<div class="layuimini-tool"><i title="展开" class="fa fa-outdent" data-side-fold="1"></i></div>
|
||||
</a>
|
||||
|
||||
<!--电脑端头部菜单-->
|
||||
<ul class="layui-nav layui-layout-left layuimini-header-menu layuimini-menu-header-pc layuimini-pc-show">
|
||||
</ul>
|
||||
|
||||
<!--手机端头部菜单-->
|
||||
<ul class="layui-nav layui-layout-left layuimini-header-menu layuimini-mobile-show">
|
||||
<li class="layui-nav-item">
|
||||
<a href="javascript:;"><i class="fa fa-list-ul"></i> 选择模块</a>
|
||||
<dl class="layui-nav-child layuimini-menu-header-mobile">
|
||||
</dl>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul class="layui-nav layui-layout-right">
|
||||
|
||||
<li class="layui-nav-item" lay-unselect>
|
||||
<a href="javascript:;" data-refresh="刷新"><i class="fa fa-refresh"></i></a>
|
||||
</li>
|
||||
<li class="layui-nav-item" lay-unselect>
|
||||
<a href="javascript:;" data-clear="清理" class="layuimini-clear"><i class="fa fa-trash-o"></i></a>
|
||||
</li>
|
||||
<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 layuimini-setting">
|
||||
<a href="javascript:;">
|
||||
<img src="{:session('admin.head_img')}" class="layui-nav-img" width="50" height="50">
|
||||
<cite class="adminName">{:session('admin.username')}</cite>
|
||||
<span class="layui-nav-more"></span>
|
||||
</a>
|
||||
<dl class="layui-nav-child">
|
||||
<dd>
|
||||
<a href="javascript:;" layuimini-content-href="{:__url('index/editAdmin')}" data-title="基本资料" data-icon="fa fa-gears">基本资料<span class="layui-badge-dot"></span></a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="javascript:;" layuimini-content-href="{:__url('index/editPassword')}" data-title="修改密码" data-icon="fa fa-gears">修改密码</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<hr>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="javascript:;" class="login-out">退出登录</a>
|
||||
</dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li class="layui-nav-item layuimini-select-bgcolor" lay-unselect>
|
||||
<a href="javascript:;" data-bgcolor="配色方案"><i class="fa fa-ellipsis-v"></i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--无限极左侧菜单-->
|
||||
<div class="layui-side layui-bg-black layuimini-menu-left">
|
||||
</div>
|
||||
|
||||
<!--初始化加载层-->
|
||||
<div class="layuimini-loader">
|
||||
<div class="layuimini-loader-inner"></div>
|
||||
</div>
|
||||
|
||||
<!--手机端遮罩层-->
|
||||
<div class="layuimini-make"></div>
|
||||
|
||||
<!-- 移动导航 -->
|
||||
<div class="layuimini-site-mobile"><i class="layui-icon"></i></div>
|
||||
|
||||
<div class="layui-body">
|
||||
<div class="layuimini-tab layui-tab-rollTool layui-tab" lay-filter="layuiminiTab" lay-allowclose="true">
|
||||
<ul class="layui-tab-title">
|
||||
<li class="layui-this" id="layuiminiHomeTabId" lay-id=""></li>
|
||||
</ul>
|
||||
<div class="layui-tab-control">
|
||||
<li class="layuimini-tab-roll-left layui-icon layui-icon-left"></li>
|
||||
<li class="layuimini-tab-roll-right layui-icon layui-icon-right"></li>
|
||||
<li class="layui-tab-tool layui-icon layui-icon-down">
|
||||
<ul class="layui-nav close-box">
|
||||
<li class="layui-nav-item">
|
||||
<a href="javascript:;"><span class="layui-nav-more"></span></a>
|
||||
<dl class="layui-nav-child">
|
||||
<dd><a href="javascript:;" layuimini-tab-close="current">关 闭 当 前</a></dd>
|
||||
<dd><a href="javascript:;" layuimini-tab-close="other">关 闭 其 他</a></dd>
|
||||
<dd><a href="javascript:;" layuimini-tab-close="all">关 闭 全 部</a></dd>
|
||||
</dl>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</div>
|
||||
<div class="layui-tab-content">
|
||||
<div id="layuiminiHomeTabIframe" class="layui-tab-item layui-show"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
164
app/admin/view/index/welcome.html
Normal file
164
app/admin/view/index/welcome.html
Normal file
@@ -0,0 +1,164 @@
|
||||
<link rel="stylesheet" href="__STATIC__/admin/css/welcome.css?v={:time()}" media="all">
|
||||
<div class="layuimini-container">
|
||||
<div class="layuimini-main">
|
||||
<div class="layui-row layui-col-space15">
|
||||
<div class="layui-col-md8">
|
||||
<div class="layui-row layui-col-space15">
|
||||
<div class="layui-col-md6">
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-header"><i class="fa fa-warning icon"></i>数据统计</div>
|
||||
<div class="layui-card-body">
|
||||
<div class="welcome-module">
|
||||
<div class="layui-row layui-col-space10">
|
||||
<div class="layui-col-xs6">
|
||||
<div class="panel layui-bg-number">
|
||||
<div class="panel-body">
|
||||
<div class="panel-title">
|
||||
<span class="label pull-right layui-bg-blue">实时</span>
|
||||
<h5>用户统计</h5>
|
||||
</div>
|
||||
<div class="panel-content">
|
||||
<h1 class="no-margins">1234</h1>
|
||||
<small>当前分类总记录数</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-xs6">
|
||||
<div class="panel layui-bg-number">
|
||||
<div class="panel-body">
|
||||
<div class="panel-title">
|
||||
<span class="label pull-right layui-bg-cyan">实时</span>
|
||||
<h5>商品统计</h5>
|
||||
</div>
|
||||
<div class="panel-content">
|
||||
<h1 class="no-margins">1234</h1>
|
||||
<small>当前分类总记录数</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-xs6">
|
||||
<div class="panel layui-bg-number">
|
||||
<div class="panel-body">
|
||||
<div class="panel-title">
|
||||
<span class="label pull-right layui-bg-orange">实时</span>
|
||||
<h5>浏览统计</h5>
|
||||
</div>
|
||||
<div class="panel-content">
|
||||
<h1 class="no-margins">1234</h1>
|
||||
<small>当前分类总记录数</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-xs6">
|
||||
<div class="panel layui-bg-number">
|
||||
<div class="panel-body">
|
||||
<div class="panel-title">
|
||||
<span class="label pull-right layui-bg-green">实时</span>
|
||||
<h5>订单统计</h5>
|
||||
</div>
|
||||
<div class="panel-content">
|
||||
<h1 class="no-margins">1234</h1>
|
||||
<small>当前分类总记录数</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-md6">
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-header"><i class="fa fa-credit-card icon icon-blue"></i>快捷入口</div>
|
||||
<div class="layui-card-body">
|
||||
<div class="welcome-module">
|
||||
<div class="layui-row layui-col-space10 layuimini-qiuck">
|
||||
|
||||
{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>
|
||||
{/foreach}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="layui-col-md12">
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-header"><i class="fa fa-line-chart icon"></i>报表统计</div>
|
||||
<div class="layui-card-body">
|
||||
<div id="echarts-records" style="width: 100%;min-height:500px"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-col-md4">
|
||||
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-header"><i class="fa fa-fire icon"></i>版本信息</div>
|
||||
<div class="layui-card-body layui-text">
|
||||
<table class="layui-table">
|
||||
<colgroup>
|
||||
<col width="100">
|
||||
<col>
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>框架名称</td>
|
||||
<td>
|
||||
EasyAdmin8
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>主要特色</td>
|
||||
<td>零门槛 / 响应式 / 清爽 / 极简</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Gitee</td>
|
||||
<td style="padding-bottom: 0;">
|
||||
<div class="layui-btn-container">
|
||||
<a href="https://gitee.com/wolf-code/easyAdmin8" style="margin-right: 15px" target="_blank">
|
||||
https://gitee.com/wolf-code/easyAdmin8
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Github</td>
|
||||
<td style="padding-bottom: 0;">
|
||||
<div class="layui-btn-container">
|
||||
<a href="https://gitee.com/wolf-code/easyAdmin8" style="margin-right: 15px" target="_blank">
|
||||
https://github.com/wolfcode-cn/easyAdmin8
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-header"><i class="fa fa-paper-plane-o icon"></i>作者心语</div>
|
||||
<div class="layui-card-body layui-text layadmin-text">
|
||||
<p>本模板基于layui2.8.x以及font-awesome-4.7.0进行实现。layui开发文档地址:<a class="layui-btn layui-btn-xs layui-btn-danger" target="_blank" href="http://layui.dev/docs">layui文档</a></p>
|
||||
<p class="layui-red">备注:此后台框架永久开源,但请勿进行出售或者上传到任何素材网站,否则将追究相应的责任。</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
32
app/admin/view/layout/default.html
Normal file
32
app/admin/view/layout/default.html
Normal file
@@ -0,0 +1,32 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>{:sysconfig('site','site_name')}</title>
|
||||
<meta name="renderer" content="webkit">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://cdn.staticfile.org/html5shiv/r29/html5.min.js"></script>
|
||||
<script src="https://cdn.staticfile.org/respond.js/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
<link rel="stylesheet" href="__STATIC__/admin/css/public.css?v={$version}" media="all">
|
||||
<script>
|
||||
window.CONFIG = {
|
||||
ADMIN: "{$adminModuleName|default='admin'}",
|
||||
CONTROLLER_JS_PATH: "{$thisControllerJsPath|default=''}",
|
||||
ACTION: "{$thisAction|default=''}",
|
||||
AUTOLOAD_JS: "{$autoloadJs|default='false'}",
|
||||
IS_SUPER_ADMIN: "{$isSuperAdmin|default='false'}",
|
||||
VERSION: "{$version|default='1.0.0'}",
|
||||
CSRF_TOKEN: "{:token()}",
|
||||
};
|
||||
</script>
|
||||
<script src="__STATIC__/plugs/layui-v2.8.x/layui.js?v={$version}" charset="utf-8"></script>
|
||||
<script src="__STATIC__/plugs/require-2.3.6/require.js?v={$version}" charset="utf-8"></script>
|
||||
<script src="__STATIC__/config-admin.js?v={$version}" charset="utf-8"></script>
|
||||
</head>
|
||||
<body>
|
||||
{__CONTENT__}
|
||||
</body>
|
||||
</html>
|
||||
45
app/admin/view/login/index.html
Normal file
45
app/admin/view/login/index.html
Normal file
@@ -0,0 +1,45 @@
|
||||
<link rel="stylesheet" href="__STATIC__/admin/css/login.css?v={$version}" media="all">
|
||||
<div class="main-body">
|
||||
<div class="login-main">
|
||||
<div class="login-top">
|
||||
<span>{:sysconfig('site','site_name')}</span>
|
||||
<span class="bg1"></span>
|
||||
<span class="bg2"></span>
|
||||
</div>
|
||||
<form class="layui-form login-bottom">
|
||||
<div class="demo{if !$demo} layui-hide{/if}">用户名:admin 密码:123456</div>
|
||||
<div class="center">
|
||||
|
||||
<div class="item">
|
||||
<span class="icon icon-2"></span>
|
||||
<input type="text" name="username" lay-verify="required" placeholder="请输入登录账号" maxlength="24"/>
|
||||
</div>
|
||||
|
||||
<div class="item">
|
||||
<span class="icon icon-3"></span>
|
||||
<input type="password" name="password" lay-verify="required" placeholder="请输入密码" maxlength="20">
|
||||
<span class="bind-password icon icon-4"></span>
|
||||
</div>
|
||||
|
||||
{if $captcha == 1}
|
||||
<div id="validatePanel" class="item" style="width: 137px;">
|
||||
<input type="text" name="captcha" placeholder="请输入验证码" maxlength="4">
|
||||
<img id="refreshCaptcha" class="validateImg" src="{:url('login/captcha')}" onclick="this.src='{:url(\'login/captcha\')}?seed='+Math.random()">
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
</div>
|
||||
<div class="tip">
|
||||
<span class="icon-nocheck"></span>
|
||||
<span class="login-tip">保持登录</span>
|
||||
<a href="javascript:" class="forget-password">忘记密码?</a>
|
||||
</div>
|
||||
<div class="layui-form-item" style="text-align:center; width:100%;height:100%;margin:0px;">
|
||||
<button class="login-btn" lay-submit>立即登录</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
{:sysconfig('site','site_copyright')}<span class="padding-5">|</span><a target="_blank" href="http://www.miitbeian.gov.cn">{:sysconfig('site','site_beian')}</a>
|
||||
</div>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user