@done-coding/admin-core 0.22.2 → 0.23.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 (30) hide show
  1. package/es/components/data-view/DataGridView.vue.mjs +7 -0
  2. package/es/components/data-view/DataGridView.vue2.mjs +448 -0
  3. package/es/components/data-view/DataListView.vue.mjs +1 -1
  4. package/es/components/data-view/DataListView.vue2.mjs +6 -62
  5. package/es/components/data-view/InfiniteListView.vue.mjs +7 -0
  6. package/es/components/data-view/InfiniteListView.vue2.mjs +205 -0
  7. package/es/components/data-view/use-data-view-field-map.mjs +70 -0
  8. package/es/components/data-view/use-pull-refresh.mjs +38 -0
  9. package/es/components/data-view/utils.mjs +21 -1
  10. package/es/components/list-layout/ListLayout.vue.mjs +1 -1
  11. package/es/components/list-layout/ListLayout.vue2.mjs +48 -8
  12. package/es/index.mjs +92 -82
  13. package/es/style.css +199 -97
  14. package/package.json +5 -2
  15. package/src/components/data-view/README.md +34 -8
  16. package/src/components/data-view/docs/README-DataGridView.md +139 -0
  17. package/src/components/data-view/docs/README-InfiniteListView.md +105 -0
  18. package/types/components/data-view/DataGridView.vue.d.ts +40 -0
  19. package/types/components/data-view/DataListView.vue.d.ts +1 -2
  20. package/types/components/data-view/InfiniteListView.vue.d.ts +30 -0
  21. package/types/components/data-view/index.d.ts +9 -3
  22. package/types/components/data-view/types.d.ts +125 -1
  23. package/types/components/data-view/use-data-view-field-map.d.ts +24 -0
  24. package/types/components/data-view/use-pull-refresh.d.ts +20 -0
  25. package/types/components/data-view/utils.d.ts +13 -1
  26. package/types/components/list-layout/ListLayout.vue.d.ts +4 -0
  27. package/types/components/list-layout/types.d.ts +16 -0
  28. package/types/components/table/index.d.ts +11 -1
  29. package/types/index.d.ts +2 -0
  30. package/types/injectInfo.json.d.ts +1 -1
package/es/index.mjs CHANGED
@@ -23,57 +23,62 @@ import { default as default24 } from "./components/panel/PanelItemNestPanel.vue.
23
23
  import { default as default25 } from "./components/misc/SelectModule.vue.mjs";
24
24
  import { default as default26 } from "./components/display/ShadowClone.vue.mjs";
25
25
  import { default as default27 } from "./components/slot-layout/SlotLayoutTemplate.vue.mjs";
26
- import { default as default28 } from "./components/display/TabsMain.vue.mjs";
27
- import { default as default29 } from "./components/misc/TriggerAutoImport.vue.mjs";
28
- import { default as default30 } from "./components/display/WatchSize.vue.mjs";
26
+ import { default as default28 } from "./components/table/TableEmpty.vue.mjs";
27
+ import { default as default29 } from "./components/display/TabsMain.vue.mjs";
28
+ import { default as default30 } from "./components/misc/TriggerAutoImport.vue.mjs";
29
+ import { default as default31 } from "./components/display/WatchSize.vue.mjs";
29
30
  import { APP_API_LIST_MODEL_KEY_CONFIG } from "./config/list-model.mjs";
30
31
  import { APP_GLOBAL_IMAGE_PREVIEW_KEY, APP_GLOBAL_VIDEO_PREVIEW_KEY, GLOBAL_MODAL_REMOTE_KEY } from "./components/modal/modal-global-keys.mjs";
31
32
  import { APP_LAYOUT_APP_STORE_KEY, APP_LAYOUT_BRIDGE_KEY, APP_LAYOUT_USER_STORE_KEY, APP_PAGE_CONTENT_INSET, BODY_CONTENT_VIEWPORT_HEIGHT, BODY_CONTENT_VIEWPORT_INSET, BODY_CONTENT_VIEWPORT_RECT, CORE_BRIDGE_KEY, FORM_NEST_REGISTRY_KEY, NEST_LAYOUT_SCALE_KEY, SCOPE_VIEWPORT_MAX_HEIGHT, TABS_MAIN_VISUAL_LEVEL, getModalShelfInjectionKey } from "./inject/key.mjs";
32
33
  import { APP_PAGE_SLOT_Z_INDEX, computeAppPageContentInset, computeAppPageReducedViewportHeight, computeAppPageReducedViewportWidth, computeAppPageSlotShimStyles, computeAppPageSlotStyles } from "./components/app-layout/app-page-geometry.mjs";
