Переглянути джерело

新增Table.api.closetabs关闭选项卡的方法
新增表单提交成功后callback功能
新增mb_ucfirst函数
修复CRUD在ENUM中文字符下的乱码错误
修复快速查询在关联模型下的错误
修复filter过滤在部分情况不生效的BUG

Karson 7 роки тому
батько
коміт
4fbc2c8eb0

+ 11 - 11
application/admin/command/Crud.php

@@ -255,7 +255,7 @@ class Crud extends Command
         $controller = str_replace('_', '', $controller);
         $controllerArr = !$controller ? explode('_', strtolower($table)) : explode('/', strtolower($controller));
         $controllerUrl = implode('/', $controllerArr);
-        $controllerName = ucfirst(array_pop($controllerArr));
+        $controllerName = mb_ucfirst(array_pop($controllerArr));
         $controllerDir = implode(DS, $controllerArr);
         $controllerFile = ($controllerDir ? $controllerDir . DS : '') . $controllerName . '.php';
         $viewDir = $adminPath . 'view' . DS . $controllerUrl . DS;
@@ -810,10 +810,10 @@ class Crud extends Command
         if (!in_array($inputType, ['datetime', 'select', 'multiple', 'checkbox', 'radio']))
             return;
         $fieldList = $this->getFieldListName($field);
-        $methodName = 'get' . ucfirst($fieldList);
+        $methodName = 'get' . mb_ucfirst($fieldList);
         foreach ($itemArr as $k => &$v)
         {
-            $v = "__('" . ucfirst($v) . "')";
+            $v = "__('" . mb_ucfirst($v) . "')";
         }
         unset($v);
         $itemString = $this->getArrayString($itemArr);
@@ -832,7 +832,7 @@ EOD;
     {
         if (!in_array($inputType, ['datetime', 'select', 'multiple', 'checkbox', 'radio']))
             return;
-        $attrField = ucfirst($this->getCamelizeName($field));
+        $attrField = mb_ucfirst($this->getCamelizeName($field));
         $getAttr[] = $this->getReplacedStub("mixins" . DS . $inputType, ['field' => $field, 'methodName' => "get{$attrField}TextAttr", 'listMethodName' => "get{$attrField}List"]);
     }
 
@@ -840,7 +840,7 @@ EOD;
     {
         if ($inputType != 'datetime')
             return;
-        $attrField = ucfirst($this->getCamelizeName($field));
+        $attrField = mb_ucfirst($this->getCamelizeName($field));
         if ($inputType == 'datetime')
         {
             $return = <<<EOD
@@ -868,13 +868,13 @@ EOD;
         {
             $modelarr = explode('_', strtolower($table));
             foreach ($modelarr as $k => &$v)
-                $v = ucfirst($v);
+                $v = mb_ucfirst($v);
             unset($v);
             $modelName = implode('', $modelarr);
         }
         else
         {
-            $modelName = ucfirst($model);
+            $modelName = mb_ucfirst($model);
         }
         return $modelName;
     }
@@ -960,7 +960,7 @@ EOD;
             $resultArr = [];
             foreach ($itemArr as $k => $v)
             {
-                $resultArr[] = "    '" . ucfirst($k) . "'  =>  '{$v}'";
+                $resultArr[] = "    '" . mb_ucfirst($k) . "'  =>  '{$v}'";
             }
             return implode(",\n", $resultArr);
         }
@@ -980,7 +980,7 @@ EOD;
         $langArr = [];
         foreach ($arr as $k => $v)
         {
-            $langArr[(is_numeric($k) ? $v : $k)] = is_numeric($k) ? ($withTpl ? "{:" : "") . "__('" . ucfirst($v) . "')" . ($withTpl ? "}" : "") : $v;
+            $langArr[(is_numeric($k) ? $v : $k)] = is_numeric($k) ? ($withTpl ? "{:" : "") . "__('" . mb_ucfirst($v) . "')" . ($withTpl ? "}" : "") : $v;
         }
         return $langArr;
     }
