模拟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数据表格分页示例 &copy; 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>
posted @ 2025-10-27 10:50  冀未然  阅读(5)  评论(0)    收藏  举报