Ajax获取PHP端csv转的json数据并js前端排序与分页
<?php
setlocale(LC_ALL, 'C'); //window:删除行首双斜杠
if($_GET["act"]=="list"){
$csvFile = 'book.csv'; // 文件路径:制表符分隔文件
$data = [];
if (($handle = fopen($csvFile, 'r')) !== false) {
$header = fgetcsv($handle,0,"\t"); // 读取表头
while (($row = fgetcsv($handle,0,"\t")) !== false) {
$data[] = array_combine($header, $row); // 将表头与数据组合
}
fclose($handle);
}
header('Content-Type: application/json');
echo json_encode($data);
exit();
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>数据表格</title>
<style>
.container {
margin: 20px;
}
table {
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
}
th, td {
border: 1px solid #ddd;
padding: 5px;
text-align: left;
}
th {
background-color: #f5f5f5;
position: relative;
padding-right: 25px;
cursor: pointer;
}
.sort-arrows {
position: absolute;
right: 5px;
top: 50%;
transform: translateY(-50%);
display: flex;
flex-direction: column;
line-height: 8px;
}
.arrow {
font-size: 8px;
color: #666;
}
.arrow.active {
color: red;
}
.pagination {
display: flex;
gap: 10px;
align-items: center;
justify-content: center;
}
button {
padding: 5px 10px;
cursor: pointer;
}
select {
padding: 5px;
}
tr:nth-child(even) {
background-color: #f9f9f9;
}
tr:hover {
background-color: #f5f5f5;
}
</style>
</head>
<body>
<div class="container">
<table id="dataTable">
<thead>
<tr id="headerRow">
<!-- 表头将由JS动态生成 -->
</tr>
</thead>
<tbody id="tableBody">
<!-- 数据行将由JS动态生成 -->
</tbody>
</table>
<div class="pagination">
<button id="firstPage">首页</button>
<button id="prevPage">上一页</button>
<select id="pageSelect"></select>
<button id="nextPage">下一页</button>
<button id="lastPage">尾页</button>
</div>
</div>
<script>
class DataTable {
constructor() {
this.data = [];
this.currentPage = 1;
this.rowsPerPage = 10;
this.sortColumn = null;
this.sortDirection = 'asc';
this.init();
}
init() {
this.loadData();
this.bindEvents();
}
async loadData() {
try {
const response = await fetch('?act=list&tt=tt');
const jsonData = await response.json();
this.data = jsonData;
this.setupTable();
this.renderTable();
this.setupPagination();
} catch (error) {
console.error('数据加载失败:', error);
}
}
setupTable() {
if (this.data.length === 0) return;
const headerRow = document.getElementById('headerRow');
headerRow.innerHTML = '';
// 创建表头
Object.keys(this.data[0]).forEach(key => {
const th = document.createElement('th');
th.innerHTML = `
${key}
<div class="sort-arrows">
<span class="arrow up" data-column="${key}">▲</span>
<span class="arrow down" data-column="${key}">▼</span>
</div>
`;
headerRow.appendChild(th);
});
}
renderTable() {
const tableBody = document.getElementById('tableBody');
tableBody.innerHTML = '';
// 排序数据
let sortedData = [...this.data];
if (this.sortColumn) {
sortedData.sort((a, b) => {
const aVal = a[this.sortColumn];
const bVal = b[this.sortColumn];
if (this.sortDirection === 'asc') {
return aVal > bVal ? 1 : -1;
} else {
return aVal < bVal ? 1 : -1;
}
});
}
// 分页
const start = (this.currentPage - 1) * this.rowsPerPage;
const paginatedData = sortedData.slice(start, start + this.rowsPerPage);
// 渲染数据行
paginatedData.forEach(row => {
const tr = document.createElement('tr');
Object.values(row).forEach(value => {
const td = document.createElement('td');
td.textContent = value;
tr.appendChild(td);
});
tableBody.appendChild(tr);
});
}
setupPagination() {
const totalPages = Math.ceil(this.data.length / this.rowsPerPage);
const pageSelect = document.getElementById('pageSelect');
pageSelect.innerHTML = '';
for (let i = 1; i <= totalPages; i++) {
const option = document.createElement('option');
option.value = i;
option.textContent = `第${i}页`;
pageSelect.appendChild(option);
}
}
bindEvents() {
// 排序事件
document.getElementById('headerRow').addEventListener('click', (e) => {
const arrow = e.target.closest('.arrow');
if (!arrow) return;
const column = arrow.dataset.column;
const isUp = arrow.classList.contains('up');
// 重置所有箭头样式
document.querySelectorAll('.arrow').forEach(a => a.classList.remove('active'));
// 设置当前箭头样式
arrow.classList.add('active');
this.sortColumn = column;
this.sortDirection = isUp ? 'asc' : 'desc';
this.renderTable();
});
// 分页事件
document.getElementById('firstPage').addEventListener('click', () => {
this.currentPage = 1;
this.renderTable();
});
document.getElementById('prevPage').addEventListener('click', () => {
if (this.currentPage > 1) {
this.currentPage--;
this.renderTable();
}
});
document.getElementById('pageSelect').addEventListener('change', (e) => {
this.currentPage = parseInt(e.target.value);
this.renderTable();
});
document.getElementById('nextPage').addEventListener('click', () => {
const totalPages = Math.ceil(this.data.length / this.rowsPerPage);
if (this.currentPage < totalPages) {
this.currentPage++;
this.renderTable();
}
});
document.getElementById('lastPage').addEventListener('click', () => {
this.currentPage = Math.ceil(this.data.length / this.rowsPerPage);
this.renderTable();
});
}
}
// 初始化表格
document.addEventListener('DOMContentLoaded', () => {
new DataTable();
});
</script>
</body>
</html>
数据示范:制表符分隔的,可以直接excel复制粘贴
姓名 学号 身份证号 科目1 科目2 科目3 科目4 科目5 科目. 科目N
李一 10001001 90001001 87 84 75 91 83 76 87
李二 10001002 90001002 95 81 81 71 60 82 99
李三 10001003 90001003 68 80 65 79 68 71 91
李四 10001004 90001004 82 80 75 90 87 64 81
李五 10001005 90001005 60 64 61 71 73 85 61