skill-base 2.0.4 → 2.0.7

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.
Files changed (46) hide show
  1. package/README.md +177 -115
  2. package/bin/skill-base.js +29 -3
  3. package/package.json +4 -1
  4. package/src/cappy.js +416 -0
  5. package/src/database.js +11 -0
  6. package/src/index.js +125 -25
  7. package/src/middleware/auth.js +96 -32
  8. package/src/routes/auth.js +1 -1
  9. package/src/routes/skills.js +10 -5
  10. package/src/utils/zip.js +15 -4
  11. package/static/android-chrome-192x192.png +0 -0
  12. package/static/android-chrome-512x512.png +0 -0
  13. package/static/apple-touch-icon.png +0 -0
  14. package/static/assets/index-BkwByEEp.css +1 -0
  15. package/static/assets/index-CB4Diul3.js +209 -0
  16. package/static/favicon-16x16.png +0 -0
  17. package/static/favicon-32x32.png +0 -0
  18. package/static/favicon.ico +0 -0
  19. package/static/favicon.svg +14 -0
  20. package/static/index.html +18 -248
  21. package/static/site.webmanifest +1 -0
  22. package/static/admin/users.html +0 -593
  23. package/static/cli-code.html +0 -203
  24. package/static/css/.gitkeep +0 -0
  25. package/static/css/style.css +0 -1567
  26. package/static/diff.html +0 -466
  27. package/static/file.html +0 -443
  28. package/static/js/.gitkeep +0 -0
  29. package/static/js/admin/users.js +0 -346
  30. package/static/js/app.js +0 -508
  31. package/static/js/auth.js +0 -151
  32. package/static/js/cli-code.js +0 -184
  33. package/static/js/collaborators.js +0 -283
  34. package/static/js/diff.js +0 -540
  35. package/static/js/file.js +0 -619
  36. package/static/js/i18n.js +0 -739
  37. package/static/js/index.js +0 -168
  38. package/static/js/publish.js +0 -718
  39. package/static/js/settings.js +0 -124
  40. package/static/js/setup.js +0 -157
  41. package/static/js/skill.js +0 -808
  42. package/static/login.html +0 -82
  43. package/static/publish.html +0 -459
  44. package/static/settings.html +0 -163
  45. package/static/setup.html +0 -101
  46. package/static/skill.html +0 -851
