FastAdmin 基本知识流程一栏

 

fastadmin进阶

安装:出现登陆页无法显示:可能是php的gd2扩展未开启

FastAdmin 在 Nginx 中的配置

用的是AdminLTE后台模板require.js、less、Bower

调试错误:看runtime/log

FastAdmin 的上传代码在哪里?

一张图解析FastAdmin中的表格列表的功能

fastadmin的页面是如何生成的?

FastAdmin 如何隐藏操作栏中的“删除”按钮“?

笔记:FastAdmin 上传设置

如何修改 FastAdmin 弹窗大小?

FastAdmin 的 CRUD 不支持层级模型

fastadmin笔记,应该能解决大部分问题

 

 

一键生成数据表的crud 的记录会保存到fa_command表中

 当在线命令行管理成功生成crud时生成的文件如下:如fa_tom

application/admin/contorller/Tom.php

application/admin/model/Tom.php

application/admin/validate/Tom.php

application/admin/view/tom/index.html、edit.html、add.html

application/admin/lang/zh-cn/tom.php

/public/assets/js/backend/tom.js

如果是fa_demo_tom则会生成(_分隔成目录)

application/admin/contorller/demo/Tom.php

application/admin/model/demo/Tom.php

application/admin/validate/demo/Tom.php

application/admin/view/demo/tom/index.html、edit.html、add.html

application/admin/lang/zh-cn/demo/tom.php

/public/assets/js/backend/demo/tom.js

 

生成菜单的记录会更新fa_auth_rule的数据   name不带方法的就是菜单显示的pidwei0是选项卡

一键生成的是层级目录的菜单,在后台展示时父级菜单会以目录名称显示,

如上面的contorller/demo/Tom.php  父菜单显示demo子菜单显示Tom ,我们必须在application/admin/lang/zh-cn.php中添加

'Demo'=>'案例','Tom'=>'案例1'     配置后菜单显示如上:

 

一键压缩打包(略)

在FastAdmin中如果修改了核心的JS或CSS文件,是需要重新压缩打包后在生产环境下才会生效。FastAdmin采用的是基于RequireJSr.js进行JS和CSS文件的压缩打包,application/config.phpapp_debug的值,当为true的时候是采用的无压缩的JS和CSS,当为false时采用的是压缩版的JS和CSS

 

 

多语言:

return[

'Home'=>'前台'

];

{:__('Home')}的方式调用,而在PHP和JS中均可以使用__('Home')的方式发起调用

如果我们需要跨模块引入其它模块的语言包,则可以在 控制器中使用loadlang方法来引入,如

$this->loadlang('模块名');

如果需要在JS中跨模块引入语言包,则需要修改Ajax.php中的lang这个方法

控制器

我们的控制器都必须继承自application/common/controller/Backend.php的\app\common\controller\Backend这个基类

这个基类application/admin/library/traits/Backend.php里引入的 use \app\admin\library\traits\Backend;它有八个公共方法

index/add/edit/del/multi/recyclebin/destroy/restore/                                 import

查看、添加、编辑、删除、批量更新、回收站、真实删除、还原               导入

common/controller/Backend里还有好多属性:

/**
 * 无需登录的方法,同时也就不需要鉴权了
 * @var array
 */
protected $noNeedLogin = [];

/**
 * 无需鉴权的方法,但需要登录
 * @var array
 */
protected $noNeedRight = [];

/**
 * 布局模板
 * @var string
 */
protected $layout = 'default';

/**
 * 权限控制类
 * @var Auth
 */
protected $auth = null;

/**
 * 快速搜索时执行查找的字段
 */
protected $searchFields = 'id';

/**
 * 是否是关联查询
 */
protected $relationSearch = false;

/**
 * 是否开启数据限制
 * 支持auth/personal
 * 表示按权限判断/仅限个人 
 * 默认为禁用,若启用请务必保证表中存在admin_id字段
 */
protected $dataLimit = false;

/**
 * 数据限制字段
 */
protected $dataLimitField = 'admin_id';

/**
 * 是否开启Validate验证
 */
protected $modelValidate = false;

/**
 * 是否开启模型场景验证
 */
protected $modelSceneValidate = false;

/**
 * Multi方法可批量修改的字段
 */
protected $multiFields = 'status';




方法

/**
 * 加载语言文件
 * @param string $name
 */
protected function loadlang($name)
{
}

/**
 * 渲染配置信息
 * @param mixed $name 键名或数组
 * @param mixed $value 值 
 */
protected function assignconfig($name, $value = '')
{    
}

/**
 * 生成查询所需要的条件,排序方式
 * @param mixed $searchfields 快速查询的字段
 * @param boolean $relationSearch 是否关联查询
 * @return array
 */
protected function buildparams($searchfields = null, $relationSearch = null)
{    
}

/**
 * 获取数据限制的管理员ID
 * 禁用数据限制时返回的是null
 * @return mixed
 */
protected function getDataLimitAdminIds()
{    
}

/**
 * Selectpage的实现方法
 * 
 * 当前方法只是一个比较通用的搜索匹配,请按需重载此方法来编写自己的搜索逻辑,$where按自己的需求写即可
 * 这里示例了所有的参数,所以比较复杂,实现上自己实现只需简单的几行即可
 * 
 */
protected function selectpage()
{
}

当两张相似的表意见curd时一个没有关联模型查询一个有时的区别:

class Demo extends Backend
{
    
    /**
     * Demo模型对象
     * @var \app\admin\model\Demo
     */
    protected $model = null;

    public function _initialize()
    {
        parent::_initialize();
        $this->model = new \app\admin\model\Demo;

    }
    
    /**
     * 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法
     * 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑
     * 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改
     */
    

}

traits  的原idnex方法

trait Backend
{

