若依系统的前端操作大部分储存在/ruoyi-admin/src/main/resources/static/ruoyi/js/ry-ui.js中。
本文对其中的各方法进行了一些备注,新增了几个方法。
有一些console.log输出的部分已经被注释掉,根据需要加回来查看可以方便理解。
js文件和配套的html如下:
/**
* 通用js方法封装处理
* Copyright (c) 2019 ruoyi
*/
// 当前table相关信息
//把table的数据取出来就在这里,table.set找到tableId,找到table options
var table = {
//根据我的观察option和config都储存的是table的各项属性,都是动态的,初始化的时候复制config中的参数table.get(tableId),但是config也会在传回参数的时候被options复写
config: {
},
// 当前实例配置
options: {
},
// 设置实例配置
set: function(id) {
//console.log('table.set::options');
//console.log(table.options);
//console.log('table.set::config');
//console.log(table.config);
//改变的是当前table的option
//只有一个表单的时候这里是不进入判断的。
if($.common.getLength(table.config) > 1) {
//set 如果给参数,就用参数作为ID去搜索相应的一条属性,如果没有,就在当前元素的父元素中寻找一个.bootstrap-table,复制他的id
console.log('table.set::tableId');
var tableId = $.common.isEmpty(id) ? $(event.currentTarget).parents(".bootstrap-table").find("table.table").attr("id") : id;
//console.log(tableId);
if ($.common.isNotEmpty(tableId)) {
table.options = table.get(tableId);
}
}
},
// 获取实例配置
get: function(id) {
return table.config[id];
},
// 记住选择实例组
rememberSelecteds: {
},
// 记住选择ID组
rememberSelectedIds: {
}
};
(function ($) {
$.extend({
_tree: {
},
bttTable: {
},
// 表格封装处理
table: {
// 初始化表格参数
init: function(options) {
var defaults = {
id: "bootstrap-table",
type: 0, // 0 代表bootstrapTable 1代表bootstrapTreeTable
method: 'post',
height: undefined,
sidePagination: "server",
sortName: undefined,
sortOrder: "asc",
pagination: true,
paginationLoop: false,
pageSize: 10,
pageNumber: 1,
pageList: [10, 25, 50],
toolbar: "toolbar",
loadingFontSize: 13,
striped: false,
escape: false,
firstLoad: true,
showFooter: false,
search: false,
showSearch: true,
showPageGo: false,
showRefresh: true,
showColumns: true,
showToggle: true,
showExport: false,
clickToSelect: false,
singleSelect: false,
mobileResponsive: true,
maintainSelected: false,
rememberSelected: false,
fixedColumns: false,
fixedNumber: 0,
fixedRightNumber: 0,
queryParams: $.table.queryParams,
rowStyle: {
},
};
var options = $.extend(defaults, options);
table.options = options;
table.config[options.id] = options;
var rst = "";
$.each(table.options,function(k,v){
rst+="\n-key-"+k+"-value-"+v;
});
//console.log(rst);
//console.log("-----------------------config-------------------------")
$.each(table.config,function(k,v){
rst+="\n-key-"+k+"-value-"+v;
});
//console.log(rst);
$.table.initEvent();
//console.log("REQUEST TABLE, ID= "+options.id);
//下面这句话是生成表格的方法,options.url对应到后端的控制器,然后在那里查询并返回数据。
//console.log("init: 即将生成表格,URL="+options.url);
//console.log("options: ");
//console.log(options);
$('#' + options.id).bootstrapTable({
id: options.id,
url: options.url, // 请求后台的URL(*)
contentType: "application/x-www-form-urlencoded", // 编码类型
method: options.method, // 请求方式(*)
cache: false, // 是否使用缓存
height: options.height, // 表格的高度
striped: options.striped, // 是否显示行间隔色
sortable: true, // 是否启用排序
sortStable: true, // 设置为 true 将获得稳定的排序
sortName: options.sortName, // 排序列名称
sortOrder: options.sortOrder, // 排序方式 asc 或者 desc
pagination: options.pagination, // 是否显示分页(*)
paginationLoop: options.paginationLoop, // 是否启用分页条无限循环的功能
pageNumber: 1, // 初始化加载第一页,默认第一页
pageSize: options.pageSize, // 每页的记录行数(*)
pageList: options.pageList, // 可供选择的每页的行数(*)
firstLoad: options.firstLoad, // 是否首次请求加载数据,对于数据较大可以配置false
escape: options.escape, // 转义HTML字符串
showFooter: options.showFooter, // 是否显示表尾
iconSize: 'outline', // 图标大小:undefined默认的按钮尺寸 xs超小按钮sm小按钮lg大按钮
toolbar: '#' + options.toolbar, // 指定工作栏
loadingFontSize: options.loadingFontSize, // 自定义加载文本的字体大小
sidePagination: options.sidePagination, // server启用服务端分页client客户端分页
search: options.search, // 是否显示搜索框功能
searchText: options.searchText, // 搜索框初始显示的内容,默认为空
showSearch: options.showSearch, // 是否显示检索信息
showPageGo: options.showPageGo, // 是否显示跳转页
showRefresh: options.showRefresh, // 是否显示刷新按钮
showColumns: options.showColumns, // 是否显示隐藏某列下拉框
showToggle: options.showToggle, // 是否显示详细视图和列表视图的切换按钮
showExport: options.showExport, // 是否支持导出文件
showHeader: options.showHeader, // 是否显示表头
showFullscreen: options.showFullscreen, // 是否显示全屏按钮
uniqueId: options.uniqueId, // 唯一的标识符,指定的应该是表中一个column的名字
clickToSelect: options.clickToSelect, // 是否启用点击选中行
singleSelect: options.singleSelect, // 是否单选checkbox
mobileResponsive: options.mobileResponsive, // 是否支持移动端适配
cardView: options.cardView, // 是否启用显示卡片视图
detailView: options.detailView, // 是否启用显示细节视图
onCheck: options.onCheck, // 当选择此行时触发
onUncheck: options.onUncheck, // 当取消此行时触发
onCheckAll: options.onCheckAll, // 当全选行时触发
onUncheckAll: options.onUncheckAll, // 当取消全选行时触发
onClickRow: options.onClickRow, // 点击某行触发的事件
onDblClickRow: options.onDblClickRow, // 双击某行触发的事件
onClickCell: options.onClickCell, // 单击某格触发的事件
onDblClickCell: options.onDblClickCell, // 双击某格触发的事件
onEditableSave: options.onEditableSave, // 行内编辑保存的事件
onExpandRow: options.onExpandRow, // 点击详细视图的事件
onPostBody: options.onPostBody, // 渲染完成后执行的事件
maintainSelected: options.maintainSelected, // 前端翻页时保留所选行
rememberSelected: options.rememberSelected, // 启用翻页记住前面的选择
fixedColumns: options.fixedColumns, // 是否启用冻结列(左侧)
fixedNumber: options.fixedNumber, // 列冻结的个数(左侧)
fixedRightNumber: options.fixedRightNumber, // 列冻结的个数(右侧)
onReorderRow: options.onReorderRow, // 当拖拽结束后处理函数
queryParams: options.queryParams, // 传递参数(*)
rowStyle: options.rowStyle, // 通过自定义函数设置行样式
footerStyle: options.footerStyle, // 通过自定义函数设置页脚样式
headerStyle: options.headerStyle, // 通过自定义函数设置标题样式
//columns是从前端传过来的,描绘查询哪些数据的最重要的参数之一,通过extend与table.options整合了
columns: options.columns, // 显示列信息(*)
data: options.data, // 被加载的数据
responseHandler: $.table.responseHandler, // 在加载服务器发送来的数据之前处理函数
onLoadSuccess: $.table.onLoadSuccess, // 当所有数据被加载时触发处理函数
exportOptions: options.exportOptions, // 前端导出忽略列索引
printPageBuilder: options.printPageBuilder, // 自定义打印页面模板
detailFormatter: options.detailFormatter, // 在行下面展示其他数据列表
});
},
// 获取实例ID,如存在多个返回#id1,#id2 delimeter分隔符
//把key,也就是各种实例的id们拿出来整成字符串了
getOptionsIds: function(separator) {
var _separator = $.common.isEmpty(separator) ? "," : separator;
var optionsIds = "";
//key是属性组的id,value应该是属性组的值,属于字典
//config的optionsid只有一个就是bootstrap-table
//console.log("--------------------in getting oprions Ids: table.config---------------------");
$.each(table.config, function(key, value){
//console.log('-key-'+key+'-value-'+value+'\n');
optionsIds += "#" + key + _separator;
});
return optionsIds.substring(0, optionsIds.length - 1);
},
// 查询条件
queryParams: function(params) {
var curParams = {
// 传递参数查询参数
pageSize: params.limit,
pageNum: params.offset / params.limit + 1,
searchValue: params.search,
orderByColumn: params.sort,
isAsc: params.order
};
var currentId = $.common.isEmpty(table.options.formId) ? $('form').attr('id') : table.options.formId;
return $.extend(curParams, $.common.formToJSON(currentId));
},
// 请求获取数据后处理回调函数
//这个函数是在获得result之后返回前端时将获取的数据数一下,总行数和行内信息装进字典返回,特殊情况除外
responseHandler: function(res) {
if (typeof table.get(this.id).responseHandler == "function") {
//id = config key
table.get(this.id).responseHandler(res);
//如果是方法调用的这个函数,就会有thisid,如果没有thisid,就把res拿出来做thisid
}
if (res.code == web_status.SUCCESS) {
if ($.common.isNotEmpty(table.options.sidePagination) && table.options.sidePagination == 'client') {
return res.rows;
//对其中特定属性sidePagination进行了筛选
} else {
if ($.common.isNotEmpty(table.options.rememberSelected) && table.options.rememberSelected) {
var column = $.common.isEmpty(table.options.uniqueId) ? table.options.columns[1].field : table.options.uniqueId;
$.each(res.rows, function(i, row) {
row.state = $.inArray(row[column], table.rememberSelectedIds[table.options.id]) !== -1;
})
}
return {
rows: res.rows, total: res.total };
}
} else {
$.modal.alertWarning(res.msg);
return {
rows: [], total: 0 };
}
},
// 初始化事件
initEvent: function() {
// 实例ID信息
//console.log("-----------------------table.config in initEvent-------------------------")
//在外面套了一个bootstrapTable,其中的属性是一样的,但是什么时候套的呢?
var rst="";
$.each(table.config,function(k,v){
rst+="-key-"+k+"-value-"+v+"\n";
//console.log(rst);
rst="";
//console.log("=======value inside========");
$.each(v,function(key,value){
//console.log(value);
//console.log("\n");
rst+="-key-"+key+"-value-"+value+"\n";
});
});
//console.log(rst);
var optionsIds = $.table.getOptionsIds();
//console.log("---------------------optionsIds----------------------");
//console.log(optionsIds);
// 监听事件处理
$(optionsIds).on(TABLE_EVENTS, function () {
//get 就是拿id去config里面找值 set 就是从config中找值丢到当前的table的option里,this指代被选中的那一个optionsIds
//目前的config里面只有一个叫bootstrap-table的值,而optionIds对应是#bootstrap-table
//console.log("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n")
//console.log($(this));
//console.log($(optionsIds));
//$(optionsIds).css("background","red");
//$(this).css("background","red");
//选取的是$("#bootstrap-table") 但是调用了很多次,因为每一次操作都属于TABLE_EVENTS,主要目的是触发表格时用config复写options
//console.log(table.options["id"]);
//console.log(table.config["bootstrap-table"]["id"]);
table.set($(this).attr("id"));
//console.log("---------TABLE_EVENTS : after set function-----------")
//console.log(table.options["id"]);
//console.log(table.config["bootstrap-table"]["id"]);
//结果这个玩意该不会是对所有操作都生效的,把当前table.config和table.options对应的验证步骤??
//所以才调用了很多次是吗?
});
// 在表格体渲染完成,并在 DOM 中可见后触发(事件)
//这种事追加绑定事件,根据Boostraptable官方api,这种jQ绑定的格式是$(#id).on("event_name.bs.table",function(e,arg1,arg2..))
$(optionsIds).on("post-body.bs.table", function (e, args) {
//这两句话属于bootstrap的内容
//console.log("--------binding post-body.bs.table-------");
// 浮动提示框特效
$(".table [data-toggle='tooltip']").tooltip();
// 气泡弹出框特效
$('.table [data-toggle="popover"]').popover();
});
//====================================================================看样子事件是自己定义的?在哪定义的呢?
$(optionsIds).on("click.bs.table", function (e, args) {
//这两句话属于bootstrap的内容
//console.log("--------binding click.bs.table-------");
});
//====================================================================
// 选中、取消、全部选中、全部取消(事件)
//这个函数无参可以执行,可以作为初始化表格的一部分。不如说这个就是在init里面的,只不过是声明
//这一部分是事件名,自定义事件check.bs.table....
//对于表中元素的选取和取消都是自定义的事件,注意这个是在选中复选框的时候执行的“check”方法触发
$(optionsIds).on("check.bs.table check-all.bs.table uncheck.bs.table uncheck-all.bs.table", function (e, rowsAfter, rowsBefore) {
//console.log("--------TABLE EVENT: check.bs.table check-all.bs.table uncheck.bs.table uncheck-all.bs.table-------");
// 复选框分页保留保存选中数组
//console.log("rowsAfter:"+rowsAfter+"\n");
//console.log(rowsAfter)
//console.log("rowsBefore:"+rowsBefore+"\n");
//console.log(rowsBefore);
var rows = $.common.equals("uncheck-all", e.type) ? rowsBefore : rowsAfter;
//这一部分是事件的type属性,check,check-all,uncheck,uncheck-all...
//table.affectedrowids是之前被选中的数据行,就是把rows当中可以用来分辨的元素(一般uniqueid)提取出来
var rowIds = $.table.affectedRowIds(rows);
if ($.common.isNotEmpty(table.options.rememberSelected) && table.options.rememberSelected) {
//func可以是union或者difference
func = $.inArray(e.type, ['check', 'check-all']) > -1 ? 'union' : 'difference';
//rememberselectedids是一个字典类型,把option的id和selectedids记录下来
//对于一个表来说,它当前的option肯定是只有一个的。
var selectedIds = table.rememberSelectedIds[table.options.id];
if($.common.isNotEmpty(selectedIds)) {
//这个_可能是存的函数?通过union和difference提取出两个不同的函数,对selectedids和rowids加以执行
//暂时没找到这个_是来自哪里,不过就功能性上讲这个位置的两句话必然是给rememberselectedids赋值,加上之前就存在里面的,塞进table数据里
//为什么是rows转换后还要加上原来的?推测rows并非扫描了table所有的数据,而是在操作的时候产生的几条。
table.rememberSelectedIds[table.options.id] = _[func](selectedIds, rowIds);
} else {
table.rememberSelectedIds[table.options.id] = _[func]([], rowIds);
}
var selectedRows = table.rememberSelecteds[table.options.id];
//不仅仅是选中的条目的可识别id被记录,条目本身也被记录进table的数据中了。
if($.common.isNotEmpty(selectedRows)) {
table.rememberSelecteds[table.options.id] = _[func](selectedRows, rows);
} else {
table.rememberSelecteds[table.options.id] = _[func]([], rows);
}
}
});
// 加载成功、选中、取消、全部选中、全部取消(事件)
$(optionsIds).on("check.bs.table uncheck.bs.table check-all.bs.table uncheck-all.bs.table load-success.bs.table", function () {
var toolbar = table.options.toolbar;
var uniqueId = table.options.uniqueId;
// 工具栏按钮控制
//uniqueid是一个字段,rows由此选出了一列column,没有就用第一列
var rows = $.common.isEmpty(uniqueId) ? $.table.selectFirstColumns() : $.table.selectColumns(uniqueId);
//console.log("--------------TABLE EVENT CHECK AND LOAD------------");
//console.log("toolbar:"+toolbar+"\nuniqueId:"+uniqueId+"\nrows"+rows);
// 非多个禁用
//这里rows是个数组,存放每一行的信息(全部)
//.multiple 和 .single是类名?
//$("#toolbar .multiple")应该是取页面中的元素,但是从哪加进去的?
$('#' + toolbar + ' .multiple').toggleClass('disabled', !rows.length);
// 非单个禁用
$('#' + toolbar + ' .single').toggleClass('disabled', rows.length!=1);
});
// 图片预览事件
//这种方法选择的.img-circle本来就是其中的后代元素
//应该是如果放了个图,就加入img-circle类,然后在table中拥有一个optionsid,通过这个来放大预览,例如带照片的表格
$(optionsIds).off("click").on("click", '.img-circle', function() {
var src = $(this).attr('src');
var target = $(this).data('target');
if($.common.equals("self", target)) {
var height = $(this).data('height');
var width = $(this).data('width');
// 如果是移动端,就使用自适应大小弹窗
if ($.common.isMobile()) {
width = 'auto';
height = 'auto';
}
layer.open({
title: false,
type: 1,
closeBtn: true,
shadeClose: true,
area: ['auto', 'auto'],
content: "<img src='" + src + "' height='" + height + "' width='" + width + "'/>"
});
} else if ($.common.equals("blank", target)) {
window.open(src);
}
});
// 单击tooltip事件
//optionsIds内容为#table1, #table2 ... 在此处直接匹配jquery选择器。
//function绑定了#tableId下.tooltip-show的点击事件。
$(optionsIds).on("click", '.tooltip-show', function() {
//.data类似.attr,通过.data(key,value)编辑,通过.data(key)提取
var target = $(this).data('target');
//prev选中了上一个同级元素,由此推测,这里的optionid肯定是一条条的数据,而不是表格级别。
var input = $(this).prev();
if ($.common.equals("copy", target)) {
//这句话实现的是选中input,并复制其中的值到剪贴板的功能。
input.select();
document.execCommand("copy");
} else if ($.common.equals("open", target)) {
//这里是layer模块,用来弹出窗口。
parent.layer.alert(input.val(), {
title: "信息内容",
shadeClose: true,
btn: ['确认'],
btnclass: ['btn btn-primary'],
});
}
});
},
// 当所有数据被加载时触发
//这个onLoadSuccess()应该是前端传过来的函数,在前端的js中自己写,提交给这里的时候带上
//顺便提交方式是通过thymeleaf往页面中插入了此js,页面中调用如$.table.init()之类的方法实现的。
onLoadSuccess: function(data) {
if (typeof table.options.onLoadSuccess == "function") {
table.options.onLoadSuccess(data);
}
},
// 表格销毁
destroy: function (tableId) {
var currentId = $.common.isEmpty(tableId) ? table.options.id : tableId;
$("#" + currentId).bootstrapTable('destroy');
delete table.rememberSelectedIds[currentId];
delete table.rememberSelecteds[currentId];
},
// 序列号生成
serialNumber: function (index, tableId) {
var currentId = $.common.isEmpty(tableId) ? table.options.id : tableId;
var tableParams = $("#" + currentId).bootstrapTable('getOptions');
var pageSize = $.common.isNotEmpty(tableParams.pageSize) ? tableParams.pageSize: table.options.pageSize;
var pageNumber = $.common.isNotEmpty(tableParams.pageNumber) ? tableParams.pageNumber: table.options.pageNumber;
return pageSize * (pageNumber - 1) + index + 1;
},
// 列超出指定长度浮动提示 target(copy单击复制文本 open弹窗打开文本)
tooltip: function (value, length, target) {
var _length = $.common.isEmpty(length) ? 20 : length;
var _text = "";
var _value = $.common.nullToStr(value);
var _target = $.common.isEmpty(target) ? 'copy' : target;
if (_value.length > _length) {
_text = _value.substr(0, _length) + "...";
_value = _value.replace(/\'/g,"'");
_value = _value.replace(/\"/g,""");
var actions = [];
actions.push($.common.sprintf('<input style="opacity: 0;position: absolute;width:5px;z-index:-1" type="text" value="%s"/>', _value));
actions.push($.common.sprintf('<a href="###" class="tooltip-show" data-toggle="tooltip" data-target="%s" title="%s">%s</a>', _target, _value, _text));
return actions.join('');
} else {
_text = _value;
return _text;
}
},
// 下拉按钮切换
//返回了一个html字符串,应该可以直接append到前端HTML代码中实现下拉增加。
dropdownToggle: function (value) {
var actions = [];
actions.push('<div class="btn-group">');
actions.push('<button type="button" class="btn btn-xs dropdown-toggle" data-toggle="dropdown" aria-expanded="false">');
actions.push('<i class="fa fa-cog"></i> <span class="fa fa-chevron-down"></span></button>');
actions.push('<ul class="dropdown-menu">');
actions.push(value.replace(/<a/g,"<li><a").replace(/<\/a>/g,"</a></li>"));
actions.push('</ul>');
actions.push('</div>');
return actions.join('');
},
// 图片预览
//这个图片是属于静态资源,src=value
imageView: function (value, height, width, target) {
if ($.common.isEmpty(width)) {
width = 'auto';
}
if ($.common.isEmpty(height)) {
height = 'auto';
}
// blank or self
var _target = $.common.isEmpty(target) ? 'self' : target;
if ($.common.isNotEmpty(value