瀏覽代碼

Merge branch 'develop' of gitee.com:karson/fastadmin into develop

Karson 3 年之前
父節點
當前提交
378aad4409

+ 199 - 200
application/admin/library/traits/Backend.php

@@ -9,12 +9,16 @@ use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
 use PhpOffice\PhpSpreadsheet\Reader\Xls;
 use PhpOffice\PhpSpreadsheet\Reader\Csv;
 use think\Db;
+use think\db\exception\BindParamException;
+use think\db\exception\DataNotFoundException;
+use think\db\exception\ModelNotFoundException;
+use think\exception\DbException;
 use think\exception\PDOException;
 use think\exception\ValidateException;
+use think\response\Json;
 
 trait Backend
 {
-
     /**
      * 排除前台提交过来的字段
      * @param $params
@@ -24,115 +28,114 @@ trait Backend
     {
         if (is_array($this->excludeFields)) {
             foreach ($this->excludeFields as $field) {
-                if (key_exists($field, $params)) {
+                if (array_key_exists($field, $params)) {
                     unset($params[$field]);
                 }
             }
-        } else {
-            if (key_exists($this->excludeFields, $params)) {
-                unset($params[$this->excludeFields]);
-            }
+        } else if (array_key_exists($this->excludeFields, $params)) {
+            unset($params[$this->excludeFields]);
         }
         return $params;
     }
 
-
     /**
      * 查看
+     *
+     * @return string|Json
+     * @throws \think\Exception
+     * @throws DbException
      */
     public function index()
     {
         //设置过滤方法
         $this->request->filter(['strip_tags', 'trim']);
-        if ($this->request->isAjax()) {
-            //如果发送的来源是Selectpage,则转发到Selectpage
-            if ($this->request->request('keyField')) {
-                return $this->selectpage();
-            }
-            list($where, $sort, $order, $offset, $limit) = $this->buildparams();
-
-            $list = $this->model
-                ->where($where)
-                ->order($sort, $order)
-                ->paginate($limit);
-
-            $result = array("total" => $list->total(), "rows" => $list->items());
-
-            return json($result);
+        if (false === $this->request->isAjax()) {
+            return $this->view->fetch();
+        }
+        //如果发送的来源是 Selectpage,则转发到 Selectpage
+        if ($this->request->request('keyField')) {
+            return $this->selectpage();
         }
-        return $this->view->fetch();
+        [$where, $sort, $order, $offset, $limit] = $this->buildparams();
+        $list = $this->model
+            ->where($where)
+            ->order($sort, $order)
+            ->paginate($limit);
+        $result = ['total' => $list->total(), 'rows' => $list->items()];
+        return json($result);
     }
 
     /**
      * 回收站
+     *
+     * @return string|Json
+     * @throws \think\Exception
      */
     public function recyclebin()
     {
         //设置过滤方法
         $this->request->filter(['strip_tags', 'trim']);
-        if ($this->request->isAjax()) {
-            list($where, $sort, $order, $offset, $limit) = $this->buildparams();
-
-            $list = $this->model
-                ->onlyTrashed()
-                ->where($where)
-                ->order($sort, $order)
-                ->paginate($limit);
-
-            $result = array("total" => $list->total(), "rows" => $list->items());
-
-            return json($result);
+        if (false === $this->request->isAjax()) {
+            return $this->view->fetch();
         }
-        return $this->view->fetch();
+        [$where, $sort, $order, $offset, $limit] = $this->buildparams();
+        $list = $this->model
+            ->onlyTrashed()
+            ->where($where)
+            ->order($sort, $order)
+            ->paginate($limit);
+        $result = ['total' => $list->total(), 'rows' => $list->items()];
+        return json($result);
     }
 
     /**
      * 添加
+     *
+     * @return string
+     * @throws \think\Exception
      */
     public function add()
     {
-        if ($this->request->isPost()) {
-            $params = $this->request->post("row/a");
-            if ($params) {
-                $params = $this->preExcludeFields($params);
+        if (false === $this->request->isPost()) {
+            return $this->view->fetch();
+        }
+        $params = $this->request->post('row/a');
+        if (empty($params)) {
+            $this->error(__('Parameter %s can not be empty', ''));
+        }
+        $params = $this->preExcludeFields($params);
 
-                if ($this->dataLimit && $this->dataLimitFieldAutoFill) {
-                    $params[$this->dataLimitField] = $this->auth->id;
-                }
-                $result = false;
-                Db::startTrans();
-                try {
-                    //是否采用模型验证
-                    if ($this->modelValidate) {
-                        $name = str_replace("\\model\\", "\\validate\\", get_class($this->model));
-                        $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : $name) : $this->modelValidate;
-                        $this->model->validateFailException(true)->validate($validate);
-                    }
-                    $result = $this->model->allowField(true)->save($params);
-                    Db::commit();
-                } catch (ValidateException $e) {
-                    Db::rollback();
-                    $this->error($e->getMessage());
-                } catch (PDOException $e) {
-                    Db::rollback();
-                    $this->error($e->getMessage());
-                } catch (Exception $e) {
-                    Db::rollback();
-                    $this->error($e->getMessage());
-                }
-                if ($result !== false) {
-                    $this->success();
-                } else {
-                    $this->error(__('No rows were inserted'));
-                }
+        if ($this->dataLimit && $this->dataLimitFieldAutoFill) {
+            $params[$this->dataLimitField] = $this->auth->id;
+        }
+        $result = false;
+        Db::startTrans();
+        try {
+            //是否采用模型验证
+            if ($this->modelValidate) {
+                $name = str_replace("\\model\\", "\\validate\\", get_class($this->model));
+                $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : $name) : $this->modelValidate;
+                $this->model->validateFailException()->validate($validate);
             }
-            $this->error(__('Parameter %s can not be empty', ''));
+            $result = $this->model->allowField(true)->save($params);
+            Db::commit();
+        } catch (ValidateException|PDOException|Exception $e) {
+            Db::rollback();
+            $this->error($e->getMessage());
         }
-        return $this->view->fetch();
+        if ($result === false) {
+            $this->error(__('No rows were inserted'));
+        }
+        $this->success();
     }
 
     /**
      * 编辑
+     *
+     * @param $ids
+     * @return string
+     * @throws DbException
+     * @throws \think\Exception
      */
     public function edit($ids = null)
     {
@@ -141,137 +144,132 @@ trait Backend
             $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 (is_array($adminIds) && !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);
-                $result = false;
-                Db::startTrans();
-                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->validateFailException(true)->validate($validate);
-                    }
-                    $result = $row->allowField(true)->save($params);
-                    Db::commit();
-                } catch (ValidateException $e) {
-                    Db::rollback();
-                    $this->error($e->getMessage());
-                } catch (PDOException $e) {
-                    Db::rollback();
-                    $this->error($e->getMessage());
-                } catch (Exception $e) {
-                    Db::rollback();
-                    $this->error($e->getMessage());
-                }
-                if ($result !== false) {
-                    $this->success();
-                } else {
-                    $this->error(__('No rows were updated'));
-                }
-            }
+        if (false === $this->request->isPost()) {
+            $this->view->assign('row', $row);
+            return $this->view->fetch();
+        }
+        $params = $this->request->post('row/a');
+        if (empty($params)) {
             $this->error(__('Parameter %s can not be empty', ''));
         }
-        $this->view->assign("row", $row);
-        return $this->view->fetch();
+        $params = $this->preExcludeFields($params);
+        $result = false;
+        Db::startTrans();
+        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->validateFailException()->validate($validate);
+            }
+            $result = $row->allowField(true)->save($params);
+            Db::commit();
+        } catch (ValidateException|PDOException|Exception $e) {
+            Db::rollback();
+            $this->error($e->getMessage());
+        }
+        if (false === $result) {
+            $this->error(__('No rows were updated'));
+        }
+        $this->success();
     }
 
     /**
      * 删除
+     *
+     * @param $ids
+     * @return void
+     * @throws DbException
+     * @throws DataNotFoundException
+     * @throws ModelNotFoundException
      */
