Browse Source

first submit

wangxx 4 months ago
parent
commit
3d2126303a
2 changed files with 339 additions and 0 deletions
  1. 9 0
      .claude/settings.local.json
  2. 330 0
      nginx-files/select-airport-custom.html

+ 9 - 0
.claude/settings.local.json

@@ -0,0 +1,9 @@
1
+{
2
+  "permissions": {
3
+    "allow": [
4
+      "Read(//c/Users/linzo/IdeaProjects/airport-server-single/**)"
5
+    ],
6
+    "deny": [],
7
+    "ask": []
8
+  }
9
+}

+ 330 - 0
nginx-files/select-airport-custom.html

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