一、业务场景描述:
例如发布一条数据,数据有非常多的状态,常规使用下拉单选已无法满足后台操作者需求,需要加按钮,如:发布草稿,提交审核
二、代码实现:
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. 页面重新刷新,发现使用正常。