-    public function del($ids = "")
+    public function del($ids = null)
     {
-        if (!$this->request->isPost()) {
+        if (false === $this->request->isPost()) {
             $this->error(__("Invalid parameters"));
         }
-        $ids = $ids ? $ids : $this->request->post("ids");
-        if ($ids) {
-            $pk = $this->model->getPk();
-            $adminIds = $this->getDataLimitAdminIds();
-            if (is_array($adminIds)) {
-                $this->model->where($this->dataLimitField, 'in', $adminIds);
-            }
-            $list = $this->model->where($pk, 'in', $ids)->select();
+        $ids = $ids ?: $this->request->post("ids");
+        if (empty($ids)) {
+            $this->error(__('Parameter %s can not be empty', 'ids'));
+        }
+        $pk = $this->model->getPk();
+        $adminIds = $this->getDataLimitAdminIds();
+        if (is_array($adminIds)) {
+            $this->model->where($this->dataLimitField, 'in', $adminIds);
+        }
+        $list = $this->model->where($pk, 'in', $ids)->select();
 
-            $count = 0;
-            Db::startTrans();
-            try {
-                foreach ($list as $k => $v) {
-                    $count += $v->delete();
-                }
-                Db::commit();
-            } catch (PDOException $e) {
-                Db::rollback();
-                $this->error($e->getMessage());
-            } catch (Exception $e) {
-                Db::rollback();
-                $this->error($e->getMessage());
-            }
-            if ($count) {
-                $this->success();
-            } else {
-                $this->error(__('No rows were deleted'));
+        $count = 0;
+        Db::startTrans();
+        try {
+            foreach ($list as $item) {
+                $count += $item->delete();
             }
+            Db::commit();
+        } catch (PDOException|Exception $e) {
+            Db::rollback();
+            $this->error($e->getMessage());
+        }
+        if ($count) {
+            $this->success();
         }
-        $this->error(__('Parameter %s can not be empty', 'ids'));
+        $this->error(__('No rows were deleted'));
     }
 
     /**
      * 真实删除
+     *
+     * @param $ids
+     * @return void
      */
-    public function destroy($ids = "")
+    public function destroy($ids = null)
     {
-        if (!$this->request->isPost()) {
+        if (false === $this->request->isPost()) {
             $this->error(__("Invalid parameters"));
         }
-        $ids = $ids ? $ids : $this->request->post("ids");
+        $ids = $ids ?: $this->request->post('ids');
+        if (empty($ids)) {
+            $this->error(__('Parameter %s can not be empty', 'ids'));
+        }
         $pk = $this->model->getPk();
         $adminIds = $this->getDataLimitAdminIds();
         if (is_array($adminIds)) {
             $this->model->where($this->dataLimitField, 'in', $adminIds);
         }
-        if ($ids) {
-            $this->model->where($pk, 'in', $ids);
-        }
+        $this->model->where($pk, 'in', $ids);
         $count = 0;
         Db::startTrans();
         try {
             $list = $this->model->onlyTrashed()->select();
-            foreach ($list as $k => $v) {
-                $count += $v->delete(true);
+            foreach ($list as $item) {
+                $count += $item->delete(true);
             }
             Db::commit();
-        } catch (PDOException $e) {
-            Db::rollback();
-            $this->error($e->getMessage());
-        } catch (Exception $e) {
+        } catch (PDOException|Exception $e) {
             Db::rollback();
             $this->error($e->getMessage());
         }
         if ($count) {
             $this->success();
-        } else {
-            $this->error(__('No rows were deleted'));
         }
-        $this->error(__('Parameter %s can not be empty', 'ids'));
+        $this->error(__('No rows were deleted'));
     }
 
     /**
      * 还原
+     *
+     * @param $ids
+     * @return void
      */
-    public function restore($ids = "")
+    public function restore($ids = null)
     {
-        if (!$this->request->isPost()) {
-            $this->error(__("Invalid parameters"));
+        if (false === $this->request->isPost()) {
+            $this->error(__('Invalid parameters'));
         }
-        $ids = $ids ? $ids : $this->request->post("ids");
+        $ids = $ids ?: $this->request->post('ids');
         $pk = $this->model->getPk();
         $adminIds = $this->getDataLimitAdminIds();
         if (is_array($adminIds)) {
@@ -284,14 +282,11 @@ trait Backend
         Db::startTrans();
         try {
             $list = $this->model->onlyTrashed()->select();
-            foreach ($list as $index => $item) {
+            foreach ($list as $item) {
                 $count += $item->restore();
             }
             Db::commit();
-        } catch (PDOException $e) {
-            Db::rollback();
-            $this->error($e->getMessage());
-        } catch (Exception $e) {
+        } catch (PDOException|Exception $e) {
             Db::rollback();
             $this->error($e->getMessage());
         }
@@ -303,52 +298,56 @@ trait Backend
 
     /**
      * 批量更新
+     *
+     * @param $ids
+     * @return void
      */
-    public function multi($ids = "")
+    public function multi($ids = null)
     {
-        if (!$this->request->isPost()) {
-            $this->error(__("Invalid parameters"));
+        if (false === $this->request->isPost()) {
+            $this->error(__('Invalid parameters'));
         }
-        $ids = $ids ? $ids : $this->request->post("ids");
-        if ($ids) {
-            if ($this->request->has('params')) {
-                parse_str($this->request->post("params"), $values);
-                $values = $this->auth->isSuperAdmin() ? $values : array_intersect_key($values, array_flip(is_array($this->multiFields) ? $this->multiFields : explode(',', $this->multiFields)));
-                if ($values) {
-                    $adminIds = $this->getDataLimitAdminIds();
-                    if (is_array($adminIds)) {
-                        $this->model->where($this->dataLimitField, 'in', $adminIds);
-                    }
-                    $count = 0;
-                    Db::startTrans();
-                    try {
-                        $list = $this->model->where($this->model->getPk(), 'in', $ids)->select();
-                        foreach ($list as $index => $item) {
-                            $count += $item->allowField(true)->isUpdate(true)->save($values);
-                        }
-                        Db::commit();
-                    } catch (PDOException $e) {
-                        Db::rollback();
-                        $this->error($e->getMessage());
-                    } catch (Exception $e) {
-                        Db::rollback();
-                        $this->error($e->getMessage());
-                    }
-                    if ($count) {
-                        $this->success();
-                    } else {
-                        $this->error(__('No rows were updated'));
-                    }
-                } else {
-                    $this->error(__('You have no permission'));
-                }
+        $ids = $ids ?: $this->request->post('ids');
+        if (empty($ids)) {
+            $this->error(__('Parameter %s can not be empty', 'ids'));
+        }
+
+        if (false === $this->request->has('params')) {
+            $this->error(__('No rows were updated'));
+        }
+        parse_str($this->request->post('params'), $values);
+        $values = $this->auth->isSuperAdmin() ? $values : array_intersect_key($values, array_flip(is_array($this->multiFields) ? $this->multiFields : explode(',', $this->multiFields)));
+        if (empty($values)) {
+            $this->error(__('You have no permission'));
+        }
+        $adminIds = $this->getDataLimitAdminIds();
+        if (is_array($adminIds)) {
+            $this->model->where($this->dataLimitField, 'in', $adminIds);
+        }
+        $count = 0;
+        Db::startTrans();
+        try {
+            $list = $this->model->where($this->model->getPk(), 'in', $ids)->select();
+            foreach ($list as $item) {
+                $count += $item->allowField(true)->isUpdate(true)->save($values);
             }
+            Db::commit();
+        } catch (PDOException|Exception $e) {
+            Db::rollback();
+            $this->error($e->getMessage());
+        }
+        if ($count) {
+            $this->success();
         }
-        $this->error(__('Parameter %s can not be empty', 'ids'));
+        $this->error(__('No rows were updated'));
     }
 
     /**
      * 导入
+     *
+     * @return void
+     * @throws PDOException
+     * @throws BindParamException
      */
     protected function import()
     {
@@ -368,12 +367,12 @@ trait Backend
         if ($ext === 'csv') {
             $file = fopen($filePath, 'r');
             $filePath = tempnam(sys_get_temp_dir(), 'import_csv');
-            $fp = fopen($filePath, "w");
+            $fp = fopen($filePath, 'w');
             $n = 0;
             while ($line = fgets($file)) {
                 $line = rtrim($line, "\n\r\0");
                 $encoding = mb_detect_encoding($line, ['utf-8', 'gbk', 'latin1', 'big5']);
-                if ($encoding != 'utf-8') {
+                if ($encoding !== 'utf-8') {
                     $line = mb_convert_encoding($line, 'utf-8', $encoding);
                 }
                 if ($n == 0 || preg_match('/^".*"$/', $line)) {

+ 1 - 1
application/api/lang/zh-cn/user.php

@@ -7,7 +7,7 @@ return [
     'Sign up successful'                    => '注册成功',
     'Username can not be empty'             => '用户名不能为空',
     'Username must be 3 to 30 characters'   => '用户名必须3-30个字符',
-    'Username must be 6 to 30 characters'   => '用户名必须3-30个字符',
+    'Username must be 6 to 30 characters'   => '用户名必须6-30个字符',
     'Password can not be empty'             => '密码不能为空',
     'Password must be 6 to 30 characters'   => '密码必须6-30个字符',
     'Mobile is incorrect'                   => '手机格式不正确',

+ 2 - 2
application/index/view/common/captcha.html

@@ -1,11 +1,11 @@
 <!--@formatter:off-->
 {if "[type]" == 'email'}
-    <input type="text" name="captcha" class="form-control" data-rule="required;length({$Think.config.captcha.length});integer[+];remote({:url('api/validate/check_ems_correct')}, event=[event], email:#email)" />
+    <input type="text" name="captcha" class="form-control" data-rule="required;length({$Think.config.captcha.length});digits;remote({:url('api/validate/check_ems_correct')}, event=[event], email:#email)" />
     <span class="input-group-btn" style="padding:0;border:none;">
         <a href="javascript:;" class="btn btn-info btn-captcha" data-url="{:url('api/ems/send')}" data-type="email" data-event="[event]">发送验证码</a>
     </span>
 {elseif "[type]" == 'mobile'/}
-    <input type="text" name="captcha" class="form-control" data-rule="required;length({$Think.config.captcha.length});integer[+];remote({:url('api/validate/check_sms_correct')}, event=[event], mobile:#mobile)" />
+    <input type="text" name="captcha" class="form-control" data-rule="required;length({$Think.config.captcha.length});digits;remote({:url('api/validate/check_sms_correct')}, event=[event], mobile:#mobile)" />
     <span class="input-group-btn" style="padding:0;border:none;">
         <a href="javascript:;" class="btn btn-info btn-captcha" data-url="{:url('api/sms/send')}" data-type="mobile" data-event="[event]">发送验证码</a>
     </span>

+ 1 - 1
application/index/view/user/login.html

@@ -69,7 +69,7 @@
                 <label for="captcha" class="control-label col-xs-12 col-sm-3">{:__('Captcha')}:</label>
                 <div class="col-xs-12 col-sm-8">
                     <div class="input-group">
-                        <input type="text" name="captcha" class="form-control" data-rule="required;length({$Think.config.captcha.length});integer[+];remote({:url('api/validate/check_ems_correct')}, event=resetpwd, email:#email)"/>
+                        <input type="text" name="captcha" class="form-control" data-rule="required;length({$Think.config.captcha.length});digits;remote({:url('api/validate/check_ems_correct')}, event=resetpwd, email:#email)"/>
                         <span class="input-group-btn" style="padding:0;border:none;">
                             <a href="javascript:;" class="btn btn-primary btn-captcha" data-url="{:url('api/ems/send')}" data-type="email" data-event="resetpwd">{:__('Send verification code')}</a>
                         </span>

+ 2 - 2
application/index/view/user/profile.html

@@ -121,7 +121,7 @@
                 <label class="control-label col-xs-12 col-sm-3">{:__('Captcha')}:</label>
                 <div class="col-xs-12 col-sm-8">
                     <div class="input-group">
-                        <input type="text" name="captcha" id="email-captcha" class="form-control" data-rule="required;length({$Think.config.captcha.length});integer[+];remote({:url('api/validate/check_ems_correct')}, event=changeemail, email:#email)" />
+                        <input type="text" name="captcha" id="email-captcha" class="form-control" data-rule="required;length({$Think.config.captcha.length});digits;remote({:url('api/validate/check_ems_correct')}, event=changeemail, email:#email)" />
                         <span class="input-group-btn" style="padding:0;border:none;">
                             <a href="javascript:;" class="btn btn-info btn-captcha" data-url="{:url('api/ems/send')}" data-type="email" data-event="changeemail">获取验证码</a>
                         </span>
@@ -155,7 +155,7 @@
                 <label for="mobile-captcha" class="control-label col-xs-12 col-sm-3">{:__('Captcha')}:</label>
                 <div class="col-xs-12 col-sm-8">
                     <div class="input-group">
-                        <input type="text" name="captcha" id="mobile-captcha" class="form-control" data-rule="required;length({$Think.config.captcha.length});integer[+];remote({:url('api/validate/check_sms_correct')}, event=changemobile, mobile:#mobile)" />
+                        <input type="text" name="captcha" id="mobile-captcha" class="form-control" data-rule="required;length({$Think.config.captcha.length});digits;remote({:url('api/validate/check_sms_correct')}, event=changemobile, mobile:#mobile)" />
                         <span class="input-group-btn" style="padding:0;border:none;">
                             <a href="javascript:;" class="btn btn-info btn-captcha" data-url="{:url('api/sms/send')}" data-type="mobile" data-event="changemobile">获取验证码</a>
                         </span>

+ 1 - 1
composer.json

@@ -38,7 +38,7 @@
     "repositories": [
         {
             "type": "git",
-            "url": "https://gitee.com/karson/framework"
+            "url": "https://gitee.com/fastadminnet/framework.git"
         }
     ]
 }

+ 39 - 39
extend/fast/Form.php

@@ -8,45 +8,45 @@ use ArrayAccess;
  * 表单元素生成
  * @class   Form
  * @package fast
- * @method string token() static 生成Token
- * @method string label(string $name, string $value = null, array $options = []) static label标签
- * @method string input($type, $name, string $value = null, array $options = []) static 按类型生成文本框
- * @method string text(string $name, string $value = null, array $options = []) static 普通文本框
- * @method string password(string $name, array $options = []) static 密码文本框
- * @method string hidden(string $name, string $value = null, array $options = []) static 隐藏文本框
- * @method string email(string $name, string $value = null, array $options = []) static Email文本框
- * @method string url(string $name, string $value = null, array $options = []) static URL文本框
- * @method string file(string $name, array $options = []) static 文件上传组件
- * @method string textarea(string $name, string $value = null, array $options = []) static 多行文本框
- * @method string editor(string $name, string $value = null, array $options = []) static 富文本编辑器
- * @method string select(string $name, array $list = [], string $selected = null, array $options = []) static 下拉列表组件
- * @method string selects(string $name, array $list = [], string $selected = null, array $options = []) static 下拉列表组件(多选)
- * @method string selectpicker(string $name, array $list = [], string $selected = null, array $options = []) static 下拉列表组件(友好)
- * @method string selectpickers(string $name, array $list = [], string $selected = null, array $options = []) static 下拉列表组件(友好)(多选)
- * @method string selectpage(string $name, string $value, string $url, string $field = null, string $primaryKey = null, array $options = []) static 动态下拉列表组件
- * @method string selectpages(string $name, string $value, string $url, string $field = null, string $primaryKey = null, array $options = []) static 动态下拉列表组件(多选)
- * @method string citypicker(string $name, string $value, array $options = []) static 城市选择组件
- * @method string switcher(string $name, string $value, array $options = []) static 切换组件
- * @method string datepicker(string $name, string $value, array $options = []) static 日期选择组件
- * @method string timepicker(string $name, string $value, array $options = []) static 时间选择组件
- * @method string datetimepicker(string $name, string $value, array $options = []) static 日期时间选择组件
- * @method string daterange(string $name, string $value, array $options = []) static 日期区间组件
- * @method string timerange(string $name, string $value, array $options = []) static 时间区间组件
- * @method string datetimerange(string $name, string $value, array $options = []) static 日期时间区间组件
- * @method string fieldlist(string $name, string $value, string $title = null, string $template = null, array $options = []) static 字段列表组件
- * @method string cxselect(string $url, array $names = [], array $values = [], array $options = []) static 联动组件
- * @method string selectRange(string $name, string $begin, string $end, string $selected = null, array $options = []) static 选择数字区间
- * @method string selectYear(string $name, string $begin, string $end, string $selected = null, array $options = []) static 选择年
- * @method string selectMonth(string $name, string $selected = null, array $options = [], string $format = '%m') static 选择月
- * @method string checkbox(string $name, string $value = '1', string $checked = null, array $options = []) static 单个复选框
- * @method string checkboxs(string $name, array $list = [], string $checked = null, array $options = []) static 一组复选框
- * @method string radio(string $name, string $value = null, string $checked = null, array $options = [])) static 单个单选框
- * @method string radios(string $name, array $list = [], string $checked = null, array $options = [])) static 一组单选框
- * @method string image(string $name = null, string $value, array $inputAttr = [], array $uploadAttr = [], array $chooseAttr = [], array $previewAttr = []) static 上传图片组件
- * @method string images(string $name = null, string $value, array $inputAttr = [], array $uploadAttr = [], array $chooseAttr = [], array $previewAttr = []) static 上传图片组件(多图))
- * @method string upload(string $name = null, string $value, array $inputAttr = [], array $uploadAttr = [], array $chooseAttr = [], array $previewAttr = []) static 上传文件组件
- * @method string uploads(string $name = null, string $value, array $inputAttr = [], array $uploadAttr = [], array $chooseAttr = [], array $previewAttr = []) static 上传文件组件(多文件))
- * @method string button(string $value = null, array $options = []) static 表单button
+ * @method static string token() 生成Token
+ * @method static string label(string $name, string $value = null, array $options = []) label标签
+ * @method static string input($type, $name, string $value = null, array $options = []) 按类型生成文本框
+ * @method static string text(string $name, string $value = null, array $options = []) 普通文本框
+ * @method static string password(string $name, array $options = []) 密码文本框
+ * @method static string hidden(string $name, string $value = null, array $options = []) 隐藏文本框
+ * @method static string email(string $name, string $value = null, array $options = []) Email文本框
+ * @method static string url(string $name, string $value = null, array $options = []) URL文本框
+ * @method static string file(string $name, array $options = []) 文件上传组件
+ * @method static string textarea(string $name, string $value = null, array $options = []) 多行文本框
+ * @method static string editor(string $name, string $value = null, array $options = []) 富文本编辑器
+ * @method static string select(string $name, array $list = [], string $selected = null, array $options = []) 下拉列表组件
+ * @method static string selects(string $name, array $list = [], string $selected = null, array $options = []) 下拉列表组件(多选)
+ * @method static string selectpicker(string $name, array $list = [], string $selected = null, array $options = []) 下拉列表组件(友好)
+ * @method static string selectpickers(string $name, array $list = [], string $selected = null, array $options = []) 下拉列表组件(友好)(多选)
+ * @method static string selectpage(string $name, string $value, string $url, string $field = null, string $primaryKey = null, array $options = []) 动态下拉列表组件
+ * @method static string selectpages(string $name, string $value, string $url, string $field = null, string $primaryKey = null, array $options = []) 动态下拉列表组件(多选)
+ * @method static string citypicker(string $name, string $value, array $options = []) 城市选择组件
+ * @method static string switcher(string $name, string $value, array $options = []) 切换组件
+ * @method static string datepicker(string $name, string $value, array $options = []) 日期选择组件
+ * @method static string timepicker(string $name, string $value, array $options = []) 时间选择组件
+ * @method static string datetimepicker(string $name, string $value, array $options = []) 日期时间选择组件
+ * @method static string daterange(string $name, string $value, array $options = []) 日期区间组件
+ * @method static string timerange(string $name, string $value, array $options = []) 时间区间组件
+ * @method static string datetimerange(string $name, string $value, array $options = []) 日期时间区间组件
+ * @method static string fieldlist(string $name, string $value, string $title = null, string $template = null, array $options = []) 字段列表组件
+ * @method static string cxselect(string $url, array $names = [], array $values = [], array $options = []) 联动组件
+ * @method static string selectRange(string $name, string $begin, string $end, string $selected = null, array $options = []) 选择数字区间
+ * @method static string selectYear(string $name, string $begin, string $end, string $selected = null, array $options = []) 选择年
+ * @method static string selectMonth(string $name, string $selected = null, array $options = [], string $format = '%m') 选择月
+ * @method static string checkbox(string $name, string $value = '1', string $checked = null, array $options = []) 单个复选框
+ * @method static string checkboxs(string $name, array $list = [], string $checked = null, array $options = []) 一组复选框
+ * @method static string radio(string $name, string $value = null, string $checked = null, array $options = [])) 单个单选框
+ * @method static string radios(string $name, array $list = [], string $checked = null, array $options = [])) 一组单选框
+ * @method static string image(string $name = null, string $value, array $inputAttr = [], array $uploadAttr = [], array $chooseAttr = [], array $previewAttr = []) 上传图片组件
+ * @method static string images(string $name = null, string $value, array $inputAttr = [], array $uploadAttr = [], array $chooseAttr = [], array $previewAttr = []) 上传图片组件(多图))
+ * @method static string upload(string $name = null, string $value, array $inputAttr = [], array $uploadAttr = [], array $chooseAttr = [], array $previewAttr = []) 上传文件组件
+ * @method static string uploads(string $name = null, string $value, array $inputAttr = [], array $uploadAttr = [], array $chooseAttr = [], array $previewAttr = []) 上传文件组件(多文件))
+ * @method static string button(string $value = null, array $options = []) 表单button
  */
 class Form
 {

+ 1 - 8
public/assets/js/backend/addon.js

@@ -68,13 +68,6 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
                 });
             });
 
-            //当表格分页变更时
-            table.on('page-change.bs.table', function (e, page, pagesize) {
-                if (!isNaN(pagesize)) {
-                    localStorage.setItem("pagesize-addon", pagesize);
-                }
-            });
-
             Template.helper("Moment", Moment);
             Template.helper("addons", Config['addons']);
 
@@ -90,6 +83,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
             // 初始化表格
             table.bootstrapTable({
                 url: $.fn.bootstrapTable.defaults.extend.index_url,
+                pageSize: 50,
                 queryParams: function (params) {
                     var userinfo = Controller.api.userinfo.get();
                     $.extend(params, {
@@ -181,7 +175,6 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
                 commonSearch: true,
                 searchFormVisible: true,
                 searchFormTemplate: 'searchformtpl',
-                pageSize: localStorage.getItem('pagesize-addon') || 50,
             });
 
             // 为表格绑定事件

File diff suppressed because it is too large
+ 626 - 626
public/assets/js/require-backend.min.js


+ 388 - 388
public/assets/js/require-frontend.min.js

@@ -11607,7 +11607,7 @@ define('table',['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstr
                 },
                 ignoreColumn: [0, 'operate'] //默认不导出第一列(checkbox)与操作(operate)列
             },
-            pageSize: localStorage.getItem("pagesize") || 10,
+            pageSize: localStorage.getItem('page-size') || 10,
             pageList: [10, 15, 20, 25, 50, 'All'],
             pagination: true,
             clickToSelect: true, //是否启用点击选中
@@ -11771,12 +11771,6 @@ define('table',['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstr
                 table.on('refresh.bs.table', function (e, settings, data) {
                     $(Table.config.refreshbtn, toolbar).find(".fa").addClass("fa-spin");
                 });
-                //当表格分页变更时
-                table.on('page-change.bs.table', function (e, page, pagesize) {
-                    if (!isNaN(pagesize)) {
-                        localStorage.setItem("pagesize", pagesize);
-                    }
-                });
                 //当执行搜索时
                 table.on('search.bs.table common-search.bs.table', function (e, settings, data) {
                     table.trigger("uncheckbox");
@@ -12121,6 +12115,12 @@ define('table',['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstr
                 Table.list[id] = table;
                 return table;
             },
+            // 设置全局分页的单页显示数
+            pageSize: function (pageSize) {
+                if (!isNaN(pageSize)) {
+                    localStorage.setItem('page-size', pageSize);
+                }
+            },
             // 批量操作请求
             multi: function (action, ids, table, element) {
                 var options = table.bootstrapTable('getOptions');
@@ -12563,387 +12563,387 @@ define('table',['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstr
     return Table;
 });
 
-// jQuery List DragSort v0.5.2
-// Website: http://dragsort.codeplex.com/
-// License: http://dragsort.codeplex.com/license
-
-(function($) {
-
-	$.fn.dragsort = function(options) {
-		if (options == "destroy") {
-			$(this.selector).trigger("dragsort-uninit");
-			return;
-		}
-
-		var opts = $.extend({}, $.fn.dragsort.defaults, options);
-		var lists = [];
-		var list = null, lastPos = null;
-
-		this.each(function(i, cont) {
-
-			//if list container is table, the browser automatically wraps rows in tbody if not specified so change list container to tbody so that children returns rows as user expected
-			if ($(cont).is("table") && $(cont).children().size() == 1 && $(cont).children().is("tbody"))
-				cont = $(cont).children().get(0);
-
-			var newList = {
-				draggedItem: null,
-				placeHolderItem: null,
-				pos: null,
-				offset: null,
-				offsetLimit: null,
-				scroll: null,
-				container: cont,
-
-				init: function() {
-					//set options to default values if not set
-					opts.tagName = opts.tagName == "" ? ($(this.container).children().size() == 0 ? "li" : $(this.container).children().get(0).tagName.toLowerCase()) : opts.tagName;
-					if (opts.itemSelector == "")
-						opts.itemSelector = opts.tagName;
-					if (opts.dragSelector == "")
-						opts.dragSelector = opts.tagName;
-					if (opts.placeHolderTemplate == "")
-						opts.placeHolderTemplate = "<" + opts.tagName + ">&nbsp;</" + opts.tagName + ">";
-
-					//listidx allows reference back to correct list variable instance
-					$(this.container).attr("data-listidx", i).mousedown(this.grabItem).bind("dragsort-uninit", this.uninit);
-					this.styleDragHandlers(true);
-				},
-
-				uninit: function() {
-					var list = lists[$(this).attr("data-listidx")];
-					$(list.container).unbind("mousedown", list.grabItem).unbind("dragsort-uninit");
-					list.styleDragHandlers(false);
-				},
-
-				getItems: function() {
-					return $(this.container).children(opts.itemSelector);
-				},
-
-				styleDragHandlers: function(cursor) {
-					this.getItems().map(function() { return $(this).is(opts.dragSelector) ? this : $(this).find(opts.dragSelector).get(); }).css("cursor", cursor ? "pointer" : "");
-				},
-
-				grabItem: function(e) {
-					var list = lists[$(this).attr("data-listidx")];
-					var item = $(e.target).closest("[data-listidx] > " + opts.tagName).get(0);
-					var insideMoveableItem = list.getItems().filter(function() { return this == item; }).size() > 0;
-
-					//if not left click or if clicked on excluded element (e.g. text box) or not a moveable list item return
-					if (e.which != 1 || $(e.target).is(opts.dragSelectorExclude) || $(e.target).closest(opts.dragSelectorExclude).size() > 0 || !insideMoveableItem)
-						return;
-
-					//prevents selection, stops issue on Fx where dragging hyperlink doesn't work and on IE where it triggers mousemove even though mouse hasn't moved,
-					//does also stop being able to click text boxes hence dragging on text boxes by default is disabled in dragSelectorExclude
-					//e.preventDefault();
-
-					//change cursor to move while dragging
-					var dragHandle = e.target;
-					while (!$(dragHandle).is(opts.dragSelector)) {
-						if (dragHandle == this) return;
-						dragHandle = dragHandle.parentNode;
-					}
-					$(dragHandle).attr("data-cursor", $(dragHandle).css("cursor"));
-					$(dragHandle).css("cursor", "move");
-
-					//on mousedown wait for movement of mouse before triggering dragsort script (dragStart) to allow clicking of hyperlinks to work
-					var listElem = this;
-					var trigger = function() {
-						list.dragStart.call(listElem, e);
-						$(list.container).unbind("mousemove", trigger);
-					};
-					$(list.container).mousemove(trigger).mouseup(function() { $(list.container).unbind("mousemove", trigger); $(dragHandle).css("cursor", $(dragHandle).attr("data-cursor")); });
-				},
-
-				dragStart: function(e) {
-					if (list != null && list.draggedItem != null)
-						list.dropItem();
-
-					list = lists[$(this).attr("data-listidx")];
-					list.draggedItem = $(e.target).closest("[data-listidx] > " + opts.tagName)
-
-					//record current position so on dragend we know if the dragged item changed position or not, not using getItems to allow dragsort to restore dragged item to original location in relation to fixed items
-					list.draggedItem.attr("data-origpos", $(this).attr("data-listidx") + "-" + $(list.container).children().index(list.draggedItem));
-
-					//calculate mouse offset relative to draggedItem
-					var mt = parseInt(list.draggedItem.css("marginTop"));
-					var ml = parseInt(list.draggedItem.css("marginLeft"));
-					list.offset = list.draggedItem.offset();
-					list.offset.top = e.pageY - list.offset.top + (isNaN(mt) ? 0 : mt) - 1;
-					list.offset.left = e.pageX - list.offset.left + (isNaN(ml) ? 0 : ml) - 1;
-
-					//calculate box the dragged item can't be dragged outside of
-					if (!opts.dragBetween) {
-						var containerHeight = $(list.container).outerHeight() == 0 ? Math.max(1, Math.round(0.5 + list.getItems().size() * list.draggedItem.outerWidth() / $(list.container).outerWidth())) * list.draggedItem.outerHeight() : $(list.container).outerHeight();
-						list.offsetLimit = $(list.container).offset();
-						list.offsetLimit.right = list.offsetLimit.left + $(list.container).outerWidth() - list.draggedItem.outerWidth();
-						list.offsetLimit.bottom = list.offsetLimit.top + containerHeight - list.draggedItem.outerHeight();
-					}
-
-					//create placeholder item
-					var h = list.draggedItem.height();
-					var w = list.draggedItem.width();
-					if (opts.tagName == "tr") {
-						list.draggedItem.children().each(function() { $(this).width($(this).width()); });
-						list.placeHolderItem = list.draggedItem.clone().attr("data-placeholder", true);
-						list.draggedItem.after(list.placeHolderItem);
-						//list.placeHolderItem.children().each(function() { $(this).css({ borderWidth:0, width: $(this).width() + 1, height: $(this).height() + 1 }).html("&nbsp;"); });
-						list.placeHolderItem.children().each(function() { $(this).html("&nbsp;"); });
-					} else {
-						list.draggedItem.after(opts.placeHolderTemplate);
-						list.placeHolderItem = list.draggedItem.next().css({ height: h, width: w }).attr("data-placeholder", true);
-					}
-
-					if (opts.tagName == "td") {
-						var listTable = list.draggedItem.closest("table").get(0);
-						$("<table id='" + listTable.id + "' style='border-width: 0px;' class='dragSortItem " + listTable.className + "'><tr></tr></table>").appendTo("body").children().append(list.draggedItem);
-					}
-
-					//style draggedItem while dragging
-					var orig = list.draggedItem.attr("style");
-					list.draggedItem.attr("data-origstyle", orig ? orig : "");
-					list.draggedItem.css({ position: "absolute", opacity: 0.8, "z-index": 999, height: h, width: w });
-
-					//auto-scroll setup
-					list.scroll = { moveX: 0, moveY: 0, maxX: $(document).width() - $(window).width(), maxY: $(document).height() - $(window).height() };
-					list.scroll.scrollY = window.setInterval(function() {
-						if (opts.scrollContainer != window) {
-							$(opts.scrollContainer).scrollTop($(opts.scrollContainer).scrollTop() + list.scroll.moveY);
-							return;
-						}
-						var t = $(opts.scrollContainer).scrollTop();
-						if (list.scroll.moveY > 0 && t < list.scroll.maxY || list.scroll.moveY < 0 && t > 0) {
-							$(opts.scrollContainer).scrollTop(t + list.scroll.moveY);
-							list.draggedItem.css("top", list.draggedItem.offset().top + list.scroll.moveY + 1);
-						}
-					}, 10);
-					list.scroll.scrollX = window.setInterval(function() {
-						if (opts.scrollContainer != window) {
-							$(opts.scrollContainer).scrollLeft($(opts.scrollContainer).scrollLeft() + list.scroll.moveX);
-							return;
-						}
-						var l = $(opts.scrollContainer).scrollLeft();
-						if (list.scroll.moveX > 0 && l < list.scroll.maxX || list.scroll.moveX < 0 && l > 0) {
-							$(opts.scrollContainer).scrollLeft(l + list.scroll.moveX);
-							list.draggedItem.css("left", list.draggedItem.offset().left + list.scroll.moveX + 1);
-						}
-					}, 10);
-
-					//misc
-					$(lists).each(function(i, l) { l.createDropTargets(); l.buildPositionTable(); });
-					list.setPos(e.pageX, e.pageY);
-					$(document).bind("mousemove", list.swapItems);
-					$(document).bind("mouseup", list.dropItem);
-					if (opts.scrollContainer != window)
-						$(window).bind("wheel", list.wheel);
-				},
-
-				//set position of draggedItem
-				setPos: function(x, y) { 
-					//remove mouse offset so mouse cursor remains in same place on draggedItem instead of top left corner
-					var top = y - this.offset.top;
-					var left = x - this.offset.left;
-
-					//limit top, left to within box draggedItem can't be dragged outside of
-					if (!opts.dragBetween) {
-						top = Math.min(this.offsetLimit.bottom, Math.max(top, this.offsetLimit.top));
-						left = Math.min(this.offsetLimit.right, Math.max(left, this.offsetLimit.left));
-					}
-
-					//adjust top & left calculations to parent offset
-					var parent = this.draggedItem.offsetParent().not("body").offset(); //offsetParent returns body even when it's static, if not static offset is only factoring margin
-					if (parent != null) {
-						top -= parent.top;
-						left -= parent.left;
-					}
-
-					//set x or y auto-scroll amount
-					if (opts.scrollContainer == window) {
-						y -= $(window).scrollTop();
-						x -= $(window).scrollLeft();
-						y = Math.max(0, y - $(window).height() + 5) + Math.min(0, y - 5);
-						x = Math.max(0, x - $(window).width() + 5) + Math.min(0, x - 5);
-					} else {
-						var cont = $(opts.scrollContainer);
-						var offset = cont.offset();
-						y = Math.max(0, y - cont.height() - offset.top) + Math.min(0, y - offset.top);
-						x = Math.max(0, x - cont.width() - offset.left) + Math.min(0, x - offset.left);
-					}
-					
-					list.scroll.moveX = x == 0 ? 0 : x * opts.scrollSpeed / Math.abs(x);
-					list.scroll.moveY = y == 0 ? 0 : y * opts.scrollSpeed / Math.abs(y);
-
-					//move draggedItem to new mouse cursor location
-					this.draggedItem.css({ top: top, left: left });
-				},
-
-				//if scroll container is a div allow mouse wheel to scroll div instead of window when mouse is hovering over
-				wheel: function(e) {
-					if (list && opts.scrollContainer != window) {
-						var cont = $(opts.scrollContainer);
-						var offset = cont.offset();
-						e = e.originalEvent;
-						if (e.clientX > offset.left && e.clientX < offset.left + cont.width() && e.clientY > offset.top && e.clientY < offset.top + cont.height()) {
-							var deltaY = (e.deltaMode == 0 ? 1 : 10) * e.deltaY;
-							cont.scrollTop(cont.scrollTop() + deltaY);
-							e.preventDefault();
-						}
-					}
-				},
-
-				//build a table recording all the positions of the moveable list items
-				buildPositionTable: function() {
-					var pos = [];
-					this.getItems().not([list.draggedItem[0], list.placeHolderItem[0]]).each(function(i) {
-						var loc = $(this).offset();
-						loc.right = loc.left + $(this).outerWidth();
-						loc.bottom = loc.top + $(this).outerHeight();
-						loc.elm = this;
-						pos[i] = loc;
-					});
-					this.pos = pos;
-				},
-
-				dropItem: function() {
-					if (list.draggedItem == null)
-						return;
-
-					//list.draggedItem.attr("style", "") doesn't work on IE8 and jQuery 1.5 or lower
-					//list.draggedItem.removeAttr("style") doesn't work on chrome and jQuery 1.6 (works jQuery 1.5 or lower)
-					var orig = list.draggedItem.attr("data-origstyle");
-					list.draggedItem.attr("style", orig);
-					if (orig == "")
-						list.draggedItem.removeAttr("style");
-					list.draggedItem.removeAttr("data-origstyle");
-
-					list.styleDragHandlers(true);
-
-					list.placeHolderItem.before(list.draggedItem);
-					list.placeHolderItem.remove();
-
-					$("[data-droptarget], .dragSortItem").remove();
-
-					window.clearInterval(list.scroll.scrollY);
-					window.clearInterval(list.scroll.scrollX);
-
-					//if position changed call dragEnd
-					if (list.draggedItem.attr("data-origpos") != $(lists).index(list) + "-" + $(list.container).children().index(list.draggedItem))
-						if (opts.dragEnd.apply(list.draggedItem) == false) { //if dragEnd returns false revert order
-							var pos = list.draggedItem.attr("data-origpos").split('-');
-							var nextItem = $(lists[pos[0]].container).children().not(list.draggedItem).eq(pos[1]);
-							if (nextItem.size() > 0)
-								nextItem.before(list.draggedItem);
-							else if (pos[1] == 0) //was the only item in list
-								$(lists[pos[0]].container).prepend(list.draggedItem);
-							else //was the last item in list
-								$(lists[pos[0]].container).append(list.draggedItem);
-						}
-					list.draggedItem.removeAttr("data-origpos");
-
-					list.draggedItem = null;
-					$(document).unbind("mousemove", list.swapItems);
-					$(document).unbind("mouseup", list.dropItem);
-					if (opts.scrollContainer != window)
-						$(window).unbind("wheel", list.wheel);
-					return false;
-				},
-
-				//swap the draggedItem (represented visually by placeholder) with the list item the it has been dragged on top of
-				swapItems: function(e) {
-					if (list.draggedItem == null)
-						return false;
-
-					//move draggedItem to mouse location
-					list.setPos(e.pageX, e.pageY);
-
-					//retrieve list and item position mouse cursor is over
-					var ei = list.findPos(e.pageX, e.pageY);
-					var nlist = list;
-					for (var i = 0; ei == -1 && opts.dragBetween && i < lists.length; i++) {
-						ei = lists[i].findPos(e.pageX, e.pageY);
-						nlist = lists[i];
-					}
-
-					//if not over another moveable list item return
-					if (ei == -1)
-						return false;
-
-					//save fixed items locations
-					var children = function() { return $(nlist.container).children().not(nlist.draggedItem); };
-					var fixed = children().not(opts.itemSelector).each(function(i) { this.idx = children().index(this); });
-
-					//if moving draggedItem up or left place placeHolder before list item the dragged item is hovering over otherwise place it after
-					if (lastPos == null || lastPos.top > list.draggedItem.offset().top || lastPos.left > list.draggedItem.offset().left)
-						$(nlist.pos[ei].elm).before(list.placeHolderItem);
-					else
-						$(nlist.pos[ei].elm).after(list.placeHolderItem);
-
-					//restore fixed items location
-					fixed.each(function() {
-						var elm = children().eq(this.idx).get(0);
-						if (this != elm && children().index(this) < this.idx)
-							$(this).insertAfter(elm);
-						else if (this != elm)
-							$(this).insertBefore(elm);
-					});
-
-					//misc
-					$(lists).each(function(i, l) { l.createDropTargets(); l.buildPositionTable(); });
-					lastPos = list.draggedItem.offset();
-					return false;
-				},
-
-				//returns the index of the list item the mouse is over
-				findPos: function(x, y) {
-					for (var i = 0; i < this.pos.length; i++) {
-						if (this.pos[i].left < x && this.pos[i].right > x && this.pos[i].top < y && this.pos[i].bottom > y)
-							return i;
-					}
-					return -1;
-				},
-
-				//create drop targets which are placeholders at the end of other lists to allow dragging straight to the last position
-				createDropTargets: function() {
-					if (!opts.dragBetween)
-						return;
-
-					$(lists).each(function() {
-						var ph = $(this.container).find("[data-placeholder]");
-						var dt = $(this.container).find("[data-droptarget]");
-						if (ph.size() > 0 && dt.size() > 0)
-							dt.remove();
-						else if (ph.size() == 0 && dt.size() == 0) {
-							if (opts.tagName == "td")
-								$(opts.placeHolderTemplate).attr("data-droptarget", true).appendTo(this.container);
-							else
-								//list.placeHolderItem.clone().removeAttr("data-placeholder") crashes in IE7 and jquery 1.5.1 (doesn't in jquery 1.4.2 or IE8)
-								$(this.container).append(list.placeHolderItem.removeAttr("data-placeholder").clone().attr("data-droptarget", true));
-							
-							list.placeHolderItem.attr("data-placeholder", true);
-						}
-					});
-				}
-			};
-
-			newList.init();
-			lists.push(newList);
-		});
-
-		return this;
-	};
-
-	$.fn.dragsort.defaults = {
-                tagName:"",
-		itemSelector: "",
-		dragSelector: "",
-		dragSelectorExclude: "input, textarea",
-		dragEnd: function() { },
-		dragBetween: false,
-		placeHolderTemplate: "",
-		scrollContainer: window,
-		scrollSpeed: 5
-	};
-
-})(jQuery);
+// jQuery List DragSort v0.5.2
+// Website: http://dragsort.codeplex.com/
+// License: http://dragsort.codeplex.com/license
+
+(function($) {
+
+	$.fn.dragsort = function(options) {
+		if (options == "destroy") {
+			$(this.selector).trigger("dragsort-uninit");
+			return;
+		}
+
+		var opts = $.extend({}, $.fn.dragsort.defaults, options);
+		var lists = [];
+		var list = null, lastPos = null;
+
+		this.each(function(i, cont) {
+
+			//if list container is table, the browser automatically wraps rows in tbody if not specified so change list container to tbody so that children returns rows as user expected
+			if ($(cont).is("table") && $(cont).children().size() == 1 && $(cont).children().is("tbody"))
+				cont = $(cont).children().get(0);
+
+			var newList = {
+				draggedItem: null,
+				placeHolderItem: null,
+				pos: null,
+				offset: null,
+				offsetLimit: null,
+				scroll: null,
+				container: cont,
+
+				init: function() {
+					//set options to default values if not set
+					opts.tagName = opts.tagName == "" ? ($(this.container).children().size() == 0 ? "li" : $(this.container).children().get(0).tagName.toLowerCase()) : opts.tagName;
+					if (opts.itemSelector == "")
+						opts.itemSelector = opts.tagName;
+					if (opts.dragSelector == "")
+						opts.dragSelector = opts.tagName;
+					if (opts.placeHolderTemplate == "")
+						opts.placeHolderTemplate = "<" + opts.tagName + ">&nbsp;</" + opts.tagName + ">";
+
+					//listidx allows reference back to correct list variable instance
+					$(this.container).attr("data-listidx", i).mousedown(this.grabItem).bind("dragsort-uninit", this.uninit);
+					this.styleDragHandlers(true);
+				},
+
+				uninit: function() {
+					var list = lists[$(this).attr("data-listidx")];
+					$(list.container).unbind("mousedown", list.grabItem).unbind("dragsort-uninit");
+					list.styleDragHandlers(false);
+				},
+
+				getItems: function() {
+					return $(this.container).children(opts.itemSelector);
+				},
+
+				styleDragHandlers: function(cursor) {
+					this.getItems().map(function() { return $(this).is(opts.dragSelector) ? this : $(this).find(opts.dragSelector).get(); }).css("cursor", cursor ? "pointer" : "");
+				},
+
+				grabItem: function(e) {
+					var list = lists[$(this).attr("data-listidx")];
+					var item = $(e.target).closest("[data-listidx] > " + opts.tagName).get(0);
+					var insideMoveableItem = list.getItems().filter(function() { return this == item; }).size() > 0;
+
+					//if not left click or if clicked on excluded element (e.g. text box) or not a moveable list item return
+					if (e.which != 1 || $(e.target).is(opts.dragSelectorExclude) || $(e.target).closest(opts.dragSelectorExclude).size() > 0 || !insideMoveableItem)
+						return;
+
+					//prevents selection, stops issue on Fx where dragging hyperlink doesn't work and on IE where it triggers mousemove even though mouse hasn't moved,
+					//does also stop being able to click text boxes hence dragging on text boxes by default is disabled in dragSelectorExclude
+					//e.preventDefault();
+
+					//change cursor to move while dragging
+					var dragHandle = e.target;
+					while (!$(dragHandle).is(opts.dragSelector)) {
+						if (dragHandle == this) return;
+						dragHandle = dragHandle.parentNode;
+					}
+					$(dragHandle).attr("data-cursor", $(dragHandle).css("cursor"));
+					$(dragHandle).css("cursor", "move");
+
+					//on mousedown wait for movement of mouse before triggering dragsort script (dragStart) to allow clicking of hyperlinks to work
+					var listElem = this;
+					var trigger = function() {
+						list.dragStart.call(listElem, e);
+						$(list.container).unbind("mousemove", trigger);
+					};
+					$(list.container).mousemove(trigger).mouseup(function() { $(list.container).unbind("mousemove", trigger); $(dragHandle).css("cursor", $(dragHandle).attr("data-cursor")); });
+				},
+
+				dragStart: function(e) {
+					if (list != null && list.draggedItem != null)
+						list.dropItem();
+
+					list = lists[$(this).attr("data-listidx")];
+					list.draggedItem = $(e.target).closest("[data-listidx] > " + opts.tagName)
+
+					//record current position so on dragend we know if the dragged item changed position or not, not using getItems to allow dragsort to restore dragged item to original location in relation to fixed items
+					list.draggedItem.attr("data-origpos", $(this).attr("data-listidx") + "-" + $(list.container).children().index(list.draggedItem));
+
+					//calculate mouse offset relative to draggedItem
+					var mt = parseInt(list.draggedItem.css("marginTop"));
+					var ml = parseInt(list.draggedItem.css("marginLeft"));
+					list.offset = list.draggedItem.offset();
+					list.offset.top = e.pageY - list.offset.top + (isNaN(mt) ? 0 : mt) - 1;
+					list.offset.left = e.pageX - list.offset.left + (isNaN(ml) ? 0 : ml) - 1;
+
+					//calculate box the dragged item can't be dragged outside of
+					if (!opts.dragBetween) {
+						var containerHeight = $(list.container).outerHeight() == 0 ? Math.max(1, Math.round(0.5 + list.getItems().size() * list.draggedItem.outerWidth() / $(list.container).outerWidth())) * list.draggedItem.outerHeight() : $(list.container).outerHeight();
+						list.offsetLimit = $(list.container).offset();
+						list.offsetLimit.right = list.offsetLimit.left + $(list.container).outerWidth() - list.draggedItem.outerWidth();
+						list.offsetLimit.bottom = list.offsetLimit.top + containerHeight - list.draggedItem.outerHeight();
+					}
+
+					//create placeholder item
+					var h = list.draggedItem.height();
+					var w = list.draggedItem.width();
+					if (opts.tagName == "tr") {
+						list.draggedItem.children().each(function() { $(this).width($(this).width()); });
+						list.placeHolderItem = list.draggedItem.clone().attr("data-placeholder", true);
+						list.draggedItem.after(list.placeHolderItem);
+						//list.placeHolderItem.children().each(function() { $(this).css({ borderWidth:0, width: $(this).width() + 1, height: $(this).height() + 1 }).html("&nbsp;"); });
+						list.placeHolderItem.children().each(function() { $(this).html("&nbsp;"); });
+					} else {
+						list.draggedItem.after(opts.placeHolderTemplate);
+						list.placeHolderItem = list.draggedItem.next().css({ height: h, width: w }).attr("data-placeholder", true);
+					}
+
+					if (opts.tagName == "td") {
+						var listTable = list.draggedItem.closest("table").get(0);
+						$("<table id='" + listTable.id + "' style='border-width: 0px;' class='dragSortItem " + listTable.className + "'><tr></tr></table>").appendTo("body").children().append(list.draggedItem);
+					}
+
+					//style draggedItem while dragging
+					var orig = list.draggedItem.attr("style");
+					list.draggedItem.attr("data-origstyle", orig ? orig : "");
+					list.draggedItem.css({ position: "absolute", opacity: 0.8, "z-index": 999, height: h, width: w });
+
+					//auto-scroll setup
+					list.scroll = { moveX: 0, moveY: 0, maxX: $(document).width() - $(window).width(), maxY: $(document).height() - $(window).height() };
+					list.scroll.scrollY = window.setInterval(function() {
+						if (opts.scrollContainer != window) {
+							$(opts.scrollContainer).scrollTop($(opts.scrollContainer).scrollTop() + list.scroll.moveY);
+							return;
+						}
+						var t = $(opts.scrollContainer).scrollTop();
+						if (list.scroll.moveY > 0 && t < list.scroll.maxY || list.scroll.moveY < 0 && t > 0) {
+							$(opts.scrollContainer).scrollTop(t + list.scroll.moveY);
+							list.draggedItem.css("top", list.draggedItem.offset().top + list.scroll.moveY + 1);
+						}
+					}, 10);
+					list.scroll.scrollX = window.setInterval(function() {
+						if (opts.scrollContainer != window) {
+							$(opts.scrollContainer).scrollLeft($(opts.scrollContainer).scrollLeft() + list.scroll.moveX);
+							return;
+						}
+						var l = $(opts.scrollContainer).scrollLeft();
+						if (list.scroll.moveX > 0 && l < list.scroll.maxX || list.scroll.moveX < 0 && l > 0) {
+							$(opts.scrollContainer).scrollLeft(l + list.scroll.moveX);
+							list.draggedItem.css("left", list.draggedItem.offset().left + list.scroll.moveX + 1);
+						}
+					}, 10);
+
+					//misc
+					$(lists).each(function(i, l) { l.createDropTargets(); l.buildPositionTable(); });
+					list.setPos(e.pageX, e.pageY);
+					$(document).bind("mousemove", list.swapItems);
+					$(document).bind("mouseup", list.dropItem);
+					if (opts.scrollContainer != window)
+						$(window).bind("wheel", list.wheel);
+				},
+
+				//set position of draggedItem
+				setPos: function(x, y) { 
+					//remove mouse offset so mouse cursor remains in same place on draggedItem instead of top left corner
+					var top = y - this.offset.top;
+					var left = x - this.offset.left;
+
+					//limit top, left to within box draggedItem can't be dragged outside of
+					if (!opts.dragBetween) {
+						top = Math.min(this.offsetLimit.bottom, Math.max(top, this.offsetLimit.top));
+						left = Math.min(this.offsetLimit.right, Math.max(left, this.offsetLimit.left));
+					}
+
+					//adjust top & left calculations to parent offset
+					var parent = this.draggedItem.offsetParent().not("body").offset(); //offsetParent returns body even when it's static, if not static offset is only factoring margin
+					if (parent != null) {
+						top -= parent.top;
+						left -= parent.left;
+					}
+
+					//set x or y auto-scroll amount
+					if (opts.scrollContainer == window) {
+						y -= $(window).scrollTop();
+						x -= $(window).scrollLeft();
+						y = Math.max(0, y - $(window).height() + 5) + Math.min(0, y - 5);
+						x = Math.max(0, x - $(window).width() + 5) + Math.min(0, x - 5);
+					} else {
+						var cont = $(opts.scrollContainer);
+						var offset = cont.offset();
+						y = Math.max(0, y - cont.height() - offset.top) + Math.min(0, y - offset.top);
+						x = Math.max(0, x - cont.width() - offset.left) + Math.min(0, x - offset.left);
+					}
+					
+					list.scroll.moveX = x == 0 ? 0 : x * opts.scrollSpeed / Math.abs(x);
+					list.scroll.moveY = y == 0 ? 0 : y * opts.scrollSpeed / Math.abs(y);
+
+					//move draggedItem to new mouse cursor location
+					this.draggedItem.css({ top: top, left: left });
+				},
+
+				//if scroll container is a div allow mouse wheel to scroll div instead of window when mouse is hovering over
+				wheel: function(e) {
+					if (list && opts.scrollContainer != window) {
+						var cont = $(opts.scrollContainer);
+						var offset = cont.offset();
+						e = e.originalEvent;
+						if (e.clientX > offset.left && e.clientX < offset.left + cont.width() && e.clientY > offset.top && e.clientY < offset.top + cont.height()) {
+							var deltaY = (e.deltaMode == 0 ? 1 : 10) * e.deltaY;
+							cont.scrollTop(cont.scrollTop() + deltaY);
+							e.preventDefault();
+						}
+					}
+				},
+
+				//build a table recording all the positions of the moveable list items
+				buildPositionTable: function() {
+					var pos = [];
+					this.getItems().not([list.draggedItem[0], list.placeHolderItem[0]]).each(function(i) {
+						var loc = $(this).offset();
+						loc.right = loc.left + $(this).outerWidth();
+						loc.bottom = loc.top + $(this).outerHeight();
+						loc.elm = this;
+						pos[i] = loc;
+					});
+					this.pos = pos;
+				},
+
+				dropItem: function() {
+					if (list.draggedItem == null)
+						return;
+
+					//list.draggedItem.attr("style", "") doesn't work on IE8 and jQuery 1.5 or lower
+					//list.draggedItem.removeAttr("style") doesn't work on chrome and jQuery 1.6 (works jQuery 1.5 or lower)
+					var orig = list.draggedItem.attr("data-origstyle");
+					list.draggedItem.attr("style", orig);
+					if (orig == "")
+						list.draggedItem.removeAttr("style");
+					list.draggedItem.removeAttr("data-origstyle");
+
+					list.styleDragHandlers(true);
+
+					list.placeHolderItem.before(list.draggedItem);
+					list.placeHolderItem.remove();
+
+					$("[data-droptarget], .dragSortItem").remove();
+
+					window.clearInterval(list.scroll.scrollY);
+					window.clearInterval(list.scroll.scrollX);
+
+					//if position changed call dragEnd
+					if (list.draggedItem.attr("data-origpos") != $(lists).index(list) + "-" + $(list.container).children().index(list.draggedItem))
+						if (opts.dragEnd.apply(list.draggedItem) == false) { //if dragEnd returns false revert order
+							var pos = list.draggedItem.attr("data-origpos").split('-');
+							var nextItem = $(lists[pos[0]].container).children().not(list.draggedItem).eq(pos[1]);
+							if (nextItem.size() > 0)
+								nextItem.before(list.draggedItem);
+							else if (pos[1] == 0) //was the only item in list
+								$(lists[pos[0]].container).prepend(list.draggedItem);
+							else //was the last item in list
+								$(lists[pos[0]].container).append(list.draggedItem);
+						}
+					list.draggedItem.removeAttr("data-origpos");
+
+					list.draggedItem = null;
+					$(document).unbind("mousemove", list.swapItems);
+					$(document).unbind("mouseup", list.dropItem);
+					if (opts.scrollContainer != window)
+						$(window).unbind("wheel", list.wheel);
+					return false;
+				},
+
+				//swap the draggedItem (represented visually by placeholder) with the list item the it has been dragged on top of
+				swapItems: function(e) {
+					if (list.draggedItem == null)
+						return false;
+
+					//move draggedItem to mouse location
+					list.setPos(e.pageX, e.pageY);
+
+					//retrieve list and item position mouse cursor is over
+					var ei = list.findPos(e.pageX, e.pageY);
+					var nlist = list;
+					for (var i = 0; ei == -1 && opts.dragBetween && i < lists.length; i++) {
+						ei = lists[i].findPos(e.pageX, e.pageY);
+						nlist = lists[i];
+					}
+
+					//if not over another moveable list item return
+					if (ei == -1)
+						return false;
+
+					//save fixed items locations
+					var children = function() { return $(nlist.container).children().not(nlist.draggedItem); };
+					var fixed = children().not(opts.itemSelector).each(function(i) { this.idx = children().index(this); });
+
+					//if moving draggedItem up or left place placeHolder before list item the dragged item is hovering over otherwise place it after
+					if (lastPos == null || lastPos.top > list.draggedItem.offset().top || lastPos.left > list.draggedItem.offset().left)
+						$(nlist.pos[ei].elm).before(list.placeHolderItem);
+					else
+						$(nlist.pos[ei].elm).after(list.placeHolderItem);
+
+					//restore fixed items location
+					fixed.each(function() {
+						var elm = children().eq(this.idx).get(0);
+						if (this != elm && children().index(this) < this.idx)
+							$(this).insertAfter(elm);
+						else if (this != elm)
+							$(this).insertBefore(elm);
+					});
+
+					//misc
+					$(lists).each(function(i, l) { l.createDropTargets(); l.buildPositionTable(); });
+					lastPos = list.draggedItem.offset();
+					return false;
+				},
+
+				//returns the index of the list item the mouse is over
+				findPos: function(x, y) {
+					for (var i = 0; i < this.pos.length; i++) {
+						if (this.pos[i].left < x && this.pos[i].right > x && this.pos[i].top < y && this.pos[i].bottom > y)
+							return i;
+					}
+					return -1;
+				},
+
+				//create drop targets which are placeholders at the end of other lists to allow dragging straight to the last position
+				createDropTargets: function() {
+					if (!opts.dragBetween)
+						return;
+
+					$(lists).each(function() {
+						var ph = $(this.container).find("[data-placeholder]");
+						var dt = $(this.container).find("[data-droptarget]");
+						if (ph.size() > 0 && dt.size() > 0)
+							dt.remove();
+						else if (ph.size() == 0 && dt.size() == 0) {
+							if (opts.tagName == "td")
+								$(opts.placeHolderTemplate).attr("data-droptarget", true).appendTo(this.container);
+							else
+								//list.placeHolderItem.clone().removeAttr("data-placeholder") crashes in IE7 and jquery 1.5.1 (doesn't in jquery 1.4.2 or IE8)
+								$(this.container).append(list.placeHolderItem.removeAttr("data-placeholder").clone().attr("data-droptarget", true));
+							
+							list.placeHolderItem.attr("data-placeholder", true);
+						}
+					});
+				}
+			};
+
+			newList.init();
+			lists.push(newList);
+		});
+
+		return this;
+	};
+
+	$.fn.dragsort.defaults = {
+                tagName:"",
+		itemSelector: "",
+		dragSelector: "",
+		dragSelectorExclude: "input, textarea",
+		dragEnd: function() { },
+		dragBetween: false,
+		placeHolderTemplate: "",
+		scrollContainer: window,
+		scrollSpeed: 5
+	};
+
+})(jQuery);
 
 define("dragsort", function(){});
 

+ 7 - 7
public/assets/js/require-table.js

@@ -26,7 +26,7 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
                 },
                 ignoreColumn: [0, 'operate'] //默认不导出第一列(checkbox)与操作(operate)列
             },
-            pageSize: localStorage.getItem("pagesize") || 10,
+            pageSize: localStorage.getItem('page-size') || 10,
             pageList: [10, 15, 20, 25, 50, 'All'],
             pagination: true,
             clickToSelect: true, //是否启用点击选中
@@ -190,12 +190,6 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
                 table.on('refresh.bs.table', function (e, settings, data) {
                     $(Table.config.refreshbtn, toolbar).find(".fa").addClass("fa-spin");
                 });
-                //当表格分页变更时
-                table.on('page-change.bs.table', function (e, page, pagesize) {
-                    if (!isNaN(pagesize)) {
-                        localStorage.setItem("pagesize", pagesize);
-                    }
-                });
                 //当执行搜索时
                 table.on('search.bs.table common-search.bs.table', function (e, settings, data) {
                     table.trigger("uncheckbox");
@@ -540,6 +534,12 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
                 Table.list[id] = table;
                 return table;
             },
+            // 设置全局分页的单页显示数
+            pageSize: function (pageSize) {
+                if (!isNaN(pageSize)) {
+                    localStorage.setItem('page-size', pageSize);
+                }
+            },
             // 批量操作请求
             multi: function (action, ids, table, element) {
                 var options = table.bootstrapTable('getOptions');

+ 1 - 1
think

@@ -14,4 +14,4 @@
 define('APP_PATH', __DIR__ . '/application/');
 
 // 加载框架引导文件
-require './thinkphp/console.php';
+require __DIR__ . '/thinkphp/console.php';