139 Star 1.1K Fork 351

Mr.Chung / EasyAdmin

 / 详情

主键名不是ID时前端列表问题

待办的
创建于  
2020-10-23 10:56

数据库表主键名不是ID,例如是username或email时前端列表页没法操作

评论 (1)

Gib神 创建了任务
Gib神 关联仓库设置为Mr.Chung/EasyAdmin
展开全部操作日志

可以修改curd trait和easy-admin.js里的一些地方达到要求
1:首先修改对应加载js的地方:比如我有一个轮播图表,主键为slider_id,那么对应js里可以加一行配置参数
文件位置:public/static/admin/js/你对应的加载的js

var init = {
        pk : 'slider_id',//这里
        table_elem: '#currentTable',
        table_render_id: 'currentTableRenderId',
        index_url: 'app.slider/index',
        ...
    };

然后在public/static/plugs/easy-admin.js里做改动(改动较多,请理解掌握)
2.在渲染按钮的地方,所有跟id有关的要改成pk,主要是edit和delete,自定义按钮的时候自定义一下filed即可不需要修改

  tool: function (data, option) {
                option.operate = option.operate || ['edit', 'delete'];
                var elem = option.init.table_elem || init.table_elem;
                var html = '';
                let pk = option.init.pk || 'id';//这里,改动的时候别忘了加默认值为id
                $.each(option.operate, function (i, item) {
                    if (typeof item === 'string') {
                        switch (item) {
                            case 'edit':
                                var operate = {
                                    class: 'layui-btn layui-btn-success layui-btn-xs',
                                    method: 'open',
                                    field: pk,//这里
                                    icon: '',
                                    text: '编辑',
                                    title: '编辑信息',
                                    auth: 'edit',
                                    url: option.init.edit_url,
                                    extend: ""
                                };
                                operate.url = admin.table.toolSpliceUrl(operate.url, operate.field, data);
                                if (admin.checkAuth(operate.auth, elem)) {
                                    html += admin.table.buildOperatHtml(operate);
                                }
                                break;
                            case 'delete':
                                var operate = {
                                    class: 'layui-btn layui-btn-danger layui-btn-xs',
                                    method: 'get',
                                    field: pk,//这里
                                    icon: '',
                                    text: '删除',
                                    title: '确定删除?',
                                    auth: 'delete',
                                    url: option.init.delete_url,
                                    extend: ""
                                };
                                operate.url = admin.table.toolSpliceUrl(operate.url, operate.field, data);
                                if (admin.checkAuth(operate.auth, elem)) {
                                    html += admin.table.buildOperatHtml(operate);
                                }
                                break;
                        }

                    } else if (typeof item === 'object') {
                        $.each(item, function (i, operate) {
                            operate.class = operate.class || '';
                            operate.icon = operate.icon || '';
                            operate.auth = operate.auth || '';
                            operate.url = operate.url || '';
                            operate.method = operate.method || 'open';
                            operate.field = operate.field || 'id';//这里原版就没问题,需要时传入你的主键名
                            operate.title = operate.title || operate.text;
                            operate.text = operate.text || operate.title;
                            operate.extend = operate.extend || '';
                            operate.url = admin.table.toolSpliceUrl(operate.url, operate.field, data, operate.to_field);
                            if (admin.checkAuth(operate.auth, elem)) {
                                html += admin.table.buildOperatHtml(operate);
                            }
                        });
                    }
                });
                return html;
            },

