unipod 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,460 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>UniPod - Unity包管理服务</title>
7
+ <style>
8
+ :root {
9
+ --bg-color: #f8f9fa;
10
+ --text-color: #212529;
11
+ --card-bg: #ffffff;
12
+ --card-border: #dee2e6;
13
+ --accent-color: #6200ee;
14
+ --accent-light: #bb86fc;
15
+ --header-bg: #6200ee;
16
+ --header-text: #ffffff;
17
+ --search-bg: #ffffff;
18
+ --shadow-color: rgba(0, 0, 0, 0.1);
19
+ }
20
+
21
+ [data-theme="dark"] {
22
+ --bg-color: #121212;
23
+ --text-color: #e0e0e0;
24
+ --card-bg: #1e1e1e;
25
+ --card-border: #333333;
26
+ --accent-color: #bb86fc;
27
+ --accent-light: #6200ee;
28
+ --header-bg: #1e1e1e;
29
+ --header-text: #ffffff;
30
+ --search-bg: #2d2d2d;
31
+ --shadow-color: rgba(0, 0, 0, 0.3);
32
+ }
33
+
34
+ * {
35
+ box-sizing: border-box;
36
+ margin: 0;
37
+ padding: 0;
38
+ }
39
+
40
+ body {
41
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
42
+ background-color: var(--bg-color);
43
+ color: var(--text-color);
44
+ transition: background-color 0.3s, color 0.3s;
45
+ line-height: 1.6;
46
+ }
47
+
48
+ .container {
49
+ max-width: 1200px;
50
+ margin: 0 auto;
51
+ padding: 0 1rem;
52
+ }
53
+
54
+ header {
55
+ background-color: var(--header-bg);
56
+ color: var(--header-text);
57
+ padding: 1.5rem 0;
58
+ box-shadow: 0 2px 5px var(--shadow-color);
59
+ }
60
+
61
+ header .container {
62
+ display: flex;
63
+ justify-content: space-between;
64
+ align-items: center;
65
+ }
66
+
67
+ .logo {
68
+ font-size: 1.8rem;
69
+ font-weight: bold;
70
+ display: flex;
71
+ align-items: center;
72
+ min-width: 140px;
73
+ }
74
+
75
+ .logo svg {
76
+ margin-right: 0.5rem;
77
+ width: 32px;
78
+ height: 32px;
79
+ }
80
+
81
+ .search-container {
82
+ flex-grow: 1;
83
+ max-width: 500px;
84
+ margin: 0 1.5rem;
85
+ }
86
+
87
+ .search-box {
88
+ display: flex;
89
+ width: 100%;
90
+ }
91
+
92
+ input[type="text"] {
93
+ width: 100%;
94
+ padding: 0.6rem 1rem;
95
+ border: none;
96
+ border-radius: 4px;
97
+ font-size: 0.9rem;
98
+ background-color: rgba(255, 255, 255, 0.2);
99
+ color: var(--header-text);
100
+ }
101
+
102
+ input[type="text"]::placeholder {
103
+ color: rgba(255, 255, 255, 0.7);
104
+ }
105
+
106
+ .theme-toggle {
107
+ background: none;
108
+ border: none;
109
+ cursor: pointer;
110
+ color: var(--header-text);
111
+ font-size: 1.5rem;
112
+ display: flex;
113
+ align-items: center;
114
+ min-width: 40px;
115
+ }
116
+
117
+ main {
118
+ padding: 2rem 0 5rem;
119
+ }
120
+
121
+ .stats {
122
+ font-size: 0.9rem;
123
+ color: var(--text-color);
124
+ margin-bottom: 1.5rem;
125
+ }
126
+
127
+ .package-grid {
128
+ display: grid;
129
+ grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
130
+ gap: 1.5rem;
131
+ margin-top: 1.5rem;
132
+ }
133
+
134
+ .package-card {
135
+ background-color: var(--card-bg);
136
+ border: 1px solid var(--card-border);
137
+ border-radius: 8px;
138
+ padding: 1.5rem;
139
+ box-shadow: 0 2px 5px var(--shadow-color);
140
+ transition: transform 0.2s, box-shadow 0.2s;
141
+ position: relative;
142
+ overflow: hidden;
143
+ }
144
+
145
+ .package-card:hover {
146
+ transform: translateY(-3px);
147
+ box-shadow: 0 5px 15px var(--shadow-color);
148
+ }
149
+
150
+ .package-name {
151
+ font-size: 1.2rem;
152
+ font-weight: bold;
153
+ margin-bottom: 0.5rem;
154
+ color: var(--accent-color);
155
+ }
156
+
157
+ .package-version {
158
+ font-size: 0.8rem;
159
+ background-color: var(--accent-light);
160
+ color: white;
161
+ padding: 0.2rem 0.5rem;
162
+ border-radius: 20px;
163
+ display: inline-block;
164
+ margin-bottom: 0.8rem;
165
+ }
166
+
167
+ .package-description {
168
+ margin-bottom: 1rem;
169
+ font-size: 0.9rem;
170
+ }
171
+
172
+ .package-keywords {
173
+ display: flex;
174
+ flex-wrap: wrap;
175
+ gap: 0.5rem;
176
+ margin-bottom: 1rem;
177
+ }
178
+
179
+ .keyword {
180
+ font-size: 0.7rem;
181
+ background-color: var(--bg-color);
182
+ padding: 0.1rem 0.5rem;
183
+ border-radius: 20px;
184
+ border: 1px solid var(--card-border);
185
+ }
186
+
187
+ .package-author {
188
+ font-size: 0.8rem;
189
+ display: flex;
190
+ align-items: center;
191
+ margin-top: 0.5rem;
192
+ }
193
+
194
+ .package-author svg {
195
+ margin-right: 0.3rem;
196
+ width: 16px;
197
+ height: 16px;
198
+ }
199
+
200
+ .package-unity {
201
+ font-size: 0.8rem;
202
+ margin-top: 0.5rem;
203
+ display: flex;
204
+ align-items: center;
205
+ }
206
+
207
+ .package-unity svg {
208
+ margin-right: 0.3rem;
209
+ width: 16px;
210
+ height: 16px;
211
+ }
212
+
213
+ .empty-state {
214
+ text-align: center;
215
+ padding: 3rem;
216
+ color: var(--text-color);
217
+ }
218
+
219
+ footer {
220
+ margin-top: 3rem;
221
+ padding: 2rem 0 1rem;
222
+ text-align: center;
223
+ font-size: 0.9rem;
224
+ color: var(--text-color);
225
+ border-top: 1px solid var(--card-border);
226
+ position: fixed;
227
+ bottom: 0;
228
+ left: 0;
229
+ width: 100%;
230
+ background-color: var(--bg-color);
231
+ z-index: 100;
232
+ }
233
+
234
+ footer .copyright {
235
+ margin-top: 0;
236
+ font-size: 0.8rem;
237
+ opacity: 0.8;
238
+ }
239
+
240
+ @media (max-width: 768px) {
241
+ .package-grid {
242
+ grid-template-columns: 1fr;
243
+ }
244
+
245
+ header .container {
246
+ flex-direction: column;
247
+ gap: 1rem;
248
+ padding: 1rem 0;
249
+ }
250
+
251
+ .search-container {
252
+ width: 100%;
253
+ max-width: 100%;
254
+ margin: 0.5rem 0;
255
+ }
256
+
257
+ .logo {
258
+ margin-right: auto;
259
+ }
260
+
261
+ .theme-toggle {
262
+ position: absolute;
263
+ top: 1rem;
264
+ right: 1rem;
265
+ }
266
+ }
267
+ </style>
268
+ </head>
269
+ <body>
270
+ <header>
271
+ <div class="container">
272
+ <div class="logo">
273
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
274
+ <path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"></path>
275
+ <polyline points="3.27 6.96 12 12.01 20.73 6.96"></polyline>
276
+ <line x1="12" y1="22.08" x2="12" y2="12"></line>
277
+ </svg>
278
+ UniPod
279
+ </div>
280
+ <div class="search-container">
281
+ <div class="search-box">
282
+ <input type="text" id="search-input" placeholder="搜索包...">
283
+ </div>
284
+ </div>
285
+ <button class="theme-toggle" id="theme-toggle" title="切换主题">
286
+ <svg id="theme-icon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
287
+ <circle cx="12" cy="12" r="5"></circle>
288
+ <line x1="12" y1="1" x2="12" y2="3"></line>
289
+ <line x1="12" y1="21" x2="12" y2="23"></line>
290
+ <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
291
+ <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
292
+ <line x1="1" y1="12" x2="3" y2="12"></line>
293
+ <line x1="21" y1="12" x2="23" y2="12"></line>
294
+ <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
295
+ <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
296
+ </svg>
297
+ </button>
298
+ </div>
299
+ </header>
300
+
301
+ <main class="container">
302
+ <div class="stats" id="stats"></div>
303
+
304
+ <section id="packages-container">
305
+ <div class="package-grid" id="package-grid"></div>
306
+ <div class="empty-state" id="empty-state" style="display: none;">
307
+ <h3>未找到包</h3>
308
+ <p>没有找到与您的搜索条件匹配的包。</p>
309
+ </div>
310
+ </section>
311
+ </main>
312
+
313
+ <footer>
314
+ <div class="container">
315
+ <div class="copyright">© 2023 UniPod - Unity 包管理服务</div>
316
+ </div>
317
+ </footer>
318
+
319
+ <script>
320
+ // 从模板中获取包数据
321
+ const packages = {{PACKAGES_JSON}};
322
+
323
+ // DOM 元素
324
+ const packageGrid = document.getElementById('package-grid');
325
+ const searchInput = document.getElementById('search-input');
326
+ const statsElement = document.getElementById('stats');
327
+ const emptyState = document.getElementById('empty-state');
328
+ const themeToggle = document.getElementById('theme-toggle');
329
+ const themeIcon = document.getElementById('theme-icon');
330
+
331
+ // 主题切换
332
+ function toggleTheme() {
333
+ const currentTheme = document.documentElement.getAttribute('data-theme');
334
+ const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
335
+
336
+ document.documentElement.setAttribute('data-theme', newTheme);
337
+ localStorage.setItem('theme', newTheme);
338
+
339
+ // 更新图标
340
+ if (newTheme === 'dark') {
341
+ themeIcon.innerHTML = `
342
+ <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
343
+ `;
344
+ } else {
345
+ themeIcon.innerHTML = `
346
+ <circle cx="12" cy="12" r="5"></circle>
347
+ <line x1="12" y1="1" x2="12" y2="3"></line>
348
+ <line x1="12" y1="21" x2="12" y2="23"></line>
349
+ <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
350
+ <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
351
+ <line x1="1" y1="12" x2="3" y2="12"></line>
352
+ <line x1="21" y1="12" x2="23" y2="12"></line>
353
+ <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
354
+ <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
355
+ `;
356
+ }
357
+ }
358
+
359
+ // 应用保存的主题
360
+ const savedTheme = localStorage.getItem('theme');
361
+ if (savedTheme) {
362
+ document.documentElement.setAttribute('data-theme', savedTheme);
363
+ if (savedTheme === 'dark') {
364
+ themeIcon.innerHTML = `
365
+ <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
366
+ `;
367
+ }
368
+ }
369
+
370
+ // 渲染包列表
371
+ function renderPackages(packagesToRender) {
372
+ packageGrid.innerHTML = '';
373
+
374
+ if (packagesToRender.length === 0) {
375
+ emptyState.style.display = 'block';
376
+ packageGrid.style.display = 'none';
377
+ } else {
378
+ emptyState.style.display = 'none';
379
+ packageGrid.style.display = 'grid';
380
+
381
+ packagesToRender.forEach(pkg => {
382
+ const card = document.createElement('div');
383
+ card.className = 'package-card';
384
+
385
+ // 关键词HTML
386
+ const keywordsHtml = pkg.keywords && pkg.keywords.length > 0
387
+ ? `<div class="package-keywords">
388
+ ${pkg.keywords.map(kw => `<span class="keyword">${kw}</span>`).join('')}
389
+ </div>`
390
+ : '';
391
+
392
+ // Unity版本HTML
393
+ const unityHtml = pkg.unity
394
+ ? `<div class="package-unity">
395
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
396
+ <path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"></path>
397
+ </svg>
398
+ Unity ${pkg.unity}
399
+ </div>`
400
+ : '';
401
+
402
+ // 作者HTML
403
+ const authorHtml = pkg.author
404
+ ? `<div class="package-author">
405
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
406
+ <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path>
407
+ <circle cx="12" cy="7" r="4"></circle>
408
+ </svg>
409
+ ${typeof pkg.author === 'string' ? pkg.author : (pkg.author.name || 'Unknown')}
410
+ </div>`
411
+ : '';
412
+
413
+ card.innerHTML = `
414
+ <div class="package-name">${pkg.name}</div>
415
+ <span class="package-version">${pkg.version}</span>
416
+ <div class="package-description">${pkg.description || '没有描述'}</div>
417
+ ${keywordsHtml}
418
+ ${unityHtml}
419
+ ${authorHtml}
420
+ `;
421
+
422
+ packageGrid.appendChild(card);
423
+ });
424
+ }
425
+
426
+ // 更新统计信息
427
+ statsElement.textContent = `找到 ${packagesToRender.length} 个包`;
428
+ }
429
+
430
+ // 过滤包
431
+ function filterPackages(searchTerm) {
432
+ if (!searchTerm) {
433
+ return packages;
434
+ }
435
+
436
+ searchTerm = searchTerm.toLowerCase();
437
+ return packages.filter(pkg => {
438
+ return (
439
+ pkg.name.toLowerCase().includes(searchTerm) ||
440
+ (pkg.description && pkg.description.toLowerCase().includes(searchTerm)) ||
441
+ (pkg.keywords && pkg.keywords.some(kw => kw.toLowerCase().includes(searchTerm)))
442
+ );
443
+ });
444
+ }
445
+
446
+ // 搜索事件处理
447
+ searchInput.addEventListener('input', () => {
448
+ const searchTerm = searchInput.value.trim();
449
+ const filteredPackages = filterPackages(searchTerm);
450
+ renderPackages(filteredPackages);
451
+ });
452
+
453
+ // 主题切换事件
454
+ themeToggle.addEventListener('click', toggleTheme);
455
+
456
+ // 初始渲染
457
+ renderPackages(packages);
458
+ </script>
459
+ </body>
460
+ </html>