    /**
     * 查看
     */
    public function index()
    {
        //设置过滤方法
        $this->request->filter(['strip_tags']);
        if ($this->request->isAjax()) {
            //如果发送的来源是Selectpage,则转发到Selectpage
            if ($this->request->request('keyField')) {
                return $this->selectpage();
            }
            list($where, $sort, $order, $offset, $limit) = $this->buildparams();
            $total = $this->model
                ->where($where)
                ->order($sort, $order)
                ->count();

            $list = $this->model
                ->where($where)
                ->order($sort, $order)
                ->limit($offset, $limit)
                ->select();

            $list = collection($list)->toArray();
            $result = array("total" => $total, "rows" => $list);

            return json($result);
        }
        return $this->view->fetch();
    }
    //......
}

有关联时的控制器:

class Dash extends Backend
{
    
    /**
     * Dash模型对象
     * @var \app\admin\model\Dash
     */
    protected $model = null;

    public function _initialize()
    {
        parent::_initialize();
        $this->model = new \app\admin\model\Dash;

    }
    
    /**
     * 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法
     * 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑
     * 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改
     */
    

    /**
     * 查看
     */
    public function index()
    {
        //当前是否为关联查询
        $this->relationSearch = true;
        //设置过滤方法
        $this->request->filter(['strip_tags']);
        if ($this->request->isAjax())
        {
            //如果发送的来源是Selectpage,则转发到Selectpage
            if ($this->request->request('keyField'))
            {
                return $this->selectpage();
            }
            list($where, $sort, $order, $offset, $limit) = $this->buildparams();
            $total = $this->model
                    ->with(['category'])
                    ->where($where)
                    ->order($sort, $order)
                    ->fetchSql(false)
                    ->count();

            $list = $this->model
                    ->with(['category'])
                    ->where($where)
                    ->order($sort, $order)
                    ->limit($offset, $limit)
                    ->fetchSql(false)
                    ->select();
            //file_put_contents(__DIR__.'/../../../runtime/log/sql_'.time().'_log.txt', $total);            
            //file_put_contents(__DIR__.'/../../../runtime/log/sql_'.time().'_log1.txt', $list);            
            foreach ($list as $row) {
                
                
            }
            $list = collection($list)->toArray();
            $result = array("total" => $total, "rows" => $list);

            return json($result);
        }
        return $this->view->fetch();
    }
}

无关联时的model

class Demo extends Model
{
    // 表名
    protected $name = 'demo';
    
    // 自动写入时间戳字段
    protected $autoWriteTimestamp = false;

    // 定义时间戳字段名
    protected $createTime = false;
    protected $updateTime = false;
    
    // 追加属性
    protected $append = [
    ];
}

 

有关联时的model(多出了一个方法)

class Dash extends Model
{
    // 表名
    protected $name = 'dash';
    
    // 自动写入时间戳字段
    protected $autoWriteTimestamp = false;

    // 定义时间戳字段名
    protected $createTime = false;
    protected $updateTime = false;
    
    // 追加属性
    protected $append = [

    ];
    
    public function category()
    {
        return $this->belongsTo('Category', 'category_id', 'id', [], 'LEFT')->setEagerlyType(0);
    }
}

js

define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {

    var Controller = {
        index: function () {
            // 初始化表格参数配置
            Table.api.init({
                extend: {
                    index_url: 'demo/index',
                    add_url: 'demo/add',
                    edit_url: 'demo/edit',
                    del_url: 'demo/del',
                    multi_url: 'demo/multi',
                    table: 'demo',
                }
            });

            var table = $("#table");

            // 初始化表格
            table.bootstrapTable({
                url: $.fn.bootstrapTable.defaults.extend.index_url,
                pk: 'id',
                sortName: 'id',
                columns: [
                    [
                        {checkbox: true},
                        {field: 'id', title: __('Id')},
                        {field: 'name', title: __('Name')},
                        {field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate}
                    ]
                ]
            });

            // 为表格绑定事件
            Table.api.bindevent(table);
        },
        add: function () {
            Controller.api.bindevent();
        },
        edit: function () {
            Controller.api.bindevent();
        },
        api: {
            bindevent: function () {
                Form.api.bindevent($("form[role=form]"));
            }
        }
    };
    return Controller;
});

关联后的js

define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {

    var Controller = {
        index: function () {
            // 初始化表格参数配置
            Table.api.init({
                extend: {
                    index_url: 'dash/index',
                    add_url: 'dash/add',
                    edit_url: 'dash/edit',
                    del_url: 'dash/del',
                    multi_url: 'dash/multi',
                    table: 'dash',
                }
            });

            var table = $("#table");

            // 初始化表格
            table.bootstrapTable({
                url: $.fn.bootstrapTable.defaults.extend.index_url,
                pk: 'id',
                sortName: 'id',
                columns: [
                    [
                        {checkbox: true},
                        {field: 'id', title: __('Id')},
                        {field: 'name', title: __('Name')},
                        {field: 'category_id', title: __('Category_id')},
                        {field: 'category.id', title: __('Category.id')},
                        {field: 'category.pid', title: __('Category.pid')},
                        {field: 'category.type', title: __('Category.type')},
                        {field: 'category.name', title: __('Category.name')},
                        {field: 'category.nickname', title: __('Category.nickname')},
                        {field: 'category.flag', title: __('Category.flag'), operate:'FIND_IN_SET', formatter: Table.api.formatter.label},
                        {field: 'category.image', title: __('Category.image'), formatter: Table.api.formatter.image},
                        {field: 'category.keywords', title: __('Category.keywords')},
                        {field: 'category.description', title: __('Category.description')},
                        {field: 'category.diyname', title: __('Category.diyname')},
                        {field: 'category.createtime', title: __('Category.createtime'), operate:'RANGE', addclass:'datetimerange', formatter: Table.api.formatter.datetime},
                        {field: 'category.updatetime', title: __('Category.updatetime'), operate:'RANGE', addclass:'datetimerange', formatter: Table.api.formatter.datetime},
                        {field: 'category.weigh', title: __('Category.weigh')},
                        {field: 'category.status', title: __('Category.status'), formatter: Table.api.formatter.status},
                        {field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate}
                    ]
                ]
            });

            // 为表格绑定事件
            Table.api.bindevent(table);
        },
        add: function () {
            Controller.api.bindevent();
        },
        edit: function () {
            Controller.api.bindevent();
        },
        api: {
            bindevent: function () {
                Form.api.bindevent($("form[role=form]"));
            }
        }
    };
    return Controller;
});

