ソースを参照

修复分类管理和规则管理父级调整的BUG
修复管理员日志数据过长的BUG

Karson 6 年 前
コミット
a7627c347f

+ 1 - 4
application/admin/behavior/AdminLog.php

@@ -4,13 +4,10 @@ namespace app\admin\behavior;
 
 class AdminLog
 {
-
     public function run(&$params)
     {
-        if (request()->isPost())
-        {
+        if (request()->isPost()) {
             \app\admin\model\AdminLog::record();
         }
     }
-
 }

+ 6 - 4
application/admin/command/Crud/stubs/mixins/recyclebinjs.stub

@@ -35,16 +35,18 @@
                                 {
                                     name: 'Restore',
                                     text: __('Restore'),
-                                    classname: 'btn btn-xs btn-info btn-restoreit',
+                                    classname: 'btn btn-xs btn-info btn-ajax btn-restoreit',
                                     icon: 'fa fa-rotate-left',
-                                    url: '{%controllerUrl%}/restore'
+                                    url: '{%controllerUrl%}/restore',
+                                    refresh: true
                                 },
                                 {
                                     name: 'Destroy',
                                     text: __('Destroy'),
-                                    classname: 'btn btn-xs btn-danger btn-destroyit',
+                                    classname: 'btn btn-xs btn-danger btn-ajax btn-destroyit',
                                     icon: 'fa fa-times',
-                                    url: '{%controllerUrl%}/destroy'
+                                    url: '{%controllerUrl%}/destroy',
+                                    refresh: true
                                 }
                             ],
                             formatter: Table.api.formatter.operate

+ 4 - 4
application/admin/common.php

