@done-coding/admin-core 0.17.1-alpha.0 → 0.18.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.
- package/README.md +77 -1
- package/es/_virtual/_plugin-vue_export-helper.mjs +7 -6
- package/es/bridge/config-hook.mjs +49 -37
- package/es/bridge/index.mjs +152 -109
- package/es/bridge/layout.mjs +45 -31
- package/es/bridge/plugin.mjs +22 -12
- package/es/bridge/route.mjs +59 -50
- package/es/bridge/state.mjs +54 -39
- package/es/bridge/storage.mjs +18 -8
- package/es/bridge/theme/index.mjs +200 -97
- package/es/bridge/theme/persist.mjs +11 -7
- package/es/bridge/theme/system-dark.mjs +13 -6
- package/es/components/app-layout/AppAside.vue.mjs +4 -4
- package/es/components/app-layout/AppAside.vue2.mjs +37 -30
- package/es/components/app-layout/AppBody.vue.mjs +4 -4
- package/es/components/app-layout/AppBody.vue2.mjs +97 -60
- package/es/components/app-layout/AppBreadcrumb.vue.mjs +4 -4
- package/es/components/app-layout/AppBreadcrumb.vue2.mjs +59 -38
- package/es/components/app-layout/AppCollapseToggle.vue.mjs +4 -4
- package/es/components/app-layout/AppCollapseToggle.vue2.mjs +51 -42
- package/es/components/app-layout/AppFooter.vue.mjs +4 -4
- package/es/components/app-layout/AppFooter.vue2.mjs +15 -12
- package/es/components/app-layout/AppHeader.vue.mjs +4 -4
- package/es/components/app-layout/AppHeader.vue2.mjs +81 -58
- package/es/components/app-layout/AppLayout.vue.mjs +4 -4
- package/es/components/app-layout/AppLayout.vue2.mjs +148 -112
- package/es/components/app-layout/AppPage.vue.mjs +4 -4
- package/es/components/app-layout/AppPage.vue2.mjs +254 -197
- package/es/components/app-layout/AppShell.vue.mjs +44 -42
- package/es/components/app-layout/AppShell.vue2.mjs +2 -2
- package/es/components/app-layout/AppSidebar.vue.mjs +4 -4
- package/es/components/app-layout/AppSidebar.vue2.mjs +76 -59
- package/es/components/app-layout/AppTheme.vue.mjs +4 -4
- package/es/components/app-layout/AppTheme.vue2.mjs +69 -57
- package/es/components/app-layout/app-page-geometry.mjs +44 -42
- package/es/components/app-layout/keep-alive.mjs +27 -19
- package/es/components/app-layout/viewport.mjs +4 -3
- package/es/components/data-view/DataListView.vue.mjs +4 -4
- package/es/components/data-view/DataListView.vue2.mjs +133 -93
- package/es/components/data-view/DataListViewItem.vue.mjs +4 -4
- package/es/components/data-view/DataListViewItem.vue2.mjs +11 -9
- package/es/components/data-view/utils.mjs +36 -34
- package/es/components/display/ActionBtn.vue.mjs +94 -71
- package/es/components/display/ActionBtn.vue2.mjs +2 -2
- package/es/components/display/ActionBtnGroup.vue.mjs +54 -48
- package/es/components/display/ActionBtnGroup.vue2.mjs +2 -2
- package/es/components/display/ActionConfirm.vue.mjs +4 -4
- package/es/components/display/ActionConfirm.vue2.mjs +116 -92
- package/es/components/display/BooleanTag.vue.mjs +24 -18
- package/es/components/display/BooleanTag.vue2.mjs +2 -2
- package/es/components/display/HeightProvider.vue.mjs +37 -27
- package/es/components/display/HeightProvider.vue2.mjs +2 -2
- package/es/components/display/TabsHeader.vue.mjs +4 -4
- package/es/components/display/TabsHeader.vue2.mjs +86 -57
- package/es/components/display/TabsMain.vue.mjs +156 -125
- package/es/components/display/TabsMain.vue2.mjs +2 -2
- package/es/components/display/TabsNaturalFlow.vue.mjs +15 -11
- package/es/components/display/TabsNaturalFlow.vue2.mjs +2 -2
- package/es/components/display/TabsRefineFlow.vue.mjs +55 -42
- package/es/components/display/TabsRefineFlow.vue2.mjs +2 -2
- package/es/components/display/TabsTile.vue.mjs +4 -4
- package/es/components/display/TabsTile.vue2.mjs +204 -146
- package/es/components/display/WatchSize.vue.mjs +50 -30
- package/es/components/display/WatchSize.vue2.mjs +2 -2
- package/es/components/display/use-tabs-query-sync.mjs +21 -17
- package/es/components/form/FormItem.vue.mjs +4 -4
- package/es/components/form/FormItem.vue2.mjs +183 -121
- package/es/components/form/FormItemNestForm.vue.mjs +4 -4
- package/es/components/form/FormItemNestForm.vue2.mjs +38 -34
- package/es/components/form/FormItemNestFormList.vue.mjs +4 -4
- package/es/components/form/FormItemNestFormList.vue2.mjs +135 -106
- package/es/components/form/FormMain.vue.mjs +4 -4
- package/es/components/form/FormMain.vue2.mjs +226 -139
- package/es/components/form/FormRadioGroup.vue.mjs +67 -52
- package/es/components/form/FormRadioGroup.vue2.mjs +2 -2
- package/es/components/form/FormSearch.vue.mjs +4 -4
- package/es/components/form/FormSearch.vue2.mjs +194 -156
- package/es/components/form/FormSelect.vue.mjs +69 -42
- package/es/components/form/FormSelect.vue2.mjs +2 -2
- package/es/components/form/FormSubmitBtn.vue.mjs +30 -25
- package/es/components/form/FormSubmitBtn.vue2.mjs +2 -2
- package/es/components/form/FormSubmitPanel.vue.mjs +4 -4
- package/es/components/form/FormSubmitPanel.vue2.mjs +129 -96
- package/es/components/form/FormTree.vue.mjs +19 -16
- package/es/components/form/FormTree.vue2.mjs +2 -2
- package/es/components/form/FormVerifyCode.vue.mjs +58 -41
- package/es/components/form/FormVerifyCode.vue2.mjs +2 -2
- package/es/components/form/FormVerifyImage.vue.mjs +4 -4
- package/es/components/form/FormVerifyImage.vue2.mjs +62 -40
- package/es/components/form/form-search-utils.mjs +83 -52
- package/es/components/form/nest-form-item-list.mjs +63 -55
- package/es/components/form/nest-form-item.mjs +30 -30
- package/es/components/form/nest-registry.mjs +4 -4
- package/es/components/form/use-form-submit.mjs +18 -15
- package/es/components/form/use-layout-by-container.mjs +23 -15
- package/es/components/form/use-nest-form-list.mjs +19 -16
- package/es/components/form/use-nest-form.mjs +37 -28
- package/es/components/form/use-nest-layout-scale.mjs +11 -10
- package/es/components/form/utils.mjs +233 -145
- package/es/components/list-page/ListPage.vue.mjs +4 -4
- package/es/components/list-page/ListPage.vue2.mjs +313 -207
- package/es/components/list-page/use-sticky.mjs +45 -33
- package/es/components/menu/MenuItemSub.vue.mjs +47 -43
- package/es/components/menu/MenuItemSub.vue2.mjs +2 -2
- package/es/components/menu/MenuTree.vue.mjs +84 -61
- package/es/components/menu/MenuTree.vue2.mjs +2 -2
- package/es/components/misc/AutoRefresh.vue.mjs +4 -4
- package/es/components/misc/AutoRefresh.vue2.mjs +78 -53
- package/es/components/misc/AutoRefreshGroup.vue.mjs +4 -4
- package/es/components/misc/AutoRefreshGroup.vue2.mjs +54 -51
- package/es/components/misc/SelectModule.vue.mjs +54 -45
- package/es/components/misc/SelectModule.vue2.mjs +2 -2
- package/es/components/misc/TriggerAutoImport.vue.mjs +7 -5
- package/es/components/misc/TriggerAutoImport.vue2.mjs +2 -2
- package/es/components/modal/ModalConfirm.vue.mjs +4 -4
- package/es/components/modal/ModalConfirm.vue2.mjs +160 -125
- package/es/components/modal/ModalDetail.vue.mjs +50 -39
- package/es/components/modal/ModalDetail.vue2.mjs +2 -2
- package/es/components/modal/ModalForm.vue.mjs +63 -52
- package/es/components/modal/ModalForm.vue2.mjs +2 -2
- package/es/components/modal/ModalPorter.vue.mjs +51 -36
- package/es/components/modal/ModalPorter.vue2.mjs +2 -2
- package/es/components/modal/ModalShelf.vue.mjs +38 -28
- package/es/components/modal/ModalShelf.vue2.mjs +2 -2
- package/es/components/modal/modal-shelf-core.mjs +52 -36
- package/es/components/modal/modal-shelf-hierarchy.mjs +11 -9
- package/es/components/panel/PanelEditSwitch.vue.mjs +4 -4
- package/es/components/panel/PanelEditSwitch.vue2.mjs +88 -66
- package/es/components/panel/PanelItem.vue.mjs +4 -4
- package/es/components/panel/PanelItem.vue2.mjs +103 -77
- package/es/components/panel/PanelItemNestForm.vue.mjs +4 -4
- package/es/components/panel/PanelItemNestForm.vue2.mjs +61 -52
- package/es/components/panel/PanelItemNestPanel.vue.mjs +22 -20
- package/es/components/panel/PanelItemNestPanel.vue2.mjs +2 -2
- package/es/components/panel/PanelMain.vue.mjs +4 -4
- package/es/components/panel/PanelMain.vue2.mjs +92 -74
- package/es/components/panel/nest-panel-form.mjs +44 -38
- package/es/components/panel/nest-panel-item.mjs +18 -17
- package/es/components/slot-layout/SlotLayoutFlowAside.vue.mjs +4 -4
- package/es/components/slot-layout/SlotLayoutFlowAside.vue2.mjs +55 -42
- package/es/components/slot-layout/SlotLayoutTemplate.vue.mjs +11 -9
- package/es/components/slot-layout/SlotLayoutTemplate.vue2.mjs +2 -2
- package/es/components/table/TableMain.vue.mjs +4 -4
- package/es/components/table/TableMain.vue2.mjs +378 -275
- package/es/components/table/TableSkeleton.vue.mjs +4 -4
- package/es/components/table/TableSkeleton.vue2.mjs +95 -74
- package/es/components/table/TableToolbar.vue.mjs +4 -4
- package/es/components/table/TableToolbar.vue2.mjs +170 -154
- package/es/components/table/ToolbarButtons.vue.mjs +12 -10
- package/es/components/table/ToolbarButtons.vue2.mjs +2 -2
- package/es/components/table/constants.mjs +4 -3
- package/es/components/table/use-fill-height.mjs +12 -10
- package/es/components/table/use-table-skeleton.mjs +19 -15
- package/es/config/list-model.mjs +2 -2
- package/es/config/route.mjs +4 -3
- package/es/helpers/form.mjs +35 -25
- package/es/helpers/list-helper.mjs +59 -44
- package/es/hooks/activated.mjs +49 -33
- package/es/hooks/feel-size.mjs +39 -23
- package/es/hooks/menus-dispatch.mjs +68 -35
- package/es/hooks/timeout.mjs +29 -14
- package/es/hooks/use-breakpoint.mjs +35 -23
- package/es/hooks/use-channel-viewport-height.mjs +30 -20
- package/es/hooks/use-custom-breakpoint.mjs +48 -31
- package/es/hooks/use-observe-size.mjs +37 -20
- package/es/hooks/use-theme-apply.mjs +175 -124
- package/es/hooks/use-viewport-apply.mjs +39 -27
- package/es/index.mjs +239 -239
- package/es/inject/key.mjs +52 -41
- package/es/injectInfo.json.mjs +2 -2
- package/es/router/group-redirect.mjs +22 -16
- package/es/router/guard/index.mjs +26 -21
- package/es/router/guard/login.mjs +4 -2
- package/es/router/guard/permission.mjs +4 -2
- package/es/store/app.mjs +163 -123
- package/es/store/router-permission.mjs +75 -46
- package/es/store/user.mjs +100 -71
- package/es/style.css +769 -1
- package/es/utils/dom.mjs +20 -16
- package/es/utils/export.mjs +34 -18
- package/es/utils/id.mjs +5 -3
- package/es/utils/router.mjs +21 -14
- package/es/utils/theme-scale.mjs +50 -35
- package/es/utils/time.mjs +20 -14
- package/package.json +4 -3
- package/src/bridge/README.md +5 -0
- package/src/bridge/docs/README.md +72 -0
- package/src/components/README.md +84 -0
- package/src/components/app-layout/README.md +46 -0
- package/src/components/app-layout/docs/README-AppAside.md +69 -0
- package/src/components/app-layout/docs/README-AppBody.md +81 -0
- package/src/components/app-layout/docs/README-AppBreadcrumb.md +71 -0
- package/src/components/app-layout/docs/README-AppFooter.md +41 -0
- package/src/components/app-layout/docs/README-AppHeader.md +73 -0
- package/src/components/app-layout/docs/README-AppLayout.md +83 -0
- package/src/components/app-layout/docs/README-AppPage.md +80 -0
- package/src/components/app-layout/docs/README-AppSidebar.md +70 -0
- package/src/components/app-layout/docs/README-AppTheme.md +66 -0
- package/src/components/data-view/README.md +19 -0
- package/src/components/data-view/docs/README-DataListView.md +114 -0
- package/src/components/display/README.md +23 -0
- package/src/components/display/docs/README-ActionBtn.md +84 -0
- package/src/components/display/docs/README-ActionBtnGroup.md +96 -0
- package/src/components/display/docs/README-ActionConfirm.md +77 -0
- package/src/components/display/docs/README-BooleanTag.md +76 -0
- package/src/components/display/docs/README-HeightProvider.md +74 -0
- package/src/components/display/docs/README-TabsMain.md +99 -0
- package/src/components/display/docs/README-WatchSize.md +70 -0
- package/src/components/form/README.md +24 -0
- package/src/components/form/docs/README-FormItemNestForm.md +86 -0
- package/src/components/form/docs/README-FormItemNestFormList.md +93 -0
- package/src/components/form/docs/README-FormMain.md +101 -0
- package/src/components/form/docs/README-FormSearch.md +89 -0
- package/src/components/form/docs/README-FormSubmitBtn.md +72 -0
- package/src/components/form/docs/README-FormSubmitPanel.md +97 -0
- package/src/components/list-page/README.md +16 -0
- package/src/components/list-page/docs/README-ListPage.md +136 -0
- package/src/components/menu/README.md +19 -0
- package/src/components/menu/docs/README-MenuItemSub.md +53 -0
- package/src/components/menu/docs/README-MenuTree.md +76 -0
- package/src/components/misc/README.md +21 -0
- package/src/components/misc/docs/README-AutoRefresh.md +74 -0
- package/src/components/misc/docs/README-AutoRefreshGroup.md +74 -0
- package/src/components/misc/docs/README-SelectModule.md +72 -0
- package/src/components/modal/README.md +21 -0
- package/src/components/modal/docs/README-ModalConfirm.md +105 -0
- package/src/components/modal/docs/README-ModalDetail.md +103 -0
- package/src/components/modal/docs/README-ModalForm.md +97 -0
- package/src/components/modal/docs/README-ModalPorter.md +92 -0
- package/src/components/modal/docs/README-ModalShelf.md +115 -0
- package/src/components/panel/README.md +19 -0
- package/src/components/panel/docs/README-PanelMain.md +149 -0
- package/src/components/slot-layout/README.md +17 -0
- package/src/components/slot-layout/docs/README-SlotLayoutFlowAside.md +83 -0
- package/src/components/slot-layout/docs/README-SlotLayoutTemplate.md +73 -0
- package/src/components/table/README.md +17 -0
- package/src/components/table/docs/README-TableMain.md +140 -0
- package/src/hooks/README.md +5 -0
- package/src/hooks/docs/README.md +49 -0
- package/types/bridge/config-hook.d.ts +68 -0
- package/types/bridge/index.d.ts +411 -0
- package/types/bridge/layout.d.ts +40 -0
- package/types/bridge/plugin.d.ts +18 -0
- package/types/bridge/route.d.ts +20 -1
- package/types/bridge/state.d.ts +14 -0
- package/types/bridge/storage.d.ts +9 -0
- package/types/bridge/theme/index.d.ts +7 -0
- package/types/bridge/theme/persist.d.ts +12 -0
- package/types/bridge/theme/system-dark.d.ts +12 -0
- package/types/bridge/theme/types.d.ts +238 -0
- package/types/components/app-layout/AppAside.vue.d.ts +1 -0
- package/types/components/app-layout/AppCollapseToggle.vue.d.ts +3 -0
- package/types/components/app-layout/AppHeader.vue.d.ts +3 -0
- package/types/components/app-layout/AppLayout.vue.d.ts +12 -0
- package/types/components/app-layout/AppPage.vue.d.ts +17 -0
- package/types/components/app-layout/AppSidebar.vue.d.ts +2 -0
- package/types/components/app-layout/app-page-geometry.d.ts +48 -0
- package/types/components/app-layout/keep-alive.d.ts +17 -0
- package/types/components/app-layout/types.d.ts +125 -0
- package/types/components/app-layout/viewport.d.ts +28 -0
- package/types/components/data-view/DataListViewItem.vue.d.ts +8 -0
- package/types/components/data-view/index.d.ts +4 -0
- package/types/components/data-view/types.d.ts +42 -0
- package/types/components/data-view/utils.d.ts +3 -0
- package/types/components/display/TabsHeader.vue.d.ts +2 -0
- package/types/components/display/TabsMain.vue.d.ts +2 -0
- package/types/components/display/TabsRefineFlow.vue.d.ts +1 -0
- package/types/components/display/TabsTile.vue.d.ts +247 -12
- package/types/components/display/WatchSize.vue.d.ts +9 -0
- package/types/components/display/index.d.ts +37 -1
- package/types/components/display/types.d.ts +163 -0
- package/types/components/display/use-tabs-query-sync.d.ts +29 -0
- package/types/components/form/FormItemNestForm.vue.d.ts +5 -0
- package/types/components/form/FormItemNestFormList.vue.d.ts +17 -0
- package/types/components/form/FormVerifyCode.vue.d.ts +9 -0
- package/types/components/form/FormVerifyImage.vue.d.ts +1 -0
- package/types/components/form/form-search-utils.d.ts +34 -0
- package/types/components/form/nest-form-item-list.d.ts +28 -0
- package/types/components/form/nest-form-item.d.ts +21 -0
- package/types/components/form/nest-registry.d.ts +14 -0
- package/types/components/form/types.d.ts +208 -8
- package/types/components/form/use-form-submit.d.ts +13 -0
- package/types/components/form/use-layout-by-container.d.ts +23 -0
- package/types/components/form/use-nest-form-list.d.ts +13 -0
- package/types/components/form/use-nest-form.d.ts +15 -0
- package/types/components/form/use-nest-layout-scale.d.ts +12 -0
- package/types/components/form/utils.d.ts +56 -1
- package/types/components/list-page/ListPage.vue.d.ts +6 -0
- package/types/components/list-page/types.d.ts +50 -2
- package/types/components/list-page/use-sticky.d.ts +23 -0
- package/types/components/misc/index.d.ts +6 -1
- package/types/components/misc/types.d.ts +7 -0
- package/types/components/modal/ModalConfirm.vue.d.ts +29 -0
- package/types/components/modal/index.d.ts +7 -1
- package/types/components/modal/modal-shelf-core.d.ts +3 -0
- package/types/components/modal/modal-shelf-hierarchy.d.ts +4 -0
- package/types/components/modal/modal-shelf-types.d.ts +34 -0
- package/types/components/modal/types.d.ts +63 -2
- package/types/components/panel/PanelItemNestForm.vue.d.ts +6 -0
- package/types/components/panel/PanelItemNestPanel.vue.d.ts +5 -0
- package/types/components/panel/nest-panel-form.d.ts +21 -0
- package/types/components/panel/nest-panel-item.d.ts +14 -0
- package/types/components/panel/types.d.ts +52 -1
- package/types/components/slot-layout/SlotLayoutTemplate.vue.d.ts +21 -0
- package/types/components/slot-layout/types.d.ts +4 -0
- package/types/components/table/constants.d.ts +8 -0
- package/types/components/table/types.d.ts +140 -9
- package/types/components/table/use-fill-height.d.ts +14 -0
- package/types/components/table/use-table-skeleton.d.ts +16 -0
- package/types/config/list-model.d.ts +29 -0
- package/types/config/route.d.ts +2 -0
- package/types/helpers/form.d.ts +5 -0
- package/types/helpers/list-helper.d.ts +26 -0
- package/types/helpers/types.d.ts +11 -0
- package/types/hooks/activated.d.ts +23 -0
- package/types/hooks/feel-size.d.ts +2 -0
- package/types/hooks/menus-dispatch.d.ts +4 -0
- package/types/hooks/timeout.d.ts +4 -0
- package/types/hooks/use-channel-viewport-height.d.ts +8 -0
- package/types/hooks/use-custom-breakpoint.d.ts +19 -0
- package/types/hooks/use-observe-size.d.ts +29 -0
- package/types/hooks/use-theme-apply.d.ts +23 -0
- package/types/hooks/use-viewport-apply.d.ts +12 -0
- package/types/inject/key.d.ts +163 -0
- package/types/injectInfo.json.d.ts +1 -1
- package/types/router/group-redirect.d.ts +9 -0
- package/types/router/guard/index.d.ts +13 -0
- package/types/router/guard/login.d.ts +1 -0
- package/types/router/guard/permission.d.ts +1 -0
- package/types/router/guard/types.d.ts +3 -0
- package/types/store/app.d.ts +27 -0
- package/types/store/router-permission.d.ts +53 -0
- package/types/store/user.d.ts +24 -0
- package/types/types/dot-path.d.ts +8 -0
- package/types/types/route.d.ts +45 -0
- package/types/types/utility-types.d.ts +7 -0
- package/types/utils/dom.d.ts +22 -0
- package/types/utils/export.d.ts +16 -1
- package/types/utils/id.d.ts +1 -0
- package/types/utils/router.d.ts +2 -0
- package/types/utils/theme-scale.d.ts +31 -0
- package/types/utils/time.d.ts +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# modal 弹窗族
|
|
2
|
+
|
|
3
|
+
弹窗三原语 + 架子体系:命令式开窗走 `ModalShelf`(层级治理)+ `ModalPorter`(evoke),`ModalShelfMap` declare merge 全链类型化。
|
|
4
|
+
|
|
5
|
+
## 组件文档(docs/)
|
|
6
|
+
|
|
7
|
+
- [ModalConfirm](./docs/README-ModalConfirm.md) — 确认弹窗/抽屉原语(onXxx props 契约)
|
|
8
|
+
- [ModalForm](./docs/README-ModalForm.md) — 弹窗 + 表单 + 校验提交
|
|
9
|
+
- [ModalDetail](./docs/README-ModalDetail.md) — CRUD 预设薄壳(add / edit / read)
|
|
10
|
+
- [ModalShelf](./docs/README-ModalShelf.md) — 弹窗架子(level: app/page/custom + 层级断言)
|
|
11
|
+
- [ModalPorter](./docs/README-ModalPorter.md) — 弹窗搬运(modalList 注册表 + evoke + 卸载自动清理)
|
|
12
|
+
|
|
13
|
+
## 关键类型与机制
|
|
14
|
+
|
|
15
|
+
- 类型:`ModalLevel` / `ModalSameKeyStrategy` / `ModalShelfMap` / `ModalInjectedProps` / `EvokeHandle` / `RegisterEntry` / `ShelfController`(经 `./types` + `./modal-shelf-types` 导出)
|
|
16
|
+
- ⚠️ deprecated 兼容别名:`ConfirmModal` / `FormModal` / `DetailModal`(指向新名,后续大版本移除)——**新代码 [MUST NOT] 用旧名**,仅存量迁移期过渡(readme API 表与范式页均用新名)
|
|
17
|
+
- 内置挂载:AppLayout 内置 `level="app"`、AppPage 内置 `level="page"`(业务 [MUST NOT] 自声明)
|
|
18
|
+
|
|
19
|
+
## 范式页(apps/reference)
|
|
20
|
+
|
|
21
|
+
- `/modal/guide`(对接内置 page 架子)/ `/modal/porter/showcase`(三层自定义架子 + 5 场景)/ `/modal/confirm/showcase`(modal/drawer 双形态)/ `/modal/form-modal/showcase`(独立原语用法)
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# ModalConfirm(配置化确认弹窗 / 抽屉)
|
|
2
|
+
|
|
3
|
+
> 确认型弹层原语:modal / drawer 双形态一键切换,确认/取消走 Promise 契约(返回 false 不关、resolve 关)。
|
|
4
|
+
> 范式页:`apps/reference/src/pages/modal/confirm/showcase/`(双形态 + $attrs 透传实证)
|
|
5
|
+
|
|
6
|
+
## 定位
|
|
7
|
+
|
|
8
|
+
- **何时用**:操作确认、轻量表单提交、任意「弹窗/抽屉外壳 + 自定义内容」场景
|
|
9
|
+
- **何时不用**:复杂表单提交用 `ModalForm`;完整 CRUD 用 `ModalDetail`;「架子 + 注册表」命令式弹窗体系用 `ModalShelf` + `ModalPorter`
|
|
10
|
+
- 关键机制:`onClose`/`onCancel`/`onConfirm` 是 **props 不是 emits**(onXxx props 约定),确认/取消回调返回 `Promise<boolean|void>` 时——返回 `false` 不关闭、reject 不关闭、resolve 关闭
|
|
11
|
+
- `inheritAttrs: false` + 全量 `v-bind $attrs` 透传底层 ElDialog/ElDrawer:未声明 EP prop(如 `draggable` / `destroy-on-close`)直达底层
|
|
12
|
+
|
|
13
|
+
## 快速上手(最小可用)
|
|
14
|
+
|
|
15
|
+
常规确认弹窗零配置——默认 modal 形态 + 宽 420 + 自动关窗:
|
|
16
|
+
|
|
17
|
+
```vue
|
|
18
|
+
<ModalConfirm
|
|
19
|
+
v-model:show="show"
|
|
20
|
+
title="操作确认"
|
|
21
|
+
:on-confirm="onConfirm" <!-- 异步 → 自动 loading 转圈,resolve 关窗 -->
|
|
22
|
+
/>
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
**要点**:
|
|
26
|
+
|
|
27
|
+
- `show` 必传(`v-model:show`);关闭路径:点确认/取消/遮罩/ESC/右上角关闭 → 统一收敛到 `onClose(status)`,`status=true` 表示因确认关闭
|
|
28
|
+
- 提交类确认让 `onConfirm` 返回 Promise 并配 `use-loading`:等待期按钮自动转圈,reject 不关窗(错误留在原地展示)、resolve 关窗
|
|
29
|
+
|
|
30
|
+
## 能力边界 / 按需使用
|
|
31
|
+
|
|
32
|
+
- **默认即够用:modal 居中 + 宽 420 + 确认/取消自动关窗**——绝大多数确认弹窗只传 `show`/`title`/`onConfirm`。
|
|
33
|
+
- `layerType="drawer"`:仅当确认内容需要抽屉形态(侧滑、大尺寸自绘内容)时开;drawer 下 `width` 语义变为抽屉尺寸(size),`direction` 控制开合方向(仅 drawer 生效)。
|
|
34
|
+
- `modalReserve`:默认 `200`(弹层可用高 = innerHeight − 200)即够用;仅当弹层内嵌表格/表单需要更高可用视口时调小(联动 TableMain 高度链)。
|
|
35
|
+
- `use-loading`:仅当 `onConfirm` 返回 Promise 时配;同步确认无需。
|
|
36
|
+
- `headerDivider`/`footerDivider`:默认随形态(drawer=true / modal=false);仅需显式覆盖时传。
|
|
37
|
+
- `#footer` 自绘操作区:仅当默认底部按钮不满足(需要自绘布局/额外内容)时用,scoped 提供 `{cancelHandler, confirmHandler, loading}`。
|
|
38
|
+
- **完整能力演示**(双形态切换 + 异步确认 + 分割线 + $attrs 透传):`apps/reference/src/pages/modal/confirm/showcase/`——能力展示,非推荐默认。
|
|
39
|
+
|
|
40
|
+
## API
|
|
41
|
+
> ⚠️ API 以 types.ts 与组件源码为真相源;与文档冲突时以源码为准。
|
|
42
|
+
|
|
43
|
+
### Props(内联 defineProps,无 types.ts)
|
|
44
|
+
|
|
45
|
+
| name | type | 默认 | 语义 |
|
|
46
|
+
| --- | --- | --- | --- |
|
|
47
|
+
| `show` | `boolean`(必传) | — | 可见性(v-model:show) |
|
|
48
|
+
| `showClose` | `boolean` | `true` | 右上角关闭按钮 |
|
|
49
|
+
| `onClose` | `(status?: boolean) => void` | — | 关闭回调,status = 是否因确认关闭 |
|
|
50
|
+
| `onCancel` | `() => void \| Promise<boolean\|void>` | — | 取消回调;返回 false 则不关闭 |
|
|
51
|
+
| `onConfirm` | `() => void \| Promise<boolean\|void>` | — | 确认回调;返回 false 不关闭、reject 不关闭,resolve 关闭并传 status=true |
|
|
52
|
+
| `title` | `string \| (() => VNode\|VNode[])` | — | 标题 |
|
|
53
|
+
| `content` | `string \| (() => VNode)` | — | 正文 |
|
|
54
|
+
| `cancelText` | `string \| (() => VNode)` | `"取消"` | 取消按钮文案 |
|
|
55
|
+
| `confirmText` | `string \| (() => VNode)` | `"确定"` | 确认按钮文案 |
|
|
56
|
+
| `hiddenCancel` | `boolean` | `false` | 隐藏取消按钮 |
|
|
57
|
+
| `width` | `number \| string` | `420` | modal = 弹窗宽度 / drawer = 抽屉尺寸(size) |
|
|
58
|
+
| `reverse` | `boolean` | `false` | 反转按钮位置 |
|
|
59
|
+
| `closeOnPressEscape` | `boolean` | `true` | ESC 关闭 |
|
|
60
|
+
| `closeOnClickModal` | `boolean` | `true` | 点击遮罩关闭 |
|
|
61
|
+
| `useLoading` | `boolean` | — | 确认按钮 loading(onConfirm 返回 Promise 时转圈) |
|
|
62
|
+
| `type` | `ButtonProps["type"]` | `"primary"` | 确认按钮 type |
|
|
63
|
+
| `layerType` | `"modal" \| "drawer"` | `"modal"` | modal = ElDialog 居中弹窗 / drawer = ElDrawer |
|
|
64
|
+
| `direction` | `"rtl"\|"ltr"\|"ttb"\|"btt"` | `"rtl"` | drawer 方向(仅 drawer 生效) |
|
|
65
|
+
| `headerDivider` | `boolean` | 按形态:drawer=true / modal=false | header 下分割线 |
|
|
66
|
+
| `footerDivider` | `boolean` | 按形态:drawer=true / modal=false | footer 上分割线 |
|
|
67
|
+
| `modalReserve` | `number` | `200` | modal 形态弹层体可用高视口预留 px(provide SCOPE_VIEWPORT_MAX_HEIGHT = innerHeight − modalReserve) |
|
|
68
|
+
|
|
69
|
+
### Emits
|
|
70
|
+
|
|
71
|
+
| 事件 | 载荷 | 语义 |
|
|
72
|
+
| --- | --- | --- |
|
|
73
|
+
| `update:show` | `boolean` | 可见性同步(v-model) |
|
|
74
|
+
|
|
75
|
+
⚠️ `onClose`/`onCancel`/`onConfirm` 是 props 不是 emits(onXxx props 约定)。
|
|
76
|
+
|
|
77
|
+
### Slots
|
|
78
|
+
|
|
79
|
+
| 槽 | scope | 语义 |
|
|
80
|
+
| --- | --- | --- |
|
|
81
|
+
| 默认 | 无 | 正文(content prop 之外的自绘内容区) |
|
|
82
|
+
| `#title` | 无 | 标题 |
|
|
83
|
+
| `#main-header` | 无 | 头部区域(含标题) |
|
|
84
|
+
| `#main-footer` | 无 | 底部区域(含按钮) |
|
|
85
|
+
| `#footer` | `{cancelHandler, confirmHandler, loading}` | 完全自绘操作区 |
|
|
86
|
+
|
|
87
|
+
### Expose
|
|
88
|
+
|
|
89
|
+
无。`inheritAttrs: false` + 全量 `v-bind $attrs` 透传底层 ElDialog/ElDrawer(未声明 EP prop 如 `draggable`/`destroy-on-close` 直达);provide `BODY_CONTENT_VIEWPORT_HEIGHT`(老 key)+ `SCOPE_VIEWPORT_MAX_HEIGHT`(新 key)。
|
|
90
|
+
|
|
91
|
+
## 反模式 / 注意
|
|
92
|
+
|
|
93
|
+
- **关闭回调命名三件套是 props**:`onClose`/`onCancel`/`onConfirm` 走 props 传(`:on-confirm="..."`),不是 `@confirm`;emit 侧只有 `update:show`
|
|
94
|
+
- **onConfirm 的 false / reject 语义**:返回 `false` 不关闭、reject 不关闭(错误留窗内展示)、resolve 关闭——三条路径别写混
|
|
95
|
+
- **`closeOnClickModal` / `closeOnPressEscape` 默认开**:误触遮罩/ESC 即关,需要「不可轻易关闭」的强确认场景显式关掉
|
|
96
|
+
- **`headerDivider` / `footerDivider` 默认随形态**:drawer=true / modal=false;直接不传会得到形态默认值,别以为「没传就是没有」
|
|
97
|
+
- **`direction` 只在 drawer 生效**:modal 形态传了不报错也不生效
|
|
98
|
+
- **老 key 并存**:`BODY_CONTENT_VIEWPORT_HEIGHT`(老)+ `SCOPE_VIEWPORT_MAX_HEIGHT`(新)双 provide,消费新 key 即可
|
|
99
|
+
|
|
100
|
+
## 关联
|
|
101
|
+
|
|
102
|
+
- 弹层族:`ModalForm`(组合 ModalConfirm + FormMain 做表单提交)、`ModalDetail`(CRUD 预设薄壳,内部委托 ModalForm)
|
|
103
|
+
- 命令式弹窗体系:`ModalShelf`(架子 + level 层级)+ `ModalPorter`(modalList 注册表)
|
|
104
|
+
- 视口可用高链:`modalReserve` → provide `SCOPE_VIEWPORT_MAX_HEIGHT`(新 key)/ `BODY_CONTENT_VIEWPORT_HEIGHT`(老 key),TableMain `viewportHeight`/`parentChannel` 同链消费
|
|
105
|
+
- 范式页:`apps/reference/src/pages/modal/confirm/showcase/`
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# ModalDetail(配置化 CRUD 弹窗 / 抽屉)
|
|
2
|
+
|
|
3
|
+
> CRUD 预设薄壳:`type`(add/edit/read)决定标题前缀与提交分支,内部委托 ModalForm 渲染配置化表单。
|
|
4
|
+
> 范式页:`apps/reference/src/pages/list-page/guide/`(DetailModalItem 作 ModalPorter item 的薄适配器)、`apps/reference/src/pages/modal/guide/`
|
|
5
|
+
|
|
6
|
+
## 定位
|
|
7
|
+
|
|
8
|
+
- **空间一等公民**:CRUD 弹窗空间首选(add / edit / read 语义内置),经 ModalPorter evoke 使用
|
|
9
|
+
- **何时用**:新增/编辑/查看三态表单弹窗,一套 `list` 配置三态复用(标题自动带前缀)
|
|
10
|
+
- **何时不用**:只有提交没有三态语义的单表单用 `ModalForm`;确认类用 `ModalConfirm`
|
|
11
|
+
- 结构:CRUD 预设薄壳内部委托 ModalForm(强制 `headerDivider:false`/`footerDivider:false`),只留 add/edit 语义——`type` 决定标题前缀与提交走哪个 api
|
|
12
|
+
- 泛型:`PO` 模型 / `SO` 序列化;提交分支在 `detailSubmitFn` 中——`type !== "add"` 都走 `editApi`
|
|
13
|
+
|
|
14
|
+
## 快速上手(最小可用)
|
|
15
|
+
|
|
16
|
+
作 ModalPorter item 的薄适配器(`list-page/guide/DetailModalItem.vue`——`show`/`closeFn`/`payload` 来自架子注入,add/edit 动态取自 payload):
|
|
17
|
+
|
|
18
|
+
```ts
|
|
19
|
+
const modalProps = computed(() => ({
|
|
20
|
+
show: props.show,
|
|
21
|
+
type: props.payload.type, // add / edit 动态取自 payload
|
|
22
|
+
data: props.payload.data,
|
|
23
|
+
list: userBaseFormList, // 静态配置直接 import,不进 payload
|
|
24
|
+
addApi: addUserApi,
|
|
25
|
+
editApi: editUserApi,
|
|
26
|
+
"onUpdate:show": (v: boolean) => { if (!v) props.closeFn(); },
|
|
27
|
+
onAfterAdd: () => { props.payload.onDone?.(); props.closeFn(); },
|
|
28
|
+
onAfterEdit: () => { props.payload.onDone?.(); props.closeFn(); },
|
|
29
|
+
}));
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**要点**:
|
|
33
|
+
|
|
34
|
+
- 四必传:`show`(v-model)、`data`、`list`、`type`(`"add"|"edit"|"read"`)
|
|
35
|
+
- 标题自动态:不传 `title` 时回退「新增[subTitle] / 编辑[subTitle]」;传 `title`(`() => VNode[]`)则整体替换内置标题
|
|
36
|
+
- 薄适配器模式(ModalPorter item):架子注入的 `closeFn` 挂在 `onUpdate:show` 上(v 为 false 时关闭),`payload.onDone` 在 after* 里回调——业务 [MUST] 自己把「关窗 + 刷新」接上,壳不代劳
|
|
37
|
+
|
|
38
|
+
## 能力边界 / 按需使用
|
|
39
|
+
|
|
40
|
+
- **`type` 三态判据**:`"add"` 新增(标题「新增…」+ 走 `addApi`)/ `"edit"` 编辑(标题「编辑…」+ 走 `editApi`)/ `"read"` 只读(`type !== "add"` 都走 `editApi`——read 态建议 `editApi` 传空/同 edit,只读不应触发真实提交)。一套 `list` 配置三态复用。
|
|
41
|
+
- `addApi`/`editApi`:不传也 resolve → 仍 emit after*——纯 UI 闭环(暂不接后端)可不传;真接后端时传,提交成功以真实响应为准。
|
|
42
|
+
- `title`/`subTitle`:默认标题(新增/编辑 + 前缀)即够用;仅需定制标题(如带图标)时传。
|
|
43
|
+
- `formLayout`/`labelWidth` 等布局 props:默认即够用;仅栅格/紧凑需求时配。
|
|
44
|
+
- `layerType="drawer"`:仅当 CRUD 表单需要抽屉形态时开。
|
|
45
|
+
- **完整能力演示**(薄适配器 + 自定义标题 + 提交闭环):`apps/reference/src/pages/list-page/guide/`、`apps/reference/src/pages/modal/guide/`——能力展示,非推荐默认。
|
|
46
|
+
|
|
47
|
+
## API
|
|
48
|
+
> ⚠️ API 以 types.ts 与组件源码为真相源;与文档冲突时以源码为准。
|
|
49
|
+
|
|
50
|
+
### Props(类型 `ModalDetailProps<PO,SO>`)
|
|
51
|
+
|
|
52
|
+
| name | type | 默认 | 语义 |
|
|
53
|
+
| --- | --- | --- | --- |
|
|
54
|
+
| `show` | `boolean`(必传) | — | 可见性 |
|
|
55
|
+
| `data` | `PO`(必传) | — | 表单数据 |
|
|
56
|
+
| `list` | `FormItemConfigList<PO,SO>`(必传) | — | 表单配置 |
|
|
57
|
+
| `type` | `DetailType = "add"\|"edit"\|"read"`(必传) | — | 表单类型:决定标题前缀与用哪个 api |
|
|
58
|
+
| `title` | `() => VNode[]` | — | 自定义标题整体替换内置标题;不传回退 新增[subTitle]/编辑[subTitle] |
|
|
59
|
+
| `subTitle` | `string` | — | 标题后缀 |
|
|
60
|
+
| `addApi` | `(data: ExtractFormStringifyFromObject<PO,SO>) => Promise<any>` | — | 新增 api;未传也 resolve → 仍 emit afterAdd |
|
|
61
|
+
| `editApi` | `(data: ExtractFormStringifyFromObject<PO,SO>) => Promise<any>` | — | 编辑 api;未传也 resolve → 仍 emit afterEdit |
|
|
62
|
+
| `width` | `number \| string` | `600` | 宽度 |
|
|
63
|
+
| `formLayout` | `FormMainProps<PO,SO>["layout"]` | `{span:24}` | 表单布局 |
|
|
64
|
+
| `formProps` | `Partial<FormProps>` | — | elForm 属性 |
|
|
65
|
+
| `formRowGutter` | `number` | — | 行 gutter |
|
|
66
|
+
| `labelWidth` | `string` | `"auto"` | label 宽度 |
|
|
67
|
+
| `layerType` | `ModalLayerType` | `"modal"` | 弹层形态 |
|
|
68
|
+
| `direction` | `ModalDirection` | `"rtl"` | drawer 方向 |
|
|
69
|
+
|
|
70
|
+
### Emits
|
|
71
|
+
|
|
72
|
+
| 事件 | 载荷 | 语义 |
|
|
73
|
+
| --- | --- | --- |
|
|
74
|
+
| `update:show` | `boolean` | 可见性同步(v-model) |
|
|
75
|
+
| `afterAdd` | 序列化数据 | 新增提交成功(addApi resolve 后) |
|
|
76
|
+
| `afterEdit` | 序列化数据 | 编辑提交成功(editApi resolve 后) |
|
|
77
|
+
|
|
78
|
+
### Slots
|
|
79
|
+
|
|
80
|
+
| 槽 | 语义 |
|
|
81
|
+
| --- | --- |
|
|
82
|
+
| `#header` | 头部(映射到 ModalConfirm 的 main-header) |
|
|
83
|
+
| `#footer` | 底部(映射到 ModalConfirm 的 main-footer) |
|
|
84
|
+
|
|
85
|
+
### Expose
|
|
86
|
+
|
|
87
|
+
无。
|
|
88
|
+
|
|
89
|
+
## 反模式 / 注意
|
|
90
|
+
|
|
91
|
+
- **`type="read"` 无独立提交语义**:`detailSubmitFn` 中 `type !== "add"` 都走 `editApi`——read 态建议 editApi 传空/同 edit(只读态不应触发真实提交分支)
|
|
92
|
+
- **薄适配器要自己接关窗/刷新**:作 ModalPorter item 时,`closeFn` 挂 `onUpdate:show`、`payload.onDone` 挂 after*——壳不代劳「关窗 + 列表刷新」闭环
|
|
93
|
+
- **addApi/editApi 未传也 resolve**:仍 emit after*——「未接 api 的假成功」可能掩盖接入遗漏,确认表单提交成功以真实响应为准
|
|
94
|
+
- **`title` 传了就是整体替换**:自定义标题替换内置前缀标题,而不是追加;只想要后缀用 `subTitle`
|
|
95
|
+
- **分割线强制关**:壳内部强制 `headerDivider:false`/`footerDivider:false`,外部传值不生效(无需传)
|
|
96
|
+
|
|
97
|
+
## 关联
|
|
98
|
+
|
|
99
|
+
- 委托链:`ModalDetail` → `ModalForm` → `ModalConfirm`(Promise 契约 / $attrs 透传 / 分割线语义同源)
|
|
100
|
+
- 表单引擎:`FormMain`(form 族)
|
|
101
|
+
- 命令式弹窗体系:`ModalShelf` + `ModalPorter`(薄适配器模式范式见 `list-page/guide/DetailModalItem.vue`)
|
|
102
|
+
- 类型:`DetailType`、`ModalLayerType`、`ModalDirection`(modal/types.ts)
|
|
103
|
+
- 范式页:`apps/reference/src/pages/list-page/guide/`、`apps/reference/src/pages/modal/guide/`
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# ModalForm(配置化表单弹窗 / 抽屉)
|
|
2
|
+
|
|
3
|
+
> 「ModalConfirm 外壳 + FormMain 表单」组合件:配置驱动渲染表单,提交走 Promise 契约(reject 不关窗 / resolve 关窗 + submitSuccess)。
|
|
4
|
+
> 范式页:`apps/reference/src/pages/modal/form-modal/showcase/`(独立原语用法)
|
|
5
|
+
|
|
6
|
+
## 定位
|
|
7
|
+
|
|
8
|
+
- **空间一等公民**:弹窗表单空间首选(非 CRUD 的表单弹窗)
|
|
9
|
+
- **何时用**:弹窗/抽屉内配置化表单提交(新增反馈、编辑资料等单表单场景)
|
|
10
|
+
- **何时不用**:完整 CRUD 弹窗(新增/编辑/查看三态 + 双 api)用 `ModalDetail`;确认类交互用 `ModalConfirm`;纯弹窗体系管理用 `ModalShelf` + `ModalPorter`
|
|
11
|
+
- 内部链路:`show` 变 true → FormMain `validate()` → `stringify()` → `submitFn(data)`;`show` 变 false 时 `clearValidate()`
|
|
12
|
+
- 泛型:`PO` 模型 / `SO` 序列化——`submitFn` 收到的是 `ExtractFormStringifyFromObject<PO,SO>`(序列化后数据)
|
|
13
|
+
|
|
14
|
+
## 快速上手(最小可用)
|
|
15
|
+
|
|
16
|
+
单表单弹窗零配置——默认 modal 形态 + 宽 600 + 布局 `{span:24}`:
|
|
17
|
+
|
|
18
|
+
```vue
|
|
19
|
+
<ModalForm
|
|
20
|
+
v-model:show="show"
|
|
21
|
+
title="提交反馈"
|
|
22
|
+
:list="feedbackFormList"
|
|
23
|
+
:data="formData"
|
|
24
|
+
:submit-fn="submitFeedback" <!-- resolve → 关窗 + submitSuccess -->
|
|
25
|
+
@submit-success="onSubmitSuccess"
|
|
26
|
+
/>
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**要点**:
|
|
30
|
+
|
|
31
|
+
- 三必传:`show`(v-model)、`data`(表单模型数据)、`list`(form 族配置 `FormItemConfigList<PO,SO>`)
|
|
32
|
+
- `submitFn` 走 ModalConfirm confirmHandler 契约:reject → 不关窗(错误留在原地展示);resolve → 关窗 + emit `submitSuccess`(载荷 = 序列化结果)
|
|
33
|
+
|
|
34
|
+
## 能力边界 / 按需使用
|
|
35
|
+
|
|
36
|
+
- **默认即够用:modal 形态 + 宽 600 + 布局 `{span:24}` + 带分割线**——常规单表单弹窗(新增反馈/编辑资料)只传 `show`/`data`/`list`/`submitFn`。
|
|
37
|
+
- `layerType="drawer"`:仅当表单需要抽屉形态(侧滑、大尺寸表单)时开;`direction` 仅 drawer 生效。
|
|
38
|
+
- `formLayout`/`formRowGutter`/`labelWidth`/`formProps`:默认即够用;仅当表单需要栅格布局(span 分栏)、紧凑排列或 elForm 定制行为时配——均透传 FormMain。
|
|
39
|
+
- `headerDivider`/`footerDivider`:ModalForm 族默认 `true`(带分割线,与 ModalConfirm 默认相反);仅需关掉时显式传 `false`。
|
|
40
|
+
- `#header`/`#footer` 插槽:仅当需要整体替换头部/底部区域时用。
|
|
41
|
+
- **完整能力演示**(独立原语 + 双形态 + 分割线切换):`apps/reference/src/pages/modal/form-modal/showcase/`——能力展示,非推荐默认。
|
|
42
|
+
|
|
43
|
+
## API
|
|
44
|
+
> ⚠️ API 以 types.ts 与组件源码为真相源;与文档冲突时以源码为准。
|
|
45
|
+
|
|
46
|
+
### Props(类型 `ModalFormProps<PO,SO>`)
|
|
47
|
+
|
|
48
|
+
| name | type | 默认 | 语义 |
|
|
49
|
+
| --- | --- | --- | --- |
|
|
50
|
+
| `show` | `boolean`(必传) | — | 可见性 |
|
|
51
|
+
| `data` | `PO`(必传) | — | 表单模型数据 |
|
|
52
|
+
| `list` | `FormItemConfigList<PO,SO>`(必传) | — | 表单配置(form 族类型) |
|
|
53
|
+
| `submitFn` | `(data: ExtractFormStringifyFromObject<PO,SO>) => Promise<any>\|any`(必传) | — | 提交方法;走 ModalConfirm confirmHandler 契约:reject → 不关窗 / resolve → 关窗 + emit submitSuccess |
|
|
54
|
+
| `title` | `string \| (() => VNode[])` | — | 标题(透传 ModalConfirm) |
|
|
55
|
+
| `width` | `number \| string` | `600` | 宽度 / drawer 尺寸 |
|
|
56
|
+
| `layerType` | `ModalLayerType` | `"modal"` | 弹层形态 |
|
|
57
|
+
| `direction` | `ModalDirection` | `"rtl"` | drawer 方向 |
|
|
58
|
+
| `formLayout` | `FormMainProps<PO,SO>["layout"]` | `{span:24}` | 表单整体布局 |
|
|
59
|
+
| `formProps` | `Partial<FormProps>` | — | elForm 其他属性 |
|
|
60
|
+
| `formRowGutter` | `number` | — | 表单行 gutter |
|
|
61
|
+
| `labelWidth` | `string` | `"auto"` | 表单 label 宽度 |
|
|
62
|
+
| `headerDivider` | `boolean` | `true` | header 分割线(ModalForm 族默认带) |
|
|
63
|
+
| `footerDivider` | `boolean` | `true` | footer 分割线 |
|
|
64
|
+
|
|
65
|
+
### Emits
|
|
66
|
+
|
|
67
|
+
| 事件 | 载荷 | 语义 |
|
|
68
|
+
| --- | --- | --- |
|
|
69
|
+
| `update:show` | `boolean` | 可见性同步(v-model) |
|
|
70
|
+
| `submitSuccess` | `data: FormMain 序列化结果` | 提交成功(submitFn resolve 后) |
|
|
71
|
+
|
|
72
|
+
### Slots
|
|
73
|
+
|
|
74
|
+
| 槽 | 语义 |
|
|
75
|
+
| --- | --- |
|
|
76
|
+
| `#header` | 头部(映射到 ModalConfirm 的 main-header) |
|
|
77
|
+
| `#footer` | 底部(映射到 ModalConfirm 的 main-footer) |
|
|
78
|
+
|
|
79
|
+
### Expose
|
|
80
|
+
|
|
81
|
+
无。内部持有 FormMain 实例走 validate → stringify → submitFn;`show` 变 false 时 `clearValidate()`。
|
|
82
|
+
|
|
83
|
+
## 反模式 / 注意
|
|
84
|
+
|
|
85
|
+
- **submitFn 别忘 Promise 语义**:返回 `false` 或 reject 都会**不关窗**——写同步返回时注意别让 falsy 值意外吞掉关闭(走 ModalConfirm confirmHandler 契约)
|
|
86
|
+
- **`data` / `list` 必传缺一即崩**:类型必传,运行时也依赖二者驱动 FormMain
|
|
87
|
+
- **分割线默认与 ModalConfirm 相反**:ModalForm 族默认 `true`(带分割线);想在 ModalConfirm 内自绘表单时注意两族默认不一致
|
|
88
|
+
- **序列化后提交**:`submitFn` 收到的是 `ExtractFormStringifyFromObject<PO,SO>` 而非 PO 原形——日期/枚举等 stringify 转换先发生
|
|
89
|
+
- **宽度默认 600 而非 420**:表单弹窗默认更宽,别按 ModalConfirm 默认想当然
|
|
90
|
+
|
|
91
|
+
## 关联
|
|
92
|
+
|
|
93
|
+
- 外壳:`ModalConfirm`(Promise 契约 / 分割线 / $attrs 透传语义同源)
|
|
94
|
+
- 表单引擎:`FormMain`(form 族,`formLayout`/`formProps` 等均透传)
|
|
95
|
+
- CRUD 预设:`ModalDetail`(内部强制 `headerDivider:false`/`footerDivider:false` 委托本组件)
|
|
96
|
+
- 命令式弹窗体系:`ModalShelf` + `ModalPorter`(ModalForm 亦可作 modalList item)
|
|
97
|
+
- 范式页:`apps/reference/src/pages/modal/form-modal/showcase/`
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# ModalPorter(弹窗注册表·命令式拉起)
|
|
2
|
+
|
|
3
|
+
> 弹窗注册表:`modalList` 声明 key → 组件 → 架子,`evoke(key, payload)` 命令式拉起;nsKey 命名空间 + 失活/卸载自动清理。
|
|
4
|
+
> 范式页:`apps/reference/src/pages/modal/porter/showcase/`(三层自定义架子 + 触发按钮组)、`apps/reference/src/pages/modal/guide/`(对接内置 page 架子)
|
|
5
|
+
|
|
6
|
+
## 定位
|
|
7
|
+
|
|
8
|
+
- **何时用**:代码任意位置需要命令式拉起弹窗(列表行操作、深层组件内触发),且弹窗有「开弹窗」层级诉求时
|
|
9
|
+
- **何时不用**:模板内直接挂载的弹窗(`v-model:show` 声明式)不需要 Porter;无嵌套的单层弹窗直接用 ModalConfirm/ModalForm/ModalDetail
|
|
10
|
+
- 职责边界:Porter 是「注册表 + 拉手」——`modalList` 把 key 与弹窗组件/懒工厂/架子绑定,`evoke` 沿 key 查表拉起并把 payload 注入弹窗 props;弹窗实例落在 ModalShelf 架子上
|
|
11
|
+
- 命名空间:每个 Porter 实例的注册 key 会被包装为 `p{porterUid}:{key}`——多 Porter 实例同 key 不互踩
|
|
12
|
+
|
|
13
|
+
## 快速上手(最小可用)
|
|
14
|
+
|
|
15
|
+
对接内置 page 架子(`modal/guide/config.tsx`——`shelf` 传字符串 `"page"` 即指 AppPage 内置架子):
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
const modalList: RegisterEntry[] = [
|
|
19
|
+
{ key: "standardDetailSpace", component: () => import("./modal/Index.vue"), shelf: "page" },
|
|
20
|
+
];
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**要点**:
|
|
24
|
+
|
|
25
|
+
- `modalList` 注册项:`{key, component | 懒工厂, shelf, sameKeyStrategy?}`——`shelf` 传 `"app"`/`"page"` 字符串寻址内置架子,custom 级传 `ShelfInstance`(ref 的架子实例)
|
|
26
|
+
- `evoke(key, payload)`:key 必须在 `ModalShelfMap` 声明合并中注册(类型化),payload 形状全链推导;未配置的 key 或找不到架子 → `console.error` + 返回 `null`
|
|
27
|
+
- 弹窗组件侧声明 `ModalInjectedProps<P>`:`{show, closeFn, removeFn, payload}`——show 受架子控,closeFn 挂 `onUpdate:show` 即可命令式关闭
|
|
28
|
+
- 生命周期:Porter 失活/卸载时自动 remove 本 porter 注册的全部 nsKey(useActivated 统一收口)——**[MUST NOT]** 手动补偿清理
|
|
29
|
+
|
|
30
|
+
## 能力边界 / 按需使用
|
|
31
|
+
|
|
32
|
+
- **默认即够用:对接内置 page 架子**——列表行操作/深层组件内命令式拉起,`shelf: "page"` 即指 AppPage 内置架子,零自定义架子。
|
|
33
|
+
- **懒工厂按需**:`component: () => import(...)` 按需加载(推荐默认);仅当弹窗必须随页面首屏就位时才直接传组件对象。
|
|
34
|
+
- `sameKeyStrategy`:默认 `"recreate"`(同 key 再 evoke 关旧重建)即够用;`"update"`(已开则整体替换 props 不 remount)仅当同 key 弹窗需要原位刷新数据时选。
|
|
35
|
+
- `shelf: "custom"`:仅当 app/page 两层不够(第三层以上)时才传 `ShelfInstance` 自建 custom 架子(判据见 ModalShelf 能力边界)。
|
|
36
|
+
- **完整能力演示**(三层自定义架子 + 触发按钮组 + 多 key 注册):`apps/reference/src/pages/modal/porter/showcase/`、`apps/reference/src/pages/modal/guide/`——能力展示,非推荐默认。
|
|
37
|
+
|
|
38
|
+
## API
|
|
39
|
+
> ⚠️ API 以 types.ts 与组件源码为真相源;与文档冲突时以源码为准。
|
|
40
|
+
|
|
41
|
+
### Props
|
|
42
|
+
|
|
43
|
+
| name | type | 默认 | 语义 |
|
|
44
|
+
| --- | --- | --- | --- |
|
|
45
|
+
| `modalList` | `RegisterEntry[]`(必传) | — | 弹窗注册表(key → component/懒工厂 → shelf → sameKeyStrategy) |
|
|
46
|
+
|
|
47
|
+
### Slots
|
|
48
|
+
|
|
49
|
+
| 槽 | scope | 语义 |
|
|
50
|
+
| --- | --- | --- |
|
|
51
|
+
| 默认 | 无 | 页面内容透传 |
|
|
52
|
+
|
|
53
|
+
### Expose
|
|
54
|
+
|
|
55
|
+
| 成员 | 签名 | 语义 |
|
|
56
|
+
| --- | --- | --- |
|
|
57
|
+
| `evoke` | `<K extends keyof ModalShelfMap>(key: K, payload: ModalShelfMap[K]) => EvokeHandle \| null` | 按 key 拉起弹窗(payload 类型全链推导);未配置/找不到架子 → console.error + null |
|
|
58
|
+
|
|
59
|
+
## 机制
|
|
60
|
+
|
|
61
|
+
### modalList 注册表寻址
|
|
62
|
+
|
|
63
|
+
`RegisterEntry<K>`:`{key, component | 懒工厂, shelf: "app"|"page"|ShelfInstance, sameKeyStrategy?}`——setup 期同步 inject app/page 控制器并缓存;`shelf:"app"`/`"page"` 字符串寻址内置架子,custom 经 `ShelfInstance` ref 直取。懒工厂写法 `() => import("./modal/Index.vue")` 按需加载。
|
|
64
|
+
|
|
65
|
+
### nsKey 命名空间
|
|
66
|
+
|
|
67
|
+
每个 Porter 实例把注册 key 包装为 `p{porterUid}:{key}`——多 Porter 实例(多页面/多架子)同 key 不互踩;evoke/remove 都以命名空间后的 nsKey 寻址,业务无需感知。
|
|
68
|
+
|
|
69
|
+
### 卸载自动清理
|
|
70
|
+
|
|
71
|
+
失活/卸载时自动 remove 本 porter 注册的全部 nsKey(useActivated 统一收口)——Porter 销毁即弹窗实例随架清理,**[MUST NOT]** 手动补偿清理。
|
|
72
|
+
|
|
73
|
+
### 注入给弹窗的 props(`ModalInjectedProps<P>`)
|
|
74
|
+
|
|
75
|
+
架子把 `{show, closeFn, removeFn, payload: P}` 注入弹窗组件(见 ModalShelf 文档)。
|
|
76
|
+
|
|
77
|
+
## 反模式 / 注意
|
|
78
|
+
|
|
79
|
+
- **未注册 key 是静默失败面**:`evoke` 返回 null + console.error——消费侧 [MUST] 判空(`evoke(...)?.close()` 或先判 null),别假设一定成功
|
|
80
|
+
- **shelf 字符串只认 "app"/"page"**:custom 架子必须传 `ShelfInstance`(ref 实例),传字符串进 custom 寻址不通
|
|
81
|
+
- **key 类型必须声明合并**:evoke 的 key 泛型约束 `keyof ModalShelfMap`——业务 [MUST] 在 `.d.ts` 里 declare module 扩展 `ModalShelfMap`(见 ModalShelf 文档),否则 key 不在 map 上 TS 直接拦截
|
|
82
|
+
- **自动清理别补偿**:Porter 失活/卸载已自动 remove 全部 nsKey,手写 `onUnmounted` 清理是重复劳动(也可能提前清掉活跃弹窗)
|
|
83
|
+
- **弹窗 UI 不在 Porter 插槽里写**:Porter 只是注册表宿主,弹窗经 evoke 落在架子上渲染——插槽只放页面内容
|
|
84
|
+
|
|
85
|
+
## 关联
|
|
86
|
+
|
|
87
|
+
- 架子宿主:`ModalShelf`(level 层级 + ModalShelfMap declare merge + evoke/remove/close + sameKeyStrategy)
|
|
88
|
+
- 注入契约:`ModalInjectedProps<P>`(show/closeFn/removeFn/payload,架子注入弹窗组件)
|
|
89
|
+
- 句柄:`EvokeHandle`(close / update 增量合并,不 remount)
|
|
90
|
+
- 弹窗组件族:`ModalConfirm` / `ModalForm` / `ModalDetail`(作注册表 item;DetailModalItem 薄适配器范式见 `list-page/guide/`)
|
|
91
|
+
- 类型:`RegisterEntry<K>`、`ModalSameKeyStrategy`("recreate" 默认 / "update" 整体替换 props 不 remount)
|
|
92
|
+
- 范式页:`apps/reference/src/pages/modal/porter/showcase/`、`apps/reference/src/pages/modal/guide/`
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# ModalShelf(弹窗架子·层级治理)
|
|
2
|
+
|
|
3
|
+
> 弹窗架子:`level` 声明结构性身份(app/page/custom),沿 DOM 收集祖先并断言层级合法,为 ModalPorter 提供命令式注册表宿主。
|
|
4
|
+
> 范式页:`apps/reference/src/pages/modal/porter/showcase/`(三层自定义嵌套架子 + ModalPorter)、`apps/reference/src/pages/modal/guide/`(对接内置 page 架子)
|
|
5
|
+
|
|
6
|
+
## 定位
|
|
7
|
+
|
|
8
|
+
- **何时用**:应用出现「弹窗开弹窗」的层级诉求时,用架子显式声明弹层寄居层级——AppLayout/AppPage 已内置 app/page 两层,业务只在需要第三层以上或自定义作用域时手挂 `level="custom"` 架子
|
|
9
|
+
- **何时不用**:单层弹窗(无嵌套)不需要架子——直接用 ModalConfirm/ModalForm/ModalDetail;也不需要在 AppLayout/AppPage 内再挂 app/page 级架子(内置,业务 [MUST NOT] 自声明)
|
|
10
|
+
- 职责边界:架子只管「身份 + 层级合法性 + 实例注册表宿主」,**不渲染弹窗 UI**——弹窗由 ModalPorter 的 modalList 注册表经 `evoke` 命令式拉起,页面内容走默认插槽透传
|
|
11
|
+
|
|
12
|
+
## 快速上手(最小可用)
|
|
13
|
+
|
|
14
|
+
对接内置 page 架子——普通业务**零架子起步**,页面只放 Porter 注册表(`modal/guide/`):
|
|
15
|
+
|
|
16
|
+
```vue
|
|
17
|
+
<AppPage>
|
|
18
|
+
<!-- ...页面内容... -->
|
|
19
|
+
<ModalPorter :modalList="modalList" /> <!-- modalList 项 shelf: "page" 即指本架子 -->
|
|
20
|
+
</AppPage>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**要点**:
|
|
24
|
+
|
|
25
|
+
- 内置挂载(业务 [MUST NOT] 自声明):AppLayout.vue 内置 `level="app"`、AppPage.vue 内置 `level="page"`——单层/双层弹窗零架子
|
|
26
|
+
- 控制器:`evoke(nsKey, component, {payload, sameKeyStrategy?})` 拉起 / `remove(nsKey|string[])` 移除 / `close(item)` 关闭——经 `ShelfController` expose 暴露,ModalPorter 内部自动对接
|
|
27
|
+
- `level` 是**架子结构性身份**:挂载后不变(setup 期快照非响应式),传给控制器 / 注册表寻址用
|
|
28
|
+
|
|
29
|
+
## 能力边界 / 按需使用
|
|
30
|
+
|
|
31
|
+
- **默认即够用:内置 app/page 两层架子**——普通业务零架子起步;单层弹窗(无嵌套)连架子都不需要,直接用 ModalConfirm/ModalForm/ModalDetail。
|
|
32
|
+
- `level="custom"`:**仅当需要第三层以上或自定义作用域的弹窗层级时**才手挂(判据:app/page 两层装不下「弹窗开弹窗开弹窗」)。custom 可任意嵌套,业务一般一层够用。
|
|
33
|
+
- 业务 [MUST NOT] 在 AppLayout/AppPage 内再挂 app/page 级架子(内置,重复挂载是层级污染);page 上禁挂 custom(非法挂法,开发期 console.error)。
|
|
34
|
+
- 层级合法性只在开发期校验:非法挂法只警告不崩,但生产仍会弹窗乱叠——守合法挂法是业务责任。
|
|
35
|
+
- **完整能力演示**(三层自定义嵌套架子 + Porter 触发按钮组):`apps/reference/src/pages/modal/porter/showcase/`——能力展示,非推荐默认。
|
|
36
|
+
|
|
37
|
+
## API
|
|
38
|
+
> ⚠️ API 以 types.ts 与组件源码为真相源;与文档冲突时以源码为准。
|
|
39
|
+
|
|
40
|
+
### Props
|
|
41
|
+
|
|
42
|
+
| name | type | 默认 | 语义 |
|
|
43
|
+
| --- | --- | --- | --- |
|
|
44
|
+
| `level` | `ModalLevel = "app"\|"page"\|"custom"`(必传) | — | 架子结构性身份,挂载后不变(setup 期快照非响应式) |
|
|
45
|
+
|
|
46
|
+
### Slots
|
|
47
|
+
|
|
48
|
+
| 槽 | scope | 语义 |
|
|
49
|
+
| --- | --- | --- |
|
|
50
|
+
| 默认 | 无 | 页面内容透传 |
|
|
51
|
+
|
|
52
|
+
### Expose(`ShelfController`)
|
|
53
|
+
|
|
54
|
+
| 成员 | 签名 | 语义 |
|
|
55
|
+
| --- | --- | --- |
|
|
56
|
+
| `level` | `ModalLevel` | 架子层级 |
|
|
57
|
+
| `evoke` | `(nsKey, component, {payload, sameKeyStrategy?}) => EvokeHandle` | 命令式拉起弹窗(nsKey 定位 / component 注册 / payload 注入) |
|
|
58
|
+
| `remove` | `(nsKey \| string[]) => void` | 按 nsKey 移除一个/多个实例 |
|
|
59
|
+
| `close` | `(item: ShelfItem) => void` | 关闭指定活跃实例 |
|
|
60
|
+
|
|
61
|
+
> ⚠️ expose 实际另含 `items: Ref<ShelfItem[]>`(内部渲染用活跃实例列表;公开类型 `ShelfController` 不含——按公开类型使用)
|
|
62
|
+
|
|
63
|
+
## 机制
|
|
64
|
+
|
|
65
|
+
### level 层级与合法性断言
|
|
66
|
+
|
|
67
|
+
`provide(getModalShelfInjectionKey(level), controller)`;onMounted 沿 `["app","page","custom"]` 收集祖先并 `assertLevelHierarchy`:
|
|
68
|
+
|
|
69
|
+
- `app` 必最顶层
|
|
70
|
+
- `page` 上仅禁 `custom`(允许 page 套 page)
|
|
71
|
+
- `custom` 可任意嵌套
|
|
72
|
+
|
|
73
|
+
非法挂法仅开发期 `console.error`,不阻断运行。
|
|
74
|
+
|
|
75
|
+
### ModalShelfMap declare merge(全链类型化)
|
|
76
|
+
|
|
77
|
+
业务侧在 `.d.ts` 里对 `@done-coding/admin-core` 的 `ModalShelfMap` 空 interface 做声明合并扩展,evoke 与弹窗 props 全链类型化(`apps/reference/src/types/standard-modal.d.ts`):
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
declare module "@done-coding/admin-core" {
|
|
81
|
+
interface ModalShelfMap {
|
|
82
|
+
/** 范式 A 列表弹窗式 CRUD:DetailModal 作 modalList item 的 payload */
|
|
83
|
+
standardListDetail: { type: DetailType; data: UserPO; onDone?: () => void };
|
|
84
|
+
standardDetailSpace: { id: number; onDone?: () => void };
|
|
85
|
+
standardTabListDetail: { type: DetailType; data: UserPO; subTitle: string; onDone?: () => void };
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
每个 key 的值类型 = 该弹窗的 payload 形状(注入给弹窗组件的 `payload` prop 全类型化)。
|
|
91
|
+
|
|
92
|
+
### 注入给弹窗的 props(`ModalInjectedProps<P>`)
|
|
93
|
+
|
|
94
|
+
架子把 `{show, closeFn, removeFn, payload: P}` 注入弹窗组件——弹窗组件声明接收,`show` 由架子受控、`closeFn`/`removeFn` 是命令式关闭出口、`payload` 为业务数据。
|
|
95
|
+
|
|
96
|
+
### 命令式句柄(`EvokeHandle`)
|
|
97
|
+
|
|
98
|
+
`evoke` 返回 `EvokeHandle`:`close()` 关闭、`update(partialPayload)` 增量合并更新 payload(不 remount)。
|
|
99
|
+
|
|
100
|
+
## 反模式 / 注意
|
|
101
|
+
|
|
102
|
+
- **业务 [MUST NOT] 自声明 app/page 架子**:AppLayout/AppPage 已内置,重复挂载是层级污染
|
|
103
|
+
- **`level` 快照非响应式**:挂载后改 level 不生效——架子身份在挂载时刻定死,需要不同层级另起架子
|
|
104
|
+
- **架子不渲染弹窗 UI**:只是宿主,弹窗实例由 ModalPorter evoke 拉起——别在架子插槽里手写 `<ModalConfirm>` 混编(破坏注册表寻址)
|
|
105
|
+
- **`sameKeyStrategy` 语义别与 EvokeHandle.update 混淆**:`"recreate"`(同 key 再 evoke 关旧重建,默认)vs `"update"`(已开则整体替换 props 不 remount);而 `EvokeHandle.update` 是**增量合并**(partialPayload)——三条路径语义各不相同
|
|
106
|
+
- **page 上禁挂 custom**:page 架子内嵌 custom 架子属非法挂法(开发期报错);要三层以上请自建 custom 链
|
|
107
|
+
- **层级合法性只在开发期校验**:生产不报错,但挂法错误导致的弹窗乱叠仍会存在——守合法挂法是业务责任
|
|
108
|
+
|
|
109
|
+
## 关联
|
|
110
|
+
|
|
111
|
+
- 注册表入口:`ModalPorter`(modalList 注册表,内部自动对接 app/page 控制器并缓存)
|
|
112
|
+
- 层级机制:`modal-shelf-hierarchy.ts`(assertLevelHierarchy 合法挂法断言)、`modal-shelf-core.ts`(实例注册表)、`modal-shelf-types.ts`(ModalLevel / ModalSameKeyStrategy / ShelfController / ShelfItem / ShelfInstance / EvokeHandle / RegisterEntry)
|
|
113
|
+
- 内置挂载点:`AppLayout.vue`(level="app")、`AppPage.vue`(level="page")
|
|
114
|
+
- 弹窗组件族:`ModalConfirm` / `ModalForm` / `ModalDetail`(可作架子注入的弹窗组件)
|
|
115
|
+
- 范式页:`apps/reference/src/pages/modal/porter/showcase/`、`apps/reference/src/pages/modal/guide/`
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# panel 面板族
|
|
2
|
+
|
|
3
|
+
配置驱动详情面板:`PanelMain` 消费 `PanelItemConfig` 列表,只读渲染 + 就地编辑(editorConfig / editorRender 三分支)+ 嵌套(C2 / C3)。
|
|
4
|
+
|
|
5
|
+
> ⚠️ **`PanelMain` 一等公民地位撤销 · 将废弃**:页级纯展示场景将由 `ViewLayout`(展示布局组件,后续迭代)承接——PanelMain 定位为 ViewLayout 默认插槽内容 / 表单预览与就地编辑场景保留。新页面 [MUST NOT] 以 PanelMain 作页级展示根容器;存量页面仅预览/编辑态保留使用。
|
|
6
|
+
|
|
7
|
+
## 组件文档(docs/)
|
|
8
|
+
|
|
9
|
+
- [PanelMain](./docs/README-PanelMain.md) — 详情面板(含 PanelItem 关键配置 PanelItemConfig 与编辑态三分支)
|
|
10
|
+
|
|
11
|
+
## 关键类型与 helper
|
|
12
|
+
|
|
13
|
+
- 类型:`PanelMainProps` / `PanelItemConfig` / `PanelScopeBase` / `PanelRenderScope`(经 `./types` 导出)
|
|
14
|
+
- helper:`nestPanelItem`(C2)/ `nestPanelForm`(C3)——与 editorConfig 互斥,同一 item [MUST NOT] 同配
|
|
15
|
+
- ⚠️ `itemCard` 默认不套卡片(旧默认已移除,breaking)
|
|
16
|
+
|
|
17
|
+
## 范式页(apps/reference)
|
|
18
|
+
|
|
19
|
+
- `/panel/panel-main/showcase`(editorConfig / editorRender / scope.refresh)/ `/panel/nest-panel/showcase`(C2/C3)/ `/panel/nest-layout-rebase`(P3 rebase)
|