@done-coding/admin-core 0.12.1 → 0.12.2-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 (128) hide show
  1. package/README.md +1 -48
  2. package/es/bridge/index.mjs +75 -72
  3. package/es/bridge/layout.mjs +51 -0
  4. package/es/bridge/theme/index.mjs +1 -1
  5. package/es/bridge/theme/persist.mjs +1 -1
  6. package/es/components/app-layout/AppAside.vue.mjs +2 -2
  7. package/es/components/app-layout/AppAside.vue2.mjs +27 -10
  8. package/es/components/app-layout/AppCollapseToggle.vue.mjs +7 -0
  9. package/es/components/app-layout/AppCollapseToggle.vue2.mjs +54 -0
  10. package/es/components/app-layout/AppFooter.vue.mjs +1 -1
  11. package/es/components/app-layout/AppHeader.vue.mjs +3 -3
  12. package/es/components/app-layout/AppHeader.vue2.mjs +1 -1
  13. package/es/components/app-layout/AppLayout.vue.mjs +2 -2
  14. package/es/components/app-layout/AppLayout.vue2.mjs +3 -3
  15. package/es/components/app-layout/AppSidebar.vue.mjs +2 -2
  16. package/es/components/app-layout/AppSidebar.vue2.mjs +41 -61
  17. package/es/components/app-layout/AppTheme.vue.mjs +3 -3
  18. package/es/components/app-layout/viewport.mjs +3 -3
  19. package/es/components/display/TabsHeader.vue.mjs +4 -4
  20. package/es/components/form/FormItemNestForm.vue.mjs +2 -2
  21. package/es/components/form/FormItemNestFormList.vue.mjs +2 -2
  22. package/es/components/form/FormSubmitPanel.vue.mjs +1 -1
  23. package/es/components/form/FormVerifyImage.vue.mjs +1 -1
  24. package/es/components/table/TableToolbar.vue.mjs +3 -3
  25. package/es/hooks/{use-admin-theme-apply.mjs → use-theme-apply.mjs} +62 -62
  26. package/es/hooks/use-viewport-apply.mjs +39 -0
  27. package/es/index.mjs +88 -88
  28. package/es/inject/key.mjs +13 -13
  29. package/es/store/app.mjs +69 -62
  30. package/es/style.css +1 -1
  31. package/package.json +6 -8
  32. package/types/bridge/config-hook.d.ts +0 -68
  33. package/types/bridge/index.d.ts +18 -417
  34. package/types/bridge/layout.d.ts +25 -0
  35. package/types/bridge/plugin.d.ts +12 -30
  36. package/types/bridge/route.d.ts +1 -20
  37. package/types/bridge/state.d.ts +0 -14
  38. package/types/bridge/storage.d.ts +0 -9
  39. package/types/bridge/theme/index.d.ts +1 -8
  40. package/types/bridge/theme/persist.d.ts +3 -15
  41. package/types/bridge/theme/system-dark.d.ts +0 -12
  42. package/types/bridge/theme/types.d.ts +27 -265
  43. package/types/components/app-layout/AppAside.vue.d.ts +0 -1
  44. package/types/components/app-layout/AppCollapseToggle.vue.d.ts +11 -0
  45. package/types/components/app-layout/AppHeader.vue.d.ts +0 -3
  46. package/types/components/app-layout/AppLayout.vue.d.ts +0 -12
  47. package/types/components/app-layout/AppPage.vue.d.ts +0 -2
  48. package/types/components/app-layout/AppSidebar.vue.d.ts +0 -2
  49. package/types/components/app-layout/types.d.ts +2 -127
  50. package/types/components/app-layout/viewport.d.ts +2 -30
  51. package/types/components/data-view/DataListViewItem.vue.d.ts +0 -8
  52. package/types/components/data-view/index.d.ts +0 -4
  53. package/types/components/data-view/types.d.ts +0 -41
  54. package/types/components/data-view/utils.d.ts +0 -3
  55. package/types/components/display/TabsHeader.vue.d.ts +0 -2
  56. package/types/components/display/TabsMain.vue.d.ts +0 -2
  57. package/types/components/display/TabsRefineFlow.vue.d.ts +0 -1
  58. package/types/components/display/index.d.ts +1 -37
  59. package/types/components/display/types.d.ts +0 -131
  60. package/types/components/form/FormItemNestForm.vue.d.ts +0 -5
  61. package/types/components/form/FormItemNestFormList.vue.d.ts +0 -17
  62. package/types/components/form/FormVerifyCode.vue.d.ts +0 -9
  63. package/types/components/form/FormVerifyImage.vue.d.ts +0 -1
  64. package/types/components/form/form-search-utils.d.ts +0 -14
  65. package/types/components/form/nest-form-item-list.d.ts +0 -28
  66. package/types/components/form/nest-form-item.d.ts +0 -21
  67. package/types/components/form/nest-registry.d.ts +0 -14
  68. package/types/components/form/types.d.ts +8 -185
  69. package/types/components/form/use-form-submit.d.ts +0 -12
  70. package/types/components/form/use-nest-form-list.d.ts +0 -13
  71. package/types/components/form/use-nest-form.d.ts +0 -15
  72. package/types/components/form/use-nest-layout-scale.d.ts +0 -12
  73. package/types/components/form/utils.d.ts +1 -56
  74. package/types/components/list-page/ListPage.vue.d.ts +0 -6
  75. package/types/components/list-page/types.d.ts +2 -19
  76. package/types/components/misc/index.d.ts +1 -6
  77. package/types/components/misc/types.d.ts +0 -6
  78. package/types/components/modal/ConfirmModal.vue.d.ts +0 -10
  79. package/types/components/modal/modal-shelf-core.d.ts +0 -3
  80. package/types/components/modal/modal-shelf-hierarchy.d.ts +0 -4
  81. package/types/components/modal/modal-shelf-types.d.ts +0 -34
  82. package/types/components/modal/types.d.ts +1 -20
  83. package/types/components/panel/PanelItemNestForm.vue.d.ts +0 -6
  84. package/types/components/panel/PanelItemNestPanel.vue.d.ts +0 -5
  85. package/types/components/panel/nest-panel-form.d.ts +0 -21
  86. package/types/components/panel/nest-panel-item.d.ts +0 -14
  87. package/types/components/panel/types.d.ts +1 -49
  88. package/types/components/table/types.d.ts +9 -124
  89. package/types/config/list-model.d.ts +0 -29
  90. package/types/config/route.d.ts +0 -2
  91. package/types/helpers/form.d.ts +0 -5
  92. package/types/helpers/list-helper.d.ts +0 -26
  93. package/types/helpers/types.d.ts +0 -11
  94. package/types/hooks/activated.d.ts +0 -10
  95. package/types/hooks/feel-size.d.ts +0 -2
  96. package/types/hooks/index.d.ts +2 -2
  97. package/types/hooks/menus-dispatch.d.ts +0 -4
  98. package/types/hooks/timeout.d.ts +0 -4
  99. package/types/hooks/use-channel-viewport-height.d.ts +0 -14
  100. package/types/hooks/use-theme-apply.d.ts +11 -0
  101. package/types/hooks/use-viewport-apply.d.ts +8 -0
  102. package/types/inject/key.d.ts +2 -87
  103. package/types/router/guard/index.d.ts +0 -13
  104. package/types/router/guard/login.d.ts +0 -1
  105. package/types/router/guard/permission.d.ts +0 -1
  106. package/types/router/guard/types.d.ts +2 -5
  107. package/types/store/app.d.ts +10 -31
  108. package/types/store/router-permission.d.ts +2 -55
  109. package/types/store/user.d.ts +2 -26
  110. package/types/types/dot-path.d.ts +0 -8
  111. package/types/types/route.d.ts +0 -45
  112. package/types/types/utility-types.d.ts +0 -7
  113. package/types/utils/export.d.ts +1 -16
  114. package/types/utils/id.d.ts +0 -1
  115. package/types/utils/router.d.ts +0 -2
  116. package/types/utils/theme-scale.d.ts +0 -31
  117. package/types/utils/time.d.ts +0 -1
  118. package/docs/TECH_SNAPSHOT.md +0 -146
  119. package/docs/nested-config-paradigm.md +0 -80
  120. package/docs/specs/2026-05-09-055250-moderate-/345/210/227/350/241/250key/351/205/215/347/275/256/347/202/271/350/267/257/345/276/204/346/224/257/346/214/201/RETROSPECTIVE.md +0 -63
  121. package/docs/specs/2026-05-09-055250-moderate-/345/210/227/350/241/250key/351/205/215/347/275/256/347/202/271/350/267/257/345/276/204/346/224/257/346/214/201/design.md +0 -575
  122. package/docs/specs/2026-05-09-055250-moderate-/345/210/227/350/241/250key/351/205/215/347/275/256/347/202/271/350/267/257/345/276/204/346/224/257/346/214/201/landing-authorizations/2026-05-09-080900-/346/234/2371-/345/205/245/345/256/236/346/226/275/346/216/210/346/235/203.md +0 -107
  123. package/docs/specs/2026-05-09-055250-moderate-/345/210/227/350/241/250key/351/205/215/347/275/256/347/202/271/350/267/257/345/276/204/346/224/257/346/214/201/project-orchestration.md +0 -58
  124. package/docs/specs/2026-05-09-055250-moderate-/345/210/227/350/241/250key/351/205/215/347/275/256/347/202/271/350/267/257/345/276/204/346/224/257/346/214/201/requirements.md +0 -238
  125. package/docs/specs/2026-05-09-055250-moderate-/345/210/227/350/241/250key/351/205/215/347/275/256/347/202/271/350/267/257/345/276/204/346/224/257/346/214/201/tasks.md +0 -290
  126. package/es/hooks/use-admin-viewport-apply.mjs +0 -39
  127. package/types/hooks/use-admin-theme-apply.d.ts +0 -34
  128. package/types/hooks/use-admin-viewport-apply.d.ts +0 -20