@@ -130,14 +130,14 @@ if (!function_exists('build_toolbar')) {
                 $template = str_replace('/', '_', $controller);
                 $download = '';
                 if (file_exists("./template/{$template}.xlsx")) {
-                    $download .= "\n                                <li><a href=\"/template/{$template}.xlsx\" target=\"_blank\">XLSX模版</a></li>";
+                    $download .= "<li><a href=\"/template/{$template}.xlsx\" target=\"_blank\">XLSX模版</a></li>";
                 }
                 if (file_exists("./template/{$template}.xls")) {
-                    $download .= "\n                                <li><a href=\"/template/{$template}.xls\" target=\"_blank\">XLS模版</a></li>";
+                    $download .= "<li><a href=\"/template/{$template}.xls\" target=\"_blank\">XLS模版</a></li>";
                 }
                 if (file_exists("./template/{$template}.csv")) {
-                    $download .= empty($download) ? '' : "\n                                <li class=\"divider\"></li>";
-                    $download .= "\n                                <li><a href=\"/template/{$template}.csv\" target=\"_blank\">CSV模版</a></li>";
+                    $download .= empty($download) ? '' : "<li class=\"divider\"></li>";
+                    $download .= "<li><a href=\"/template/{$template}.csv\" target=\"_blank\">CSV模版</a></li>";
                 }
                 $download .= empty($download) ? '' : "\n                            ";
                 if (!empty($download)) {

+ 72 - 24
application/admin/controller/Category.php

@@ -10,7 +10,7 @@ use fast\Tree;
  * 分类管理
  *
  * @icon fa fa-list
- * @remark 用于统一管理网站的所有分类,分类可进行无限级分类
+ * @remark 用于统一管理网站的所有分类,分类可进行无限级分类,分类类型请在常规管理->系统配置->字典配置中添加
  */
 class Category extends Backend
 {
@@ -32,13 +32,14 @@ class Category extends Backend
         $tree->init(collection($this->model->order('weigh desc,id desc')->select())->toArray(), 'pid');
         $this->categorylist = $tree->getTreeList($tree->getTreeArray(0), 'name');
         $categorydata = [0 => ['type' => 'all', 'name' => __('None')]];
-        foreach ($this->categorylist as $k => $v)
-        {
+        foreach ($this->categorylist as $k => $v) {
             $categorydata[$v['id']] = $v;
         }
+        $typeList = CategoryModel::getTypeList();
         $this->view->assign("flagList", $this->model->getFlagList());
-        $this->view->assign("typeList", CategoryModel::getTypeList());
+        $this->view->assign("typeList", $typeList);
         $this->view->assign("parentList", $categorydata);
+        $this->assignconfig('typeList', $typeList);
     }
 
     /**
@@ -46,35 +47,30 @@ class Category extends Backend
      */
     public function index()
     {
-        if ($this->request->isAjax())
-        {
+        if ($this->request->isAjax()) {
             $search = $this->request->request("search");
             $type = $this->request->request("type");
 
             //构造父类select列表选项数据
             $list = [];
 
-                foreach ($this->categorylist as $k => $v)
-                {
-                    if ($search) {
-                        if ($v['type'] == $type && stripos($v['name'], $search) !== false || stripos($v['nickname'], $search) !== false)
-                        {
-                            if($type == "all" || $type == null) {
-                                $list = $this->categorylist;
-                            } else {
-                                $list[] = $v;
-                            }
-                        }
-                    } else {
-                        if($type == "all" || $type == null) {
+            foreach ($this->categorylist as $k => $v) {
+                if ($search) {
+                    if ($v['type'] == $type && stripos($v['name'], $search) !== false || stripos($v['nickname'], $search) !== false) {
+                        if ($type == "all" || $type == null) {
                             $list = $this->categorylist;
-                        } else if ($v['type'] == $type){
+                        } else {
                             $list[] = $v;
                         }
-
                     }
-
+                } else {
+                    if ($type == "all" || $type == null) {
+                        $list = $this->categorylist;
+                    } elseif ($v['type'] == $type) {
+                        $list[] = $v;
+                    }
                 }
+            }
 
             $total = count($list);
             $result = array("total" => $total, "rows" => $list);
@@ -85,13 +81,65 @@ class Category extends Backend
     }
 
     /**
+     * 编辑
+     */
+    public function edit($ids = null)
+    {
+        $row = $this->model->get($ids);
+        if (!$row) {
+            $this->error(__('No Results were found'));
+        }
+        $adminIds = $this->getDataLimitAdminIds();
+        if (is_array($adminIds)) {
+            if (!in_array($row[$this->dataLimitField], $adminIds)) {
+                $this->error(__('You have no permission'));
+            }
+        }
+        if ($this->request->isPost()) {
+            $params = $this->request->post("row/a");
+            if ($params) {
+                $params = $this->preExcludeFields($params);
+
+                if ($params['pid'] != $row['pid']) {
+                    $childrenIds = Tree::instance()->init(collection(\app\common\model\Category::select())->toArray())->getChildrenIds($row['id']);
+                    if (in_array($params['pid'], $childrenIds)) {
+                        $this->error(__('Can not change the parent to child'));
+                    }
+                }
+
+                try {
+                    //是否采用模型验证
+                    if ($this->modelValidate) {
+                        $name = str_replace("\\model\\", "\\validate\\", get_class($this->model));
+                        $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.edit' : $name) : $this->modelValidate;
+                        $row->validate($validate);
+                    }
+                    $result = $row->allowField(true)->save($params);
+                    if ($result !== false) {
+                        $this->success();
+                    } else {
+                        $this->error($row->getError());
+                    }
+                } catch (\think\exception\PDOException $e) {
+                    $this->error($e->getMessage());
+                } catch (\think\Exception $e) {
+                    $this->error($e->getMessage());
+                }
+            }
+            $this->error(__('Parameter %s can not be empty', ''));
+        }
+        $this->view->assign("row", $row);
+        return $this->view->fetch();
+    }
+
+
+    /**
      * Selectpage搜索
-     * 
+     *
      * @internal
      */
     public function selectpage()
     {
         return parent::selectpage();
     }
-
 }

+ 27 - 33
application/admin/controller/auth/Rule.php

@@ -2,6 +2,7 @@
 
 namespace app\admin\controller\auth;
 
+use app\admin\model\AuthRule;
 use app\common\controller\Backend;
 use fast\Tree;
 use think\Cache;
@@ -28,8 +29,7 @@ class Rule extends Backend
         $this->model = model('AuthRule');
         // 必须将结果集转换为数组
         $ruleList = collection($this->model->order('weigh', 'desc')->order('id', 'asc')->select())->toArray();
-        foreach ($ruleList as $k => &$v)
-        {
+        foreach ($ruleList as $k => &$v) {
             $v['title'] = __($v['title']);
             $v['remark'] = __($v['remark']);
         }
@@ -37,10 +37,10 @@ class Rule extends Backend
         Tree::instance()->init($ruleList);
         $this->rulelist = Tree::instance()->getTreeList(Tree::instance()->getTreeArray(0), 'title');
         $ruledata = [0 => __('None')];
-        foreach ($this->rulelist as $k => &$v)
-        {
-            if (!$v['ismenu'])
+        foreach ($this->rulelist as $k => &$v) {
+            if (!$v['ismenu']) {
                 continue;
+            }
             $ruledata[$v['id']] = $v['title'];
         }
         unset($v);
@@ -52,8 +52,7 @@ class Rule extends Backend
      */
     public function index()
     {
-        if ($this->request->isAjax())
-        {
+        if ($this->request->isAjax()) {
             $list = $this->rulelist;
             $total = count($this->rulelist);
 
@@ -69,18 +68,14 @@ class Rule extends Backend
      */
     public function add()
     {
-        if ($this->request->isPost())
-        {
+        if ($this->request->isPost()) {
             $params = $this->request->post("row/a", [], 'strip_tags');
-            if ($params)
-            {
-                if (!$params['ismenu'] && !$params['pid'])
-                {
+            if ($params) {
+                if (!$params['ismenu'] && !$params['pid']) {
                     $this->error(__('The non-menu rule must have parent'));
                 }
                 $result = $this->model->validate()->save($params);
-                if ($result === FALSE)
-                {
+                if ($result === false) {
                     $this->error($this->model->getError());
                 }
                 Cache::rm('__menu__');
@@ -94,28 +89,31 @@ class Rule extends Backend
     /**
      * 编辑
      */
-    public function edit($ids = NULL)
+    public function edit($ids = null)
     {
         $row = $this->model->get(['id' => $ids]);
-        if (!$row)
+        if (!$row) {
             $this->error(__('No Results were found'));
-        if ($this->request->isPost())
-        {
+        }
+        if ($this->request->isPost()) {
             $params = $this->request->post("row/a", [], 'strip_tags');
-            if ($params)
-            {
-                if (!$params['ismenu'] && !$params['pid'])
-                {
+            if ($params) {
+                if (!$params['ismenu'] && !$params['pid']) {
                     $this->error(__('The non-menu rule must have parent'));
                 }
+                if ($params['pid'] != $row['pid']) {
+                    $childrenIds = Tree::instance()->init(collection(AuthRule::select())->toArray())->getChildrenIds($row['id']);
+                    if (in_array($params['pid'], $childrenIds)) {
+                        $this->error(__('Can not change the parent to child'));
+                    }
+                }
                 //这里需要针对name做唯一验证
                 $ruleValidate = \think\Loader::validate('AuthRule');
                 $ruleValidate->rule([
                     'name' => 'require|format|unique:AuthRule,name,' . $row->id,
                 ]);
                 $result = $row->validate()->save($params);
-                if ($result === FALSE)
-                {
+                if ($result === false) {
                     $this->error($row->getError());
                 }
                 Cache::rm('__menu__');
@@ -132,22 +130,18 @@ class Rule extends Backend
      */
     public function del($ids = "")
     {
-        if ($ids)
-        {
+        if ($ids) {
             $delIds = [];
-            foreach (explode(',', $ids) as $k => $v)
-            {
-                $delIds = array_merge($delIds, Tree::instance()->getChildrenIds($v, TRUE));
+            foreach (explode(',', $ids) as $k => $v) {
+                $delIds = array_merge($delIds, Tree::instance()->getChildrenIds($v, true));
             }
             $delIds = array_unique($delIds);
             $count = $this->model->where('id', 'in', $delIds)->delete();
-            if ($count)
-            {
+            if ($count) {
                 Cache::rm('__menu__');
                 $this->success();
             }
         }
         $this->error();
     }
-
 }

+ 1 - 1
application/admin/lang/zh-cn.php

@@ -172,7 +172,7 @@ return [
     'Third group 2'                                         => '三级管理组2',
     'Dashboard tips'                                        => '用于展示当前系统中的统计数据、统计报表及重要实时数据',
     'Config tips'                                           => '可以在此增改系统的变量和分组,也可以自定义分组和变量,如果需要删除请从数据库中删除',
-    'Category tips'                                         => '用于统一管理网站的所有分类,分类可进行无限级分类',
+    'Category tips'                                         => '用于统一管理网站的所有分类,分类可进行无限级分类,分类类型请在常规管理->系统配置->字典配置中添加',
     'Attachment tips'                                       => '主要用于管理上传到服务器或第三方存储的数据',
     'Addon tips'                                            => '可在线安装、卸载、禁用、启用插件,同时支持添加本地插件。FastAdmin已上线插件商店 ,你可以发布你的免费或付费插件:<a href="https://www.fastadmin.net/store.html" target="_blank">https://www.fastadmin.net/store.html</a>',
     'Admin tips'                                            => '一个管理员可以有多个角色组,左侧的菜单根据管理员所拥有的权限进行生成',

+ 1 - 0
application/admin/lang/zh-cn/auth/rule.php

@@ -15,5 +15,6 @@ return [
     'Menu tips'                                                 => '父级菜单无需匹配控制器和方法,子级菜单请使用控制器名',
     'Node tips'                                                 => '控制器/方法名,如果有目录请使用 目录名/控制器名/方法名',
     'The non-menu rule must have parent'                        => '非菜单规则节点必须有父级',
+    'Can not change the parent to child'                        => '父组别不能是它的子组别',
     'Name only supports letters, numbers, underscore and slash' => 'URL规则只能是小写字母、数字、下划线和/组成',
 ];

+ 13 - 12
application/admin/lang/zh-cn/category.php

@@ -1,16 +1,17 @@
 <?php
 
 return [
-    'Id'          => 'ID',
-    'Pid'         => '父ID',
-    'Type'        => '栏目类型',
-    'All'         => '全部',
-    'Image'       => '图片',
-    'Keywords'    => '关键字',
-    'Description' => '描述',
-    'Diyname'     => '自定义名称',
-    'Createtime'  => '创建时间',
-    'Updatetime'  => '更新时间',
-    'Weigh'       => '权重',
-    'Status'      => '状态'
+    'Id'                                 => 'ID',
+    'Pid'                                => '父ID',
+    'Type'                               => '栏目类型',
+    'All'                                => '全部',
+    'Image'                              => '图片',
+    'Keywords'                           => '关键字',
+    'Description'                        => '描述',
+    'Diyname'                            => '自定义名称',
+    'Createtime'                         => '创建时间',
+    'Updatetime'                         => '更新时间',
+    'Weigh'                              => '权重',
+    'Can not change the parent to child' => '父组别不能是它的子组别',
+    'Status'                             => '状态'
 ];

+ 1 - 1
application/admin/library/traits/Backend.php

@@ -17,7 +17,7 @@ trait Backend
      * @param $params
      * @return array
      */
-    private function preExcludeFields($params)
+    protected function preExcludeFields($params)
     {
         if (is_array($this->excludeFields)) {
             foreach ($this->excludeFields as $field) {

+ 7 - 13
application/admin/model/AdminLog.php

@@ -34,24 +34,19 @@ class AdminLog extends Model
         $admin_id = $auth->isLogin() ? $auth->id : 0;
         $username = $auth->isLogin() ? $auth->username : __('Unknown');
         $content = self::$content;
-        if (!$content)
-        {
+        if (!$content) {
             $content = request()->param();
-            foreach ($content as $k => $v)
-            {
-                if (is_string($v) && strlen($v) > 200 || stripos($k, 'password') !== false)
-                {
+            foreach ($content as $k => $v) {
+                if (is_string($v) && strlen($v) > 200 || stripos($k, 'password') !== false) {
                     unset($content[$k]);
                 }
             }
         }
         $title = self::$title;
-        if (!$title)
-        {
+        if (!$title) {
             $title = [];
             $breadcrumb = Auth::instance()->getBreadcrumb();
-            foreach ($breadcrumb as $k => $v)
-            {
+            foreach ($breadcrumb as $k => $v) {
                 $title[] = $v['title'];
             }
             $title = implode(' ', $title);
@@ -59,10 +54,10 @@ class AdminLog extends Model
         self::create([
             'title'     => $title,
             'content'   => !is_scalar($content) ? json_encode($content) : $content,
-            'url'       => request()->url(),
+            'url'       => substr(request()->url(), 0, 1500),
             'admin_id'  => $admin_id,
             'username'  => $username,
-            'useragent' => request()->server('HTTP_USER_AGENT'),
+            'useragent' => substr(request()->server('HTTP_USER_AGENT'), 0, 255),
             'ip'        => request()->ip()
         ]);
     }
@@ -71,5 +66,4 @@ class AdminLog extends Model
     {
         return $this->belongsTo('Admin', 'admin_id')->setEagerlyType(0);
     }
-
 }

+ 287 - 287
application/index/controller/User.php

@@ -1,287 +1,287 @@
-<?php
-
-namespace app\index\controller;
-
-use app\common\controller\Frontend;
-use think\Config;
-use think\Cookie;
-use think\Hook;
-use think\Session;
-use think\Validate;
-
-/**
- * 会员中心
- */
-class User extends Frontend
-{
-
-    protected $layout = 'default';
-    protected $noNeedLogin = ['login', 'register', 'third'];
-    protected $noNeedRight = ['*'];
-
-    public function _initialize()
-    {
-        parent::_initialize();
-        $auth = $this->auth;
-
-        if (!Config::get('fastadmin.usercenter')) {
-            $this->error(__('User center already closed'));
-        }
-
-        $ucenter = get_addon_info('ucenter');
-        if ($ucenter && $ucenter['state']) {
-            include ADDON_PATH . 'ucenter' . DS . 'uc.php';
-        }
-
-        //监听注册登录注销的事件
-        Hook::add('user_login_successed', function ($user) use ($auth) {
-            $expire = input('post.keeplogin') ? 30 * 86400 : 0;
-            Cookie::set('uid', $user->id, $expire);
-            Cookie::set('token', $auth->getToken(), $expire);
-        });
-        Hook::add('user_register_successed', function ($user) use ($auth) {
-            Cookie::set('uid', $user->id);
-            Cookie::set('token', $auth->getToken());
-        });
-        Hook::add('user_delete_successed', function ($user) use ($auth) {
-            Cookie::delete('uid');
-            Cookie::delete('token');
-        });
-        Hook::add('user_logout_successed', function ($user) use ($auth) {
-            Cookie::delete('uid');
-            Cookie::delete('token');
-        });
-    }
-
-    /**
-     * 空的请求
-     * @param $name
-     * @return mixed
-     */
-    public function _empty($name)
-    {
-        $data = Hook::listen("user_request_empty", $name);
-        foreach ($data as $index => $datum) {
-            $this->view->assign($datum);
-        }
-        return $this->view->fetch('user/' . $name);
-    }
-
-    /**
-     * 会员中心
-     */
-    public function index()
-    {
-        $this->view->assign('title', __('User center'));
-        return $this->view->fetch();
-    }
-
-    /**
-     * 注册会员
-     */
-    public function register()
-    {
-        $url = $this->request->request('url');
-        if ($this->auth->id)
-            $this->success(__('You\'ve logged in, do not login again'), $url);
-        if ($this->request->isPost()) {
-            $username = $this->request->post('username');
-            $password = $this->request->post('password');
-            $email = $this->request->post('email');
-            $mobile = $this->request->post('mobile', '');
-            $captcha = $this->request->post('captcha');
-            $token = $this->request->post('__token__');
-            $rule = [
-                'username'  => 'require|length:3,30',
-                'password'  => 'require|length:6,30',
-                'email'     => 'require|email',
-                'mobile'    => 'regex:/^1\d{10}$/',
-                'captcha'   => 'require|captcha',
-                '__token__' => 'token',
-            ];
-
-            $msg = [
-                'username.require' => 'Username can not be empty',
-                'username.length'  => 'Username must be 3 to 30 characters',
-                'password.require' => 'Password can not be empty',
-                'password.length'  => 'Password must be 6 to 30 characters',
-                'captcha.require'  => 'Captcha can not be empty',
-                'captcha.captcha'  => 'Captcha is incorrect',
-                'email'            => 'Email is incorrect',
-                'mobile'           => 'Mobile is incorrect',
-            ];
-            $data = [
-                'username'  => $username,
-                'password'  => $password,
-                'email'     => $email,
-                'mobile'    => $mobile,
-                'captcha'   => $captcha,
-                '__token__' => $token,
-            ];
-            $validate = new Validate($rule, $msg);
-            $result = $validate->check($data);
-            if (!$result) {
-                $this->error(__($validate->getError()), null, ['token' => $this->request->token()]);
-            }
-            if ($this->auth->register($username, $password, $email, $mobile)) {
-                $synchtml = '';
-                ////////////////同步到Ucenter////////////////
-                if (defined('UC_STATUS') && UC_STATUS) {
-                    $uc = new \addons\ucenter\library\client\Client();
-                    $synchtml = $uc->uc_user_synregister($this->auth->id, $password);
-                }
-                $this->success(__('Sign up successful') . $synchtml, $url ? $url : url('user/index'));
-            } else {
-                $this->error($this->auth->getError(), null, ['token' => $this->request->token()]);
-            }
-        }
-        //判断来源
-        $referer = $this->request->server('HTTP_REFERER');
-        if (!$url && (strtolower(parse_url($referer, PHP_URL_HOST)) == strtolower($this->request->host()))
-            && !preg_match("/(user\/login|user\/register)/i", $referer)) {
-            $url = $referer;
-        }
-        $this->view->assign('url', $url);
-        $this->view->assign('title', __('Register'));
-        return $this->view->fetch();
-    }
-
-    /**
-     * 会员登录
-     */
-    public function login()
-    {
-        $url = $this->request->request('url');
-        if ($this->auth->id)
-            $this->success(__('You\'ve logged in, do not login again'), $url);
-        if ($this->request->isPost()) {
-            $account = $this->request->post('account');
-            $password = $this->request->post('password');
-            $keeplogin = (int)$this->request->post('keeplogin');
-            $token = $this->request->post('__token__');
-            $rule = [
-                'account'   => 'require|length:3,50',
-                'password'  => 'require|length:6,30',
-                '__token__' => 'token',
-            ];
-
-            $msg = [
-                'account.require'  => 'Account can not be empty',
-                'account.length'   => 'Account must be 3 to 50 characters',
-                'password.require' => 'Password can not be empty',
-                'password.length'  => 'Password must be 6 to 30 characters',
-            ];
-            $data = [
-                'account'   => $account,
-                'password'  => $password,
-                '__token__' => $token,
-            ];
-            $validate = new Validate($rule, $msg);
-            $result = $validate->check($data);
-            if (!$result) {
-                $this->error(__($validate->getError()), null, ['token' => $this->request->token()]);
-                return FALSE;
-            }
-            if ($this->auth->login($account, $password)) {
-                $synchtml = '';
-                ////////////////同步到Ucenter////////////////
-                if (defined('UC_STATUS') && UC_STATUS) {
-                    $uc = new \addons\ucenter\library\client\Client();
-                    $synchtml = $uc->uc_user_synlogin($this->auth->id);
-                }
-                $this->success(__('Logged in successful') . $synchtml, $url ? $url : url('user/index'));
-            } else {
-                $this->error($this->auth->getError(), null, ['token' => $this->request->token()]);
-            }
-        }
-        //判断来源
-        $referer = $this->request->server('HTTP_REFERER');
-        if (!$url && (strtolower(parse_url($referer, PHP_URL_HOST)) == strtolower($this->request->host()))
-            && !preg_match("/(user\/login|user\/register)/i", $referer)) {
-            $url = $referer;
-        }
-        $this->view->assign('url', $url);
-        $this->view->assign('title', __('Login'));
-        return $this->view->fetch();
-    }
-
-    /**
-     * 注销登录
-     */
-    function logout()
-    {
-        //注销本站
-        $this->auth->logout();
-        $synchtml = '';
-        ////////////////同步到Ucenter////////////////
-        if (defined('UC_STATUS') && UC_STATUS) {
-            $uc = new \addons\ucenter\library\client\Client();
-            $synchtml = $uc->uc_user_synlogout();
-        }
-        $this->success(__('Logout successful') . $synchtml, url('user/index'));
-    }
-
-    /**
-     * 个人信息
-     */
-    public function profile()
-    {
-        $this->view->assign('title', __('Profile'));
-        return $this->view->fetch();
-    }
-
-    /**
-     * 修改密码
-     */
-    public function changepwd()
-    {
-        if ($this->request->isPost()) {
-            $oldpassword = $this->request->post("oldpassword");
-            $newpassword = $this->request->post("newpassword");
-            $renewpassword = $this->request->post("renewpassword");
-            $token = $this->request->post('__token__');
-            $rule = [
-                'oldpassword'   => 'require|length:6,30',
-                'newpassword'   => 'require|length:6,30',
-                'renewpassword' => 'require|length:6,30|confirm:newpassword',
-                '__token__'     => 'token',
-            ];
-
-            $msg = [
-            ];
-            $data = [
-                'oldpassword'   => $oldpassword,
-                'newpassword'   => $newpassword,
-                'renewpassword' => $renewpassword,
-                '__token__'     => $token,
-            ];
-            $field = [
-                'oldpassword'   => __('Old password'),
-                'newpassword'   => __('New password'),
-                'renewpassword' => __('Renew password')
-            ];
-            $validate = new Validate($rule, $msg, $field);
-            $result = $validate->check($data);
-            if (!$result) {
-                $this->error(__($validate->getError()), null, ['token' => $this->request->token()]);
-                return FALSE;
-            }
-
-            $ret = $this->auth->changepwd($newpassword, $oldpassword);
-            if ($ret) {
-                $synchtml = '';
-                ////////////////同步到Ucenter////////////////
-                if (defined('UC_STATUS') && UC_STATUS) {
-                    $uc = new \addons\ucenter\library\client\Client();
-                    $synchtml = $uc->uc_user_synlogout();
-                }
-                $this->success(__('Reset password successful') . $synchtml, url('user/login'));
-            } else {
-                $this->error($this->auth->getError(), null, ['token' => $this->request->token()]);
-            }
-        }
-        $this->view->assign('title', __('Change password'));
-        return $this->view->fetch();
-    }
-
-}
+<?php
+
+namespace app\index\controller;
+
+use app\common\controller\Frontend;
+use think\Config;
+use think\Cookie;
+use think\Hook;
+use think\Session;
+use think\Validate;
+
+/**
+ * 会员中心
+ */
+class User extends Frontend
+{
+    protected $layout = 'default';
+    protected $noNeedLogin = ['login', 'register', 'third'];
+    protected $noNeedRight = ['*'];
+
+    public function _initialize()
+    {
+        parent::_initialize();
+        $auth = $this->auth;
+
+        if (!Config::get('fastadmin.usercenter')) {
+            $this->error(__('User center already closed'));
+        }
+
+        $ucenter = get_addon_info('ucenter');
+        if ($ucenter && $ucenter['state']) {
+            include ADDON_PATH . 'ucenter' . DS . 'uc.php';
+        }
+
+        //监听注册登录注销的事件
+        Hook::add('user_login_successed', function ($user) use ($auth) {
+            $expire = input('post.keeplogin') ? 30 * 86400 : 0;
+            Cookie::set('uid', $user->id, $expire);
+            Cookie::set('token', $auth->getToken(), $expire);
+        });
+        Hook::add('user_register_successed', function ($user) use ($auth) {
+            Cookie::set('uid', $user->id);
+            Cookie::set('token', $auth->getToken());
+        });
+        Hook::add('user_delete_successed', function ($user) use ($auth) {
+            Cookie::delete('uid');
+            Cookie::delete('token');
+        });
+        Hook::add('user_logout_successed', function ($user) use ($auth) {
+            Cookie::delete('uid');
+            Cookie::delete('token');
+        });
+    }
+
+    /**
+     * 空的请求
+     * @param $name
+     * @return mixed
+     */
+    public function _empty($name)
+    {
+        $data = Hook::listen("user_request_empty", $name);
+        foreach ($data as $index => $datum) {
+            $this->view->assign($datum);
+        }
+        return $this->view->fetch('user/' . $name);
+    }
+
+    /**
+     * 会员中心
+     */
+    public function index()
+    {
+        $this->view->assign('title', __('User center'));
+        return $this->view->fetch();
+    }
+
+    /**
+     * 注册会员
+     */
+    public function register()
+    {
+        $url = $this->request->request('url');
+        if ($this->auth->id) {
+            $this->success(__('You\'ve logged in, do not login again'), $url);
+        }
+        if ($this->request->isPost()) {
+            $username = $this->request->post('username');
+            $password = $this->request->post('password');
+            $email = $this->request->post('email');
+            $mobile = $this->request->post('mobile', '');
+            $captcha = $this->request->post('captcha');
+            $token = $this->request->post('__token__');
+            $rule = [
+                'username'  => 'require|length:3,30',
+                'password'  => 'require|length:6,30',
+                'email'     => 'require|email',
+                'mobile'    => 'regex:/^1\d{10}$/',
+                'captcha'   => 'require|captcha',
+                '__token__' => 'token',
+            ];
+
+            $msg = [
+                'username.require' => 'Username can not be empty',
+                'username.length'  => 'Username must be 3 to 30 characters',
+                'password.require' => 'Password can not be empty',
+                'password.length'  => 'Password must be 6 to 30 characters',
+                'captcha.require'  => 'Captcha can not be empty',
+                'captcha.captcha'  => 'Captcha is incorrect',
+                'email'            => 'Email is incorrect',
+                'mobile'           => 'Mobile is incorrect',
+            ];
+            $data = [
+                'username'  => $username,
+                'password'  => $password,
+                'email'     => $email,
+                'mobile'    => $mobile,
+                'captcha'   => $captcha,
+                '__token__' => $token,
+            ];
+            $validate = new Validate($rule, $msg);
+            $result = $validate->check($data);
+            if (!$result) {
+                $this->error(__($validate->getError()), null, ['token' => $this->request->token()]);
+            }
+            if ($this->auth->register($username, $password, $email, $mobile)) {
+                $synchtml = '';
+                ////////////////同步到Ucenter////////////////
+                if (defined('UC_STATUS') && UC_STATUS) {
+                    $uc = new \addons\ucenter\library\client\Client();
+                    $synchtml = $uc->uc_user_synregister($this->auth->id, $password);
+                }
+                $this->success(__('Sign up successful') . $synchtml, $url ? $url : url('user/index'));
+            } else {
+                $this->error($this->auth->getError(), null, ['token' => $this->request->token()]);
+            }
+        }
+        //判断来源
+        $referer = $this->request->server('HTTP_REFERER');
+        if (!$url && (strtolower(parse_url($referer, PHP_URL_HOST)) == strtolower($this->request->host()))
+            && !preg_match("/(user\/login|user\/register)/i", $referer)) {
+            $url = $referer;
+        }
+        $this->view->assign('url', $url);
+        $this->view->assign('title', __('Register'));
+        return $this->view->fetch();
+    }
+
+    /**
+     * 会员登录
+     */
+    public function login()
+    {
+        $url = $this->request->request('url');
+        if ($this->auth->id) {
+            $this->success(__('You\'ve logged in, do not login again'), $url);
+        }
+        if ($this->request->isPost()) {
+            $account = $this->request->post('account');
+            $password = $this->request->post('password');
+            $keeplogin = (int)$this->request->post('keeplogin');
+            $token = $this->request->post('__token__');
+            $rule = [
+                'account'   => 'require|length:3,50',
+                'password'  => 'require|length:6,30',
+                '__token__' => 'token',
+            ];
+
+            $msg = [
+                'account.require'  => 'Account can not be empty',
+                'account.length'   => 'Account must be 3 to 50 characters',
+                'password.require' => 'Password can not be empty',
+                'password.length'  => 'Password must be 6 to 30 characters',
+            ];
+            $data = [
+                'account'   => $account,
+                'password'  => $password,
+                '__token__' => $token,
+            ];
+            $validate = new Validate($rule, $msg);
+            $result = $validate->check($data);
+            if (!$result) {
+                $this->error(__($validate->getError()), null, ['token' => $this->request->token()]);
+                return false;
+            }
+            if ($this->auth->login($account, $password)) {
+                $synchtml = '';
+                ////////////////同步到Ucenter////////////////
+                if (defined('UC_STATUS') && UC_STATUS) {
+                    $uc = new \addons\ucenter\library\client\Client();
+                    $synchtml = $uc->uc_user_synlogin($this->auth->id);
+                }
+                $this->success(__('Logged in successful') . $synchtml, $url ? $url : url('user/index'));
+            } else {
+                $this->error($this->auth->getError(), null, ['token' => $this->request->token()]);
+            }
+        }
+        //判断来源
+        $referer = $this->request->server('HTTP_REFERER');
+        if (!$url && (strtolower(parse_url($referer, PHP_URL_HOST)) == strtolower($this->request->host()))
+            && !preg_match("/(user\/login|user\/register)/i", $referer)) {
+            $url = $referer;
+        }
+        $this->view->assign('url', $url);
+        $this->view->assign('title', __('Login'));
+        return $this->view->fetch();
+    }
+
+    /**
+     * 注销登录
+     */
+    public function logout()
+    {
+        //注销本站
+        $this->auth->logout();
+        $synchtml = '';
+        ////////////////同步到Ucenter////////////////
+        if (defined('UC_STATUS') && UC_STATUS) {
+            $uc = new \addons\ucenter\library\client\Client();
+            $synchtml = $uc->uc_user_synlogout();
+        }
+        $this->success(__('Logout successful') . $synchtml, url('user/index'));
+    }
+
+    /**
+     * 个人信息
+     */
+    public function profile()
+    {
+        $this->view->assign('title', __('Profile'));
+        return $this->view->fetch();
+    }
+
+    /**
+     * 修改密码
+     */
+    public function changepwd()
+    {
+        if ($this->request->isPost()) {
+            $oldpassword = $this->request->post("oldpassword");
+            $newpassword = $this->request->post("newpassword");
+            $renewpassword = $this->request->post("renewpassword");
+            $token = $this->request->post('__token__');
+            $rule = [
+                'oldpassword'   => 'require|length:6,30',
+                'newpassword'   => 'require|length:6,30',
+                'renewpassword' => 'require|length:6,30|confirm:newpassword',
+                '__token__'     => 'token',
+            ];
+
+            $msg = [
+            ];
+            $data = [
+                'oldpassword'   => $oldpassword,
+                'newpassword'   => $newpassword,
+                'renewpassword' => $renewpassword,
+                '__token__'     => $token,
+            ];
+            $field = [
+                'oldpassword'   => __('Old password'),
+                'newpassword'   => __('New password'),
+                'renewpassword' => __('Renew password')
+            ];
+            $validate = new Validate($rule, $msg, $field);
+            $result = $validate->check($data);
+            if (!$result) {
+                $this->error(__($validate->getError()), null, ['token' => $this->request->token()]);
+                return false;
+            }
+
+            $ret = $this->auth->changepwd($newpassword, $oldpassword);
+            if ($ret) {
+                $synchtml = '';
+                ////////////////同步到Ucenter////////////////
+                if (defined('UC_STATUS') && UC_STATUS) {
+                    $uc = new \addons\ucenter\library\client\Client();
+                    $synchtml = $uc->uc_user_synlogout();
+                }
+                $this->success(__('Reset password successful') . $synchtml, url('user/login'));
+            } else {
+                $this->error($this->auth->getError(), null, ['token' => $this->request->token()]);
+            }
+        }
+        $this->view->assign('title', __('Change password'));
+        return $this->view->fetch();
+    }
+}

+ 28 - 26
public/assets/js/backend/auth/group.js

@@ -45,17 +45,19 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'jstree'], function (
                 escape: false,
                 columns: [
                     [
-                        {field: 'state', checkbox: true, },
+                        {field: 'state', checkbox: true,},
                         {field: 'id', title: 'ID'},
                         {field: 'pid', title: __('Parent')},
                         {field: 'name', title: __('Name'), align: 'left'},
                         {field: 'status', title: __('Status'), formatter: Table.api.formatter.status},
-                        {field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: function (value, row, index) {
+                        {
+                            field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: function (value, row, index) {
                                 if (Config.admin.group_ids.indexOf(parseInt(row.id)) > -1) {
                                     return '';
                                 }
                                 return Table.api.formatter.operate.call(this, value, row, index);
-                            }}
+                            }
+                        }
                     ]
                 ],
                 pagination: false,
@@ -105,7 +107,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'jstree'], function (
                                     $("#treeview").jstree("destroy");
                                     Controller.api.rendertree(data);
                                 } else {
-                                    Backend.api.toastr.error(ret.data);
+                                    Backend.api.toastr.error(ret.msg);
                                 }
                             }
                         }, error: function (e) {
@@ -124,31 +126,31 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'jstree'], function (
             },
             rendertree: function (content) {
                 $("#treeview")
-                        .on('redraw.jstree', function (e) {
-                            $(".layer-footer").attr("domrefresh", Math.random());
-                        })
-                        .jstree({
-                            "themes": {"stripes": true},
-                            "checkbox": {
-                                "keep_selected_style": false,
+                    .on('redraw.jstree', function (e) {
+                        $(".layer-footer").attr("domrefresh", Math.random());
+                    })
+                    .jstree({
+                        "themes": {"stripes": true},
+                        "checkbox": {
+                            "keep_selected_style": false,
+                        },
+                        "types": {
+                            "root": {
+                                "icon": "fa fa-folder-open",
                             },
-                            "types": {
-                                "root": {
-                                    "icon": "fa fa-folder-open",
-                                },
-                                "menu": {
-                                    "icon": "fa fa-folder-open",
-                                },
-                                "file": {
-                                    "icon": "fa fa-file-o",
-                                }
+                            "menu": {
+                                "icon": "fa fa-folder-open",
                             },
-                            "plugins": ["checkbox", "types"],
-                            "core": {
-                                'check_callback': true,
-                                "data": content
+                            "file": {
+                                "icon": "fa fa-file-o",
                             }
-                        });
+                        },
+                        "plugins": ["checkbox", "types"],
+                        "core": {
+                            'check_callback': true,
+                            "data": content
+                        }
+                    });
             }
         }
     };

+ 3 - 3
public/assets/js/backend/category.js

@@ -15,7 +15,6 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
                 }
             });
 
-
             var table = $("#table");
             var tableOptions = {
                 url: $.fn.bootstrapTable.defaults.extend.index_url,
@@ -24,11 +23,12 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
                 sortName: 'weigh',
                 pagination: false,
                 commonSearch: false,
+                search: false,
                 columns: [
                     [
                         {checkbox: true},
                         {field: 'id', title: __('Id')},
-                        {field: 'type', title: __('Type')},
+                        {field: 'type', title: __('Type'), searchList: Config.searchList, formatter: Table.api.formatter.normal},
                         {field: 'name', title: __('Name'), align: 'left'},
                         {field: 'nickname', title: __('Nickname')},
                         {field: 'flag', title: __('Flag'), operate: false, formatter: Table.api.formatter.flag},
@@ -48,7 +48,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
             //绑定TAB事件
             $('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
                 // var options = table.bootstrapTable(tableOptions);
-                var typeStr = $(this).attr("href").replace('#','');
+                var typeStr = $(this).attr("href").replace('#', '');
                 var options = table.bootstrapTable('getOptions');
                 options.pageNumber = 1;
                 options.queryParams = function (params) {