@done-coding/admin-core 0.20.1-alpha.0 → 0.21.1-alpha.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.
Files changed (136) hide show
  1. package/es/components/app-layout/AppLayout.vue.mjs +1 -1
  2. package/es/components/app-layout/AppLayout.vue2.mjs +51 -6
  3. package/es/components/app-layout/AppPage.vue.mjs +1 -1
  4. package/es/components/app-layout/AppPage.vue2.mjs +16 -9
  5. package/es/components/display/ShadowClone.vue.mjs +32 -0
  6. package/es/components/display/ShadowClone.vue2.mjs +4 -0
  7. package/es/components/display/use-shadow-target.mjs +76 -0
  8. package/es/components/form/FormActiveFilter.vue.mjs +7 -0
  9. package/es/components/form/FormActiveFilter.vue2.mjs +62 -0
  10. package/es/components/form/FormInput.vue.mjs +27 -0
  11. package/es/components/form/FormInput.vue2.mjs +4 -0
  12. package/es/components/form/FormInputShadowClone.vue.mjs +47 -0
  13. package/es/components/form/FormInputShadowClone.vue2.mjs +4 -0
  14. package/es/components/form/FormMain.vue.mjs +1 -1
  15. package/es/components/form/FormMain.vue2.mjs +5 -25
  16. package/es/components/form/FormSelectShadowClone.vue.mjs +57 -0
  17. package/es/components/form/FormSelectShadowClone.vue2.mjs +4 -0
  18. package/es/components/form/FormShadowCloneDispatch.vue.mjs +7 -0
  19. package/es/components/form/FormShadowCloneDispatch.vue2.mjs +74 -0
  20. package/es/components/form/FormSortSwitch.vue.mjs +7 -0
  21. package/es/components/form/FormSortSwitch.vue2.mjs +188 -0
  22. package/es/components/form/FormSortSwitchGroup.vue.mjs +7 -0
  23. package/es/components/form/FormSortSwitchGroup.vue2.mjs +68 -0
  24. package/es/components/form/FormUpload.vue.mjs +8 -0
  25. package/es/components/form/FormUpload.vue2.mjs +112 -0
  26. package/es/components/form/FormUploadAudio.vue.mjs +7 -0
  27. package/es/components/form/FormUploadAudio.vue2.mjs +88 -0
  28. package/es/components/form/FormUploadCard.vue.mjs +7 -0
  29. package/es/components/form/FormUploadCard.vue2.mjs +56 -0
  30. package/es/components/form/FormUploadFileInfo.vue.mjs +7 -0
  31. package/es/components/form/FormUploadFileInfo.vue2.mjs +36 -0
  32. package/es/components/form/FormUploadImage.vue.mjs +7 -0
  33. package/es/components/form/FormUploadImage.vue2.mjs +77 -0
  34. package/es/components/form/FormUploadTrigger.vue.mjs +7 -0
  35. package/es/components/form/FormUploadTrigger.vue2.mjs +34 -0
  36. package/es/components/form/FormUploadVideo.vue.mjs +7 -0
  37. package/es/components/form/FormUploadVideo.vue2.mjs +74 -0
  38. package/es/components/form/use-password-autofill.mjs +34 -0
  39. package/es/components/form/use-upload-state.mjs +98 -0
  40. package/es/components/list-layout/ListLayout.vue.mjs +1 -1
  41. package/es/components/list-layout/ListLayout.vue2.mjs +36 -9
  42. package/es/components/list-layout/use-active-filter.mjs +133 -0
  43. package/es/components/modal/ImagePreviewTrigger.vue.mjs +34 -0
  44. package/es/components/modal/ImagePreviewTrigger.vue2.mjs +4 -0
  45. package/es/components/modal/ModalImagePreview.vue.mjs +52 -0
  46. package/es/components/modal/ModalImagePreview.vue2.mjs +4 -0
  47. package/es/components/modal/ModalPorter.vue.mjs +49 -2
  48. package/es/components/modal/ModalShelf.vue.mjs +13 -4
  49. package/es/components/modal/ModalVideoPreview.vue.mjs +8 -0
  50. package/es/components/modal/ModalVideoPreview.vue2.mjs +93 -0
  51. package/es/components/modal/VideoPreviewTrigger.vue.mjs +7 -0
  52. package/es/components/modal/VideoPreviewTrigger.vue2.mjs +96 -0
  53. package/es/components/modal/modal-global-keys.mjs +11 -0
  54. package/es/components/modal/modal-global-symbol.mjs +6 -0
  55. package/es/components/modal/modal-shelf-core.mjs +53 -4
  56. package/es/components/table/TableEmpty.vue.mjs +36 -0
  57. package/es/components/table/TableEmpty.vue2.mjs +4 -0
  58. package/es/components/table/TableMain.vue.mjs +1 -1
  59. package/es/components/table/TableMain.vue2.mjs +21 -8
  60. package/es/components/view-layout/ViewLayout.vue.mjs +1 -1
  61. package/es/components/view-layout/ViewLayout.vue2.mjs +1 -1
  62. package/es/hooks/menus-dispatch.mjs +8 -3
  63. package/es/index.mjs +127 -91
  64. package/es/style.css +412 -33
  65. package/package.json +2 -2
  66. package/src/components/app-layout/docs/README-AppLayout.md +48 -0
  67. package/src/components/app-layout/docs/README-AppPage.md +40 -2
  68. package/src/components/display/README.md +9 -3
  69. package/src/components/display/docs/README-ShadowClone.md +75 -0
  70. package/src/components/form/README.md +15 -2
  71. package/src/components/form/docs/README-FormActiveFilter.md +57 -0
  72. package/src/components/form/docs/README-FormInput.md +66 -0
  73. package/src/components/form/docs/README-FormSelect.md +77 -0
  74. package/src/components/form/docs/README-FormShadowCloneDispatch.md +65 -0
  75. package/src/components/form/docs/README-FormSortSwitchGroup.md +131 -0
  76. package/src/components/form/docs/README-FormUpload.md +108 -0
  77. package/src/components/form/docs/README-FormUploadAudio.md +80 -0
  78. package/src/components/form/docs/README-FormUploadImage.md +83 -0
  79. package/src/components/form/docs/README-FormUploadVideo.md +82 -0
  80. package/src/components/list-layout/README.md +6 -2
  81. package/src/components/list-layout/docs/README-ListLayout.md +1 -0
  82. package/src/components/modal/README.md +7 -2
  83. package/src/components/modal/docs/README-ImagePreviewTrigger.md +78 -0
  84. package/src/components/modal/docs/README-ModalImagePreview.md +78 -0
  85. package/src/components/modal/docs/README-ModalPorter.md +10 -0
  86. package/src/components/modal/docs/README-ModalShelf.md +11 -2
  87. package/src/components/modal/docs/README-ModalVideoPreview.md +89 -0
  88. package/src/components/modal/docs/README-VideoPreviewTrigger.md +91 -0
  89. package/src/components/table/docs/README-TableMain.md +3 -0
  90. package/types/components/app-layout/AppLayout.vue.d.ts +31 -1
  91. package/types/components/app-layout/AppPage.vue.d.ts +7 -2
  92. package/types/components/app-layout/types.d.ts +25 -0
  93. package/types/components/display/ShadowClone.vue.d.ts +20 -0
  94. package/types/components/display/TabsTile.vue.d.ts +2 -2
  95. package/types/components/display/index.d.ts +8 -1
  96. package/types/components/display/types.d.ts +7 -0
  97. package/types/components/display/use-shadow-target.d.ts +9 -0
  98. package/types/components/form/FormActiveFilter.vue.d.ts +9 -0
  99. package/types/components/form/FormInput.vue.d.ts +3 -0
  100. package/types/components/form/FormInputShadowClone.vue.d.ts +7 -0
  101. package/types/components/form/FormSearch.vue.d.ts +1 -1
  102. package/types/components/form/FormSelectShadowClone.vue.d.ts +39 -0
  103. package/types/components/form/FormShadowCloneDispatch.vue.d.ts +44 -0
  104. package/types/components/form/FormSortSwitch.vue.d.ts +17 -0
  105. package/types/components/form/FormSortSwitchGroup.vue.d.ts +15 -0
  106. package/types/components/form/FormUpload.vue.d.ts +57 -0
  107. package/types/components/form/FormUploadAudio.vue.d.ts +30 -0
  108. package/types/components/form/FormUploadCard.vue.d.ts +24 -0
  109. package/types/components/form/FormUploadFileInfo.vue.d.ts +10 -0
  110. package/types/components/form/FormUploadImage.vue.d.ts +34 -0
  111. package/types/components/form/FormUploadTrigger.vue.d.ts +11 -0
  112. package/types/components/form/FormUploadVideo.vue.d.ts +34 -0
  113. package/types/components/form/index.d.ts +12 -1
  114. package/types/components/form/types.d.ts +158 -0
  115. package/types/components/form/use-password-autofill.d.ts +11 -0
  116. package/types/components/form/use-upload-state.d.ts +29 -0
  117. package/types/components/list-layout/ListLayout.vue.d.ts +3 -0
  118. package/types/components/list-layout/types.d.ts +16 -0
  119. package/types/components/list-layout/use-active-filter.d.ts +27 -0
  120. package/types/components/modal/ImagePreviewTrigger.vue.d.ts +41 -0
  121. package/types/components/modal/ModalConfirm.vue.d.ts +1 -1
  122. package/types/components/modal/ModalImagePreview.vue.d.ts +31 -0
  123. package/types/components/modal/ModalPorter.vue.d.ts +7 -0
  124. package/types/components/modal/ModalShelf.vue.d.ts +12 -3
  125. package/types/components/modal/ModalVideoPreview.vue.d.ts +40 -0
  126. package/types/components/modal/VideoPreviewTrigger.vue.d.ts +43 -0
  127. package/types/components/modal/index.d.ts +6 -1
  128. package/types/components/modal/modal-global-keys.d.ts +25 -0
  129. package/types/components/modal/modal-global-symbol.d.ts +8 -0
  130. package/types/components/modal/modal-shelf-core.d.ts +11 -3
  131. package/types/components/modal/modal-shelf-types.d.ts +50 -0
  132. package/types/components/table/TableEmpty.vue.d.ts +11 -0
  133. package/types/components/table/types.d.ts +11 -0
  134. package/types/components/view-layout/types.d.ts +1 -1
  135. package/types/injectInfo.json.d.ts +1 -1
  136. package/types/store/app.d.ts +1 -1
