Bootstrap表格插件bootstrap-table配置與應用小結
by:授客 QQ:1033553122
- 1. 測試環境
win7
JQuery-3.2.1.min.js
下載地址:
https://gitee.com/ishouke/front_end_plugin/blob/master/jquery-3.2.1.min.js
Bootstrap-3.3.7-dist
下載地址:
https://gitee.com/ishouke/front_end_plugin/blob/master/bootstrap-3.3.7.zip
bootstrap-table-develop-v1.12.1.zip
下載地址:
https://github.com/wenzhixin/bootstrap-table
https://gitee.com/ishouke/front_end_plugin/blob/master/bootstrap-table-develop-v1.12.1.zip
- 2. 配置與應用
效果展示
HTML代碼片段
head設置
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3個meta標簽*必須*放在最前面,任何其他內容都*必須*跟隨其后! -->
{% load staticfiles %}
<!-- jQuery (Bootstrap 的所有 JavaScript 插件都依賴 jQuery,所以必須放在前邊) -->
<script type="text/javascript" src="{% static 'website/jquery-3.2.1.min.js' %}" defer></script>
<!-- Bootstrap -->
<link rel="stylesheet" type="text/css" href="{% static 'website/bootstrap-3.3.7-dist/css/bootstrap.min.css' %}" />
<!-- 加載 Bootstrap 的所有 JavaScript 插件。你也可以根據需要只加載單個插件。 -->
<script type="text/javascript" src="{% static 'website/bootstrap-3.3.7-dist/js/bootstrap.min.js' %}" defer></script>
<!-- HTML5 shim 和 Respond.js 是為了讓 IE8 支持 HTML5 元素和媒體查詢(media queries)功能 -->
<!-- 警告:通過 file:// 協議(就是直接將 html 頁面拖拽到瀏覽器中)訪問頁面時 Respond.js 不起作用 -->
<!--[if lt IE 9]>
<script src="https://cdn.bootcss.com/html5shiv/3.7.3/html5shiv.min.js" defer></script>
<script src="https://cdn.bootcss.com/respond.js/1.4.2/respond.min.js" defer></script>
<![endif]-->
<!-- Bootstrap-Table -->
<link rel="stylesheet" type="text/css" href="{% static 'website/bootstrap-table-1.12.1-dist/bootstrap-table.min.css' %}" />
<script type="text/javascript" src="{% static 'website/bootstrap-table-1.12.1-dist/bootstrap-table.min.js' %}" defer></script>
<!-- 引入中文語言包,注意:locale files 必須放在bootstrap-table.js后面 -->
<script type="text/javascript" src="{% static 'website/bootstrap-table-1.12.1-dist/locale/bootstrap-table-zh-CN.min.js' %}" defer></script>
……略
</head>
table及toolbar工具條
<div class="container-fluid">
<div class="row">
<table id="roleTable"></table>
<div id="toolbar">
<div class="btn-group">
<button class="btn btn-default" data-toggle="modal" data-target="#roleDialog" id="addBtn">新增
<i class="glyphicon glyphicon-plus"></i>
</button>
<button class="btn btn-default" id="editBtn">修改
<i class="glyphicon glyphicon-edit"></i>
</button>
<button class="btn btn-default" id="deleteBtn">刪除
<i class="glyphicon glyphicon-remove"></i>
</button>
</div>
<form class="form-inline" id="queryForm">
<div class="form-group">
<div class="input-group">
<div class="input-group-addon">角色名稱</div>
<input type="text" class="form-control" name="roleNameQ" id="roleNameQ" placeholder="請輸入角色名稱">
</div>
<div class="input-group date" id="startTimePicker">
<div class="input-group-addon">開始時間</div>
<input type="text" class="form-control" name="startTime" id="startTime" >
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
<div class="input-group date" id="endTimePicker">
<div class="input-group-addon">結束時間</div>
<input type="text" class="form-control" name="endTime" id="endTime">
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
<button type="button" id="queryBtn" class="btn btn-primary queryButton">查詢</button>
</form>
</div>
</div>
</div>
JS代碼片段
數據表初始化配置
/**
* 獲取角色表數據
*/
function loadTableData () {
$('#' + roleTableID).bootstrapTable({
url: roleTableDataURL, // 服務器數據的加載地址。
method:'get', // 服務器數據的請求方式 'get' 或 'post'。
pagination:true,// 在表格底部顯示分頁信息(顯示第 x 到第 x 條記錄,總共 x 條記錄),翻頁條 // 注意:數據頁頁數超過1頁會才展示翻頁條
paginationVAlign:'bottom', // 指定分頁條在垂直方向的位置。'top','bottom' 或 'both'。
sidePagination:'server', // 設置在哪里進行分頁,可選值為 'client' 或者 'server'。注意:設置 'server'時,必須設置服務器數據地址(url)或者重寫ajax方法。
responseHandler:responseHandler, // 加載服務器數據之前的處理程序,可以用來格式化數據。
pageSize:10, // 如果啟用分頁,設置初始化界面時,默認的每頁顯示數據條數
pageList:[10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 'All'], // 如果設置了分頁,設置可供選擇的頁面記錄數。設置為 All 或者 Unlimited,則顯示所有記錄
smartDisplay:false, // 設置為 true 是程序自動判斷顯示分頁信息和 card 視圖。這會導致自定義的 pageList不起作用
silentSort:true, // 設置為true將在點擊分頁按鈕時,自動記住排序項。僅在 sidePagination設置為 server時生效
showColumns:true, // 展示內容列下拉框,方便設置展示那些列
showRefresh:true, // 顯示刷新按鈕
idField:'id', // 指定主鍵列
//dataField: "data", //返回的json數組記錄(表格數據)的key.默認是"rows", 數據格式: {"total": 0, "rows": []}
checkboxHeader:true, // 如果設置 false,將在列頭隱藏全選復選框,反之則顯示,設置為ture時,必須設置singleSelect=false 才有效
clickToSelect:true, // 如果設置 true,則在點擊行時,自動選中 rediobox 、 checkbox。
singleSelect:false, //如果設置為true - 禁止多選,否則不禁止多選
striped:true, // 設置為 true 會有隔行變色效果
toolbar:'#toolbar', // 一個jQuery 選擇器,形如#toolbar, .toolbar,指明自定義的 toolbar
toolbarAlign:'left', // 指定 toolbar 水平方向的位置。'left' 或 'right'。
columns: [{
field: 'checkbox',
align: 'center', // 設置數據對齊方式可選項: 'left', 'right', 'center'
halign: 'center', // 設置表頭標題對齊方式可選項: 'left', 'right', 'center'
valign: 'middle', // 設置單元格數據的垂直方向上的對齊方式,有:top(靠上)、middle(居中)、bottom(靠下)針對checkbox似乎不起作用
checkbox:true, // 顯示為復選框
width: '1%',// 設置列寬度
},{
field: 'id',
title: '角色ID',
align: 'center',
halign: 'center',
valign:'middle',
sortable:true, // 允許排序列
order:'desc', // 默認排序方式升序-asc 降序-desc
width: '2%',
}, {
field: 'name',
title: '角色名稱',
align: 'center',
valign: 'middle',
halign: 'center',
width: '14%'
}, {
field: 'remark',
title: '角色描述',
valign: 'middle',
align: 'center',
halign: 'center',
width: '20%'
}, {
field: 'is_enable',
title: '是否啟用',
valign: 'middle',
align: 'center',
halign: 'center',
width:'4%'
}, {
field: 'creater',
title: '創建人',
valign: 'middle',
align: 'center',
halign: 'center',
width:'7%'
}, {
field: 'create_time',
title: '創建時間',
valign: 'middle',
align: 'center',
halign: 'center',
width:'11%'
}, {
field: 'modifier',
title: '修改人',
valign: 'middle',
align: 'center',
halign: 'center',
width:'7%'
},{
field: 'modify_time',
title: '修改時間',
valign: 'middle',
align: 'center',
halign: 'center',
width:'11%'
},{
field:'operate',
title:'操作',
algin:'left',
halgin:'center',
width:'23%',
events: operateEvents,
formatter:operateFormatter
} ]
});
}
// 加載表格數據
loadTableData();
加載服務器數據之前的數據處理(responseHandler)
/**
* 加載服務器數據之前的處理程序,可以用來格式化數據。
* 參數:result為從服務器請求到的數據
* @param result
*/
function responseHandler(result){
if (result.success == 'false') {
alert('獲取角色信息失敗');
return;
}
// 返回數據,渲染表格
return {
total: result.data.total, //總頁數, key名稱固定為"total"
rows: result.data.rows //行數據,key名稱必須和bootstrapTable函數中dataField的值保持一致,默認為rows.
};
};
格式化操作列
/**
* 操作列格式化函數
*/
function operateFormatter(value, row, index) {
if (row.is_enable == '是') {
return ''+
'<div class="btn-group">' +
'<button class="btn btn-default asign-resource">分配資源 <i class="glyphicon glyphicon-plus"></i></button>' +
'<button class="btn btn-default edit" >修改 <i class="glyphicon glyphicon-edit"></i></button>' +
'<button class="btn btn-default delete">刪除 <i class="glyphicon glyphicon-remove"></i></button>' +
'<button class="btn btn-default switch" >禁用 <i class="glyphicon glyphicon-cog"></i></button>' +
'</div>';
} else {
return ''+
'<div class="btn-group">' +
'<button class="btn btn-default asign-resource">分配資源 <i class="glyphicon glyphicon-plus"></i></button>' +
'<button class="btn btn-default edit" >修改 <i class="glyphicon glyphicon-edit"></i></button>' +
'<button class="btn btn-default delete">刪除 <i class="glyphicon glyphicon-remove"></i></button>' +
'<button class="btn btn-default switch" >啟用 <i class="glyphicon glyphicon-cog"></i></button>' +
'</div>';
}
}
給操作列按鈕注冊點擊事件
// 給操作按鈕注冊點擊事件
window.operateEvents = {
'click .asign-resource': function (event, value, row, index) { // 注意click和.class之間必須有空格
……略
},
'click .edit': function (event, value, row, index) {
……略
},
'click .delete': function (event, value, row, index) {
……略
},
'click .switch': function (event, value, row, index) {
……略
}
};
函數參數說明:
event:jQuery事件(參考Events)。
value:字段名(實踐發現,該參數獲取到的值為undefined
row:json串格式表示的行數據
index:所點擊行的index
給toolbar工具條按鈕添加點擊事件
// 給查詢按鈕增加點擊事件
$('#' + queryBtnID).click(function () {
//刷新處理,指定query 的參數,注:此地方指定的參數,僅在當次刷新時使用
var dataArray = $('#' + queryFormID).serializeArray();
var queryContent = {}
$.each(dataArray, function () {
queryContent[this.name] = this.value;
});
// 刷新如果不指定參數刷新:$(tableSelector).bootstrapTable('refresh');
$('#' + roleTableID).bootstrapTable('refresh', {
query: queryContent
});
});
// 給表格上方的修改按鈕綁定點擊事件
$('#' + editBtnID).click(function() {
editRole('byTopEditBtn');
});
// 給表格上方的刪除按鈕綁定點擊事件
$('#' + deleteBtnID).click(function() {
deleteRole('byTopDeleteBtn');
});
提交新增、修改表單
/**
* 提交新增、修改角色表單
*/
$(document).ready(function() {
$('#' + roleFormID).submit(function() {
var dataArray = $('#' + roleFormID).serializeArray();
var data = {};
$.each(dataArray, function () {
data[this.name] = this.value;
});
var csrfToken = getCookie('csrftoken');
if (csrfToken == '') {
alert('獲取Cookie失敗');
return false;
}
if (opType == 'add') { // 新增
$.ajax({
type: "POST",
url: addRoleURL,
async: false,
data: data,
beforeSend: function (xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X_CSRFTOKEN", csrfToken);
}
},
success: function (result) {
if (result.success == 'true') {
alert(result.msg);
// 頂部插入一條記錄
$('#' + roleTableID).bootstrapTable('insertRow', {index: 0, row: result.data});
$('#' + roleTableID).bootstrapTable('refresh');
// 隱藏模態對話框,並重置數據
$('#' + roleDialogID).modal('hide');
} else {
alert(result.msg + "," + result.reason);
}
},
error: function(XmlHttpRequest, textStatus, errorThrown) {
alert('新增角色請求失敗' + XmlHttpRequest.responseText);
}
});
} else if (opType == 'update') { // 修改
data['id'] = currentRole.id;
$.ajax({
type: "POST",
url: updateRoleURL,
async: false,
data: data,
beforeSend: function (xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X_CSRFTOKEN", csrfToken);
}
},
success: function (result) {
if (result.success == 'true') {
alert(result.msg);
// 在頁面上更新角色信息
delete data['csrfmiddlewaretoken'];
// 更新行記錄
$('#' + roleTableID).bootstrapTable('updateRow', {index: parseInt(rowIndex), row:result.data});
// 隱藏模態對話框,並重置數據
$('#' + roleDialogID).modal('hide');
} else {
alert(result.msg + "," + result.reason);
// 需要手動關閉模態對話框,所以也會自動重置數據
}
},
error: function(XmlHttpRequest, textStatus, errorThrown) {
alert('修改角色請求失敗' + XmlHttpRequest.responseText);
// 需要手動關閉模態對話框,所以也會自動重置數據
}
});
}
return false; // 避免跳轉到django的返回結果數據頁
});
});
插入行
$('#tableID').bootstrapTable('insertRow', {index: 0, row: result.data});
參數說明:
index 新增行的索引
row 新增行的數據,json串表示
更新行
$('#tableID').bootstrapTable('updateRow', {index: parseInt(rowIndex), row:result.data});
參數說明
index 要更新行的索引
row 要更新行的數據據,json串表示
修改記錄
/**
* 修改角色
*/
function editRole(flag) {
opType = 'update';
if (flag == 'byTopEditBtn') { // 通過點擊表格上方的修改按鈕進入
var rowArray = $('#' + roleTableID).bootstrapTable('getSelections');
if (rowArray.length <1) {
alert('請先選擇要修改的角色');
return;
} else if (rowArray.length >1) {
alert('每次修改,只能選擇一個角色');
return;
}
// 獲取選中行索引
rowIndex = $('#' + roleTableID).find('tbody>tr.selected').first().attr('data-index');
currentRole = rowArray[0]; // 記錄當前被修改的角色信息
data = [{'name': 'roleName', 'value':rowArray[0].name}, {'name':'roleDesc', 'value':rowArray[0].remark}]
} else if (flag == 'byRowEditBtn') { // 通過點擊行右側的修改按鈕進入
data = [{'name': 'roleName', 'value':currentRole.name}, {'name':'roleDesc', 'value':currentRole.remark}]
}
// 用所選記錄信息,填充即將彈出對話框中表單組件值
$.each(data, function () {
$('#' + this.name).val(this.value);
});
$('#' + roleDialogID).modal('show'); // 打開修改模態對話框
}
獲取選中行索引
rowIndex = $('#' + roleTableID).find('tbody>tr.selected').first().attr('data-index');
這里為啥要獲取,為啥可以這么獲取?原因是這樣的,通過選擇表記錄行,然后點擊表格上方的修改按鈕修改對應記錄,這種情況下,無法直接獲取對應行記錄的索引,導致沒法更新對應記錄行,所以需要獲取索引,沒找到對應,至於為啥這么獲取,是由table 表結構決定的,如下圖:
刪除記錄
/**
* 刪除角色
*/
function deleteRole(flag) {
var idArray = [];
if (flag == 'byTopDeleteBtn') { // 通過點擊表格上方的刪除按鈕進入
rowArray = $('#' + roleTableID).bootstrapTable('getSelections');
if (rowArray.length <1) {
alert('請先選擇要刪除的角色');
return;
}
} else if (flag == 'byRowDeleteBtn') { // 通過點擊行右側的刪除按鈕進入
idArray.push(currentRole.id);
}
var mark = true; // 標記是否刪除成功
if (confirm('是否刪除選中記錄?')) {
$.each(rowArray, function() {
idArray.push(this.id);
});
$.ajax({
type: "POST",
url: deleteRoleURL,
async: false,
data: {'idArray':"" + idArray + ""},
success: function (result) {
if (result.success == 'true') {
alert(result.msg);
// 批量刪除對應記錄行
$('#' + roleTableID).bootstrapTable('remove',{ field: 'id', values: idArray});
//$('#' + roleTableID).bootstrapTable('refresh');
} else {
alert(result.msg + "," + result.reason);
}
},
error: function(XmlHttpRequest, textStatus, errorThrown) {
alert('刪除角色請求失敗' + XmlHttpRequest.responseText);
}
});
}
}
刪除記錄
$('#tableID').bootstrapTable('remove',{ field: 'id', values: idArray});
field: 需要刪除的行的 field 名稱,
values: 需要刪除的行的值,類型為數組。
獲取選中行
$('#tableID').bootstrapTable('getSelections');
getSelections 返回所選的行,當沒有選擇任何行的時候返回一個空數組
后台代碼片段
查詢表數據
def role_tabe_data(request):
'''
獲取角色表數據
:param request:
'''
if request.method == 'GET':
rows = [] # 用於存儲記錄行
table_data = {"total": 0, "rows": []}
try:
params = request.GET
# search = params.get('search') # 通過表格插件自帶的搜索框搜索的內容 # 如果要實現,需要確認按哪些列搜索
page_size = int(params.get('limit')) # 每頁記錄數
offset = int(params.get('offset'))
page_index = offset // page_size + 1 # 第幾頁數據
sort = params.get('sort') # 排序字段 // 初始化頁面時,無排序獲取值為None
order = params.get('order') # 排序方式
role_name = params.get('roleNameQ') # 角色名稱
start_time = params.get('startTime') # 開始時間
end_time = params.get('endTime') # 結束時間
sql_ddl = 'select id, name, remark, is_enable, creater, create_time, modifier, modify_time from website_role '
if role_name:
sql_ddl = sql_ddl + "where name like '%s%s' " % (role_name, '%%')
temp_mark = 1
else:
temp_mark = 0
if start_time:
if temp_mark:
sql_ddl = sql_ddl + "and create_time>='%s' " % start_time
else:
sql_ddl = sql_ddl + "where create_time>='%s' " % start_time
temp_mark = 1
else:
temp_mark = 0
if end_time:
if temp_mark:
sql_ddl = sql_ddl + "and create_time<='%s' " % end_time
else:
sql_ddl = sql_ddl + "where create_time<='%s' " % start_time
if order and sort:
sql_ddl = sql_ddl + 'order by %s %s' % (sort, order)
else:
sql_ddl = sql_ddl + 'order by id desc' # 最新創建的排在最前面
records = Role.objects.raw(sql_ddl)
records = json.loads(serializers.serialize('json', records), encoding='utf-8')
table_data["total"] = len(records)
paginator = Paginator(records, page_size) # 設置每頁展示的數據
try:
page = paginator.page(page_index)
except PageNotAnInteger as e: # 如果請求的頁面編號不存在,返回第一頁數據
logger.warn('%s' % e)
page = paginator.page(1)
except EmptyPage as e: # 如果請求頁面,超出頁面范圍,返回最后一頁數據
logger.warn('%s' % e)
page = paginator.page(paginator.num_pages)
records = page.object_list
for record in records:
row = {}
row['id'] = record['pk']
row.update(record['fields'])
if row['is_enable']:
row['is_enable'] = '是'
else:
row['is_enable'] = '否'
rows.append(row)
table_data["rows"] = rows
content = {'data':table_data, 'msg':'獲取角色信息成功', 'success':'true', 'reason': ''}
except Exception as e:
logger.error('getting roles info data failed: %s' % e)
content = {'data':[], 'msg':'獲取角色信息失敗', 'success':'false', 'reason': '%s' % e}
else:
logger.error('only get method allowed for getting roles data')
content = {'data':[], 'msg':'獲取角色信息失敗', 'success':'false', 'reason': 'only get method allowed for getting roles data'}
return JsonResponse(content)
說明:
bootstarp-table默認只支持按單列排序,默認打開頁面,請求表數據時,會附加提供以下參數:
order=asc&offset=0&limit=pageSize
或者如下(添加了搜索框的情況下)
search=&order=asc&offset=0&limit=pageSize
search:前端輸入的搜索內容
order:排序方式,asc - 升序 desc - 降序
sort:需要排序的列
offset:偏移
limit:限制查詢返回記錄數,即每頁記錄數
如下,我們可以通過limit和offset獲取要查詢要查詢頁面的索引(索引從1開始)
page_size = int(params.get('limit')) # 每頁記錄數
offset = int(params.get('offset'))
page_index = offset // page_size + 1 # 第幾頁數據
新增記錄
def add_role(request):
'''
新增角色
'''
if request.method == 'POST':
try:
params = request.POST
creater = str(request.user)
role_name = params.get('roleName') # 資源名稱
role_desc = params.get('roleDesc') # 資源描述
create_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
# 驗證數據合法性
if not role_name:
content = {'msg':'新增角色失敗', 'success':'false', 'reason': '角色名稱不能為空'}
return JsonResponse(content)
role_obj = Role(name=role_name,
remark=role_desc,
is_enable=1,
creater = creater,
create_time=create_time)
role_obj.save()
data = {'id':role_obj.id, 'name':role_name, 'remark':role_desc, 'is_enable':'是', 'creater':str(creater), 'create_time':create_time, 'modifier':'-', 'modify_time':'-' }
content = {'data':data, 'msg':'新增角色成功', 'success':'true', 'reason':''}
except Exception as e:
logger.error('adding role failed: %s' % e)
content = {'data':{}, 'msg':'新增角色失敗', 'success':'false', 'reason': '%s' % e}
else:
logger.error('only post method allowed for adding role data')
content = {'data':{}, 'msg':'新增角色失敗', 'success':'false', 'reason': 'only get method allowed for adding role data'}
return JsonResponse(content)
修改記錄
def update_role(request):
'''
修改角色
'''
if request.method == 'POST':
try:
params = request.POST
modifier = str(request.user)
id = params['id']
role_name = params['roleName'] # 資源名稱
role_desc = params['roleDesc'] # 資源描述
modify_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
# 數據合法性驗證
if not Role.objects.exclude(id=id).exists():
return JsonResponse({'msg':'修改失敗', 'success':'false', 'reason': '角色不存在'})
# 更新數據
obj = Role.objects.get(id=id)
obj.name = role_name
obj.remark = role_desc
obj.modify_time = modify_time
obj.modifier = modifier
obj.save()
data = { 'name':role_name, 'remark':role_desc, 'modify_time':modify_time, 'modifier':modifier} # 返回需要更新的數據,以便頁面更新對應行信息
content = {'msg':'修改成功', 'data':data, 'success':'true', 'reason':''}
except Exception as e:
logger.error('updating role failed: %s' % e)
content = {'msg':'修改失敗', 'data':{}, 'success':'false', 'reason': '%s' % e}
else:
logger.error('only post method allowed for updating role')
content = {'msg':'修改失敗', 'data':{}, 'success':'false', 'reason': 'only post method allowed for updating role'}
return JsonResponse(content)
刪除記錄
def delete_role(request):
'''
刪除角色
'''
if request.method == 'POST':
try:
params = request.POST
id_list = eval(params.get('idArray') + ",") # 如果不加逗號,前端只傳遞一個參數時,這里獲取到的id_list為單個整數值
mark = True
reason = ''
try:
with transaction.atomic():
for id in id_list:
role = Role.objects.filter(id=id)
if role.exists():
role.delete()
except Exception as e:
reason = 'deleting role failed: %s' % e
logger.error(reason)
mark = False
if mark:
return JsonResponse({'msg':'刪除成功', 'success':'true', 'reason': ''})
else:
return JsonResponse({'msg':'刪除失敗', 'success':'false', 'reason': '%s' % reason})
except Exception as e:
logger.error('deleting role failed: %s' % e)
content = {'msg':'刪除失敗', 'success':'false', 'reason': '%s' % e}
else:
logger.error('only post method allowed for deleting role')
content = {'msg':'刪除失敗', 'success':'false', 'reason': 'only post method allowed for deleting role'}
return JsonResponse(content)
- 3. 參考鏈接
http://bootstrap-table.wenzhixin.net.cn/zh-cn/documentation/