layui.define(['layer', 'form', 'jquery', 'table', 'laydate'], function(exports) {
/* 这些方法建议单独存放于一个JS中,此处为了整体代码的简洁性,不单独存放 */
window.isBlank = (str) => {
return str === undefined || str === null || /^\s*$/.test(str)
}
window.isNotBlank = (str) => {
return !isBlank(str)
}
window.defaultString = function(str, defaultStr) {
return isBlank(str) ? (defaultStr ? defaultStr : "") : str
}
window.formatTime = (millsecond) => {
// 将毫秒格式化为 可读的 字符串
if (!Number.isInteger(millsecond)) {
return millsecond
}
let second = millsecond / 1000
if (second < 60) {
return (second) + "秒"
} else if (second / 60 < 60) {
return Math.floor((second / 60)) + "分" + Math.floor((second % 60)) + "秒"
} else if (second / 60 / 60 < 24) {
return Math.floor((second / 60 / 60)) + "时" + Math.floor((second / 60 % 60)) + "分" + Math.floor((second % 60)) + "秒"
} else {
return Math.floor((second / 86400)) + "天" + Math.floor((second % 86400 / 60 / 60)) + "时" +
Math.floor((second % 86400 / 60 % 60)) + "分" + Math.floor((second % 60)) + "秒"
}
return millsecond
}
Date.prototype.format = function(fmt) {
let o = {
"M+": this.getMonth() + 1, //月份
"d+": this.getDate(), //日
"h+": this.getHours(), //小时
"m+": this.getMinutes(), //分
"s+": this.getSeconds(), //秒
"q+": Math.floor((this.getMonth() + 3) / 3), //季度
"S": this.getMilliseconds() //毫秒
};
fmt = fmt.replace(new RegExp("HH", 'g'), "hh")
if (/(y+)/.test(fmt)) {
fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
}
for (var k in o) {
if (new RegExp("(" + k + ")").test(fmt)) {
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
}
}
return fmt;
}
/**
* 将日期字符串从一种类型转换为另一种类型
* @param {string} dateStr
* @param {string} pattern
*/
function formatToAnotherPattern(dateStr, pattern) {
if (dateStr === undefined || dateStr === null || dateStr.trim() === "") {
return ""
}
if (pattern === undefined || pattern === null || pattern.trim() === "") {
return ""
}
return new Date(dateStr).format(pattern)
}
/**
* 增强layui table 功能
* 1、给表格数据增加默认属性,以实现工具栏重新渲染功能
* 2、当分页不启用时,将默认只显示10条 修改为显示所有
* 3、设置表格的默认分页参数
* 4、增加获取table实例的方法
* 5、增加 新增行功能,可指定位置
* 6、增加 渲染指定行、列方法
* 7、增加 获取表格所有行数据
* 8、增加 删除指定行
* 9、扩展表格加载耗时显示
* 10、内容超出设置
* 11、支持单元格单击事件
* 12、增强 当工具栏宽度不够时,弹出详情里面的按钮不能点击
* 13、增加 可编辑列的配置(增加字段:editConfig: { form: "input", verify: "required", placeholder: "必填",dict: ""} )
* 14、增加 扩展操作列表(增加字段
* extToolbar: ["excel","csv"],
* excel: {templateUrl: "", exportUrl: "" , importUrl: "",params: {},beforeHandler(obj){} }
* csv: {templateUrl: "", exportUrl: "" , importUrl: "",params: {},beforeHandler(obj){} }
* 15、获取 指定表格的指定列配置信息
* 16、增加 合并单元格方法
* 17、增强 当列表中某列为字典值时,自动设置 templet 函数 (为col 增加 dict 字段)
* 18、增强 当列表中某列开启日期格式化时,自动设置templet 函数(为col 增加字段:dateFormat: boolean || string,取值:true/false、yyyy-MM-dd hh:mm:ss)
* 19、增强 合计行数据自定义显示(为col 增加:totalRowFormatter(rows){return value})
* 20、设置列对齐默认为居中
*/
let $ = layui.$,
table = layui.table,
form = layui.form
if (layui && layui.table && !layui.table.$enhanced) {
let wait = ms => new Promise((r, j) => setTimeout(r, ms))
layui.table.config.cellToolbarName = "LAY_CELL_TOOLBAR"
layui.table.config.parseData = (res) => {
// 覆盖数据表格默认的数据转换,增加自定义字段,以实现更新指定行时可对列工具栏进行重新渲染,只对ajax访问时有效
res.data && res.data.constructor == Array && res.data.forEach(o => o[layui.table.config.cellToolbarName] = "just for update cell toolbar")
return res
}
let instanceMap = new Map()
let $render = layui.table.render
layui.table.render = (config) => {
let waitForInstance = (timeoutms) => new Promise((resolve, reject) => {
let check = () => {
if (layui.table.getInstance(config.id))
resolve()
else if ((timeoutms -= 100) < 0)
reject('timed out!')
else
setTimeout(check, 100)
}
setTimeout(check, 100)
})
config.request = config.request || {}
config.startTime = new Date().getTime()
if (!config.page) {
config.limit = Number.MAX_VALUE
config.request.pageName = 'currPage'
delete config.request.limitName
} else {
config.request.pageName = 'currPage'
config.request.limitName = 'pageSize'
}
if (config.page && !(config.limit || config.page.limit)) {
if (typeof config.page === "boolean") {
config.page = { limit: 30 }
} else {
config.page.limit = 30
}
}
config.data && config.data.constructor == Array && config.data.forEach(o => o[layui.table.config.cellToolbarName] = "just for update cell toolbar")
// 设置列表页字典、设置列对齐默认为居中
config.cols && config.cols.forEach(o => {
o.forEach(col => {
col.align = col.align || "center"
const dict = col.dict
if (!col.templet && isNotBlank(dict) && Array.isArray(dict)) {
col.templet = (item) => {
let result = ""
for (let i = 0; i < dict.length; i++) {
if (dict[i].value == item[col.field]) {
result = `${dict[i].label} `
}
}
return `
${result}
`
}
}
})
})
/**
* 设置可编辑列。
* editConfig: {form: "input", verify: "required", placeholder: "必填"}
* form 表单类型,值可以为:input、select
* verify。 表单验证,参考 layui form verify
* dict。字典类型,针对select适用
* placeholder
*/
config.cols && config.cols.forEach(o => {
o.forEach(col => {
if (!col.editConfig || col.templet) {
return
}
let editConfig = col.editConfig
let templateStr = null
if (editConfig.form === 'input') {
templateStr = ` `
col.templet = `${templateStr}
`
return
}
if (editConfig.form === 'color') {
templateStr = ` `
col.templet = `${templateStr}
`
return
}
// 必须通过 dom 模板的方式
let templateId = `${config.id}_${col.field}_tpl`
if (editConfig.form === 'select' && editConfig.dict) {
templateStr = `
` +
(defaultString(editConfig.verify).indexOf("required") != -1 ? "" : `${defaultString(editConfig.placeholder, "请选择")} `)
if (typeof editConfig.dict == "string") {
templateStr += `{{# $global.getDictDataList('${editConfig.dict}').forEach(function(o) { }}
{{o.label}}
{{# }) }}`
} else {
editConfig.dict.forEach(o => {
templateStr += `${o.label} `
})
}
templateStr += ` `
} else if (editConfig.form === 'checkbox') {
templateStr = ` `
}
let $templte = $(`#${templateId}`)
if ($templte.length == 0) {
layui.$("body").append(``)
}
col.templet = `#${templateId}`
return
})
})
/**
* 设置列的日期时间格式化,
* dateFormat: boolean || string
* dateFormat: true
* dateFormat: "yyyy-MM-dd hh:mm:ss"
*/
config.cols && config.cols.forEach(o => {
o.forEach(col => {
if (col.templet || !col.dateFormat || !col.field) {
return
}
let pattern = "yyyy-MM-dd"
if (typeof col.dateFormat == 'string') {
pattern = col.dateFormat
}
col.templet = function(d) {
return `${formatToAnotherPattern(d[col.field], pattern)}
`
}
})
})
config.overflow = config.overflow || { type: 'tips' }
let $done = config.done
config.done = (res, curr, count) => {
if (!config.id) {
return
}
// 去除可编辑表格,文本超出无省略号的问题
$(`div[lay-id='${config.id}'] .layui-table-body .layui-table-cell:not(:has(input))`).css("cssText", "overflow:hidden!important;")
$(`div[lay-id='${config.id}'] .layui-table-body .layui-table-cell:not(:has(div))`).css("cssText", "overflow:hidden!important;")
if (config.overflow) {
let overflowOptions = {
type: "tips",
minWidth: 300,
maxWidth: 300,
color: "white",
bgColor: "black"
}
$.extend(overflowOptions, config.overflow)
let layBody = $(`div[lay-id='${config.id}'] .layui-table-body`)
// let color = 'white', bgColor = 'black', minWidth = 300, maxWidth = 300
let { type, color, bgColor, minWidth, maxWidth } = overflowOptions
let tooltipIndex = null
layBody.off(['mouseenter', 'mouseleave'], 'td').on('mouseenter', 'td', function() {
let othis = $(this),
elemCell = othis.children('.layui-table-cell')
if (othis.data('off') || othis.data("field") === 'LAY_CELL_TOOLBAR') return;
if (othis.has('select').length != 0) return;
let outerWidth = othis.children('.layui-table-cell').outerWidth()
let layerWidth = (outerWidth < minWidth ? minWidth : (outerWidth > maxWidth ? maxWidth : outerWidth))
if (elemCell.prop('scrollWidth') > elemCell.outerWidth()) {
tooltipIndex = layer.tips('' + othis.text() + ' ', this, {
tips: [1, bgColor],
maxWidth: layerWidth,
time: 0
});
}
}).on('mouseleave', 'td', function() {
layer.close(tooltipIndex)
})
}
(async () => {
// 等待获取到实例
await waitForInstance(10 * 1000)
let ins = layui.table.getInstance(config.id)
if (!ins) {
$done && $done(res, curr, count)
return
}
let layTable = $(`div[lay-id='${ins.config.id}']`),
layBody = layTable.find(`.layui-table-body`),
layTotal = layTable.find(`.layui-table-total`)
// let time = new Date().getTime() - ins.config.startTime
// $(`div[lay-id='${config.id}'] .layui-table-page>div`).append($(`加载耗时:${formatTime(time)}
`))
if (ins.config.time) {
let time = ins.config.time
let elapsedTime = Number.parseInt(time.substring(0, time.indexOf(" ")))
layTable.find(`.layui-table-page>div`).append($(`加载耗时:${formatTime(elapsedTime)}
`))
}
if (ins.config.scrollTop && ins.config.data) {
layBody.scrollTop(ins.config.scrollTop)
delete ins.config.scrollTop
}
// 支持单元格单击事件
layBody.on("click", "td", function(event) {
let rows = layui.table.getRows(ins.config.id)
let rowIndex = $(this).parent().data("index")
let colIndex = $(this).index()
// let col = ins.config.cols.length == 1 ? ins.config.cols[0][colIndex] : ins.config.cols[1][colIndex]
// data-key="2-0-0" 2 代表cols有3组,0:代表第一组,0: 代表第一列
let col = layui.table.getColConfigByField(config.id, $(this).attr("data-field"))
if (!col) {
return;
}
// 复选框、单选框、索引列,不进行监听
if (["checkbox", "radio", "numbers"].includes(col.type)) {
return
}
layui.event.call(ins, 'table', "cell(" + ins.config.elem.attr("lay-filter") + ")", {
data: rows[rowIndex],
rowIndex: rowIndex,
colIndex: colIndex,
col: col
})
// event.stopPropagation()
})
/***** 给工具栏增加扩展按钮 开始 **/
$(document).on("click", function(e) {
$(".layui-table-custom-tool-panel").removeClass("layui-hide").addClass("layui-hide")
layui.stope(e)
})
if (config.extToolbar && Array.isArray(config.extToolbar) && !ins.config.$extToolbarInited) {
let $toolbar = $(`div[lay-id='${config.id}'] > .layui-table-tool .layui-table-tool-self`)
// 监听自定义bar点击事件,显示相应的panel,并组织事件传播
$toolbar.on("click", "*[custom-event]", function(e) {
layui.stope(e)
let layEvent = $(this).attr("custom-event")
if (!layEvent || !layEvent.startsWith("custom-")) {
return
}
let curIndex = $(this).index()
$(`[lay-id='${config.id}'] .layui-table-tool-self>div:not(:eq(${curIndex}))`).find(".layui-table-custom-tool-panel").not(".layui-hide").addClass("layui-hide")
$(this).find(".layui-table-custom-tool-panel").toggleClass("layui-hide")
})
let defaultToolbar = {
"excel": {
title: "EXCEL导入导出",
icon: "layui-icon layui-icon-export",
buttons: [{
type: "excel_template",
icon: "fa fa-download",
title: "EXCEL模板",
condition: config.excel && config.excel.templateUrl,
click: () => {
let loadIndex = top.layer.load(1, {
shade: [0.8, '#393D49'],
offset: [`${screen.availHeight / 2 - 50}px`, `${screen.availWidth / 2 - 50}px`]
})
$http.download(config.excel.templateUrl, instance.config.excel.params).finally(() => top.layer.close(loadIndex))
}
}, {
type: "excel_export",
icon: "fa fa-download",
title: "EXCEL导出",
condition: config.excel && config.excel.exportUrl,
click: () => {
let loadIndex = top.layer.load(1, {
shade: [0.8, '#393D49'],
offset: [`${screen.availHeight / 2 - 50}px`, `${screen.availWidth / 2 - 50}px`]
})
$http.download(config.excel.exportUrl, instance.config.excel.params).finally(() => top.layer.close(loadIndex))
}
}, {
type: "excel_import",
icon: "fa fa-upload",
title: "EXCEL导入",
condition: config.excel && config.excel.importUrl,
click: () => {
if (!layui.importExcel) {
layer.error("导入功能暂不可用,请检查导入组件是否加载")
return
}
layui.importExcel && layui.importExcel.render({
url: config.excel.importUrl,
title: config.title,
autoClose: true,
loading: true,
params: instance.config.excel.params,
success: (res) => {
if (res.data && res.data.successCount != 0) {
window.reloadTable && window.reloadTable()
}
}
})
}
}]
},
"csv": {
title: "CSV导入导出",
icon: "layui-icon layui-icon-export",
buttons: [{
type: "csv_export",
icon: "fa fa-download",
title: "CSV导出",
condition: config.csv && config.csv.exportUrl,
click: () => {
let loadIndex = top.layer.load(1, {
shade: [0.8, '#393D49'],
offset: [`${screen.availHeight / 2 - 50}px`, `${screen.availWidth / 2 - 50}px`]
})
$http.download(config.csv.exportUrl, instance.config.csv.params).finally(() => top.layer.close(loadIndex))
}
}]
}
}
for (const key in defaultToolbar) {
if (!config.extToolbar.includes(key)) {
continue
}
let toolbar = defaultToolbar[key]
let $exim = $(`
`)
let $ul = $(``)
$exim.append($ul)
toolbar.buttons.forEach(o => {
$ul.append((o.condition ? ` ${o.title} ` : ""))
})
$toolbar.append($exim)
// 监听自定义li点击事件
$exim.on("click", "li", function(e) {
layui.stope(e)
let type = this.getAttribute("data-type")
config[key] && config[key].beforeHandle && config[key].beforeHandle({ type })
// toolbar.beforeHandle && toolbar.beforeHandle({type})
for (const o of toolbar.buttons) {
if (o.type && o.type == type) {
o.click()
break
}
}
})
}
ins.config.$extToolbarInited = true
/***** 给工具栏增加扩展按钮 结束 **/
}
// 合计行自定义显示值
config.cols && config.cols.forEach(o => {
o.forEach(col => {
if (col.templet || !col.totalRow || !col.totalRowFormatter || !col.field) {
return
}
let rows = layui.table.getRows(config.id)
let value = (typeof col.totalRowFormatter === "function") ? col.totalRowFormatter(rows) : ""
layTotal.find(`[data-field='${col.field}']>div`).html(value)
})
})
$done && $done(res, curr, count)
})()
}
let instance = $render(config)
instance != null && isNotBlank(instance.config.id) && instanceMap.set(instance.config.id, instance)
return instance
}
let $reload = layui.table.reload
layui.table.reload = (tableId, config) => {
config.data && config.data.constructor == Array && config.data.forEach(o => o[layui.table.config.cellToolbarName] = "just for update cell toolbar")
let ins = layui.table.getInstance(tableId)
if (!ins) {
return $reload(tableId, config)
}
ins.config.scrollTop = $(`div[lay-id='report_grid_field_table'] .layui-table-body`).scrollTop()
ins.config.startTime = new Date().getTime()
if (ins.config.url && ins.config.page) {
// 如果通过URL进行加载,reload时自动从第一页加载
if (config.page) {
config.page.curr = 1
} else {
config.page = { curr: 1 }
}
}
// 当reload的时候扩展工具栏需要重新渲染
ins.config.$extToolbarInited = false
return $reload(tableId, config)
}
// layui.table.config.request = {pageName: 'currPage', limitName: 'pageSize'}
/**
* 获取Table实例
* @param tableId
* @return {any}
*/
layui.table.getInstance = (tableId) => {
return instanceMap.get(tableId)
}
/**
* 获取指定表格的指定列配置信息
* @param tableId
* @param field
* @return {null|*}
*/
layui.table.getColConfigByField = (tableId, field) => {
let ins = layui.table.getInstance(tableId)
if (!ins) {
return null
}
for (let i = 0; i < ins.config.cols.length; i++) {
for (let j = 0; j < ins.config.cols[i].length; j++) {
if (ins.config.cols[i][j].field == field) {
return ins.config.cols[i][j]
}
}
}
}
/**
* 添加新行
* @param tableId
* @param index 位置,从0开始
* @param data
*/
layui.table.addRow = (tableId, index, data) => {
if (!(layui.table.cache[tableId] && data)) {
return
}
// 如果有可编辑列,且为单选下拉框,并为必填,自动设置默认值为 字典的第一个值
let row = {}
let ins = layui.table.getInstance(tableId)
ins.config.cols.forEach(cols => {
cols.forEach(col => {
// 已经设置过值就不再重复设置了
if (data[col.field]) {
return;
}
let editConfig = col.editConfig
if (editConfig && editConfig.form == "select" && isNotBlank(editConfig.dict) && defaultString(editConfig.verify).indexOf("required") != -1) {
let list = typeof editConfig.dict == "string" ? $global.getDictDataList(editConfig.dict) : editConfig.dict
if (list.length == 0) {
return
}
row[col.field] = list[0].value
return;
}
if (editConfig && editConfig.form == "checkbox") {
row[col.field] = 0
return;
}
})
})
row = { ...data, ...row }
let bak = layui.table.cache[tableId].slice()
// 当有默认值/下拉框时,手动指定默认值
bak.splice(index, 0, row)
layui.table.reload(tableId, {
data: bak
})
}
/**
* 重新渲染指定行
* @param tableId 表格ID
* @param rowIndex 行索引
* @param data 数据
*/
layui.table.renderSpecRow = (tableId, rowIndex, data) => {
let instance = layui.table.getInstance(tableId)
if (instance == null) {
return
}
if (!data) {
return
}
data = $.extend({
LAY_CELL_TOOLBAR: "just for update cell toolbar",
LAY_TABLE_INDEX: rowIndex
}, data)
let tr = $(`[lay-id='${tableId}'] .layui-table-body .layui-table tr:eq(${rowIndex})`)
layui.each(data, (field, index) => {
let td = tr.children('td[data-field="' + field + '"]')
let templet = null
let cols = instance.config.cols
for (let i = 0; i < cols.length; i++) {
let bFind = false
for (let j = 0; j < cols[i].length; j++) {
let col = cols[i][j]
if (col.field == field) {
col.templet && (templet = col.templet)
bFind = true
break
}
}
if (bFind) {
break
}
}
td.children(".layui-table-cell").html(function() {
return templet ? function() {
return "function" == typeof templet ? templet(data) :
layui.laytpl(layui.$(templet).html() || data[field]).render(data)
}() : data[field]
}()), td.data("content", data[field])
})
let trFixed = $(`[lay-id='${tableId}'] .layui-table-fixed .layui-table-body .layui-table tr:eq(${rowIndex})`)
layui.each(data, (field, index) => {
let td = trFixed.children('td[data-field="' + field + '"]')
let templet = null
let cols = instance.config.cols
for (let i = 0; i < cols.length; i++) {
let bFind = false
for (let j = 0; j < cols[i].length; j++) {
let col = cols[i][j]
if (col.field == field) {
col.templet && (templet = col.templet)
bFind = true
break
}
}
if (bFind) {
break
}
}
td.children(".layui-table-cell").html(function() {
return templet ? function() {
return "function" == typeof templet ? templet(data) :
layui.laytpl(layui.$(templet).html() || data[field]).render(data)
}() : data[field]
}()), td.data("content", data[field])
})
layui.table.cache[tableId][rowIndex] = $.extend(layui.table.cache[tableId][rowIndex], data)
}
/**
* 获取指定表格所有行数据
* @param tableId
* @return {Array}
*/
layui.table.getRows = (tableId) => {
if (isBlank(tableId)) {
return []
}
return layui.table.cache[tableId] ? layui.table.cache[tableId] : []
}
/**
* 删除指定行
* @param {string} tableId 表格ID
* @param {number} rowIndex 行索引。>= 0
* @return {boolean}
*/
layui.table.deleteRow = (tableId, rowIndex) => {
let ins = layui.table.getInstance(tableId)
if (ins == null) {
return false
}
if (rowIndex < 0) {
return false
}
$(`[lay-id='${tableId}'] .layui-table-body .layui-table tr:eq(${rowIndex})`).remove()
layui.table.cache[tableId].splice(rowIndex, 1)
layui.table.reload(tableId, {
data: layui.table.cache[tableId]
})
}
/**
* 合并单元格
* @param tableId 表格ID
* @param field 字段名
*/
layui.table.mergeCell = (tableId, field) => {
let $trs = $(`[lay-id='${tableId}'] .layui-table-body>.layui-table tr`);
// 依据字段自动获取列索引
let ins = layui.table.getInstance(tableId)
if (!ins) {
return
}
let merge = (data, index, field) => {
let lastValue = data[0][field],
spanNum = 1;
for (let i = 1; i < data.length; i++) {
if (data[i][field] == lastValue) {
spanNum++;
if (i == data.length - 1) {
$trs.eq(i - spanNum + 1).find('td').eq(index).attr('rowspan', spanNum);
for (let j = 1; j < spanNum; j++) {
$trs.eq(i - j + 1).find('td').eq(index).attr('del', 'true');
}
}
} else {
$trs.eq(i - spanNum).find('td').eq(index).attr('rowspan', spanNum);
for (let j = 1; j < spanNum; j++) {
$trs.eq(i - j).find('td').eq(index).attr('del', 'true');
}
spanNum = 1;
lastValue = data[i][field];
}
}
}
let data = layui.table.getRows(tableId)
if (!data || data.length == 0) {
return
}
let tableCols = ins.config.cols
let col = null
for (let i = 0; i < tableCols.length; i++) {
for (let j = 0; j < tableCols[i].length; j++) {
if (tableCols[i][j].field == field) {
col = tableCols[i][j]
break
}
}
if (col) {
break
}
}
// 如果有合并单元格,先查看表头有没有合并,并找到相应的索引
let index = null
let curIndex = Number.parseInt(col.key.substring(col.key.lastIndexOf("-") + 1))
let parentKey = col.parentKey
if (parentKey) {
let parentIndex = Number.parseInt(parentKey.substring(parentKey.lastIndexOf("-") + 1))
index = parentIndex + curIndex
} else {
index = curIndex
}
merge(data, index, field);
$trs.find('[del="true"]').hide();
}
/*** =============== 增强 当工具栏宽度不够时,弹出详情里面的按钮不能点击 =============== */
$(document).off('mousedown', `.layui-table-grid-down`).on('mousedown', `.layui-table-grid-down`, function(event) {
//直接记录td的jquery对象
layui.table._tableTrCurrr = $(this).closest('td');
});
//给弹出的详情里面的按钮添加监听级联的触发原始table的按钮的点击事件
$(document).off('click', '[lay-event]').on('click', '.layui-table-tips-main [lay-event]', function(event) {
let elem = $(this);
let tableTrCurrr = layui.table._tableTrCurrr;
if (!tableTrCurrr) {
return;
}
let layerIndex = elem.closest('.layui-table-tips').attr('times');
layer.close(layerIndex);
layui.table._tableTrCurrr.find('[lay-event="' + elem.attr('lay-event') + '"]').first().click();
});
/*** =============== 增强 当工具栏宽度不够时,弹出详情里面的按钮不能点击 =============== */
layui.table.$enhanced = true
}
/**
* 增强layer功能
* 1、增加 layer.open {@code btnConfirmIndex} 参数,用于设置确认按钮索引,以修改默认样式
* 2、增加 layer.success 方法
* 3、增加 layer.error 方法
* 4、增加 layer.loading 方法
*/
if (layui && layui.layer && !layui.layer.$enhanced) {
let $open = layer.open
layer.open = (config) => {
if (config.type == 2) {
// iframe 模式
let $end = config.end
config.end = () => {
// 删除open_cache_table 相关dom
let win = top != parent ? parent : window
let $layers = $(`[id*='layui-layer-iframe'][id*='open_cache_table']`, win.document).parent()
$layers.prev(".layui-layer-shade").remove()
$layers.remove()
$end && $end()
}
}
if (config.id && config.side) {
// 可拖动表格(一般用于列表右侧)
let name = $(`#${config.id} iframe[id^='layui-layer-iframe']`).attr("name")
let index = layer.getFrameIndex(name)
if (name && index) {
config.success($(`#${config.id}`).parent(), index)
return
}
let width = $global.getParameterValue("project.front.default.dialogFormWidth", '40%')
config = $.extend(config, {
shade: 0,
offset: "rt",
anim: -1,
area: config.area ? config.area : [width, '100%'],
isOutAnim: true,
move: false, // 禁止默认标题拖拽
resize: false
})
let $success = config.success
config.success = (layero, index) => {
let wrapper = $(`div[id='layui-layer${index}']`)[0]
wrapper.style.border = "0"
let maxWidth = $(wrapper).parent().width()
let el = $(
`
`
)
let body = layer.getChildFrame('body', index)
body.append(el)
let iframeDoc = window[layero.find('iframe')[0]['name']].document
el[0].onmousedown = (e) => {
// 当前点击时Left的值
let offsetLeft = wrapper.offsetLeft
let mouseMoveFn = function(e) {
//e.preventDefault(); // 移动时禁用默认事件
if (offsetLeft == e.clientX) {
return;
}
// 移动的距离
let moveDistance = -e.clientX;
wrapper.style.left = (wrapper.offsetLeft - moveDistance) + "px";
wrapper.style.width = (maxWidth - wrapper.offsetLeft) + "px";
// 已经拉到最左边了,最大化显示
if (wrapper.offsetLeft <= 0) {
wrapper.style.left = "0px";
wrapper.style.width = maxWidth + "px";
return;
}
// 已经拉到最右边了
if (wrapper.offsetLeft >= (maxWidth - 50)) {
wrapper.style.left = (maxWidth - 50) + "px";
wrapper.style.width = "50px";
return;
}
// 更新左边当前位置
offsetLeft = wrapper.offsetLeft
}
let fnMouseUp = (e) => {
iframeDoc.onmousemove = null;
iframeDoc.onmouseup = null;
}
iframeDoc.onmousemove = _.debounce(mouseMoveFn, 5)
iframeDoc.onmouseup = fnMouseUp
iframeDoc.ondragstart = iframeDoc.onselectstart = () => {
return false
}
}
$success && $success(layero, index)
}
return $open(config)
}
// 设置按钮样式
let btnConfirmIndex = config.btnConfirmIndex
if (!btnConfirmIndex) {
return $open(config)
}
let $success = config.success
config.success = (layero, index) => {
layui.$(`${layero.selector} .layui-layer-btn->a:eq(0)`).removeClass("layui-layer-btn0")
layui.$(`${layero.selector} .layui-layer-btn->a:eq(${btnConfirmIndex})`).addClass("layui-layer-btn0")
$success && $success(layero, index)
}
return $open(config)
}
layer.success = (msg, config = {}) => {
config.icon = 1
return layer.msg(msg, config)
}
layer.error = (msg, config = {}) => {
config.icon = 5
return layer.msg(msg, config)
}
layer.loading = (options) => {
let defaultOptions = {
shade: [0.5, 'gray'], //0.5透明度的灰色背景,
offset: [`${screen.availHeight / 2 - 50}px`, `${screen.availWidth / 2 - 50}px`],
content: "加载中...",
success(layero) {
layero.find('.layui-layer-content').css({
'padding-top': '39px',
'width': '60px'
});
}
}
let tmpOptions = { ...defaultOptions, ...options }
return layer.load(1, tmpOptions)
}
layui.layer.$enhanced = true
}
/**
* 增强laydate功能
* 1、当日期选择完成时,自动赋值相应的元素value
* 2、支持渲染多个dom
* 3、增加 获取laydate 实例方法
* 4、增加快捷方式选项(增加字段:pickerOptions)
*/
if (layui && layui.laydate && !layui.laydate.$enhanced) {
let laydate = layui.laydate
let instanceMap = new Map()
let $render = laydate.render
laydate.render = (config) => {
// config.pickerOptions = config.pickerOptions || $dates.pickerOptions.date
if (config.isInitValue) {
// && config.value.every(o => o instanceof Date)
if (config.range && config.value && Array.isArray(config.value)) {
config.value = config.value.map(o => o.format($strings.defaultIfBlank(config.format, 'yyyy-MM-dd'))).join(` ${typeof config.range === "boolean" ? "-" : config.range} `)
}
}
let $done = config.done
config.done = (value, date, endDate) => {
if (!config.range) {
config.elem && $(config.elem).val(value) && $(config.elem).change()
}
$done && $done(value, date, endDate)
}
let $ready = config.ready
config.ready = function(date) {
if (!(config.pickerOptions && config.pickerOptions.shortcuts)) {
$ready && typeof $ready === 'function' && $ready(date)
return
}
let shortcuts = config.pickerOptions.shortcuts
let that = this
let key = that.elem.attr("lay-key")
let $elem = $("#layui-laydate" + key)
let $ul = $(` `)
shortcuts && shortcuts.forEach(o => {
let $li = $(`${o.text} `)
$li.click(() => {
$elem.remove()
o.onClick(that)
instanceMap.delete(key)
})
$ul.append($li)
})
$elem.prepend($ul)
$ul.height($elem.find(".layui-laydate-main").outerHeight())
if (!config.range) {
$elem.find(".layui-laydate-main").css({ "display": "inline-block" })
// 宽度超限
let divWidth = $elem.offset().left + $elem.outerWidth() + $ul.outerWidth()
if (divWidth > document.body.offsetWidth) {
let left = document.body.offsetWidth - ($elem.outerWidth() + ($ul.outerWidth() / 2))
$elem.css({ "left": `${left}px` })
}
} else {
$elem.width($elem.outerWidth() + $ul.outerWidth())
}
$ready && typeof $ready === 'function' && $ready(date)
}
let tmpConfig = { ...config }
$(config.elem).each(function() {
let that = this
let conf = { ...tmpConfig }
conf.elem = that
conf.done = (value, date, endDate) => {
$(that).val(value) && $(that).change()
$done && $done(value, date, endDate)
}
let ins = $render(conf)
instanceMap.set(conf.elem.getAttribute("lay-key"), ins)
});
}
/**
* 获取laydate实例
* @param key 所渲染的表单元素 lay-key
* @return {any}
*/
laydate.getInstance = (key) => {
return instanceMap.get(key)
}
laydate.$enhanced = true
}
/**
* 表单验证功能增强
*/
form.verify({
"radio-required"(value, item) {
//单选按钮必选
let va = $(item).find("input[type='radio']:checked").val();
if (typeof(va) == "undefined") {
return $(item).attr("lay-verify-msg");
}
},
"checkbox-required"(value, item) {
//复选框必选
let va = $(item).find("input[type='checkbox']:checked").val();
if (typeof(va) == "undefined") {
return $(item).attr("lay-verify-msg");
}
},
"required"(value, item) {
if (value === undefined && value == null) {
return '必填项不能为空'
}
if (value.trim() === '') {
return '必填项不能为空'
}
},
"abc"(value, item) {
if (!/^\w+$/.test(value)) {
return '只能填写字母、数字及下划线'
}
},
"email"(value, item) {
if (isBlank(value)) {
return
}
if (!/\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/.test(value)) {
return '邮箱格式不正确'
}
},
"number"(value, item) {
if (isNotBlank(value) && isNaN(value)) {
return '只能填写数字'
}
},
"phone"(value, item) {
if (isBlank(value)) {
return
}
if (!/^1\d{10}$/.test(value)) {
return '请输入正确的手机号'
}
},
"integer": [/^-?\d+$/, "只能填写整数"],
"positive_integer": [/^\d+$/, "只能填写正整数"],
"negative_integer": [/^-\d+$/, "只能填写负整数"]
// integer /^-?\d+$/
// digits /^(0|\+?[1-9][0-9]*)$/
// /^(([^0][0-9]+|0)\.([0-9]{1,2}))$/
});
/**
* 可编辑表格相关工具
* @type {{validateSingleRow(*=): boolean}}
*/
let editable = {
/**
* 监听表格,当表格的可编辑内容(文本框、下拉框、复选框等) 值改变后,同步更新表格缓存的值
* @param tableId
*/
watch(tableId) {
if (isBlank(tableId)) {
throw new Error(`The parameter tableId cannot be blank`)
}
if (!layui.table.cache[tableId]) {
throw new Error(`The table ${tableId} is not exist,please first to init`)
}
let instance = table.getInstance(tableId)
if (instance && instance.$watched) {
// 已经监听,不再进行重复监听
return
}
let trs = $(`[lay-id='${tableId}'] .layui-table tr:gt(0)`)
// 监听文本框,当值有更新时,修改缓存中的数据
$(document).on('change', `[lay-id='${tableId}'] .layui-table input[data-name]`, (e) => {
let row = e.target.getAttribute('data-index')
let name = e.target.getAttribute('data-name')
layui.table.cache[tableId][row][name] = e.target.value
})
// 监听下拉框,当值有更新时,修改缓存中的数据。 防止当表格没有数据时,监听失败
instance.config.cols.forEach(cols => {
cols.forEach(col => {
if ((col.editConfig && col.editConfig.form == "select") ||
(typeof col.templet == "string" && $(col.templet).html().indexOf("") != -1)) {
form.on(`select(${col.field})`, function(obj) {
let row = obj.elem.getAttribute('data-index')
let name = obj.elem.getAttribute('data-name')
table.cache[tableId][row][name] = obj.value
});
}
})
})
// 监听下拉框,当值有更新时,修改缓存中的数据
// let selects = $(`[lay-id='${tableId}'] .layui-table select[data-name] `)
// for (let i = 0; i < selects.length; i++) {
// let select = selects[i]
// form.on(`select(${select.getAttribute('lay-filter')})`, function (obj) {
// let row = obj.elem.getAttribute('data-index')
// let name = obj.elem.getAttribute('data-name')
// table.cache[tableId][row][name] = obj.value
// });
// }
let checkboxs = $(`[lay-id='${tableId}'] .layui-table input[type='checkbox'][data-name] `)
for (let i = 0; i < checkboxs.length; i++) {
let checkbox = checkboxs[i]
form.on(`checkbox(${checkbox.getAttribute('lay-filter')})`, function(obj) {
let row = obj.elem.getAttribute('data-index')
let name = obj.elem.getAttribute('data-name')
table.cache[tableId][row][name] = obj.elem.checked ? 1 : 0
});
}
instance.$watched = true
},
/**
* 校验所有行数据
* @param tableId
* @param callback
*/
validateAllRows(tableId, callback) {
let trs = $(`[lay-id='${tableId}'] .layui-table-body .layui-table tr`)
let errors = new Array()
for (let i = 0; i < trs.length; i++) {
let tr = trs[i]
this.validateSingleRow(tableId, i, (valid, error) => {
if (!valid) {
errors.push(error)
}
})
}
if (errors.length == 0) {
callback && typeof callback === "function" && callback(true, [])
return
}
callback && typeof callback === "function" && callback(false, errors)
},
/**
* 校验单行数据
* @param tableId 表格ID
* @param rowIndex 行索引
* @param callback 成功/失败回调, 有两个参数: (valid,error) ,当校验成功失败时,valid为false、error为具体的错误信息 @code {field,rowIndex,message}
*/
validateSingleRow(tableId, rowIndex, callback) {
let tr = $(`[lay-id='${tableId}'] .layui-table-body .layui-table tr:eq(${rowIndex})`)[0]
// let tr = $(trSelector)[0]
if (!tr) {
return
}
let tdChildren = tr.children
let fields = new Array()
for (let i = 0; i < tdChildren.length; i++) {
fields.push(tdChildren[i].dataset.field)
}
for (let i = 0; i < fields.length; i++) {
let field = fields[i]
let el = $(`[data-name="${field}"][data-index="${rowIndex}"]`)
// 获取校验规则、字段值
let verify = el.attr("lay-verify")
let verifies = verify ? verify.split("|") : []
let value = el.val()
el.removeClass('layui-form-danger')
for (let j = 0; j < verifies.length; j++) {
let v = layui.form.config.verify[verifies[j]]
if (!v) {
continue
}
// return undefined or false,代表校验成功
let r = typeof v == 'function' ? v(value, el) : !v[0].test(value)
// 读取通过函数返回的参数 或者 直接取配置的正则 相应的提示信息 ,具体格式详见 layui.form.config.verify
let message = typeof r === "boolean" ? v[1] : r
"required" === verifies[j] && (message = el.attr("lay-reqText") || message)
if (!(r === undefined || r === false)) {
layui.layer.msg(message, {
icon: 5,
shift: 6
})
setTimeout(() => {
el.focus()
el.addClass("layui-form-danger")
}, 10)
callback && typeof callback === "function" && callback(false, {
field,
rowIndex,
message
})
return
}
}
}
callback(true, {})
}
}
window.$editable = editable
exports('enhance', {}); //注意,这里是模块输出的核心,模块名必须和use时的模块名一致
});