有些问题,重置了下。
1
.env
Normal file
@ -0,0 +1 @@
|
||||
APP_DEBUG = true
[APP]
DEFAULT_TIMEZONE = Asia/Shanghai
[DATABASE]
TYPE = mysql
HOSTNAME = 127.0.0.1
DATABASE = fr_lab
USERNAME = root
PASSWORD =
HOSTPORT = 3306
CHARSET = utf8
DEBUG = true
[LANG]
default_lang = zh-cn
|
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
/.idea
|
||||
/.vscode
|
||||
*.log
|
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
|
32
LICENSE.txt
Normal file
@ -0,0 +1,32 @@
|
||||
|
||||
ThinkPHP遵循Apache2开源协议发布,并提供免费使用。
|
||||
版权所有Copyright © 2006-2016 by ThinkPHP (http://thinkphp.cn)
|
||||
All rights reserved。
|
||||
ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。
|
||||
|
||||
Apache Licence是著名的非盈利开源组织Apache采用的协议。
|
||||
该协议和BSD类似,鼓励代码共享和尊重原作者的著作权,
|
||||
允许代码修改,再作为开源或商业软件发布。需要满足
|
||||
的条件:
|
||||
1. 需要给代码的用户一份Apache Licence ;
|
||||
2. 如果你修改了代码,需要在被修改的文件中说明;
|
||||
3. 在延伸的代码中(修改和有源代码衍生的代码中)需要
|
||||
带有原来代码中的协议,商标,专利声明和其他原来作者规
|
||||
定需要包含的说明;
|
||||
4. 如果再发布的产品中包含一个Notice文件,则在Notice文
|
||||
件中需要带有本协议内容。你可以在Notice中增加自己的
|
||||
许可,但不可以表现为对Apache Licence构成更改。
|
||||
具体的协议参考:http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
59
README.md
Normal file
@ -0,0 +1,59 @@
|
||||
<!--
|
||||
* @Author: 彭雨
|
||||
* @Date: 2019-10-24 11:08:49
|
||||
* @LastEditors : 彭雨
|
||||
* @LastEditTime : 2020-01-09 12:35:37
|
||||
-->
|
||||
# authorize
|
||||
|
||||
#### 介绍
|
||||
完整的权限控制系统,后端ThinkPHP 6 + 前端Layui 2.5.4,权限验证类使用5ini99/think-auth(已修改为适配ThinkPHP6)。
|
||||
|
||||
手上有套自己写的数据查询和数据图形化的系统,因为涉及到各个部门、各地办事处的用户权限不同,所以用了5ini99/think-auth权限控制类进行权限控制,发现还挺好用,所以特别将权限部分抽出来,适配最新版本ThinkPHP然后开源出来抛砖引玉,可用于二次开发。
|
||||
GitHub项目地址:[https://github.com/fkueyu/authorize](https://github.com/fkueyu/authorize)
|
||||
码云项目地址:[https://gitee.com/frxc/authorize](https://gitee.com/frxc/authorize)
|
||||
|
||||
#### 软件架构
|
||||
开发环境: XAMPP 3.2.4(PHP 7.3.7+Mysql),ThinkPHP 6.0.1,Layui 2.5.4,jquery 3.4.1
|
||||
后续ThinkPHP 6发布正式版本后会同步升级到最新版本。
|
||||
|
||||
#### 安装教程
|
||||
|
||||
1. 根据自身条件搭建环境,Linux环境和Windows Server环境建议使用宝塔面板。其它Windows可以选择XAMPP(以下内容以XAMPP为例)。
|
||||
2. 安装composer (后续可以升级ThinkPHP6框架核心)
|
||||
3. 切换到XAMPP的htdocs目录克隆本仓库
|
||||
4. 运行XAMPP,修改apache配置文件中网站根目录到ThinkPHP的public目录,下面是开发环境示例:
|
||||
找到配置文件中两行:
|
||||
DocumentRoot "D:/xampp7/htdocs"
|
||||
<Directory "D:/xampp7/htdocs">
|
||||
修改为:
|
||||
DocumentRoot "D:/xampp7/htdocs/authorize/public"
|
||||
<Directory "D:/xampp7/htdocs/authorize/public">
|
||||
5. 启动mysql数据库服务,参考ThinkPHP6官方手册配置数据库连接([https://www.kancloud.cn/manual/thinkphp6_0/1037531](https://www.kancloud.cn/manual/thinkphp6_0/1037531) )
|
||||
6. 导入数据数据库结构及演示数据,(共5张表),默认数据库名称为fr_lab,数据表前缀为fr_lab_,供导入的sql文件fr_lab.sql位于public目录
|
||||
7. 启动apache服务即可访问(管理员账号:admin,密码:123456)
|
||||
|
||||
|
||||
#### 使用说明
|
||||
|
||||
1. 若修改数据库名和表名需同步修改ThinkPHP数据库配置文件和think-auth验证类的源文件(位于\authorize\vendor\5ini99\think-auth\src\Auth.php)
|
||||
2. 欢迎提出问题和建议(QQ交流群:18685945,加群请备注项目名称)
|
||||
3. 查看代码前建议先仔细阅读,权限认证类功能特性(来自[https://github.com/5ini99/think-auth](https://github.com/5ini99/think-auth)):
|
||||
* 1,是对规则进行认证,不是对节点进行认证。用户可以把节点当作规则名称实现对节点进行认证。
|
||||
* $auth=new Auth(); $auth->check('规则名称','用户id')
|
||||
* 2,可以同时对多条规则进行认证,并设置多条规则的关系(or或者and)
|
||||
* $auth=new Auth(); $auth->check('规则1,规则2','用户id','and')
|
||||
* 第三个参数为and时表示,用户需要同时具有规则1和规则2的权限。 当第三个参数为or时,表示用户值需要具备其中一个条件即可。默认为or
|
||||
* 3,一个用户可以属于多个用户组(think_auth_group_access表 定义了用户所属用户组)。我们需要设置每个用户组拥有哪些规则(think_auth_group 定义了用户组权限)
|
||||
* 4,支持规则表达式。
|
||||
* 在think_auth_rule 表中定义一条规则时,如果type为1, condition字段就可以定义规则表达式。 如定义{score}>5 and {score}<100 表示用户的分数在5-100之间时这条规则才会通过。
|
||||
|
||||
#### 系统截图
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
1
app/.htaccess
Normal file
@ -0,0 +1 @@
|
||||
deny from all
|
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
@ -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);
|
||||
}
|
||||
}
|
8
app/Request.php
Normal file
@ -0,0 +1,8 @@
|
||||
<?php
|
||||
namespace app;
|
||||
|
||||
// 应用请求对象类
|
||||
class Request extends \think\Request
|
||||
{
|
||||
|
||||
}
|
2
app/common.php
Normal file
@ -0,0 +1,2 @@
|
||||
<?php
|
||||
// 应用公共文件
|
429
app/controller/Authorize.php
Normal file
@ -0,0 +1,429 @@
|
||||
<?php
|
||||
|
||||
namespace app\controller;
|
||||
|
||||
use think\facade\{Session, Request, View};
|
||||
use app\model\{AuthGroup, AuthRule, User, AuthGroupAccess};
|
||||
use think\auth\Auth;
|
||||
|
||||
class Authorize
|
||||
{
|
||||
private $auth;
|
||||
|
||||
//检查是否登录
|
||||
public function __construct()
|
||||
{
|
||||
if ('' == Session::get('id')) {
|
||||
echo View::fetch('/login');
|
||||
exit;
|
||||
} else {
|
||||
$this->auth = Auth::instance();
|
||||
}
|
||||
}
|
||||
|
||||
//用户管理
|
||||
public function User()
|
||||
{
|
||||
if ($this->auth->check('user_list', Session::get('id'))) {
|
||||
return View::fetch('/authorize/user');
|
||||
}
|
||||
}
|
||||
|
||||
//个人信息
|
||||
public function personal()
|
||||
{
|
||||
return View::fetch('/authorize/personal');
|
||||
}
|
||||
|
||||
//添加用户
|
||||
public function addUser()
|
||||
{
|
||||
if ($this->auth->check('user_list', Session::get('id'))) {
|
||||
return View::fetch('/authorize/add_user');
|
||||
}
|
||||
}
|
||||
|
||||
//角色管理
|
||||
public function group()
|
||||
{
|
||||
if ($this->auth->check('group_list', Session::get('id'))) {
|
||||
return View::fetch('/authorize/group');
|
||||
}
|
||||
}
|
||||
|
||||
//菜单(规则)管理
|
||||
public function rules()
|
||||
{
|
||||
if ($this->auth->check('menu_list', Session::get('id'))) {
|
||||
return View::fetch('/authorize/rules');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改个人信息
|
||||
* @access public
|
||||
* @param int $id 个人id
|
||||
* @param string $field 修改的字段名
|
||||
* @param string $value 修改为该值
|
||||
* @param string $opassword 修改密码时需提供旧密码验证
|
||||
* @return json
|
||||
*/
|
||||
public function updatePersonal($id, $field, $value, $opassword = '')
|
||||
{
|
||||
$User = new User;
|
||||
$result = $User->updatePersonal($id, $field, $value, $opassword);
|
||||
return json($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取个人数据
|
||||
* @access public
|
||||
* @return json
|
||||
*/
|
||||
public function getPersonal()
|
||||
{
|
||||
$User = new User;
|
||||
$result = $User->getPersonal();
|
||||
return json($result);
|
||||
}
|
||||
|
||||
// 新增用户数据
|
||||
public function saveUser()
|
||||
{
|
||||
if ($this->auth->check('user_list', Session::get('id'))) {
|
||||
$user = [
|
||||
'name' => input('name'),
|
||||
'username' => input('username'),
|
||||
'password' => password_hash(input('password'), PASSWORD_ARGON2I),
|
||||
'email' => input('email'),
|
||||
'tel' => input('tel'),
|
||||
'position' => input('position'),
|
||||
'department' => input('department'),
|
||||
];
|
||||
$User = new User;
|
||||
return $User->saveUser($user, input('group'));
|
||||
}
|
||||
}
|
||||
|
||||
//读取所有用户数据
|
||||
public function getUsers()
|
||||
{
|
||||
if ($this->auth->check('user_list', Session::get('id'))) {
|
||||
$rows = input('limit') ?? 10;
|
||||
$page = input('page') ?? 1;
|
||||
$page -= 1;
|
||||
$offset = ($page) * $rows;
|
||||
$result = array();
|
||||
$result['code'] = 0;
|
||||
$result['msg'] = '';
|
||||
$result['count'] = User::where('name', 'like', '%' . input('name') . '%')->where('tel', 'like', '%' . input('tel') . '%')->count();
|
||||
$result_temp = User::field('id,name,username,email,tel,department,position,status,update_time,create_time')->where('name', 'like', '%' . input('name') . '%')->where('tel', 'like', '%' . input('tel') . '%')->limit($offset, $rows)->select()->toArray();
|
||||
$i = 0;
|
||||
foreach ($result_temp as $value) {
|
||||
$group_ids = AuthGroupAccess::where('uid', $value['id'])->select();
|
||||
$group_title = '';
|
||||
if ($group_ids) {
|
||||
foreach ($group_ids as $group_id) {
|
||||
$group_titles = AuthGroup::field('title')->where('id', $group_id['group_id'])->select()->toArray();
|
||||
$group_title .= $group_titles[0]['title'] . ',';
|
||||
}
|
||||
$group_title = substr($group_title, 0, strlen($group_title) - 1);
|
||||
$result_temp[$i]['group'] = $group_title;
|
||||
}
|
||||
++$i;
|
||||
}
|
||||
$result['data'] = $result_temp;
|
||||
|
||||
return json($result);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除用户
|
||||
* @access public
|
||||
* @param int $id 个人id
|
||||
* @return json
|
||||
*/
|
||||
public function delUser($id)
|
||||
{
|
||||
if ($this->auth->check('user_list', Session::get('id'))) {
|
||||
$User = new User;
|
||||
return json($User->delUser($id));
|
||||
}
|
||||
}
|
||||
|
||||
//修改用户数据
|
||||
public function updateUser()
|
||||
{
|
||||
$id = Request::param('id');
|
||||
$field = Request::param('field');
|
||||
$value = Request::param('value');
|
||||
if ($this->auth->check('user_list', Session::get('id'))) {
|
||||
if ('password_hash' == $field) {
|
||||
$value = password_hash($value, PASSWORD_ARGON2I);
|
||||
}
|
||||
if (1 == $id && 'status' == $field && 1 != $value) {
|
||||
return '系统管理员无法禁用';
|
||||
}
|
||||
$user = User::find($id);
|
||||
$user->$field = $value;
|
||||
|
||||
return $user->save() ? '更新成功' : '更新失败';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增角色组
|
||||
* @access public
|
||||
* @param string $title 角色组名称
|
||||
* @return json
|
||||
*/
|
||||
public function saveGroup()
|
||||
{
|
||||
$title = Request::param('title');
|
||||
if ($this->auth->check('group_list', Session::get('id'))) {
|
||||
$AuthGroup = new AuthGroup;
|
||||
return json($AuthGroup->saveGroup($title));
|
||||
}
|
||||
}
|
||||
|
||||
//读取用户组数据
|
||||
public function getGroup()
|
||||
{
|
||||
if ($this->auth->check('group_list', Session::get('id'))) {
|
||||
$rows = input('limit') ?? 10;
|
||||
$page = input('page') ?? 1;
|
||||
$page -= 1;
|
||||
$offset = ($page) * $rows;
|
||||
$result['code'] = 0;
|
||||
$result['msg'] = '';
|
||||
$result['count'] = AuthGroup::where('title', 'like', '%' . input('title') . '%')->count();
|
||||
$result['data'] = AuthGroup::where('title', 'like', '%' . input('title') . '%')->limit($offset, $rows)->select();
|
||||
|
||||
return json($result);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新用户组
|
||||
* @access public
|
||||
* @param int $id 用户组id
|
||||
* @param string $field 需修改的字段
|
||||
* @param string $value 修改为
|
||||
* @return string
|
||||
*/
|
||||
public function updateGroup()
|
||||
{
|
||||
$id = Request::param('id');
|
||||
$field = Request::param('field');
|
||||
$value = Request::param('value');
|
||||
if ($this->auth->check('group_list', Session::get('id'))) {
|
||||
$AuthGroup = new AuthGroup;
|
||||
return $AuthGroup->updateGroup($id, $field, $value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除用户组
|
||||
* @access public
|
||||
* @param int $id 用户组id
|
||||
* @return json
|
||||
*/
|
||||
public function delGroup()
|
||||
{
|
||||
$id = Request::param('id');
|
||||
if ($this->auth->check('group_list', Session::get('id'))) {
|
||||
$AuthGroup = new AuthGroup;
|
||||
return json($AuthGroup->delGroup($id));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取用户组规则
|
||||
* @access public
|
||||
* @param int $id 用户组id
|
||||
* @return json
|
||||
*/
|
||||
public function getUserRules()
|
||||
{
|
||||
$id = Request::param('id');
|
||||
if ($this->auth->check('group_list', Session::get('id'))) {
|
||||
$userRules = AuthGroup::where('id', $id)->field('title,rules')->select()->toArray();
|
||||
$rules = explode(',', $userRules[0]['rules']);
|
||||
//获取根节点
|
||||
$result = AuthRule::where('id', 1)->field('title,id')->select()->toArray();
|
||||
//获取一级节点
|
||||
$children = AuthRule::where('pid', $result[0]['id'])->field('title,id')->order('navid')->select()->toArray();
|
||||
//获取二级节点
|
||||
$y = 0;
|
||||
foreach ($children as $value) {
|
||||
$children1 = AuthRule::where('pid', $value['id'])->field('title,id')->order('navid')->select()->toArray();
|
||||
if (empty($children1)) {
|
||||
$children[$y]['children'] = array(); //二节节点不存在时将children设置为空数组
|
||||
if (in_array($value['id'], $rules)) {
|
||||
$children[$y]['checked'] = true; //一节节点为末节点且有权限时设置选择状态
|
||||
}
|
||||
} else {
|
||||
//二节节点存在时设置为展开状态
|
||||
$children[$y]['spread'] = true;
|
||||
$i = 0;
|
||||
//向二级节点数组增加checked状态并设置children为空
|
||||
foreach ($children1 as $ch) {
|
||||
if (in_array($ch['id'], $rules)) {
|
||||
$children1[$i]['checked'] = true;
|
||||
}
|
||||
$children1[$i]['children'] = array();
|
||||
++$i;
|
||||
}
|
||||
$children[$y]['children'] = $children1;
|
||||
}
|
||||
++$y;
|
||||
}
|
||||
//设置根节点为展开状态,并添加children
|
||||
$result[0]['spread'] = true;
|
||||
$result[0]['children'] = $children;
|
||||
|
||||
return json($result);
|
||||
}
|
||||
}
|
||||
|
||||
// 读取组所包含用户
|
||||
public function getUserGroup($id = '')
|
||||
{
|
||||
if ($this->auth->check('group_list', Session::get('id'))) {
|
||||
$groupUser = AuthGroupAccess::where('group_id', $id)->field('uid')->select()->toArray();
|
||||
$users = array();
|
||||
if ($groupUser != array()) {
|
||||
foreach ($groupUser as $value) {
|
||||
$users[] = $value['uid'];
|
||||
}
|
||||
}
|
||||
//根节点
|
||||
$row[0]['title'] = '全选';
|
||||
$row[0]['id'] = 0;
|
||||
$result = User::field('name,username,id')->where('status', 1)->select()->toArray();
|
||||
$y = 0;
|
||||
//向一级节点数组增加title、checked状态并设置children为空
|
||||
foreach ($result as $value) {
|
||||
$result[$y]['title'] = $result[$y]['name'] . ' [' . $result[$y]['username'] . ']';
|
||||
if (in_array($value['id'], $users)) {
|
||||
$result[$y]['checked'] = true;
|
||||
}
|
||||
$result[$y]['children'] = array();
|
||||
++$y;
|
||||
}
|
||||
$row[0]['spread'] = true;
|
||||
$row[0]['children'] = $result;
|
||||
|
||||
return json($row);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新用户组所包含的账户
|
||||
* @access public
|
||||
* @param int $id 用户组id
|
||||
* @param string $users 用户ID(逗号分隔字符串)
|
||||
* @return json
|
||||
*/
|
||||
public function updateGroupUser()
|
||||
{
|
||||
$id = Request::param('id');
|
||||
$users = Request::param('users');
|
||||
if ($this->auth->check('group_list', Session::get('id'))) {
|
||||
$AuthGroupAccess = new AuthGroupAccess;
|
||||
return json($AuthGroupAccess->updateGroupUser($id, $users));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取规则
|
||||
* @access public
|
||||
* @param int $id 规则id
|
||||
* @return json
|
||||
*/
|
||||
public function getRules()
|
||||
{
|
||||
$id = Request::param('id');
|
||||
if ($this->auth->check('menu_list', Session::get('id'))) {
|
||||
$AuthRule = new AuthRule;
|
||||
return json($AuthRule->getRules($id));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新规则单个字段(状态字段)
|
||||
* @access public
|
||||
* @param int $id 规则id
|
||||
* @param string $field 需修改的字段
|
||||
* @param string $value 修改为
|
||||
* @return string
|
||||
*/
|
||||
public function updateRulesState()
|
||||
{
|
||||
$id = Request::param('id');
|
||||
$field = Request::param('field');
|
||||
$value = Request::param('value');
|
||||
if ($this->auth->check('menu_list', Session::get('id'))) {
|
||||
$AuthRule = new AuthRule;
|
||||
return $AuthRule->updateRulesState($id, $field, $value) ? '更新成功' : '更新失败';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除规则
|
||||
* @access public
|
||||
* @param int $id 规则id
|
||||
* @return string
|
||||
*/
|
||||
public function delRules()
|
||||
{
|
||||
$id = Request::param('id');
|
||||
if ($this->auth->check('menu_list', Session::get('id'))) {
|
||||
$AuthRule = new AuthRule;
|
||||
return json($AuthRule->delRules($id));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增规则
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function saveRules()
|
||||
{
|
||||
if ($this->auth->check('menu_list', Session::get('id'))) {
|
||||
$rules = [
|
||||
'pid' => input('pid'),
|
||||
'name' => input('name'),
|
||||
'title' => input('title'),
|
||||
'condition' => input('condition'),
|
||||
'remarks' => input('remarks')
|
||||
];
|
||||
$AuthRule = new AuthRule;
|
||||
return json($AuthRule->saveRules($rules));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新规则
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function updateRules()
|
||||
{
|
||||
if ($this->auth->check('menu_list', Session::get('id'))) {
|
||||
$rules = [
|
||||
'id' => input('id'),
|
||||
'pid' => input('pid'),
|
||||
'name' => input('name'),
|
||||
'title' => input('title'),
|
||||
'navid' => input('navid'),
|
||||
'condition' => input('condition'),
|
||||
'remarks' => input('remarks')
|
||||
];
|
||||
$AuthRule = new AuthRule;
|
||||
return json($AuthRule->updateRules($rules));
|
||||
}
|
||||
}
|
||||
}
|
97
app/controller/Common.php
Normal file
@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
namespace app\controller;
|
||||
|
||||
use think\facade\{Session, View, Db};
|
||||
use think\auth\Auth;
|
||||
|
||||
class Common
|
||||
{
|
||||
|
||||
//输出角色列表
|
||||
public function groupList()
|
||||
{
|
||||
$result = Db::name('auth_group')->field('id,title')->select();
|
||||
|
||||
return json($result);
|
||||
}
|
||||
|
||||
//数据字典
|
||||
public function sql()
|
||||
{
|
||||
$auth = Auth::instance();
|
||||
// 检测权限
|
||||
if ($auth->check('sql', Session::get('id'))) {// 第一个参数是规则名称,第二个参数是用户UID
|
||||
$database = 'fr_lab';
|
||||
$table_result = Db::query('show tables');
|
||||
$no_show_table = array(); //不需要显示的表
|
||||
$no_show_field = array(); //不需要显示的字段
|
||||
//取得所有的表名
|
||||
foreach ($table_result as $row) {
|
||||
if (!in_array($row, $no_show_table)) {
|
||||
$tables[]['TABLE_NAME'] = $row['Tables_in_fr_lab'];
|
||||
}
|
||||
}
|
||||
//循环取得所有表的备注及表中列消息
|
||||
foreach ($tables as $k => $v) {
|
||||
$sql = 'SELECT * FROM ';
|
||||
$sql .= 'INFORMATION_SCHEMA.TABLES ';
|
||||
$sql .= 'WHERE ';
|
||||
$sql .= "table_name = '{$v['TABLE_NAME']}' AND table_schema = '{$database}'";
|
||||
$table_result = Db::query($sql);
|
||||
foreach ($table_result as $t) {
|
||||
$tables[$k]['TABLE_COMMENT'] = $t['TABLE_COMMENT'];
|
||||
}
|
||||
|
||||
$sql = 'SELECT * FROM ';
|
||||
$sql .= 'INFORMATION_SCHEMA.COLUMNS ';
|
||||
$sql .= 'WHERE ';
|
||||
$sql .= "table_name = '{$v['TABLE_NAME']}' AND table_schema = '{$database}'";
|
||||
|
||||
$fields = array();
|
||||
$field_result = Db::query($sql);
|
||||
foreach ($field_result as $t) {
|
||||
$fields[] = $t;
|
||||
}
|
||||
$tables[$k]['COLUMN'] = $fields;
|
||||
}
|
||||
$html = '';
|
||||
//循环所有表
|
||||
foreach ($tables as $k => $v) {
|
||||
$html .= ' <h3>'.($k + 1).'、'.$v['TABLE_COMMENT'].' ('.$v['TABLE_NAME'].')</h3>'."\n";
|
||||
$html .= ' <table border="1" cellspacing="0" cellpadding="0" width="100%">'."\n";
|
||||
$html .= ' <tbody>'."\n";
|
||||
$html .= ' <tr>'."\n";
|
||||
$html .= ' <th>字段名</th>'."\n";
|
||||
$html .= ' <th>数据类型</th>'."\n";
|
||||
$html .= ' <th>默认值</th>'."\n";
|
||||
$html .= ' <th>允许非空</th>'."\n";
|
||||
$html .= ' <th>自动递增</th>'."\n";
|
||||
$html .= ' <th>备注</th>'."\n";
|
||||
$html .= ' </tr>'."\n";
|
||||
foreach ($v['COLUMN'] as $f) {
|
||||
if (@!is_array($no_show_field[$v['TABLE_NAME']])) {
|
||||
$no_show_field[$v['TABLE_NAME']] = array();
|
||||
}
|
||||
if (!in_array($f['COLUMN_NAME'], $no_show_field[$v['TABLE_NAME']])) {
|
||||
$html .= ' <tr>'."\n";
|
||||
$html .= ' <td class="c1">'.$f['COLUMN_NAME'].'</td>'."\n";
|
||||
$html .= ' <td class="c2">'.$f['COLUMN_TYPE'].'</td>'."\n";
|
||||
$html .= ' <td class="c3">'.$f['COLUMN_DEFAULT'].'</td>'."\n";
|
||||
$html .= ' <td class="c4">'.$f['IS_NULLABLE'].'</td>'."\n";
|
||||
$html .= ' <td class="c5">'.('auto_increment' == $f['EXTRA'] ? '是' : ' ').'</td>'."\n";
|
||||
$html .= ' <td class="c6">'.$f['COLUMN_COMMENT'].'</td>'."\n";
|
||||
$html .= ' </tr>'."\n";
|
||||
}
|
||||
}
|
||||
$html .= ' </tbody>'."\n";
|
||||
$html .= ' </table>'."\n";
|
||||
}
|
||||
|
||||
View::assign('html', $html);
|
||||
|
||||
return View::fetch('/sql');
|
||||
}
|
||||
return '无权访问';
|
||||
}
|
||||
}
|
49
app/controller/Index.php
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace app\controller;
|
||||
|
||||
use think\facade\{Session, View, Request};
|
||||
use app\model\{User, Log};
|
||||
|
||||
class Index
|
||||
{
|
||||
|
||||
public function login()
|
||||
{
|
||||
$username = Request::param('username');
|
||||
$password = Request::param('password');
|
||||
if ('' != $username || '' != Session::get('user')) {
|
||||
if (Session::get('user')) {
|
||||
$this->redirect('index');
|
||||
} else {
|
||||
$User = new User;
|
||||
return json($User->login($username, $password));
|
||||
}
|
||||
} else {
|
||||
return View::fetch('/login');
|
||||
}
|
||||
}
|
||||
|
||||
//首页
|
||||
public function index()
|
||||
{
|
||||
if ('' != Session::get('id')) {
|
||||
return View::fetch('/header/index');
|
||||
} else {
|
||||
return View::fetch('/login');
|
||||
}
|
||||
}
|
||||
|
||||
//注销登录
|
||||
public function logout()
|
||||
{
|
||||
$username = Session::get('username');
|
||||
if ('' != $username) {
|
||||
$log_data = ['userid' => $username, 'operation' => 'logout', 'login_city' => ''];
|
||||
$Log = new Log;
|
||||
$Log->saveLog($log_data);
|
||||
}
|
||||
Session::clear();
|
||||
return json(['code' => 0, 'msg' => '您已安全退出', 'data' => '']);
|
||||
}
|
||||
}
|
17
app/event.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
// 事件定义文件
|
||||
return [
|
||||
'bind' => [
|
||||
],
|
||||
|
||||
'listen' => [
|
||||
'AppInit' => [],
|
||||
'HttpRun' => [],
|
||||
'HttpEnd' => [],
|
||||
'LogLevel' => [],
|
||||
'LogWrite' => [],
|
||||
],
|
||||
|
||||
'subscribe' => [
|
||||
],
|
||||
];
|
10
app/middleware.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
// 全局中间件定义文件
|
||||
return [
|
||||
// 全局请求缓存
|
||||
// \think\middleware\CheckRequestCache::class,
|
||||
// 多语言加载
|
||||
// \think\middleware\LoadLangPack::class,
|
||||
// Session初始化
|
||||
\think\middleware\SessionInit::class
|
||||
];
|
72
app/model/AuthGroup.php
Normal file
@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use think\Model;
|
||||
use app\model\{AuthGroupAccess};
|
||||
|
||||
class AuthGroup extends Model
|
||||
{
|
||||
/**
|
||||
* 新增角色组
|
||||
* @access public
|
||||
* @param string $title 角色组名称
|
||||
* @return json
|
||||
*/
|
||||
public function saveGroup($title)
|
||||
{
|
||||
if ('' == $title) {
|
||||
$result = ['code' => -1, 'msg' => '请输入角色名'];
|
||||
} else {
|
||||
$group = array();
|
||||
$group['title'] = $title;
|
||||
$row = AuthGroup::where('title', $title)->count();
|
||||
if ($row > 0) {
|
||||
$result = ['code' => -2, 'msg' => '添加失败,角色【' . $title . '】已存在'];
|
||||
} else {
|
||||
$this->create($group);
|
||||
$result = ['code' => 0, 'msg' => '角色【' . $title . '】添加成功'];
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新用户组
|
||||
* @access public
|
||||
* @param int $id 用户组id
|
||||
* @param string $field 需修改的字段
|
||||
* @param string $value 修改为
|
||||
* @return string
|
||||
*/
|
||||
public function updateGroup($id, $field, $value = '')
|
||||
{
|
||||
$updateGroup = AuthGroup::find($id);
|
||||
$updateGroup->setAttr($field, $value);
|
||||
$updateGroup->save();
|
||||
return '更新成功';
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除用户组
|
||||
* @access public
|
||||
* @param int $id 用户组id
|
||||
* @return json
|
||||
*/
|
||||
public function delGroup($id)
|
||||
{
|
||||
if (1 == $id) {
|
||||
$result = ['code' => -1, 'msg' => '角色【系统管理员】禁止删除'];
|
||||
} else {
|
||||
$group = AuthGroup::find($id);
|
||||
if ($group) {
|
||||
AuthGroupAccess::where('group_id', $id)->delete(); //删除角色与用户关系
|
||||
$group->delete();
|
||||
$result = ['code' => 0, 'msg' => '删除成功'];
|
||||
} else {
|
||||
$result = ['code' => -1, 'msg' => '删除的角色不存在'];
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
49
app/model/AuthGroupAccess.php
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use think\Model;
|
||||
|
||||
class AuthGroupAccess extends Model
|
||||
{
|
||||
/**
|
||||
* 更新用户组所包含的账户
|
||||
* @access public
|
||||
* @param int $id 用户组id
|
||||
* @param string $users 用户ID(逗号分隔字符串)
|
||||
* @return json
|
||||
*/
|
||||
public function updateGroupUser($id, $users)
|
||||
{
|
||||
//取出数据库中当前角色与组关系,后续若写入失败用于恢复
|
||||
$oldInfo = AuthGroupAccess::where('group_id', $id)->select()->toArray();
|
||||
//清空该用户组与人员的对应关系
|
||||
$this->where('group_id', $id)->delete();
|
||||
//重新写入对应关系
|
||||
if ('' != $users) {
|
||||
$users = explode(',', $users); //角色列表字符串转换为数组
|
||||
if (!in_array('1', $users) && 1 == $id) {
|
||||
$this->saveAll($oldInfo);
|
||||
return ['code' => -2, 'msg' => '系统管理员组必须包含管理员(admin)'];
|
||||
}
|
||||
$data = array(); //创建空数组用于保存用户组对应关系
|
||||
foreach ($users as $user) {
|
||||
$data[] = ['uid' => $user, 'group_id' => $id];
|
||||
}
|
||||
if ($this->saveAll($data)) {
|
||||
$rows = ['code' => 0, 'msg' => '角色成员更新成功'];
|
||||
} else {
|
||||
$this->saveAll($oldInfo);
|
||||
$rows = ['code' => -1, 'msg' => '角色成员更新出错'];
|
||||
}
|
||||
} else {
|
||||
if (1 == $id) {
|
||||
$this->saveAll($oldInfo);
|
||||
$rows = ['code' => -2, 'msg' => '系统管理员组必须包含管理员(admin)'];
|
||||
} else {
|
||||
$rows = ['code' => 0, 'msg' => '角色成员已全部清除'];
|
||||
}
|
||||
}
|
||||
return $rows;
|
||||
}
|
||||
}
|
119
app/model/AuthRule.php
Normal file
@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use think\Model;
|
||||
|
||||
class AuthRule extends Model
|
||||
{
|
||||
/**
|
||||
* 读取规则
|
||||
* @access public
|
||||
* @param int $id 规则id
|
||||
* @return json
|
||||
*/
|
||||
public function getRules($id)
|
||||
{
|
||||
if ('' == $id) {
|
||||
$result = AuthRule::field('id,title as name,pid,navid,name as title,type,status,condition,remarks')
|
||||
->order('navid')
|
||||
->select()
|
||||
->toArray();
|
||||
} else {
|
||||
//修改规则的二次读取
|
||||
$result = AuthRule::where('id', $id)->field('id,title as name,pid,navid,name as title,type,status,condition,remarks')
|
||||
->select()
|
||||
->toArray();
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新规则单个字段(状态字段)
|
||||
* @access public
|
||||
* @param int $id 规则id
|
||||
* @param string $field 需修改的字段
|
||||
* @param string $value 修改为
|
||||
* @return string
|
||||
*/
|
||||
public function updateRulesState($id, $field, $value)
|
||||
{
|
||||
$AuthRule = AuthRule::find($id);
|
||||
$AuthRule->setAttr($field, $value);
|
||||
$AuthRule->save();
|
||||
return '更新成功';
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除规则
|
||||
* @access public
|
||||
* @param int $id 规则id
|
||||
* @return string
|
||||
*/
|
||||
public function delRules($id)
|
||||
{
|
||||
if (1 === $id) {
|
||||
$result = ['code' => -1, 'msg' => '根节点禁止删除'];
|
||||
} else {
|
||||
$children = AuthRule::where('pid', $id)->count();
|
||||
if ($children > 0) {
|
||||
$result = ['code' => -2, 'msg' => '此节点存在子规则,需先删除子规则'];
|
||||
} else {
|
||||
if ($this->where('id', $id)->delete()) {
|
||||
$result = ['code' => 0, 'msg' => '删除成功'];
|
||||
} else {
|
||||
$result = ['code' => -3, 'msg' => '规则不存在'];
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增规则
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function saveRules($rules)
|
||||
{
|
||||
if ('' == $rules['pid'] || '' == $rules['name'] || '' == $rules['title']) {
|
||||
$result = ['code' => -1, 'msg' => '缺少必要字段,请检查'];
|
||||
} else {
|
||||
$row = AuthRule::whereOr(['name' => $rules['name'], 'title' => $rules['title']])->count();
|
||||
if ($row) {
|
||||
$result = ['code' => -2, 'msg' => '添加失败,名称或控制器已存在'];
|
||||
} else {
|
||||
$this->create($rules);
|
||||
$result = ['code' => 0, 'msg' => '规则[ ' . $rules['title'] . ' ]添加成功'];
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
/**
|
||||
* 更新规则
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function updateRules($rules)
|
||||
{
|
||||
if ('' == $rules['id'] || '' == $rules['pid'] || '' == $rules['name'] || '' == $rules['title']) {
|
||||
$result = ['code' => -1, 'msg' => '缺少必要字段,请检查'];
|
||||
} else {
|
||||
$row = AuthRule::where("id <> {$rules['id']} AND (title = '{$rules['title']}' OR name = '{$rules['name']}')")->count();
|
||||
if ($row) {
|
||||
$result = ['code' => -2, 'msg' => '更新失败,名称或控制器已存在'];
|
||||
} else {
|
||||
$AuthRule = AuthRule::find($rules['id']);
|
||||
$AuthRule->setAttr('name', $rules['name']);
|
||||
$AuthRule->setAttr('title', $rules['title']);
|
||||
$AuthRule->setAttr('pid', $rules['pid']);
|
||||
$AuthRule->setAttr('navid', $rules['navid']);
|
||||
$AuthRule->setAttr('condition', $rules['condition']);
|
||||
$AuthRule->setAttr('remarks', $rules['remarks']);
|
||||
$AuthRule->save();
|
||||
$result = ['code' => 0, 'msg' => '规则[ ' . $rules['title'] . ' ]更新成功'];
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
19
app/model/Log.php
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use think\Model;
|
||||
|
||||
class Log extends Model
|
||||
{
|
||||
/**
|
||||
* 新增LOG数据
|
||||
* @access public
|
||||
* @return json
|
||||
*/
|
||||
public function saveLog($log)
|
||||
{
|
||||
$this->create($log);
|
||||
return 0;
|
||||
}
|
||||
}
|
134
app/model/User.php
Normal file
@ -0,0 +1,134 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use think\Model;
|
||||
use think\facade\{Session};
|
||||
use app\model\{AuthGroupAccess, Log};
|
||||
|
||||
class User extends Model
|
||||
{
|
||||
public function login($username, $password)
|
||||
{
|
||||
$user = User::where('username', $username)->find();
|
||||
if (password_verify($password, $user->password_hash)) {
|
||||
$this->assistant = new \mylib\Assistant();
|
||||
$time = date('Y-m-d H:i:s');
|
||||
Session::set('id', $user->getAttr('id'));
|
||||
Session::set('user', $user->getAttr('name'));
|
||||
Session::set('username', $user->getAttr('username'));
|
||||
Session::set('tel', $user->getAttr('tel'));
|
||||
$log_data = ['userid' => $user->getAttr('username'), 'operation' => 'login', 'create_time' => $time];
|
||||
$Log = new Log;
|
||||
$Log->saveLog($log_data);
|
||||
$intensity = $this->assistant->checkPassword(input('password'));
|
||||
if (0 == $intensity['code']) {
|
||||
Session::set('intensity', 0);
|
||||
$result = ['code' => 0, 'data' => $_SERVER['HTTP_REFERER'], 'msg' => '登录成功,正在跳转...'];
|
||||
} else {
|
||||
Session::set('intensity', 1);
|
||||
$result = ['code' => 0, 'data' => '/authorize/personal', 'msg' => '密码强度不足,即将跳转到密码修改页...'];
|
||||
}
|
||||
} else {
|
||||
$result = ['code' => -1, 'data' => '', 'msg' => '账号或密码错误,请重试'];
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改个人信息
|
||||
* @access public
|
||||
* @param int $id 个人id
|
||||
* @param string $field 修改的字段名
|
||||
* @param string $value 修改为该值
|
||||
* @param string $opassword 修改密码时需提供旧密码验证
|
||||
* @param string $level 为1时可直接修改密码
|
||||
* @return json
|
||||
*/
|
||||
public function updatePersonal($id, $field, $value, $opassword = '', $level = 0)
|
||||
{
|
||||
//更改密码时验证旧密码
|
||||
if ('password_hash' == $field && $level == 0) {
|
||||
$assistant = new \mylib\Assistant();
|
||||
$intensity = $assistant->checkPassword($value);
|
||||
if (1 == $intensity['code']) {
|
||||
$result = $intensity;
|
||||
} else {
|
||||
$password_hash = password_hash($value, PASSWORD_ARGON2I);
|
||||
$user = User::where('id', $id)->find();
|
||||
if (password_verify($opassword, $user->password_hash)) {
|
||||
$user->setAttr($field, $password_hash);
|
||||
$user->save();
|
||||
Session::set('intensity', 0);
|
||||
$result = ['code' => 0, 'data' => '/authorize/personal', 'msg' => '密码更新成功,即将刷新页面...'];
|
||||
} else {
|
||||
$result = ['code' => -1, 'data' => '', 'msg' => '旧密码错误,请检查'];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$personalInfo = User::find($id);
|
||||
$personalInfo->$field = $value;
|
||||
$personalInfo->save();
|
||||
$result = '更新成功';
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取个人数据
|
||||
* @access public
|
||||
* @return json
|
||||
*/
|
||||
public function getPersonal()
|
||||
{
|
||||
$result = array();
|
||||
$id = Session::get('id');
|
||||
$row = User::field('id,name,username,email,tel,department,position,status,update_time,create_time')
|
||||
->find($id)->toArray();
|
||||
$result = ['code' => 0, 'msg' => '', 'count' => 1, 'data' => [$row]];
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增用户数据
|
||||
* @access public
|
||||
* @return json
|
||||
*/
|
||||
public function saveUser($user, $group)
|
||||
{
|
||||
$row = User::where('username', $user['username'])->count();
|
||||
if ($row > 0) {
|
||||
return '添加失败,用户[ ' . $user['username'] . ' ]已存在';
|
||||
} else {
|
||||
$result = $this->create($user);
|
||||
$access = ['group_id' => $group, 'uid' => $result->id];
|
||||
if ('' != $access['group_id']) {
|
||||
AuthGroupAccess::create($access);
|
||||
}
|
||||
return '用户[ ' . $result->name . ' ]新增成功';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除用户
|
||||
* @access public
|
||||
* @param int $id 个人id
|
||||
* @return json
|
||||
*/
|
||||
public function delUser($id)
|
||||
{
|
||||
if (1 == $id) {
|
||||
$result = ['code' => -1, 'msg' => '用户【系统管理员】禁止删除'];
|
||||
} else {
|
||||
$user = User::find($id);
|
||||
if ($user) {
|
||||
AuthGroupAccess::where('uid', $id)->delete(); //删除用户与角色关系
|
||||
$user->delete();
|
||||
$result = ['code' => 0, 'msg' => '删除成功', 'data' => ''];
|
||||
} else {
|
||||
$result = ['code' => -2, 'msg' => '删除的用户不存在', 'data' => ''];
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
9
app/provider.php
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
use app\ExceptionHandle;
|
||||
use app\Request;
|
||||
|
||||
// 容器Provider定义文件
|
||||
return [
|
||||
'think\Request' => Request::class,
|
||||
'think\exception\Handle' => ExceptionHandle::class,
|
||||
];
|
1
app/view/README.md
Normal file
@ -0,0 +1 @@
|
||||
如果不使用模板,可以删除该目录
|
87
app/view/authorize/add_user.html
Normal file
@ -0,0 +1,87 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Authorize 添加账号</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">
|
||||
<link rel="stylesheet" href="/static/layui/css/layui.css">
|
||||
<link rel="stylesheet" href="/static/css/font.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<br>
|
||||
<form class="layui-form" id="user" action="">
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">角色</label>
|
||||
<div class="layui-input-block" style="width: 320px;">
|
||||
<select name="group" id="group" lay-filter="group" lay-verify="required">
|
||||
<option value="">请选择</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">姓名</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="name" name="name" lay-verify="required" style="width: 320px;" autocomplete="off"
|
||||
class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">账号</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="username" name="username" lay-verify="required" style="width: 320px;" autocomplete="off"
|
||||
class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">邮箱</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="email" lay-verify="email" style="width: 320px;" autocomplete="off" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">手机</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="tel" name="tel" lay-verify="required|phone" style="width: 320px;" autocomplete="off"
|
||||
class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">部门</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="department" name="department" style="width: 320px;" lay-verify="required" autocomplete="off"
|
||||
class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">职位</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="position" name="position" style="width: 320px;" lay-verify="required" autocomplete="off"
|
||||
class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">密码</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="password" name="password" style="width: 320px;" lay-verify="pass" placeholder="请填写6到12位密码"
|
||||
autocomplete="off" class="layui-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-input-block">
|
||||
<button class="layui-btn" lay-submit="" style="width: 120px;" lay-filter="submit">
|
||||
<i title="提交" class="iconfont"></i> 提交</button>
|
||||
<button id="reset" type="reset" style="width: 120px;" class="layui-btn layui-btn-primary">
|
||||
<i title="重置" class="iconfont">ဆ</i> 重置</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<script type="text/javascript" src="//cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
|
||||
<script src="/static/layui/layui.js" charset="utf-8"></script>
|
||||
<script src="/static/js/authorize/add_user.js?{:time()}" charset="utf-8"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
44
app/view/authorize/group.html
Normal file
@ -0,0 +1,44 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<title>Authorize 角色信息</title>
|
||||
<link rel="stylesheet" href="/static/layui/css/layui.css">
|
||||
<link rel="stylesheet" href="/static/css/font.css">
|
||||
</head>
|
||||
|
||||
<body class="layui-layout-body">
|
||||
<div class="layui-layout layui-layout-admin">
|
||||
{include file="public/header" /} {include file="public/leftside" usermenu="layui-nav-itemed" grouplist="layui-this"
|
||||
/}
|
||||
<fieldset class="layui-elem-field layui-field-title" style="margin-top: 20px;margin-bottom: 10px;">
|
||||
<legend>角色管理</legend>
|
||||
</fieldset>
|
||||
<div class="layui-from layui-form-pane" style="margin-bottom: 0px;">
|
||||
<div class="groupTable">
|
||||
<div class="layui-inline">
|
||||
<div class="layui-input-inline">
|
||||
<label class="layui-form-label" style="width: 80px;">角色名</label>
|
||||
<div class="layui-inline" style="width: 100px;">
|
||||
<input class="layui-input" name="title" id="title" autocomplete="off">
|
||||
</div>
|
||||
</div>
|
||||
<button title="搜索" class="layui-btn " data-type="reload">
|
||||
<i class="iconfont"></i>
|
||||
</button>
|
||||
<button title="添加" class="layui-btn layui-btn-warm" data-type="addGroup">
|
||||
<i class="iconfont"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<table id="grouplist" lay-filter="group"></table>
|
||||
<script type="text/javascript" src="//cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
|
||||
<script src="/static/layui/layui.js" charset="utf-8"></script>
|
||||
<script src="/static/js/authorize/group.js?{:time()}" charset="utf-8"></script>{include file="public/footer"/}
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
33
app/view/authorize/personal.html
Normal file
@ -0,0 +1,33 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<title>Authorize 个人中心</title>
|
||||
<link rel="stylesheet" href="/static/layui/css/layui.css">
|
||||
<link rel="stylesheet" href="/static/css/font.css">
|
||||
<script type="text/javascript" src="//cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
|
||||
<script src="/static/layui/layui.js" charset="utf-8"></script>
|
||||
</head>
|
||||
|
||||
<body class="layui-layout-body">
|
||||
<div class="layui-layout layui-layout-admin">
|
||||
{include file="public/header" /}{include file="public/leftside" /} {if($Request.session.intensity == 0)}
|
||||
<fieldset class="layui-elem-field layui-field-title" style="margin-top: 20px;margin-bottom: 10px;">
|
||||
<legend>个人中心</legend>
|
||||
</fieldset>
|
||||
{else}
|
||||
<fieldset class="layui-elem-field layui-field-title" style="margin-top: 20px;margin-bottom: 10px;">
|
||||
<legend>更新密码后提供完整功能</legend>
|
||||
</fieldset>
|
||||
{/if}
|
||||
<table id="user" lay-filter="user"></table>
|
||||
<script src="/static/js/authorize/personal.js?{:time()}" charset="utf-8"></script>
|
||||
<script type="text/html" id="toolbar">
|
||||
<a title="修改密码" class="layui-btn layui-btn-sm" lay-event="edit"><i class="layui-icon"></i>修改密码</a>
|
||||
</script> {include file="public/footer"/}
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
35
app/view/authorize/rules.html
Normal file
@ -0,0 +1,35 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<title>Authorize 规则信息</title>
|
||||
<link rel="stylesheet" href="/static/layui/css/layui.css">
|
||||
<link rel="stylesheet" href="/static/css/font.css">
|
||||
<script type="text/javascript" src="//cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
|
||||
<script src="/static/layui/layui.js" charset="utf-8"></script>
|
||||
</head>
|
||||
|
||||
<body class="layui-layout-body">
|
||||
<div class="layui-layout layui-layout-admin">
|
||||
{include file="public/header" /} {include file="public/leftside" usermenu="layui-nav-itemed" menulist="layui-this"
|
||||
/}
|
||||
<fieldset class="layui-elem-field layui-field-title" style="margin-top: 20px;margin-bottom: 10px;">
|
||||
<legend>规则管理</legend>
|
||||
</fieldset>
|
||||
<div class="layui-from layui-form-pane" style="margin-bottom: 0px;">
|
||||
<div class="userTable">
|
||||
<div class="layui-inline">
|
||||
<button type="button" class="layui-btn layui-btn-primary layui-btn-sm open-all">全部展开</button>
|
||||
<button type="button" class="layui-btn layui-btn-primary layui-btn-sm close-all">全部关闭</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<table class="layui-table layui-form" id="tree-table"></table>
|
||||
<script src="/static/js/authorize/rules.js?{:time()}" charset="utf-8"></script>
|
||||
{include file="public/footer"/}
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
54
app/view/authorize/user.html
Normal file
@ -0,0 +1,54 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<title>Authorize 用户信息</title>
|
||||
<link rel="stylesheet" href="/static/layui/css/layui.css">
|
||||
<link rel="stylesheet" href="/static/css/font.css">
|
||||
<script type="text/javascript" src="//cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
|
||||
<script src="/static/layui/layui.js" charset="utf-8"></script>
|
||||
</head>
|
||||
|
||||
<body class="layui-layout-body">
|
||||
<div class="layui-layout layui-layout-admin">
|
||||
{include file="public/header" /} {include file="public/leftside" usermenu="layui-nav-itemed" userlist="layui-this"
|
||||
/}
|
||||
<fieldset class="layui-elem-field layui-field-title" style="margin-top: 20px;margin-bottom: 10px;">
|
||||
<legend>账户管理</legend>
|
||||
</fieldset>
|
||||
<div class="layui-from layui-form-pane" style="margin-bottom: 0px;">
|
||||
<div class="userTable">
|
||||
<div class="layui-inline">
|
||||
<div class="layui-input-inline">
|
||||
<label class="layui-form-label" style="width: 60px;">姓名</label>
|
||||
<div class="layui-inline" style="width: 130px;">
|
||||
<input class="layui-input" name="name" id="name" autocomplete="off">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-input-inline">
|
||||
<label class="layui-form-label" style="width: 60px;">电话</label>
|
||||
<div class="layui-inline" style="width: 130px;">
|
||||
<input class="layui-input" name="tel" id="tel" autocomplete="off">
|
||||
</div>
|
||||
</div>
|
||||
<button title="搜索" class="layui-btn " data-type="reload">
|
||||
<i class="iconfont"></i>
|
||||
</button>
|
||||
<button title="添加" class="layui-btn layui-btn-warm" onclick="addUser();">
|
||||
<i class="iconfont"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<table id="userlist" lay-filter="user"></table>
|
||||
<script src="/static/js/authorize/user.js?{:time()}" charset="utf-8"></script>
|
||||
<script type="text/html" id="toolbar">
|
||||
<a title="修改密码" class="layui-btn layui-btn-xs" lay-event="edit"><i class="iconfont"></i></a>
|
||||
<a title="删除账号" class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del"><i class="iconfont"></i></a>
|
||||
</script> {include file="public/footer"/}
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
35
app/view/header/index.html
Normal file
@ -0,0 +1,35 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<title>Authorize</title>
|
||||
<link rel="stylesheet" href="/static/layui/css/layui.css">
|
||||
<link rel="stylesheet" href="/static/css/font.css">
|
||||
<script src="//cdn.bootcss.com/jquery/3.4.1/jquery.min.js" charset="utf-8"></script>
|
||||
<script src="/static/layui/layui.js" charset="utf-8"></script>
|
||||
<script>
|
||||
//JavaScript代码区域
|
||||
layui.use(['element', 'layer'], function () {
|
||||
var element = layui.element
|
||||
, layer = layui.layer;
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body class="layui-layout-body" style="background-color: #F2F2F2;">
|
||||
<div class="layui-layout layui-layout-admin">
|
||||
{include file="public/header" index="layui-this" /} {include file="public/leftside"/}
|
||||
<!-- 内容主体区域 -->
|
||||
<br>
|
||||
<span class="layui-breadcrumb">
|
||||
<a id="collect" title="查看明细">系统说明</a>
|
||||
</span>
|
||||
<div style="padding: 20px;">
|
||||
正文
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
57
app/view/login.html
Normal file
@ -0,0 +1,57 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<title>Authorize 后台登录</title>
|
||||
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />
|
||||
<link rel="stylesheet" href="/static/css/radmin.css">
|
||||
<script src="/static/layui/layui.js" charset="utf-8"></script>
|
||||
<script src="//cdn.bootcss.com/jquery/3.4.1/jquery.min.js" charset="utf-8"></script>
|
||||
</head>
|
||||
|
||||
<body class="login-bg">
|
||||
<div class="login">
|
||||
<div class="message">Authorize 权限控制</div>
|
||||
<div id="darkbannerwrap"></div>
|
||||
<form id="user" class="layui-form">
|
||||
<input name="username" placeholder="用户名" type="text" lay-verify="required" class="layui-input">
|
||||
<hr class="hr15">
|
||||
<input name="password" id="password" lay-verify="required" placeholder="密码" type="password" class="layui-input">
|
||||
<hr class="hr15">
|
||||
<hr class="hr15">
|
||||
<input value="登录" lay-submit lay-filter="login" style="width:100%;" type="submit">
|
||||
<hr class="hr20">
|
||||
</form>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
layui.use('form', function () {
|
||||
var form = layui.form;
|
||||
});
|
||||
})
|
||||
$("#user").on("submit", function (ev) {
|
||||
var e = layer.load(2, { shade: [0.2, '#2F4056'] });
|
||||
ev.preventDefault();
|
||||
$.post("/index/login", $("#user").serialize(), function (data) {
|
||||
if (data.code == 0) {
|
||||
layer.close(e);
|
||||
layer.msg(data.msg
|
||||
, { time: 3000 }
|
||||
, function () {
|
||||
location.replace(data.data);
|
||||
});
|
||||
} else {
|
||||
$("#password").val('');
|
||||
layer.close(e);
|
||||
layer.msg(data.msg, { time: 3000 });
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
<!-- 底部结束 -->
|
||||
</body>
|
||||
|
||||
</html>
|
25
app/view/public/exception.html
Normal file
@ -0,0 +1,25 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Authorize 404</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">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
<link rel="stylesheet" href="/static/css/layui.css">
|
||||
</head>
|
||||
|
||||
<body class="childrenBody">
|
||||
<div style="text-align: center; padding:11% 0;">
|
||||
<i class="layui-icon" style="line-height:20rem; font-size:20rem; color: #393D50;"></i>
|
||||
<p style="font-size: 20px; font-weight: 300; color: #999;">我勒个去,页面被外星人挟持了!</p>
|
||||
<br>
|
||||
<p><a style="font-size: 20px; font-weight: 300; color: #008B8B;" href="/index">返回首页</a></p>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
5
app/view/public/footer.html
Normal file
@ -0,0 +1,5 @@
|
||||
</div>
|
||||
<div class="layui-footer" style="left: 200px;">
|
||||
<!-- 底部固定区域 -->
|
||||
<span>© F.R Lab</span>
|
||||
</div>
|
85
app/view/public/header.html
Normal file
@ -0,0 +1,85 @@
|
||||
<?php
|
||||
use think\auth\Auth;
|
||||
$auth = Auth::instance();
|
||||
?>
|
||||
<div class="layui-header">
|
||||
<div class="layui-logo" style="color:#e2e2e2; font-size:25px">Authorize</div>
|
||||
<!-- 头部区域(可配合layui已有的水平导航) -->
|
||||
{if($Request.session.intensity == 0)}
|
||||
<ul class="layui-nav layui-layout-left">
|
||||
<li class="layui-nav-item">
|
||||
<i onclick="State();" title="关闭左侧栏" class="iconfont"></i>
|
||||
</li>
|
||||
{if($auth->check('header_index',$Request.session.id))}
|
||||
<li class="layui-nav-item [index]">
|
||||
<a href="/index">总览</a>
|
||||
</li>
|
||||
{/if}
|
||||
</ul>
|
||||
{/if}
|
||||
<ul class="layui-nav layui-layout-right">
|
||||
<li class="layui-nav-item">
|
||||
<a href="javascript:;">
|
||||
<img src="/static/images/user.png" class="layui-nav-img"> {$Request.session.user}
|
||||
</a>
|
||||
<dl class="layui-nav-child">
|
||||
<dd>
|
||||
<a href="/authorize/personal">
|
||||
<i class="iconfont"></i> 个人信息</a>
|
||||
</dd> {if($auth->check('sql', $Request.session.id))}
|
||||
<dd>
|
||||
<a href="/common/sql" target="_blank">
|
||||
<i class="iconfont"></i> 数据字典</a>
|
||||
</dd>
|
||||
{/if}
|
||||
</dl>
|
||||
</li>
|
||||
<li class="layui-nav-item">
|
||||
<a href="javascript:;" onclick="LogOut();">退出</a>
|
||||
</li>
|
||||
<li class="layui-nav-item">
|
||||
<a href="mailto:fkueyu@gmail.com">问题反馈</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<script>
|
||||
function State() {
|
||||
if ($('.layui-side').css('left') == '0px') {
|
||||
$('.layui-side').animate({
|
||||
left: '-200px'
|
||||
}, 100);
|
||||
$('.layui-body').animate({
|
||||
left: '0px'
|
||||
}, 100);
|
||||
$('.layui-footer').animate({
|
||||
left: '0px'
|
||||
}, 0);
|
||||
} else {
|
||||
$('.layui-side').animate({
|
||||
left: '0px'
|
||||
}, 100);
|
||||
$('.layui-body').animate({
|
||||
left: '200px'
|
||||
}, 100);
|
||||
$('.layui-footer').animate({
|
||||
left: '200px'
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
function LogOut() {
|
||||
var e = layer.load(2, { shade: [0.2, '#2F4056'] });
|
||||
$.post("/index/logOut", function (data) {
|
||||
if (data.code == 0) {
|
||||
layer.close(e);
|
||||
layer.msg(data.msg
|
||||
, { time: 2000 }
|
||||
, function () {
|
||||
location.reload();
|
||||
});
|
||||
} else {
|
||||
layer.close(e);
|
||||
layer.msg(data.msg, { time: 2000 });
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
34
app/view/public/leftside.html
Normal file
@ -0,0 +1,34 @@
|
||||
{if($Request.session.intensity == 0)}
|
||||
<div class="layui-side layui-bg-black" style="left: 0px;">
|
||||
<div class="layui-side-scroll">
|
||||
<!-- 左侧导航区域(可配合layui已有的垂直导航) -->
|
||||
<ul class="layui-nav layui-nav-tree" lay-filter="test">
|
||||
{if($auth->check('user', $Request.session.id))}
|
||||
<li class="layui-nav-item [usermenu]">
|
||||
<a class="" href="javascript:;">
|
||||
<i class="iconfont"></i> 权限管理</a>
|
||||
<dl class="layui-nav-child">
|
||||
{if($auth->check('user_list', $Request.session.id))}
|
||||
<dd class="[userlist]">
|
||||
<a href="/authorize/user">
|
||||
<i class="iconfont"></i> 用户管理</a>
|
||||
</dd>
|
||||
{/if} {if($auth->check('group_list', $Request.session.id))}
|
||||
<dd class="[grouplist]">
|
||||
<a href="/authorize/group">
|
||||
<i class="iconfont"></i> 角色管理</a>
|
||||
</dd>
|
||||
{/if} {if($auth->check('menu_list', $Request.session.id))}
|
||||
<dd class="[menulist]">
|
||||
<a href="/authorize/rules">
|
||||
<i class="iconfont"></i> 规则管理</a>
|
||||
</dd>
|
||||
{/if}
|
||||
</dl>
|
||||
</li>
|
||||
{/if}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-body" style="left: 200px;">
|
||||
{/if}
|
88
app/view/sql.html
Normal file
@ -0,0 +1,88 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-cmn-Hans">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=0">
|
||||
<title>数据字典</title>
|
||||
<style>
|
||||
body,
|
||||
td,
|
||||
th {
|
||||
font-family: "微软雅黑";
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.warp {
|
||||
margin: auto;
|
||||
width: 900px;
|
||||
}
|
||||
|
||||
.warp h3 {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
line-height: 30px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border: 1px solid #CCC;
|
||||
background: #efefef;
|
||||
}
|
||||
|
||||
table th {
|
||||
text-align: left;
|
||||
font-weight: bold;
|
||||
height: 26px;
|
||||
line-height: 26px;
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
border: 1px solid #CCC;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
table td {
|
||||
height: 20px;
|
||||
font-size: 14px;
|
||||
border: 1px solid #CCC;
|
||||
background-color: #fff;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.c1 {
|
||||
width: 120px;
|
||||
}
|
||||
|
||||
.c2 {
|
||||
width: 120px;
|
||||
}
|
||||
|
||||
.c3 {
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
.c4 {
|
||||
width: 80px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.c5 {
|
||||
width: 80px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.c6 {
|
||||
width: 270px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="warp">
|
||||
<h1 style="text-align:center;">数据字典</h1>
|
||||
<?php echo $html; ?>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
46
composer.json
Normal file
@ -0,0 +1,46 @@
|
||||
{
|
||||
"name": "topthink/think",
|
||||
"description": "the new thinkphp framework",
|
||||
"type": "project",
|
||||
"keywords": [
|
||||
"framework",
|
||||
"thinkphp",
|
||||
"ORM"
|
||||
],
|
||||
"homepage": "http://thinkphp.cn/",
|
||||
"license": "Apache-2.0",
|
||||
"authors": [
|
||||
{
|
||||
"name": "liu21st",
|
||||
"email": "liu21st@gmail.com"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=7.1.0",
|
||||
"topthink/framework": "^6.0.0",
|
||||
"topthink/think-orm": "^2.0",
|
||||
"topthink/think-view": "^1.0",
|
||||
"5ini99/think-auth": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/var-dumper": "^4.2",
|
||||
"topthink/think-trace":"^1.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"app\\": "app"
|
||||
},
|
||||
"psr-0": {
|
||||
"": "extend/"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"preferred-install": "dist"
|
||||
},
|
||||
"scripts": {
|
||||
"post-autoload-dump": [
|
||||
"@php think service:discover",
|
||||
"@php think vendor:publish"
|
||||
]
|
||||
}
|
||||
}
|
999
composer.lock
generated
Normal file
@ -0,0 +1,999 @@
|
||||
{
|
||||
"_readme": [
|
||||
"This file locks the dependencies of your project to a known state",
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "3f299da8589ea3b7ae902440978b9a29",
|
||||
"packages": [
|
||||
{
|
||||
"name": "5ini99/think-auth",
|
||||
"version": "1.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/5ini99/think-auth.git",
|
||||
"reference": "f9f20d18b5e400d67312a7ca75e4dc35be630a4c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/5ini99/think-auth/zipball/f9f20d18b5e400d67312a7ca75e4dc35be630a4c",
|
||||
"reference": "f9f20d18b5e400d67312a7ca75e4dc35be630a4c",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||
"preferred": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.4.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"think\\auth\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"Apache-2.0"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "xiaobo.sun",
|
||||
"email": "xiaobo.sun@qq.com"
|
||||
}
|
||||
],
|
||||
"description": "auth package for thinkphp5",
|
||||
"homepage": "https://github.com/5ini99/think-auth",
|
||||
"time": "2016-11-02T06:26:09+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/flysystem",
|
||||
"version": "1.0.63",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/flysystem.git",
|
||||
"reference": "8132daec326565036bc8e8d1876f77ec183a7bd6"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/flysystem/zipball/8132daec326565036bc8e8d1876f77ec183a7bd6",
|
||||
"reference": "8132daec326565036bc8e8d1876f77ec183a7bd6",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||
"preferred": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"require": {
|
||||
"ext-fileinfo": "*",
|
||||
"php": ">=5.5.9"
|
||||
},
|
||||
"conflict": {
|
||||
"league/flysystem-sftp": "<1.0.6"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpspec/phpspec": "^3.4",
|
||||
"phpunit/phpunit": "^5.7.10"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-fileinfo": "Required for MimeType",
|
||||
"ext-ftp": "Allows you to use FTP server storage",
|
||||
"ext-openssl": "Allows you to use FTPS server storage",
|
||||
"league/flysystem-aws-s3-v2": "Allows you to use S3 storage with AWS SDK v2",
|
||||
"league/flysystem-aws-s3-v3": "Allows you to use S3 storage with AWS SDK v3",
|
||||
"league/flysystem-azure": "Allows you to use Windows Azure Blob storage",
|
||||
"league/flysystem-cached-adapter": "Flysystem adapter decorator for metadata caching",
|
||||
"league/flysystem-eventable-filesystem": "Allows you to use EventableFilesystem",
|
||||
"league/flysystem-rackspace": "Allows you to use Rackspace Cloud Files",
|
||||
"league/flysystem-sftp": "Allows you to use SFTP server storage via phpseclib",
|
||||
"league/flysystem-webdav": "Allows you to use WebDAV storage",
|
||||
"league/flysystem-ziparchive": "Allows you to use ZipArchive adapter",
|
||||
"spatie/flysystem-dropbox": "Allows you to use Dropbox storage",
|
||||
"srmklive/flysystem-dropbox-v2": "Allows you to use Dropbox storage for PHP 5 applications"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.1-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"League\\Flysystem\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Frank de Jonge",
|
||||
"email": "info@frenky.net"
|
||||
}
|
||||
],
|
||||
"description": "Filesystem abstraction: Many filesystems, one API.",
|
||||
"keywords": [
|
||||
"Cloud Files",
|
||||
"WebDAV",
|
||||
"abstraction",
|
||||
"aws",
|
||||
"cloud",
|
||||
"copy.com",
|
||||
"dropbox",
|
||||
"file systems",
|
||||
"files",
|
||||
"filesystem",
|
||||
"filesystems",
|
||||
"ftp",
|
||||
"rackspace",
|
||||
"remote",
|
||||
"s3",
|
||||
"sftp",
|
||||
"storage"
|
||||
],
|
||||
"time": "2020-01-04T16:30:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/flysystem-cached-adapter",
|
||||
"version": "1.0.9",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/flysystem-cached-adapter.git",
|
||||
"reference": "08ef74e9be88100807a3b92cc9048a312bf01d6f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/flysystem-cached-adapter/zipball/08ef74e9be88100807a3b92cc9048a312bf01d6f",
|
||||
"reference": "08ef74e9be88100807a3b92cc9048a312bf01d6f",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||
"preferred": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"require": {
|
||||
"league/flysystem": "~1.0",
|
||||
"psr/cache": "^1.0.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"mockery/mockery": "~0.9",
|
||||
"phpspec/phpspec": "^3.4",
|
||||
"phpunit/phpunit": "^5.7",
|
||||
"predis/predis": "~1.0",
|
||||
"tedivm/stash": "~0.12"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-phpredis": "Pure C implemented extension for PHP"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"League\\Flysystem\\Cached\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "frankdejonge",
|
||||
"email": "info@frenky.net"
|
||||
}
|
||||
],
|
||||
"description": "An adapter decorator to enable meta-data caching.",
|
||||
"time": "2018-07-09T20:51:04+00:00"
|
||||
},
|
||||
{
|
||||
"name": "opis/closure",
|
||||
"version": "3.5.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/opis/closure.git",
|
||||
"reference": "93ebc5712cdad8d5f489b500c59d122df2e53969"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/opis/closure/zipball/93ebc5712cdad8d5f489b500c59d122df2e53969",
|
||||
"reference": "93ebc5712cdad8d5f489b500c59d122df2e53969",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||
"preferred": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.4 || ^7.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"jeremeamia/superclosure": "^2.0",
|
||||
"phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.5.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Opis\\Closure\\": "src/"
|
||||
},
|
||||
"files": [
|
||||
"functions.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Marius Sarca",
|
||||
"email": "marius.sarca@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Sorin Sarca",
|
||||
"email": "sarca_sorin@hotmail.com"
|
||||
}
|
||||
],
|
||||
"description": "A library that can be used to serialize closures (anonymous functions) and arbitrary objects.",
|
||||
"homepage": "https://opis.io/closure",
|
||||
"keywords": [
|
||||
"anonymous functions",
|
||||
"closure",
|
||||
"function",
|
||||
"serializable",
|
||||
"serialization",
|
||||
"serialize"
|
||||
],
|
||||
"time": "2019-11-29T22:36:02+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/cache",
|
||||
"version": "1.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/cache.git",
|
||||
"reference": "d11b50ad223250cf17b86e38383413f5a6764bf8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8",
|
||||
"reference": "d11b50ad223250cf17b86e38383413f5a6764bf8",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||
"preferred": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Cache\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "http://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interface for caching libraries",
|
||||
"keywords": [
|
||||
"cache",
|
||||
"psr",
|
||||
"psr-6"
|
||||
],
|
||||
"time": "2016-08-06T20:24:11+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/container",
|
||||
"version": "1.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/container.git",
|
||||
"reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
|
||||
"reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||
"preferred": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Container\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "http://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common Container Interface (PHP FIG PSR-11)",
|
||||
"homepage": "https://github.com/php-fig/container",
|
||||
"keywords": [
|
||||
"PSR-11",
|
||||
"container",
|
||||
"container-interface",
|
||||
"container-interop",
|
||||
"psr"
|
||||
],
|
||||
"time": "2017-02-14T16:28:37+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/log",
|
||||
"version": "1.1.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/log.git",
|
||||
"reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/log/zipball/446d54b4cb6bf489fc9d75f55843658e6f25d801",
|
||||
"reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||
"preferred": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.1.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Log\\": "Psr/Log/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "http://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interface for logging libraries",
|
||||
"homepage": "https://github.com/php-fig/log",
|
||||
"keywords": [
|
||||
"log",
|
||||
"psr",
|
||||
"psr-3"
|
||||
],
|
||||
"time": "2019-11-01T11:05:21+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/simple-cache",
|
||||
"version": "1.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/simple-cache.git",
|
||||
"reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b",
|
||||
"reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||
"preferred": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\SimpleCache\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "http://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interfaces for simple caching",
|
||||
"keywords": [
|
||||
"cache",
|
||||
"caching",
|
||||
"psr",
|
||||
"psr-16",
|
||||
"simple-cache"
|
||||
],
|
||||
"time": "2017-10-23T01:57:42+00:00"
|
||||
},
|
||||
{
|
||||
"name": "topthink/framework",
|
||||
"version": "v6.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/top-think/framework.git",
|
||||
"reference": "501f3dd17dc6266e17b7d8df3e9fd090bd2cc85f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/top-think/framework/zipball/501f3dd17dc6266e17b7d8df3e9fd090bd2cc85f",
|
||||
"reference": "501f3dd17dc6266e17b7d8df3e9fd090bd2cc85f",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||
"preferred": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"ext-mbstring": "*",
|
||||
"league/flysystem": "^1.0",
|
||||
"league/flysystem-cached-adapter": "^1.0",
|
||||
"opis/closure": "^3.1",
|
||||
"php": ">=7.1.0",
|
||||
"psr/container": "~1.0",
|
||||
"psr/log": "~1.0",
|
||||
"psr/simple-cache": "^1.0",
|
||||
"topthink/think-helper": "^3.1.1",
|
||||
"topthink/think-orm": "^2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"mikey179/vfsstream": "^1.6",
|
||||
"mockery/mockery": "^1.2",
|
||||
"phpunit/phpunit": "^7.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [],
|
||||
"psr-4": {
|
||||
"think\\": "src/think/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"Apache-2.0"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "liu21st",
|
||||
"email": "liu21st@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "yunwuxin",
|
||||
"email": "448901948@qq.com"
|
||||
}
|
||||
],
|
||||
"description": "The ThinkPHP Framework.",
|
||||
"homepage": "http://thinkphp.cn/",
|
||||
"keywords": [
|
||||
"framework",
|
||||
"orm",
|
||||
"thinkphp"
|
||||
],
|
||||
"time": "2019-12-24T07:57:03+00:00"
|
||||
},
|
||||
{
|
||||
"name": "topthink/think-helper",
|
||||
"version": "v3.1.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/top-think/think-helper.git",
|
||||
"reference": "4d85dfd3778623bbb1de3648f1dcd0c82f4439f4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/top-think/think-helper/zipball/4d85dfd3778623bbb1de3648f1dcd0c82f4439f4",
|
||||
"reference": "4d85dfd3778623bbb1de3648f1dcd0c82f4439f4",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||
"preferred": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"think\\": "src"
|
||||
},
|
||||
"files": [
|
||||
"src/helper.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"Apache-2.0"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "yunwuxin",
|
||||
"email": "448901948@qq.com"
|
||||
}
|
||||
],
|
||||
"description": "The ThinkPHP6 Helper Package",
|
||||
"time": "2019-09-30T02:36:48+00:00"
|
||||
},
|
||||
{
|
||||
"name": "topthink/think-orm",
|
||||
"version": "v2.0.30",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/top-think/think-orm.git",
|
||||
"reference": "b6f61fc243974a25cb6914b84a529b373a717626"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/top-think/think-orm/zipball/b6f61fc243974a25cb6914b84a529b373a717626",
|
||||
"reference": "b6f61fc243974a25cb6914b84a529b373a717626",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||
"preferred": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"php": ">=7.1.0",
|
||||
"psr/log": "~1.0",
|
||||
"psr/simple-cache": "^1.0",
|
||||
"topthink/think-helper": "^3.1"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"think\\": "src"
|
||||
},
|
||||
"files": []
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"Apache-2.0"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "liu21st",
|
||||
"email": "liu21st@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "think orm",
|
||||
"keywords": [
|
||||
"database",
|
||||
"orm"
|
||||
],
|
||||
"time": "2020-01-02T09:09:50+00:00"
|
||||
},
|
||||
{
|
||||
"name": "topthink/think-template",
|
||||
"version": "v2.0.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/top-think/think-template.git",
|
||||
"reference": "e98bdbb4a4c94b442f17dfceba81e0134d4fbd19"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/top-think/think-template/zipball/e98bdbb4a4c94b442f17dfceba81e0134d4fbd19",
|
||||
"reference": "e98bdbb4a4c94b442f17dfceba81e0134d4fbd19",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||
"preferred": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1.0",
|
||||
"psr/simple-cache": "^1.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"think\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"Apache-2.0"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "liu21st",
|
||||
"email": "liu21st@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "the php template engine",
|
||||
"time": "2019-09-20T15:31:04+00:00"
|
||||
},
|
||||
{
|
||||
"name": "topthink/think-view",
|
||||
"version": "v1.0.13",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/top-think/think-view.git",
|
||||
"reference": "90803b73f781db5d42619082c4597afc58b2d4c5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/top-think/think-view/zipball/90803b73f781db5d42619082c4597afc58b2d4c5",
|
||||
"reference": "90803b73f781db5d42619082c4597afc58b2d4c5",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||
"preferred": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1.0",
|
||||
"topthink/think-template": "^2.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"think\\view\\driver\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"Apache-2.0"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "liu21st",
|
||||
"email": "liu21st@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "thinkphp template driver",
|
||||
"time": "2019-10-07T12:23:10+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [
|
||||
{
|
||||
"name": "symfony/polyfill-mbstring",
|
||||
"version": "v1.13.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
||||
"reference": "7b4aab9743c30be783b73de055d24a39cf4b954f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/7b4aab9743c30be783b73de055d24a39cf4b954f",
|
||||
"reference": "7b4aab9743c30be783b73de055d24a39cf4b954f",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||
"preferred": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.3"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-mbstring": "For best performance"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.13-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Polyfill\\Mbstring\\": ""
|
||||
},
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nicolas Grekas",
|
||||
"email": "p@tchwork.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony polyfill for the Mbstring extension",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"compatibility",
|
||||
"mbstring",
|
||||
"polyfill",
|
||||
"portable",
|
||||
"shim"
|
||||
],
|
||||
"time": "2019-11-27T14:18:11+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php72",
|
||||
"version": "v1.13.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php72.git",
|
||||
"reference": "66fea50f6cb37a35eea048d75a7d99a45b586038"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/66fea50f6cb37a35eea048d75a7d99a45b586038",
|
||||
"reference": "66fea50f6cb37a35eea048d75a7d99a45b586038",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||
"preferred": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.3"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.13-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Polyfill\\Php72\\": ""
|
||||
},
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nicolas Grekas",
|
||||
"email": "p@tchwork.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"compatibility",
|
||||
"polyfill",
|
||||
"portable",
|
||||
"shim"
|
||||
],
|
||||
"time": "2019-11-27T13:56:44+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/var-dumper",
|
||||
"version": "v4.4.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/var-dumper.git",
|
||||
"reference": "be330f919bdb395d1e0c3f2bfb8948512d6bdd99"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/be330f919bdb395d1e0c3f2bfb8948512d6bdd99",
|
||||
"reference": "be330f919bdb395d1e0c3f2bfb8948512d6bdd99",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||
"preferred": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.1.3",
|
||||
"symfony/polyfill-mbstring": "~1.0",
|
||||
"symfony/polyfill-php72": "~1.5"
|
||||
},
|
||||
"conflict": {
|
||||
"phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0",
|
||||
"symfony/console": "<3.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-iconv": "*",
|
||||
"symfony/console": "^3.4|^4.0|^5.0",
|
||||
"symfony/process": "^4.4|^5.0",
|
||||
"twig/twig": "^1.34|^2.4|^3.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).",
|
||||
"ext-intl": "To show region name in time zone dump",
|
||||
"symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script"
|
||||
},
|
||||
"bin": [
|
||||
"Resources/bin/var-dump-server"
|
||||
],
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "4.4-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"Resources/functions/dump.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\VarDumper\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nicolas Grekas",
|
||||
"email": "p@tchwork.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony mechanism for exploring and dumping PHP variables",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"debug",
|
||||
"dump"
|
||||
],
|
||||
"time": "2019-12-18T13:41:29+00:00"
|
||||
},
|
||||
{
|
||||
"name": "topthink/think-trace",
|
||||
"version": "v1.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/top-think/think-trace.git",
|
||||
"reference": "4589d06a07945d57478cc2236f4b23d51ff919cc"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/top-think/think-trace/zipball/4589d06a07945d57478cc2236f4b23d51ff919cc",
|
||||
"reference": "4589d06a07945d57478cc2236f4b23d51ff919cc",
|
||||
"shasum": "",
|
||||
"mirrors": [
|
||||
{
|
||||
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||
"preferred": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1.0",
|
||||
"topthink/framework": "^6.0.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"think": {
|
||||
"services": [
|
||||
"think\\trace\\Service"
|
||||
],
|
||||
"config": {
|
||||
"trace": "src/config.php"
|
||||
}
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"think\\trace\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"Apache-2.0"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "liu21st",
|
||||
"email": "liu21st@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "thinkphp debug trace",
|
||||
"time": "2019-10-17T02:14:09+00:00"
|
||||
}
|
||||
],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": [],
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": {
|
||||
"php": ">=7.1.0"
|
||||
},
|
||||
"platform-dev": []
|
||||
}
|
36
config/app.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | 应用设置
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
use think\facade\Env;
|
||||
|
||||
return [
|
||||
// 应用地址
|
||||
'app_host' => Env::get('app.host', ''),
|
||||
// 应用的命名空间
|
||||
'app_namespace' => '',
|
||||
// 是否启用路由
|
||||
'with_route' => true,
|
||||
// 是否启用事件
|
||||
'with_event' => true,
|
||||
// 默认应用
|
||||
'default_app' => 'index',
|
||||
// 默认时区
|
||||
'default_timezone' => 'Asia/Shanghai',
|
||||
|
||||
// 应用映射(自动多应用模式有效)
|
||||
'app_map' => [],
|
||||
// 域名绑定(自动多应用模式有效)
|
||||
'domain_bind' => [],
|
||||
// 禁止URL访问的应用列表(自动多应用模式有效)
|
||||
'deny_app_list' => [],
|
||||
|
||||
// 异常页面的模板文件
|
||||
'exception_tmpl' => app()->getThinkPath() . 'tpl/think_exception.tpl',
|
||||
|
||||
// 错误显示信息,非调试模式有效
|
||||
'error_message' => '页面错误!请稍后再试~',
|
||||
// 显示错误信息
|
||||
'show_error_msg' => false,
|
||||
];
|
30
config/cache.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
use think\facade\Env;
|
||||
|
||||
// +----------------------------------------------------------------------
|
||||
// | 缓存设置
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
return [
|
||||
// 默认缓存驱动
|
||||
'default' => Env::get('cache.driver', 'file'),
|
||||
|
||||
// 缓存连接方式配置
|
||||
'stores' => [
|
||||
'file' => [
|
||||
// 驱动方式
|
||||
'type' => 'File',
|
||||
// 缓存保存目录
|
||||
'path' => '',
|
||||
// 缓存前缀
|
||||
'prefix' => '',
|
||||
// 缓存有效期 0表示永久缓存
|
||||
'expire' => 0,
|
||||
// 缓存标签前缀
|
||||
'tag_prefix' => 'tag:',
|
||||
// 序列化机制 例如 ['serialize', 'unserialize']
|
||||
'serialize' => [],
|
||||
],
|
||||
// 更多的缓存连接
|
||||
],
|
||||
];
|
9
config/console.php
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | 控制台配置
|
||||
// +----------------------------------------------------------------------
|
||||
return [
|
||||
// 指令定义
|
||||
'commands' => [
|
||||
],
|
||||
];
|
18
config/cookie.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | Cookie设置
|
||||
// +----------------------------------------------------------------------
|
||||
return [
|
||||
// cookie 保存时间
|
||||
'expire' => 0,
|
||||
// cookie 保存路径
|
||||
'path' => '/',
|
||||
// cookie 有效域名
|
||||
'domain' => '',
|
||||
// cookie 启用安全传输
|
||||
'secure' => false,
|
||||
// httponly设置
|
||||
'httponly' => false,
|
||||
// 是否使用 setcookie
|
||||
'setcookie' => true,
|
||||
];
|
64
config/database.php
Normal file
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
use think\facade\Env;
|
||||
|
||||
return [
|
||||
// 默认使用的数据库连接配置
|
||||
'default' => Env::get('database.driver', 'mysql'),
|
||||
|
||||
// 自定义时间查询规则
|
||||
'time_query_rule' => [],
|
||||
|
||||
// 自动写入时间戳字段
|
||||
// true为自动识别类型 false关闭
|
||||
// 字符串则明确指定时间字段类型 支持 int timestamp datetime date
|
||||
'auto_timestamp' => true,
|
||||
|
||||
// 时间字段取出后的默认时间格式
|
||||
'datetime_format' => 'Y-m-d H:i:s',
|
||||
|
||||
// 数据库连接配置信息
|
||||
'connections' => [
|
||||
'mysql' => [
|
||||
// 数据库类型
|
||||
'type' => Env::get('database.type', 'mysql'),
|
||||
// 服务器地址
|
||||
'hostname' => Env::get('database.hostname', '127.0.0.1'),
|
||||
// 数据库名
|
||||
'database' => Env::get('database.database', 'fr_lab'),
|
||||
// 用户名
|
||||
'username' => Env::get('database.username', 'root'),
|
||||
// 密码
|
||||
'password' => Env::get('database.password', ''),
|
||||
// 端口
|
||||
'hostport' => Env::get('database.hostport', '3306'),
|
||||
// 数据库连接参数
|
||||
'params' => [],
|
||||
// 数据库编码默认采用utf8
|
||||
'charset' => Env::get('database.charset', 'utf8'),
|
||||
// 数据库表前缀
|
||||
'prefix' => Env::get('database.prefix', 'fr_lab_'),
|
||||
|
||||
// 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
|
||||
'deploy' => 0,
|
||||
// 数据库读写是否分离 主从式有效
|
||||
'rw_separate' => false,
|
||||
// 读写分离后 主服务器数量
|
||||
'master_num' => 1,
|
||||
// 指定从服务器序号
|
||||
'slave_no' => '',
|
||||
// 是否严格检查字段是否存在
|
||||
'fields_strict' => true,
|
||||
// 是否需要断线重连
|
||||
'break_reconnect' => false,
|
||||
// 监听SQL
|
||||
'trigger_sql' => true,
|
||||
// 开启字段缓存
|
||||
'fields_cache' => false,
|
||||
// 字段缓存路径
|
||||
'schema_cache_path' => app()->getRuntimePath() . 'schema' . DIRECTORY_SEPARATOR,
|
||||
],
|
||||
|
||||
// 更多的数据库配置信息
|
||||
],
|
||||
];
|
26
config/filesystem.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
use think\facade\Env;
|
||||
|
||||
return [
|
||||
// 默认磁盘
|
||||
'default' => Env::get('filesystem.driver', 'local'),
|
||||
// 磁盘列表
|
||||
'disks' => [
|
||||
'local' => [
|
||||
'type' => 'local',
|
||||
'root' => app()->getRuntimePath() . 'storage',
|
||||
],
|
||||
'public' => [
|
||||
// 磁盘类型
|
||||
'type' => 'local',
|
||||
// 磁盘路径
|
||||
'root' => app()->getRootPath() . 'public/storage',
|
||||
// 磁盘路径对应的外部URL路径
|
||||
'url' => '/storage',
|
||||
// 可见性
|
||||
'visibility' => 'public',
|
||||
],
|
||||
// 更多的磁盘配置信息
|
||||
],
|
||||
];
|
27
config/lang.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | 多语言设置
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
use think\facade\Env;
|
||||
|
||||
return [
|
||||
// 默认语言
|
||||
'default_lang' => Env::get('lang.default_lang', 'zh-cn'),
|
||||
// 允许的语言列表
|
||||
'allow_lang_list' => [],
|
||||
// 多语言自动侦测变量名
|
||||
'detect_var' => 'lang',
|
||||
// 是否使用Cookie记录
|
||||
'use_cookie' => true,
|
||||
// 多语言cookie变量
|
||||
'cookie_var' => 'think_lang',
|
||||
// 扩展语言包
|
||||
'extend_list' => [],
|
||||
// Accept-Language转义为对应语言包名称
|
||||
'accept_language' => [
|
||||
'zh-hans-cn' => 'zh-cn',
|
||||
],
|
||||
// 是否支持语言分组
|
||||
'allow_group' => false,
|
||||
];
|
46
config/log.php
Normal file
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
use think\facade\Env;
|
||||
|
||||
// +----------------------------------------------------------------------
|
||||
// | 日志设置
|
||||
// +----------------------------------------------------------------------
|
||||
return [
|
||||
// 默认日志记录通道
|
||||
'default' => Env::get('log.channel', 'file'),
|
||||
// 日志记录级别
|
||||
'level' => [],
|
||||
// 日志类型记录的通道 ['error'=>'email',...]
|
||||
'type_channel' => [],
|
||||
// 关闭全局日志写入
|
||||
'close' => false,
|
||||
// 全局日志处理 支持闭包
|
||||
'processor' => null,
|
||||
|
||||
// 日志通道列表
|
||||
'channels' => [
|
||||
'file' => [
|
||||
// 日志记录方式
|
||||
'type' => 'File',
|
||||
// 日志保存目录
|
||||
'path' => '',
|
||||
// 单文件日志写入
|
||||
'single' => false,
|
||||
// 独立日志级别
|
||||
'apart_level' => [],
|
||||
// 最大日志文件数量
|
||||
'max_files' => 0,
|
||||
// 使用JSON格式记录
|
||||
'json' => false,
|
||||
// 日志处理
|
||||
'processor' => null,
|
||||
// 关闭通道日志写入
|
||||
'close' => false,
|
||||
// 日志输出格式化
|
||||
'format' => '[%s][%s] %s',
|
||||
// 是否实时写入
|
||||
'realtime_write' => false,
|
||||
],
|
||||
// 其它日志通道配置
|
||||
],
|
||||
|
||||
];
|
8
config/middleware.php
Normal file
@ -0,0 +1,8 @@
|
||||
<?php
|
||||
// 中间件配置
|
||||
return [
|
||||
// 别名或分组
|
||||
'alias' => [],
|
||||
// 优先级设置,此数组中的中间件会按照数组中的顺序优先执行
|
||||
'priority' => [],
|
||||
];
|
45
config/route.php
Normal file
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | 路由设置
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
return [
|
||||
// pathinfo分隔符
|
||||
'pathinfo_depr' => '/',
|
||||
// URL伪静态后缀
|
||||
'url_html_suffix' => 'html',
|
||||
// URL普通方式参数 用于自动生成
|
||||
'url_common_param' => true,
|
||||
// 是否开启路由延迟解析
|
||||
'url_lazy_route' => false,
|
||||
// 是否强制使用路由
|
||||
'url_route_must' => false,
|
||||
// 合并路由规则
|
||||
'route_rule_merge' => false,
|
||||
// 路由是否完全匹配
|
||||
'route_complete_match' => false,
|
||||
// 访问控制器层名称
|
||||
'controller_layer' => 'controller',
|
||||
// 空控制器名
|
||||
'empty_controller' => 'Error',
|
||||
// 是否使用控制器后缀
|
||||
'controller_suffix' => false,
|
||||
// 默认的路由变量规则
|
||||
'default_route_pattern' => '[\w\.]+',
|
||||
// 是否开启请求缓存 true自动缓存 支持设置请求缓存规则
|
||||
'request_cache' => false,
|
||||
// 请求缓存有效期
|
||||
'request_cache_expire' => null,
|
||||
// 全局请求缓存排除规则
|
||||
'request_cache_except' => [],
|
||||
// 默认控制器名
|
||||
'default_controller' => 'Index',
|
||||
// 默认操作名
|
||||
'default_action' => 'index',
|
||||
// 操作方法后缀
|
||||
'action_suffix' => '',
|
||||
// 默认JSONP格式返回的处理方法
|
||||
'default_jsonp_handler' => 'jsonpReturn',
|
||||
// 默认JSONP处理方法
|
||||
'var_jsonp_handler' => 'callback',
|
||||
];
|
19
config/session.php
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | 会话设置
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
return [
|
||||
// session name
|
||||
'name' => 'PHPSESSID',
|
||||
// SESSION_ID的提交变量,解决flash上传跨域
|
||||
'var_session_id' => '',
|
||||
// 驱动方式 支持file cache
|
||||
'type' => 'file',
|
||||
// 存储连接标识 当type使用cache的时候有效
|
||||
'store' => null,
|
||||
// 过期时间
|
||||
'expire' => 1440,
|
||||
// 前缀
|
||||
'prefix' => '',
|
||||
];
|
10
config/trace.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | Trace设置 开启调试模式后有效
|
||||
// +----------------------------------------------------------------------
|
||||
return [
|
||||
// 内置Html和Console两种方式 支持扩展
|
||||
'type' => 'Html',
|
||||
// 读取的日志通道名
|
||||
'channel' => '',
|
||||
];
|
25
config/view.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | 模板设置
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
return [
|
||||
// 模板引擎类型使用Think
|
||||
'type' => 'Think',
|
||||
// 默认模板渲染规则 1 解析为小写+下划线 2 全部转换小写 3 保持操作方法
|
||||
'auto_rule' => 1,
|
||||
// 模板目录名
|
||||
'view_dir_name' => 'view',
|
||||
// 模板后缀
|
||||
'view_suffix' => 'html',
|
||||
// 模板文件名分隔符
|
||||
'view_depr' => DIRECTORY_SEPARATOR,
|
||||
// 模板引擎普通标签开始标记
|
||||
'tpl_begin' => '{',
|
||||
// 模板引擎普通标签结束标记
|
||||
'tpl_end' => '}',
|
||||
// 标签库标签开始标记
|
||||
'taglib_begin' => '{',
|
||||
// 标签库标签结束标记
|
||||
'taglib_end' => '}',
|
||||
];
|
79
extend/mylib/Assistant.php
Normal file
@ -0,0 +1,79 @@
|
||||
<?php
|
||||
namespace mylib;
|
||||
|
||||
class Assistant
|
||||
{
|
||||
/**
|
||||
* 获取周一和周日 getdays('2017-03-18')
|
||||
* Array
|
||||
* (
|
||||
* [0] => 2017-03-13
|
||||
* [1] => 2017-03-19
|
||||
* )
|
||||
*/
|
||||
public function getdays($day)
|
||||
{
|
||||
$lastday = date('Y-m-d', strtotime("$day Sunday"));
|
||||
$firstday = date('Y-m-d', strtotime("$lastday -6 days"));
|
||||
return array($firstday, $lastday);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取月初和月末 getmonths('2017-2-2')
|
||||
* Array
|
||||
* (
|
||||
* [0] => 2017-02-01
|
||||
* [1] => 2017-02-28
|
||||
* )
|
||||
*/
|
||||
public function getmonths($day)
|
||||
{
|
||||
$firstday = date('Y-m-01', strtotime($day));
|
||||
$lastday = date('Y-m-d', strtotime("$firstday +1 month -1 day"));
|
||||
return array($firstday, $lastday);
|
||||
}
|
||||
|
||||
//POST请求
|
||||
public function request_by_curl($remote_server, $post_string, $znv = FALSE)
|
||||
{
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $remote_server);
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
|
||||
if($znv == FALSE){
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json;charset=utf-8'));
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_string);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
$data = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function checkPassword($pwd) {
|
||||
if ($pwd == null) {
|
||||
return ['code' => 1, 'data' => '', 'msg' => '密码不能为空'];
|
||||
}
|
||||
$pwd = trim($pwd);
|
||||
if (!strlen($pwd) >= 6) {//必须大于6个字符
|
||||
return ['code' => 1, 'data' => '', 'msg' => '密码必须大于6字符'];
|
||||
}
|
||||
if (preg_match("/(0(?=1)|1(?=2)|2(?=3)|3(?=4)|4(?=5)|5(?=6)|6(?=7)|7(?=8)|8(?=9)){2}\d/", $pwd)){
|
||||
return ['code' => 1, 'data' => '', 'msg' => '密码不能包含连续数字'];
|
||||
}
|
||||
if (preg_match("/^[0-9]+$/", $pwd)) { //必须含有特殊字符
|
||||
return ['code' => 1, 'data' => '', 'msg' => '密码不能全是数字,请包含数字,字母大小写或者特殊字符'];
|
||||
}
|
||||
if (preg_match("/^[a-zA-Z]+$/", $pwd)) {
|
||||
return ['code' => 1, 'data' => '', 'msg' => '密码不能全是字母,请包含数字,字母大小写或者特殊字符'];
|
||||
}
|
||||
// if (preg_match("/^[0-9A-Z]+$/", $pwd)) {
|
||||
// return ['code' => 1, 'data' => '', 'msg' => '请包含数字,字母大小写或者特殊字符'];
|
||||
// }
|
||||
// if (preg_match("/^[0-9a-z]+$/", $pwd)) {
|
||||
// return ['code' => 1, 'data' => '', 'msg' => '请包含数字,字母大小写或者特殊字符'];
|
||||
// }
|
||||
return ['code' => 0, 'data' => '', 'msg' => '密码复杂度通过验证'];
|
||||
}
|
||||
|
||||
}
|
8
public/.htaccess
Normal file
@ -0,0 +1,8 @@
|
||||
<IfModule mod_rewrite.c>
|
||||
Options +FollowSymlinks -Multiviews
|
||||
RewriteEngine On
|
||||
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L]
|
||||
</IfModule>
|
BIN
public/favicon.ico
Normal file
After Width: | Height: | Size: 9.4 KiB |
136
public/fr_lab.sql
Normal file
@ -0,0 +1,136 @@
|
||||
/*
|
||||
Navicat Premium Data Transfer
|
||||
|
||||
Source Server : 本机
|
||||
Source Server Type : MySQL
|
||||
Source Server Version : 100316
|
||||
Source Host : localhost:3306
|
||||
Source Schema : fr_lab
|
||||
|
||||
Target Server Type : MySQL
|
||||
Target Server Version : 100316
|
||||
File Encoding : 65001
|
||||
|
||||
Date: 09/01/2020 12:40:32
|
||||
*/
|
||||
|
||||
SET NAMES utf8mb4;
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for fr_lab_auth_group
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `fr_lab_auth_group`;
|
||||
CREATE TABLE `fr_lab_auth_group` (
|
||||
`id` mediumint(8) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
|
||||
`title` char(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '用户组中文名称',
|
||||
`status` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态:为1正常,为0禁用',
|
||||
`rules` varchar(600) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '用户组拥有的规则id, 多个规则\",\"隔开',
|
||||
`update_time` int(11) NOT NULL,
|
||||
`create_time` int(11) NOT NULL,
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 63 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of fr_lab_auth_group
|
||||
-- ----------------------------
|
||||
INSERT INTO `fr_lab_auth_group` VALUES (1, '系统管理员', 1, '1,46,48,50,3,13,14,15,93,9,28,29,30,52', 1564550565, 0);
|
||||
INSERT INTO `fr_lab_auth_group` VALUES (16, '测试1', 1, '1,46,48,50,9,29,30,52', 1564551105, 1533117210);
|
||||
INSERT INTO `fr_lab_auth_group` VALUES (31, '测试2', 1, '1,46,48,50,3,13,14,15,93,52', 1564551093, 1533803865);
|
||||
INSERT INTO `fr_lab_auth_group` VALUES (32, '测试3', 1, '1,46,9,28,29', 1564551078, 1533804068);
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for fr_lab_auth_group_access
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `fr_lab_auth_group_access`;
|
||||
CREATE TABLE `fr_lab_auth_group_access` (
|
||||
`uid` mediumint(8) UNSIGNED NOT NULL COMMENT '用户id',
|
||||
`group_id` mediumint(8) UNSIGNED NOT NULL COMMENT '用户组id',
|
||||
`update_time` int(11) NOT NULL,
|
||||
`create_time` int(11) NOT NULL,
|
||||
UNIQUE INDEX `uid_group_id`(`uid`, `group_id`) USING BTREE,
|
||||
INDEX `uid`(`uid`) USING BTREE,
|
||||
INDEX `group_id`(`group_id`) USING BTREE
|
||||
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of fr_lab_auth_group_access
|
||||
-- ----------------------------
|
||||
INSERT INTO `fr_lab_auth_group_access` VALUES (1, 1, 1564550996, 1564550996);
|
||||
INSERT INTO `fr_lab_auth_group_access` VALUES (29, 16, 1564551043, 1564551043);
|
||||
INSERT INTO `fr_lab_auth_group_access` VALUES (31, 32, 1570698794, 1570698794);
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for fr_lab_auth_rule
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `fr_lab_auth_rule`;
|
||||
CREATE TABLE `fr_lab_auth_rule` (
|
||||
`id` mediumint(8) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
|
||||
`name` char(80) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '规则唯一标识',
|
||||
`title` char(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '规则中文名称',
|
||||
`type` tinyint(1) NOT NULL DEFAULT 1 COMMENT '在think_auth_rule 表中定义一条规则时,如果type为1, condition字段就可以定义规则表达式。 如定义{score}>5 and {score}<100 表示用户的分数在5-100之间时这条规则才会通过。',
|
||||
`status` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态:为1正常,为0禁用',
|
||||
`condition` char(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '规则表达式,为空表示存在就验证,不为空表示按照条件验证',
|
||||
`pid` int(8) NOT NULL COMMENT '父级ID',
|
||||
`navid` int(8) NOT NULL DEFAULT 0,
|
||||
`update_time` int(11) NOT NULL,
|
||||
`create_time` int(11) NOT NULL,
|
||||
`remarks` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
UNIQUE INDEX `name`(`name`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 112 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of fr_lab_auth_rule
|
||||
-- ----------------------------
|
||||
INSERT INTO `fr_lab_auth_rule` VALUES (1, '/', 'root', 1, 1, '', 0, 0, 1564044544, 1533544732, '根节点');
|
||||
INSERT INTO `fr_lab_auth_rule` VALUES (9, 'user', '权限管理', 1, 1, '{status} === 1', 1, 19, 1564554081, 1533544732, '');
|
||||
INSERT INTO `fr_lab_auth_rule` VALUES (28, 'user_list', '用户管理', 1, 1, '{status} === 1', 9, 0, 1564553909, 1533544732, '');
|
||||
INSERT INTO `fr_lab_auth_rule` VALUES (29, 'group_list', '角色管理', 1, 1, '{status} === 1', 9, 0, 1564553921, 1533544732, '');
|
||||
INSERT INTO `fr_lab_auth_rule` VALUES (30, 'menu_list', '菜单管理', 1, 1, '{status} === 1', 9, 0, 1564553932, 1533544732, '');
|
||||
INSERT INTO `fr_lab_auth_rule` VALUES (46, 'header_index', '总览', 1, 1, '{status} === 1', 1, 1, 1571887928, 1533544652, '');
|
||||
INSERT INTO `fr_lab_auth_rule` VALUES (52, 'sql', '数据字典', 1, 1, '{status} === 1', 1, 32, 1564122382, 1533613635, '');
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for fr_lab_log
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `fr_lab_log`;
|
||||
CREATE TABLE `fr_lab_log` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`userid` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '用户账号',
|
||||
`operation` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '动作',
|
||||
`create_time` datetime(0) NOT NULL COMMENT '创建时间',
|
||||
`login_city` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '登录城市',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
INDEX `userid`(`userid`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 13466 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for fr_lab_user
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `fr_lab_user`;
|
||||
CREATE TABLE `fr_lab_user` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '姓名',
|
||||
`username` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '用户名',
|
||||
`password_hash` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '密码hash',
|
||||
`email` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '邮箱',
|
||||
`tel` varchar(11) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '电话',
|
||||
`department` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '部门',
|
||||
`position` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '职位',
|
||||
`status` int(1) NOT NULL DEFAULT 1 COMMENT '账户状态',
|
||||
`update_time` int(11) NOT NULL COMMENT '最后修改时间',
|
||||
`create_time` int(11) NOT NULL COMMENT '添加时间',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
UNIQUE INDEX `username`(`username`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 207 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of fr_lab_user
|
||||
-- ----------------------------
|
||||
INSERT INTO `fr_lab_user` VALUES (1, '系统管理员', 'admin', '$argon2i$v=19$m=1024,t=2,p=2$LmkwOHNhR25aYkxGbUNiMQ$9FTd18zr7bI15izevDWxvNL6tnMRHZiSUNvtcvgDB1A', 'admin@xxx.com', '13500000000', '系统管理员', '-', 1, 1578544825, 1521533170);
|
||||
INSERT INTO `fr_lab_user` VALUES (29, '测试账号1', 'test1', '$argon2i$v=19$m=1024,t=2,p=2$MjN0dGRhVkJJSWN6eUluTw$OaA3ZXxu3E+y8ZYe+C5GxtD7gUBKF0k7foBPJ7PKP5M', 'test1@xxx.com', '18300000000', '测试组', '-', 1, 1578543495, 1521533170);
|
||||
INSERT INTO `fr_lab_user` VALUES (30, '测试账号2', 'test2', '$argon2i$v=19$m=1024,t=2,p=2$Vml1QUNWNjBsQk9rV0hhcA$nEcyqaCr5wK3aThPKEBFul2sWYy9LcTY5Ig72MLptBY', 'test2@xxx.com', '13500000000', '测试组', '-', 0, 1578543499, 1521533170);
|
||||
INSERT INTO `fr_lab_user` VALUES (31, '测试账号3', 'test3', '$argon2i$v=19$m=1024,t=2,p=2$a1dJWDUwYjBHakIuWmEwZA$XtF/v7nKQy5dzuSbhURaIPPlzjkyyvq9CWw9M//DaC8', 'test3@xxx.com', '18900000000', '测试组', '-', 1, 1578543502, 1521533170);
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
24
public/index.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2006-2019 http://thinkphp.cn All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: liu21st <liu21st@gmail.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
// [ 应用入口文件 ]
|
||||
namespace think;
|
||||
|
||||
require __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
// 执行HTTP应用并响应
|
||||
$http = (new App())->http;
|
||||
|
||||
$response = $http->run();
|
||||
|
||||
$response->send();
|
||||
|
||||
$http->end($response);
|
2
public/robots.txt
Normal file
@ -0,0 +1,2 @@
|
||||
User-agent: *
|
||||
Disallow:
|
17
public/router.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2006~2019 http://thinkphp.cn All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: liu21st <liu21st@gmail.com>
|
||||
// +----------------------------------------------------------------------
|
||||
// $Id$
|
||||
|
||||
if (is_file($_SERVER["DOCUMENT_ROOT"] . $_SERVER["SCRIPT_NAME"])) {
|
||||
return false;
|
||||
} else {
|
||||
require __DIR__ . "/index.php";
|
||||
}
|
16
public/static/css/font.css
Normal file
@ -0,0 +1,16 @@
|
||||
@charset "utf-8";
|
||||
@font-face {
|
||||
font-family: 'iconfont';
|
||||
src: url('/static/layui/font/iconfont.eot');
|
||||
src: url('/static/layui/font/iconfont.eot?#iefix') format('embedded-opentype'),
|
||||
url('/static/layui/font/iconfont.woff') format('woff'),
|
||||
url('/static/layui/font/iconfont.ttf') format('truetype'),
|
||||
url('/static/layui/font/iconfont.svg#iconfont') format('svg');
|
||||
}
|
||||
.iconfont{
|
||||
font-family:"iconfont" !important;
|
||||
font-size:16px;font-style:normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-webkit-text-stroke-width: 0.2px;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
112
public/static/css/radmin.css
Normal file
@ -0,0 +1,112 @@
|
||||
@charset "utf-8";
|
||||
@import url(../layui/css/layui.css);
|
||||
html{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow-x:hidden;
|
||||
overflow-y:auto;
|
||||
}
|
||||
body{
|
||||
width: 100%;
|
||||
min-height: 100%;
|
||||
}
|
||||
.login-bg{
|
||||
/*background: #eeeeee url() 0 0 no-repeat;*/
|
||||
background:url(../images/bg.png) no-repeat center;
|
||||
background-size: cover;
|
||||
overflow: hidden;
|
||||
}
|
||||
.login{
|
||||
margin: 120px auto 0 auto;
|
||||
min-height: 420px;
|
||||
max-width: 420px;
|
||||
padding: 40px;
|
||||
background-color: #ffffff;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
border-radius: 4px;
|
||||
/* overflow-x: hidden; */
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.login a.logo{
|
||||
display: block;
|
||||
height: 58px;
|
||||
width: 167px;
|
||||
margin: 0 auto 30px auto;
|
||||
background-size: 167px 42px;
|
||||
}
|
||||
.login .message {
|
||||
margin: 10px 0 0 -58px;
|
||||
padding: 18px 10px 18px 60px;
|
||||
background: #189F92;
|
||||
position: relative;
|
||||
color: #fff;
|
||||
font-size: 16px;
|
||||
}
|
||||
.login #darkbannerwrap {
|
||||
background: url(../images/aiwrap.png);
|
||||
width: 18px;
|
||||
height: 10px;
|
||||
margin: 0 0 20px -58px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.login input[type=text],
|
||||
.login input[type=file],
|
||||
.login input[type=password],
|
||||
.login input[type=email], select {
|
||||
border: 1px solid #DCDEE0;
|
||||
vertical-align: middle;
|
||||
border-radius: 3px;
|
||||
height: 50px;
|
||||
padding: 0px 16px;
|
||||
font-size: 14px;
|
||||
color: #555555;
|
||||
outline:none;
|
||||
width:100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.login input[type=text]:focus,
|
||||
.login input[type=file]:focus,
|
||||
.login input[type=password]:focus,
|
||||
.login input[type=email]:focus, select:focus {
|
||||
border: 1px solid #27A9E3;
|
||||
}
|
||||
.login input[type=submit],
|
||||
.login input[type=button]{
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
padding: 12px 24px;
|
||||
margin: 0px;
|
||||
font-size: 18px;
|
||||
line-height: 24px;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
vertical-align: middle;
|
||||
cursor: pointer;
|
||||
color: #ffffff;
|
||||
background-color: #189F92;
|
||||
border-radius: 3px;
|
||||
border: none;
|
||||
-webkit-appearance: none;
|
||||
outline:none;
|
||||
width:100%;
|
||||
}
|
||||
.login hr {
|
||||
background: #fff url() 0 0 no-repeat;
|
||||
}
|
||||
.login hr.hr15 {
|
||||
height: 15px;
|
||||
border: none;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
width: 100%;
|
||||
}
|
||||
.login hr.hr20 {
|
||||
height: 20px;
|
||||
border: none;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
width: 100%;
|
||||
}
|
||||
i:hover{ cursor:pointer; }
|
BIN
public/static/images/aiwrap.png
Normal file
After Width: | Height: | Size: 3.0 KiB |
BIN
public/static/images/bg.png
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
public/static/images/user.png
Normal file
After Width: | Height: | Size: 9.0 KiB |
47
public/static/js/authorize/add_user.js
Normal file
@ -0,0 +1,47 @@
|
||||
layui.use(['form', 'layer', 'layedit'], function () {
|
||||
var form = layui.form
|
||||
, layer = layui.layer
|
||||
, layedit = layui.layedit;
|
||||
//自定义验证规则
|
||||
form.verify({
|
||||
pass: [/(.+){6,12}$/, '密码必须6到12位']
|
||||
, content: function (value) {
|
||||
layedit.sync(editIndex);
|
||||
}
|
||||
});
|
||||
// 后端获取角色列表并允许多选
|
||||
$(function () {
|
||||
$.ajax({
|
||||
type: 'get',
|
||||
url: '/Common/groupList',
|
||||
dataType: 'json',
|
||||
success: function (dataDictList) {
|
||||
var obj = eval(dataDictList);
|
||||
var objLength = obj.length;
|
||||
if (objLength > 0) {
|
||||
$(obj).each(function (i) {
|
||||
$("#group").append('<option value="' + obj[i].id + '">' + obj[i].title + '</option>');
|
||||
form.render('select');
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
//监听提交
|
||||
form.on('submit(submit)', function (data) {
|
||||
//通过ajax提交数据
|
||||
$.post("/authorize/saveUser", $("#user").serialize(), function (data) {
|
||||
layer.msg(data, {
|
||||
time: 10000, //20s后自动关闭
|
||||
btn: ['确定', '继续添加']
|
||||
, yes: function () {
|
||||
window.parent.location.reload(); //刷新父页面
|
||||
}
|
||||
, btn2: function () {
|
||||
$("#reset").click()
|
||||
}
|
||||
});
|
||||
});
|
||||
return false;
|
||||
});
|
||||
});
|
228
public/static/js/authorize/group.js
Normal file
@ -0,0 +1,228 @@
|
||||
var from, tree, layer, util;
|
||||
layui.use(['element', 'layer', 'table', 'form', 'tree'], function () {
|
||||
form = layui.form
|
||||
, layer = layui.layer
|
||||
, util = layui.util
|
||||
, tree = layui.tree;
|
||||
var element = layui.element
|
||||
, table = layui.table;
|
||||
table.render({
|
||||
elem: '#grouplist'
|
||||
, id: 'uReload'
|
||||
, height: 'full-220'
|
||||
, method: 'post'
|
||||
, url: '/authorize/getGroup' //数据接口
|
||||
, page: true //开启分页
|
||||
, limits: [15, 50, 100]
|
||||
, limit: 15
|
||||
, cols: [[ //表头
|
||||
{ field: 'ids', title: '#', width: 50, type: 'numbers', fixed: 'left' }
|
||||
, { field: 'id', title: 'ID', width: 60 }
|
||||
, { field: 'title', edit: 'text', title: '角色名', width: 200 }
|
||||
, { field: 'status', title: '状态', width: 110, templet: "<div>{{ status(d.status,d.id)}}</div>" }
|
||||
, { field: 'operation', title: '操作', width: 323, templet: "<div>{{ operation(d.id,d.title)}}</div>" }
|
||||
]]
|
||||
});
|
||||
var $ = layui.$, active = {
|
||||
reload: function () {
|
||||
var title = $('#title');
|
||||
//执行重载
|
||||
table.reload('uReload', {
|
||||
page: {
|
||||
curr: 1 //重新从第 1 页开始
|
||||
}
|
||||
, where: {
|
||||
title: title.val(),
|
||||
}
|
||||
});
|
||||
},
|
||||
addGroup: function () {
|
||||
var title = $('#title').val();
|
||||
if (title == '') {
|
||||
layer.msg('请输入角色名称', { time: 2000 });
|
||||
} else {
|
||||
var e = layer.load(2, { shade: [0.2, '#2F4056'] });
|
||||
$.post("/authorize/saveGroup/", { title: title }, function (msg) {
|
||||
layer.close(e);
|
||||
layer.msg(msg.msg, { time: 1000 });
|
||||
if (msg.code == 0) {
|
||||
//执行重载
|
||||
table.reload('uReload', {
|
||||
page: {
|
||||
curr: 1 //重新从第 1 页开始
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
$('.groupTable .layui-btn').on('click', function () {
|
||||
var type = $(this).data('type');
|
||||
active[type] ? active[type].call(this) : '';
|
||||
});
|
||||
//监听单元格编辑
|
||||
table.on('edit(group)', function (obj) {
|
||||
var e = layer.load(2, { shade: [0.2, '#2F4056'] });
|
||||
var value = obj.value //得到修改后的值
|
||||
, data = obj.data //得到所在行所有键值
|
||||
, field = obj.field; //得到字段
|
||||
$.post("/authorize/updateGroup", { id: data.id, field: field, value: value }, function (msg) {
|
||||
layer.close(e);
|
||||
layer.msg(msg, { time: 1000 });
|
||||
});
|
||||
});
|
||||
//监听账户状态操作
|
||||
form.on('checkbox(lockstatus)', function (obj) {
|
||||
var e = layer.load(2, { shade: [0.2, '#2F4056'] });
|
||||
if (obj.elem.checked == false) {
|
||||
value = 0;
|
||||
} else {
|
||||
value = 1;
|
||||
}
|
||||
$.post("/authorize/updateGroup", { id: this.value, field: 'status', value: value }, function (msg) {
|
||||
layer.close(e);
|
||||
layer.msg(msg, { time: 1000 });
|
||||
});
|
||||
});
|
||||
|
||||
table.on('tool(group)', function (obj) { //注:tool是工具条事件名,test是table原始容器的属性 lay-filter="对应的值"
|
||||
var layEvent = obj.event; //获得 lay-event 对应的值(也可以是表头的 event 参数对应的值)
|
||||
if (layEvent === 'del') { //删除
|
||||
layer.confirm('确认删除该角色【' + obj.data.title + '】?', function (index) {
|
||||
//向服务端发送删除指令
|
||||
$.post("/authorize/delGroup/", { id: obj.data.id }, function (data) {
|
||||
layer.close(index);
|
||||
if (data.code === 0) {
|
||||
obj.del(); //删除对应行(tr)的DOM结构,并更新缓存
|
||||
}
|
||||
layer.msg(data.msg, { time: 2000 });
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
//传入URL前缀及字段值
|
||||
function status(vals, id) {
|
||||
if (id === 1) {
|
||||
result = '<input type="checkbox" name="lock" value="' + id + '" title="启用" lay-filter="lockstatus" checked="checked" disabled="">';
|
||||
} else {
|
||||
if (vals === 0) {
|
||||
result = '<input type="checkbox" name="lock" value="' + id + '" title="启用" lay-filter="lockstatus">';
|
||||
} else if (vals === 1) {
|
||||
result = '<input type="checkbox" name="lock" value="' + id + '" title="启用" lay-filter="lockstatus" checked="checked">';
|
||||
} else {
|
||||
result = vals;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
//传入URL前缀及字段值
|
||||
function operation(id, title) {
|
||||
var result_mod = '<a class="layui-btn layui-btn-sm" onclick="groupUser(' + id + ",\'" + title + '\')"><i class="layui-icon"></i> 角色成员</a><a class="layui-btn layui-btn-warm layui-btn-sm" onclick="userMenu(' + id + ",\'" + title + '\')"><i class="layui-icon"></i> 角色权限</a>';
|
||||
var result_del = '<a class="layui-btn layui-btn-danger layui-btn-sm" lay-event="del"><i class="layui-icon"></i> 删除角色</a>';
|
||||
if (id == 1) {
|
||||
return result_mod;
|
||||
} else {
|
||||
return result_mod + result_del;
|
||||
}
|
||||
}
|
||||
|
||||
function userMenu(id, title) {
|
||||
$('#userMenu').html("");
|
||||
var index = layer.open({
|
||||
type: 1
|
||||
, title: '编辑权限-' + title
|
||||
, area: ['360px', '600px']
|
||||
, content: '<br><form class="layui-form"><div id="userMenu"></div></form>' //这里content是一个普通的String
|
||||
, btn: ['提交', '关闭']
|
||||
, yes: function () {
|
||||
layer.close(index);
|
||||
var e = layer.load(2, { shade: [0.2, '#2F4056'] });
|
||||
var ruless = '';
|
||||
var checkedData = tree.getChecked('userMenu'); //获取选中节点的数据
|
||||
if (checkedData != '') {
|
||||
ruless = checkedData[0]['id'] + ','; //获取根节点id
|
||||
checkedData = checkedData[0]["children"];
|
||||
//获取第一节节点ID
|
||||
var dataLength = checkedData.length;
|
||||
for (let index = 0; index < dataLength; index++) {
|
||||
ruless += checkedData[index]['id'] + ',';
|
||||
var temp = checkedData[index]['children'].length
|
||||
//判断是否有第二节节点
|
||||
if (temp > 0) {
|
||||
//获取第二节节点ID
|
||||
for (let i = 0; i < temp; i++) {
|
||||
ruless += checkedData[index]['children'][i]['id'] + ',';
|
||||
}
|
||||
}
|
||||
}
|
||||
ruless = ruless.substr(0, ruless.length - 1);
|
||||
}
|
||||
$.post("/authorize/updateGroup", { id: id, field: 'rules', value: ruless }, function (msg) {
|
||||
layer.close(e);
|
||||
layer.msg(msg, { time: 1000 });
|
||||
});
|
||||
}
|
||||
, btn2: function () {
|
||||
layer.close(index);
|
||||
}
|
||||
});
|
||||
var e = layer.load(2, { shade: [0.2, '#2F4056'] });
|
||||
//data数据中仅需要末节点设置选中状态,其它节点无需设置,否则出错
|
||||
$.post('/authorize/getUserRules', { id, id }, function (data) {
|
||||
layer.close(e);
|
||||
tree.render({
|
||||
elem: '#userMenu'
|
||||
, data: data
|
||||
, showCheckbox: true //是否显示复选框
|
||||
, id: 'userMenu'
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function groupUser(id, title) {
|
||||
$('#groupUser').html("");
|
||||
var index = layer.open({
|
||||
type: 1
|
||||
, title: '编辑成员-' + title
|
||||
, area: ['360px', '600px']
|
||||
, content: '<br><form class="layui-form"><div id="groupUser"></div></form>' //这里content是一个普通的String
|
||||
, btn: ['提交', '关闭']
|
||||
, yes: function () {
|
||||
layer.close(index);
|
||||
var e = layer.load(2, { shade: [0.2, '#2F4056'] });
|
||||
var users = '';
|
||||
var checkedData = tree.getChecked('groupUser'); //获取选中节点的数据
|
||||
if (checkedData != '') {
|
||||
checkedData = checkedData[0]["children"]; //取出子节点
|
||||
var dataLength = checkedData.length;
|
||||
for (let index = 0; index < dataLength; index++) {
|
||||
users += checkedData[index]['id'] + ',';
|
||||
}
|
||||
users = users.substr(0, users.length - 1);
|
||||
}
|
||||
$.post("/authorize/updateGroupUser/", { id: id, users: users }, function (msg) {
|
||||
layer.close(e);
|
||||
layer.msg(msg.msg, { time: 1000 });
|
||||
});
|
||||
}
|
||||
, btn2: function () {
|
||||
layer.close(index);
|
||||
}
|
||||
});
|
||||
//读取接口数据并渲染tree
|
||||
var e = layer.load(2, { shade: [0.2, '#2F4056'] });
|
||||
//data数据中仅需要末节点设置选中状态,其它节点无需设置,否则出错
|
||||
$.post('/authorize/getUserGroup', { id: id }, function (data) {
|
||||
layer.close(e);
|
||||
tree.render({
|
||||
elem: '#groupUser'
|
||||
, data: data
|
||||
, showCheckbox: true //是否显示复选框
|
||||
, id: 'groupUser'
|
||||
});
|
||||
});
|
||||
}
|
90
public/static/js/authorize/personal.js
Normal file
@ -0,0 +1,90 @@
|
||||
layui.use(['element', 'layer', 'table'], function () {
|
||||
var element = layui.element
|
||||
, table = layui.table
|
||||
, layer = layui.layer;
|
||||
table.render({
|
||||
elem: '#user'
|
||||
, id: 'uReload'
|
||||
, height: 'full-180'
|
||||
, method: 'post'
|
||||
, url: '/authorize/getPersonal' //数据接口
|
||||
, cols: [[ //表头
|
||||
{ field: 'ids', title: '#', width: 50, type: 'numbers', fixed: 'left' }
|
||||
, { field: 'name', edit: 'text', title: '姓名', width: 130 }
|
||||
, { field: 'username', title: '账号', width: 130 }
|
||||
, { field: 'email', edit: 'text', title: '邮箱', width: 220 }
|
||||
, { field: 'tel', edit: 'text', title: '电话', width: 130, sort: true }
|
||||
, { field: 'department', edit: 'text', title: '部门', width: 155 }
|
||||
, { field: 'position', edit: 'text', title: '职位', width: 155 }
|
||||
, { field: 'update_time', title: '更新时间', width: 200, sort: true }
|
||||
, { fixed: 'right', width: 120, title: '操作', align: 'center', toolbar: '#toolbar' } //这里的toolbar值是模板元素的选择器
|
||||
]]
|
||||
});
|
||||
var $ = layui.$, active = {
|
||||
reload: function () {
|
||||
var name = $('#name');
|
||||
var tel = $('#tel');
|
||||
//执行重载
|
||||
table.reload('uReload', {
|
||||
page: {
|
||||
curr: 1 //重新从第 1 页开始
|
||||
}
|
||||
, where: {
|
||||
name: name.val(),
|
||||
tel: tel.val(),
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
$('.userTable .layui-btn').on('click', function () {
|
||||
var type = $(this).data('type');
|
||||
active[type] ? active[type].call(this) : '';
|
||||
});
|
||||
//监听单元格编辑
|
||||
table.on('edit(user)', function (obj) {
|
||||
var e = layer.load(2, { shade: [0.2, '#2F4056'] });
|
||||
var value = obj.value //得到修改后的值
|
||||
, data = obj.data //得到所在行所有键值
|
||||
, field = obj.field; //得到字段
|
||||
$.post("/authorize/updatePersonal/" + data.id + "/" + field + "/" + value, function (msg) {
|
||||
layer.close(e);
|
||||
layer.msg(msg, { time: 1000 });
|
||||
});
|
||||
});
|
||||
table.on('tool(user)', function (obj) { //注:tool是工具条事件名,test是table原始容器的属性 lay-filter="对应的值"
|
||||
var data = obj.data; //获得当前行数据
|
||||
var layEvent = obj.event; //获得 lay-event 对应的值(也可以是表头的 event 参数对应的值)
|
||||
var tr = obj.tr; //获得当前行 tr 的DOM对象
|
||||
if (layEvent === 'edit') { //编辑
|
||||
var index = layer.open({
|
||||
type: 1
|
||||
, title: '修改密码'
|
||||
, area: ['420px', '320px']
|
||||
, content: '<br><form id="new_menu" class="layui-form" action=""><div class="layui-form-item"><label class="layui-form-label" style="width: 50px;">旧密码</label><div class="layui-inline" style="width: 300px;"><input class="layui-input" type="password" name="password" id="password" autocomplete="off"></div></div><div class="layui-form-item"><label class="layui-form-label" style="width: 50px;">新密码</label><div class="layui-inline" style="width: 300px;"><input class="layui-input" type="password" name="passwordn" id="passwordn" autocomplete="off"></div></div><div class="layui-form-item"><label class="layui-form-label" style="width: 50px;">重复新密码</label><div class="layui-inline" style="width: 300px;"><input class="layui-input" type="password" name="passwordn1" id="passwordn1" autocomplete="off"></div></div></form>' //这里content是一个普通的String
|
||||
, btn: ['提交', '关闭']
|
||||
, yes: function () {
|
||||
//通过ajax提交数据
|
||||
if ($('#passwordn').val() != $('#passwordn1').val()) {
|
||||
layer.msg('两次输入密码不同,请检查', { time: 2000 });
|
||||
} else {
|
||||
$.post("/authorize/updatePersonal/", { id: obj.data.id, field: 'password_hash', value: $('#passwordn').val(), opassword: $('#password').val() }, function (data) {
|
||||
if (data.code == 0) {
|
||||
layer.close(index);
|
||||
layer.msg(data.msg
|
||||
, { time: 3000 }
|
||||
, function () {
|
||||
location.replace(data.data);
|
||||
});
|
||||
} else {
|
||||
layer.msg(data.msg, { time: 3000 });
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
, btn2: function () {
|
||||
layer.close(index);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
225
public/static/js/authorize/rules.js
Normal file
@ -0,0 +1,225 @@
|
||||
//使用treeTable扩展
|
||||
layui.config({
|
||||
base: '/static/js/',
|
||||
})
|
||||
var treeTable, re, form;
|
||||
layui.use(['element', 'treeTable', 'layer', 'code', 'form'], function () {
|
||||
treeTable = layui.treeTable;
|
||||
var o = layui.$,
|
||||
form = layui.form,
|
||||
layer = layui.layer;
|
||||
var e = layer.load(2, { shade: [0.2, '#2F4056'] }); //打开数据加载动画
|
||||
re = treeTable.render({
|
||||
elem: '#tree-table',
|
||||
url: '/authorize/getRules/',
|
||||
icon_key: 'title',// 必须
|
||||
cols: [
|
||||
{
|
||||
key: 'title',
|
||||
title: '控制器',
|
||||
width: '180px',
|
||||
template: function (item) {
|
||||
if (item.level == 0) {
|
||||
return '<span style="color:#FF5722;">' + item.title + '</span>';
|
||||
} else if (item.level == 1) {
|
||||
return '<span style="color:#009688;">' + item.title + '</span>';
|
||||
} else if (item.level == 2) {
|
||||
return '<span style="color:#5FB878;">' + item.title + '</span>';
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'id',
|
||||
title: 'ID',
|
||||
width: '20px',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
key: 'pid',
|
||||
title: '父ID',
|
||||
width: '20px',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
key: 'navid',
|
||||
title: '排序',
|
||||
width: '20px',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
key: 'name',
|
||||
title: '名称',
|
||||
width: '80px',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
key: 'condition',
|
||||
title: '条件',
|
||||
width: '80px',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
key: 'type',
|
||||
title: '条件状态',
|
||||
width: '80px',
|
||||
align: 'center',
|
||||
template: function (item) {
|
||||
var result = '';
|
||||
if (item.id != 1) {
|
||||
if (item.type == 1) {
|
||||
result = '<input type="checkbox" name="type" value="' + item.id + '" lay-skin="switch" lay-text="启用|禁用" lay-filter="typeSwitch" checked="checked">'
|
||||
} else if (item.type == 'null') {
|
||||
result = '';
|
||||
} else {
|
||||
result = '<input type="checkbox" name="type" value="' + item.id + '" lay-skin="switch" lay-text="启用|禁用" lay-filter="typeSwitch">'
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'remarks',
|
||||
title: '备注',
|
||||
width: '200px',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
key: 'status',
|
||||
title: '规则状态',
|
||||
width: '80px',
|
||||
align: 'center',
|
||||
template: function (item) {
|
||||
var result = '';
|
||||
if (item.id != 1) {
|
||||
if (item.status == 1) {
|
||||
result = '<input type="checkbox" name="type" value="' + item.id + '" lay-skin="switch" lay-text="启用|禁用" lay-filter="statusSwitch" checked="checked">'
|
||||
} else if (item.status == 'null') {
|
||||
result = '';
|
||||
} else {
|
||||
result = '<input type="checkbox" name="type" value="' + item.id + '" lay-skin="switch" lay-text="启用|禁用" lay-filter="statusSwitch">'
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
align: 'left',
|
||||
width: '200px',
|
||||
template: function (item) {
|
||||
var add = '<a class="layui-btn layui-btn-sm" onclick="add(' + item.id + ')"><i class="layui-icon"></i>子规则</a>';
|
||||
var modify = '<a class="layui-btn layui-btn-normal layui-btn-sm" onclick="modify(' + item.id + ')"><i class="layui-icon"></i></a>';
|
||||
var del = '<a class="layui-btn layui-btn-danger layui-btn-sm" onclick="del(' + item.id + ')"><i class="layui-icon"></i></a>';
|
||||
if (item.level == 0) {
|
||||
return add + modify;
|
||||
} else if (item.level == 1) {
|
||||
return add + modify + del;
|
||||
} else {
|
||||
return modify + del;
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
end: function () {
|
||||
form.render(); //因表单动态生成需手动渲染表单元素
|
||||
layer.close(e); //关闭加载动画
|
||||
}
|
||||
});
|
||||
//监听指定开关
|
||||
form.on('switch(typeSwitch)', function (data) {
|
||||
var e = layer.load(2, { shade: [0.2, '#2F4056'] });
|
||||
if (this.checked == false) {
|
||||
value = 0;
|
||||
} else {
|
||||
value = 1;
|
||||
}
|
||||
$.post("/authorize/updateRulesState", { id: this.value, field: 'type', value: value }, function (msg) {
|
||||
layer.close(e);
|
||||
layer.msg(msg, { time: 1000 });
|
||||
});
|
||||
});
|
||||
//监听指定开关
|
||||
form.on('switch(statusSwitch)', function (data) {
|
||||
var e = layer.load(2, { shade: [0.2, '#2F4056'] });
|
||||
if (this.checked == false) {
|
||||
value = 0;
|
||||
} else {
|
||||
value = 1;
|
||||
}
|
||||
$.post("/authorize/updateRulesState", { id: this.value, field: 'status', value: value }, function (msg) {
|
||||
layer.close(e);
|
||||
layer.msg(msg, { time: 1000 });
|
||||
});
|
||||
});
|
||||
// 全部展开
|
||||
o('.open-all').click(function () {
|
||||
treeTable.openAll(re);
|
||||
})
|
||||
// 全部关闭
|
||||
o('.close-all').click(function () {
|
||||
treeTable.closeAll(re);
|
||||
})
|
||||
})
|
||||
function del(id) {
|
||||
layer.confirm('确认删除该规则?', function (index) {
|
||||
$.post("/authorize/delRules", { id: id }, function (data) {
|
||||
if (data.code === 0) {
|
||||
treeTable.render(re);
|
||||
}
|
||||
layer.close(index);
|
||||
layer.msg(data.msg, { time: 2000 });
|
||||
});
|
||||
});
|
||||
}
|
||||
function add(id) {
|
||||
var index = layer.open({
|
||||
type: 1
|
||||
, title: '添加规则'
|
||||
, area: ['460px', '410px']
|
||||
, content: '<br><form id="new_menu" class="layui-form" action=""><div class="layui-form-item"><label class="layui-form-label" style="width: 60px;">名称</label><div class="layui-inline" style="width: 340px;"><input class="layui-input" name="title" id="title" autocomplete="off"></div></div><div class="layui-form-item"><label class="layui-form-label" style="width: 60px;">控制器</label><div class="layui-inline" style="width: 340px;"><input class="layui-input" name="name" id="name" autocomplete="off"></div></div><div class="layui-form-item"><label class="layui-form-label" style="width: 60px;">条件</label><div class="layui-inline" style="width: 340px;"><input class="layui-input" name="condition" id="condition" autocomplete="off" value="{status} === 1"></div></div><div class="layui-form-item"><label class="layui-form-label" style="width: 60px;">备注</label><div class="layui-inline" style="width: 340px;"><textarea placeholder="请输入内容" name="remarks" id="remarks" class="layui-textarea"></textarea></div></div><input name="pid" id="pid" type="hidden" value="' + id + '"></form>' //这里content是一个普通的String
|
||||
, btn: ['提交', '关闭']
|
||||
, yes: function () {
|
||||
//通过ajax提交数据
|
||||
if ($('#name').val() == '' || $('#title').val() == '') {
|
||||
layer.msg('名称和控制器字段不能为空', { time: 2000 });
|
||||
} else {
|
||||
$.post("/authorize/saveRules", $("#new_menu").serialize(), function (data) {
|
||||
if (data.code === 0) {
|
||||
treeTable.render(re);
|
||||
}
|
||||
layer.close(index);
|
||||
layer.msg(data.msg, { time: 2000 });
|
||||
});
|
||||
}
|
||||
}
|
||||
, btn2: function () {
|
||||
layer.close(index);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function modify(id) {
|
||||
$.post("/authorize/getRules", { id: id }, function (result) {
|
||||
var index = layer.open({
|
||||
type: 1
|
||||
, title: '修改规则'
|
||||
, area: ['480px', '530px']
|
||||
, content: '<br><form id="mod_menu" class="layui-form" action=""><div class="layui-form-item"><label class="layui-form-label" style="width: 60px;">父ID</label><div class="layui-inline" style="width: 340px;"><input class="layui-input" name="pid" id="pid" value="' + result[0].pid + '" autocomplete="off"></div></div><div class="layui-form-item"><label class="layui-form-label" style="width: 60px;">名称</label><div class="layui-inline" style="width: 340px;"><input class="layui-input" name="title" id="title" value="' + result[0].name + '" autocomplete="off"></div></div><div class="layui-form-item"><label class="layui-form-label" style="width: 60px;">控制器</label><div class="layui-inline" style="width: 340px;"><input class="layui-input" name="name" id="name" value="' + result[0].title + '" autocomplete="off"></div></div><div class="layui-form-item"><label class="layui-form-label" style="width: 60px;">条件</label><div class="layui-inline" style="width: 340px;"><input class="layui-input" name="condition" id="condition" value="' + result[0].condition + '" autocomplete="off"></div></div><div class="layui-form-item"><label class="layui-form-label" style="width: 60px;">排序规则</label><div class="layui-inline" style="width: 340px;"><input class="layui-input" name="navid" id="navid" value="' + result[0].navid + '" autocomplete="off"></div></div><div class="layui-form-item"><label class="layui-form-label" style="width: 60px;">备注</label><div class="layui-inline" style="width: 340px;"><textarea class="layui-textarea" name="remarks" id="remarks">' + result[0].remarks + '</textarea></div></div><input name="id" id="id" type="hidden" value="' + id + '"></form>' //这里content是一个普通的String
|
||||
, btn: ['提交', '关闭']
|
||||
, yes: function () {
|
||||
//通过ajax提交数据
|
||||
$.post("/authorize/updateRules", $("#mod_menu").serialize(), function (data) {
|
||||
if (data.code === 0) {
|
||||
treeTable.render(re);
|
||||
}
|
||||
layer.close(index);
|
||||
layer.msg(data.msg, { time: 2000 });
|
||||
});
|
||||
}
|
||||
, btn2: function () {
|
||||
layer.close(index);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
141
public/static/js/authorize/user.js
Normal file
@ -0,0 +1,141 @@
|
||||
function addUser() {
|
||||
layer.open({
|
||||
type: 2 //此处以iframe举例
|
||||
, title: '添加账号'
|
||||
, area: ['500px', '600px']
|
||||
, shade: 0
|
||||
, maxmin: true
|
||||
, content: '/authorize/addUser'
|
||||
});
|
||||
}
|
||||
var from;
|
||||
layui.use(['element', 'form', 'layer', 'table'], function () {
|
||||
form = layui.form;
|
||||
var element = layui.element
|
||||
, table = layui.table
|
||||
, layer = layui.layer;
|
||||
table.render({
|
||||
elem: '#userlist'
|
||||
, id: 'uReload'
|
||||
, height: 'full-220'
|
||||
, method: 'post'
|
||||
, url: '/authorize/getUsers' //数据接口
|
||||
, page: true //开启分页
|
||||
, limits: [15, 50, 100]
|
||||
, limit: 15
|
||||
, cols: [[ //表头
|
||||
{ field: 'ids', title: '#', width: 50, type: 'numbers', fixed: 'left' }
|
||||
, { field: 'name', edit: 'text', title: '姓名', width: 100 }
|
||||
, { field: 'username', title: '账号', width: 120 }
|
||||
, { field: 'email', edit: 'text', title: '邮箱', width: 200 }
|
||||
, { field: 'tel', edit: 'text', title: '电话', width: 120, sort: true }
|
||||
, { field: 'department', edit: 'text', title: '部门', width: 160 }
|
||||
, { field: 'position', edit: 'text', title: '职位', width: 160 }
|
||||
, { field: 'group', title: '用户角色', width: 160 }
|
||||
, { field: 'update_time', title: '更新时间', width: 120, sort: true }
|
||||
, { field: 'status', title: '账户状态', width: 110, templet: "<div>{{ status(d.status,d.id)}}</div>" }
|
||||
, { fixed: 'right', width: 100, title: '操作', align: 'center', toolbar: '#toolbar' } //这里的toolbar值是模板元素的选择器
|
||||
]]
|
||||
});
|
||||
var $ = layui.$, active = {
|
||||
reload: function () {
|
||||
var name = $('#name');
|
||||
var tel = $('#tel');
|
||||
//执行重载
|
||||
table.reload('uReload', {
|
||||
page: {
|
||||
curr: 1 //重新从第 1 页开始
|
||||
}
|
||||
, where: {
|
||||
name: name.val(),
|
||||
tel: tel.val(),
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
$('.userTable .layui-btn').on('click', function () {
|
||||
var type = $(this).data('type');
|
||||
active[type] ? active[type].call(this) : '';
|
||||
});
|
||||
//监听单元格编辑
|
||||
table.on('edit(user)', function (obj) {
|
||||
var e = layer.load(2, { shade: [0.2, '#2F4056'] });
|
||||
var value = obj.value //得到修改后的值
|
||||
, data = obj.data //得到所在行所有键值
|
||||
, field = obj.field; //得到字段
|
||||
$.post("/authorize/updateUser", { id: data.id, field: field, value: value }, function (msg) {
|
||||
layer.close(e);
|
||||
layer.msg(msg, { time: 1000 });
|
||||
});
|
||||
});
|
||||
//监听账户状态操作
|
||||
form.on('checkbox(lockstatus)', function (obj) {
|
||||
var e = layer.load(2, { shade: [0.2, '#2F4056'] });
|
||||
if (obj.elem.checked == false) {
|
||||
value = 0;
|
||||
} else {
|
||||
value = 1;
|
||||
}
|
||||
$.post("/authorize/updateUser", { id: this.value, field: 'status', value: value }, function (msg) {
|
||||
layer.close(e);
|
||||
layer.msg(msg, { time: 1000 });
|
||||
});
|
||||
});
|
||||
table.on('tool(user)', function (obj) { //注:tool是工具条事件名,test是table原始容器的属性 lay-filter="对应的值"
|
||||
var data = obj.data; //获得当前行数据
|
||||
var layEvent = obj.event; //获得 lay-event 对应的值(也可以是表头的 event 参数对应的值)
|
||||
var tr = obj.tr; //获得当前行 tr 的DOM对象
|
||||
if (layEvent === 'del') { //删除
|
||||
layer.confirm('确认删除账号【' + obj.data.name + '】?', function (index) {
|
||||
//向服务端发送删除指令
|
||||
$.post("/authorize/delUser/", { id: obj.data.id }, function (data) {
|
||||
if (data.code === 0) {
|
||||
obj.del(); //删除对应行(tr)的DOM结构,并更新缓存
|
||||
}
|
||||
layer.close(index);
|
||||
layer.msg(data.msg, { time: 2000 });
|
||||
});
|
||||
});
|
||||
} else if (layEvent === 'edit') { //编辑
|
||||
var index = layer.open({
|
||||
type: 1
|
||||
, title: '【' + obj.data.name + '】重置密码'
|
||||
, area: ['420px', '200px']
|
||||
, content: '<br><form id="new_menu" class="layui-form" action=""><div class="layui-form-item"><label class="layui-form-label" style="width: 50px;">重置为</label><div class="layui-inline" style="width: 300px;"><input class="layui-input" type="text" id="passwordn" value="123456" disabled></div></div></form>' //这里content是一个普通的String
|
||||
, btn: ['提交', '关闭']
|
||||
, yes: function () {
|
||||
//通过ajax提交数据
|
||||
$.post("/authorize/updateUser/", { id: obj.data.id, field: 'password_hash', value: $('#passwordn').val() }, function (data) {
|
||||
layer.close(index);
|
||||
layer.msg(data, { time: 2000 });
|
||||
});
|
||||
}
|
||||
, btn2: function () {
|
||||
layer.close(index);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
//传入URL前缀及字段值
|
||||
function status(vals, id) {
|
||||
//判断是否需要拼接URL
|
||||
if (id === 1) {
|
||||
result = '<input type="checkbox" name="lock" value="' + id + '" title="启用" lay-filter="lockstatus" checked="checked" disabled="">';
|
||||
} else {
|
||||
if (vals === 0) {
|
||||
result = '<input type="checkbox" name="lock" value="' + id + '" title="启用" lay-filter="lockstatus">';
|
||||
} else if (vals === 1) {
|
||||
result = '<input type="checkbox" name="lock" value="' + id + '" title="启用" lay-filter="lockstatus" checked="checked">';
|
||||
} else {
|
||||
result = vals;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//传入URL前缀及字段值
|
||||
function operation(id) {
|
||||
var result = '<a class="layui-btn layui-btn-danger layui-btn-sm" lay-event="del"><i class="layui-icon"></i> 重置密码</a>';
|
||||
return result;
|
||||
}
|
235
public/static/js/treeTable.js
Normal file
@ -0,0 +1,235 @@
|
||||
layui.define(['jquery'], function(exports) {
|
||||
var MOD_NAME = 'treeTable',
|
||||
o = layui.jquery,
|
||||
tree = function() {};
|
||||
tree.prototype.config = function() {
|
||||
return {
|
||||
top_value: 0,
|
||||
primary_key: 'id',
|
||||
parent_key: 'pid',
|
||||
hide_class: 'layui-hide',
|
||||
icon: {
|
||||
open: 'layui-icon layui-icon-triangle-d',
|
||||
close: 'layui-icon layui-icon-triangle-r',
|
||||
left: 16,
|
||||
},
|
||||
cols: [],
|
||||
checked: {},
|
||||
is_click_icon: false,
|
||||
is_checkbox: false,
|
||||
is_cache: true,
|
||||
};
|
||||
}
|
||||
tree.prototype.template = function(e) {
|
||||
var t = this,
|
||||
level = [],
|
||||
tbody = '',
|
||||
is_table = o('table' + e.elem).length || !(e.is_click_icon = true),
|
||||
checkbox = e.is_checkbox ? '<div class="layui-unselect layui-form-checkbox cbx" lay-skin="primary"><i class="layui-icon layui-icon-ok"></i></div>' : '',
|
||||
checked = checkbox ? checkbox.replace('cbx', 'cbx layui-form-checked') : '',
|
||||
thead = checkbox && '<th style="width:28px;">' + (o.inArray(e.top_value, e.checked.data) > -1 ? checked : checkbox) + '</th>';
|
||||
o.each(t.data(e, e.data), function(idx, item) {
|
||||
var tr = '',
|
||||
is_checked = false,
|
||||
hide_class = (item[e.parent_key] == e.top_value) || (item[e.parent_key] == t.cache(e, item[e.parent_key])) ? '' : e.hide_class;
|
||||
// 设置每行数据层级
|
||||
item.level = level[item[e.primary_key]] = item[e.parent_key] != e.top_value ? (level[item[e.parent_key]] + 1) : 0;
|
||||
// 设置是否为最后一级
|
||||
item.is_end = !e.childs[item[e.primary_key]];
|
||||
o.each(e.cols, function(index, obj) {
|
||||
var style = '';
|
||||
obj.width && (style += 'width:' + obj.width + ';'), obj.align && (style += 'text-align:' + obj.align + ';'), style && (style = 'style="' + style + '"');
|
||||
// 标记设置行checkbox选中
|
||||
if(e.is_checkbox && e.checked && o.inArray(item[e.checked.key], e.checked.data) > -1) {
|
||||
is_checked = true;
|
||||
}
|
||||
// 第一次遍历头部的时候拼接表格头部
|
||||
idx || (thead += '<th ' + style + '>' + obj.title + '</th>');
|
||||
// 指定列加入开启、关闭小图标
|
||||
var icon = (obj.key == e.icon_key && !item.is_end) ? '<i class="' + (t.cache(e, item[e.primary_key]) ? e.icon.open : e.icon.close) + '"></i>' : '<span></span>';
|
||||
// 指定列小图标按照层级向后位移
|
||||
var left = (obj.key == e.icon_key ? level[item[e.primary_key]] * e.icon.left + 'px' : '');
|
||||
icon = icon.replace('>', ' style="margin-left:' + left + ';">');
|
||||
// 拼接行
|
||||
tr += '<td ' + style + (left ? 'data-down' : '') + '>' + icon + (is_table ? '' : (is_checked ? checked : checkbox)) + (obj.template ? obj.template(item) : item[obj.key]) + '</td>';
|
||||
});
|
||||
var box = is_table ? o(is_checked ? checked : checkbox).wrap('<td style="width:28px;">').parent().prop('outerHTML') : '';
|
||||
tbody += '<tr class="' + hide_class + '" data-id="' + item[e.primary_key] + '" data-pid="' + item[e.parent_key] + '">' + box + tr + '</tr>';
|
||||
});
|
||||
// 处理表树和树的赋值模板
|
||||
var table = is_table ? '<thead><tr data-id="' + e.top_value + '">' + thead + '</tr></thead><tbody>' + tbody + '</tbody>' : tbody.replace(/<tr/g, '<ul').replace(/tr>/g, 'ul>').replace(/<td/g, '<li').replace(/td>/g, 'li>');
|
||||
// 确认点击图标或点击列触发展开关闭
|
||||
var click_btn = e.is_click_icon ? '[data-down] i:not(.layui-icon-ok)' : '[data-down]';
|
||||
// 模板渲染并处理点击展开收起等功能
|
||||
o(e.elem).html(table).off('click', click_btn).on('click', click_btn, function() {
|
||||
var tr = o(this).parents('[data-id]'),
|
||||
td = tr.find('[data-down]'),
|
||||
id = tr.data('id'),
|
||||
pid = tr.data('pid'),
|
||||
is_open = (td.find('i:not(.layui-icon-ok)').attr('class') == e.icon.close);
|
||||
if(is_open) {
|
||||
// 展开子级(子级出现、更改图标)
|
||||
td.find('i:not(.layui-icon-ok)').attr('class', e.icon.open);
|
||||
td.parents(e.elem).find('[data-pid=' + id + ']').removeClass(e.hide_class);
|
||||
t.cache(e, id, true);
|
||||
} else {
|
||||
// 关闭子级(更改图标、隐藏所有子孙级)
|
||||
td.find('i:not(.layui-icon-ok)').attr('class', e.icon.close);
|
||||
t.childs_hide(e, id);
|
||||
}
|
||||
// 设置监听展开关闭
|
||||
layui.event.call(this, MOD_NAME, 'tree(flex)', {
|
||||
elem: this,
|
||||
item: e.childs[pid][id],
|
||||
table: e.elem,
|
||||
is_open: is_open,
|
||||
})
|
||||
}).off('click', '.cbx').on('click', '.cbx', function() {
|
||||
var is_checked = o(this).toggleClass('layui-form-checked').hasClass('layui-form-checked'),
|
||||
tr = o(this).parents('[data-id]'),
|
||||
id = tr.data('id'),
|
||||
pid = tr.data('pid');
|
||||
t.childs_checkbox(e, id, is_checked);
|
||||
t.parents_checkbox(e, pid);
|
||||
// 设置监听checkbox选择
|
||||
layui.event.call(this, MOD_NAME, 'tree(box)', {
|
||||
elem: this,
|
||||
item: pid === undefined ? {} : e.childs[pid][id],
|
||||
table: e.elem,
|
||||
is_checked: is_checked,
|
||||
})
|
||||
}).off('click', '[lay-filter]').on('click', '[lay-filter]', function() {
|
||||
var tr = o(this).parents('[data-id]'),
|
||||
id = tr.data('id'),
|
||||
pid = tr.data('pid'),
|
||||
filter = o(this).attr("lay-filter");
|
||||
return layui.event.call(this, MOD_NAME, 'tree(' + filter + ')', {
|
||||
elem: this,
|
||||
item: e.childs[pid][id],
|
||||
})
|
||||
});
|
||||
e.end && e.end(e);
|
||||
};
|
||||
// 同级全部选中父级选中/同级全部取消取消父级
|
||||
tree.prototype.parents_checkbox = function(e, pid) {
|
||||
var po = o(e.elem).find('[data-pid=' + pid + ']'),
|
||||
co = o(e.elem).find('[data-id=' + pid + ']'),
|
||||
len = o(e.elem).find('[data-pid=' + pid + '] .cbx.layui-form-checked').length;
|
||||
if(po.length == len || len == 0) {
|
||||
var pid = co.data('pid');
|
||||
len ? co.find('.cbx').addClass('layui-form-checked') : co.find('.cbx').removeClass('layui-form-checked');
|
||||
pid === undefined || this.parents_checkbox(e, pid);
|
||||
}
|
||||
};
|
||||
// 子级反选
|
||||
tree.prototype.childs_checkbox = function(e, id, is_checked) {
|
||||
var t = this;
|
||||
o(e.elem).find('[data-pid=' + id + ']').each(function() {
|
||||
var checkbox = o(this).find('.cbx');
|
||||
is_checked ? checkbox.addClass('layui-form-checked') : checkbox.removeClass('layui-form-checked');
|
||||
t.childs_checkbox(e, o(this).data('id'), is_checked);
|
||||
})
|
||||
};
|
||||
// 点击收起循环隐藏子级元素
|
||||
tree.prototype.childs_hide = function(e, id) {
|
||||
var t = this;
|
||||
t.cache(e, id, false);
|
||||
o(e.elem).find('[data-pid=' + id + ']:not(.' + e.hide_class + ')').each(function() {
|
||||
var td = o(this).find('[data-down]'),
|
||||
i = td.find('i:not(.layui-icon-ok)');
|
||||
// 关闭更换小图标
|
||||
i.length && i.attr('class', e.icon.close);
|
||||
// 隐藏子级
|
||||
td.parents(e.elem).find('[data-pid=' + id + ']').addClass(e.hide_class);
|
||||
t.childs_hide(e, o(this).data('id'))
|
||||
});
|
||||
};
|
||||
// 重新组合数据,父子级关系跟随
|
||||
tree.prototype.data = function(e) {
|
||||
var lists = [],
|
||||
childs = [];
|
||||
o.each(e.data, function(idx, item) {
|
||||
lists[item[e.primary_key]] = item;
|
||||
if(!childs[item[e.parent_key]]) {
|
||||
childs[item[e.parent_key]] = [];
|
||||
}
|
||||
childs[item[e.parent_key]][item[e.primary_key]] = item;
|
||||
});
|
||||
e.childs = childs;
|
||||
return this.tree_data(e, lists, e.top_value, []);
|
||||
};
|
||||
tree.prototype.tree_data = function(e, lists, pid, data) {
|
||||
var t = this;
|
||||
if(lists[pid]) {
|
||||
data.push(lists[pid]);
|
||||
delete lists[pid]
|
||||
}
|
||||
o.each(e.data, function(index, item) {
|
||||
if(item[e.parent_key] == pid) {
|
||||
data.concat(t.tree_data(e, lists, item[e.primary_key], data))
|
||||
}
|
||||
});
|
||||
return data;
|
||||
};
|
||||
tree.prototype.render = function(e) {
|
||||
var t = this;
|
||||
e = o.extend(t.config(), e);
|
||||
if(e.url) {
|
||||
o.get(e.url, function(res) {
|
||||
e.data = res;
|
||||
t.template(e);
|
||||
})
|
||||
} else {
|
||||
t.template(e);
|
||||
}
|
||||
return e;
|
||||
};
|
||||
// 获取已选值集合
|
||||
tree.prototype.checked = function(e) {
|
||||
var ids = [];
|
||||
o(e.elem).find('.cbx.layui-form-checked').each(function() {
|
||||
var id = o(this).parents('[data-id]').data('id');
|
||||
ids.push(id);
|
||||
})
|
||||
return ids;
|
||||
};
|
||||
// 全部展开
|
||||
tree.prototype.openAll = function(e) {
|
||||
var t = this;
|
||||
o.each(e.data, function(idx, item) {
|
||||
item[e.primary_key] && t.cache(e, item[e.primary_key], true);
|
||||
})
|
||||
t.render(e);
|
||||
}
|
||||
// 全部关闭
|
||||
tree.prototype.closeAll = function(e) {
|
||||
localStorage.setItem(e.elem.substr(1), '');
|
||||
this.render(e);
|
||||
}
|
||||
tree.prototype.on = function(events, callback) {
|
||||
return layui.onevent.call(this, MOD_NAME, events, callback)
|
||||
};
|
||||
// 存储折叠状态
|
||||
tree.prototype.cache = function(e, val, option) {
|
||||
if(!e.is_cache) {
|
||||
return false;
|
||||
}
|
||||
var t = this,
|
||||
name = e.elem.substr(1),
|
||||
val = val.toString(),
|
||||
cache = localStorage.getItem(name) ? localStorage.getItem(name).split(',') : [],
|
||||
index = o.inArray(val, cache);
|
||||
if(option === undefined) {
|
||||
return index == -1 ? false : val
|
||||
}
|
||||
if(option && index == -1) {
|
||||
cache.push(val)
|
||||
}
|
||||
if(!option && index > -1) {
|
||||
cache.splice(index, 1)
|
||||
}
|
||||
localStorage.setItem(name, cache.join(','));
|
||||
};
|
||||
var tree = new tree();
|
||||
exports(MOD_NAME, tree)
|
||||
});
|
2
public/static/layui/css/layui.css
Normal file
2
public/static/layui/css/layui.mobile.css
Normal file
2
public/static/layui/css/modules/code.css
Normal file
@ -0,0 +1,2 @@
|
||||
/** layui-v2.5.4 MIT License By https://www.layui.com */
|
||||
html #layuicss-skincodecss{display:none;position:absolute;width:1989px}.layui-code-h3,.layui-code-view{position:relative;font-size:12px}.layui-code-view{display:block;margin:10px 0;padding:0;border:1px solid #e2e2e2;border-left-width:6px;background-color:#F2F2F2;color:#333;font-family:Courier New}.layui-code-h3{padding:0 10px;height:32px;line-height:32px;border-bottom:1px solid #e2e2e2}.layui-code-h3 a{position:absolute;right:10px;top:0;color:#999}.layui-code-view .layui-code-ol{position:relative;overflow:auto}.layui-code-view .layui-code-ol li{position:relative;margin-left:45px;line-height:20px;padding:0 5px;border-left:1px solid #e2e2e2;list-style-type:decimal-leading-zero;*list-style-type:decimal;background-color:#fff}.layui-code-view pre{margin:0}.layui-code-notepad{border:1px solid #0C0C0C;border-left-color:#3F3F3F;background-color:#0C0C0C;color:#C2BE9E}.layui-code-notepad .layui-code-h3{border-bottom:none}.layui-code-notepad .layui-code-ol li{background-color:#3F3F3F;border-left:none}
|
BIN
public/static/layui/css/modules/layer/default/icon-ext.png
Normal file
After Width: | Height: | Size: 5.8 KiB |
BIN
public/static/layui/css/modules/layer/default/icon.png
Normal file
After Width: | Height: | Size: 11 KiB |
2
public/static/layui/css/modules/layer/default/layer.css
Normal file
BIN
public/static/layui/css/modules/layer/default/loading-0.gif
Normal file
After Width: | Height: | Size: 5.7 KiB |
BIN
public/static/layui/css/modules/layer/default/loading-1.gif
Normal file
After Width: | Height: | Size: 701 B |
BIN
public/static/layui/css/modules/layer/default/loading-2.gif
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
public/static/layui/font/iconfont.eot
Normal file
485
public/static/layui/font/iconfont.svg
Normal file
After Width: | Height: | Size: 277 KiB |
BIN
public/static/layui/font/iconfont.ttf
Normal file
BIN
public/static/layui/font/iconfont.woff
Normal file
BIN
public/static/layui/font/iconfont.woff2
Normal file
BIN
public/static/layui/images/face/0.gif
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
public/static/layui/images/face/1.gif
Normal file
After Width: | Height: | Size: 5.4 KiB |
BIN
public/static/layui/images/face/10.gif
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
public/static/layui/images/face/11.gif
Normal file
After Width: | Height: | Size: 4.0 KiB |
BIN
public/static/layui/images/face/12.gif
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
public/static/layui/images/face/13.gif
Normal file
After Width: | Height: | Size: 7.3 KiB |
BIN
public/static/layui/images/face/14.gif
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
public/static/layui/images/face/15.gif
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
public/static/layui/images/face/16.gif
Normal file
After Width: | Height: | Size: 6.6 KiB |
BIN
public/static/layui/images/face/17.gif
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
public/static/layui/images/face/18.gif
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
public/static/layui/images/face/19.gif
Normal file
After Width: | Height: | Size: 3.0 KiB |
BIN
public/static/layui/images/face/2.gif
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
public/static/layui/images/face/20.gif
Normal file
After Width: | Height: | Size: 5.0 KiB |
BIN
public/static/layui/images/face/21.gif
Normal file
After Width: | Height: | Size: 5.1 KiB |
BIN
public/static/layui/images/face/22.gif
Normal file
After Width: | Height: | Size: 9.6 KiB |
BIN
public/static/layui/images/face/23.gif
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
public/static/layui/images/face/24.gif
Normal file
After Width: | Height: | Size: 7.9 KiB |