index.html 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>会友信息考勤打卡系统</title>
  7. <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css">
  8. <style>
  9. body { padding-top: 20px; }
  10. .container { max-width: 800px; }
  11. </style>
  12. </head>
  13. <body>
  14. <div class="container">
  15. <h1 class="mb-4">会友信息考勤打卡系统</h1>
  16. <div class="form-check form-switch mb-3">
  17. <input class="form-check-input" type="checkbox" id="apiToggle">
  18. <label class="form-check-label" for="apiToggle">使用模拟API</label>
  19. </div>
  20. <form id="addMemberForm" class="mb-4">
  21. <div class="input-group">
  22. <input type="text" id="memberName" class="form-control" placeholder="输入会员姓名" required>
  23. <button type="submit" class="btn btn-primary">添加会员</button>
  24. </div>
  25. </form>
  26. <h2>会员列表</h2>
  27. <ul id="memberList" class="list-group mb-4"></ul>
  28. <h2>设备状态</h2>
  29. <ul id="deviceList" class="list-group"></ul>
  30. </div>
  31. <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
  32. <script src="/mockApi.js"></script>
  33. <script>
  34. const API_URL = '/api';
  35. let useMockApi = false;
  36. document.getElementById('apiToggle').addEventListener('change', (e) => {
  37. useMockApi = e.target.checked;
  38. fetchMembers();
  39. fetchDevices();
  40. });
  41. async function apiFetch(url, options = {}) {
  42. if (useMockApi) {
  43. return window.mockApi.fetch(url, options);
  44. }
  45. return fetch(url, options);
  46. }
  47. async function fetchMembers() {
  48. const response = await apiFetch(`${API_URL}/members`);
  49. const members = await response.json();
  50. const memberList = document.getElementById('memberList');
  51. memberList.innerHTML = members.map(member => `
  52. <li class="list-group-item d-flex justify-content-between align-items-center">
  53. ${member.name}
  54. <div>
  55. <button onclick="recordAttendance('${member._id}')" class="btn btn-sm btn-success">记录考勤</button>
  56. <button onclick="viewAttendance('${member._id}')" class="btn btn-sm btn-info">查看考勤</button>
  57. </div>
  58. </li>
  59. `).join('');
  60. }
  61. document.getElementById('addMemberForm').addEventListener('submit', async (e) => {
  62. e.preventDefault();
  63. const name = document.getElementById('memberName').value;
  64. await apiFetch(`${API_URL}/members`, {
  65. method: 'POST',
  66. headers: { 'Content-Type': 'application/json' },
  67. body: JSON.stringify({ name })
  68. });
  69. document.getElementById('memberName').value = '';
  70. fetchMembers();
  71. });
  72. async function recordAttendance(memberId) {
  73. const date = new Date().toISOString().split('T')[0];
  74. await apiFetch(`${API_URL}/attendance`, {
  75. method: 'POST',
  76. headers: { 'Content-Type': 'application/json' },
  77. body: JSON.stringify({ memberId, date })
  78. });
  79. alert('考勤已记录');
  80. }
  81. async function viewAttendance(memberId) {
  82. const response = await apiFetch(`${API_URL}/attendance/${memberId}`);
  83. const attendance = await response.json();
  84. alert(`考勤记录:\n${attendance.join('\n')}`);
  85. }
  86. async function fetchDevices() {
  87. const response = await apiFetch(`${API_URL}/devices`);
  88. const devices = await response.json();
  89. const deviceList = document.getElementById('deviceList');
  90. deviceList.innerHTML = devices.map(device => `
  91. <li class="list-group-item d-flex justify-content-between align-items-center">
  92. ${device.name} (${device.deviceId})
  93. <span class="badge bg-${device.status === 'online' ? 'success' : 'danger'} rounded-pill">${device.status}</span>
  94. </li>
  95. `).join('');
  96. }
  97. fetchMembers();
  98. fetchDevices();
  99. setInterval(fetchDevices, 30000); // 每30秒更新一次设备状态
  100. </script>
  101. </body>
  102. </html>