select-airport-custom.html 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  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, maximum-scale=1.0, user-scalable=no">
  6. <meta name="apple-mobile-web-app-capable" content="yes">
  7. <meta name="apple-mobile-web-app-status-bar-style" content="black">
  8. <title>选择机场 - 安检分级质控系统</title>
  9. <style>
  10. * {
  11. margin: 0;
  12. padding: 0;
  13. box-sizing: border-box;
  14. }
  15. body {
  16. font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  17. background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  18. min-height: 100vh;
  19. display: flex;
  20. align-items: center;
  21. justify-content: center;
  22. padding: 20px;
  23. }
  24. .container {
  25. width: 100%;
  26. max-width: 400px;
  27. }
  28. .logo-section {
  29. text-align: center;
  30. margin-bottom: 40px;
  31. }
  32. .logo {
  33. width: 80px;
  34. height: 80px;
  35. background: white;
  36. border-radius: 20px;
  37. margin: 0 auto 20px;
  38. display: flex;
  39. align-items: center;
  40. justify-content: center;
  41. font-size: 40px;
  42. box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
  43. }
  44. .title {
  45. color: white;
  46. font-size: 24px;
  47. font-weight: 600;
  48. margin-bottom: 8px;
  49. }
  50. .subtitle {
  51. color: rgba(255, 255, 255, 0.8);
  52. font-size: 14px;
  53. }
  54. .card {
  55. background: white;
  56. border-radius: 16px;
  57. padding: 30px 20px;
  58. box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
  59. }
  60. .card-title {
  61. font-size: 18px;
  62. font-weight: 600;
  63. color: #333;
  64. margin-bottom: 20px;
  65. text-align: center;
  66. }
  67. .airport-list {
  68. list-style: none;
  69. }
  70. .airport-item {
  71. background: #f7f8fa;
  72. border-radius: 12px;
  73. padding: 16px;
  74. margin-bottom: 12px;
  75. cursor: pointer;
  76. transition: all 0.3s ease;
  77. display: flex;
  78. align-items: center;
  79. border: 2px solid transparent;
  80. }
  81. .airport-item:hover {
  82. background: #e8ecf4;
  83. transform: translateY(-2px);
  84. box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  85. }
  86. .airport-item:active {
  87. transform: translateY(0);
  88. }
  89. .airport-item.selected {
  90. border-color: #667eea;
  91. background: #f0f3ff;
  92. }
  93. .airport-icon {
  94. width: 40px;
  95. height: 40px;
  96. background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  97. border-radius: 10px;
  98. display: flex;
  99. align-items: center;
  100. justify-content: center;
  101. font-size: 20px;
  102. margin-right: 15px;
  103. flex-shrink: 0;
  104. }
  105. .airport-info {
  106. flex: 1;
  107. }
  108. .airport-name {
  109. font-size: 16px;
  110. font-weight: 600;
  111. color: #333;
  112. margin-bottom: 4px;
  113. }
  114. .airport-desc {
  115. font-size: 12px;
  116. color: #999;
  117. }
  118. .arrow {
  119. color: #ccc;
  120. font-size: 20px;
  121. }
  122. .airport-item.selected .arrow {
  123. color: #667eea;
  124. }
  125. .footer {
  126. text-align: center;
  127. margin-top: 20px;
  128. color: rgba(255, 255, 255, 0.6);
  129. font-size: 12px;
  130. }
  131. .loading {
  132. display: none;
  133. text-align: center;
  134. margin-top: 20px;
  135. }
  136. .loading.show {
  137. display: block;
  138. }
  139. .loading-spinner {
  140. width: 30px;
  141. height: 30px;
  142. border: 3px solid rgba(255, 255, 255, 0.3);
  143. border-radius: 50%;
  144. border-top-color: white;
  145. animation: spin 1s ease-in-out infinite;
  146. margin: 0 auto 10px;
  147. }
  148. @keyframes spin {
  149. to { transform: rotate(360deg); }
  150. }
  151. .loading-text {
  152. color: white;
  153. font-size: 14px;
  154. }
  155. /* 移动端优化 */
  156. @media (max-width: 480px) {
  157. .title {
  158. font-size: 20px;
  159. }
  160. .card {
  161. padding: 24px 16px;
  162. }
  163. .airport-item {
  164. padding: 14px;
  165. }
  166. }
  167. </style>
  168. </head>
  169. <body>
  170. <div class="container">
  171. <div class="logo-section">
  172. <div class="logo">✈️</div>
  173. <div class="title">安检分级质控系统</div>
  174. <div class="subtitle">Airport Security Quality Control</div>
  175. </div>
  176. <div class="card">
  177. <div class="card-title">请选择您的机场</div>
  178. <ul class="airport-list" id="airportList">
  179. <!-- 动态生成 -->
  180. </ul>
  181. </div>
  182. <div class="loading" id="loading">
  183. <div class="loading-spinner"></div>
  184. <div class="loading-text">正在跳转...</div>
  185. </div>
  186. <div class="footer">
  187. © 2025 机场安检质控系统
  188. </div>
  189. </div>
  190. <script>
  191. // 机场配置列表(根据实际环境配置)
  192. const airports = [
  193. {
  194. code: 'SHUANGLIU',
  195. name: '双流机场',
  196. description: '成都双流国际机场',
  197. icon: '🛫'
  198. },
  199. {
  200. code: 'HAIKOU',
  201. name: '海口机场',
  202. description: '海口美兰国际机场',
  203. icon: '✈️'
  204. }
  205. // 可以继续添加更多机场
  206. // {
  207. // code: 'ANOTHER_AIRPORT',
  208. // name: '其他机场',
  209. // description: '其他机场描述',
  210. // icon: '🛬'
  211. // }
  212. ];
  213. let selectedCode = null;
  214. // 渲染机场列表
  215. function renderAirports() {
  216. const listEl = document.getElementById('airportList');
  217. listEl.innerHTML = airports.map(airport => `
  218. <li class="airport-item" data-code="${airport.code}" onclick="selectAirport('${airport.code}')">
  219. <div class="airport-icon">${airport.icon}</div>
  220. <div class="airport-info">
  221. <div class="airport-name">${airport.name}</div>
  222. <div class="airport-desc">${airport.description}</div>
  223. </div>
  224. <div class="arrow">›</div>
  225. </li>
  226. `).join('');
  227. }
  228. // 选择机场
  229. function selectAirport(code) {
  230. selectedCode = code;
  231. // 更新UI
  232. document.querySelectorAll('.airport-item').forEach(item => {
  233. item.classList.remove('selected');
  234. });
  235. document.querySelector(`[data-code="${code}"]`).classList.add('selected');
  236. // 延迟跳转,让用户看到选中效果
  237. setTimeout(() => {
  238. confirmSelection(code);
  239. }, 300);
  240. }
  241. // 确认选择并跳转
  242. function confirmSelection(code) {
  243. // 显示加载动画
  244. document.getElementById('loading').classList.add('show');
  245. // 设置 Cookie(30天有效期)
  246. const maxAge = 30 * 24 * 60 * 60; // 30天
  247. document.cookie = `airport_code=${code}; path=/; max-age=${maxAge}; SameSite=Lax`;
  248. // 同时设置 localStorage(备用方案)
  249. try {
  250. localStorage.setItem('airport_code', code);
  251. } catch (e) {
  252. console.warn('无法设置 localStorage:', e);
  253. }
  254. // 延迟跳转到首页
  255. setTimeout(() => {
  256. window.location.href = '/';
  257. }, 500);
  258. }
  259. // 检查是否已有选择
  260. function checkExistingSelection() {
  261. // 从 cookie 读取
  262. const cookies = document.cookie.split(';');
  263. for (let cookie of cookies) {
  264. const [name, value] = cookie.trim().split('=');
  265. if (name === 'airport_code') {
  266. // 已有选择,自动跳转
  267. window.location.href = '/';
  268. return;
  269. }
  270. }
  271. }
  272. // 初始化
  273. document.addEventListener('DOMContentLoaded', () => {
  274. checkExistingSelection();
  275. renderAirports();
  276. });
  277. // 防止iOS端的bounce效果
  278. document.addEventListener('touchmove', (e) => {
  279. if (e.target.closest('.airport-list')) {
  280. return;
  281. }
  282. e.preventDefault();
  283. }, { passive: false });
  284. </script>
  285. </body>
  286. </html>