3.在选择数据删除的地方,要改主键为获取

 renderToolbar: function (data, elem, tableId, init) {
                data = data || [];
                var toolbarHtml = '';
                $.each(data, function (i, v) {
                    if (v === 'refresh') {
                        toolbarHtml += ' <button class="layui-btn layui-btn-sm layuimini-btn-primary" data-table-refresh="' + tableId + '"><i class="fa fa-refresh">刷新</i> </button>\n';
                    } else if (v === 'add') {
                        if (admin.checkAuth('add', elem)) {
                            toolbarHtml += '<button class="layui-btn layui-btn-normal layui-btn-sm" data-open="' + init.add_url + '" data-title="添加"><i class="fa fa-plus"></i> 添加</button>\n';
                        }
                    } else if (v === 'delete') {
                        if (admin.checkAuth('delete', elem)) {
                            let pk = init.pk || 'id';//这里很关键,一定要有
                            toolbarHtml += '<button class="layui-btn layui-btn-sm layui-btn-danger" data-pk="' + pk + '" data-url="' + init.delete_url + '" data-table-delete="' + tableId + '"><i class="fa fa-trash-o"></i> 删除</button>\n';//这里要加上data-pk=pk,不然渲染的时候没法读入
                        }
                    } else if (v === 'export') {
                        if (admin.checkAuth('export', elem)) {
                            toolbarHtml += '<button class="layui-btn layui-btn-sm layui-btn-success easyadmin-export-btn" data-url="' + init.export_url + '" data-table-export="' + tableId + '"><i class="fa fa-file-excel-o"></i> 导出</button>\n';
                        }
                    } else if (v === 'jsExport') {//这里我自己加载了一个前端导出,忽略就好
                        toolbarHtml += '<button class="layui-btn layui-btn-sm layui-btn-success jsExport" data-url="' + init.export_url + '"  data-table-jsExport="' + tableId + '"><i class="fa fa-file-excel-o"></i> 导出</button>\n';
                    } else if (typeof v === "object") {
                        $.each(v, function (ii, vv) {
                            vv.class = vv.class || '';
                            vv.icon = vv.icon || '';
                            vv.auth = vv.auth || '';
                            vv.url = vv.url || '';
                            vv.method = vv.method || 'open';
                            vv.title = vv.title || vv.text;
                            vv.text = vv.text || vv.title;
                            vv.extend = vv.extend || '';
                            vv.checkbox = vv.checkbox || false;
                            if (admin.checkAuth(vv.auth, elem)) {
                                toolbarHtml += admin.table.buildToolbarHtml(vv, tableId);
                            }
                        });
                    }
                });
                return '<div>' + toolbarHtml + '</div>';
            },

4.接上面,这里在绑定表格多删除的时候需要读取上面我们定义的data-pk属性来重新定义主键

// 数据表格多删除
            $('body').on('click', '[data-table-delete]', function () {
                var tableId = $(this).attr('data-table-delete'),
                url = $(this).attr('data-url');
                tableId = tableId || init.table_render_id;
                url = url !== undefined ? admin.url(url) : window.location.href;
                var checkStatus = table.checkStatus(tableId),
                    data = checkStatus.data;
                if (data.length <= 0) {
                    admin.msg.error('请勾选需要删除的数据');
                    return false;
                }
                var ids = [];
                let pk = $(this).attr('data-pk');//这里,读到我们再第3步里定义的属性
                $.each(data, function (i, v) {
                    ids.push(v[pk]);//别忘了修改这里v.id改成v[pk],因为表格数据里已经没有id这一列了
                });
                admin.msg.confirm('确定删除?', function () {
                    admin.request.post({
                        url: url,
                        data: {
                            id: ids//这里不用换,就还用id就好,这样后端curd的trait里也改动少
                        },
                    }, function (res) {
                        admin.msg.success(res.msg, function () {
                            table.reload(tableId);
                            setTimeout(function () {
                                element.init();
                            }, 300);
                        });
                    });
                });
                return false;
            });

5.listenEdit,同样修改id为pk

            listenEdit: function (tableInit, layFilter, tableId, modifyReload) {
                tableInit.modify_url = tableInit.modify_url || false;
                tableId = tableId || init.table_render_id;
                if (tableInit.modify_url !== false) {
                    table.on('edit(' + layFilter + ')', function (obj) {
                        let pk = tableInit.pk || 'id';//这里其实是读页面加载的同名js里的配置(在第1步里定义的)
                        var value = obj.value,
                            data = obj.data,
                            id = data[pk],//这里别忘了改,因为data里已经没有id的字段了,而是我们的主键名的字段
                            field = obj.field;
                        var _data = {
                            id: id,//这里就别换了,不然你还得去改curd trait,更麻烦
                            field: field,
                            value: value,
                        };
                        admin.request.post({
                            url: tableInit.modify_url,
                            prefix: true,
                            data: _data,
                        }, function (res) {
                            if (modifyReload) {
                                table.reload(tableId);
                            }
                        }, function (res) {
                            admin.msg.error(res.msg, function () {
                                table.reload(tableId);
                            });
                        }, function () {
                            table.reload(tableId);
                        });
                    });
                }
            },
        },

