有些问题,重置了下。

This commit is contained in:
彭雨 2020-01-09 12:45:01 +08:00
commit 62b0a59f1f
713 changed files with 92036 additions and 0 deletions

1
.env Normal file
View 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
View File

@ -0,0 +1,3 @@
/.idea
/.vscode
*.log

42
.travis.yml Normal file
View 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
View 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
View 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.4PHP 7.3.7+MysqlThinkPHP 6.0.1Layui 2.5.4jquery 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之间时这条规则才会通过
#### 系统截图
![首页](https://images.gitee.com/uploads/images/2019/0731/151222_2c6411f1_1219033.png "QQ截图20190731151159.png")
![用户管理](https://images.gitee.com/uploads/images/2019/0731/151320_b1679188_1219033.png "QQ截图20190731151159.png")
![角色管理-角色成员](https://images.gitee.com/uploads/images/2019/0731/151422_4da967ef_1219033.png "QQ截图20190731151349.png")
![角色管理-角色权限](https://images.gitee.com/uploads/images/2019/0731/151740_ae445a4f_1219033.png "QQ截图20190731151717.png")
![规则管理](https://images.gitee.com/uploads/images/2019/0731/151823_fed7920b_1219033.png "QQ截图20190731151717.png")
![数据字典](https://images.gitee.com/uploads/images/2019/0731/170740_4d74217f_1219033.png "QQ截图20190731151717.png")

1
app/.htaccess Normal file
View File

@ -0,0 +1 @@
deny from all

94
app/BaseController.php Normal file
View 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
View 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
View File

@ -0,0 +1,8 @@
<?php
namespace app;
// 应用请求对象类
class Request extends \think\Request
{
}

2
app/common.php Normal file
View File

@ -0,0 +1,2 @@
<?php
// 应用公共文件

View 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
View 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
View 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
View File

@ -0,0 +1,17 @@
<?php
// 事件定义文件
return [
'bind' => [
],
'listen' => [
'AppInit' => [],
'HttpRun' => [],
'HttpEnd' => [],
'LogLevel' => [],
'LogWrite' => [],
],
'subscribe' => [
],
];

10
app/middleware.php Normal file
View 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
View 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;
}
}

View 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
View 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
View 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
View 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
View 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
View File

@ -0,0 +1 @@
如果不使用模板,可以删除该目录

View 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">&#xe605;</i> 提交</button>
<button id="reset" type="reset" style="width: 120px;" class="layui-btn layui-btn-primary">
<i title="重置" class="iconfont">&#x1006;</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>

View 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">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<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">&#xe615;</i>
</button>
<button title="添加" class="layui-btn layui-btn-warm" data-type="addGroup">
<i class="iconfont">&#xe654;</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>

View 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">&#xe642;</i>修改密码</a>
</script> {include file="public/footer"/}
</div>
</body>
</html>

View 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">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<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>

View 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">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<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">&#xe615;</i>
</button>
<button title="添加" class="layui-btn layui-btn-warm" onclick="addUser();">
<i class="iconfont">&#xe654;</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">&#xe642;</i></a>
<a title="删除账号" class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del"><i class="iconfont">&#xe640;</i></a>
</script> {include file="public/footer"/}
</div>
</body>
</html>

View 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>&nbsp;&nbsp;&nbsp;&nbsp;
<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
View 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>

View 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;">&#xe61c;</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>

View File

@ -0,0 +1,5 @@
</div>
<div class="layui-footer" style="left: 200px;">
<!-- 底部固定区域 -->
<span>© F.R Lab</span>
</div>

View 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">&#xe671;</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">&#xe612;</i>&nbsp;&nbsp;个人信息</a>
</dd> {if($auth->check('sql', $Request.session.id))}
<dd>
<a href="/common/sql" target="_blank">
<i class="iconfont">&#xe62e;</i>&nbsp;&nbsp;数据字典</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>

View 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">&#xe672;</i>&nbsp;&nbsp;权限管理</a>
<dl class="layui-nav-child">
{if($auth->check('user_list', $Request.session.id))}
<dd class="[userlist]">
<a href="/authorize/user">&nbsp;&nbsp;
<i class="iconfont">&#xe770;</i>&nbsp;&nbsp;用户管理</a>
</dd>
{/if} {if($auth->check('group_list', $Request.session.id))}
<dd class="[grouplist]">
<a href="/authorize/group">&nbsp;&nbsp;
<i class="iconfont">&#xe66f;</i>&nbsp;&nbsp;角色管理</a>
</dd>
{/if} {if($auth->check('menu_list', $Request.session.id))}
<dd class="[menulist]">
<a href="/authorize/rules">&nbsp;&nbsp;
<i class="iconfont">&#xe64e;</i>&nbsp;&nbsp;规则管理</a>
</dd>
{/if}
</dl>
</li>
{/if}
</ul>
</div>
</div>
<div class="layui-body" style="left: 200px;">
{/if}

88
app/view/sql.html Normal file
View 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
View 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
View 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
View 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
View 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
View File

@ -0,0 +1,9 @@
<?php
// +----------------------------------------------------------------------
// | 控制台配置
// +----------------------------------------------------------------------
return [
// 指令定义
'commands' => [
],
];

18
config/cookie.php Normal file
View 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
View 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
View 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
View 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
View 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
View File

@ -0,0 +1,8 @@
<?php
// 中间件配置
return [
// 别名或分组
'alias' => [],
// 优先级设置,此数组中的中间件会按照数组中的顺序优先执行
'priority' => [],
];

45
config/route.php Normal file
View 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
View 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
View File

@ -0,0 +1,10 @@
<?php
// +----------------------------------------------------------------------
// | Trace设置 开启调试模式后有效
// +----------------------------------------------------------------------
return [
// 内置Html和Console两种方式 支持扩展
'type' => 'Html',
// 读取的日志通道名
'channel' => '',
];

25
config/view.php Normal file
View 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' => '}',
];

View 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
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

136
public/fr_lab.sql Normal file
View 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
View 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
View File

@ -0,0 +1,2 @@
User-agent: *
Disallow:

17
public/router.php Normal file
View 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";
}

View 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;
}

View 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; }

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
public/static/images/bg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

View 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;
});
});

View 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">&#xe66f;</i> 角色成员</a><a class="layui-btn layui-btn-warm layui-btn-sm" onclick="userMenu(' + id + ",\'" + title + '\')"><i class="layui-icon">&#xe679;</i> 角色权限</a>';
var result_del = '<a class="layui-btn layui-btn-danger layui-btn-sm" lay-event="del"><i class="layui-icon">&#xe640;</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'
});
});
}

View 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);
}
});
}
});
});

View 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">&#xe654;</i>子规则</a>';
var modify = '<a class="layui-btn layui-btn-normal layui-btn-sm" onclick="modify(' + item.id + ')"><i class="layui-icon">&#xe642;</i></a>';
var del = '<a class="layui-btn layui-btn-danger layui-btn-sm" onclick="del(' + item.id + ')"><i class="layui-icon">&#xe640;</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);
}
});
});
}

View 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">&#xe640;</i> 重置密码</a>';
return result;
}

View 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)
});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View 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}

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 701 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 277 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Some files were not shown because too many files have changed in this diff Show More