package/es/style.css CHANGED
@@ -71,9 +71,30 @@
71
71
  .form-item-label-hide[data-v-8b508d64] .el-form-item__label-wrap {
72
72
  display: none;
73
73
  }
74
- [data-v-cc2ea388] .el-row > .el-col > .el-form-item {
74
+ [data-v-fca51c0e] .el-row > .el-col > .el-form-item {
75
75
  margin-bottom: 18px;
76
76
  }
77
+ .dc-form-shadow-clone-dispatch[data-v-5096627a] {
78
+ display: inline-flex;
79
+ align-items: center;
80
+ gap: 2px;
81
+ color: var(--el-text-color-regular);
82
+ }
83
+ .dc-form-shadow-clone-dispatch__label[data-v-5096627a] {
84
+ font-size: 14px;
85
+ font-weight: 600;
86
+ white-space: nowrap;
87
+ }
88
+ .dc-form-shadow-clone-dispatch--active[data-v-5096627a] {
89
+ color: var(--dc-core-primary-color, var(--el-color-primary));
90
+ }
91
+ .dc-form-shadow-clone-dispatch--active .dc-form-filter-funnel[data-v-5096627a] {
92
+ color: inherit;
93
+ }
94
+ .dc-form-filter-funnel[data-v-5096627a] {
95
+ padding: 4px;
96
+ color: var(--el-text-color-secondary);
97
+ }
77
98
  .form-submit-panel[data-v-1505775a] {
78
99
  display: flex;
79
100
  flex-direction: column;
@@ -520,27 +541,79 @@
520
541
  .app-theme__style-select[data-v-06ca4822] {
521
542
  width: 120px;
522
543
  }
523
- .app-layout[data-v-f6f87b30] {
544
+ .modal-video-preview__stage[data-v-d4b84c07] {
545
+ height: 100vh;
546
+ display: flex;
547
+ align-items: center;
548
+ justify-content: center;
549
+ background: var(--el-color-black);
550
+ }
551
+ .modal-video-preview__shim[data-v-d4b84c07] {
552
+ width: min(960px, 100%);
553
+ aspect-ratio: 16 / 9;
554
+ }
555
+ .modal-video-preview__video[data-v-d4b84c07] {
556
+ display: block;
557
+ width: 100%;
558
+ height: 100%;
559
+ background: var(--el-color-black);
560
+ }
561
+ .dc-modal-video-preview.el-dialog {
562
+ background: transparent;
563
+ box-shadow: none;
564
+ border: none;
565
+ border-radius: 0;
566
+ overflow: visible;
567
+ padding: 0;
568
+ }
569
+ .dc-modal-video-preview.el-dialog .el-dialog__header {
570
+ padding: 0;
571
+ }
572
+ .dc-modal-video-preview.el-dialog .el-dialog__body {
573
+ padding: 0;
574
+ }
575
+ .dc-modal-video-preview.el-dialog .el-dialog__headerbtn {
576
+ top: 40px;
577
+ right: 40px;
578
+ width: 44px;
579
+ height: 44px;
580
+ border-radius: 50%;
581
+ background: #606266;
582
+ color: var(--el-color-white);
583
+ opacity: 0.9;
584
+ transition: opacity 0.2s;
585
+ }
586
+ .dc-modal-video-preview.el-dialog .el-dialog__headerbtn:hover {
587
+ opacity: 1;
588
+ }
589
+ .dc-modal-video-preview.el-dialog .el-dialog__headerbtn .el-dialog__close {
590
+ color: inherit;
591
+ font-size: 24px;
592
+ }
593
+ .dc-modal-video-preview__overlay {
594
+ background: var(--el-overlay-color-dark, rgba(0, 0, 0, 0.7));
595
+ }
596
+ .app-layout[data-v-b45bcdfd] {
524
597
  position: relative;
525
598
  }
526
- .app-layout_noLogin[data-v-f6f87b30] .app-body,
527
- .app-layout_noLogin[data-v-f6f87b30] .app-sidebar,
528
- .app-layout_noLogin[data-v-f6f87b30] .app-header,
529
- .app-layout_noLogin[data-v-f6f87b30] .app-footer {
599
+ .app-layout_noLogin[data-v-b45bcdfd] .app-body,
600
+ .app-layout_noLogin[data-v-b45bcdfd] .app-sidebar,
601
+ .app-layout_noLogin[data-v-b45bcdfd] .app-header,
602
+ .app-layout_noLogin[data-v-b45bcdfd] .app-footer {
530
603
  transition: none !important;
531
604
  }
532
- .app-page[data-v-8fb8acc9] {
533
- --dc-page-content-viewport-top: var(--v292949d5);
534
- --dc-page-content-viewport-bottom: var(--v45d97caa);
535
- --dc-page-content-viewport-left: var(--v0807b0f2);
536
- --dc-page-content-viewport-right: var(--f841aac8);
537
- --dc-page-content-viewport-width: var(--f7b4d374);
538
- --dc-page-content-viewport-height: var(--v32838eb2);
605
+ .app-page[data-v-2d4bb608] {
606
+ --dc-page-content-viewport-top: var(--v68a1d5b5);
607
+ --dc-page-content-viewport-bottom: var(--v0a30a9cb);
608
+ --dc-page-content-viewport-left: var(--a8d5d0b2);
609
+ --dc-page-content-viewport-right: var(--v71378308);
610
+ --dc-page-content-viewport-width: var(--v70aaabb4);
611
+ --dc-page-content-viewport-height: var(--v13dba0c7);
539
612
  }
540
- .app-page-shim[data-v-8fb8acc9] {
541
- --app-viewport-max-height: var(--v5c736bbc);
613
+ .app-page-shim[data-v-2d4bb608] {
614
+ --app-viewport-max-height: var(--v746c0602);
542
615
  }
543
- .app-page-slot-shim[data-v-8fb8acc9] {
616
+ .app-page-slot-shim[data-v-2d4bb608] {
544
617
  box-sizing: border-box;
545
618
  width: 100%;
546
619
  height: 100%;
@@ -568,6 +641,26 @@ to {
568
641
  transform: rotate(360deg);
569
642
  }
570
643
  }
644
+ .form-active-filter[data-v-6d2d37c2] {
645
+ display: flex;
646
+ flex-wrap: wrap;
647
+ align-items: center;
648
+ gap: 8px;
649
+ padding-bottom: 4px;
650
+ }
651
+ .form-active-filter__label[data-v-6d2d37c2] {
652
+ font-weight: 600;
653
+ }
654
+ .form-active-filter__clear[data-v-6d2d37c2] {
655
+ margin-left: 4px;
656
+ }
657
+ .form-active-filter__empty[data-v-6d2d37c2] {
658
+ display: inline-flex;
659
+ align-items: center;
660
+ height: 24px;
661
+ font-size: 13px;
662
+ color: var(--el-text-color-placeholder);
663
+ }
571
664
  .form-item-nest-form[data-v-a413a382] {
572
665
  padding: 16px;
573
666
  border: 1px solid var(--dc-core-border-color);
@@ -594,6 +687,292 @@ to {
594
687
  border-radius: 6px;
595
688
  box-shadow: var(--el-box-shadow-lighter);
596
689
  }
690
+ .form-sort__chip[data-v-9aa4f615] {
691
+ position: relative;
692
+ align-self: flex-start;
693
+ margin-left: 0;
694
+ padding-left: 6px;
695
+ padding-right: 6px;
696
+ color: var(--el-text-color-regular);
697
+ background: var(--el-fill-color-blank);
698
+ border-color: var(--el-border-color);
699
+ border-radius: var(--dc-core-radius, var(--el-border-radius-base));
700
+ }
701
+ .form-sort--cycle.form-sort__chip[data-v-9aa4f615]:hover {
702
+ color: var(--el-color-primary);
703
+ border-color: var(--el-color-primary-light-5);
704
+ background: var(--el-fill-color-light);
705
+ }
706
+ .form-sort__chip_active[data-v-9aa4f615] {
707
+ color: var(--el-color-primary);
708
+ background: var(--el-color-primary-light-9);
709
+ border-color: var(--el-color-primary-light-5);
710
+ }
711
+ .form-sort__icon[data-v-9aa4f615] {
712
+ display: inline-flex;
713
+ flex-direction: column;
714
+ align-items: center;
715
+ justify-content: center;
716
+ width: 14px;
717
+ height: 22px;
718
+ margin-right: 4px;
719
+ }
720
+ .form-sort__caret[data-v-9aa4f615] {
721
+ position: relative;
722
+ font-size: 12px;
723
+ line-height: 0.6;
724
+ color: var(--el-text-color-placeholder);
725
+ }
726
+ .form-sort__caret[data-v-9aa4f615]::before {
727
+ content: "";
728
+ position: absolute;
729
+ inset: -3px -5px;
730
+ }
731
+ .form-sort__caret[data-v-9aa4f615]:first-child {
732
+ margin-bottom: -2px;
733
+ }
734
+ .form-sort__caret[data-v-9aa4f615]:last-child {
735
+ margin-top: -2px;
736
+ }
737
+ .form-sort--dual-arrow.form-sort__chip[data-v-9aa4f615] {
738
+ cursor: default;
739
+ }
740
+ .form-sort--dual-arrow .form-sort__caret[data-v-9aa4f615] {
741
+ cursor: pointer;
742
+ color: var(--el-text-color-secondary);
743
+ }
744
+ .form-sort--dual-arrow .form-sort__caret[data-v-9aa4f615]:hover {
745
+ color: var(--el-color-primary);
746
+ }
747
+ .form-sort__caret_on[data-v-9aa4f615],
748
+ .form-sort--dual-arrow .form-sort__caret_on[data-v-9aa4f615] {
749
+ color: var(--el-color-primary);
750
+ }
751
+ .form-sort__order[data-v-9aa4f615] {
752
+ margin-left: 6px;
753
+ font-size: 11px;
754
+ font-weight: 600;
755
+ line-height: 1;
756
+ color: var(--el-color-primary);
757
+ }
758
+ .form-sort[data-v-e86178b8] {
759
+ display: inline-flex;
760
+ vertical-align: middle;
761
+ }
762
+ .dc-form-upload-trigger[data-v-9fb0fb2a] {
763
+ display: flex;
764
+ align-items: center;
765
+ justify-content: center;
766
+ gap: 6px;
767
+ padding: 14px 16px;
768
+ color: var(--el-text-color-secondary);
769
+ cursor: pointer;
770
+ transition: color 0.2s;
771
+ }
772
+ .dc-form-upload-trigger[data-v-9fb0fb2a]:hover {
773
+ color: var(--el-color-primary);
774
+ }
775
+ .dc-form-upload-trigger_card[data-v-9fb0fb2a] {
776
+ width: 100%;
777
+ height: 100%;
778
+ padding: 0;
779
+ color: var(--el-text-color-secondary);
780
+ }
781
+ .dc-form-upload__placeholder[data-v-158fc67d] {
782
+ margin-top: 4px;
783
+ font-size: 12px;
784
+ line-height: 1.5;
785
+ color: var(--el-text-color-secondary);
786
+ }
787
+ .dc-form-upload__inner {
788
+ display: flex;
789
+ flex-direction: column;
790
+ }
791
+ .dc-form-upload__inner > .el-upload-list {
792
+ order: 1;
793
+ }
794
+ .dc-form-upload__inner > .el-upload {
795
+ order: 2;
796
+ }
797
+ .dc-form-upload_full .el-upload {
798
+ display: none;
799
+ }
800
+ .dc-form-upload-file-info[data-v-6a6d170c] {
801
+ min-width: 0;
802
+ flex: 1;
803
+ display: flex;
804
+ flex-direction: column;
805
+ gap: 2px;
806
+ }
807
+ .dc-form-upload-file-info__name[data-v-6a6d170c] {
808
+ overflow: hidden;
809
+ text-overflow: ellipsis;
810
+ white-space: nowrap;
811
+ font-size: 13px;
812
+ color: var(--el-text-color-primary);
813
+ }
814
+ .dc-form-upload-file-info__meta[data-v-6a6d170c] {
815
+ font-size: 12px;
816
+ color: var(--el-text-color-secondary);
817
+ }
818
+ .dc-form-upload-audio__item[data-v-3884f0f6] {
819
+ display: flex;
820
+ align-items: center;
821
+ gap: 12px;
822
+ width: 100%;
823
+ }
824
+ .dc-form-upload-audio__player[data-v-3884f0f6] {
825
+ flex-shrink: 0;
826
+ width: 240px;
827
+ height: 32px;
828
+ }
829
+ .dc-form-upload-audio__player_empty[data-v-3884f0f6] {
830
+ background: var(--el-fill-color-light);
831
+ border-radius: var(--dc-core-radius, var(--el-border-radius-base));
832
+ }
833
+ .dc-form-upload-audio__remove[data-v-3884f0f6] {
834
+ flex-shrink: 0;
835
+ display: flex;
836
+ align-items: center;
837
+ justify-content: center;
838
+ width: 20px;
839
+ height: 20px;
840
+ padding: 0;
841
+ border: none;
842
+ border-radius: 50%;
843
+ background: var(--el-color-info-dark-2, #606266);
844
+ color: var(--el-color-white);
845
+ cursor: pointer;
846
+ opacity: 0;
847
+ transition: opacity 0.2s;
848
+ }
849
+ .dc-form-upload-audio__item:hover .dc-form-upload-audio__remove[data-v-3884f0f6] {
850
+ opacity: 1;
851
+ }
852
+ .dc-form-upload-card[data-v-48323f64] {
853
+ position: relative;
854
+ width: 100%;
855
+ height: 100%;
856
+ overflow: hidden;
857
+ background: var(--el-fill-color-light);
858
+ }
859
+ .dc-form-upload-card__mask[data-v-48323f64] {
860
+ position: absolute;
861
+ inset: 0;
862
+ display: flex;
863
+ flex-direction: column;
864
+ align-items: center;
865
+ justify-content: center;
866
+ gap: 4px;
867
+ padding: 0 8px;
868
+ background: var(--el-overlay-color-lighter, rgba(0, 0, 0, 0.2));
869
+ color: var(--el-color-white);
870
+ font-size: 12px;
871
+ }
872
+ .dc-form-upload-card__mask-name[data-v-48323f64] {
873
+ max-width: 100%;
874
+ overflow: hidden;
875
+ text-overflow: ellipsis;
876
+ white-space: nowrap;
877
+ }
878
+ .dc-form-upload-card__mask-percent[data-v-48323f64] {
879
+ font-size: 13px;
880
+ font-weight: 600;
881
+ }
882
+ .dc-form-upload-card__mask-bar[data-v-48323f64] {
883
+ position: absolute;
884
+ left: 0;
885
+ bottom: 0;
886
+ height: 3px;
887
+ background: var(--el-color-primary);
888
+ transition: width 0.2s;
889
+ }
890
+ .dc-form-upload-card__remove[data-v-48323f64] {
891
+ position: absolute;
892
+ top: 4px;
893
+ right: 4px;
894
+ display: flex;
895
+ align-items: center;
896
+ justify-content: center;
897
+ width: 20px;
898
+ height: 20px;
899
+ padding: 0;
900
+ border: none;
901
+ border-radius: 50%;
902
+ background: var(--el-color-info-dark-2, #606266);
903
+ color: var(--el-color-white);
904
+ cursor: pointer;
905
+ opacity: 0;
906
+ transition: opacity 0.2s;
907
+ }
908
+ .dc-form-upload-card:hover .dc-form-upload-card__remove[data-v-48323f64] {
909
+ opacity: 1;
910
+ }
911
+ .dc-form-upload-image__thumb[data-v-9d62114a] {
912
+ display: block;
913
+ width: 100%;
914
+ height: 100%;
915
+ }
916
+ .dc-form-upload-image__thumb_empty[data-v-9d62114a] {
917
+ background: var(--el-fill-color-light);
918
+ }
919
+ .video-preview-trigger_placeholder[data-v-49e0acc8] {
920
+ display: flex;
921
+ align-items: center;
922
+ justify-content: center;
923
+ width: 100%;
924
+ aspect-ratio: 16 / 9;
925
+ max-width: 360px;
926
+ background: var(--el-fill-color-dark);
927
+ border-radius: var(--dc-core-radius, var(--el-border-radius-base));
928
+ cursor: pointer;
929
+ transition: background-color 0.2s;
930
+ }
931
+ .video-preview-trigger_placeholder[data-v-49e0acc8]:hover {
932
+ background: var(--el-fill-color-darker);
933
+ }
934
+ .video-preview-trigger_cover[data-v-49e0acc8] {
935
+ position: relative;
936
+ display: inline-block;
937
+ line-height: 0;
938
+ border-radius: var(--dc-core-radius, var(--el-border-radius-base));
939
+ overflow: hidden;
940
+ cursor: pointer;
941
+ }
942
+ .video-preview-trigger_cover .video-preview-trigger__cover[data-v-49e0acc8] {
943
+ display: block;
944
+ }
945
+ .video-preview-trigger__play-badge[data-v-49e0acc8] {
946
+ position: absolute;
947
+ top: 50%;
948
+ left: 50%;
949
+ transform: translate(-50%, -50%);
950
+ display: flex;
951
+ align-items: center;
952
+ justify-content: center;
953
+ width: 48px;
954
+ height: 48px;
955
+ border-radius: 50%;
956
+ background: var(--el-overlay-color-light, rgba(0, 0, 0, 0.35));
957
+ color: var(--el-color-white);
958
+ pointer-events: none;
959
+ transition: transform 0.2s;
960
+ }
961
+ .video-preview-trigger_cover:hover .video-preview-trigger__play-badge[data-v-49e0acc8] {
962
+ transform: translate(-50%, -50%) scale(1.08);
963
+ }
964
+ .video-preview-trigger__play-icon[data-v-49e0acc8] {
965
+ color: var(--dc-core-primary-color, var(--el-color-primary));
966
+ }
967
+ .dc-form-upload[data-v-5eac98bc] .video-preview-trigger_placeholder {
968
+ width: 100%;
969
+ height: 100%;
970
+ max-width: none;
971
+ border-radius: 0;
972
+ }
973
+ .dc-form-upload-video__thumb_empty[data-v-5eac98bc] {
974
+ background: var(--el-fill-color-light);
975
+ }
597
976
  .table-toolbar[data-v-0220e327] {
598
977
  display: flex;
599
978
  justify-content: space-between;
@@ -692,13 +1071,13 @@ to {
692
1071
  min-height: 60px;
693
1072
  grid-column: 1 / -1;
694
1073
  }
695
- .table-main-pagination[data-v-54ab0e8e] {
1074
+ .table-main-pagination[data-v-6a8d4637] {
696
1075
  margin-top: 10px;
697
1076
  display: flex;
698
1077
  justify-content: flex-end;
699
1078
  }
700
- .table-main_fill[data-v-54ab0e8e] .el-table__body-wrapper {
701
- min-height: var(--v6df3e765);
1079
+ .table-main_fill[data-v-6a8d4637] .el-table__body-wrapper {
1080
+ min-height: var(--ed56f300);
702
1081
  }
703
1082
  .dc-slot-layout-flow-aside_separate[data-v-5c6ef74b] {
704
1083
  position: relative;
@@ -728,40 +1107,40 @@ to {
728
1107
  .dc-slot-layout-flow-aside-main[data-v-5c6ef74b] {
729
1108
  width: var(--v7e1d11ca);
730
1109
  }
731
- .list-layout[data-v-5301293b] {
732
- min-height: var(--ee852864);
1110
+ .list-layout[data-v-8527d1df] {
1111
+ min-height: var(--v3483351c);
733
1112
  }
734
- .list-layout-header[data-v-5301293b] {
1113
+ .list-layout-header[data-v-8527d1df] {
735
1114
  margin-bottom: 10px;
736
1115
  }
737
- .list-layout-operation[data-v-5301293b] {
1116
+ .list-layout-operation[data-v-8527d1df] {
738
1117
  margin-bottom: 10px;
739
1118
  }
740
- .list-layout_search-sticky[data-v-5301293b] .form-search {
1119
+ .list-layout_search-sticky[data-v-8527d1df] .form-search {
741
1120
  position: sticky;
742
- top: var(--v6179ebd9);
1121
+ top: var(--v5ccbcb06);
743
1122
  z-index: 10;
744
1123
  background: var(--dc-core-surface, var(--el-bg-color));
745
1124
  box-shadow: 0 1px 0 0 var(--dc-core-border-color, var(--el-border-color-lighter));
746
1125
  }
747
- .list-layout_toolbar-sticky[data-v-5301293b] .dc-table-main__toolbar {
1126
+ .list-layout_toolbar-sticky[data-v-8527d1df] .dc-table-main__toolbar {
748
1127
  position: sticky;
749
- top: var(--v0e6603c8);
1128
+ top: var(--e69ab810);
750
1129
  z-index: 9;
751
1130
  padding-top: 10px;
752
1131
  background: var(--dc-core-surface, var(--el-bg-color));
753
1132
  box-shadow: 0 1px 0 0 var(--dc-core-border-color, var(--el-border-color-lighter));
754
1133
  }
755
- .list-layout_pager-sticky[data-v-5301293b] .dc-table-main__pagination {
1134
+ .list-layout_pager-sticky[data-v-8527d1df] .dc-table-main__pagination {
756
1135
  position: sticky;
757
- bottom: var(--v6d62e58c);
1136
+ bottom: var(--v5631fb30);
758
1137
  z-index: 9;
759
1138
  margin-top: 0;
760
1139
  padding-top: 10px;
761
1140
  background: var(--dc-core-surface, var(--el-bg-color));
762
1141
  box-shadow: 0 -1px 0 0 var(--dc-core-border-color, var(--el-border-color-lighter));
763
1142
  }
764
- .list-layout[data-v-5301293b] .el-loading-mask {
1143
+ .list-layout[data-v-8527d1df] .el-loading-mask {
765
1144
  left: -10px;
766
1145
  top: -10px;
767
1146
  right: -10px;
@@ -773,15 +1152,15 @@ to {
773
1152
  gap: 8px;
774
1153
  margin-top: 8px;
775
1154
  }
776
- .view-layout[data-v-e6c42f0b] {
1155
+ .view-layout[data-v-773e43bd] {
777
1156
  display: flex;
778
1157
  flex-direction: column;
779
1158
  gap: 8px;
780
1159
  }
781
- .view-layout-toolbar[data-v-e6c42f0b] {
1160
+ .view-layout-toolbar[data-v-773e43bd] {
782
1161
  display: flex;
783
1162
  justify-content: flex-end;
784
1163
  }
785
- .view-layout-content[data-v-e6c42f0b] {
1164
+ .view-layout-content[data-v-773e43bd] {
786
1165
  overflow: auto;
787
1166
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@done-coding/admin-core",
3
- "version": "0.20.1-alpha.0",
3
+ "version": "0.21.1-alpha.0",
4
4
  "description": "内部前端库",
5
5
  "private": false,
6
6
  "main": "es/index.mjs",
@@ -80,5 +80,5 @@
80
80
  "node": ">=18.0.0",
81
81
  "pnpm": ">=9.0.0"
82
82
  },
83
- "gitHead": "fbc8dc3578fa1627664ad5fc9dbf6e4d200d3b0f"
83
+ "gitHead": "ced1823ad04dbe91e2fbb07812f249032034a976"
84
84
  }
@@ -46,6 +46,10 @@ App.vue 总装配——三个必填注入 + 两个必填内容锚即完整可跑
46
46
  | `userStore` | `AppLayoutUserStoreSlice<UserInfo>`(必填) | — | 用户 store 窄化实例(USER_STORE_KEY) |
47
47
  | `watermarkContent` | `WatermarkProps["content"]` | 无默认 | 水印内容;空数组/空串/undefined 则关闭水印 |
48
48
  | `sidebarAboveHeader` | `boolean` | `false` | sidebar z-index 高于 header |
49
+ | `globalModalConfig` | `RegisterEntry[]`(非必需) | 无默认 | 全局弹窗配置数组(shelf 限定 `"app"`)——全局登录 / 配置等通用弹窗的注册入口,直接传给 AppLayout 内部专用 ModalPorter(Symbol 模式,只收 app 级) |
50
+ | `enableGlobalImagePreview` | `boolean` | `false` | 是否开启全局图片预览弹窗:开启后内部给 `globalModalConfig` **拼接**内置配置项 `{ key: APP_GLOBAL_IMAGE_PREVIEW_KEY, component: ModalImagePreview, shelf: "app" }`——消费方零配置拿全局图片预览,**命令式** `globalModalRemote.evoke(APP_GLOBAL_IMAGE_PREVIEW_KEY, { src })` 开图(点击路径不走它——ImagePreviewTrigger/ElImage 原生直达) |
51
+ | `enableGlobalVideoPreview` | `boolean` | `false` | 是否开启全局视频预览弹窗:开启后内部给 `globalModalConfig` **拼接**内置配置项 `{ key: APP_GLOBAL_VIDEO_PREVIEW_KEY, component: ModalVideoPreview, shelf: "app" }`——消费方零配置拿全局视频预览,触发端 `VideoPreviewTrigger` 经遥控器按此 key 唤起 |
52
+ | `v-model:globalModalRemote` | `GlobalModalRemote` | `() => ({})` | 全局弹窗遥控器对象:应用根(App.vue)持有后按 key 遥控全局弹窗(evoke / close / update);AppLayout 透传给内置 app 级 ModalShelf(`v-model:remote`)挂载句柄 |
49
53
 
50
54
  ### Emits
51
55
 
@@ -67,6 +71,50 @@ App.vue 总装配——三个必填注入 + 两个必填内容锚即完整可跑
67
71
 
68
72
 
69
73
 
74
+ ### 全局弹窗遥控器(`globalModalRemote`,应用根范式)
75
+
76
+ **性质**:AppLayout 把全局弹窗的控制面以 `v-model:globalModalRemote` 显式交给应用根(App.vue 持有遥控器)——**app 级弹窗只经这里注册 + 遥控**;全局唯一、与 app 同寿(AppLayout 常驻),不随路由切换销毁。**page 级弹窗不受影响**(页面内 Porter + page 架子,随页面生命周期)——两套入口各管各的层级。
77
+
78
+ **类型**:`GlobalModalRemote = Record<string, GlobalModalControl> & { modalKey: string[] }`——按业务 key 寻址,句柄三件套(`evoke(payload?)` / `close()` / `update(payload)`);**`modalKey` = 已注册全局弹窗 key 清单**(架子 `registerConfig` 同步维护),触发端等调用方用 `modalKey.includes(key)` 显式判断「该 key 是否已注册」(`evoke` 无返回值,未注册直接调会 TypeError);重复 `evoke` 是重新打开还是更新由 `globalModalConfig` 条目配置期 `sameKeyStrategy`(`recreate` / `update`)决定。
79
+
80
+ **应用根消费范式**(App.vue):
81
+
82
+ ```vue
83
+ <script lang="ts" setup>
84
+ import { ref } from "vue";
85
+ import { AppLayout } from "@done-coding/admin-core";
86
+
87
+ /** 全局弹窗配置(shelf 限定 "app")——注册入口 */
88
+ const globalModalConfig = [
89
+ { key: "globalLogin", component: GlobalLoginModal, shelf: "app" },
90
+ ];
91
+ /** 遥控器:App.vue 持有,可随时 evoke / close / update 全局弹窗 */
92
+ const globalModalRemote = ref({});
93
+ </script>
94
+
95
+ <template>
96
+ <AppLayout
97
+ v-model:globalModalRemote="globalModalRemote"
98
+ :global-modal-config="globalModalConfig"
99
+ :bridge="appCoreBridge"
100
+ :appStore="appStore"
101
+ :userStore="userStore"
102
+ >
103
+ <!-- 业务锚槽 -->
104
+ </AppLayout>
105
+ </template>
106
+
107
+ <script lang="ts" setup>
108
+ // 任意位置遥控(经 inject 或直传):
109
+ // globalModalRemote.value.globalLogin?.evoke({ user: "x" }); // 打开
110
+ // globalModalRemote.value.globalLogin?.close(); // 关闭(全局弹窗不能只靠用户点击关闭)
111
+ </script>
112
+ ```
113
+
114
+ **机制链路**:`globalModalConfig`(入)→ AppLayout 内部专用 ModalPorter(`globalOnly` Symbol 模式,只收 app 级)推送 → 内置 app 级 ModalShelf 挂载句柄进 remote(`v-model:remote`,`modalKey` 同步维护)→ 应用根遥控。无 provide——遥控器对象经 v-model 链直传(core 另导出注入 key `GLOBAL_MODAL_REMOTE_KEY` 供触发组件等消费端 inject,App 根 provide 同一对象即可接通)。
115
+
116
+ **全局预览弹窗拼接**:`enableGlobalImagePreview` / `enableGlobalVideoPreview` 开启时,AppLayout 把内置两项**拼进**传给专用 Porter 的配置数组(`[...globalModalConfig, 内置项]`,shelf:"app")——业务 key 与预置 key 平级共处 remote(`modalKey` 均收录)。**命令式入口**(不经过点击):`globalModalRemote.evoke(APP_GLOBAL_*_PREVIEW_KEY, payload)` 即开图/开视频(视频触发端 `VideoPreviewTrigger` 的点击决策链也经 `modalKey.includes` 命中后走此入口;图片触发端点击直达 ElImage 原生预览,不经全局)。关掉开关即整项摘除(`unregisterConfig` 同步清理)。
117
+
70
118
  ## 反模式 / 注意
71
119
 
72
120
  - **别找 AppLayout 的默认 slot**:页面内容由 AppBody(内置 RouterView)渲染,AppLayout 只承接内容锚
@@ -30,7 +30,7 @@
30
30
 
31
31
  ## 能力边界 / 按需使用
32
32
 
33
- - **四向悬浮插槽(`#top`/`#bottom`/`#left`/`#right`):默认全关、常规页面不需要。** 仅当页面需要「悬浮于内容之上的固定补充区」(通栏操作条 / 侧边抽屉 / 浮动提示)才开对应槽——判据:内容必须 fixed 悬浮且不参与文档流(top/bottom 通栏量高 → padding 让位,left/right 量宽)。列表/表单/详情常规页一律不开。
33
+ - **四向悬浮插槽(`#top`/`#bottom`/`#left`/`#right`):默认全关、常规页面不需要。** 仅当页面需要「悬浮于内容之上的固定补充区」(通栏操作条 / 侧边抽屉 / 浮动提示)才开对应槽——判据:内容必须 fixed 悬浮且不参与文档流(top/bottom 通栏量高 → padding 让位,left/right 量宽)。列表/表单/详情常规页一律不开。**`#left`/`#right` 内放列表时用 scope 的 `listLayoutRecommended`(见 API)拿窄栏推荐配置,[MUST NOT] 自行拍脑袋配窄栏列表形态。**
34
34
  - `topBg`/`bottomBg`/`leftBg`/`rightBg`:仅悬浮槽需要着色时设,默认无背景即够用。
35
35
  - `*ObserveResize`:仅当槽内内容有 CSS 过渡折叠 / 异步撑开(不触发重渲染的尺寸变化)才开对应 RO;普通槽内容(v-if/v-show/静态)不开。
36
36
  - `fullMode`:默认 `"min-height"` 即够用;`"height"` 仅当页面内子级依赖硬高撑满(如顶级自撑 TabsMain)时选。
@@ -61,7 +61,42 @@
61
61
  | --- | --- | --- |
62
62
  | `default` | 无 | 页面主体(ModalShelf page 层包裹) |
63
63
  | `#top` / `#bottom` | 无 | 通栏悬浮槽(量高 → padding-top/bottom) |
64
- | `#left` / `#right` | | 侧向悬浮槽(量宽) |
64
+ | `#left` / `#right` | `{ listLayoutRecommended }` | 侧向悬浮槽(量宽)——scope 携带窄栏 ListLayout 推荐配置(见下) |
65
+
66
+ ### `#left` / `#right` scope:`listLayoutRecommended`(窄栏 ListLayout 推荐配置)
67
+
68
+ **性质**:固定内置推荐值(写死、非运行时开关、不做响应式探测),仅经 `#left`/`#right` 插槽 scoped 带出。面向「列表放进 left/right 窄栏」的展示形态推荐;消费者拿到后直接 `v-bind` 展开进 ListLayout,可按需 spread 覆盖(`v-bind="{ ...listLayoutRecommended, customView: false }"`)。
69
+
70
+ **形状**(与 ListLayout props 平铺对齐):
71
+
72
+ | 字段 | 类型 | 固定值 | 语义 |
73
+ | --- | --- | --- | --- |
74
+ | `customView` | `boolean` | `true` | 开启自定义视图(DataListView 卡片形态替代 ElTable——窄栏过窄表格必然崩,卡片更优)。需配套 ListLayout `#custom-view-item` 定义单项 |
75
+ | `tableMainProps.pageLayout` | `string` | `"prev, pager, next"` | 分页器最简形态——去 total/sizes/jumper,仅页码(`« 1 2 3 4 5 »`) |
76
+ | `tableMainProps.paginationBackground` | `boolean` | `false` | 页码不带背景框(透传 ElPagination `background=false` 纯数字链接形态;TableMain 默认 `true` 带框) |
77
+
78
+ **消费示例**(`#left`/`#right` 内放列表):
79
+
80
+ ```vue
81
+ <AppPage>
82
+ <template #left="{ listLayoutRecommended }">
83
+ <ListLayout
84
+ v-bind="listLayoutRecommended"
85
+ :api="leftApi"
86
+ :columns="leftColumns"
87
+ >
88
+ <template #custom-view-item="{ item }">
89
+ <!-- 窄栏卡片单项 -->
90
+ </template>
91
+ </ListLayout>
92
+ </template>
93
+ <template #default>
94
+ <!-- 主内容区 -->
95
+ </template>
96
+ </AppPage>
97
+ ```
98
+
99
+ **类型**:`AppPageListLayoutRecommended`(`app-layout/types.ts` 导出,非泛型——与 ListLayout 泛型 props 无关的平铺子集)。
65
100
 
66
101
  ### Expose
67
102
 
@@ -72,9 +107,12 @@
72
107
  - **悬浮槽尺寸变化来自 CSS 过渡/异步撑开 → 必须开对应 `observeResize`**(onUpdated 只读渲染后瞬时值,过渡动画读起点漏最终)
73
108
  - 四向槽 fixed 定位——内容滚动时悬浮不动,属设计语义,勿误当普通 inline 槽
74
109
  - 槽尺寸/inset 几何由 `app-page-geometry` 纯函数计算导出,[MUST NOT] 手写自造
110
+ - `listLayoutRecommended` 开 `customView` 后 [MUST] 配套 ListLayout `#custom-view-item`,否则窄栏卡片渲染为空
111
+ - `listLayoutRecommended` 是 AppPage → ListLayout 的**定向耦合**(AppPage 持有 ListLayout prop 形状子集),属本能力设计使然;若 ListLayout 该子集发生 breaking,[MUST] 同步更新 `app-layout/types.ts` 与本 README
75
112
 
76
113
  ## 关联
77
114
 
78
115
  - 几何纯函数:`app-page-geometry.ts`(computeAppPageReducedViewportHeight/Width、computeAppPageContentInset、computeAppPageSlotStyles、computeAppPageSlotShimStyles + `APP_PAGE_SLOT_Z_INDEX`=1)
79
116
  - 高度链:AppBody provide 的 `BODY_CONTENT_VIEWPORT_HEIGHT` / `BODY_CONTENT_VIEWPORT_RECT` / `BODY_CONTENT_VIEWPORT_INSET` / `SCOPE_VIEWPORT_MAX_HEIGHT`
80
117
  - 范式页:`apps/reference/src/pages/app-layout/page-slots/`(含 ChainReadout 高度链互动面板)
118
+ - 窄栏列表范式:`apps/reference/src/pages/app-layout/narrow-list/`(#left/#right 放 ListLayout + `listLayoutRecommended`,与裸用对照)