33
- import { default as default31 } from "./components/display/ActionConfirm.vue.mjs";
34
- import { default as default32 } from "./components/app-layout/AppAside.vue.mjs";
35
- import { default as default33 } from "./components/app-layout/AppBody.vue.mjs";
36
- import { default as default34 } from "./components/app-layout/AppBreadcrumb.vue.mjs";
37
- import { default as default35 } from "./components/app-layout/AppFooter.vue.mjs";
38
- import { default as default36 } from "./components/app-layout/AppHeader.vue.mjs";
39
- import { default as default37 } from "./components/app-layout/AppLayout.vue.mjs";
40
- import { default as default38 } from "./components/app-layout/AppPage.vue.mjs";
41
- import { default as default39 } from "./components/app-layout/AppSidebar.vue.mjs";
42
- import { default as default40 } from "./components/app-layout/AppTheme.vue.mjs";
43
- import { default as default41 } from "./components/misc/AutoRefresh.vue.mjs";
44
- import { default as default42 } from "./components/misc/AutoRefreshGroup.vue.mjs";
34
+ import { default as default32 } from "./components/display/ActionConfirm.vue.mjs";
35
+ import { default as default33 } from "./components/app-layout/AppAside.vue.mjs";
36
+ import { default as default34 } from "./components/app-layout/AppBody.vue.mjs";
37
+ import { default as default35 } from "./components/app-layout/AppBreadcrumb.vue.mjs";
38
+ import { default as default36 } from "./components/app-layout/AppFooter.vue.mjs";
39
+ import { default as default37 } from "./components/app-layout/AppHeader.vue.mjs";
40
+ import { default as default38 } from "./components/app-layout/AppLayout.vue.mjs";
41
+ import { default as default39 } from "./components/app-layout/AppPage.vue.mjs";
42
+ import { default as default40 } from "./components/app-layout/AppSidebar.vue.mjs";
43
+ import { default as default41 } from "./components/app-layout/AppTheme.vue.mjs";
44
+ import { default as default42 } from "./components/misc/AutoRefresh.vue.mjs";
45
+ import { default as default43 } from "./components/misc/AutoRefreshGroup.vue.mjs";
45
46
  import { CORE_VIEWPORT_DECOR_ZINDEX_ABOVE, CORE_VIEWPORT_DECOR_ZINDEX_BELOW } from "./components/app-layout/viewport.mjs";
46
- import { default as default43, default as default44 } from "./components/modal/ModalConfirm.vue.mjs";
47
+ import { default as default44, default as default45 } from "./components/modal/ModalConfirm.vue.mjs";
47
48
  import { DC_SLOT_ATTR, SlotRegion, parseSlotRegion } from "./config/slot-region.mjs";
49
+ import { default as default46 } from "./components/data-view/DataGridView.vue.mjs";
48
50
  import { EXPORT_MAX_LIMIT, OPERATE_COLUMN_PROP, exportCSV, pickExportColumns } from "./utils/export.mjs";
49
51
  import { FORM_CONFIG_SELECT_ALL_VALUE, getConfirmPasswordRule, passwordRule, setFormComponentType } from "./helpers/form.mjs";
50
52
  import { FORM_ITEM_CHANGE_LOADING, NEST_LAYOUT_TIERS, ceilToTier, generateFormData, getBlurSubmit, getChangeSubmit, getDatePickerShortcuts, getEnterSubmit, getPlaceholder, getVModelSugar, parseFormData, resolveFormLayout, resolveLayoutSpan, setInputComponent, setSelectComponent, stringifyFormData, swiftFormItemConfig } from "./components/form/utils.mjs";
51
- import { default as default45 } from "./components/form/FormActiveFilter.vue.mjs";
52
- import { default as default46 } from "./components/form/FormItemNestForm.vue.mjs";
53
- import { default as default47 } from "./components/form/FormItemNestFormList.vue.mjs";
54
- import { default as default48 } from "./components/form/FormMain.vue.mjs";
55
- import { default as default49 } from "./components/form/FormSearch.vue.mjs";
56
- import { default as default50 } from "./components/form/FormShadowCloneDispatch.vue.mjs";
57
- import { default as default51 } from "./components/form/FormSortSwitch.vue.mjs";
58
- import { default as default52 } from "./components/form/FormSortSwitchGroup.vue.mjs";
59
- import { default as default53 } from "./components/form/FormSubmitPanel.vue.mjs";
60
- import { default as default54 } from "./components/form/FormUpload.vue.mjs";
61
- import { default as default55 } from "./components/form/FormUploadAudio.vue.mjs";
62
- import { default as default56 } from "./components/form/FormUploadImage.vue.mjs";
63
- import { default as default57 } from "./components/form/FormUploadVideo.vue.mjs";
64
- import { default as default58 } from "./components/form/FormVerifyImage.vue.mjs";
65
- import { default as default59, default as default60 } from "./components/list-layout/ListLayout.vue.mjs";
66
- import { default as default61 } from "./components/modal/ModalVideoPreview.vue.mjs";
67
- import { default as default62 } from "./components/panel/PanelEditSwitch.vue.mjs";
68
- import { default as default63 } from "./components/panel/PanelItem.vue.mjs";
69
- import { default as default64 } from "./components/panel/PanelItemNestForm.vue.mjs";
70
- import { default as default65 } from "./components/panel/PanelMain.vue.mjs";
53
+ import { default as default47 } from "./components/form/FormActiveFilter.vue.mjs";
54
+ import { default as default48 } from "./components/form/FormItemNestForm.vue.mjs";
55
+ import { default as default49 } from "./components/form/FormItemNestFormList.vue.mjs";
56
+ import { default as default50 } from "./components/form/FormMain.vue.mjs";
57
+ import { default as default51 } from "./components/form/FormSearch.vue.mjs";
58
+ import { default as default52 } from "./components/form/FormShadowCloneDispatch.vue.mjs";
59
+ import { default as default53 } from "./components/form/FormSortSwitch.vue.mjs";
60
+ import { default as default54 } from "./components/form/FormSortSwitchGroup.vue.mjs";
61
+ import { default as default55 } from "./components/form/FormSubmitPanel.vue.mjs";
62
+ import { default as default56 } from "./components/form/FormUpload.vue.mjs";
63
+ import { default as default57 } from "./components/form/FormUploadAudio.vue.mjs";
64
+ import { default as default58 } from "./components/form/FormUploadImage.vue.mjs";
65
+ import { default as default59 } from "./components/form/FormUploadVideo.vue.mjs";
66
+ import { default as default60 } from "./components/form/FormVerifyImage.vue.mjs";
67
+ import { default as default61 } from "./components/data-view/InfiniteListView.vue.mjs";
68
+ import { default as default62, default as default63 } from "./components/list-layout/ListLayout.vue.mjs";
69
+ import { default as default64 } from "./components/modal/ModalVideoPreview.vue.mjs";
70
+ import { default as default65 } from "./components/panel/PanelEditSwitch.vue.mjs";
71
+ import { default as default66 } from "./components/panel/PanelItem.vue.mjs";
72
+ import { default as default67 } from "./components/panel/PanelItemNestForm.vue.mjs";
73
+ import { default as default68 } from "./components/panel/PanelMain.vue.mjs";
71
74
  import { ROUTE_MODULE_LEVEL, TabsMainReplaceQueryKey } from "./config/route.mjs";