fastadmin关于table的说明及示例

bootstraptable详细的参数

 

更详细教程

var table = $("#table");

// 初始化表格
table.bootstrapTable({
    url: '/Home/GetDepartment',         //请求后台的URL(*)用于从远程站点请求数据的URL
    method: 'get',                      //请求方式(*)
    toolbar: '#toolbar',                //工具栏按钮用哪个容器 一个jQuery 选择器,指明自定义的 buttons toolbar。例如:#buttons-toolbar, .buttons-toolbar 或 DOM 节点
    toolbarAlign:'left'                 //指示如何对齐自定义工具栏。可以使用'left','right'
    buttonsToolbar:'',                  //一个jQuery选择器,指示按钮工具栏,例如:#buttons-toolbar,.buttons-toolbar或DOM节点
    buttonsAlign:'right',               //指示如何对齐工具栏按钮。可以使用'left','right'。
    buttonsClass:'secondary',           //定义表按钮的Bootstrap类(在'btn-'之后添加)
    striped: true,                      //是否显示行间隔色
    cache: false,                       //是否使用缓存,默认为true,所以一般情况下需要设置一下这个属性(*)
    pagination: true,                   //是否显示分页(*) 设置为true以在表格底部显示分页工具栏默认false
    sortable: true,                     //是否启用排序  列中也有此变量
    sortName:'',                        //定义要排序的列   没定义默认都不排列,同sortOrder结合使用,sortOrder没写的话列默认递增(asc)
    sortOrder: "asc",                   //定义列排序顺序,只能是'asc'或'desc'。
    sortStable: false,                   //如果你把此属性设为了true)我们将为此行添加'_position'属性 (别看错了,是sortStable,sortable在下面)设为true,则和sort部分一样,区别是:在排序过程中,如果存在相等的元素,则原来的顺序不会改变
    queryParams: oTableInit.queryParams,//传递参数(*)
    sidePagination: "server",           //分页方式:client客户端分页(默认),server服务端分页(*)
    silentSort:true,//设置为false以便对加载的消息数据进行排序。当sidePagination选项设置为“server”时,此选项有效。 
    pageNumber:1,                       //初始化加载第一页,默认第一页
    pageSize: 10,                       //每页的记录行数(*)
    pageList: [10, 25, 50, 100],        //可供选择的每页的行数(*)
    search: true,                       //是否显示表格搜索input,此搜索是客户端搜索,不会进服务端,所以,个人感觉意义不大
    strictSearch: true,                 //启用严格搜索
    showColumns: false,                 //是否显示所有的列 设置为true以显示列下拉列表(一个可以设置显示想要的列的下拉f按钮)  
    showRefresh: true,                  //是否显示刷新按钮 默认false
    minimumCountColumns: 1,             //最少允许的列数  要从列下拉列表中隐藏的最小列数
    clickToSelect: true,                //是否启用点击选中行
    height: 500,                        //行高,如果没有设置height属性,表格自动根据记录条数觉得表格高度
    idField:'',                         //表明哪个是字段是标识字段  
    uniqueId: "ID",                     //表明每一行的唯一标识字段,一般为主键列
    showToggle:true,                    //是否显示详细视图和列表视图的切换按钮
    cardView: false,                    //是否显示详细视图  设置为true以显示卡片视图表,例如mobile视图(卡片视图)
    detailView: false,                   //设置为true以显示detail 视图表(细节视图)
    locale:'zh-CN',
    height:800,                           //固定表格的高度
    classes:'table table-bordered table-hover',//表的类名。可以使用'table','table-bordered','table-hover','table-striped','table-dark','table-sm'和'table-borderless'。默认情况下,表格是有界的。
    theadClasses:'',// 表thead的类名 如使用.thead-light或.thead-dark使theads显示为浅灰色或深灰色。   
    rowStyle:function(row,index){},//    行样式格式化程序函数支持类或css
    rowAttributes:function(row,index){},//  row属性formatter函数,支持所有自定义属性  
    undefinedText:'-',// 定义默认的未定义文本   
    sortClass:'',//已排序的td元素的类名       
    rememberOrder:false,//设置为true以记住每列的顺序    
    data:[],//    要加载的数据 [] or {}
    contentType:'application/json',//请求远程数据的contentType,例如:application/x-www-form-urlencoded。    
    dataType:'json',//您希望服务器返回的数据类型    
    totalField:'total',//Key in incoming json containing 'total' data.
    dataField:'rows',//名称写自己定义的每列的字段名,也就是key,通过key才能给某行的某列赋value原文:获取每行数据json内的key
    onlyInfoPagination:false,//设置为true以仅显示表中显示的数据量。它需要将分页表选项即pagination设置为true    
    paginationLoop:true,//设置为true以启用分页连续循环模式    
    paginationHAlign:'right',//分页条水平方向的位置,默认right(最右),可选left   
    totalRows:0,//该属性主要由分页服务器传递,易于使用    
    paginationDetailHAlign:'left',//如果解译的话太长,举个例子,paginationDetail就是“显示第 1 到第 8 条记录,总共 15 条记录 每页显示 8 条记录”,默认left(最左),可选right    
    paginationVAlign:'bottom',//分页条垂直方向的位置,默认bottom(底部),可选top、both(顶部和底部均有分页条)    
    paginationPreText:'<',//上一页的按钮符号    
    paginationNextText:'>',//下一页的按钮符号    
    paginationSuccessivelySize:5,//分页时会有<12345...80>这种格式而5则表示显示...左边的的页数   
    paginationPagesBySide:1,//...右边的最大连续页数如改为2则 <1 2 3 4....79 80>   
    paginationUseIntermediate:false,//计算并显示中间页面以便快速访问 true 会将...替换为计算的中间页数42    
    searchOnEnterKey:false,// true时搜索方法将一直执行,直到按下Enter键(即按下回车键才进行搜索)   
    trimOnSearch:true,//默认true,自动忽略空格        
    searchAlign:'right',//指定搜索输入框的方向。可以使用'left','right'。    
    searchTimeOut:500,//设置搜索触发超时    
    searchText:'',//设置搜索文本框的默认搜索值  
    showHeader:true,//设置为false以隐藏表头    
    showFooter:false,//设置为true以显示摘要页脚行(固定也交 比如显示总数什么的最合适)    
    showPaginationSwitch:false,//设置为true以显示分页组件的切换按钮    
    showFullscreen:false,// 设置为true以显示全屏按钮   
    smartDisplay:true,//设置为true以巧妙地显示分页或卡片视图    
    escape:false,// 转义字符串以插入HTML,替换 &, <, >, “, `, 和 ‘字符  跳过插入HTML中的字符串,替换掉特殊字符 
    selectItemName:'btSelectItem',//  设置radio 或者 checkbox的字段名称   
    clickToSelect:false,//设置为true时 在点击列时可以选择checkbox或radio
    singleSelect:false,// 默认false,设为true则允许复选框仅选择一行(不能多选了?)
    checkboxHeader:true,//设置为false以隐藏标题行中的check-all复选框 即隐藏全选框     
    maintainSelected:false,// true时点击分页按钮或搜索按钮时,记住checkbox的选择项    设为true则保持被选的那一行的状态
    icons:{//定义工具栏,分页和详细信息视图中使用的图标    
        paginationSwitchDown: 'fa-caret-square-down',
        paginationSwitchUp: 'fa-caret-square-up',
        refresh: 'fa-sync',
        toggleOff: 'fa-toggle-off',
        toggleOn: 'fa-toggle-on',
        columns: 'fa-th-list',
        detailOpen: 'fa-plus',
        detailClose: 'fa-minus',
        fullscreen: 'fa-arrows-alt'
    },
    iconSize:'undefined',// 定义icon图表的尺寸大小html对应为data-icon-undefined (默认btn)、data-icon-lg 大按钮的尺寸(btn-lg)...;  这里的值依次为undefined => btnxs => btn-xssm => btn-smlg => btn-lg   
    iconsPrefix:'fa',//定义图标集名称(FontAwesome的'glyphicon'或'fa')。默认情况下,'fa'用于Bootstrap v4    
   
    queryParamsType:'limit',//设置'limit'以使用RESTFul类型发送查询参数。    
    ajaxOptions:{},//提交ajax请求的其他选项。值列表:jQuery.ajax。    
    customSort:function(sortName,sortOrder,data){},//自定义排序功能(用来代替自带的排序功能),需要两个参数(可以参考前面):    
    ajax:function(){},// 一种替换ajax调用的方法。应该实现与jQuery ajax方法相同的API       
    queryParams: function(params) { // 请求远程数据时,您可以通过修改queryParams来发送其他参数
        return params 
    },   
    responseHandler:function(res) { //在加载远程数据之前,处理响应数据格式,参数对象包含 
        return res 
    },   
    customSearch:function(data,text){// 执行自定义搜索功能替换内置搜索功能,需要两个参数   
        return data.filter(function (row) {return row.field.indexOf(text) > -1})
    },
    footerStyle:function(column){//  页脚样式格式化程序函数,只需一个参数 m默认{}  
        return {
            css: { 'font-weight': 'normal' }, 
            classes: 'my-class'
        }
    },
    detailFormatter:function(index,row,element){//前提:detailView设为true,启用了显示detail view。- 用于格式化细节视图- 返回一个字符串,通过第三个参数element直接添加到细节视图的cell(某一格)中,其中,element为目标cell的jQuery element    
        return '';
    },    detailFilter:function(index,row){//当detailView设置为true时,每行启用扩展。返回true并且将启用该行以进行扩展,返回false并禁用该行的扩展。默认函数返回true以启用所有行的扩展。    
        return true
    },    ignoreClickToSelectOn:function(element){// 包含一个参数:element: 点击的元素。返回 true 是点击事件会被忽略,返回 false 将会自动选中。该选项只有在 clickToSelect 为 true 时才生效。  
        return $.inArray(element.tagName, ['A', 'BUTTON']
    },   
   
    columns: [
        {checkbox: false},
        {radio: false},
        {
            radio: false,//此列转成radio上面单独领出来是应为有字段显示就不需要它呀
            checkbox: false,//此列转成checkbox  单独拎出来同上
            field: 'operate', //设置data-field的值
            title: __('Operate'),//设置data-field的值
            table: table,
            events: Table.api.events.operate,
            formatter: Table.api.formatter.operate,//单元格格式函数 this上下文是当前列对象
            formatter: function (value, row, index,field){},
            titleTooltip:'列标题工具提示文本。此选项还支持标题HTML属性',
            class:'定义列的类名',
            rowspan:1,//指定单元格应占用的行数。
            colspan:1,//指定单元格应占用的列数。
            align:'center',//指定如何对齐列数据。可以使用'left','right','center'。
            halign:'center',//指定如何对齐表头。可以使用'left','right','center'。
            falign:'center',//指示如何对齐表格页脚。可以使用'left','right','center'。
            valign:'middle',//指出如何对齐单元格数据。可以使用'top','middle','bottom'
            width:'10%',//列的宽度。如果未定义,宽度将自动扩展以适合其内容。格式'100px','10%',100,如果想表格保持列自适应并且尺寸太小,则可以忽略这项(通过类等使用min / max-width)
            sortable:false,//设置为true以允许列可以排序。
            order:'asc',//默认排序顺序,只能是'asc'或'desc'。
            visible:true,//设置为false以隐藏列项。
            cardVisible:true,//设置为false以隐藏card 视图状态中的列项
            switchable:true,//设置为false以禁用可切换的列项
            clickToSelect:true,//设置为true时 在点击列时可以选择checkbox或radio
            footerFormatter:function(data){},//当前列对象函数该函数应返回一个字符串,其中包含要在页脚单元格中显示的文本
            events::{},//使用格式化函数时的单元事件监听器 四个参数event,value,row,index; html可以这么用 <th .. data-events="operateEvent">
            sorter:function(a,b,rowA,rowB){},//用于进行本地排序的自定义字段排序函数(第一个字段值,第二个字段值,第一行,第二行)
            sortName:'',//提供可自定义的排序名称,而不是标题中的默认排序名称或列的字段名称
            cellStyle:function(value,row,index,field){},//单元格样式格式化函数 支持classs和css
            searchable:true,//设置为true以搜索此列的数据。
            searchFormatter:true,//设置为true以搜索使用格式化数据
            escape:false,//转义字符串以插入HTML,替换 &, <, >, “, `, and ‘ 字符。
            showSelectTitle:false,//设置为true以使用'radio'或'singleSelect''复选框'选项显示列的标题。
        }

    ]
});
var operateEvents = {
    /* 'click .like' 是类名?*/
    'click .like': function (e, value, row, index) {}
}

 

bootstrapTable   

bootstraptable文档2

中文文档

模态框

require.js

require.js作为基本的js来启动所有的js  data-main属性指向了一个启动脚本加载过程的文件(一般和require文件同目录) 

<script src="/assets/js/require.js" data-main="/assets/js/require-backend.js?v=1551577968"></script>

然后在 data-main指向的js文件中定义模板加载选项  注意data-main里定义加载的文件是异步的哦,如果用了require.js那么就不要在之外定义对require.js里加载的文件有依赖的js

require使用分两步;   基本的require例子

1、define()定义模块(必须返回个对象)

2、调用模块  require(function(){}) 

//全局配置
require.config({
    // 根路径设置,paths下面全部都是根据baseUrl的路径去设置
    baseUrl:'./js/',//显式的定义baseUrl;不显式定义的情况下默认是和require.js同一个目录如果定义了data-main则以data-main的路径(path以/开头、以.js结尾、含有https等协议时不会使用baseUrl?)
    
    paths:{//显式的映射哪些不是在baseUrl目录路径的文件
            // 引入jQuery.js
           jquery:'plugin/jquery',
           // 引入bootstrap.js
           bootstrap:'plugin/bootstrap',
           //引入其他的js
           //custom:'cunstom'
    },
    shim:{//为那些没有使用define()来声明依赖关系 想要实际加载指或者涉及的模块仍然需要一个常规的require、define调用,设置shim本身不会触发代码的加载
        bootstrap:{
            //deps定义依赖的,这里的bootstrap依赖jquery
            deps:["jquery"],
            exports:'该依赖没有加载成功输出这段'或者这里也可以是个函数                
        }
    },
     //map 对于给定的模块前缀,使用一个不同的模块ID来加载该模块  
      该特性仅适用于那些调用了define()并将其注册为匿名模块的真正AMD模块脚本。并且,请在map配置中仅使用绝对模块ID,“../some/thing”之类的相对ID不能工作。

      另外在map中支持“*”,意思是“对于所有的模块加载,使用本map配置”。如果还有更细化的map配置,会优先于“*”配置

     //当“some/newmodule”调用了“require('foo')”,它将获取到foo1.2.js
     //而当“some/oldmodule”调用“`require('foo')”时它将获取到foo1.0.js。
     //当调用其它时将获取到fool1.1.js
     foo1.0.js
     foo1.1.js
     foo1.2.js
     some/
         newmodule.js
         oldmodule.js

    map: {
        '*': {
            'foo': 'foo1.1'
        },
        'some/oldmodule': {
            'foo': 'foo1.2'
        },
        'some/oldmodule': {
            'foo': 'foo1.0'
        }
    }

});

urlArgs:RequireJS获取资源时附加在URL后面的额外的query参数。作为浏览器或服务器未正确配置时的“cache bust”手段很有用。使用cache bust配置的一个示例:

urlArgs: "bust=" +  (new Date()).getTime()

packages:从CommonJS包(package)中加载模块。参见从包中加载模块。

include:xx

paths:xx

shim:xx

baseUrl:xx

map:xx

waitSeconds:命名一个加载上下文。这允许require.js在同一页面上加载模块的多个版本,如果每个顶层require调用都指定了一个唯一的上下文字符串。想要正确地使用,请参考多版本支持一节

charset:xx

config:常常需要将配置信息传给一个模块。这些配置往往是application级别的信息,需要一个手段将它们向下传递给模块。在RequireJS中,基于requirejs.config()的config配置项来实现。要获取这些信息的模块可以加载特殊的依赖“module”,并调用module.config()

nodeIdCompat: 在放弃加载一个脚本之前等待的秒数。设为0禁用等待超时。默认为7秒。

context: 指定要加载的一个依赖数组。当将require设置为一个config object在加载require.js之前使用时很有用。一旦require.js被定义,这些依赖就已加载。使用deps就像调用require([]),但它在loader处理配置完毕之后就立即生效。它并不阻塞其他的require()调用,它仅是指定某些模块作为config块的一部分而异步加载的手段而已。

deps: 指定要加载的一个依赖数组。当将require设置为一个config object在加载require.js之前使用时很有用。一旦require.js被定义,这些依赖就已加载。使用deps就像调用require([]),但它在loader处理配置完毕之后就立即生效。它并不阻塞其他的require()调用,它仅是指定某些模块作为config块的一部分而异步加载的手段而已。

callback: 在deps加载完毕后执行的函数。当将require设置为一个config object在加载require.js之前使用时很有用,其作为配置的deps数组加载完毕后为require指定的函数。

enforceDefine: 如果设置为true,则当一个脚本不是通过define()定义且不具备可供检查的shim导出字串值时,就会抛出错误。参考在IE中捕获加载错误一节。

xhtml: 如果设置为true,则使用document.createElementNS()去创建script元素。

使用:

1、

require(
    ['jquery', 'bootstrap'], 
    function ($, undefined) {
           
    }
);

 

2、定义模块:具有作用域来避免全局名称空间污染

简单定义:

define({
    color: "black",
    size: "unisize"
});

函数式定义:

define(function () {
    //Do setup work here

    return {
        color: "black",
        size: "unisize"
    }
});

存在依赖的函数式定义:

模块函数以参数"cart"及"inventory"使用这两个以"./cart"及"./inventory"名称指定的模块。在这两个模块加载完毕之前,模块函数不会被调用。

严重不鼓励模块定义全局变量。遵循此处的定义模式,可以使得同一模块的不同版本并存于同一个页面上(参见 高级用法 )。另外,函参的顺序应与依赖顺序保存一致。

返回的object定义了"my/shirt"模块。这种定义模式下,"my/shirt"不作为一个全局变量而存在。

// my/shirt.js现在有一些依赖项,cart和inventory
// 假设他们与shirt.js在同一目录中的模块
define(["./cart", "./inventory"], function(cart, inventory) {
        //返回一个对象来定义"my/shirt"模块。
        return {
            color: "blue",
            size: "large",
            addToCart: function() {
                inventory.decrement(this);
                cart.add(this);
            }
        }
    }
);

将模块定义为一个函数

// foo/title.js中的模块定义。 它使用之前的my/cart 和my/inventory模块,
//但由于foo/title.js与"my" 模块位于不同的目录中,因此它使用模块依赖项名称中的"my" 来查找它们。 
//名称的"my" 部分可以映射到任何目录,但默认情况下,它被假定相邻"foo"目录。
define(["my/cart", "my/inventory"],
    function(cart, inventory) {
        //返回一个函数用来定义"foo/title".
        //它获取或者设置 window title.
        return function(title) {
            return title ? (window.title = title) :
                   inventory.storeName + ' ' + cart.name;
        }
    }
);

定义一个命名模块

这些常由优化工具生成。你也可以自己显式指定模块名称,但这使模块更不具备移植性——就是说若你将文件移动到其他目录下,你就得重命名。一般最好避免对模块硬编码,而是交给优化工具去生成。优化工具需要生成模块名以将多个模块打成一个包,加快到浏览器的载人速度。

    //明确地定义 "foo/title"模块:
    define("foo/title",
        ["my/cart", "my/inventory"],
        function(cart, inventory) {
            //Define foo/title object in here.
       }
    );

当定义的模块依赖太多的模块时

如:

//如:
define(
    ['dep1', 'dep2', 'dep3', 'dep4', 'dep5', 'dep6', 'dep7', 'dep8'],
    function(dep1,   dep2,   dep3,   dep4,   dep5,   dep6,   dep7,   dep8){
        ...
    }
);

//可以简化成这样
define(
    function (require) {
        var dep1 = require('dep1'),
            dep2 = require('dep2'),
            dep3 = require('dep3'),
            dep4 = require('dep4'),
            dep5 = require('dep5'),
            dep6 = require('dep6'),
            dep7 = require('dep7'),
            dep8 = require('dep8');

            ...
    }

});

 

 

 

