声明:本站文章均为作者个人原创,图片均为实际截图。如有需要请收藏网站,禁止转载,谢谢配合!!!

1、显示/隐藏导出功能

require-table.js

showExport: true

2、导出时忽略列

exportOptions: {ignoreColumn: [0, 'operate', 'photos']}

3、设置弹窗高度

Fast.config.openArea = ['100%', '95%']

4、添加行内按钮(自定义列)

//自定义按钮
{field: 'id', title: "MD编辑", formatter: function (val, row, index){
      var str = 'MD编辑';
      return '<a title="MD编辑" href="/et?id='+ row.id +'"  class="btn btn-xs btn-primary btn-dialog">'+str+'</a>'
 }, operate: false},

5、添加行内按钮组别(操作列)

{
    field: 'buttons',
    width: "120px",
    title: __('按钮组'),
    table: table,
    events: Table.api.events.operate,
    buttons: [
        {
            name: 'detail',
            text:  '下级',
            title: '下级',
            classname: 'btn btn-xs btn-primary btn-dialog',
            icon: 'fa fa-list',
            url: 'user/level_graph',
            callback: function (data) {
            Layer.alert("接收到回传数据:" + JSON.stringify(data), {title: "回传数据"});
            },
            visible: function (row) {
                //返回true时按钮显示,返回false隐藏
                return true;
        },
    ]
},

6、页面使用vue

<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.9/vue.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>

<div id="app" style="margin-top: 10px; padding: 10px">

</div>

<script>
    new Vue({
        el: '#app',
        data: function (){
            return {
            }
        },
        created: function (){
            this.getList()
        },
        methods:{
           getList(){
               axios.post('/user/list', {

               }).then( (response) => {

               }).catch(function (error) {
                       console.log(error);
               });
           },
        }
    })
</script>

7、页面按钮绑定点击事件,使用ajax

diy: function () {
    $('.btn-save').bind('click', function (){
        Fast.api.ajax({
            url:'test',
            data:{
            'a': $('#a').val(),
            },
        },function (res){
        if (res.code == 1){
            window.location.reload()
        }
        });
    })
    Controller.api.bindevent();
},

8、审核通过、审核驳回下拉按钮组

javascript代码

{
    field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate,
    formatter: Table.api.formatter.operate,
    buttons: [
        {
            name: 'detail', text: '审核通过', icon: '', classname: 'btn btn-xs btn-success btn-pass',dropdown: '操作',
        },
        {
            name: 'detail', text: '审核不通过', icon: '', classname: 'btn btn-xs btn-success btn-reject',dropdown: '操作',
        },
        {
        name: 'addtabs',
        text: __('订单明细'),
        title: __('订单明细'),
        classname: 'btn btn-xs btn-warning btn-addtabs',
        url: 'order/index?id={ids}'
        }
    ]
}

// 为表格绑定事件
Table.api.bindevent(table);
table.on('post-body.bs.table', function(e, setting, json, xhr) {
    $('.btn-pass', this).on('click', function(e) {
        var row = table.bootstrapTable('getData')[$(this).data('row-index')]
        Layer.confirm('您确定通过此申请吗?', {icon: 3, title: '提示'}, function(index) {
            Fast.api.ajax({
            url: 'a/setStatus',
            data: {
                id: row.id,
                status: 1
            }
    }, function(data, ret) {
        table.bootstrapTable('refresh')
    })
        Layer.close(index)
    })
    })
$('.btn-reject', this).on('click', function(e) {
    var row = table.bootstrapTable('getData')[$(this).data('row-index')]
    var content = '<div class="form" style="padding: 5px;" xmlns="http://www.w3.org/1999/html"><div class="form-group"><label class="label-control col-xs-12 col-sm-12"></label><textarea class="form-control" id="reject-reason" rows="5" cols="30" placeholder="请填写拒绝理由"></textarea></div></div>';
    var index = Layer.open({
    type: 1,
    title: '拒绝通过',
    // area: ['350px', '230px'],
    content: content,
    btn: ['确定', '取消'],
    btn1: function() { //用户点击确定
        Fast.api.ajax({
        url: 'a/setStatus',
        data: {
            id: row.id,
            reject_reason: $("#reject-reason").val(),
            status: 2
        }
    }, function(ret, data) {
        Layer.close(index)
        table.bootstrapTable('refresh')
        return false //阻止默认事件
    }, function(ret, data) {
        Toastr.error(data.msg)
        return false
})
}
})
})
})

php代码

 public function setStatus()
    {
        $data = $this->request->param();

        $res = \app\admin\model\BuildPartner::where('id', $data['id'])->find();

        !$res && $this->error('不存在');

        if ($data['status'] == 2 && (!isset($data['reject_reason']) || empty($data['reject_reason']))) {
            $this->error('请填写拒绝理由');
        }

        $updateData = ['status' => $data['status'], 'handle_time' => time()];

        if (!empty($data['reject_reason'])) {
            $updateData = array_merge($updateData, ['reject_reason' => $data['reject_reason']]);
        }

        Db::startTrans();

        try {
            \app\admin\model\XXX::where('id', $data['id'])->update($updateData);
            //如果同意则
            if ($data['status'] == 1){

            }
            Db::commit();
        } catch (Exception $e) {
            Db::rollback();
            $this->error($e->getMessage());
        }

        $this->success('操作成功');
    }

9、列表页面渲染多个

使用场景:订单列表页面js文件会包含发货、退款等各种操作,比较复杂。如果想单独分离出来未支付订单、已发货订单、售后订单,可以公用index方法,操作如下:

//默认查看所有订单
index: function() {
  Controller.bootIndex('order/index')
},
//查看未支付订单
unpay: function() {
  Controller.bootIndex('order/unpay')
},
//查看已发货订单
hasSend: function() {
  Controller.bootIndex('order/hasSend')
},
//查看售后订单
after_sale: function() {
  Controller.bootIndex('order/after_sale')
},
//commonList即之前的index方法,以上都能公用下面的方法
commonList: function (url) {
        // 初始化表格参数配置
        Table.api.init({
        extend: {
        index_url: url + location.search,
        add_url: 'order/add',
        edit_url: 'order/edit',
        del_url: 'order/del',
        multi_url: 'order/multi',
        table: 'order',
        //...一大堆逻辑
},

10、使用定时任务

10.1、安装官方定时任务插件
10.2、运行crontab -e -u root,添加

* * * * * /usr/bin/php /www/yoursite/public/index.php /addons/crontab/autotask/index > /dev/null  2>&1 &

10.3、后台管理-常规管理-定时任务-添加计划任务
*/1 每一分钟执行一次

11、忘记密码,数据库重置密码为123456

password 541acf0cc702c085e411601e611ff2e4
halt umPKsI

12、列表页面工具栏新增时间筛选,ajax请求

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<script src="https://cdn.bootcss.com/moment.js/2.22.1/moment-with-locales.min.js"></script>
<script src="https://cdn.bootcss.com/bootstrap-datetimepicker/4.17.47/js/bootstrap-datetimepicker.min.js"></script>

<div id="toolbar" class="toolbar">
     <input id="c-start" style="display: inline-block;width: 150px" class="form-control" data-date-format="YYYY-MM-DD HH:mm:ss"  type="text" value="{$start}">
    <input id="c-end"  style="display: inline-block;width: 150px"  class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss"  type="text" value="{$end}">
    <a href="javascript:void(0);" onclick="exportSalesInfo()" class="btn btn-primary">导出汇总单</a>
    <a href="javascript:;" class="btn btn-success deliveryCgpOrderAll">一键发货</a>
</div>

<script>
$('#c-start').datetimepicker({
    locale: moment.locale('zh-CN')
});
$('#c-end').datetimepicker({
    locale: moment.locale('zh-CN')
});

function exportSalesInfo(){
    var start = $('#c-start').val();
    var end = $('#c-end').val();
    window.location.href = '/admin.php/order/exportSalesInfo?start=' + start + '&end=' + end;
}

function deliveryCgpOrderAll(){
    $.post('/admin.php/order/deliveryCgpOrderAll',{},function(res){});
}

</script>

13、配置跨域

13.1 接口新增初始化方法

public function _initialize()
{
    //方便本地调试(解决跨域问题)
    header('Access-Control-Allow-Origin: *');
    header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization");
    header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE');
    parent::_initialize();
}

13.2 注释掉跨域检测

application/common/controller/Api.php

 // check_cors_request();

14、放置静态常量

application/common/Constant.php 新建文件

namespace app\common;
/**
 * 常量
 */
class Constant {
    public static $userLevel = [
        0 => "普通用户",
        1 => "会员",
    ];
}

其他文件使用

use app\common\Constant;
$arr = Constant::$userLevel;

15、同一账号不能同时登录

fastadmin自带的是同一账号可以多处登录,即可以一个账号可以同时在线
可以在App\Common\Library\Auth中修改为一个账号只能同时在线一个
direct 方法中 增加 Token::clear($user->id);(大概320行)

     $this->_user = $user;
     Token::clear($user->id);
     $this->_token = Random::uuid();
     Token::set($this->_token, $user->id, $this->keeptime);

16、页面元素(输入框、按钮)绑定弹窗等相关事件

input button

$(document).on("click", ".btn-forgot", function () {
    var id = "resetpwdtpl";
    var content = Template(id, {});
    Layer.open({
        type: 1,
        title: __('Reset password'),
        area: ["450px", "355px"],
        content: content,
        success: function (layero) {
        Form.api.bindevent($("#resetpwd-form", layero), function (data) {
            Layer.closeAll();
            }
            );
        }
    });
});

//输入框
$(document).on("change", "input[name=type]", function () {
    var type = $(this).val();
    $("div.form-group[data-type]").addClass("hide");
    $("div.form-group[data-type='" + type + "']").removeClass("hide");
    $('#resetpwd-form').validator("setField", {
        captcha: "required;length(4);integer[+];remote(" + $(this).data("check-url") + ", event=resetpwd, " + type + ":#" + type + ")",
    });
    $(".btn-captcha").data("url", $(this).data("send-url")).data("type", type);
});

17、状态字段(toggle)

新增

    {:build_radios('row[enable]', [0 => '否', 1 => '是'], 1)}

编辑

    {:build_radios('row[enable]', [0 => '否', 1 => '是'], $row['enable'])}

列表(主键为id)

    {field: 'enable', title: __('Enable'), formatter: Table.api.formatter.toggle},

列表(主键非id)

    {field: 'enable', title: __('Enable'), formatter: function(val, row, index){
            if (val == 0){
                return '<a href="javascript:;" data-toggle="tooltip" title="" class="btn-change " data-index="0" data-id="'+ row.task_id +'" data-params="enable=1" data-original-title="点击切换"><i class="fa fa-toggle-on text-success text-success fa-flip-horizontal text-gray fa-2x"></i></a>';
            }else{
                return  '<a href="javascript:;" data-toggle="tooltip" title="" class="btn-change " data-index="1" data-id="'+ row.task_id +'" data-params="enable=0" data-original-title="点击切换"><i class="fa fa-toggle-on text-success text-success  fa-2x"></i></a>';
            }
         }},

18、status lable normal searchList flag

Table.api.formatter.status
Table.api.formatter.normal

      {field: 'item', title: __('Item'), searchList: {"1":"头部","2":"上衣"},formatter: Table.api.formatter.status},

19、全局字段

application/common/controller/Backend.php

此处注意,如果是常量类,则可以使用反射,获取所有静态属性

      $config = [
            'part'           => Constant::$part //注入常量
            //使用反射,获取所有静态属性
            'OrderConstant' => (new \ReflectionClass(OrderConstant::class))->getStaticProperties(),
       ];

使用 window.Config.part

      {field: 'item', title: __('Item'), searchList: window.Config.part, formatter:                     Table.api.formatter.status},

20、二维数组FieldList

数据源为json数组

<div class="form-group" id="consume-input">
        <label class="control-label col-xs-12 col-sm-2">{:__('Consume')}:</label>
        <div class="col-xs-12 col-sm-8">
            <dl class="fieldlist" data-name="row[consume]" data-template="testtpl">
                <dd>
                    <ins>道具</ins>
                    <ins>数量</ins>
                </dd>
                <dd>
                    <a href="javascript:;" class="btn btn-sm btn-success btn-append"><i class="fa fa-plus"></i> 追加</a>
                </dd>
                <textarea name="row[consume]" class="form-control hide" cols="30" rows="5">{$row.consume|htmlentities}</textarea>
            </dl>
            <!--定义模板-->
            <script type="text/html" id="testtpl">
                <dd class="form-inline">

                    <input type="text" name="row[<%=name%>][<%=index%>][ItemId]" class="form-control selectpage"  data-primary-key="item_id" data-source="ngc_items/synthetic_items_list" data-field="item_name" value="<%=row['ItemId']%>" size="10">
                    <input type="text" name="row[<%=name%>][<%=index%>][ConsumeNum]" class="form-control" value="<%=row['ConsumeNum']%>" size="30">
                    <span class="btn btn-sm btn-danger btn-remove"><i class="fa fa-times"></i></span> <span class="btn btn-sm btn-primary btn-dragsort"><i class="fa fa-arrows"></i></span>
                </dd>
            </script>

        </div>
    </div>

js

edit: function () {
    $(document).on("fa.event.appendfieldlist", ".btn-append", function(){
        Form.events.selectpage($("#consume-input"));
    });
    Controller.api.bindevent();
},

21、列表页增加tab标签页切换筛选过滤功能

index.html

 <div class="panel-heading">
        {:build_heading(null, false)}
        <ul class="nav nav-tabs">
            <li class="active"><a href="#all" data-toggle="tab">所有记录</a></li>
            {foreach $typeList as $index=>$vo}
            <li class="{$vo.active?'active':''}"><a href="#{$index}" data-toggle="tab" data-record_type="{$index}">{$vo}</a></li>
            {/foreach}
        </ul>
    </div>

js

$('.panel-heading a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
    var that = $(this)
    var options = table.bootstrapTable('getOptions');
        options.pageNumber = 1;
        options.queryParams = function (params){
        var filter = {}
        filter['record_type'] = that.data('record_type')
        params.filter = JSON.stringify(filter)
        return params
    }
    table.bootstrapTable('refresh', {})
    return false;
})