<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Bootstrap Table 示例 (Bootstrap 5)</title>
<!-- Bootstrap 5 CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<!-- Bootstrap Icons -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css">
<!-- Bootstrap Table CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-table@1.24.1/dist/bootstrap-table.min.css">
<!-- Bootstrap Table Fixed Columns CSS -->
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap-table@1.24.1/dist/extensions/fixed-columns/bootstrap-table-fixed-columns.min.css">
<!-- Bootstrap Table Export CSS -->
<style>
.toolbar {
margin-bottom: 10px;
}
.editable-input {
width: 100%;
padding: 0.375rem 0.75rem;
font-size: 1rem;
border: 1px solid #ced4da;
border-radius: 0.375rem;
}
.editable-input:focus {
border-color: #86b7fe;
outline: 0;
box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);
}
.edit-actions {
display: flex;
gap: 5px;
}
.edit-btn {
padding: 0.1rem 0.3rem;
font-size: 0.8rem;
}
.editing-row .editable {
display: none;
}
/* 添加编辑状态下的样式 */
.is-editing .edit-btn.edit {
background-color: #198754;
border-color: #198754;
color: white;
}
/* 设置表格容器高度 */
.fixed-table-container {
height: 500px !important;
}
</style>
</head>
<body>
<div class="container-fluid mt-3">
<h2>Bootstrap Table 示例 (Bootstrap 5)</h2>
<div class="toolbar">
<button id="addRow" class="btn btn-primary">添加行</button>
<button id="removeRow" class="btn btn-danger">删除选中行</button>
</div>
<table id="table">
</table>
</div>
<!-- jQuery -->
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>
<!-- Bootstrap 5 JS -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<!-- Bootstrap Table JS -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap-table@1.24.1/dist/bootstrap-table.min.js"></script>
<!-- Bootstrap Table 中文语言包 -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap-table@1.24.1/dist/locale/bootstrap-table-zh-CN.min.js"></script>
<!-- Bootstrap Table Fixed Columns JS -->
<script
src="https://cdn.jsdelivr.net/npm/bootstrap-table@1.24.1/dist/extensions/fixed-columns/bootstrap-table-fixed-columns.min.js"></script>
<!-- Bootstrap Table Export JS -->
<script src="https://cdn.jsdelivr.net/npm/tableexport.jquery.plugin@1.28.0/tableExport.min.js"></script>
<script
src="https://cdn.jsdelivr.net/npm/bootstrap-table@1.24.1/dist/extensions/export/bootstrap-table-export.min.js"></script>
<script>
$(document).ready(function () {
// 准备数据
var data = [
{ id: 1, name: '张三', position: '前端工程师', office: '北京', age: 28, startDate: '2020-03-15', salary: '12000' },
{ id: 2, name: '李四', position: '后端工程师', office: '上海', age: 32, startDate: '2019-07-01', salary: '15000' },
{ id: 3, name: '王五', position: '全栈工程师', office: '深圳', age: 26, startDate: '2021-02-20', salary: '18000' },
{ id: 4, name: '赵六', position: '产品经理', office: '杭州', age: 30, startDate: '2018-11-10', salary: '20000' },
{ id: 5, name: '钱七', position: 'UI设计师', office: '广州', age: 25, startDate: '2022-01-05', salary: '10000' },
{ id: 6, name: '孙八', position: '前端工程师', office: '成都', age: 27, startDate: '2020-09-18', salary: '13000' },
{ id: 7, name: '周九', position: '后端工程师', office: '武汉', age: 29, startDate: '2019-05-12', salary: '16000' },
{ id: 8, name: '吴十', position: '测试工程师', office: '南京', age: 24, startDate: '2021-08-30', salary: '9000' },
{ id: 9, name: '王五', position: '全栈工程师', office: '深圳', age: 26, startDate: '2021-02-20', salary: '18000' },
{ id: 10, name: '周九', position: '后端工程师', office: '武汉', age: 29, startDate: '2019-05-12', salary: '16000' },
{ id: 11, name: '张三', position: '前端工程师', office: '北京', age: 28, startDate: '2020-03-15', salary: '12000' },
{ id: 12, name: '李四', position: '后端工程师', office: '上海', age: 32, startDate: '2019-07-01', salary: '15000' },
{ id: 13, name: '王五', position: '全栈工程师', office: '深圳', age: 26, startDate: '2021-02-20', salary: '18000' },
{ id: 14, name: '赵六', position: '产品经理', office: '杭州', age: 30, startDate: '2018-11-10', salary: '20000' },
{ id: 15, name: '钱七', position: 'UI设计师', office: '广州', age: 25, startDate: '2022-01-05', salary: '10000' },
{ id: 16, name: '孙八', position: '前端工程师', office: '成都', age: 27, startDate: '2020-09-18', salary: '13000' },
{ id: 17, name: '周九', position: '后端工程师', office: '武汉', age: 29, startDate: '2019-05-12', salary: '16000' },
{ id: 18, name: '吴十', position: '测试工程师', office: '南京', age: 24, startDate: '2021-08-30', salary: '9000' },
{ id: 19, name: '钱七', position: 'UI设计师', office: '广州', age: 25, startDate: '2022-01-05', salary: '10000' },
{ id: 20, name: '孙八', position: '前端工程师', office: '成都', age: 27, startDate: '2020-09-18', salary: '13000' },
{ id: 21, name: '张三', position: '前端工程师', office: '北京', age: 28, startDate: '2020-03-15', salary: '12000' },
{ id: 22, name: '李四', position: '后端工程师', office: '上海', age: 32, startDate: '2019-07-01', salary: '15000' },
{ id: 23, name: '王五', position: '全栈工程师', office: '深圳', age: 26, startDate: '2021-02-20', salary: '18000' },
{ id: 24, name: '赵六', position: '产品经理', office: '杭州', age: 30, startDate: '2018-11-10', salary: '20000' },
{ id: 25, name: '钱七', position: 'UI设计师', office: '广州', age: 25, startDate: '2022-01-05', salary: '10000' },
{ id: 26, name: '孙八', position: '前端工程师', office: '成都', age: 27, startDate: '2020-09-18', salary: '13000' },
{ id: 27, name: '周九', position: '后端工程师', office: '武汉', age: 29, startDate: '2019-05-12', salary: '16000' },
{ id: 28, name: '吴十', position: '测试工程师', office: '南京', age: 24, startDate: '2021-08-30', salary: '9000' }
];
// 初始化表格并加载数据
$('#table').bootstrapTable({
data: data,
columns: [{
checkbox: true, // 是否显示复选框列
visible: true // 是否可见
}, {
field: 'id',
title: 'ID',
sortable: true, // 是否可排序
fixed: 'left' // 固定第一列
}, {
field: 'name',
title: '姓名',
sortable: true,
formatter: editFormatter, // 单元格格式化函数,用于自定义显示内容
fixed: 'left' // 固定第二列
}, {
field: 'position',
title: '职位',
sortable: true,
formatter: editFormatter
}, {
field: 'office',
title: '办公室',
sortable: true,
formatter: editFormatter
}, {
field: 'age',
title: '年龄',
sortable: true,
formatter: editFormatter
}, {
field: 'startDate',
title: '入职日期',
sortable: true,
formatter: editFormatter
}, {
field: 'salary',
title: '薪资',
sortable: true,
formatter: editFormatter
}, {
field: 'operate',
title: '操作',
align: 'center',
events: window.operateEvents, // 列内元素的事件处理对象,绑定操作事件
formatter: operateFormatter,
fixed: 'right' // 列固定位置,可选 'left'(左固定) 或 'right'(右固定)
}],
toolbar: '.toolbar',
search: true,
showRefresh: true,
showToggle: true,
showFullscreen: true,
showColumns: true,
showColumnsToggleAll: true,
showExport: true,
clickToSelect: true, // 是否启用点击行选择功能
detailFormatter: detailFormatter, // 详情行格式化函数
minimumCountColumns: 2, // 最少显示的列数
showPaginationSwitch: true, // 是否显示分页切换按钮
pagination: true, // 是否启用分页
idField: 'id', // 主键字段名
pageList: [10, 25, 50, 100, 'all'],
showFooter: false, // 是否显示表脚
sidePagination: 'client', // 分页方式,'client'(客户端) 或 'server'(服务器端)
responseHandler: responseHandler, // 服务器响应数据处理函数
fixedColumns: true, // 启用固定列功能
fixedNumber: 2, // 固定前2列
fixedRightNumber: 1, // 固定右侧1列
height: 500, // 设置表格高度以启用固定表头
exportOptions: { // 用于配置数据导出功能的相关参数
fileName: '员工信息表',
ignoreColumn: [0, 8], // 导出时需要忽略的列索引数组,忽略第0列和第8列的数据导出
pdfmake: { // PDF生成配置选项
enabled: true,
docDefinition: {
pageOrientation: 'landscape'
}
}
}
});
// 添加行按钮事件
$('#addRow').click(function () {
var newRow = {
id: $('#table').bootstrapTable('getData').length + 1,
name: '',
position: '',
office: '',
age: '',
startDate: '',
salary: ''
};
$('#table').bootstrapTable('append', newRow);
// 延迟执行以确保数据已添加
setTimeout(function () {
// 获取总页数并跳转到最后一页
var options = $('#table').bootstrapTable('getOptions');
var totalRows = options.totalRows;
var pageSize = options.pageSize;
var lastPage = Math.ceil(totalRows / pageSize);
$('#table').bootstrapTable('selectPage', lastPage);
}, 100);
});
// 删除行按钮事件
$('#removeRow').click(function () {
var selections = $('#table').bootstrapTable('getSelections');
if (selections.length === 0) {
alert('请先选择要删除的行');
return;
}
var ids = $.map(selections, function (row) {
return row.id;
});
$('#table').bootstrapTable('remove', {
field: 'id',
values: ids
});
});
});
// 编辑格式化器
function editFormatter(value, row, index, field) {
return [
'<span class="editable" data-field="' + field + '" data-index="' + index + '">' + (value || '') + '</span>'
].join('');
}
// 操作列格式化
function operateFormatter(value, row, index) {
// 检查当前行是否处于编辑状态
if (row.isEditing) {
return [
'<a class="save btn btn-sm btn-success edit-btn" href="javascript:void(0)" title="保存">',
'保存',
'</a> ',
'<a class="cancel btn btn-sm btn-secondary edit-btn" href="javascript:void(0)" title="取消">',
'取消',
'</a>'
].join('');
} else {
return [
'<a class="edit btn btn-sm btn-outline-primary edit-btn" href="javascript:void(0)" title="编辑">',
'编辑',
'</a> ',
'<a class="remove btn btn-sm btn-outline-danger edit-btn" href="javascript:void(0)" title="删除">',
'删除',
'</a>'
].join('');
}
}
// 操作事件
window.operateEvents = {
'click .edit': function (e, value, row, index) {
startEdit(row, index);
console.log('编辑', index, row);
},
'click .save': function (e, value, row, index) {
saveEdit(row, index);
console.log('保存', index, row);
},
'click .cancel': function (e, value, row, index) {
cancelEdit(row, index);
console.log('取消', index, row);
},
'click .remove': function (e, value, row, index) {
$('#table').bootstrapTable('remove', {
field: 'id',
values: [row.id]
});
console.log('删除', index, row);
}
};
// 开始编辑
function startEdit(row, index) {
// 获取表格当前数据
var data = $('#table').bootstrapTable('getData');
// 创建一个干净的原始数据副本
var originalData = $.extend(true, {}, data[index]);
// 确保移除所有与编辑状态相关的属性
delete originalData.isEditing;
delete originalData.originalData;
// 保存原始数据副本
data[index].originalData = originalData;
// 标记行为编辑状态
data[index].isEditing = true;
// 更新行以显示编辑控件
$('#table').bootstrapTable('updateRow', {
index: index,
row: createEditRow(data[index], index)
});
}
// 保存编辑
function saveEdit(row, index) {
var rowData = $('#table').bootstrapTable('getData')[index];
// 获取编辑后的值
var $tr = $('#table').find('tbody tr[data-index="' + index + '"]');
$tr.find('input, select').each(function () {
var field = $(this).data('field');
if (field) {
rowData[field] = $(this).val();
}
});
// 移除编辑状态标记和原始数据
delete rowData.isEditing;
delete rowData.originalData;
// 更新行
$('#table').bootstrapTable('updateRow', {
index: index,
row: rowData
});
}
// 取消编辑
function cancelEdit(row, index) {
// 获取表格当前数据
var data = $('#table').bootstrapTable('getData');
// 获取原始数据
var originalRow = data[index].originalData;
// 确保移除编辑状态标记
originalRow.isEditing = false;
delete originalRow.originalData;
// 恢复原始数据
$('#table').bootstrapTable('updateRow', {
index: index,
row: originalRow
});
console.log('取消', index, originalRow);
}
// 创建编辑行
function createEditRow(row, index) {
var editRow = $.extend(true, {}, row);
editRow.name = '<input type="text" class="editable-input" data-field="name" value="' + (row.name || '') + '">';
editRow.position = '<select class="editable-input" data-field="position">' +
'<option value="前端工程师" ' + (row.position === '前端工程师' ? 'selected' : '') + '>前端工程师</option>' +
'<option value="后端工程师" ' + (row.position === '后端工程师' ? 'selected' : '') + '>后端工程师</option>' +
'<option value="全栈工程师" ' + (row.position === '全栈工程师' ? 'selected' : '') + '>全栈工程师</option>' +
'<option value="产品经理" ' + (row.position === '产品经理' ? 'selected' : '') + '>产品经理</option>' +
'<option value="UI设计师" ' + (row.position === 'UI设计师' ? 'selected' : '') + '>UI设计师</option>' +
'<option value="测试工程师" ' + (row.position === '测试工程师' ? 'selected' : '') + '>测试工程师</option>' +
'</select>';
editRow.office = '<input type="text" class="editable-input" data-field="office" value="' + (row.office || '') + '">';
editRow.age = '<input type="number" class="editable-input" data-field="age" value="' + (row.age || '') + '">';
editRow.startDate = '<input type="date" class="editable-input" data-field="startDate" value="' + (row.startDate || '') + '">';
editRow.salary = '<input type="text" class="editable-input" data-field="salary" value="' + (row.salary || '') + '">';
return editRow;
}
// 详情格式化
function detailFormatter(index, row) {
var html = [];
$.each(row, function (key, value) {
html.push('<p><b>' + key + ':</b> ' + value + '</p>');
});
return html.join('');
}
// 数据响应处理
function responseHandler(res) {
return res;
}
</script>
</body>
</html>