72
- import { default as default66 } from "./components/slot-layout/SlotLayoutFlowAside.vue.mjs";
75
+ import { default as default69 } from "./components/slot-layout/SlotLayoutFlowAside.vue.mjs";
73
76
  import { TABLE_COLUMN_KEY_OPERATE, TABLE_COLUMN_KEY_SELECTION } from "./components/table/constants.mjs";
74
- import { default as default67 } from "./components/table/TableMain.vue.mjs";
75
- import { default as default68 } from "./components/modal/VideoPreviewTrigger.vue.mjs";
76
- import { default as default69 } from "./components/view-layout/ViewLayout.vue.mjs";
77
+ import { default as default70 } from "./components/table/TableMain.vue.mjs";
78
+ import { default as default71 } from "./components/table/TableSkeleton.vue.mjs";
79
+ import { default as default72 } from "./components/table/TableToolbar.vue.mjs";
80
+ import { default as default73 } from "./components/modal/VideoPreviewTrigger.vue.mjs";
81
+ import { default as default74 } from "./components/view-layout/ViewLayout.vue.mjs";
77
82
  import { buildRhythmCss, useCoreThemeApply } from "./hooks/use-theme-apply.mjs";
78
83
  import { checkLogin } from "./router/guard/login.mjs";
79
84
  import { checkPermission } from "./router/guard/permission.mjs";
