【Fastadmin】fastadmin后台默认分类列表视图和功能美化

目录

前言:

美化前:

美化后:

视图美化代码:

批量添加代码:


前言:


fastadmin是一款很好的快速开发php后台框架,也是博主在项目开发中使用最多的,但是项目自带的分类显示有些不尽人意,于是做了稍微改动,并做了部分字段删减

美化前:


美化前是这样的,并且没有折叠打开的功能,不同级别之间层次感不强。

美化后:


在彩蛋列表的基础上做了折叠打开的功能,并增加了不同级别的间隙以层次感

  • 可通过点击图标或者名字进行折叠和展开
  • 最后一个级别显示灰色字体,代表没有下级列表
  • 并增加了批量添加的功能

视图美化代码:


粗暴法直接复制即可,内容过多不再做详细解释,目标文件 category.js:

javascript 复制代码
define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function ($, undefined, Backend, Table, Form, Template) {

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

            var table = $("#table");

            // 初始化表格
            table.bootstrapTable({
                url: $.fn.bootstrapTable.defaults.extend.index_url,
                sortName: '',
                escape: false,
                columns: [
                    [
                        {field: 'id', title: __('Id')},
                        {field: 'name', title: __('Name'), align: 'left', formatter: Controller.api.formatter.name},
                        {field: 'flag', title: __('Flag'), formatter: Table.api.formatter.flag},
                        {field: 'weigh', title: __('Weigh')},
                        {field: 'status', title: __('Status'), operate: false, formatter: Table.api.formatter.status},
                        {
                            field: 'id',
                            title: '<a href="javascript:;" class="btn btn-success btn-xs btn-toggle" style="border-top:none;"><i class="fa fa-chevron-up"></i></a>',
                            operate: false,
                            formatter: Controller.api.formatter.subnode
                        },
                        {
                            field: 'operate',
                            title: __('Operate'),
                            table: table,
                            events: Table.api.events.operate,
                            formatter: Table.api.formatter.operate
                        }
                    ]
                ],
                pagination: false,
                search: false,
                commonSearch: false,
                rowAttributes: function (row, index) {
                    if (this.totalRows > 500) {
                        return row.pid == 0 ? {} : {style: "display:none"};
                    }
                    return row.haschild == 1 ? {} : {style: "display:none"};
                }
            });

            // 为表格绑定事件
            Table.api.bindevent(table);
            //绑定TAB事件
            $('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
                // var options = table.bootstrapTable(tableOptions);
                var typeStr = $(this).attr("href").replace('#', '');
                var options = table.bootstrapTable('getOptions');
                options.pageNumber = 1;
                options.queryParams = function (params) {
                    // params.filter = JSON.stringify({type: typeStr});
                    params.type = typeStr;

                    return params;
                };
                table.bootstrapTable('refresh', {});
                return false;

            });
            var btnSuccessEvent = function (data, ret) {
                if ($(this).hasClass("btn-change")) {
                    var index = $(this).data("index");
                    var row = Table.api.getrowbyindex(table, index);
                    table.bootstrapTable("updateRow", {index: index, row: row});
                } else if ($(this).hasClass("btn-delone")) {
                    if ($(this).closest("tr[data-index]").find("a.btn-node-sub.disabled").length > 0) {
                        $(this).closest("tr[data-index]").remove();
                    } else {
                        table.bootstrapTable('refresh');
                    }
                } else if ($(this).hasClass("btn-dragsort")) {
                    table.bootstrapTable('refresh');
                }
                Fast.api.refreshmenu();
                return false;
            };

            //表格内容渲染前
            table.on('pre-body.bs.table', function (e, data) {
                var options = table.bootstrapTable("getOptions");
                options.escape = true;
            });

            //当内容渲染完成后
            table.on('post-body.bs.table', function (e, data) {
                var options = table.bootstrapTable("getOptions");
                options.escape = false;

                //点击切换/排序/删除操作后刷新左侧菜单
                $(".btn-change[data-id],.btn-delone,.btn-dragsort").data("success", btnSuccessEvent);

            });

            //显示隐藏子节点
            $(document).on("click", ".btn-node-sub", function (e) {
                var status = $(this).data("shown") ? true : false;
                $("a.btn[data-pid='" + $(this).data("id") + "']").each(function () {
                    $(this).closest("tr").toggle(!status);
                });
                $(this).data("shown", !status);
                return false;
            });

            //批量删除后的回调
            $(".toolbar > .btn-del,.toolbar .btn-more~ul>li>a").data("success", function (e) {
                Fast.api.refreshmenu();
            });

            //展开隐藏一级
            $(document.body).on("click", ".btn-toggle", function (e) {
                $("a.btn[data-id][data-pid][data-pid!=0].disabled").closest("tr").hide();
                var that = this;
                var show = $("i", that).hasClass("fa-chevron-down");
                $("i", that).toggleClass("fa-chevron-down", !show);
                $("i", that).toggleClass("fa-chevron-up", show);
                $("a.btn[data-id][data-pid][data-pid!=0]").not('.disabled').closest("tr").toggle(show);
                $(".btn-node-sub[data-pid=0]").data("shown", show);
            });

            //展开隐藏全部
            $(document.body).on("click", ".btn-toggle-all", function (e) {
                var that = this;
                var show = $("i", that).hasClass("fa-plus");
                $("i", that).toggleClass("fa-plus", !show);
                $("i", that).toggleClass("fa-minus", show);
                $(".btn-node-sub.disabled").closest("tr").toggle(show);
                $(".btn-node-sub").data("shown", show);
            });
        },
        add: function () {
            Controller.api.bindevent();
        },
        edit: function () {
            Controller.api.bindevent();
        },
        api: {
            formatter: {
                name: function (value, row, index) {
                    value = value.toString().replace(/(&|&amp;)nbsp;/g, '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;');
                    if(row.haschild == 1){
                        value = '<a href="javascript:;" data-toggle="tooltip" data-id="' + row.id + '" data-pid="' + row.pid + '" class="'
                            + (row.haschild == 1 ? '' : 'text-muted disabled') + ' btn-node-sub">' + value + '</a>';
                    }else{
                        value = '<span class="text-muted">' + value + '<span>';
                    }
                    return row.status == 'hidden' ? "<span class='text-muted'>" + value + "</span>" : value;
                },

                subnode: function (value, row, index) {
                    return '<a href="javascript:;" data-toggle="tooltip" title="' + __('Toggle sub menu') + '" data-id="' + row.id + '" data-pid="' + row.pid + '" class="btn btn-xs '
                        + (row.haschild == 1 ? 'btn-success' : 'btn-default disabled') + ' btn-node-sub"><i class="fa fa-sitemap"></i></a>';
                }
            },
            bindevent: function () {

                Form.api.bindevent($("form[role=form]"), function (data) {
                    Fast.api.refreshmenu();
                });
            }
        }
    };
    return Controller;
});