6.switch组件里要改一下,不然没法正常使用

        switch: function (data, option) {
                // console.log(data, option)
                var field = option.field;
                option.filter = option.filter || option.field || null;
                option.checked = option.checked || 1;
                option.tips = option.tips || '开|关';
                let pk = option.init.pk || 'id';//这里,option.init其实就是我们页面加载里的同名js的init配置(看步骤1)
                try {
                    var value = eval("data." + field);
                } catch (e) {
                    var value = undefined;
                }
                var checked = value === option.checked ? 'checked' : '';
                return laytpl('<input type="checkbox" name="' + option.field + '" value="' + data[pk] + '" lay-skin="switch" lay-text="' + option.tips + '" lay-filter="' + option.filter + '" ' + checked + ' >').render(data);//这里别忘了,拼接的时候用data[pk]而不是data.id
            },

7.app/admin/traits/Curd.php 要微调一下,其实就是把括号里必须传递的$id删掉,改为用input函数获取主键名的参数而不是固定id

 /**
     * @NodeAnotation(title="编辑")
     */
    public function edit()
    {
        $id = input("{$this->model->getPk()}");//这里
        $row = $this->model->find($id);
        empty($row) && $this->error('数据不存在');
        if ($this->request->isAjax()) {
            $post = $this->request->post();
            $rule = [];
            $this->validate($post, $rule);
            try {
                $save = $row->save($post);
            } catch (\Exception $e) {
                $this->error('保存失败');
            }
            $save ? $this->success('保存成功') : $this->error('保存失败');
        }
        $this->assign('row', $row);
        return $this->fetch();
    }

    /**
     * @NodeAnotation(title="删除")
     */
    public function delete()
    {
        $id = input("{$this->model->getPk()}");//这里
        $pk_name = $this->model->getPk();
        $row = $this->model->whereIn($pk_name, $id)->field([$pk_name])->select();
        $row->isEmpty() && $this->error('数据不存在');
        try {
            $save = $row->delete();
        } catch (\Exception $e) {
            $this->error('删除失败' . $this->model->getLastSql());
        }
        $save ? $this->success('删除成功') : $this->error('删除失败');
    }

    /**
     * @NodeAnotation(title="导出")
     */
    public function export()
    {
        list($page, $limit, $where) = $this->buildTableParams();
        $tableName = $this->model->getName();
        $tableName = CommonTool::humpToLine(lcfirst($tableName));
        $prefix = config('database.connections.mysql.prefix');
        $dbList = Db::query("show full columns from {$prefix}{$tableName}");
        $header = [];
        foreach ($dbList as $vo) {
            $comment = !empty($vo['comment']) ? $vo['comment'] : $vo['field'];
            if (!in_array($vo['field'], $this->noExportFields)) {
                $header[] = [$comment, $vo['field']];
            }
        }
        $order_key = $this->model->getPk();//这里
        $list = $this->model
            ->where($where)
            ->limit(100000)
            ->order($order_key, 'desc')
            ->select()
            ->toArray();
        $fileName = $this->exportName ?? time();
        return Excel::exportData($list, $header, $fileName, 'xlsx');
    }

到这里基本就解决了。。。希望大家先理解一下再改,改前备份,免得改错了追悔莫及。。。

登录 后才可以发表评论

状态
负责人
里程碑
Pull Requests
关联的 Pull Requests 被合并后可能会关闭此 issue
分支
开始日期   -   截止日期
-
置顶选项
优先级
参与者(2)
PHP
1
https://gitee.com/zhongshaofa/easyadmin.git
git@gitee.com:zhongshaofa/easyadmin.git
zhongshaofa
easyadmin
EasyAdmin

搜索帮助