@@ -119,18 +124,18 @@ export {
119
124
  APP_PAGE_SLOT_Z_INDEX,
120
125
  default2 as ActionBtn,
121
126
  default3 as ActionBtnGroup,
122
- default31 as ActionConfirm,
123
- default32 as AppAside,
124
- default33 as AppBody,
125
- default34 as AppBreadcrumb,
126
- default35 as AppFooter,
127
- default36 as AppHeader,
128
- default37 as AppLayout,
129
- default38 as AppPage,
130
- default39 as AppSidebar,
131
- default40 as AppTheme,
132
- default41 as AutoRefresh,
133
- default42 as AutoRefreshGroup,
127
+ default32 as ActionConfirm,
128
+ default33 as AppAside,
129
+ default34 as AppBody,
130
+ default35 as AppBreadcrumb,
131
+ default36 as AppFooter,
132
+ default37 as AppHeader,
133
+ default38 as AppLayout,
134
+ default39 as AppPage,
135
+ default40 as AppSidebar,
136
+ default41 as AppTheme,
137
+ default42 as AutoRefresh,
138
+ default43 as AutoRefreshGroup,
134
139
  BODY_CONTENT_VIEWPORT_HEIGHT,
135
140
  BODY_CONTENT_VIEWPORT_INSET,
136
141
  BODY_CONTENT_VIEWPORT_RECT,
@@ -138,75 +143,80 @@ export {
138
143
  CORE_BRIDGE_KEY,
139
144
  CORE_VIEWPORT_DECOR_ZINDEX_ABOVE,
140
145
  CORE_VIEWPORT_DECOR_ZINDEX_BELOW,
141
- default43 as ConfirmModal,
146
+ default44 as ConfirmModal,
142
147
  DC_SLOT_ATTR,
148
+ default46 as DataGridView,
143
149
  default5 as DetailModal,
144
150
  EXPORT_MAX_LIMIT,
145
151
  FORM_CONFIG_SELECT_ALL_VALUE,
146
152
  FORM_ITEM_CHANGE_LOADING,
147
153
  FORM_NEST_REGISTRY_KEY,
148
- default45 as FormActiveFilter,
154
+ default47 as FormActiveFilter,
149
155
  default7 as FormInput,
150
156
  default8 as FormInputShadowClone,
151
- default46 as FormItemNestForm,
152
- default47 as FormItemNestFormList,
153
- default48 as FormMain,
157
+ default48 as FormItemNestForm,
158
+ default49 as FormItemNestFormList,
159
+ default50 as FormMain,
154
160
  default9 as FormModal,
155
161
  default11 as FormRadioGroup,
156
- default49 as FormSearch,
162
+ default51 as FormSearch,
157
163
  default12 as FormSelect,
158
164
  default13 as FormSelectShadowClone,
159
- default50 as FormShadowCloneDispatch,
160
- default51 as FormSortSwitch,
161
- default52 as FormSortSwitchGroup,
165
+ default52 as FormShadowCloneDispatch,
166
+ default53 as FormSortSwitch,
167
+ default54 as FormSortSwitchGroup,
162
168
  default14 as FormSubmitBtn,
163
- default53 as FormSubmitPanel,
169
+ default55 as FormSubmitPanel,
164
170
  default15 as FormTree,
165
- default54 as FormUpload,
166
- default55 as FormUploadAudio,
167
- default56 as FormUploadImage,
168
- default57 as FormUploadVideo,
171
+ default56 as FormUpload,
172
+ default57 as FormUploadAudio,
173
+ default58 as FormUploadImage,
174
+ default59 as FormUploadVideo,
169
175
  default16 as FormVerifyCode,
170
- default58 as FormVerifyImage,
176
+ default60 as FormVerifyImage,
171
177
  GLOBAL_MODAL_REMOTE_KEY,
172
178
  default17 as HeightProvider,
173
179
  default18 as ImagePreviewTrigger,
174
- default59 as ListLayout,
175
- default60 as ListPage,
180
+ default61 as InfiniteListView,
181
+ default62 as ListLayout,
182
+ default63 as ListPage,
176
183
  default19 as MenuItemSub,
177
184
  default20 as MenuTree,
178
- default44 as ModalConfirm,
185
+ default45 as ModalConfirm,
179
186
  default6 as ModalDetail,
180
187
  default10 as ModalForm,
181
188
  default21 as ModalImagePreview,
182
189
  default22 as ModalPorter,
183
190
  default23 as ModalShelf,
184
- default61 as ModalVideoPreview,
191
+ default64 as ModalVideoPreview,
185
192
  NEST_LAYOUT_SCALE_KEY,
186
193
  NEST_LAYOUT_TIERS,
187
194
  OPERATE_COLUMN_PROP,
188
- default62 as PanelEditSwitch,
189
- default63 as PanelItem,
190
- default64 as PanelItemNestForm,
195
+ default65 as PanelEditSwitch,
196
+ default66 as PanelItem,
197
+ default67 as PanelItemNestForm,
191
198
  default24 as PanelItemNestPanel,
192
- default65 as PanelMain,
199
+ default68 as PanelMain,
193
200
  ROUTE_MODULE_LEVEL,
194
201
  SCOPE_VIEWPORT_MAX_HEIGHT,
195
202
  default25 as SelectModule,
196
203
  default26 as ShadowClone,
197
- default66 as SlotLayoutFlowAside,
204
+ default69 as SlotLayoutFlowAside,
198
205
  default27 as SlotLayoutTemplate,
199
206
  SlotRegion,
200
207
  TABLE_COLUMN_KEY_OPERATE,
201
208
  TABLE_COLUMN_KEY_SELECTION,
202
209
  TABS_MAIN_VISUAL_LEVEL,
203
- default67 as TableMain,
204
- default28 as TabsMain,
210
+ default28 as TableEmpty,
211
+ default70 as TableMain,
212
+ default71 as TableSkeleton,
213
+ default72 as TableToolbar,
214
+ default29 as TabsMain,
205
215
  TabsMainReplaceQueryKey,
206
- default29 as TriggerAutoImport,
207
- default68 as VideoPreviewTrigger,
208
- default69 as ViewLayout,
209
- default30 as WatchSize,
216
+ default30 as TriggerAutoImport,
217
+ default73 as VideoPreviewTrigger,
218
+ default74 as ViewLayout,
219
+ default31 as WatchSize,
210
220
  buildRhythmCss,
211
221
  ceilToTier,
212
222
  checkLogin,
package/es/style.css CHANGED
@@ -641,6 +641,192 @@ to {
641
641
  transform: rotate(360deg);
642
642
  }
643
643
  }
644
+ .table-toolbar[data-v-0220e327] {
645
+ display: flex;
646
+ justify-content: space-between;
647
+ align-items: center;
648
+ padding-bottom: 8px;
649
+ gap: 20px;
650
+ }
651
+ .table-toolbar-left[data-v-0220e327] {
652
+ display: flex;
653
+ align-items: center;
654
+ gap: 10px;
655
+ }
656
+ .table-toolbar-right[data-v-0220e327] {
657
+ display: flex;
658
+ align-items: center;
659
+ gap: 10px;
660
+ }
661
+ .table-toolbar-switch-view[data-v-0220e327] {
662
+ --el-switch-off-color: var(--dc-core-primary-color);
663
+ --el-switch-on-color: var(--dc-core-warning-color);
664
+ }
665
+ .table-skeleton[data-v-c813d7d1] {
666
+ border: 1px solid var(--dc-core-border-color, var(--el-border-color-lighter));
667
+ border-radius: var(--dc-core-radius, var(--el-border-radius-base));
668
+ overflow: hidden;
669
+ }
670
+ .table-skeleton__row[data-v-c813d7d1] {
671
+ display: flex;
672
+ align-items: center;
673
+ gap: 16px;
674
+ padding: 13px 12px;
675
+ border-bottom: 1px solid var(--el-fill-color, var(--el-border-color-lighter));
676
+ }
677
+ .table-skeleton__row_head[data-v-c813d7d1] {
678
+ background: var(--el-fill-color, var(--el-fill-color-light));
679
+ }
680
+ .table-skeleton__row_head .table-skeleton__bar[data-v-c813d7d1] {
681
+ height: 10px;
682
+ }
683
+ .table-skeleton__row[data-v-c813d7d1]:last-child {
684
+ border-bottom: none;
685
+ }
686
+ .table-skeleton__cell[data-v-c813d7d1] {
687
+ flex: 1;
688
+ min-width: 0;
689
+ }
690
+ .table-skeleton__bar[data-v-c813d7d1] {
691
+ height: 12px;
692
+ border-radius: 4px;
693
+ }
694
+ .table-skeleton__cell:nth-child(3n + 1) .table-skeleton__bar[data-v-c813d7d1] {
695
+ width: 52%;
696
+ }
697
+ .table-skeleton__cell:nth-child(3n + 2) .table-skeleton__bar[data-v-c813d7d1] {
698
+ width: 82%;
699
+ }
700
+ .table-skeleton__cell:nth-child(3n) .table-skeleton__bar[data-v-c813d7d1] {
701
+ width: 38%;
702
+ }
703
+ .table-skeleton__grid[data-v-c813d7d1] {
704
+ display: grid;
705
+ grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
706
+ gap: 12px;
707
+ padding: 12px;
708
+ }
709
+ .table-skeleton__card[data-v-c813d7d1] {
710
+ min-width: 0;
711
+ display: flex;
712
+ flex-direction: column;
713
+ gap: 10px;
714
+ padding: 14px;
715
+ border: 1px solid var(--el-border-color-lighter);
716
+ border-radius: var(--dc-core-radius, var(--el-border-radius-base));
717
+ }
718
+ .table-skeleton__card-media[data-v-c813d7d1] {
719
+ width: 100%;
720
+ aspect-ratio: 16 / 9;
721
+ border-radius: var(--dc-core-radius, var(--el-border-radius-base));
722
+ }
723
+ @media (prefers-reduced-motion: reduce) {
724
+ .table-skeleton[data-v-c813d7d1] .el-skeleton.is-animated .el-skeleton__item {
725
+ animation: none;
726
+ }
727
+ }
728
+ .infinite-list-view[data-v-e597453f] {
729
+ width: 100%;
730
+ }
731
+ .infinite-list-view__viewport[data-v-e597453f] {
732
+ width: 100%;
733
+ }
734
+ .infinite-list-view__sentinel[data-v-e597453f] {
735
+ height: 1px;
736
+ }
737
+ .infinite-list-view__footer[data-v-e597453f] {
738
+ display: flex;
739
+ justify-content: center;
740
+ align-items: center;
741
+ padding: 8px 0;
742
+ color: var(--dc-core-text-color-secondary, var(--el-text-color-secondary));
743
+ font-size: 13px;
744
+ }
745
+ .infinite-list-view__json[data-v-e597453f] {
746
+ margin: 0;
747
+ font-size: 12px;
748
+ white-space: pre-wrap;
749
+ word-break: break-all;
750
+ color: var(--dc-core-text-color-secondary, var(--el-text-color-secondary));
751
+ }
752
+ .infinite-list-view__tip[data-v-e597453f] {
753
+ color: var(--dc-core-text-color-secondary, var(--el-text-color-secondary));
754
+ }
755
+ .infinite-list-view__retry[data-v-e597453f] {
756
+ border: none;
757
+ background: transparent;
758
+ color: var(--dc-core-primary-color, var(--el-color-primary));
759
+ font-size: 13px;
760
+ cursor: pointer;
761
+ padding: 0;
762
+ }
763
+ .infinite-list-view__retry[data-v-e597453f]:hover {
764
+ opacity: 0.8;
765
+ }
766
+ .infinite-list-view__empty[data-v-e597453f] {
767
+ display: flex;
768
+ justify-content: center;
769
+ align-items: center;
770
+ width: 100%;
771
+ min-height: 60px;
772
+ color: var(--dc-core-text-color-secondary, var(--el-text-color-secondary));
773
+ }
774
+ .infinite-list-view__pull-indicator[data-v-e597453f] {
775
+ display: flex;
776
+ justify-content: center;
777
+ align-items: flex-end;
778
+ overflow: hidden;
779
+ font-size: 13px;
780
+ color: var(--dc-core-text-color-secondary, var(--el-text-color-secondary));
781
+ transition: height 0.2s;
782
+ }
783
+ .infinite-list-view__pull-indicator > span[data-v-e597453f] {
784
+ padding-bottom: 6px;
785
+ }
786
+ .data-grid-view[data-v-d9e5439d] {
787
+ width: 100%;
788
+ }
789
+ .data-grid-view__grid[data-v-d9e5439d] {
790
+ display: grid;
791
+ gap: 12px;
792
+ padding-bottom: 12px;
793
+ }
794
+ .data-grid-view__cell[data-v-d9e5439d] {
795
+ min-width: 0;
796
+ }
797
+ .data-grid-view__card[data-v-d9e5439d] {
798
+ border: 1px solid var(--dc-core-border-color, var(--el-border-color-lighter));
799
+ border-radius: var(--dc-core-radius, 4px);
800
+ padding: 10px 12px;
801
+ height: 100%;
802
+ box-sizing: border-box;
803
+ overflow: hidden;
804
+ }
805
+ .data-grid-view__field[data-v-d9e5439d] {
806
+ display: flex;
807
+ gap: 6px;
808
+ align-items: baseline;
809
+ line-height: 1.6;
810
+ font-size: 13px;
811
+ }
812
+ .data-grid-view__field-label[data-v-d9e5439d] {
813
+ flex-shrink: 0;
814
+ color: var(--dc-core-text-color-secondary, var(--el-text-color-secondary));
815
+ }
816
+ .data-grid-view__field-value[data-v-d9e5439d] {
817
+ overflow: hidden;
818
+ text-overflow: ellipsis;
819
+ white-space: nowrap;
820
+ }
821
+ .data-grid-view__empty-error[data-v-d9e5439d] {
822
+ display: flex;
823
+ justify-content: center;
824
+ align-items: center;
825
+ gap: 8px;
826
+ padding: 20px 0;
827
+ color: var(--dc-core-text-color-secondary, var(--el-text-color-secondary));
828
+ font-size: 13px;
829
+ }
644
830
  .form-active-filter[data-v-6d2d37c2] {
645
831
  display: flex;
646
832
  flex-wrap: wrap;
@@ -988,97 +1174,13 @@ to {
988
1174
  .dc-form-upload-video__thumb_empty[data-v-5eac98bc] {
989
1175
  background: var(--el-fill-color-light);
990
1176
  }
991
- .table-toolbar[data-v-0220e327] {
992
- display: flex;
993
- justify-content: space-between;
994
- align-items: center;
995
- padding-bottom: 8px;
996
- gap: 20px;
997
- }
998
- .table-toolbar-left[data-v-0220e327] {
999
- display: flex;
1000
- align-items: center;
1001
- gap: 10px;
1002
- }
1003
- .table-toolbar-right[data-v-0220e327] {
1004
- display: flex;
1005
- align-items: center;
1006
- gap: 10px;
1007
- }
1008
- .table-toolbar-switch-view[data-v-0220e327] {
1009
- --el-switch-off-color: var(--dc-core-primary-color);
1010
- --el-switch-on-color: var(--dc-core-warning-color);
1011
- }
1012
- .table-skeleton[data-v-c813d7d1] {
1013
- border: 1px solid var(--dc-core-border-color, var(--el-border-color-lighter));
1014
- border-radius: var(--dc-core-radius, var(--el-border-radius-base));
1015
- overflow: hidden;
1016
- }
1017
- .table-skeleton__row[data-v-c813d7d1] {
1018
- display: flex;
1019
- align-items: center;
1020
- gap: 16px;
1021
- padding: 13px 12px;
1022
- border-bottom: 1px solid var(--el-fill-color, var(--el-border-color-lighter));
1023
- }
1024
- .table-skeleton__row_head[data-v-c813d7d1] {
1025
- background: var(--el-fill-color, var(--el-fill-color-light));
1026
- }
1027
- .table-skeleton__row_head .table-skeleton__bar[data-v-c813d7d1] {
1028
- height: 10px;
1029
- }
1030
- .table-skeleton__row[data-v-c813d7d1]:last-child {
1031
- border-bottom: none;
1032
- }
1033
- .table-skeleton__cell[data-v-c813d7d1] {
1034
- flex: 1;
1035
- min-width: 0;
1036
- }
1037
- .table-skeleton__bar[data-v-c813d7d1] {
1038
- height: 12px;
1039
- border-radius: 4px;
1040
- }
1041
- .table-skeleton__cell:nth-child(3n + 1) .table-skeleton__bar[data-v-c813d7d1] {
1042
- width: 52%;
1043
- }
1044
- .table-skeleton__cell:nth-child(3n + 2) .table-skeleton__bar[data-v-c813d7d1] {
1045
- width: 82%;
1046
- }
1047
- .table-skeleton__cell:nth-child(3n) .table-skeleton__bar[data-v-c813d7d1] {
1048
- width: 38%;
1049
- }
1050
- .table-skeleton__grid[data-v-c813d7d1] {
1051
- display: grid;
1052
- grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
1053
- gap: 12px;
1054
- padding: 12px;
1055
- }
1056
- .table-skeleton__card[data-v-c813d7d1] {
1057
- min-width: 0;
1058
- display: flex;
1059
- flex-direction: column;
1060
- gap: 10px;
1061
- padding: 14px;
1062
- border: 1px solid var(--el-border-color-lighter);
1063
- border-radius: var(--dc-core-radius, var(--el-border-radius-base));
1064
- }
1065
- .table-skeleton__card-media[data-v-c813d7d1] {
1066
- width: 100%;
1067
- aspect-ratio: 16 / 9;
1068
- border-radius: var(--dc-core-radius, var(--el-border-radius-base));
1069
- }
1070
- @media (prefers-reduced-motion: reduce) {
1071
- .table-skeleton[data-v-c813d7d1] .el-skeleton.is-animated .el-skeleton__item {
1072
- animation: none;
1073
- }
1074
- }
1075
1177
  .data-list-view-item.is-selected[data-v-d9b5d5ca] {
1076
1178
  /* 选中态钩子,具体视觉由消费方覆写 */
1077
1179
  }
1078
- .data-list-view[data-v-da082546] {
1180
+ .data-list-view[data-v-ce0bb05b] {
1079
1181
  width: 100%;
1080
1182
  }
1081
- .data-list-view-empty[data-v-da082546] {
1183
+ .data-list-view-empty[data-v-ce0bb05b] {
1082
1184
  display: flex;
1083
1185
  justify-content: center;
1084
1186
  align-items: center;
@@ -1122,40 +1224,40 @@ to {
1122
1224
  .dc-slot-layout-flow-aside-main[data-v-5c6ef74b] {
1123
1225
  width: var(--v7e1d11ca);
1124
1226
  }
1125
- .list-layout[data-v-ce5a651b] {
1126
- min-height: var(--bbc8b4b6);
1227
+ .list-layout[data-v-a47ec619] {
1228
+ min-height: var(--v37fdcdf2);
1127
1229
  }
1128
- .list-layout-header[data-v-ce5a651b] {
1230
+ .list-layout-header[data-v-a47ec619] {
1129
1231
  margin-bottom: 10px;
1130
1232
  }
1131
- .list-layout-operation[data-v-ce5a651b] {
1233
+ .list-layout-operation[data-v-a47ec619] {
1132
1234
  margin-bottom: 10px;
1133
1235
  }
1134
- .list-layout_search-sticky[data-v-ce5a651b] .form-search {
1236
+ .list-layout_search-sticky[data-v-a47ec619] .form-search {
1135
1237
  position: sticky;
1136
- top: var(--v2ce52870);
1238
+ top: var(--v5bcb0a52);
1137
1239
  z-index: 10;
1138
1240
  background: var(--dc-core-surface, var(--el-bg-color));
1139
1241
  box-shadow: 0 1px 0 0 var(--dc-core-border-color, var(--el-border-color-lighter));
1140
1242
  }
1141
- .list-layout_toolbar-sticky[data-v-ce5a651b] .dc-table-main__toolbar {
1243
+ .list-layout_toolbar-sticky[data-v-a47ec619] .dc-table-main__toolbar {
1142
1244
  position: sticky;
1143
- top: var(--ca6d5736);
1245
+ top: var(--v489faec3);
1144
1246
  z-index: 9;
1145
1247
  padding-top: 10px;
1146
1248
  background: var(--dc-core-surface, var(--el-bg-color));
1147
1249
  box-shadow: 0 1px 0 0 var(--dc-core-border-color, var(--el-border-color-lighter));
1148
1250
  }
1149
- .list-layout_pager-sticky[data-v-ce5a651b] .dc-table-main__pagination {
1251
+ .list-layout_pager-sticky[data-v-a47ec619] .dc-table-main__pagination {
1150
1252
  position: sticky;
1151
- bottom: var(--v0af15863);
1253
+ bottom: var(--v17e649c5);
1152
1254
  z-index: 9;
1153
1255
  margin-top: 0;
1154
1256
  padding-top: 10px;
1155
1257
  background: var(--dc-core-surface, var(--el-bg-color));
1156
1258
  box-shadow: 0 -1px 0 0 var(--dc-core-border-color, var(--el-border-color-lighter));
1157
1259
  }
1158
- .list-layout[data-v-ce5a651b] .el-loading-mask {
1260
+ .list-layout[data-v-a47ec619] .el-loading-mask {
1159
1261
  left: -10px;
1160
1262
  top: -10px;
1161
1263
  right: -10px;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@done-coding/admin-core",
3
- "version": "0.22.2",
3
+ "version": "0.23.0",
4
4
  "description": "内部前端库",
5
5
  "private": false,
6
6
  "main": "es/index.mjs",
@@ -80,5 +80,8 @@
80
80
  "node": ">=18.0.0",
81
81
  "pnpm": ">=9.0.0"
82
82
  },
83
- "gitHead": "e23d3f11214fc43bc0a6e1149ebe56e014a89d8e"
83
+ "dependencies": {
84
+ "@tanstack/vue-virtual": "^3.13.35"
85
+ },
86
+ "gitHead": "345849870494584a62144db4e7bc983d49ed38fa"
84
87
  }
@@ -1,19 +1,45 @@
1
1
  # data-view 数据视图族
2
2
 
3
3
  > `DataListView` / `DataListViewItem`:table 的内部衍生品——**仅供 TableMain 内部 import,[MUST NOT] 对外导出 / 全局注册 / 提供 install 插件**(不进 core 顶层 export)。
4
- > 对外入口:经 `TableMain` `customView` 模式消费(范式页 `apps/reference/src/pages/data-view/custom-view/`)。
4
+ > `InfiniteListView` / `DataGridView`:**转正对外组件**——进 core 顶层 export(数据视图族的公共底座与网格容器)。
5
+ > 对外入口:`DataListView` 经 `TableMain` 的 `customView` 模式消费(范式页 `apps/reference/src/pages/data-view/custom-view/`);`DataGridView` 经 `ListLayout` 的 `viewMode="grid"` 或独立使用(范式页 `apps/reference/src/pages/data-view/grid/`)。
5
6
 
6
7
  ## 组件清单
7
8
 
8
- | 组件 | 一句话 | 文档 |
9
- | --- | --- | --- |
10
- | `DataListView` | 数据视图列表(卡片/自定义渲染,el-table 形态替代),TableMain `customView` 模式渲染载体 | [README-DataListView](./docs/README-DataListView.md) |
11
- | `DataListViewItem` | 列表项容器:仅承载选中态 class 钩子(`.is-selected`)+ 项内容插槽 | 并入 README-DataListView 小节 |
9
+ | 组件 | 一句话 | 对外 | 文档 |
10
+ | --- | --- | --- | --- |
11
+ | `InfiniteListView` | 通用无限滚动容器(受控:存量数据 + 加载状态 + IO 哨兵触发 load-more + 底部错误/到底 + 虚拟列表),**通用原语建议独立使用** | ✅ 顶层 export | [README-InfiniteListView](./docs/README-InfiniteListView.md) |
12
+ | `DataGridView` | 网格数据容器(对齐 TableMain props,自持存量累加状态机,内部复 InfiniteListView + TableToolbar),ListLayout `viewMode="grid"` 渲染载体 | 顶层 export | [README-DataGridView](./docs/README-DataGridView.md) |
13
+ | `DataListView` | 数据视图列表(卡片/自定义渲染,el-table 形态替代),TableMain `customView` 模式渲染载体 | ❌ 内部衍生品 | [README-DataListView](./docs/README-DataListView.md) |
14
+ | `DataListViewItem` | 列表项容器:仅承载选中态 class 钩子(`.is-selected`)+ 项内容插槽 | ❌ 内部 | 并入 README-DataListView 小节 |
12
15
 
13
- 族 index.ts 导出 `{ DataListView, DataListViewItem }` + `export * from "./types"`(5 个类型,含 `DataViewColumn<T>` / `DataListViewItemScope<T>`)。
16
+ 族 index.ts 导出:`InfiniteListView` / `DataGridView` / `DataListView` / `DataListViewItem` + `export * from "./types"`(含 `DataViewColumn<T>` / `DataListViewItemScope<T>` / `InfiniteListViewProps` / `DataGridViewProps`)。
14
17
 
15
18
  ## 内部件边界
16
19
 
17
- - **不进 core 顶层 export**:core 顶层 `index.ts` data-view 导出行;两组件 [MUST NOT] 对外导出 / 全局注册 / 提供 install 插件
18
- - **消费入口**:走 `TableMain` `customView` prop + `#custom-view-item` 插槽(TableMain `customView.value ? markRaw(DataListView) : markRaw(ElTable)` 择一渲染;ListLayout 已转发该插槽,类型 `DataListViewItemScope<T>`)
20
+ - **`DataListView` / `DataListViewItem` 不进 core 顶层 export**:[MUST NOT] 对外导出 / 全局注册 / 提供 install 插件
21
+ - **`InfiniteListView` / `DataGridView` core 顶层 export**:公共组件(规则 10 配套 demo;`DataGridView` 推荐经 `ListLayout` 门面使用,独立使用需自配数据/工具栏上下文,成本与 TableMain 独立使用相同)
22
+ - **消费入口**:
23
+ - `DataListView`:走 `TableMain` `customView` prop + `#custom-view-item` 插槽(TableMain `customView.value ? markRaw(DataListView) : markRaw(ElTable)` 择一渲染;ListLayout 已转发该插槽,类型 `DataListViewItemScope<T>`)
24
+ - `DataGridView`:走 `ListLayout` `viewMode="grid"`(`viewMode="table"` 时 ListLayout 渲染 TableMain,内部 `customView` 仍切 ElTable/DataListView——切换在 ListLayout 层,两容器数据路径不同构故不共存于 TableMain 内)
19
25
  - **DataListViewItem**:由 DataListView 内部 `v-for` 使用,消费方不直接使用;[MUST NOT] 写死视觉样式(卡片阴影/圆角归消费方)、[MUST NOT] 内置选中状态机
26
+
27
+ ## 分层(A 底座 / B 容器)
28
+
29
+ ```
30
+ data-view 族
31
+ ├── InfiniteListView (A · 通用受控无限滚动容器,公共)
32
+ │ ├─ IO 哨兵触发 load-more(root 限滚容器,零环境适配)
33
+ │ ├─ 状态机展示:loading / loadingMore / error(底部原因+手动重试) / finished(到底)
34
+ │ ├─ 虚拟列表:@tanstack/vue-virtual 单轴虚拟化
35
+ │ └─ opt-in 触摸下拉刷新(pullRefresh,默认关)
36
+ └── DataGridView (B · 网格数据容器,公共)
37
+ ├─ 对齐 TableMain 主 props,自持存量累加状态机(api + query + fetchNextPage + hasMore)
38
+ ├─ 内部按 gridColumns 把存量 chunk 成行 → 喂 InfiniteListView 虚拟化
39
+ ├─ 复用 TableToolbar(存量上下文:currentPage = 已拉最大页)
40
+ ├─ 列配置驱动卡片渲染(useDataViewFieldMap 同源;custom-view-item 插槽默认 label: value 卡片)
41
+ └─ 无分页器;loading/错误重试/到底由 InfiniteListView 提供
42
+ ```
43
+
44
+ - **共享 hook**:`useDataViewFieldMap`(列 → 稳定字段组件)供 `DataListView` 与 `DataGridView` 同源渲染(渲染层防双线漂移)。
45
+ - **防漂移三层**(spec 2026-08-09-105416):契约面 TS 类型复用(`TableMainInstance`/`TablePageInfo`/`TableExportContext`)+ 参数构造面 config 共享(`APP_API_LIST_MODEL_KEY_CONFIG`)+ 行为面契约测试网(`runContainerContractTests` 对 TableMain + DataGridView 跑同一套断言)。