批量添加代码:


html页面,目标文件add.html

html 复制代码
<div class="form-group">
    <label for="c-name" class="control-label col-xs-12 col-sm-2">{:__('Name')}:</label>
    <div class="col-xs-12 col-sm-8">
        <textarea id="c-name" data-rule="required" style="overflow-y: scroll;height: 300px;" class="form-control" name="row[name]" type="text" value="" placeholder="同时添加多个换行输入,如:
设计
开发
..."></textarea>
    </div>
</div>

后端代码:

php 复制代码
$params = $this->request->post('row/a');
// 分割字符换为数组,换行符分割
$lines = explode("\n", $params['name']);

// 过滤空行
$filteredLines = array_map(function ($value) {
    return trim($value);
}, $lines);

$filteredLines = array_filter($filteredLines);

foreach ($filteredLines as $line) {
    // 避免重复添加
    $find = $this->model->where(['name' => $line, 'pid' => $params['pid']])->find();
    if(empty($find)){
        $params['name'] = $line;
        $arr[] = $params;
    }
}
if(empty($arr)){
    $this->success('成功添加 0 条数据');
}
$result = $this->model->allowField(true)->saveAll($arr);

$this->success('成功添加 ' . $result . ' 条数据');
相关推荐
GISer_Jing2 小时前
前端面试通关:Cesium+Three+React优化+TypeScript实战+ECharts性能方案
前端·react.js·面试
落霞的思绪2 小时前
CSS复习
前端·css
咖啡の猫4 小时前
Shell脚本-for循环应用案例
前端·chrome
百万蹄蹄向前冲7 小时前
Trae分析Phaser.js游戏《洋葱头捡星星》
前端·游戏开发·trae
朝阳5817 小时前
在浏览器端使用 xml2js 遇到的报错及解决方法
前端
GIS之路7 小时前
GeoTools 读取影像元数据
前端
ssshooter8 小时前
VSCode 自带的 TS 版本可能跟项目TS 版本不一样
前端·面试·typescript
你的人类朋友8 小时前
【Node.js】什么是Node.js
javascript·后端·node.js
Jerry9 小时前
Jetpack Compose 中的状态
前端
dae bal9 小时前
关于RSA和AES加密
前端·vue.js