package/static/skill.html DELETED
@@ -1,851 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title data-i18n="skill.title">Skill 详情 - Skill Base</title>
7
- <link rel="stylesheet" href="/css/style.css">
8
- <!-- highlight.js 样式 -->
9
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/highlight.js@11.9.0/styles/github-dark.min.css">
10
- <style>
11
- /* 面包屑导航 */
12
- .breadcrumb {
13
- display: flex;
14
- align-items: center;
15
- gap: var(--spacing-sm);
16
- font-size: 0.875rem;
17
- color: var(--text-secondary);
18
- margin-bottom: var(--spacing-lg);
19
- }
20
-
21
- .breadcrumb a {
22
- color: var(--text-secondary);
23
- }
24
-
25
- .breadcrumb a:hover {
26
- color: var(--primary-color);
27
- }
28
-
29
- .breadcrumb-separator {
30
- color: var(--text-muted);
31
- }
32
-
33
- /* Skill 信息区域 */
34
- .skill-info {
35
- background-color: var(--white);
36
- border-radius: var(--radius);
37
- box-shadow: var(--shadow);
38
- padding: var(--spacing-lg);
39
- margin-bottom: var(--spacing-lg);
40
- }
41
-
42
- .skill-header {
43
- display: flex;
44
- align-items: flex-start;
45
- justify-content: space-between;
46
- gap: var(--spacing-md);
47
- margin-bottom: var(--spacing-md);
48
- }
49
-
50
- .skill-title {
51
- font-size: 1.5rem;
52
- font-weight: 700;
53
- color: var(--text-color);
54
- margin: 0;
55
- }
56
-
57
- .skill-desc {
58
- color: var(--text-secondary);
59
- margin-bottom: var(--spacing-md);
60
- line-height: 1.6;
61
- }
62
-
63
- .skill-meta {
64
- display: flex;
65
- flex-wrap: wrap;
66
- gap: var(--spacing-lg);
67
- font-size: 0.875rem;
68
- color: var(--text-secondary);
69
- }
70
-
71
- .skill-meta-item {
72
- display: flex;
73
- align-items: center;
74
- gap: var(--spacing-xs);
75
- }
76
-
77
- /* 版本选择器和操作按钮 */
78
- .skill-actions {
79
- display: flex;
80
- flex-wrap: wrap;
81
- align-items: center;
82
- gap: var(--spacing-md);
83
- margin-top: var(--spacing-lg);
84
- padding-top: var(--spacing-md);
85
- border-top: 1px solid var(--border-color);
86
- }
87
-
88
- .version-select {
89
- min-width: 200px;
90
- }
91
-
92
- /* 左右分栏布局(minmax(0,1fr) 防止右侧被长内容撑开整页) */
93
- .skill-content {
94
- display: grid;
95
- grid-template-columns: 280px minmax(0, 1fr);
96
- gap: var(--spacing-lg);
97
- margin-bottom: var(--spacing-lg);
98
- }
99
-
100
- /* 文件树面板 */
101
- .file-tree-panel {
102
- background-color: var(--white);
103
- border-radius: var(--radius);
104
- box-shadow: var(--shadow);
105
- padding: var(--spacing-md);
106
- max-height: calc(100vh - 300px);
107
- overflow-y: auto;
108
- }
109
-
110
- .file-tree-panel-title {
111
- font-size: 0.875rem;
112
- font-weight: 600;
113
- color: var(--text-color);
114
- margin-bottom: var(--spacing-md);
115
- padding-bottom: var(--spacing-sm);
116
- border-bottom: 1px solid var(--border-color);
117
- }
118
-
119
- /* 文件预览面板 */
120
- .file-preview-panel {
121
- background-color: var(--white);
122
- border-radius: var(--radius);
123
- box-shadow: var(--shadow);
124
- min-height: 400px;
125
- max-height: 900px;
126
- overflow-y: auto;
127
- min-width: 0;
128
- display: flex;
129
- flex-direction: column;
130
- }
131
-
132
- .file-preview-header {
133
- padding: var(--spacing-md) var(--spacing-lg);
134
- border-bottom: 1px solid var(--border-color);
135
- display: flex;
136
- align-items: center;
137
- justify-content: space-between;
138
- gap: var(--spacing-md);
139
- flex-wrap: wrap;
140
- }
141
-
142
- .file-preview-path {
143
- flex: 1;
144
- min-width: 0;
145
- font-family: 'SF Mono', Monaco, 'Courier New', monospace;
146
- font-size: 0.875rem;
147
- color: var(--text-secondary);
148
- overflow: hidden;
149
- text-overflow: ellipsis;
150
- white-space: nowrap;
151
- }
152
-
153
- .file-preview-md-actions {
154
- flex-shrink: 0;
155
- }
156
-
157
- .md-view-toggle {
158
- display: inline-flex;
159
- border: 1px solid var(--border-color);
160
- border-radius: var(--radius-sm);
161
- overflow: hidden;
162
- }
163
-
164
- .md-view-btn {
165
- padding: 0.25rem 0.625rem;
166
- font-size: 0.8125rem;
167
- border: none;
168
- background: var(--bg-color);
169
- color: var(--text-secondary);
170
- cursor: pointer;
171
- }
172
-
173
- .md-view-btn + .md-view-btn {
174
- border-left: 1px solid var(--border-color);
175
- }
176
-
177
- .md-view-btn.is-active {
178
- background: var(--white);
179
- color: var(--text-color);
180
- font-weight: 500;
181
- }
182
-
183
- .file-preview-content {
184
- flex: 1;
185
- min-width: 0;
186
- padding: var(--spacing-lg);
187
- overflow: auto;
188
- overflow-wrap: break-word;
189
- word-break: break-word;
190
- }
191
-
192
- .file-preview-content pre {
193
- margin: 0;
194
- padding: var(--spacing-md);
195
- background-color: var(--bg-color);
196
- border-radius: var(--radius);
197
- overflow-x: hidden;
198
- white-space: pre-wrap;
199
- word-break: break-word;
200
- overflow-wrap: anywhere;
201
- }
202
-
203
- .file-preview-content code {
204
- font-family: 'SF Mono', Monaco, 'Courier New', monospace;
205
- font-size: 0.8125rem;
206
- line-height: 1.6;
207
- }
208
-
209
- .file-preview-content > pre code,
210
- .file-preview-content pre code {
211
- white-space: pre-wrap;
212
- word-break: break-word;
213
- overflow-wrap: anywhere;
214
- }
215
-
216
- /* Markdown 预览样式 */
217
- .markdown-body {
218
- line-height: 1.8;
219
- max-width: 100%;
220
- overflow-wrap: break-word;
221
- word-break: break-word;
222
- }
223
-
224
- .markdown-body pre {
225
- white-space: pre-wrap;
226
- word-break: break-word;
227
- overflow-wrap: anywhere;
228
- overflow-x: hidden;
229
- max-width: 100%;
230
- }
231
-
232
- .markdown-body pre code {
233
- white-space: pre-wrap;
234
- word-break: break-word;
235
- overflow-wrap: anywhere;
236
- }
237
-
238
- /* 宽表格在面板内横向滚动,不撑开栅格 */
239
- .markdown-body .md-table-wrap {
240
- max-width: 100%;
241
- overflow-x: auto;
242
- }
243
-
244
- .markdown-body .md-table-wrap table {
245
- width: max-content;
246
- max-width: none;
247
- }
248
-
249
- .markdown-body h1,
250
- .markdown-body h2,
251
- .markdown-body h3,
252
- .markdown-body h4 {
253
- margin-top: 1.5em;
254
- margin-bottom: 0.5em;
255
- font-weight: 600;
256
- }
257
-
258
- .markdown-body h1 { font-size: 1.5rem; }
259
- .markdown-body h2 { font-size: 1.25rem; }
260
- .markdown-body h3 { font-size: 1.125rem; }
261
-
262
- .markdown-body p {
263
- margin-bottom: 1em;
264
- }
265
-
266
- .markdown-body ul,
267
- .markdown-body ol {
268
- padding-left: 2em;
269
- margin-bottom: 1em;
270
- }
271
-
272
- .markdown-body li {
273
- list-style: disc;
274
- margin-bottom: 0.25em;
275
- }
276
-
277
- .markdown-body ol li {
278
- list-style: decimal;
279
- }
280
-
281
- .markdown-body code {
282
- background-color: var(--bg-color);
283
- padding: 0.125em 0.375em;
284
- border-radius: var(--radius-sm);
285
- font-size: 0.875em;
286
- }
287
-
288
- .markdown-body pre code {
289
- background: none;
290
- padding: 0;
291
- }
292
-
293
- .markdown-body blockquote {
294
- border-left: 4px solid var(--border-color);
295
- padding-left: 1em;
296
- color: var(--text-secondary);
297
- margin: 1em 0;
298
- }
299
-
300
- .markdown-body table {
301
- width: 100%;
302
- border-collapse: collapse;
303
- margin: 1em 0;
304
- }
305
-
306
- .markdown-body th,
307
- .markdown-body td {
308
- border: 1px solid var(--border-color);
309
- padding: 0.5em 1em;
310
- text-align: left;
311
- }
312
-
313
- .markdown-body th {
314
- background-color: var(--bg-color);
315
- }
316
-
317
- /* 版本历史 */
318
- .version-history {
319
- margin-top: 2em;
320
- background-color: var(--white);
321
- border-radius: var(--radius);
322
- box-shadow: var(--shadow);
323
- }
324
-
325
- .version-history-header {
326
- padding: var(--spacing-md) var(--spacing-lg);
327
- border-bottom: 1px solid var(--border-color);
328
- display: flex;
329
- align-items: center;
330
- justify-content: space-between;
331
- cursor: pointer;
332
- }
333
-
334
- .version-history-header:hover {
335
- background-color: var(--bg-color);
336
- }
337
-
338
- .version-history-title {
339
- font-size: 1rem;
340
- font-weight: 600;
341
- color: var(--text-color);
342
- display: flex;
343
- align-items: center;
344
- gap: var(--spacing-sm);
345
- }
346
-
347
- .version-history-toggle {
348
- color: var(--text-muted);
349
- transition: var(--transition);
350
- }
351
-
352
- .version-history.collapsed .version-history-toggle {
353
- transform: rotate(-90deg);
354
- }
355
-
356
- .version-history-list {
357
- padding: 0;
358
- max-height: 400px;
359
- overflow-y: auto;
360
- }
361
-
362
- .version-history.collapsed .version-history-list {
363
- display: none;
364
- }
365
-
366
- .version-item {
367
- padding: var(--spacing-md) var(--spacing-lg);
368
- border-bottom: 1px solid var(--border-color);
369
- display: flex;
370
- align-items: flex-start;
371
- gap: var(--spacing-md);
372
- }
373
-
374
- .version-item:last-child {
375
- border-bottom: none;
376
- }
377
-
378
- .version-item:hover {
379
- background-color: var(--bg-color);
380
- }
381
-
382
- .version-item-tag {
383
- flex-shrink: 0;
384
- }
385
-
386
- .version-item-info {
387
- flex: 1;
388
- min-width: 0;
389
- }
390
-
391
- .version-item-changelog {
392
- font-size: 0.875rem;
393
- color: var(--text-color);
394
- margin-bottom: var(--spacing-xs);
395
- }
396
-
397
- .version-item-meta {
398
- font-size: 0.75rem;
399
- color: var(--text-muted);
400
- display: flex;
401
- gap: var(--spacing-md);
402
- }
403
-
404
- /* 空状态 */
405
- .empty-preview {
406
- display: flex;
407
- flex-direction: column;
408
- align-items: center;
409
- justify-content: center;
410
- height: 100%;
411
- min-height: 300px;
412
- color: var(--text-muted);
413
- }
414
-
415
- .empty-preview-icon {
416
- font-size: 3rem;
417
- margin-bottom: var(--spacing-md);
418
- opacity: 0.5;
419
- }
420
-
421
- /* Loading */
422
- .loading-content {
423
- display: flex;
424
- align-items: center;
425
- justify-content: center;
426
- min-height: 200px;
427
- }
428
-
429
- /* 二进制文件提示 */
430
- .binary-notice {
431
- text-align: center;
432
- padding: var(--spacing-xl);
433
- color: var(--text-secondary);
434
- }
435
-
436
- .binary-notice-icon {
437
- font-size: 3rem;
438
- margin-bottom: var(--spacing-md);
439
- }
440
-
441
- /* 协作者面板 */
442
- .collaborators-panel {
443
- margin-top: var(--spacing-lg);
444
- padding: var(--spacing-lg);
445
- background-color: var(--white);
446
- border-radius: var(--radius);
447
- box-shadow: var(--shadow);
448
- }
449
-
450
- .collaborators-panel .panel-header {
451
- display: flex;
452
- align-items: center;
453
- justify-content: space-between;
454
- margin-bottom: var(--spacing-md);
455
- }
456
-
457
- .collaborators-panel .panel-header h3 {
458
- font-size: 1rem;
459
- font-weight: 600;
460
- margin: 0;
461
- }
462
-
463
- .collaborators-list {
464
- display: flex;
465
- flex-direction: column;
466
- gap: var(--spacing-sm);
467
- }
468
-
469
- .collaborator-item {
470
- display: flex;
471
- align-items: center;
472
- justify-content: space-between;
473
- padding: var(--spacing-sm) var(--spacing-md);
474
- background-color: var(--bg-color);
475
- border-radius: var(--radius-sm, 4px);
476
- }
477
-
478
- .collaborator-info {
479
- display: flex;
480
- align-items: center;
481
- gap: var(--spacing-sm);
482
- }
483
-
484
- .collaborator-role {
485
- font-size: 0.75rem;
486
- padding: 2px 8px;
487
- border-radius: 10px;
488
- background-color: var(--primary-color);
489
- color: var(--white);
490
- font-weight: 500;
491
- }
492
-
493
- .collaborator-role.owner {
494
- background-color: #f59e0b;
495
- }
496
-
497
- .danger-zone {
498
- margin-top: var(--spacing-lg);
499
- padding-top: var(--spacing-lg);
500
- border-top: 1px solid var(--border-color);
501
- }
502
-
503
- .btn-danger {
504
- background-color: #ef4444;
505
- color: white;
506
- border: none;
507
- padding: 6px 16px;
508
- border-radius: var(--radius-sm, 4px);
509
- cursor: pointer;
510
- }
511
-
512
- .btn-danger:hover {
513
- background-color: #dc2626;
514
- }
515
-
516
- /* 弹窗样式 */
517
- .modal {
518
- position: fixed;
519
- top: 0;
520
- left: 0;
521
- right: 0;
522
- bottom: 0;
523
- z-index: 1000;
524
- display: flex;
525
- align-items: center;
526
- justify-content: center;
527
- }
528
-
529
- .modal-overlay {
530
- position: absolute;
531
- top: 0;
532
- left: 0;
533
- right: 0;
534
- bottom: 0;
535
- background-color: rgba(0, 0, 0, 0.5);
536
- }
537
-
538
- .modal-content {
539
- position: relative;
540
- background-color: var(--white);
541
- border-radius: var(--radius);
542
- box-shadow: var(--shadow-lg);
543
- width: 90%;
544
- max-width: 420px;
545
- padding: var(--spacing-lg);
546
- }
547
-
548
- .modal-header {
549
- display: flex;
550
- align-items: center;
551
- justify-content: space-between;
552
- margin-bottom: var(--spacing-md);
553
- }
554
-
555
- .modal-header h3 {
556
- margin: 0;
557
- font-size: 1.125rem;
558
- }
559
-
560
- .modal-close {
561
- background: none;
562
- border: none;
563
- font-size: 1.5rem;
564
- cursor: pointer;
565
- color: var(--text-secondary);
566
- line-height: 1;
567
- }
568
-
569
- .modal-body {
570
- margin-bottom: var(--spacing-lg);
571
- }
572
-
573
- .modal-footer {
574
- display: flex;
575
- justify-content: flex-end;
576
- gap: var(--spacing-sm);
577
- }
578
-
579
- .form-group {
580
- margin-bottom: var(--spacing-md);
581
- }
582
-
583
- .form-group label {
584
- display: block;
585
- margin-bottom: var(--spacing-xs);
586
- font-size: 0.875rem;
587
- font-weight: 500;
588
- }
589
-
590
- .form-input {
591
- width: 100%;
592
- padding: 8px 12px;
593
- border: 1px solid var(--border-color);
594
- border-radius: var(--radius-sm, 4px);
595
- font-size: 0.875rem;
596
- background-color: var(--bg-color);
597
- color: var(--text-color);
598
- box-sizing: border-box;
599
- }
600
-
601
- .warning-text {
602
- color: #ef4444;
603
- font-size: 0.875rem;
604
- margin-bottom: var(--spacing-md);
605
- }
606
-
607
- /* 协作者 username 小字 */
608
- .collaborator-username {
609
- color: var(--text-muted);
610
- font-size: 0.8125rem;
611
- margin-left: 4px;
612
- }
613
-
614
- /* 联想搜索下拉 */
615
- .suggestions-container {
616
- position: relative;
617
- }
618
-
619
- .suggestions-dropdown {
620
- position: absolute;
621
- top: 100%;
622
- left: 0;
623
- right: 0;
624
- background: var(--white);
625
- border: 1px solid var(--border-color);
626
- border-top: none;
627
- border-radius: 0 0 var(--radius-sm, 4px) var(--radius-sm, 4px);
628
- max-height: 200px;
629
- overflow-y: auto;
630
- z-index: 10;
631
- display: none;
632
- }
633
-
634
- .suggestions-dropdown.is-open {
635
- display: block;
636
- }
637
-
638
- .suggestion-item {
639
- padding: 8px 12px;
640
- cursor: pointer;
641
- font-size: 0.875rem;
642
- display: flex;
643
- align-items: center;
644
- gap: 8px;
645
- }
646
-
647
- .suggestion-item:hover,
648
- .suggestion-item.is-active {
649
- background-color: var(--bg-color);
650
- }
651
-
652
- .suggestion-item-name {
653
- color: var(--text-color);
654
- font-weight: 500;
655
- }
656
-
657
- .suggestion-item-username {
658
- color: var(--text-muted);
659
- font-size: 0.8125rem;
660
- }
661
-
662
- .suggestion-empty {
663
- padding: 8px 12px;
664
- font-size: 0.875rem;
665
- color: var(--text-muted);
666
- text-align: center;
667
- }
668
-
669
- @media (max-width: 768px) {
670
- .skill-content {
671
- grid-template-columns: 1fr;
672
- }
673
-
674
- .file-tree-panel {
675
- max-height: 300px;
676
- }
677
-
678
- .skill-header {
679
- flex-direction: column;
680
- }
681
-
682
- .skill-actions {
683
- flex-direction: column;
684
- align-items: stretch;
685
- }
686
-
687
- .version-select {
688
- width: 100%;
689
- }
690
- }
691
- </style>
692
- </head>
693
- <body class="app-devtools">
694
- <!-- 导航栏 -->
695
- <nav class="navbar">
696
- <div class="container">
697
- <a href="/" class="navbar-brand">
698
- <svg class="navbar-brand-icon" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><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"/><polyline points="3.27 6.96 12 12.01 20.73 6.96"/><line x1="12" y1="22.08" x2="12" y2="12"/></svg>
699
- <span>Skill Base</span>
700
- </a>
701
- <div class="navbar-nav">
702
- <a href="/" data-i18n="nav.home">首页</a>
703
- <a href="/publish.html" class="hide-mobile" data-i18n="nav.publish">发布</a>
704
- </div>
705
- </div>
706
- </nav>
707
-
708
- <!-- 页面内容 -->
709
- <main class="page-content">
710
- <div class="container">
711
- <!-- 面包屑导航 -->
712
- <nav class="breadcrumb">
713
- <a href="/" data-i18n="skill.breadcrumbHome">首页</a>
714
- <span class="breadcrumb-separator">›</span>
715
- <span id="breadcrumb-name" data-i18n="state.loading">加载中...</span>
716
- </nav>
717
-
718
- <!-- Skill 基本信息 -->
719
- <section class="skill-info" id="skill-info">
720
- <div class="loading-content">
721
- <div class="spinner"></div>
722
- </div>
723
- </section>
724
-
725
- <!-- 左右分栏:目录树 + 文件预览 -->
726
- <section class="skill-content">
727
- <!-- 文件树面板 -->
728
- <div class="file-tree-panel">
729
- <div class="file-tree-panel-title" data-i18n="skill.fileDir">文件目录</div>
730
- <div id="file-tree" class="file-tree">
731
- <div class="loading-content">
732
- <div class="spinner spinner-sm"></div>
733
- </div>
734
- </div>
735
- </div>
736
-
737
- <!-- 文件预览面板 -->
738
- <div class="file-preview-panel">
739
- <div class="file-preview-header">
740
- <span id="file-preview-path" class="file-preview-path" data-i18n="skill.selectFile">选择文件以预览</span>
741
- <div id="file-preview-md-actions" class="file-preview-md-actions" hidden>
742
- <div class="md-view-toggle" role="group" aria-label="Markdown 显示方式">
743
- <button type="button" id="md-view-render" class="md-view-btn is-active" data-i18n="skill.htmlPreview">HTML 预览</button>
744
- <button type="button" id="md-view-source" class="md-view-btn" data-i18n="skill.mdSource">Markdown 源码</button>
745
- </div>
746
- </div>
747
- </div>
748
- <div id="file-content" class="file-preview-content">
749
- <div class="empty-preview">
750
- <div class="empty-preview-icon">📄</div>
751
- <p data-i18n="skill.clickFile">点击左侧文件查看内容</p>
752
- </div>
753
- </div>
754
- </div>
755
- </section>
756
-
757
- <!-- 协作者管理 -->
758
- <div id="collaborators-panel" class="collaborators-panel" style="display:none;">
759
- <div class="panel-header">
760
- <h3 data-i18n="skill.team">管理团队</h3>
761
- <button id="add-collaborator-btn" class="btn btn-primary btn-sm" style="display:none;" data-i18n="skill.addCollaborator">+ 添加协作者</button>
762
- </div>
763
- <div id="collaborators-list" class="collaborators-list">
764
- <!-- 由 JS 动态渲染 -->
765
- </div>
766
- <div id="skill-danger-zone" class="danger-zone" style="display:none;">
767
- <button id="delete-skill-btn" class="btn btn-danger btn-sm" data-i18n="skill.deleteSkill">删除 Skill</button>
768
- </div>
769
- </div>
770
-
771
- <!-- 版本历史 -->
772
- <section class="version-history" id="version-history">
773
- <div class="version-history-header" onclick="toggleVersionHistory()">
774
- <h3 class="version-history-title">
775
- <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
776
- <circle cx="12" cy="12" r="10"/>
777
- <polyline points="12 6 12 12 16 14"/>
778
- </svg>
779
- <span data-i18n="skill.versionHistory">版本历史</span>
780
- </h3>
781
- <span class="version-history-toggle">
782
- <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
783
- <polyline points="6 9 12 15 18 9"/>
784
- </svg>
785
- </span>
786
- </div>
787
- <div class="version-history-list" id="version-list">
788
- <div class="loading-content">
789
- <div class="spinner spinner-sm"></div>
790
- </div>
791
- </div>
792
- </section>
793
- </div>
794
- </main>
795
-
796
- <!-- 添加协作者弹窗 -->
797
- <div id="add-collaborator-modal" class="modal" style="display:none;">
798
- <div class="modal-overlay"></div>
799
- <div class="modal-content">
800
- <div class="modal-header">
801
- <h3 data-i18n="collab.modal">添加协作者</h3>
802
- <button class="modal-close" onclick="closeCollaboratorModal()">&times;</button>
803
- </div>
804
- <div class="modal-body">
805
- <div class="form-group suggestions-container">
806
- <label data-i18n="collab.usernameLabel">用户名</label>
807
- <input type="text" id="collaborator-username" data-i18n-placeholder="collab.usernamePlaceholder" placeholder="输入用户名" class="form-input" autocomplete="off">
808
- <div id="user-suggestions" class="suggestions-dropdown"></div>
809
- </div>
810
- </div>
811
- <div class="modal-footer">
812
- <button class="btn btn-secondary" onclick="closeCollaboratorModal()" data-i18n="btn.cancel">取消</button>
813
- <button class="btn btn-primary" onclick="submitAddCollaborator()" data-i18n="btn.add">添加</button>
814
- </div>
815
- </div>
816
- </div>
817
-
818
- <!-- 删除 Skill 确认弹窗 -->
819
- <div id="delete-skill-modal" class="modal" style="display:none;">
820
- <div class="modal-overlay"></div>
821
- <div class="modal-content">
822
- <div class="modal-header">
823
- <h3 data-i18n="collab.deleteModal">确认删除</h3>
824
- <button class="modal-close" onclick="closeDeleteModal()">&times;</button>
825
- </div>
826
- <div class="modal-body">
827
- <p class="warning-text" data-i18n="collab.deleteWarning">⚠️ 此操作不可恢复!将删除该 Skill 的所有版本和数据。</p>
828
- <div class="form-group">
829
- <label data-i18n="collab.deleteLabel">请输入 Skill ID 确认删除:</label>
830
- <input type="text" id="delete-confirm-input" placeholder="" class="form-input">
831
- </div>
832
- </div>
833
- <div class="modal-footer">
834
- <button class="btn btn-secondary" onclick="closeDeleteModal()" data-i18n="btn.cancel">取消</button>
835
- <button class="btn btn-danger" onclick="submitDeleteSkill()" data-i18n="collab.deleteConfirmBtn">确认删除</button>
836
- </div>
837
- </div>
838
- </div>
839
-
840
- <!-- CDN 库 -->
841
- <script src="https://cdn.jsdelivr.net/npm/jszip@3.10.1/dist/jszip.min.js"></script>
842
- <script src="https://cdn.jsdelivr.net/npm/marked@11.1.1/marked.min.js"></script>
843
- <script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/highlight.min.js"></script>
844
-
845
- <!-- 引入 JS -->
846
- <script src="/js/i18n.js"></script>
847
- <script src="/js/app.js"></script>
848
- <script src="/js/skill.js"></script>
849
- <script src="/js/collaborators.js"></script>
850
- </body>
851
- </html>