注意:

一个文件一个模块

为了能在define()内部使用require的调用可以将require作一个依赖注入到模块中

生成与相对于模块的url

 

实例:

文件:

 

<script src="./require.js" data-main="main.js" type="text/javascript" defer async="true"></script>    

 

全局配置文件main.js:

 /*全局配置*/
 require.config({
     baseUrl:'./',
     paths:{
         layer:"plugin/layer",
         jquery:["https://cdn.bootcss.com/jquery/3.3.1/jquery","plugin/jquery"],//可配置多个地址第一个加载不上加载第二个
         bootstrap:"https://cdn.bootcss.com/bootstrap/3.3.5/js/bootstrap.min",
         custom1:"js/custom1.0",
         custom2:"js/custom1.2",//custom1.2.js
         math:"js/math",//math.js
         datatable:"datatable",//和baseUrl同一文件下无需在这指定都行(可省略)
     },
     shim:{
         'datatable':{//这个键名为要是载入的目标文件的文件名,不能随便命名。
             exports: '_' //exports的值为datatable.js提供的 对外接口的名称??不理解  在其他模块require引入时可以引用它
         },
         'datatables':{
             'init':function(){
                 return{
          sayHi: datatable,//键可以随便取名(定义数据的键),值必须和datatables.js里的变量名一致
          sayHello: datatableDemo,
          sayname: name,
          sayLike: like,
                 }
             },
             'deps':['jquery','bootstrap'],//设置的依赖只datatable在jquery和bootstrap加载完毕后才会加载
             //如果木有init这些参数我们可以简化依赖设置 例如 'datatables':['jquery','bootstrap'] 
             //z注意bootstrap是依赖jqury的所以下面必须填上'bootstrap':['jquery'],
         },
         'layui':{

         },
         'bootstrap':['jquery'],

     }

 });