@@ -1,35 +1,8 @@
1
1
  import { CSSProperties } from 'vue';
2
- import { AdminBridge } from '../bridge';
3
- /**
4
- * createAppStore 工厂依赖(#A 期,与 createUserStore deps 收敛单字段 `{ bridge }` 范式对齐)。
5
- *
6
- * 业务无泛型消费——layout/theme 配置全经 bridge 12 readonly 属性直读,业务 shape
7
- * 不渗透 core;UserInfo / LoginParams 双泛型纯透传给入参 `AdminBridge` 签名
8
- * (避免 app 侧具体类型 bridge 赋给 `AdminBridge<unknown,unknown>` 时的逆变位置
9
- * 类型冲突,与 createUserStore 范式对齐),core setup 内 [MUST NOT] 消费双泛型字段。
10
- * #C 期:删第 3 泛型 RefreshTokenParams 透传(bridge 签名已删第 3 泛型)。
11
- */
2
+ import { CoreBridge } from '../bridge';
12
3
  export interface CreateAppStoreDeps<UserInfo = unknown, LoginParams = unknown> {
13
- /** app 侧 admin bridge 单例(注入而非 core 持单例,守规则 8;layout/theme 配置全经此读) */
14
- bridge: AdminBridge<UserInfo, LoginParams>;
4
+ bridge: CoreBridge<UserInfo, LoginParams>;
15
5
  }
16
- /**
17
- * app store 工厂下沉 core。
18
- *
19
- * 返回 `defineStore("APP", setup)` 结果(store id 保持 `"APP"`;core 工厂无状态,
20
- * store 实例由 app 侧 pinia 管理,规则 8)。
21
- *
22
- * 主题架构反转(不再 1:1 镜像原 app store dark 状态机):dark/风格切换真相全移交
23
- * bridge(`bridge.themeIsDark` / `bridge.theme.setStyle/setDark`)——
24
- * - `isDarkTheme` 改读 `bridge.themeIsDark`(store 不再持 ref 真相);
25
- * - `changeIsDarkTheme` 转发 `bridge.theme.setDark`(旧消费方兼容兜底);
26
- * - 退役 store `watch isDarkTheme → className`(由挂值 composable toggle `.dark`);
27
- * - 退役 store dark 持久化(`pick:["isDarkTheme"]`)——bridge 持久化 `{themeStyle,themeIsDark}`。
28
- * layout/route/sidebar 等非主题运行时行为保持不变。
29
- *
30
- * @example
31
- * export const useAppStore = createAppStore({ bridge: appAdminBridge });
32
- */
33
6
  export declare function createAppStore<UserInfo = unknown, LoginParams = unknown>(deps: CreateAppStoreDeps<UserInfo, LoginParams>): import('pinia').StoreDefinition<"APP", Pick<{
34
7
  name: import('vue').ComputedRef<string>;
35
8
  isDarkTheme: import('vue').ComputedRef<boolean>;
@@ -72,7 +45,9 @@ export declare function createAppStore<UserInfo = unknown, LoginParams = unknown
72
45
  left: string;
73
46
  }>;
74
47
  sidebarIsCollapse: import('vue').ComputedRef<boolean>;
48
+ asideIsCollapse: import('vue').ComputedRef<boolean>;
75
49
  changeSidebarCollapseStatus: (status: boolean) => void;
50
+ changeAsideCollapseStatus: (status: boolean) => void;
76
51
  changeSidebarHasMenusStatus: (status: boolean) => void;
