前言
开发的项目使用的是ruyi框架,需要bootstraptable的可编辑功能,文本框下拉框之类的还好说,x-editable中自带的日期控件确实挺难看的,项目经理希望日期风格保持一致,都使用layui.laydate
渲染生成的样式的风格
前端技术垃圾,网上搜索一下,发现有替换插件的方法,移植之后bug有很多,根本无法使用,无奈只能自己丰衣足食,折腾很久,终于做的完美无缺,以此记录探索过程。
先看看效果如何
bootstrap editable 集成ruoyi 日期控件 效果视频
不说废话直接上代码
table部分
{
field: 'rectifyFinishDate',
title: '完成时间',
formatter: function (value,row,index) {
var actions = [];
if(value == null || value == undefined || value == '' || value == '请填写'){
actions.push('<a href="javascript:void(0)" style="border-bottom: dashed 1px #0088cc;width: 80px;color: gray;" data-name="rectifyFinishDate" class="asdfa" _index="'+ index +'" _tableId="'+ tableId +'">请填写<a/>');
}else{
actions.push('<a href="javascript:void(0)" style="border-bottom: dashed 1px #0088cc;" data-name="rectifyFinishDate" class="asdfa" _index="'+ index +'" _tableId="'+ tableId +'" value="'+ value +'" style="width: 80px;">'+ value +'<a/>');
}
return actions.join('')
}
},
需要手动调用渲染日期控件,一定要用定时器延迟渲染,这个我不知道怎么回事,不然会渲染不上,点击弹不出日期框
var testDate = function () {
setTimeout(function(){
$(".asdfa").each(function(index,item){
//日期时间选择器
layui.use('laydate', function () {
var laydate = layui.laydate;
laydate.render({
elem: item
, type: 'date'
, theme: 'molv'
});
});
})
$("[data-toggle='tooltip']").tooltip();
},200)
}
testDate();
前面的操作都很简单,点击就能弹出日期框,也可以选择日期,问题在于当点击保存或者进行其他操作导致表格重新渲染,刚才选的日期又会还原,因此,关键点我们要让选的日期保存到表格中去,这个saveDate十分关键,因为不知道点击的是哪一行的日期控件,只好通过class循环全部修改保存,代码如下:
var saveDate = function(){
$(".asdfa").each(function(index,item){
$('#' + $(item).attr("_tableid")).bootstrapTable('updateCell', {
index: $(item).attr("_index"),
field: 'rectifyFinishDate',
value: $(item).html()
})
})
}
laydate.js源码修改
目前为止已经完成99%了,就差1%,搞了很久,一个问题就是,当第一次点击日期选择框时,由于渲染的问题,它会自动帮你渲染为当前日期,这个特别烦,因为我那个字段并不是必填项,每次点击其他地方导致日期控件会渲染一个初始值在去删掉很麻烦,因此,我把改了laydate.js的源码,让它不会检查并初始化默认值,查看源码,主要是T.prototype.checkDate = function(e) {.....};
函数的作用,大概在600行左右,修改代码如下,原来的代码我就不展示了,只放上修改后的,我放个图片标注一下修改的地方:
T.prototype.systemDate = function(e) {
var t = e || new Date;
return {
year: t.getFullYear(),
month: t.getMonth(),
date: t.getDate(),
hours: e ? e.getHours() : 0,
minutes: e ? e.getMinutes() : 0,
seconds: e ? e.getSeconds() : 0
}
}
,
T.prototype.checkDate = function(e) {
var t, a, i = this, r = (new Date,
i.config), o = r.dateTime = r.dateTime || i.systemDate(), s = i.bindElem || r.elem[0], l = (i.isInput(s) ? "val" : "html",
i.isInput(s) ? s.value : "static" === r.position ? "" : s.innerHTML), c = function(e) {
e.year > d[1] && (e.year = d[1],
a = !0),
e.month > 11 && (e.month = 11,
a = !0),
e.hours > 23 && (e.hours = 0,
a = !0),
e.minutes > 59 && (e.minutes = 0,
e.hours++,
a = !0),
e.seconds > 59 && (e.seconds = 0,
e.minutes++,
a = !0),
t = n.getEndDate(e.month + 1, e.year),
e.date > t && (e.date = t,
a = !0)
}, m = function(e, t, n) {
var o = ["startTime", "endTime"];
t = (t.match(i.EXP_SPLIT) || []).slice(1),
n = n || 0,
r.range && (i[o[n]] = i[o[n]] || {}),
w.each(i.format, function(s, l) {
var c = parseFloat(t[s]);
t[s].length < l.length && (a = !0),
/yyyy|y/.test(l) ? (c < d[0] && (c = d[0],
a = !0),
e.year = c) : /MM|M/.test(l) ? (c < 1 && (c = 1,
a = !0),
e.month = c - 1) : /dd|d/.test(l) ? (c < 1 && (c = 1,
a = !0),
e.date = c) : /HH|H/.test(l) ? (c < 1 && (c = 0,
a = !0),
e.hours = c,
r.range && (i[o[n]].hours = c)) : /mm|m/.test(l) ? (c < 1 && (c = 0,
a = !0),
e.minutes = c,
r.range && (i[o[n]].minutes = c)) : /ss|s/.test(l) && (c < 1 && (c = 0,
a = !0),
e.seconds = c,
r.range && (i[o[n]].seconds = c))
}),
c(e)
};
return "limit" === e ? (c(o),
i) : (l = l || r.value,
"string" == typeof l && (l = l.replace(/\s+/g, " ").replace(/^\s|\s$/g, "")),
i.startState && !i.endState && (delete i.startState,
i.endState = !0),
"string" == typeof l && l ? i.EXP_IF.test(l) ? r.range ? (l = l.split(" " + r.range + " "),
i.startDate = i.startDate || i.systemDate(),
i.endDate = i.endDate || i.systemDate(),
r.dateTime = w.extend({}, i.startDate),
w.each([i.startDate, i.endDate], function(e, t) {
m(t, l[e], e)
})) : m(o, l) : (a = !0) : l && l.constructor === Date ? r.dateTime = i.systemDate(l) : (
r.dateTime = i.systemDate(),
delete i.startState,
delete i.endState,
delete i.startDate,
delete i.endDate,
delete i.startTime,
delete i.endTime),
c(o),
a && l && i.setValue("请填写"),
e && e(),
i)
}
除此之外,还有日期控件下有三个按钮,***清空,现在,确定,***,还有点击具体某一天的那个事件,这四个地方的函数也要做一下修改,通过便看边调试,我找到了修改的地方,代码如下:
三个按钮的函数
在1080行左右
T.prototype.tool = function(e, t) {
var n = this
, a = n.config
, i = a.dateTime
, r = "static" === a.position
, o = {
datetime: function() {
w(e).hasClass(s) || (n.list("time", 0),
a.range && n.list("time", 1),
w(e).attr("lay-type", "date").html(n.lang().dateTips))
},
date: function() {
n.closeList(),
w(e).attr("lay-type", "datetime").html(n.lang().timeTips)
},
clear: function() {
n.setValue("请填写").remove(),
r && (w.extend(i, n.firstDate),
n.calendar()),
a.range && (delete n.startState,
delete n.endState,
delete n.endDate,
delete n.startTime,
delete n.endTime),
dateTask();
n.done(["", {}, {}])
},
now: function() {
var e = new Date;
w.extend(i, n.systemDate(), {
hours: e.getHours(),
minutes: e.getMinutes(),
seconds: e.getSeconds()
}),
n.setValue(n.parse()).remove(),
r && n.calendar(),
dateTask();
n.done()
},
confirm: function() {
if (a.range) {
if (!n.endDate)
return n.hint("请先选择日期范围");
if (w(e).hasClass(s))
return n.hint("time" === a.type ? l.replace(/日期/g, "时间") : l)
} else if (w(e).hasClass(s))
return n.hint("不在有效日期或时间范围内");
n.done(),
n.setValue(n.parse()).remove()
dateTask();
}
};
o[t] && o[t]()
}
我只修改了一个地方,就是按钮事件里结束的时候调了一个函数,dateTask(),这个函数的代码如下:
var dateTask = function(){
saveDate();
$("#bootstrap-table-yjya-assess").bootstrapTable('load',$("#bootstrap-table-yjya-assess").bootstrapTable('getData'));
$("#bootstrap-table-yjya-assess").bootstrapTable('load',$("#bootstrap-table-yjyl-assess").bootstrapTable('getData'));
testDate();
}
dateTask函数里分别又调用了saveDate()保存数据,bootstrapTable的load方法加载数据(目的是让table页面显示的样式重新渲染出来),最后又调了testDate()方法重新渲染日期控件(不调这个方法,日期控件就会失效,点击不会弹出);clear那里我还修改了一个地方,clear的时候设置了一个值“请填写”(n.setValue("请填写").remove(),
),这个是项目的要求,没有值的时候要显示“请填写”
点击具体某一天的那个事件
在1000行左右,代码如下:
T.prototype.choose = function(e) {
var t = this
, n = t.config
, a = n.dateTime
, i = w(t.elem).find("td")
, r = e.attr("lay-ymd").split("-")
, l = function(e) {
new Date;
e && w.extend(a, r),
n.range && (t.startDate ? w.extend(t.startDate, r) : t.startDate = w.extend({}, r, t.startTime),
t.startYMD = r)
};
if (r = {
year: 0 | r[0],
month: (0 | r[1]) - 1,
date: 0 | r[2]
},
!e.hasClass(s))
if (n.range) {
if (w.each(["startTime", "endTime"], function(e, n) {
t[n] = t[n] || {
hours: 0,
minutes: 0,
seconds: 0
}
}),
t.endState)
l(),
delete t.endState,
delete t.endDate,
t.startState = !0,
i.removeClass(o + " " + u),
e.addClass(o);
else if (t.startState) {
if (e.addClass(o),
t.endDate ? w.extend(t.endDate, r) : t.endDate = w.extend({}, r, t.endTime),
t.newDate(r).getTime() < t.newDate(t.startYMD).getTime()) {
var d = w.extend({}, t.endDate, {
hours: t.startDate.hours,
minutes: t.startDate.minutes,
seconds: t.startDate.seconds
});
w.extend(t.endDate, t.startDate, {
hours: t.endDate.hours,
minutes: t.endDate.minutes,
seconds: t.endDate.seconds
}),
t.startDate = d
}
n.showBottom || t.done(),
t.stampRange(),
t.endState = !0,
t.done(null, "change")
} else
e.addClass(o),
l(),
t.startState = !0;
w(t.footer).find(g)[t.endDate ? "removeClass" : "addClass"](s)
} else
"static" === n.position ? (l(!0),
t.calendar().done().done(null, "change")) : "date" === n.type ? (l(!0),
t.setValue(t.parse()).remove().done()) : "datetime" === n.type && (l(!0),
t.calendar().done(null, "change"))
dateTask();
}
经过测试,也是在最下面调一下dateTask()
就行了
至此,laydate已经可以完美嵌入x-editable中了,经过测试,暂时没有发现bug;
最后我在放上laydate.js和我自己写的代码供大家参考
链接: https://pan.baidu.com/s/1Y8M5I3CuzpKMU7jK6KI1IQ 提取码: nu8y