require(['math'], function (math){
    //math:为math.js return回来的数据 {add: ƒ, mathAdd: ƒ, controller: {…}}
    console.log(math.add('1   ',1));
    console.log(math.controller);
});

模块文件math.js

//不依赖其他模块
//define(function (){
//define([],function (){
//依赖其他模块则第一个参数为数组值为依赖的模块(这里依赖jquey和layui还有datatable),
//jqury和layui在main.js显式指定了位置,datatable.js没有在paths里没有指定那么他的路径会默认在baseUrl
define(['jquery','layer','datatable','datatables'],function ($,layer,_,tables){    
    var mathAdd = function (x,y){
    
        console.log(datatable);//这里得到datatable是undefined,非规范化的模块我们需要定义在shim中
        console.log(_);//??
        console.log(tables);


        return parseInt($.trim(x))+parseInt($.trim(y));
    };
    var updateData=function(){
        return '需要的代码';
    };

    var controller={
        sex:'男',
        params:{
            id:'1',
            name:'tom',
            phone:13132613871
        },
        index:function(){

        },
        add:updateData,
        eidt:function(){

        }
    };

    return {
        add: mathAdd,
        mathAdd: mathAdd,
        controller:controller
    };
});

非规范化模块

datatable。js

var datatable={

    showRow:function(index){
        return idnex;
    }
};

