模拟Ajax获取数据,表格分页显示
模拟Ajax获取数据。表格显示, 带有分页功能,支持翻页,每页显示8行数据。响应式设计,适配不同屏幕尺寸
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ajax数据表格分页</title>
<style>
:root {
--primary-color: #3498db;
--secondary-color: #2980b9;
--border-color: #bdc3c7;
--text-color: #2c3e50;
--light-bg: #f8f9fa;
--success-color: #2ecc71;
--danger-color: #e74c3c;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
line-height: 1.6;
color: var(--text-color);
background-color: #f5f7fa;
padding: 20px;
max-width: 1200px;
margin: 0 auto;
}
.container {
background-color: white;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
padding: 25px;
margin-bottom: 20px;
}
h1 {
text-align: center;
color: var(--primary-color);
margin-bottom: 10px;
}
.description {
text-align: center;
color: #7f8c8d;
margin-bottom: 30px;
}
.controls {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
flex-wrap: wrap;
gap: 15px;
}
#btn {
background-color: var(--primary-color);
color: white;
border: none;
padding: 12px 24px;
font-size: 16px;
border-radius: 4px;
cursor: pointer;
transition: all 0.3s;
display: flex;
align-items: center;
gap: 8px;
}
#btn:hover {
background-color: var(--secondary-color);
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
#btn:disabled {
background-color: #95a5a6;
cursor: not-allowed;
transform: none;
box-shadow: none;
}
.spinner {
display: inline-block;
width: 20px;
height: 20px;
border: 3px solid rgba(255,255,255,.3);
border-radius: 50%;
border-top-color: #fff;
animation: spin 1s ease-in-out infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
.status {
padding: 10px 15px;
border-radius: 4px;
font-weight: 500;
}
.status.loading {
background-color: #fff9e6;
color: #e67e22;
border-left: 4px solid #e67e22;
}
.status.success {
background-color: #e8f6ef;
color: var(--success-color);
border-left: 4px solid var(--success-color);
}
.status.error {
background-color: #fdeded;
color: var(--danger-color);
border-left: 4px solid var(--danger-color);
}
table {
width: 100%;
border-collapse: collapse;
margin: 20px 0;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
background-color: white;
}
th, td {
border: 1px solid var(--border-color);
padding: 12px 15px;
text-align: center;
}
th {
background-color: var(--primary-color);
color: white;
font-weight: 600;
position: sticky;
top: 0;
}
tr:nth-child(even) {
background-color: #f8f9fa;
}
tr:hover {
background-color: #e9f7fe;
}
tr.empty-row {
background-color: #f9f9f9;
}
tr.empty-row td {
color: #aaa;
font-style: italic;
}
.pagination {
display: flex;
justify-content: center;
align-items: center;
margin-top: 25px;
gap: 10px;
flex-wrap: wrap;
}
.pagination button {
background-color: white;
border: 1px solid var(--border-color);
color: var(--text-color);
padding: 8px 15px;
border-radius: 4px;
cursor: pointer;
transition: all 0.3s;
}
.pagination button:hover:not(:disabled) {
background-color: var(--primary-color);
color: white;
border-color: var(--primary-color);
}
.pagination button:disabled {
background-color: #ecf0f1;
color: #bdc3c7;
cursor: not-allowed;
}
.pagination .page-info {
margin: 0 15px;
font-weight: 500;
}
.empty {
text-align: center;
padding: 40px 20px;
color: #7f8c8d;
font-style: italic;
background-color: #f8f9fa;
border-radius: 4px;
}
.footer {
text-align: center;
margin-top: 30px;
color: #7f8c8d;
font-size: 0.9rem;
}
@media (max-width: 768px) {
.controls {
flex-direction: column;
align-items: stretch;
}
table {
font-size: 14px;
}
th, td {
padding: 8px 10px;
}
.pagination {
flex-direction: column;
gap: 15px;
}
.pagination .page-info {
margin: 10px 0;
}
}
</style>
</head>
<body>
<div class="container">
<div class="controls">
<button id="btn">
<span class="spinner" style="display: none;"></span>
加载数据
</button>
<div id="status" class="status" style="display: none;"></div>
</div>
<div id="mylist">
<div class="empty">暂无数据,请点击"加载数据"按钮获取数据</div>
</div>
<div class="pagination" id="pagination" style="display: none;">
<button id="first-page">首页</button>
<button id="prev-page">上一页</button>
<span class="page-info">第 <span id="current-page">1</span> 页,共 <span id="total-pages">1</span> 页</span>
<button id="next-page">下一页</button>
<button id="last-page">末页</button>
</div>
</div>
<div class="footer">
<p>Ajax数据表格分页示例 © 2023</p>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const btn = document.getElementById('btn');
const mylist = document.getElementById('mylist');
const pagination = document.getElementById('pagination');
const statusEl = document.getElementById('status');
const spinner = btn.querySelector('.spinner');
// 分页相关元素
const firstPageBtn = document.getElementById('first-page');
const prevPageBtn = document.getElementById('prev-page');
const nextPageBtn = document.getElementById('next-page');
const lastPageBtn = document.getElementById('last-page');
const currentPageEl = document.getElementById('current-page');
const totalPagesEl = document.getElementById('total-pages');
const url = "http://localhost:3000/result";
// 分页变量
let currentPage = 1;
let itemsPerPage = 8;
let allData = [];
// 真正的数据获取函数
function fetchRealData() {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.onload = function() {
if (xhr.status >= 200 && xhr.status < 300) {
try {
const result = JSON.parse(xhr.responseText);
resolve(result);
} catch (e) {
reject(new Error("解析响应数据失败: " + e.message));
}
} else {
reject(new Error("请求失败,状态码: " + xhr.status));
}
};
xhr.onerror = function() {
reject(new Error("网络错误,请检查连接"));
};
xhr.send();
});
}
// 备用模拟数据函数
function generateMockData() {
const mockData = [];
const dates = ['2023-10-01', '2023-10-02', '2023-10-03', '2023-10-04', '2023-10-05',
'2023-10-06', '2023-10-07', '2023-10-08', '2023-10-09', '2023-10-10'];
// 生成随机数量的数据(5-15条)
const dataCount = Math.floor(Math.random() * 11) + 5;
for (let i = 1; i <= dataCount; i++) {
mockData.push({
id: i,
createDate: dates[Math.floor(Math.random() * dates.length)],
wtI1: Math.floor(Math.random() * 100),
wtI2: Math.floor(Math.random() * 100),
blT1: (Math.random() * 50).toFixed(2),
blT2: (Math.random() * 50).toFixed(2),
diB1: Math.floor(Math.random() * 10),
diB2: Math.floor(Math.random() * 10)
});
}
return { listEntity: mockData };
}
// 加载数据按钮点击事件
btn.addEventListener('click', function() {
// 显示加载状态
btn.disabled = true;
spinner.style.display = 'inline-block';
btn.textContent = '加载中...';
showStatus('正在加载数据,请稍候...', 'loading');
// 尝试从真实API获取数据,失败则使用模拟数据
fetchRealData()
.then(result => {
allData = result.listEntity || [];
handleDataLoadSuccess();
})
.catch(error => {
console.warn('真实API请求失败,使用模拟数据:', error.message);
// 使用模拟数据作为备用
const mockResult = generateMockData();
allData = mockResult.listEntity;
handleDataLoadSuccess();
});
});
function handleDataLoadSuccess() {
// 重置按钮状态
btn.disabled = false;
spinner.style.display = 'none';
btn.innerHTML = '<span class="spinner" style="display: none;"></span>重新加载数据';
currentPage = 1;
showStatus(`成功加载 ${allData.length} 条数据`, 'success');
renderTable();
setupPagination();
}
// 显示状态信息
function showStatus(message, type) {
statusEl.textContent = message;
statusEl.className = `status ${type}`;
statusEl.style.display = 'block';
// 3秒后自动隐藏成功/错误消息
if (type !== 'loading') {
setTimeout(() => {
statusEl.style.display = 'none';
}, 3000);
}
}
// 渲染表格
function renderTable() {
if (!allData || allData.length === 0) {
mylist.innerHTML = '<div class="empty">暂无数据</div>';
pagination.style.display = 'none';
return;
}
// 计算当前页的数据
const startIndex = (currentPage - 1) * itemsPerPage;
const endIndex = Math.min(startIndex + itemsPerPage, allData.length);
const currentPageData = allData.slice(startIndex, endIndex);
// 创建表格结构
let tableHTML = '<table>' +
'<thead><tr>' +
'<th>ID</th>' +
'<th>日期</th>' +
'<th>WTI首行</th>' +
'<th>WTI次行</th>' +
'<th>BLT首行</th>' +
'<th>BLT次行</th>' +
'<th>DIB首行</th>' +
'<th>DIB次行</th>' +
'</tr></thead><tbody>';
// 添加表格行
currentPageData.forEach(item => {
tableHTML += '<tr>' +
'<td>' + (item.id || '-') + '</td>' +
'<td>' + (item.createDate ? item.createDate.substring(0, 10) : '-') + '</td>' +
'<td>' + (item.wtI1 || '-') + '</td>' +
'<td>' + (item.wtI2 || '-') + '</td>' +
'<td>' + (item.blT1 || '-') + '</td>' +
'<td>' + (item.blT2 || '-') + '</td>' +
'<td>' + (item.diB1 || '-') + '</td>' +
'<td>' + (item.diB2 || '-') + '</td>' +
'</tr>';
});
// 补齐空行
const emptyRowsCount = itemsPerPage - currentPageData.length;
for (let i = 0; i < emptyRowsCount; i++) {
tableHTML += '<tr class="empty-row">' +
'<td>-</td>' +
'<td>-</td>' +
'<td>-</td>' +
'<td>-</td>' +
'<td>-</td>' +
'<td>-</td>' +
'<td>-</td>' +
'<td>-</td>' +
'</tr>';
}
tableHTML += '</tbody></table>';
mylist.innerHTML = tableHTML;
}
// 设置分页
function setupPagination() {
if (!allData || allData.length === 0) {
pagination.style.display = 'none';
return;
}
const totalPages = Math.ceil(allData.length / itemsPerPage);
// 更新分页信息
currentPageEl.textContent = currentPage;
totalPagesEl.textContent = totalPages;
// 更新按钮状态
firstPageBtn.disabled = currentPage === 1;
prevPageBtn.disabled = currentPage === 1;
nextPageBtn.disabled = currentPage === totalPages;
lastPageBtn.disabled = currentPage === totalPages;
// 显示分页控件
pagination.style.display = 'flex';
}
// 分页按钮事件
firstPageBtn.addEventListener('click', function() {
currentPage = 1;
renderTable();
setupPagination();
});
prevPageBtn.addEventListener('click', function() {
if (currentPage > 1) {
currentPage--;
renderTable();
setupPagination();
}
});
nextPageBtn.addEventListener('click', function() {
const totalPages = Math.ceil(allData.length / itemsPerPage);
if (currentPage < totalPages) {
currentPage++;
renderTable();
setupPagination();
}
});
lastPageBtn.addEventListener('click', function() {
const totalPages = Math.ceil(allData.length / itemsPerPage);
currentPage = totalPages;
renderTable();
setupPagination();
});
});
</script>
</body>
</html>
浙公网安备 33010602011771号