|
392 | 392 | {#if globalState.selectedBucket} |
393 | 393 | <!-- Main Content Area (Flexible Height) --> |
394 | 394 | <div class="flex flex-1 flex-col gap-4 overflow-hidden"> |
395 | | - <!-- Files Section --> |
| 395 | + <!-- Combined Files and Multipart Uploads Section --> |
396 | 396 | <div class="relative flex flex-1 flex-col gap-4 rounded-lg border border-slate-200 dark:border-slate-700 overflow-hidden"> |
397 | 397 | {#if loading} |
398 | 398 | <!-- Loading Overlay --> |
|
404 | 404 | </div> |
405 | 405 | {/if} |
406 | 406 |
|
407 | | - {#if files.length === 0 && !loading} |
| 407 | + {#if files.length === 0 && multipartUploads.length === 0 && !loading} |
408 | 408 | <div class="flex flex-1 items-center justify-center p-4 text-center text-slate-500 dark:text-slate-400"> |
409 | 409 | {t().manage.files.noFiles} |
410 | 410 | </div> |
411 | | - {:else if files.length > 0} |
| 411 | + {:else if files.length > 0 || multipartUploads.length > 0} |
412 | 412 | <div class="flex flex-1 flex-col overflow-hidden"> |
413 | 413 | <!-- Table Header (Fixed) --> |
414 | | - <table class="w-full text-sm flex-shrink-0"> |
| 414 | + <table class="w-full text-sm flex-shrink-0 table-fixed"> |
| 415 | + <colgroup> |
| 416 | + <col style="width: auto;" /> |
| 417 | + <col style="width: 120px;" /> |
| 418 | + <col style="width: 200px;" /> |
| 419 | + <col style="width: 160px;" /> |
| 420 | + </colgroup> |
415 | 421 | <thead class="border-b border-slate-200 bg-slate-50 dark:border-slate-700 dark:bg-slate-800"> |
416 | 422 | <tr> |
417 | 423 | <th class="px-4 py-2 text-left">{t().manage.files.name}</th> |
418 | | - <th class="px-4 py-2 text-right">{t().manage.files.size}</th> |
419 | | - <th class="px-4 py-2 text-left">{t().manage.files.modified}</th> |
420 | | - <th class="px-4 py-2 text-right">{t().manage.files.actions}</th> |
| 424 | + <th class="px-4 py-2 text-right whitespace-nowrap">{t().manage.files.size}</th> |
| 425 | + <th class="px-4 py-2 text-left whitespace-nowrap">{t().manage.files.modified}</th> |
| 426 | + <th class="px-4 py-2 text-right whitespace-nowrap">{t().manage.files.actions}</th> |
421 | 427 | </tr> |
422 | 428 | </thead> |
423 | 429 | </table> |
424 | 430 |
|
425 | 431 | <!-- Table Body (Scrollable) --> |
426 | 432 | <div class="flex-1 overflow-y-auto"> |
427 | | - <table class="w-full text-sm"> |
| 433 | + <table class="w-full text-sm table-fixed"> |
| 434 | + <colgroup> |
| 435 | + <col style="width: auto;" /> |
| 436 | + <col style="width: 120px;" /> |
| 437 | + <col style="width: 200px;" /> |
| 438 | + <col style="width: 160px;" /> |
| 439 | + </colgroup> |
428 | 440 | <tbody> |
| 441 | + <!-- Multipart Uploads (显示在最前面) --> |
| 442 | + {#each multipartUploads as upload} |
| 443 | + <tr class="border-b border-slate-200 bg-orange-50 hover:bg-orange-100 dark:border-slate-700 dark:bg-orange-900/20 dark:hover:bg-orange-900/30"> |
| 444 | + <td class="px-4 py-2 font-mono text-xs truncate" title={upload.key}> |
| 445 | + <div class="flex items-center gap-2"> |
| 446 | + <span class="inline-flex items-center rounded-full bg-orange-100 px-2 py-0.5 text-xs font-medium text-orange-800 dark:bg-orange-900/50 dark:text-orange-300"> |
| 447 | + 上传中 |
| 448 | + </span> |
| 449 | + <span>{upload.key}</span> |
| 450 | + </div> |
| 451 | + </td> |
| 452 | + <td class="px-4 py-2 text-right whitespace-nowrap text-slate-400 dark:text-slate-500">-</td> |
| 453 | + <td class="px-4 py-2 whitespace-nowrap">{formatDate(upload.initiated)}</td> |
| 454 | + <td class="px-4 py-2 text-right whitespace-nowrap"> |
| 455 | + <button |
| 456 | + onclick={() => abortUpload(upload.key, upload.uploadId)} |
| 457 | + class="text-red-500 hover:text-red-700" |
| 458 | + title={t().manage.multipartUploads.abort} |
| 459 | + > |
| 460 | + <Trash2 size={16} /> |
| 461 | + </button> |
| 462 | + </td> |
| 463 | + </tr> |
| 464 | + {/each} |
| 465 | + |
| 466 | + <!-- Files (正常文件列表) --> |
429 | 467 | {#each files as file} |
430 | 468 | <tr class="border-b border-slate-200 hover:bg-slate-50 dark:border-slate-700 dark:hover:bg-slate-800"> |
431 | | - <td class="px-4 py-2 font-mono text-xs">{file.key}</td> |
432 | | - <td class="px-4 py-2 text-right">{formatSize(file.size)}</td> |
433 | | - <td class="px-4 py-2">{formatDate(file.lastModified)}</td> |
434 | | - <td class="px-4 py-2 text-right"> |
435 | | - <div class="flex justify-end gap-2"> |
| 469 | + <td class="px-4 py-2 font-mono text-xs truncate" title={file.key}>{file.key}</td> |
| 470 | + <td class="px-4 py-2 text-right whitespace-nowrap">{formatSize(file.size)}</td> |
| 471 | + <td class="px-4 py-2 whitespace-nowrap">{formatDate(file.lastModified)}</td> |
| 472 | + <td class="px-4 py-2 text-right whitespace-nowrap"> |
| 473 | + <div class="flex justify-end gap-2 flex-nowrap"> |
436 | 474 | {#if isImageFile(file.key)} |
437 | 475 | <button |
438 | 476 | onclick={() => previewImage(file.key)} |
|
555 | 593 | {error} |
556 | 594 | </div> |
557 | 595 | {/if} |
558 | | - |
559 | | - <!-- Multipart Uploads Section --> |
560 | | - {#if multipartUploads.length > 0} |
561 | | - <div class="rounded-lg border border-slate-200 dark:border-slate-700"> |
562 | | - <div class="border-b border-slate-200 bg-slate-50 p-3 dark:border-slate-700 dark:bg-slate-800"> |
563 | | - <h2 class="font-semibold text-slate-800 dark:text-slate-200"> |
564 | | - {t().manage.multipartUploads.title} |
565 | | - </h2> |
566 | | - </div> |
567 | | - <div class="overflow-x-auto"> |
568 | | - <table class="w-full text-sm"> |
569 | | - <thead class="border-b border-slate-200 bg-slate-50 dark:border-slate-700 dark:bg-slate-800"> |
570 | | - <tr> |
571 | | - <th class="px-4 py-2 text-left">{t().manage.multipartUploads.name}</th> |
572 | | - <th class="px-4 py-2 text-left">{t().manage.multipartUploads.initiated}</th> |
573 | | - <th class="px-4 py-2 text-right">{t().manage.multipartUploads.actions}</th> |
574 | | - </tr> |
575 | | - </thead> |
576 | | - <tbody> |
577 | | - {#each multipartUploads as upload} |
578 | | - <tr class="border-b border-slate-200 hover:bg-slate-50 dark:border-slate-700 dark:hover:bg-slate-800"> |
579 | | - <td class="px-4 py-2">{upload.key}</td> |
580 | | - <td class="px-4 py-2">{formatDate(upload.initiated)}</td> |
581 | | - <td class="px-4 py-2 text-right"> |
582 | | - <button |
583 | | - onclick={() => abortUpload(upload.key, upload.uploadId)} |
584 | | - class="text-red-500 hover:text-red-700" |
585 | | - > |
586 | | - {t().manage.multipartUploads.abort} |
587 | | - </button> |
588 | | - </td> |
589 | | - </tr> |
590 | | - {/each} |
591 | | - </tbody> |
592 | | - </table> |
593 | | - </div> |
594 | | - </div> |
595 | | - {/if} |
596 | 596 | {/if} |
597 | 597 | </div> |
598 | 598 | </div> |
|
0 commit comments