datatable。js

/*非规范的模块有许多变量对象等情况*/
var datatable={

    showRow:function(index){
        return idnex;
    }
};

function datatableDemo(){
    return 'demo';
}
var name='tom';
var like=['sing','jump','drink'];

 

 

 

 

 

 

 

 

 

 

 

生成的模板  两表字段 id、name、category_id(关联的多的字段)

add.html

<form id="add-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">

    <div class="form-group">
        <label class="control-label col-xs-12 col-sm-2">{:__('Name')}:</label>
        <div class="col-xs-12 col-sm-8">
            <input id="c-name" data-rule="required" class="form-control" name="row[name]" type="text">
        </div>
    </div>
    <div class="form-group layer-footer">
        <label class="control-label col-xs-12 col-sm-2"></label>
        <div class="col-xs-12 col-sm-8">
            <button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button><!--确定-->
            <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button><!--重置-->
        </div>
    </div>
</form>

index:

 

<div class="panel panel-default panel-intro">
    {:build_heading()}

    <div class="panel-body">
        <div id="myTabContent" class="tab-content">
            <div class="tab-pane fade active in" id="one">
                <div class="widget-body no-padding">
                    <div id="toolbar" class="toolbar">
                        <a href="javascript:;" class="btn btn-primary btn-refresh" title="{:__('Refresh')}" ><i class="fa fa-refresh"></i> </a>
                        <a href="javascript:;" class="btn btn-success btn-add {:$auth->check('demo/add')?'':'hide'}" title="{:__('Add')}" ><i class="fa fa-plus"></i> {:__('Add')}</a>
                        <a href="javascript:;" class="btn btn-success btn-edit btn-disabled disabled {:$auth->check('demo/edit')?'':'hide'}" title="{:__('Edit')}" ><i class="fa fa-pencil"></i> {:__('Edit')}</a>
                        <a href="javascript:;" class="btn btn-danger btn-del btn-disabled disabled {:$auth->check('demo/del')?'':'hide'}" title="{:__('Delete')}" ><i class="fa fa-trash"></i> {:__('Delete')}</a>
                        <a href="javascript:;" class="btn btn-danger btn-import {:$auth->check('demo/import')?'':'hide'}" title="{:__('Import')}" id="btn-import-file" data-url="ajax/upload" data-mimetype="csv,xls,xlsx" data-multiple="false"><i class="fa fa-upload"></i> {:__('Import')}</a>

                        <div class="dropdown btn-group {:$auth->check('demo/multi')?'':'hide'}">
                            <a class="btn btn-primary btn-more dropdown-toggle btn-disabled disabled" data-toggle="dropdown"><i class="fa fa-cog"></i> {:__('More')}</a>
                            <ul class="dropdown-menu text-left" role="menu">
                                <li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=normal"><i class="fa fa-eye"></i> {:__('Set to normal')}</a></li>
                                <li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=hidden"><i class="fa fa-eye-slash"></i> {:__('Set to hidden')}</a></li>
                            </ul>
                        </div>
                    </div>
                    <table id="table" class="table table-striped table-bordered table-hover table-nowrap"
                           data-operate-edit="{:$auth->check('demo/edit')}" 
                           data-operate-del="{:$auth->check('demo/del')}" 
                           width="100%">
                    </table>
                </div>
            </div>

        </div>
    </div>