77
52
  changeIsDarkTheme: (status: boolean) => void;
78
53
  }, never>, Pick<{
@@ -117,10 +92,12 @@ export declare function createAppStore<UserInfo = unknown, LoginParams = unknown
117
92
  left: string;
118
93
  }>;
119
94
  sidebarIsCollapse: import('vue').ComputedRef<boolean>;
95
+ asideIsCollapse: import('vue').ComputedRef<boolean>;
120
96
  changeSidebarCollapseStatus: (status: boolean) => void;
97
+ changeAsideCollapseStatus: (status: boolean) => void;
121
98
  changeSidebarHasMenusStatus: (status: boolean) => void;
122
99
  changeIsDarkTheme: (status: boolean) => void;
123
- }, "name" | "theme" | "showHeader" | "keepAlive" | "bodyShimPadding" | "isDarkTheme" | "showFooter" | "showSidebar" | "showAside" | "showBreadcrumb" | "headerStyle" | "footerStyle" | "sidebarStyle" | "asideStyle" | "bodyStyle" | "bodyShimStyle" | "viewportPadding" | "sidebarIsCollapse">, Pick<{
100
+ }, "name" | "theme" | "showHeader" | "keepAlive" | "bodyShimPadding" | "isDarkTheme" | "showFooter" | "showSidebar" | "showAside" | "showBreadcrumb" | "headerStyle" | "footerStyle" | "sidebarStyle" | "asideStyle" | "bodyStyle" | "bodyShimStyle" | "viewportPadding" | "sidebarIsCollapse" | "asideIsCollapse">, Pick<{
124
101
  name: import('vue').ComputedRef<string>;
125
102
  isDarkTheme: import('vue').ComputedRef<boolean>;
126
103
  theme: import('vue').ComputedRef<{
@@ -162,7 +139,9 @@ export declare function createAppStore<UserInfo = unknown, LoginParams = unknown
162
139
  left: string;
163
140
  }>;
164
141
  sidebarIsCollapse: import('vue').ComputedRef<boolean>;
142
+ asideIsCollapse: import('vue').ComputedRef<boolean>;
165
143
  changeSidebarCollapseStatus: (status: boolean) => void;
144
+ changeAsideCollapseStatus: (status: boolean) => void;
166
145
  changeSidebarHasMenusStatus: (status: boolean) => void;
167
146
  changeIsDarkTheme: (status: boolean) => void;
168
- }, "changeSidebarCollapseStatus" | "changeSidebarHasMenusStatus" | "changeIsDarkTheme">>;
147
+ }, "changeSidebarCollapseStatus" | "changeAsideCollapseStatus" | "changeSidebarHasMenusStatus" | "changeIsDarkTheme">>;
@@ -1,72 +1,19 @@
1
1
  import { RouteLocationNormalizedLoaded } from 'vue-router';
2
- import { AdminBridge } from '../bridge';
3
- /**
4
- * createRoutePermissionStore 工厂依赖(#B 期;与 createUserStore / createAppStore
5
- * deps 范式对齐——bridge 经 init 注入,业务 hook / 业务路径常量经 deps 注入)。
6
- *
7
- * `useUserStore` 采用 hook 注入(方案 A)——业务层传入 createUserStore 实例化结果,
8
- * core setup 内调 `useUserStore()` 取响应式 store 实例。方案 B(store 实例注入)
9
- * 在 createRoutePermissionStore 模块求值期调 hook 会 throw "pinia not active",故采纳 A。
10
- * Hook 返回的 store 实例形状用结构最小约束 `{ isLogin, havePermissionByPath, noApiLogout }`
11
- * 表达——避免 core 反向耦合 createUserStore 三泛型 + 与 createUserStore 返回的具体
12
- * store 结构自动结构兼容(业务侧零摩擦传入 useUserStore)。
13
- *
14
- * `paths` 4 业务路径经 deps 注入而非 bridge schema——业务路径非通用 layout config,
15
- * 不内化到 bridge(产研统筹勘察结论;保 bridge schema 0 扩张)。
16
- *
17
- * 双泛型 `<UserInfo, LoginParams>` 纯透传给入参 `AdminBridge` 签名(避免 app 侧
18
- * 具体类型 bridge 赋给 `AdminBridge<unknown,unknown>` 时的逆变位置类型冲突,
19
- * 与 createUserStore / createAppStore 范式对齐),core setup 内 [MUST NOT] 消费双泛型字段。
20
- * #C 期:删第 3 泛型 RefreshTokenParams 透传(bridge 签名已删第 3 泛型)。
21
- */
2
+ import { CoreBridge } from '../bridge';
22
3
  export interface CreateRoutePermissionStoreDeps<UserInfo = unknown, LoginParams = unknown> {
23
- /** app 侧 admin bridge 单例(注入而非 core 持单例,守规则 8;APP_ROUTER_META_DEFAULT_CONFIG 经此直读 + register goToLogin 经此注册) */
24
- bridge: AdminBridge<UserInfo, LoginParams>;
25
- /**
26
- * 业务侧 createUserStore 实例化结果(hook 形态)。
27
- * core setup 内调 `useUserStore()` 取响应式 store 实例;本字段仅约束最小消费面,
28
- * [MUST NOT] 扩展为全 user store API surface(保 core 对 UserInfo shape 不透明)。
29
- */
4
+ bridge: CoreBridge<UserInfo, LoginParams>;
30
5
  useUserStore: () => {
31
6
  isLogin: boolean;
32
7
  havePermissionByPath: (path: string) => boolean;
33
8
  noApiLogout: () => void;
34
9
  };
35
- /**
36
- * 4 业务路径常量(业务路径非通用 layout config,[MUST NOT] 内化到 bridge schema)。
37
- * core 不知具体路径值,经 deps 注入;业务层在 packages/app/src/router/config.ts 维护。
38
- */
39
10
  paths: {
40
- /** 登录路径 */
41
11
  login: string;
42
- /** 无权限路径 */
43
12
  noPermission: string;
44
- /** 登录免检路径列表 */
45
13
  loginNoCheck: string[];
46
- /** 权限免检路径列表 */
47
14
  authNoCheck: string[];
48
15
  };
49
16
  }
