dcat admin后台框架 form 表单增加自定义按钮

一、业务场景描述:

     例如发布一条数据,数据有非常多的状态,常规使用下拉单选已无法满足后台操作者需求,需要加按钮,如:发布草稿,提交审核


二、代码实现:

 1. 在表单中,增加动态 JS 代码,初始化2个按钮(提交审核、发布草稿)。思路是为了区分点击的是哪个按钮,增加了 input 隐藏域,name值是draft_button。点击【发布草稿】时值是1,点击【提交审核】时值是0;以下是主要实现代码:

protected function form()
    {
        return Form::make(模型类), function (Form $form) {
            $form->display('id');
            
            //  ====重要代码开始 ====
            Admin::script(
                <<<JS
    // 获取现有的提交按钮
    var submitButton = document.querySelector('.btn.btn-primary.pull-right');

    if (submitButton) {
        // 修改提交按钮的文字
        submitButton.innerHTML = ' 提交审核';

        // 创建一个新的草稿按钮
        var newButton = document.createElement('button');
        newButton.type = 'submit';
        newButton.className = 'btn btn-success pull-right custom-button';
        newButton.innerHTML = ' 发布草稿';

        // 点击事件:草稿按钮
        newButton.addEventListener('click', function() {
            var hiddenInput = document.createElement('input');
            hiddenInput.type = 'hidden';
            hiddenInput.name = 'draft_button';
            hiddenInput.value = '1';
            document.querySelector('form').appendChild(hiddenInput);
        });

        // 点击事件:提交按钮
        submitButton.addEventListener('click', function() {
            var hiddenInput = document.createElement('input');
            hiddenInput.type = 'hidden';
            hiddenInput.name = 'draft_button';
            hiddenInput.value = '0';
            document.querySelector('form').appendChild(hiddenInput);
        });

        // 获取父容器
        var container = submitButton.parentNode;

        // 关键点:将草稿按钮添加到提交按钮的后面(DOM 顺序)
        // 由于 pull-right 的浮动特性,后添加的按钮会显示在左侧
        container.appendChild(newButton);

        // 添加间距(草稿按钮右侧留出 30px)
        newButton.style.marginRight = '40px';
    }
JS
);
 //  ====重要代码结束 ====
//下面代码忽略..

 2. 在提交表单时,通过提交表单回调事件,使用 $form->draft_button去获取,可以确定点击是哪个按钮,方便处理逻辑,主要代码如下:

// 提交表单回调
$form->saving(function (Form $form) {

    // 点击草稿按钮 draft_button = 1
    if ($form->draft_button) {
       // 对应处理逻辑
    }
    // 点击提交审核且没有选择任务状态
    if (is_null($form->task_status) && $form->draft_button == NumberService::ZERO) {
        // 对应处理逻辑
    }

});

3. 在这一步时,重新加载页面,可以看到出现了2个按钮,但问题是,例如新增页面会有字段必填校验,校验后!!! 2个按钮文字变得一样了。解决方式需要修改dcat admin框架的JS代码,位置在public/vendor/dcat-admin/dcat/js/dcat-app.js中,我是用的编辑器是phpstorm,进入文件后Ctrl + A全选代码,然后Ctrl + Alt + L将代码格式化。格式化代码的位置在 1167行,将1167 ~ 1176行代码替换成如下代码。


点击原始JS文件重写的修改如下:

$.fn.buttonLoading = function (t) {
    // 遍历当前 jQuery 对象中的每个按钮
    return this.each(function () {
        var n, r = $(this), o = r.attr("data-loading");
        if (!1 === t) {
            // 如果传入的参数为 false,表示需要恢复按钮状态
            if (o) {
                r.find(".waves-ripple").remove();
                r.removeClass("disabled btn-loading waves-effect")
                    .removeAttr("disabled")
                    .removeAttr("data-loading")
                    .html(r.find("." + o).html());
            }
        } else {
            // 如果按钮已经有 data-loading 属性,直接返回
            if (o) return;

            // 保存原始按钮内容
            n = r.html();
            // 生成唯一的 data-loading 类名
            o = "ld-" + e.helpers.random();

            // 默认加载动画
            var a = '',
                i = ["btn", "layui-layer-btn0", "layui-layer-btn1"];

            // 根据按钮的类名选择合适的加载动画
            for (var s in i) {
                if (r.hasClass(i[s])) {
                    a = W[0].replace("{color}", "currentColor").replace("{width}", "50px;height:11px;");
                    break; // 找到匹配的类后退出循环
                }
            }

            // 修改按钮状态
            r.addClass("disabled btn-loading")
                .attr("disabled", true)
                .attr("data-loading", o)
                .html('\n' + n + "\n" + a + "\n");
        }
    });
};


4. 页面重新刷新,发现使用正常。