</div>

edit.html

<form id="edit-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">

    <div class="form-group">
        <label class="control-label col-xs-12 col-sm-2">{:__('Name')}:</label>
        <div class="col-xs-12 col-sm-8">
            <input id="c-name" data-rule="required" class="form-control" name="row[name]" type="text" value="{$row.name}">
        </div>
    </div>
    <div class="form-group layer-footer">
        <label class="control-label col-xs-12 col-sm-2"></label>
        <div class="col-xs-12 col-sm-8">
            <button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
            <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
        </div>
    </div>
</form>

关联后的模板

add

<form id="add-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">

    <div class="form-group">
        <label class="control-label col-xs-12 col-sm-2">{:__('Name')}:</label>
        <div class="col-xs-12 col-sm-8">
            <input id="c-name" data-rule="required" class="form-control" name="row[name]" type="text">
        </div>
    </div>
    <div class="form-group">
        <label class="control-label col-xs-12 col-sm-2">{:__('Category_id')}:</label>
        <div class="col-xs-12 col-sm-8">
            <input id="c-category_id" data-rule="required" data-source="category/selectpage" data-params='{"custom[type]":"dash"}' class="form-control selectpage" name="row[category_id]" type="text" value="">
        </div>
    </div>
    <div class="form-group layer-footer">
        <label class="control-label col-xs-12 col-sm-2"></label>
        <div class="col-xs-12 col-sm-8">
            <button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
            <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
        </div>
    </div>