50
- /**
51
- * 路由权限 store 泛型工厂下沉 core。
52
- *
53
- * 返回 `defineStore("ROUTE_PERMISSION", setup)` 结果(store id 保持 `"ROUTE_PERMISSION"`;
54
- * core 工厂无状态,store 实例由 app 侧 pinia 管理,规则 8)。setup 内 1:1 镜像原
55
- * `packages/app/src/store/router-permission.ts` 全部 139 行运行时行为
56
- * (checkRouteNeedLogin / checkNeedGoToLoginPage / needGoToLoginPage /
57
- * checkNeedGoToAuthPage / needGoToAuthPage / goToLoginPage / register goToLogin /
58
- * 2 watch redirect),[MUST NOT] 重构 / 精简 / 调整顺序。
59
- *
60
- * `bridge.APP_ROUTER_META_DEFAULT_CONFIG` 直读取代原 `from "@/config"` import;
61
- * `getRoutePermissionKey` 走 `@/utils` 复用。
62
- *
63
- * @example
64
- * export const useRoutePermission = createRoutePermissionStore({
65
- * bridge: appAdminBridge,
66
- * useUserStore,
67
- * paths: { login: loginPath, noPermission: noPermissionPath, loginNoCheck: loginNoCheckPath, authNoCheck: authNoCheckPath },
68
- * });
69
- */
70
17
  export declare function createRoutePermissionStore<UserInfo = unknown, LoginParams = unknown>(deps: CreateRoutePermissionStoreDeps<UserInfo, LoginParams>): import('pinia').StoreDefinition<"ROUTE_PERMISSION", Pick<{
71
18
  checkNeedGoToAuthPage: (routeInfo: Pick<RouteLocationNormalizedLoaded, "path">) => boolean;
72
19
  checkNeedGoToLoginPage: (routeInfo: RouteLocationNormalizedLoaded) => boolean;
@@ -1,33 +1,9 @@
1
1
  import { ComputedRef } from 'vue';
2
- import { AdminBridge } from '../bridge';
2
+ import { CoreBridge } from '../bridge';
3
3
  import { RoutePermission } from '../types';
4
- /**
5
- * createUserStore 工厂依赖(v3 终锁 Δ1:deps 收敛单字段 `{ bridge }`)。
6
- *
7
- * 业务类型 shape 经泛型 `<UserInfo, LoginParams>` 注入(core 不锁 shape,规则 8);
8
- * 运行时配置 + 注入面全部经 `bridge`——`getAppConfig` / `getRoutes` / 4 业务 api /
9
- * `getUserInfoInitFn()`(用户信息空保底工厂,替代 0fd94cc `userInfoInit` deps 字段)。
10
- *
11
- * 第一宪法:token / refreshToken / permission 三字段经 `bridge.userInfoAccess.<字段>`
12
- * 业务注入访问器读写(纯函数 get/set,core 零字面字段名耦合,业务 UserInfo shape 自由)。
13
- */
14
4
  export interface CreateUserStoreDeps<UserInfo, LoginParams = unknown> {
15
- /** app 侧 admin bridge 单例(注入而非 core 持单例,守规则 8;getUserInfoInitFn 经 bridge.init 注入,本工厂经 bridge.getUserInfoInitFn() 读) */
16
- bridge: AdminBridge<UserInfo, LoginParams>;
5
+ bridge: CoreBridge<UserInfo, LoginParams>;
17
6
  }
18
- /**
19
- * 用户 store 泛型工厂下沉 core。
20
- *
21
- * 返回 `defineStore("USER", setup)` 结果(store id 保持 `"USER"`;core 工厂
22
- * 无状态,store 实例由 app 侧 pinia 管理,规则 8)。setup 内 1:1 镜像原
23
- * `packages/app/src/store/user.ts` 全部运行时行为(actions / computed / watch /
24
- * return / 路由权限计算),[MUST NOT] 重构 / 精简 / 调整顺序。
25
- *
26
- * @example
27
- * export const useUserStore = createUserStore<LoginAccountInfo, AccountLoginParams>({
28
- * bridge: appAdminBridge,
29
- * });
30
- */
31
7
  export declare function createUserStore<UserInfo, LoginParams = unknown>(deps: CreateUserStoreDeps<UserInfo, LoginParams>): import('pinia').StoreDefinition<"USER", Pick<{
32
8
  userInfo: ComputedRef<UserInfo>;
33
9
  token: ComputedRef<string>;
@@ -1,11 +1,3 @@
1
- /**
2
- * 字符串点路径转嵌套对象类型
3
- * ---
4
- * @example
5
- * DotToObject<"page.page", number> -> { page: { page: number } }
6
- * DotToObject<"items", T[]> -> { items: T[] }
7
- * DotToObject<"a.b.c", string> -> { a: { b: { c: string } } }
8
- */
9
1
  export type DotToObject<P extends string, V> = P extends `${infer Head}.${infer Tail}` ? {
10
2
  [K in Head]: DotToObject<Tail, V>;
11
3
  } : {
@@ -1,93 +1,48 @@
1
1
  import { RouteRecordRaw } from 'vue-router';
2
2
  import { DefineComponent } from 'vue';
3
- /** 路由权限配置 */
4
3
  export type RoutePermission = Partial<{
5
- /** 是否需要登录 */
6
4
  login: boolean;
7
- /**
8
- * 权限key
9
- * 若为number 期望!=0
10
- * 若为string 期望!=""
11
- */
12
5
  key: number | string;
13
- /** 权限key使用路径 */
14
6
  keyUsePath: boolean;
15
- /** 权限编辑时是否展示 默认配置权限key就会展示 */
16
7
  editShow: boolean;
17
8
  }>;
18
- /**
19
- * 路由 meta 扩展形状(与 app 端 vue-router declaration merging 对齐)
20
- * ---
21
- * core 不做全局 declaration merging,仅作 core 内部类型自洽用;
22
- * app 端仍通过自身 router-meta.d.ts 做 vue-router declaration merging,获得 vue-router RouteMeta 的扩展类型
23
- */
24
9
  export interface AppRouteMeta {
25
- /** 页面名称 */
26
10
  title: string;
27
- /** 是否缓存 */
28
11
  keepAlive?: boolean;
29
- /** 是否重定向到第一个有权限的子路由 */
30
12
  redirectToFirstChildRoute?: boolean;
31
- /** 页面布局 */
32
13
  layout?: Partial<{
33
14
  header: boolean;
34
15
  sidebar: boolean;
35
- /** 右侧 aside 补充区显隐(additive;默认 false,仅自定义 shell 渲染) */
36
16
  aside: boolean;
37
17
  footer: boolean;
38
18
  breadcrumb: boolean;
39
19
  bodyShimPadding: number;
40
20
  }>;
41
- /** 菜单 */
42
21
  menu?: Partial<{
43
22
  show: boolean;
44
23
  sort: number;
45
- /** 图标 (element-plus 等图标实例的 DefineComponent 签名差异较大,这里用 any 兼容) */
46
24
  icon: any;
47
25
  }>;
48
- /** 权限 */
49
26
  permission?: RoutePermission;
50
27
  }
51
- /** 获取路由权限key入参 */
52
28
  export interface GetRoutePermissionParams {
53
- /** 路由路径 */
54
29
  path: string;
55
- /** 权限配置 */
56
30
  permission: RoutePermission | undefined;
57
31
  }
58
- /** 路由元信息解析raw */
59
32
  export interface RouteMetaResolveRaw {
60
- /** 路由地址 */
61
33
  path: string;
62
- /** 页面名称 */
63
34
  title: string;
64
- /** 路由级别 */
65
35
  routeLevel: number;
66
- /**
67
- * 是否重定向到第一个有权限的子路由
68
- * 详见 RouteMeta.redirectToFirstChildRoute
69
- */
70
36
  redirectToFirstChildRoute: boolean;
71
- /** 是否在菜单展示 */
72
37
  menuShow: boolean;
73
- /** 菜单icon */
74
38
  menuIcon?: DefineComponent;
75
- /** 菜单排序 */
76
39
  menuSort: number;
77
- /** 子路由原始配置 */
78
40
  childrenRaw: RouteRecordRaw[];
79
- /** 子路由元信息解析raw */
80
41
  children: RouteMetaResolveRaw[];
81
- /** 父路由地址 */
82
42
  parentPath: string;
83
- /** 父路由地址列表 */
84
43
  parentPathList: string[];
85
- /** 权限key */
86
44
  permissionKey?: string | number;
87
- /** 是否检测权限 */
88
45
  checkPermission: boolean;
89
- /** (配置权限的前提下)权限编辑时是否展示 */
90
46
  permissionEditShow: boolean;
91
- /** 是否需要登录 */
92
47
  needLogin: boolean;
93
48
  }
@@ -1,8 +1 @@
1
- /**
2
- * 联合类型转交叉类型
3
- * ---
4
- * 用于多个 DotToObject 结果合并:
5
- * { page: { page: number } } | { page: { pageSize: number } }
6
- * -> { page: { page: number; pageSize: number } }
7
- */
8
1
  export type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
@@ -1,31 +1,16 @@
1
1
  import { ElTableColumnProps } from '../components/table/types';
2
- /** 操作列标记 prop。消费方以此值标记操作列,导出时自动过滤 */
3
2
  export declare const OPERATE_COLUMN_PROP = "OPERATE";
4
- /** 前端导出最大行数 */
5
3
  export declare const EXPORT_MAX_LIMIT = 10000;
6
- /** 导出列:从 ElTableColumnProps 中提取 proplabeltype */
7
- export type ExportColumn<T extends Record<string, any>,
8
- /** 期望注入到表格列插槽上的额外内容 */
9
- F extends Record<string, any> = {}> = Pick<ElTableColumnProps<T, F>, "prop" | "label" | "type">;
10
- /** 导出列配置:支持 valueMap 自定义取值 */
4
+ export type ExportColumn<T extends Record<string, any>, F extends Record<string, any> = {}> = Pick<ElTableColumnProps<T, F>, "prop" | "label" | "type">;
11
5
  export interface ExportColumnConfig<T extends Record<string, any>> {
12
6
  prop: keyof T;
13
7
  label: string;
14
- /** 自定义取值,不传则取 row[prop] */
15
8
  valueMap?: (row: Record<keyof T, any>) => unknown;
16
9
  }
17
- /** 导出参数 */
18
10
  export interface ExportOptions<T extends Record<string, any>> {
19
11
  columns: ExportColumnConfig<T>[];
20
12
  list: T[];
21
13
  filename?: string;
22
14
  }
23
- /**
24
- * 从表格列配置中提取可导出列
25
- * ---
26
- * 过滤规则:排除 type 为 selection / index / expand 的列(除 default 外均排除),
27
- * 排除 prop 为 OPERATE_COLUMN_PROP 的列,排除无 prop 的列
28
- */
29
15
  export declare const pickExportColumns: <T extends Record<string, any>, F extends Record<string, any>>(columns: ElTableColumnProps<T, F>[]) => ExportColumn<T, F>[];
30
- /** 导出 CSV 文件 */
31
16
  export declare const exportCSV: <T extends Record<string, any>>({ columns, list, filename, }: ExportOptions<T>) => void;
@@ -1,2 +1 @@
1
- /** 获取不重复的值[单次生命周期中] */
2
1
  export declare const getId: (prefix?: string) => string;
@@ -1,7 +1,5 @@
1
1
  import { GetRoutePermissionParams } from '../types';
2
- /** 获取路由权限key */
3
2
  export declare const getRoutePermissionKey: ({ path, permission: permissionConfig, }: GetRoutePermissionParams) => string | number | undefined;
4
- /** 扁平化路由元信息解析raw */
5
3
  export declare const flatRouteMetaResolveRaw: <T extends {
6
4
  children: T[];
7
5
  }>(list: T[], arr?: T[]) => T[];
@@ -1,15 +1,5 @@
1
- /**
2
- * 主题色阶派生(模式感知,复刻 Element Plus 的 SCSS `mix` 算法)。
3
- *
4
- * core 挂值时对 6 个语义色(primary/success/warning/danger/info + error)
5
- * 由基色派生 EP 7 档(base 自身 + light-3/5/7/8/9 + dark-2),亮/暗模式各用
6
- * 不同的混入色,使派生结果与 EP 原生色阶一致。
7
- */
8
- /** 主题明暗模式(决定色阶向哪一端混合) */
9
1
  export type ThemeScaleMode = "light" | "dark";
10
- /** 一个语义色的 EP 7 档色阶(key 与 `--el-color-*-light-#` / `-dark-2` 对齐) */
11
2
  export interface ThemeColorScale {
12
- /** 基色自身 */
13
3
  base: string;
14
4
  "light-3": string;
15
5
  "light-5": string;
@@ -18,28 +8,7 @@ export interface ThemeColorScale {
18
8
  "light-9": string;
19
9
  "dark-2": string;
20
10
  }
21
- /** `#rgb` / `#rrggbb` → [r,g,b];非法格式返回 null */
22
11
  export declare const themeScaleParseHex: (hex: string) => [number, number, number] | null;
23
- /**
24
- * 混色:`c1` 占 `w1`、`c2` 占 `1-w1`,各通道线性混合后四舍五入
25
- * (复刻 EP/SCSS `mix(c1, c2, w1)` 语义,w1 为 c1 的权重 [0,1])。
26
- * 任一入参非 hex(如 `var(...)` / `rgba(...)`)→ 返回 `c2` 兜底,不崩。
27
- */
28
12
  export declare const themeScaleMix: (c1: string, c2: string, w1: number) => string;
29
- /**
30
- * `#rgb` / `#rrggbb` + alpha → `rgba(r, g, b, a)`。
31
- *
32
- * 供吃不了 CSS `var()` 的 JS / canvas 消费方(如 ElWatermark `font.color`)按主题
33
- * 真实色值 + 透明度生成可绘制色串。`alpha` 自动裁剪到 [0,1]。
34
- * 非 hex 入参(`var(...)` / `rgba(...)`)→ 原样返回(不崩、不强转)。
35
- */
36
13
  export declare const themeScaleToRgba: (hex: string, alpha: number) => string;
37
- /**
38
- * 按 EP 算法 + 模式感知派生一个语义色的 7 档色阶。
39
- *
40
- * - light:`light-i = mix(#fff, base, i*10%)`,`dark-2 = mix(#000, base, 20%)`
41
- * - dark: `light-i = mix(#141414, base, i*10%)`,`dark-2 = mix(#fff, base, 20%)`
42
- *
43
- * `base` 非 hex 时各档兜底返回 `base` 原值(保持可挂载、不崩)。
44
- */
45
14
  export declare const themeScaleDerive: (base: string, mode: ThemeScaleMode) => ThemeColorScale;
@@ -1,2 +1 @@
1
- /** 倒计时 */
2
1
  export declare const timeCountDown: (time: number, handler: (t: number) => void, endHandler: () => void) => () => void;
@@ -1,146 +0,0 @@
1
- # @done-coding/admin-core 技术架构快照
2
-
3
- > 文档定位:快照型——始终反映当前技术架构状态,覆盖式更新,不保留历史变更(变更见 git history)。
4
- > 维护者:架构师;触发时机:归档协议执行时。
5
-
6
- ## 1. 设计边界
7
-
8
- ### 1.1 包含范围(✓)
9
-
10
- - 通用 admin 基础设施组件(form / menu / display / misc)
11
- - 通用列表分页结构(`APP_API_LIST_MODEL_KEY_CONFIG` / `AppApiListModel<T>` / `AppApiListParamsModel<P>` / `AppApiListPageParamsKey` / `AppNoPageParamsKey`)
12
- - dot-path 类型工具(`DotToObject` / `UnionToIntersection` / `BuildListModel` / `BuildListParams`)
13
- - 通用 hooks / utils / types
14
- - 路由通用类型(`./types/route`)
15
-
16
- ### 1.2 排除范围(✗,业务壳层永不下沉)
17
-
18
- - 业务码外壳:`APP_API_BUSINESS_MODEL_KEY_CONFIG` / `AppApiBusinessModel<T>`(code / message / data 字段名属公司级业务约定)
19
- - 业务接口配置:`APP_REQUEST_CONFIG`(含 `basePath` 来自 `import.meta.env.VITE_API_BASE_PATH` 的构建期常量,core 包构建期不可知)
20
- - 业务路由 / 业务枚举(如 `BusinessErrorEnum`)
21
- - IoC 注入式 KEY 配置(一个月内不引入;见 ADR-4)
22
-
23
- > 边界硬规则:**业务壳层永不下沉 core**。任何带公司业务特征(业务码语义 / basePath 构建期常量 / 业务路由)的成员均留 app 包。
24
-
25
- ## 2. 已知约束
26
-
27
- ### 2.1 分页 KEY 固化
28
-
29
- `APP_API_LIST_MODEL_KEY_CONFIG` 的 4 KEY 取值在 core 内固化为公司级约定:
30
-
31
- | KEY | 取值 |
32
- |---|---|
33
- | CURRENT_PAGE_KEY | `"page.page"` |
34
- | PAGE_SIZE_KEY | `"page.pageSize"` |
35
- | TOTAL_KEY | `"page.totalRecord"` |
36
- | LIST_KEY | `"items"` |
37
-
38
- **类型层与运行时层均从 `typeof KEY_CONFIG` 推导**——所有列表/分页相关类型(`AppApiListModel` / `AppApiListParamsModel` / `TableApiParams` / `TableApiResult`)的字段名 [MUST] 通过 `typeof APP_API_LIST_MODEL_KEY_CONFIG.XXX_KEY` 读取,[MUST NOT] 手写嵌套字面量(如 `{ items: T[]; page: { totalRecord: number } }`)。
39
-
40
- 理由——KEY runtime 取值并非永久不变,消费方可通过发新版或 pnpm patch 重写;手写字面量会让 runtime 改而类型不跟进,等于自废 dot-path 推导能力。
41
-
42
- ### 2.2 pnpm patch 逃生通道
43
-
44
- 消费方自定义分页字段时,通过 `pnpm patch @done-coding/admin-core` 在工具链层重写已发布产物的 `APP_API_LIST_MODEL_KEY_CONFIG` 取值。
45
-
46
- 最小步骤:
47
-
48
- ```bash
49
- # 1. 创建 patch
50
- pnpm patch @done-coding/admin-core
51
-
52
- # 2. 修改 patch 临时目录下 3 个产物文件(必须同步改)
53
- # - es/index.mjs (ESM 运行时)
54
- # - lib/index.cjs (CJS 运行时)
55
- # - types/index.d.ts (as const 字符串字面量类型,必须同步以保 typeof 推导)
56
- # 将 APP_API_LIST_MODEL_KEY_CONFIG 4 KEY 取值改为消费方约定(如 current / size / total / list)
57
-
58
- # 3. 提交 patch
59
- pnpm patch-commit <临时目录>
60
-
61
- # 4. 重启 dev / 重新 build
62
- ```
63
-
64
- **警示:** [MUST NOT] 通过业务运行时配置(plugin install 选项 / 全局变量 / 工厂函数)覆盖 KEY 取值——会让 `typeof KEY_CONFIG` 类型推导失效(编译期常量),等于自废 dot-path 工具能力。
65
-
66
- ## 3. 类型工具说明
67
-
68
- ### 3.1 `DotToObject<P, V>`
69
-
70
- 字符串点路径转嵌套对象类型。
71
-
72
- | 输入 | 输出 |
73
- |---|---|
74
- | `DotToObject<"a.b.c", string>` | `{ a: { b: { c: string } } }` |
75
- | `DotToObject<"page.page", number>` | `{ page: { page: number } }` |
76
- | `DotToObject<"items", T[]>` | `{ items: T[] }` |
77
-
78
- ### 3.2 `UnionToIntersection<U>`
79
-
80
- 联合类型转交叉类型。用于多个 `DotToObject` 结果合并:
81
-
82
- | 输入 | 输出 |
83
- |---|---|
84
- | `UnionToIntersection<{a:{x:1}} \| {a:{y:2}}>` | `{a:{x:1; y:2}}` |
85
-
86
- ### 3.3 `BuildListModel<KC, T>`
87
-
88
- 基于 KEY_CONFIG 联合推导完整列表响应模型(高阶组合工具)。
89
-
90
- | 输入 | 输出 |
91
- |---|---|
92
- | `BuildListModel<typeof APP_API_LIST_MODEL_KEY_CONFIG, User>` | `{ items: User[]; page: { page: number; pageSize: number; totalRecord: number } }` |
93
-
94
- ### 3.4 `BuildListParams<KC, P>`
95
-
96
- 基于 KEY_CONFIG 联合推导列表请求参数模型。
97
-
98
- | 输入 | 输出 |
99
- |---|---|
100
- | `BuildListParams<typeof APP_API_LIST_MODEL_KEY_CONFIG, { keyword?: string }>` | `{ keyword?: string } & { page: { page: number; pageSize: number } }` |
101
-
102
- ## 4. 架构决策记录 (ADR)
103
-
104
- ### ADR-1:4 工具 2 层架构(基础 + 应用)
105
-
106
- **决策:** dot-path 工具拆分为 2 层——基础层(`DotToObject` / `UnionToIntersection`)与应用层(`BuildListModel` / `BuildListParams`),全部归属 `packages/core/src/types/dot-path.ts` 单文件。
107
-
108
- **理由:** 基础层是纯 TS 字符串路径推导,与列表领域无关,未来其他领域(表单 schema / URL query)也可复用;应用层是基于基础层组合的列表领域专用工具,给 list-model.ts 提供高阶接口。
109
-
110
- **否决方案:** 仅暴露 2 个高阶工具(不出基础层)——TableApiResult 只需 items + page.totalRecord 子集,强制带入完整 4 KEY 推导后还要 Pick 二次裁剪,反而不灵活。
111
-
112
- **状态:** 活跃。
113
-
114
- ### ADR-2:core 单一来源 + app re-export 切源
115
-
116
- **决策:** `APP_API_LIST_MODEL_KEY_CONFIG` 等 5 项的唯一定义点位于 `packages/core/src/config/list-model.ts`;`packages/app/src/config/request.ts` 删除原定义,改为从 `@done-coding/admin-core` re-export。
117
-
118
- **理由:** ① 消除 core/app 双份漂移根因(取消 CI 检查的前提);② core 自身后续迁组件需直接引用,不能从 app 反向 import;③ app 端通过 re-export 而非全仓库改 import path,业务面零改动。
119
-
120
- **否决方案:** 双份维护 + CI 检查——治标不治本,已被用户裁决取消(NG-6)。
121
-
122
- **状态:** 活跃。
123
-
124
- ### ADR-3:DUCK 最小化 + `typeof KEY_CONFIG` 推导贯彻全域
125
-
126
- **决策:** 所有列表/分页类型(`AppApiListModel` / `AppApiListParamsModel` / `AppApiListPageParamsKey` / `TableApiParams` / `TableApiResult`)的字段名 [MUST] 从 `typeof APP_API_LIST_MODEL_KEY_CONFIG.XXX_KEY` 读取,禁止手写嵌套字面量。
127
-
128
- **理由:** KEY runtime 可经 pnpm patch 改写;手写字面量会让 runtime 改而类型不跟进。
129
-
130
- **状态:** 活跃。
131
-
132
- ### ADR-4:取消双份镜像,pnpm patch 作为消费方自定义分页字段的逃生通道
133
-
134
- **决策:** 不引入 IoC 注入(plugin install 选项 / createAdminCore 工厂等);消费方需自定义 KEY 时通过 pnpm patch 重写产物。
135
-
136
- **理由:** ① IoC 注入需给所有列表类型工具提供运行时配置出口,复杂度溢出;② 真实业务场景中分页字段是公司级约定,跨项目变更频率极低;③ pnpm patch 是 monorepo 工具链层标准能力,零代码侵入;④ 用户裁决:一个月内不考虑 IoC(NG-2)。
137
-
138
- **状态:** 活跃。
139
-
140
- ### ADR-5:业务壳层(code / data / message + APP_REQUEST_CONFIG)永不下沉 core
141
-
142
- **决策:** `APP_REQUEST_CONFIG` / `APP_API_BUSINESS_MODEL_KEY_CONFIG` / `AppApiBusinessModel<T>` 三项保留 app,不下沉 core。
143
-
144
- **理由:** ① 业务码字段名(code / data / message)属公司级业务约定,不同后端可能用 errno / result / msg;② basePath 来自 `import.meta.env.VITE_API_BASE_PATH` 是 app 构建期常量,core 包构建期不可知;③ NG-1 硬约束。
145
-
146
- **状态:** 活跃。
@@ -1,80 +0,0 @@
1
- # 配置化嵌套范式(FormMain 套 FormMain / PanelMain 套 PanelMain / 交叉互套)— 实现纪要
2
-
3
- > **定位**:**P1/P2/P3 已实现纪要**。本文原为设计提案(design-only),其后 nest 联结组件落地,P1(校验穿透)、P2(Panel 嵌套)、P3(布局 rebase span 值轴)均已实现,**实现走了比初版设想更干净的路**;仅 P3 的**断点选择轴**(容器查询)留后续 opt-in。
4
- > **实现去向**:4 个联结薄壳(C1 `FormItemNestForm` / C4 `FormItemNestFormList` / C2 `PanelItemNestPanel` / C3 `PanelItemNestForm`)+ 配套 helper(`nestFormItem` / `nestFormItemList` / `nestPanelItem` / `nestPanelForm`)。
5
- > **上位原则**:KB `paradigm.md` §3.0.1「非顶级子空间挂载薄壳(递归下探二等公民层)」——本文是该范式在 Form/Panel 自嵌套 + 交叉嵌套切片上的工程纪要。
6
-
7
- ---
8
-
9
- ## 1. 范式:薄壳即嵌套(已落地)
10
-
11
- FormMain / PanelMain **本身没有**「表单套表单 / 面板套面板」的一等 prop 支持,但**也不需要**——两族配置化 item 的渲染出口(`render` / `editorRender`)本就是**开放契约**:返回 `VNode[]` 即可,内容由配置方决定。
12
-
13
- > 嵌套 = 在一个 item 的 `render`/`editorRender` 里套一层**薄壳**(联结组件),薄壳内部挂一个**新的配置化容器**(子 FormMain / PanelMain)。只要薄壳对外仍满足父容器对该 item 的契约(值、校验、布局),父容器无感知,嵌套即成立。
14
-
15
- 三种形态(无界组合,均已落地):
16
- - **Form 套 Form**:C1 `FormItemNestForm`(1:1)/ C4 `FormItemNestFormList`(1:N 数组)。
17
- - **Panel 套 Panel**:C2 `PanelItemNestPanel`(纯展示)。
18
- - **交叉互套**:C3 `PanelItemNestForm`(Panel 项编辑态内嵌 FormMain)。
19
-
20
- > KB 视角的本体定位:联结薄壳 = 把**空间二等公民**(子 FormMain/PanelMain,当不了空间根)适配成满足父 item 契约的可嵌挂载件,**非空间一等公民**。见 `paradigm.md` §3.0.1。
21
-
22
- ---
23
-
24
- ## 2. P1 校验穿透 — ✅ 已实现(registry 级联,非初版 validator 桥)
25
-
26
- ### 实际落地
27
-
28
- - **form 族经 registry 级联**:`FormItemNestForm`(C1)/ `FormItemNestFormList`(C4)经 `useNestForm` / `useNestFormList` 把子 `FormMain` 的 `{ validate, clearValidate, resetFields }` 注册进**最近祖先 FormMain** 的 `exposeMap`(`NestFormExposeMap = shallowReactive<Record<itemKey, NestFormExpose>>`,`nest-registry.ts`)。父顶层一次 `validate/clearValidate/resetFields` 即经 `exposeMap` 级联到子(C4 为聚合 expose + fan-out 遍历 N 行)。
29
- - **对齐 hideKeyList**:父 FormMain `validate` 按 item key 过滤——整 list 被 hide 时不级联(ADR-8)。
30
- - **panel 族不接 registry**:panel 是 per-item submit、无父顶层 validate,故 C3 `PanelItemNestForm` 改走组件内**局部 `validateChild`**(提交前自校验,reject 留编辑态);C2 纯展示无校验。
31
-
32
- > **与初版提案的差异(求真)**:提案曾设想用 item `rules` 的 async `validator` 作「校验穿透桥」。**实现未采用**——registry/exposeMap 级联更干净(无需把子 formInstance 塞进规则闭包,天然对齐 hideKeyList)。初版 validator 桥设想已废弃,不再保留为方向。
33
-
34
- ---
35
-
36
- ## 3. P2 PanelMain 嵌套 — ✅ 已实现
37
-
38
- - **展示态**(C2 `PanelItemNestPanel`):内层 PanelMain 置 `itemCard=false` → 子项平铺("一项展示多字段"观感,本质潜套 PanelMain);值贯通 = `render` 的 `scope.value` 嵌套对象只读直供子 PanelMain。
39
- - **编辑态**(C3 `PanelItemNestForm`):经 `editorRender`(优先级高于 `editorConfig`,互斥)挂子 FormMain;`PanelEditSwitch` 进编辑深克隆**草稿**,子 FormMain 绑草稿 in-place,校验通过 `submitFn(草稿) → closeEdit` **回流**真实 data,取消弃草稿。这正是「配置式 `editorConfig` 单字段表达不了的多字段子表单」的合规 escape hatch。
40
-
41
- ---
42
-
43
- ## 4. P3 嵌套后的布局继承(layout 基于父 item 实际宽而非屏幕)— ✅ 已实现(span 值轴;断点选择轴留 opt-in)
44
-
45
- ### 落地(2026-06-13)
46
-
47
- - 4 联结薄壳现经 `layoutScale` 累乘因子向子 FormMain/PanelMain 传 rebase 因子:`childScale = parentScale × (24 / 父item span)`,子 `resolveFormLayout(span, scale)` 把 span×scale 后 `ceilToTier` 到档集 `{6,8,12,24}`(封顶 24)。**默认开**;helper 加 `rebase?: boolean`(缺省 `true`,`false` = 逆向逃生口原样直透)。
48
- - 链路:`FormMain`/`PanelMain` 加 prop `layoutScale`(缺省 1)+ provide `NEST_LAYOUT_SCALE_KEY`;薄壳 `useNestLayoutScale` inject 父 scale 叠本层因子;helper 经 `resolveLayoutSpan(layout)` 把父 item 代表 span 传薄壳。
49
- - 不变量:叶子字段绝对宽 ≈ `(authoredSpan/24) × 屏宽`,与嵌套深度无关。
50
- - 设计 + worked examples 见 `docs/specs/2026-06-13-045727-moderate-嵌套布局rebase-P3/design.md`。
51
-
52
- ### 解决的缺口
53
-
54
- 外层 item 用窄栅格(如父 `span:12` = 半宽容器)时,子字段 `span` 相对**容器**算百分比 → 嵌套层过挤;rebase 按父 item 实际分配宽放大子 span,维持字段绝对宽与顶级一致。
55
-
56
- ### 已知近似(v1 接受)
57
-
58
- - 仅修 **span 值轴**;**断点选择轴**(el 的 `xs/sm/md/lg/xl` 由 **window 宽** media query 选档,非容器宽)留后续 opt-in 容器查询治理。
59
- - 3+ 层且中间层被 ceil/clamp 时,因子用 authored span 略欠精;2 层常见场景精确。
60
-
61
- ---
62
-
63
- ## 5. 状态小结
64
-
65
- | # | 缺口 | 状态 | 实际落地 / 遗留 |
66
- |---|---|---|---|
67
- | P1 | 校验穿透 | ✅ 已实现 | form 族 registry/exposeMap 级联(C1/C4,ADR-1/8);panel 族局部 validateChild(C3)/ 无校验(C2)。初版 validator 桥设想已废 |
68
- | P2 | Panel 嵌套 | ✅ 已实现 | C2 展示(itemCard 平铺)+ C3 编辑(editorRender 挂子 FormMain + 草稿回流) |
69
- | P3 | 布局继承 rebase | ✅ 已实现(span 值轴) | layoutScale 累乘链 + ceilToTier 档集;断点选择轴留 opt-in 容器查询 |
70
-
71
- **遗留边界**:本文不再据 P1/P2/P3 实现展开(已落地,API 见 KB 组件档 + MIGRATION §38);唯一未做项为 P3 的**断点选择轴**(容器查询替代 viewport 媒体断点),留后续 opt-in spec。
72
-
73
- ---
74
-
75
- ## 附:相关源码 / KB 锚点
76
-
77
- - 联结薄壳源:`packages/core/src/components/form/{FormItemNestForm,FormItemNestFormList}.vue` + `{nest-form-item,nest-form-item-list}.ts`;`packages/core/src/components/panel/{PanelItemNestPanel,PanelItemNestForm}.vue` + `{nest-panel-item,nest-panel-form}.ts`
78
- - registry 基建:`packages/core/src/components/form/{nest-registry,use-nest-form,use-nest-form-list}.ts`
79
- - 上位范式 + 组件 API(KB):`~/.claude/knowledge/admin-core/paradigm.md` §3.0.1;`components/{FormItemNestForm,FormItemNestFormList,PanelItemNestPanel,PanelItemNestForm}.md`
80
- - 嵌套三件套实现 spec(含 ADR-1/5/6/8):`docs/specs/2026-06-12-020608-complex-配置化嵌套联结组件Nest三件套/`