|
|
<!DOCTYPE html><html lang="zh-CN"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>落地页管理系统</title> <style> /* 基础样式 */ * { margin: 0; padding: 0; box-sizing: border-box; font-family: "Microsoft YaHei", sans-serif; } body { background-color: #f5f7fa; color: #333; } .container { display: flex; min-height: 100vh; }
/* 侧边栏样式 */ .sidebar { width: 220px; background-color: #2c3e50; color: #fff; padding: 20px 0; } .sidebar-logo { text-align: center; padding: 0 20px 20px; border-bottom: 1px solid rgba(255,255,255,0.1); margin-bottom: 20px; } .sidebar-logo h2 { font-size: 18px; margin-top: 10px; } .sidebar-menu { list-style: none; } .sidebar-menu li a { display: flex; align-items: center; padding: 12px 20px; color: rgba(255,255,255,0.8); text-decoration: none; transition: all 0.3s; } .sidebar-menu li a:hover, .sidebar-menu li a.active { background-color: #34495e; color: #fff; } .sidebar-menu li a i { margin-right: 10px; font-size: 16px; }
/* 主内容区样式 */ .main-content { flex: 1; padding: 20px; overflow-y: auto; } .header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; padding-bottom: 15px; border-bottom: 1px solid #eee; } .header-title { font-size: 20px; font-weight: 600; } .user-info { display: flex; align-items: center; } .user-info img { width: 36px; height: 36px; border-radius: 50%; margin-right: 10px; }
/* 功能区样式 */ .function-bar { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; } .search-box { display: flex; } .search-box input { width: 300px; padding: 8px 15px; border: 1px solid #ddd; border-radius: 4px 0 0 4px; outline: none; } .search-box button { background-color: #3498db; color: #fff; border: none; padding: 0 15px; border-radius: 0 4px 4px 0; cursor: pointer; } .add-btn { background-color: #2ecc71; color: #fff; border: none; padding: 8px 20px; border-radius: 4px; cursor: pointer; display: flex; align-items: center; } .add-btn i { margin-right: 5px; } .add-btn:hover { background-color: #27ae60; }
/* 表格样式 */ .table-container { background-color: #fff; border-radius: 4px; box-shadow: 0 2px 12px rgba(0,0,0,0.1); overflow: hidden; } .data-table { width: 100%; border-collapse: collapse; } .data-table th, .data-table td { padding: 12px 15px; text-align: left; border-bottom: 1px solid #f0f0f0; } .data-table th { background-color: #f9fafb; font-weight: 600; color: #666; } .data-table tbody tr:hover { background-color: #f5f7fa; } .status { display: inline-block; padding: 3px 8px; border-radius: 4px; font-size: 12px; } .status-active { background-color: rgba(46, 204, 113, 0.1); color: #2ecc71; } .status-inactive { background-color: rgba(231, 76, 60, 0.1); color: #e74c3c; } .action-btn { margin-right: 8px; color: #3498db; text-decoration: none; font-size: 14px; cursor: pointer; } .action-btn.delete { color: #e74c3c; } .action-btn:hover { text-decoration: underline; }
/* 分页样式 */ .pagination { display: flex; justify-content: space-between; align-items: center; padding: 15px; border-top: 1px solid #f0f0f0; } .pagination-info { color: #666; font-size: 14px; } .pagination-list { display: flex; list-style: none; padding: 0; margin: 0; } .pagination-list li { margin: 0 2px; } /* 核心:确保a和span统一尺寸和居中 */ .pagination-list a, .pagination-list span { display: inline-block; width: 45px; height: 45px; line-height: 45px; text-align: center; border: 1px solid #ddd; border-radius: 4px; text-decoration: none; color: #333; font-size: 14px; box-sizing: border-box; } .pagination-list a { cursor: pointer; } /* 激活和hover状态 */ .pagination-list a:hover, .pagination-list a.active { background-color: #3498db; color: #fff; border-color: #3498db; } /* 禁用状态(span标签) */ .pagination-list span { background-color: #f5f5f5; color: #999; cursor: not-allowed; } /* 跳转区域样式 */ .pagination-jump { display: flex; align-items: center; font-size: 14px; gap: 5px; } .pagination-jump input { width: 50px; height: 32px; margin: 0 5px; padding: 0 5px; border: 1px solid #ddd; border-radius: 4px; text-align: center; box-sizing: border-box; } .pagination-jump button { padding: 6px 12px; border: 1px solid #ddd; border-radius: 4px; background-color: #fff; cursor: pointer; height: 32px; box-sizing: border-box; } /* 加载中样式 */ .loading { text-align: center; padding: 50px 0; color: #666; } .loading i { font-size: 24px; margin-bottom: 10px; animation: spin 1s linear infinite; } @keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } </style> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"></head><body> <div class="container"> <!-- 侧边栏 --> <div class="sidebar"> <div class="sidebar-logo"> <i class="fa fa-line-chart" style="font-size: 24px;"></i> <h2>后台管理系统</h2> </div> <ul class="sidebar-menu"> <li><a href="#" class="active"><i class="fa fa-file-text-o"></i> 落地页管理</a></li> </ul> </div>
<!-- 主内容区 --> <div class="main-content"> <div class="header"> <div class="header-title">落地页管理</div> </div>
<!-- 功能区 --> <div class="function-bar"> <button class="add-btn"> <i class="fa fa-plus"></i> 新增落地页 </button> </div>
<!-- 数据表格 --> <div class="table-container"> <table class="data-table"> <thead> <tr> <th>序号</th> <th>活动名称</th> <th>活动简介</th> <th>活动时间</th> <th>编辑时间</th> <th>操作</th> </tr> </thead> <tbody id="tableBody"> <tr> <td colspan="6" class="loading"> <i class="fa fa-spinner"></i> <p>加载中...</p> </td> </tr> </tbody> </table>
<!-- 分页控件 --> <div class="pagination" id="paginationContainer"> </div> </div> </div> </div>
<script type="module"> // 导入API函数 import { getLandingListApi } from './src/api/member.js';
// DOM元素 const tableBody = document.getElementById('tableBody'); const paginationContainer = document.getElementById('paginationContainer');
// 分页参数 let currentPage = 1; const pageSize = 10; let totalCount = 0; let totalPages = 0;
// 模拟数据 const mockData = Array.from({ length: 15 }, (_, index) => ({ id: index + 1, title: `双十${index + 1}促销活动`, desc: `这是第${index + 1}个落地页活动,主要推广新品上市和优惠折扣`, activityTime: `2023-11-${(index % 20) + 10} 00:00:00 - 2023-11-${(index % 20) + 20} 23:59:59`, updateTime: `2023-11-${(index % 20) + 5} ${10 + index}:${index * 5}:00` }));
// 初始化页面 async function initPage() { const urlParams = new URLSearchParams(window.location.search); const pageParam = urlParams.get('page'); if (pageParam && !isNaN(pageParam)) { currentPage = parseInt(pageParam); }
// 获取列表数据 // await fetchLandingList(); await fetchMockLandingList(); }
// 新增:使用模拟数据获取列表(替代真实API调用) async function fetchMockLandingList() { // 模拟网络延迟 await new Promise(resolve => setTimeout(resolve, 800));
// 计算分页数据 totalCount = mockData.length; totalPages = Math.ceil(totalCount / pageSize); // 截取当前页的数据(数组切片) const startIndex = (currentPage - 1) * pageSize; const endIndex = startIndex + pageSize; const currentPageData = mockData.slice(startIndex, endIndex);
// 渲染表格数据 renderTable(currentPageData); // 渲染分页控件 renderPagination(); }
// 从后端获取落地页列表 async function fetchLandingList() { try { // 调用API接口,传递分页参数 const response = await getLandingListApi({ page: currentPage, size: pageSize });
if (response.code === 200 && response.data) { const { list: landingPages, total } = response.data; totalCount = total; totalPages = Math.ceil(totalCount / pageSize); // 渲染表格数据 renderTable(landingPages); // 渲染分页控件 renderPagination(); } else { renderEmptyState('获取数据失败'); } } catch (error) { console.error('获取列表失败:', error); renderEmptyState('网络错误,请重试'); } }
// 渲染表格数据 function renderTable(landingPages) { if (!landingPages || landingPages.length === 0) { renderEmptyState('暂无数据'); return; }
let html = ''; landingPages.forEach((page, index) => { // 计算序号(当前页-1)*每页条数 + 索引+1 const serialNumber = (currentPage - 1) * pageSize + index + 1; html += ` <tr> <td>${serialNumber}</td> <td>${escapeHtml(page.title || '')}</td> <td>${escapeHtml(page.desc || '无简介')}</td> <td>${formatDate(page.activityTime || '')}</td> <td>${formatDate(page.updateTime || '')}</td> <td> <a class="action-btn">编辑</a> <a href="adminDetail.html?id=${page.id}" class="action-btn">详情</a> </td> </tr> `; });
tableBody.innerHTML = html; }
// 渲染空状态 function renderEmptyState(message) { tableBody.innerHTML = ` <tr> <td colspan="6" style="text-align: center; padding: 30px;"> <i class="fa fa-inbox" style="font-size: 24px; color: #ddd; margin-bottom: 10px;"></i> <p>${message}</p> </td> </tr> `; // 清空分页 paginationContainer.innerHTML = ''; }
// 渲染分页控件 function renderPagination() { if (totalCount === 0) return;
// 生成页码列表(显示当前页前后2页) const pageNumbers = []; let startPage = Math.max(1, currentPage - 2); let endPage = Math.min(totalPages, currentPage + 2); // 确保至少显示5个页码(如果总页数够的话) if (endPage - startPage < 4 && totalPages >= 5) { if (startPage === 1) { endPage = 5; } else if (endPage === totalPages) { startPage = totalPages - 4; } } for (let i = startPage; i <= endPage; i++) { pageNumbers.push(i); }
// 分页HTML const html = ` <div class="pagination-info"> 共 ${totalCount} 条记录,当前第 ${currentPage} / ${totalPages} 页 </div> <ul class="pagination-list"> <li> ${currentPage === 1 ? `<span>首页</span>` : `<a href="?page=1">首页</a>` } </li> <li> ${currentPage > 1 ? `<a href="?page=${currentPage - 1}">上一页</a>` : `<span>上一页</span>` } </li> ${pageNumbers.map(num => ` <li> <a href="?page=${num}" class="${num === currentPage ? 'active' : ''}"> ${num} </a> </li> `).join('')} <li> ${currentPage < totalPages ? `<a href="?page=${currentPage + 1}">下一页</a>` : `<span>下一页</span>` } </li> <li> ${currentPage === totalPages ? `<span>尾页</span>` : `<a href="?page=${totalPages}">尾页</a>` } </li> </ul> <div class="pagination-jump"> <span>跳至</span> <input type="number" min="1" max="${totalPages}" value="${currentPage}" id="jumpPageInput"> <span>页</span> <button id="jumpBtn">确定</button> </div> `;
paginationContainer.innerHTML = html;
// 绑定跳转事件 document.getElementById('jumpBtn').addEventListener('click', handlePageJump); document.getElementById('jumpPageInput').addEventListener('keypress', (e) => { if (e.key === 'Enter') handlePageJump(); }); }
// 处理页码跳转 function handlePageJump() { const pageInput = document.getElementById('jumpPageInput'); const page = parseInt(pageInput.value); if (page && !isNaN(page) && page >= 1 && page <= totalPages && page !== currentPage) { window.location.href = `?page=${page}`; } else { alert('请输入有效的页码'); } }
// 工具函数:格式化日期 function formatDate(dateString) { if (!dateString) return ''; const date = new Date(dateString); return date.toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit' }).replace(/\//g, '-'); }
// 工具函数:HTML转义(防止XSS) function escapeHtml(str) { if (!str) return ''; return str .replace(/&/g, '&') .replace(/</g, '<') .replace(/>/g, '>') .replace(/"/g, '"') .replace(/'/g, '''); }
// 页面加载时初始化 window.addEventListener('DOMContentLoaded', initPage); </script></body></html>
|