</form>

 

index:

<div class="panel panel-default panel-intro">
    {:build_heading()}

    <div class="panel-body">
        <div id="myTabContent" class="tab-content">
            <div class="tab-pane fade active in" id="one">
                <div class="widget-body no-padding">
                    <div id="toolbar" class="toolbar">
                        <a href="javascript:;" class="btn btn-primary btn-refresh" title="{:__('Refresh')}" ><i class="fa fa-refresh"></i> </a>
                        <a href="javascript:;" class="btn btn-success btn-add {:$auth->check('dash/add')?'':'hide'}" title="{:__('Add')}" ><i class="fa fa-plus"></i> {:__('Add')}</a>
                        <a href="javascript:;" class="btn btn-success btn-edit btn-disabled disabled {:$auth->check('dash/edit')?'':'hide'}" title="{:__('Edit')}" ><i class="fa fa-pencil"></i> {:__('Edit')}</a>
                        <a href="javascript:;" class="btn btn-danger btn-del btn-disabled disabled {:$auth->check('dash/del')?'':'hide'}" title="{:__('Delete')}" ><i class="fa fa-trash"></i> {:__('Delete')}</a>
                        <a href="javascript:;" class="btn btn-danger btn-import {:$auth->check('dash/import')?'':'hide'}" title="{:__('Import')}" id="btn-import-file" data-url="ajax/upload" data-mimetype="csv,xls,xlsx" data-multiple="false"><i class="fa fa-upload"></i> {:__('Import')}</a>

                        <div class="dropdown btn-group {:$auth->check('dash/multi')?'':'hide'}">
                            <a class="btn btn-primary btn-more dropdown-toggle btn-disabled disabled" data-toggle="dropdown"><i class="fa fa-cog"></i> {:__('More')}</a>
                            <ul class="dropdown-menu text-left" role="menu">
                                <li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=normal"><i class="fa fa-eye"></i> {:__('Set to normal')}</a></li>
                                <li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=hidden"><i class="fa fa-eye-slash"></i> {:__('Set to hidden')}</a></li>
                            </ul>
                        </div>
                    </div>
                    <table id="table" class="table table-striped table-bordered table-hover table-nowrap"
                           data-operate-edit="{:$auth->check('dash/edit')}" 
                           data-operate-del="{:$auth->check('dash/del')}" 
                           width="100%">
                    </table>
                </div>
            </div>

        </div>
    </div>
</div>

{:$auth->check('dash/add')?'':'hide'} 检查权限 无权限加hide类隐藏

 

edit.html

<form id="edit-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">

    <div class="form-group">
        <label class="control-label col-xs-12 col-sm-2">{:__('Name')}:</label>
        <div class="col-xs-12 col-sm-8">
            <input id="c-name" data-rule="required" class="form-control" name="row[name]" type="text" value="{$row.name}">
        </div>
    </div>
    <div class="form-group">
        <label class="control-label col-xs-12 col-sm-2">{:__('Category_id')}:</label>
        <div class="col-xs-12 col-sm-8">
            <input id="c-category_id" data-rule="required" data-source="category/selectpage" data-params='{"custom[type]":"dash"}' class="form-control selectpage" name="row[category_id]" type="text" value="{$row.category_id}">
        </div>
    </div>
    <div class="form-group layer-footer">
        <label class="control-label col-xs-12 col-sm-2"></label>
        <div class="col-xs-12 col-sm-8">
            <button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
            <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
        </div>
    </div>
</form>

 新增输出下拉列表的数据:

在_initialize方法里分配查出来的管理组变量给模板

 

edit模板

    <div class="form-group">
        <label class="control-label col-xs-12 col-sm-2">{:__('Group')}:</label>
        <div class="col-xs-12 col-sm-8">
            {:build_select('group[]', $groupdata, null, ['class'=>'form-control selectpicker', 'multiple'=>'', 'data-rule'=>'required'])}
        </div>
    </div>

模板的函数解析出来为:

 echo build_select('group[]', $groupdata, null, ['class'=>'form-control selectpicker', 'multiple'=>'', 'data-rule'=>'required']);

调用该函数生成一个下拉列表的html(第一个参数是name值,第二个参数是数组或者,分隔的字符串)

<select class="form-control selectpicker" multiple="" name="group[]" tabindex="-98">
    <option value="1"> 超级管理组</option>
    <option value="2">&nbsp;├ 二级管理组</option>
    <option value="3">&nbsp;&nbsp;├ 三级管理组</option>
    <option value="5">&nbsp;&nbsp;└ 三级管理组2</option>
    <option value="4">&nbsp;└ 二级管理组2</option>
</select>

 

common.php

if (!function_exists('build_select')) {

    /**
     * 生成下拉列表
     * @param string $name
     * @param mixed $options
     * @param mixed $selected
     * @param mixed $attr
     * @return string
     */
    function build_select($name, $options, $selected = [], $attr = [])
    {
        $options = is_array($options) ? $options : explode(',', $options);
        $selected = is_array($selected) ? $selected : explode(',', $selected);
        return Form::select($name, $options, $selected, $attr);
    }
}

 

posted @ 2019-02-25 10:44  虚无缥缈的云  阅读(3393)  评论(0编辑  收藏  举报