@@ -1129,7 +1129,7 @@ EOD;
      */
     protected function getFormGroup($field, $content)
     {
-        $langField = ucfirst($field);
+        $langField = mb_ucfirst($field);
         return<<<EOD
     <div class="form-group">
         <label for="c-{$field}" class="control-label col-xs-12 col-sm-2">{:__('{$langField}')}:</label>
@@ -1175,7 +1175,7 @@ EOD;
      */
     protected function getJsColumn($field, $datatype = '', $extend = '')
     {
-        $lang = ucfirst($field);
+        $lang = mb_ucfirst($field);
         $formatter = '';
         foreach ($this->fieldFormatterSuffix as $k => $v)
         {

Різницю між файлами не показано, бо вона завелика
+ 1 - 1
application/admin/command/Install/fastadmin.sql


+ 3 - 3
application/admin/view/common/menu.html

@@ -30,9 +30,9 @@
     <ul class="sidebar-menu">
         {$menulist}
         <li class="header">相关链接</li>
-        <li><a href="http://doc.fastadmin.net"><i class="fa fa-list text-red"></i> <span>官方文档</span></a></li>
-        <li><a href="http://forum.fastadmin.net"><i class="fa fa-comment text-yellow"></i> <span>社区交流</span></a></li>
-        <li><a href="https://jq.qq.com/?_wv=1027&k=487PNBb"><i class="fa fa-qq text-aqua"></i> <span>QQ交流群</span></a></li>
+        <li><a href="http://doc.fastadmin.net" target="_blank"><i class="fa fa-list text-red"></i> <span>官方文档</span></a></li>
+        <li><a href="http://forum.fastadmin.net" target="_blank"><i class="fa fa-comment text-yellow"></i> <span>社区交流</span></a></li>
+        <li><a href="https://jq.qq.com/?_wv=1027&k=487PNBb" target="_blank"><i class="fa fa-qq text-aqua"></i> <span>QQ交流群</span></a></li>
     </ul>
 </section>
 <!-- /.sidebar -->

+ 10 - 0
application/common.php

@@ -198,3 +198,13 @@ if (!function_exists('copydirs'))
     }
 
 }
+
+if (!function_exists('mb_ucfirst'))
+{
+
+    function mb_ucfirst($string)
+    {
+        return mb_strtoupper(mb_substr($string, 0, 1)) . mb_strtolower(mb_substr($string, 1));
+    }
+
+}

+ 9 - 7
application/common/controller/Backend.php

@@ -192,7 +192,7 @@ class Backend extends Controller
 
     /**
      * 生成查询所需要的条件,排序方式
-     * @param mixed $searchfields 查询条件
+     * @param mixed $searchfields 快速查询的字段
      * @param boolean $relationSearch 是否关联查询
      * @return array
      */
@@ -220,17 +220,14 @@ class Backend extends Controller
                 $name = basename(str_replace('\\', '/', $class));
                 $tableName = $this->model->getQuery()->getTable($name) . ".";
             }
-            if (stripos($sort, ".") === false)
-            {
-                $sort = $tableName . $sort;
-            }
+            $sort = stripos($sort, ".") === false ? $tableName . $sort : $sort;
         }
         if ($search)
         {
             $searcharr = is_array($searchfields) ? $searchfields : explode(',', $searchfields);
             foreach ($searcharr as $k => &$v)
             {
-                $v = $tableName . $v;
+                $v = stripos($v, ".") === false ? $tableName . $v : $v;
             }
             unset($v);
             $where[] = [implode("|", $searcharr), "LIKE", "%{$search}%"];
@@ -249,7 +246,7 @@ class Backend extends Controller
                 case '!=':
                 case 'LIKE':
                 case 'NOT LIKE':
-                    $where[] = [$k, $sym, $v];
+                    $where[] = [$k, $sym, (string) $v];
                     break;
                 case '>':
                 case '>=':
@@ -257,7 +254,9 @@ class Backend extends Controller
                 case '<=':
                     $where[] = [$k, $sym, intval($v)];
                     break;
+                case 'IN':
                 case 'IN(...)':
+                case 'NOT IN':
                 case 'NOT IN(...)':
                     $where[] = [$k, str_replace('(...)', '', $sym), explode(',', $v)];
                     break;
@@ -265,10 +264,13 @@ class Backend extends Controller
                 case 'NOT BETWEEN':
                     $where[] = [$k, $sym, array_slice(explode(',', $v), 0, 2)];
                     break;
+                case 'LIKE':
                 case 'LIKE %...%':
                     $where[] = [$k, 'LIKE', "%{$v}%"];
                     break;
+                case 'NULL':
                 case 'IS NULL':
+                case 'NOT NULL':
                 case 'IS NOT NULL':
                     $where[] = [$k, strtolower(str_replace('IS ', '', $sym))];
                     break;

+ 25 - 1
public/assets/js/backend.js

@@ -50,7 +50,7 @@ define(['fast', 'moment'], function (Fast, Moment) {
                             title = typeof title !== 'undefined' ? title : leftlink.find("span:first").text();
                             leftlink.trigger("fa.event.toggleitem");
                         }
-                        var navnode = $(".nav-tabs ul li a[node-url='" + url + "']");
+                        var navnode = top.window.$(".nav-tabs ul li a[node-url='" + url + "']");
                         if (navnode.size() > 0) {
                             navnode.trigger("click");
                         } else {
@@ -63,6 +63,30 @@ define(['fast', 'moment'], function (Fast, Moment) {
                     }
                 }
             },
+            closetabs: function (url) {
+                if (typeof url === 'undefined') {
+                    top.window.$("ul.nav-addtabs li.active .close-tab").trigger("click");
+                } else {
+                    var dom = "a[url='{url}']"
+                    var navlink = top.window.$(dom.replace(/\{url\}/, url));
+                    if (navlink.size() === 0) {
+                        url = Fast.api.fixurl(url);
+                        navlink = top.window.$(dom.replace(/\{url\}/, url));
+                        if (navlink.size() === 0) {
+                        } else {
+                            var baseurl = url.substr(0, url.indexOf("?") > -1 ? url.indexOf("?") : url.length);
+                            navlink = top.window.$(dom.replace(/\{url\}/, baseurl));
+                            //能找到相对地址
+                            if (navlink.size() === 0) {
+                                navlink = top.window.$(".nav-tabs ul li a[node-url='" + url + "']");
+                            }
+                        }
+                    }
+                    if (navlink.size() > 0 && navlink.attr('addtabs')) {
+                        top.window.$("ul.nav-addtabs li#tab_" + navlink.attr('addtabs') + " .close-tab").trigger("click");
+                    }
+                }
+            },
             replaceids: function (elem, url) {
                 //如果有需要替换ids的
                 if (url.indexOf("{ids}") > -1) {

+ 52 - 16
public/assets/js/require-backend.min.js

@@ -6761,7 +6761,7 @@ define('backend',['fast', 'moment'], function (Fast, Moment) {
                             title = typeof title !== 'undefined' ? title : leftlink.find("span:first").text();
                             leftlink.trigger("fa.event.toggleitem");
                         }
-                        var navnode = $(".nav-tabs ul li a[node-url='" + url + "']");
+                        var navnode = top.window.$(".nav-tabs ul li a[node-url='" + url + "']");
                         if (navnode.size() > 0) {
                             navnode.trigger("click");
                         } else {
@@ -6774,6 +6774,30 @@ define('backend',['fast', 'moment'], function (Fast, Moment) {
                     }
                 }
             },
+            closetabs: function (url) {
+                if (typeof url === 'undefined') {
+                    top.window.$("ul.nav-addtabs li.active .close-tab").trigger("click");
+                } else {
+                    var dom = "a[url='{url}']"
+                    var navlink = top.window.$(dom.replace(/\{url\}/, url));
+                    if (navlink.size() === 0) {
+                        url = Fast.api.fixurl(url);
+                        navlink = top.window.$(dom.replace(/\{url\}/, url));
+                        if (navlink.size() === 0) {
+                        } else {
+                            var baseurl = url.substr(0, url.indexOf("?") > -1 ? url.indexOf("?") : url.length);
+                            navlink = top.window.$(dom.replace(/\{url\}/, baseurl));
+                            //能找到相对地址
+                            if (navlink.size() === 0) {
+                                navlink = top.window.$(".nav-tabs ul li a[node-url='" + url + "']");
+                            }
+                        }
+                    }
+                    if (navlink.size() > 0 && navlink.attr('addtabs')) {
+                        top.window.$("ul.nav-addtabs li#tab_" + navlink.attr('addtabs') + " .close-tab").trigger("click");
+                    }
+                }
+            },
             replaceids: function (elem, url) {
                 //如果有需要替换ids的
                 if (url.indexOf("{ids}") > -1) {
@@ -10953,8 +10977,15 @@ define('form',['jquery', 'bootstrap', 'upload', 'validator'], function ($, undef
                     }
                 }, function (data, ret) {
                     $('.form-group', form).removeClass('has-feedback has-success has-error');
-                    if (data && typeof data === 'object' && typeof data.token !== 'undefined') {
-                        $("input[name='__token__']", form).val(data.token);
+                    if (data && typeof data === 'object') {
+                        //刷新客户端token
+                        if (typeof data.token !== 'undefined') {
+                            $("input[name='__token__']", form).val(data.token);
+                        }
+                        //调用客户端事件
+                        if (typeof data.callback !== 'undefined' && typeof data.callback === 'function') {
+                            data.callback.call(form, data);
+                        }
                     }
                     if (typeof success === 'function') {
                         if (!success.call(form, data, ret)) {
@@ -11486,21 +11517,24 @@ $.fn.addtabs = function (options) {
     });
 
     _add = function (opts) {
-        id = 'tab_' + opts.id;
+        var id, tabid, conid, url;
+        id = opts.id;
+        tabid = 'tab_' + opts.id;
+        conid = 'con_' + opts.id;
         url = opts.url;
         url += (opts.url.indexOf("?") > -1 ? "&addtabs=1" : "?addtabs=1");
         navobj.find("[role='presentation']").removeClass('active');
         tabobj.find("[role='tabpanel']").removeClass('active');
         //如果TAB不存在,创建一个新的TAB
-        if ($("#" + id).size() == 0) {
+        if ($("#" + tabid).size() == 0) {
             //创建新TAB的title
-            title = $('<li role="presentation" id="tab_' + id + '"><a href="#' + id + '" node-id="' + opts.id + '" aria-controls="' + id + '" role="tab" data-toggle="tab">' + opts.title + '</a></li>');
+            title = $('<li role="presentation" id="' + tabid + '"><a href="#' + conid + '" node-id="' + opts.id + '" aria-controls="' + id + '" role="tab" data-toggle="tab">' + opts.title + '</a></li>');
             //是否允许关闭
             if (options.close && $("li", navobj).size() > 0) {
                 title.append(' <i class="close-tab fa fa-remove"></i>');
             }
             //创建新TAB的内容
-            content = $('<div role="tabpanel" class="tab-pane" id="' + id + '"></div>');
+            content = $('<div role="tabpanel" class="tab-pane" id="' + conid + '"></div>');
             //是否指定TAB内容
             if (opts.content) {
                 content.append(opts.content);
@@ -11522,23 +11556,25 @@ $.fn.addtabs = function (options) {
         }
 
         //激活TAB
-        $("#tab_" + id).addClass('active');
-        $("#" + id).addClass("active");
+        $("#" + tabid).addClass('active');
+        $("#" + conid).addClass("active");
         _drop();
     };
 
     _close = function (id) {
+        var tabid = 'tab_'+id;
+        var conid = 'con_'+id;
         //如果关闭的是当前激活的TAB,激活他的前一个TAB
-        if (obj.find("li.active").attr('id') == "tab_" + id) {
-            if ($("#tab_" + id).prev().not(".tabdrop").size() > 0) {
-                $("#tab_" + id).prev().not(".tabdrop").find("a").trigger("click");
-            } else if ($("#tab_" + id).next().size() > 0) {
-                $("#tab_" + id).next().trigger("click");
+        if (obj.find("li.active").attr('id') == tabid) {
+            if ($("#" + tabid).prev().not(".tabdrop").size() > 0) {
+                $("#" + tabid).prev().not(".tabdrop").find("a").trigger("click");
+            } else if ($("#" + tabid).next().size() > 0) {
+                $("#" + tabid).next().trigger("click");
             }
         }
         //关闭TAB
-        $("#tab_" + id).remove();
-        $("#" + id).remove();
+        $("#" + tabid).remove();
+        $("#" + conid).remove();
         _drop();
         options.callback();
     };

+ 9 - 2
public/assets/js/require-form.js

@@ -186,8 +186,15 @@ define(['jquery', 'bootstrap', 'upload', 'validator'], function ($, undefined, U
                     }
                 }, function (data, ret) {
                     $('.form-group', form).removeClass('has-feedback has-success has-error');
-                    if (data && typeof data === 'object' && typeof data.token !== 'undefined') {
-                        $("input[name='__token__']", form).val(data.token);
+                    if (data && typeof data === 'object') {
+                        //刷新客户端token
+                        if (typeof data.token !== 'undefined') {
+                            $("input[name='__token__']", form).val(data.token);
+                        }
+                        //调用客户端事件
+                        if (typeof data.callback !== 'undefined' && typeof data.callback === 'function') {
+                            data.callback.call(form, data);
+                        }
                     }
                     if (typeof success === 'function') {
                         if (!success.call(form, data, ret)) {