@done-coding/admin-core 0.28.1-alpha.0 → 0.29.1-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/es/bridge/layout.mjs +31 -2
  2. package/es/components/app-layout/AppAside.vue.mjs +1 -1
  3. package/es/components/app-layout/AppCollapseToggle.vue.mjs +1 -1
  4. package/es/components/app-layout/AppFooter.vue.mjs +1 -1
  5. package/es/components/app-layout/AppHeader.vue.mjs +1 -1
  6. package/es/components/app-layout/AppHeader.vue2.mjs +1 -1
  7. package/es/components/app-layout/AppSidebar.vue.mjs +1 -1
  8. package/es/components/app-layout/AppSidebar.vue2.mjs +60 -34
  9. package/es/components/data-view/DataGridView.vue.mjs +1 -1
  10. package/es/components/data-view/DataGridView.vue2.mjs +30 -6
  11. package/es/components/data-view/DataListView.vue.mjs +1 -1
  12. package/es/components/data-view/DataListView.vue2.mjs +38 -14
  13. package/es/components/data-view/DataListViewItem.vue.mjs +1 -1
  14. package/es/components/data-view/DataListViewItem.vue2.mjs +23 -4
  15. package/es/components/data-view/InfiniteListView.vue.mjs +1 -1
  16. package/es/components/data-view/InfiniteListView.vue2.mjs +9 -3
  17. package/es/components/data-view/use-grid-layout.mjs +46 -0
  18. package/es/components/data-view/use-masonry.mjs +65 -0
  19. package/es/components/display/BadgeMark.vue.mjs +1 -1
  20. package/es/components/display/BadgeMark.vue2.mjs +11 -3
  21. package/es/components/display/HeightProvider.vue.mjs +17 -3
  22. package/es/components/display/use-badge.mjs +22 -13
  23. package/es/components/form/use-upload-state.mjs +33 -11
  24. package/es/components/page-layout/AppPageDetail.vue.mjs +1 -1
  25. package/es/components/page-layout/AppPageDetail.vue2.mjs +12 -2
  26. package/es/components/page-layout/AppPageListDetailLayout.vue.mjs +11 -4
  27. package/es/components/page-layout/AppPageListDetailSheet.vue.mjs +8 -1
  28. package/es/components/page-layout/AppPageListDetailSplit.vue.mjs +1 -1
  29. package/es/components/page-layout/AppPageListDetailSplit.vue2.mjs +8 -1
  30. package/es/components/table/TableMain.vue.mjs +1 -1
  31. package/es/components/table/TableMain.vue2.mjs +8 -5
  32. package/es/components/view-layout/ViewLayout.vue.mjs +1 -1
  33. package/es/components/view-layout/ViewLayout.vue2.mjs +68 -20
  34. package/es/hooks/use-surface.mjs +4 -1
  35. package/es/hooks/use-theme-apply.mjs +78 -0
  36. package/es/index.mjs +118 -120
  37. package/es/store/app.mjs +25 -0
  38. package/es/style.css +120 -95
  39. package/package.json +2 -2
  40. package/src/bridge/docs/README.md +31 -0
  41. package/src/components/app-layout/docs/README-AppAside.md +11 -0
  42. package/src/components/app-layout/docs/README-AppFooter.md +11 -1
  43. package/src/components/app-layout/docs/README-AppHeader.md +16 -0
  44. package/src/components/app-layout/docs/README-AppSidebar.md +18 -0
  45. package/src/components/data-view/README.md +2 -1
  46. package/src/components/data-view/docs/README-DataGridView.md +21 -1
  47. package/src/components/data-view/docs/README-DataListView.md +65 -3
  48. package/src/components/data-view/docs/README-InfiniteListView.md +17 -0
  49. package/src/components/display/README.md +1 -1
  50. package/src/components/display/docs/README-BadgeMark.md +52 -10
  51. package/src/components/display/docs/README-HeightProvider.md +14 -8
  52. package/src/components/form/docs/README-FormUpload.md +79 -0
  53. package/src/components/form/docs/README-FormUploadImage.md +19 -0
  54. package/src/components/form/docs/README-FormUploadVideo.md +19 -0
  55. package/src/components/page-layout/README.md +15 -0
  56. package/src/components/page-layout/docs/README-AppPageDetail.md +3 -0
  57. package/src/components/page-layout/docs/README-AppPageListDetailLayout.md +33 -0
  58. package/src/components/table/docs/README-TableMain.md +17 -0
  59. package/src/components/view-layout/README.md +2 -2
  60. package/src/components/view-layout/docs/README-ViewLayout.md +97 -6
  61. package/types/bridge/badge.d.ts +3 -1
  62. package/types/bridge/layout.d.ts +42 -5
  63. package/types/components/app-layout/AppSidebar.vue.d.ts +286 -2
  64. package/types/components/app-layout/types.d.ts +1 -1
  65. package/types/components/data-view/DataListViewItem.vue.d.ts +12 -7
  66. package/types/components/data-view/types.d.ts +76 -0
  67. package/types/components/data-view/use-grid-layout.d.ts +42 -0
  68. package/types/components/data-view/use-masonry.d.ts +44 -0
  69. package/types/components/display/BadgeMark.vue.d.ts +5 -5
  70. package/types/components/display/HeightProvider.vue.d.ts +1 -0
  71. package/types/components/display/use-badge.d.ts +6 -0
  72. package/types/components/page-layout/AppPageDetail.vue.d.ts +18 -0
  73. package/types/components/page-layout/AppPageListDetailLayout.vue.d.ts +20 -0
  74. package/types/components/page-layout/AppPageListDetailSheet.vue.d.ts +4 -0
  75. package/types/components/page-layout/AppPageListDetailSplit.vue.d.ts +4 -0
  76. package/types/components/table/types.d.ts +8 -0
  77. package/types/components/view-layout/ViewLayout.vue.d.ts +30 -0
  78. package/types/components/view-layout/types.d.ts +12 -0
  79. package/types/hooks/use-surface.d.ts +11 -0
  80. package/types/index.d.ts +0 -1
  81. package/types/injectInfo.json.d.ts +1 -1
  82. package/es/components/icon/IconHammer.vue.mjs +0 -26
  83. package/es/components/icon/IconHammer.vue2.mjs +0 -4
  84. package/src/components/icon/README.md +0 -38
  85. package/types/components/icon/IconHammer.vue.d.ts +0 -2
  86. package/types/components/icon/index.d.ts +0 -7
@@ -9,6 +9,20 @@ import { ElTableColumnProps, TableApiParams, TableApiResult, TableColumnDefaultS
9
9
  * 未配置的断点回落 ≤ 当前断点最近一档(el-col 心智),全无则用全局 span。
10
10
  */
11
11
  export type GridColumnsConfig = Partial<Record<Breakpoint, number>>;
12
+ /**
13
+ * 流体列宽:列数由**容器宽**自然得出(`repeat(auto-fill, minmax(min px, 1fr))`),不需要断点表。
14
+ * 消费方 2026-09-02 拍板过「列数按容器宽流体、[MUST NOT] 钉死」。
15
+ *
16
+ * ⚠️ 仅**无虚拟化**的路径(`DataListView`)支持:`DataGridView` 要按列数把存量 chunk 成
17
+ * 等长的行做虚拟化,而本档的列数是浏览器算的、JS 拿不到 ⇒ 那条路径的 `gridColumns`
18
+ * [MUST NOT] 放开本形态。
19
+ */
20
+ export interface DataViewFluidColumns {
21
+ /** 单列最小宽(px) */
22
+ min: number;
23
+ }
24
+ /** 卡片网格列数配置的全部形态(数字定列 / 断点表 / 流体) */
25
+ export type DataViewGridColumns = number | GridColumnsConfig | DataViewFluidColumns;
12
26
  /**
13
27
  * DataListView 字段渲染作用域
14
28
  * ---
@@ -48,6 +62,36 @@ export interface DataListViewProps<T extends Record<string, any>, F extends Reco
48
62
  maxHeight?: number;
49
63
  /** 最小高度;传入时容器撑满至此高(配合 TableMain fillHeight 顶分页器到底),缺省不设 */
50
64
  minHeight?: number;
65
+ /**
66
+ * 卡片网格列数。**不传 = 不成网格**(单列流式,与本能力引入前逐字一致)。
67
+ * - `number`:定列数 `repeat(N, 1fr)`;
68
+ * - 对象断点表:el-col span 制 24 栅格(与 `DataGridView` **同语义同实现**,
69
+ * 未配档回落 ≤ 当前断点最近一档);
70
+ * - `{ min: N }`:**流体列宽** `repeat(auto-fill, minmax(Npx, 1fr))`,列数由容器宽自然得出。
71
+ *
72
+ * 🔴 [MUST NOT] 在消费侧再手写 `:deep(.data-list-view){display:grid;…}` ——
73
+ * 本 prop 存在的理由正是收掉那 15 份重复。
74
+ */
75
+ gridColumns?: DataViewGridColumns;
76
+ /**
77
+ * item 间距(px)。缺省取间距阶梯的**模块档**(`gap.size × 密度 × 1`,默认 8)——
78
+ * grid 的 gap 是**卡与卡之间**,正是模块档的定义值。
79
+ * [MUST NOT] 在消费侧写死像素补偿(改 gap 基数 / 换密度档时会脱钩)。
80
+ */
81
+ gap?: number;
82
+ /**
83
+ * 内置卡壳(默认 `true`):border + radius + padding,全走 token,落在
84
+ * `.data-list-view-item` 上([MUST NOT] 另包一层,见该组件注释)。
85
+ * 自带卡片视觉时传 `false`,[MUST NOT] 在自己的卡上再画一层边框叠上去。
86
+ */
87
+ card?: boolean;
88
+ /**
89
+ * 瀑布流装箱(默认 `false`)。开启后卡片按实测高度跨行装箱,**顺序仍是行优先(横向)**。
90
+ * 🔴 默认关的依据是「需要 JS 就默认不开」—— 纯 CSS 三条路都死(`columns` 竖着填会打乱
91
+ * 排序、`masonry` 规范未定稿 Chrome 不支持、`grid-row: span` 仍要先知道像素高)。
92
+ * ⚠️ `DataGridView` **不提供**本能力:它按列数 chunk 成等高行做虚拟化,与瀑布流冲突。
93
+ */
94
+ masonry?: boolean;
51
95
  /** 是否启用选中能力,缺省关闭 */
52
96
  selectable?: boolean;
53
97
  /** 获取column 列 上下文 render参数 */
@@ -133,6 +177,14 @@ export interface InfiniteListViewProps<T extends Record<string, any> = Record<st
133
177
  * 详见 `hooks/use-surface.ts`。
134
178
  */
135
179
  surface?: boolean;
180
+ /**
181
+ * **项自己已经成卡**(面与面不叠,p4wrtn)。为真时容器**只撤面色、不撤呼吸与圆角** ——
182
+ * 呼吸计入高度账(与可用高扣减同源),撤了会连带改 refine 的 reserve。
183
+ *
184
+ * 🔴 判据 [MUST NOT] 收窄成「`card === true`」:`InfiniteListView` 没有 `card`
185
+ * (卡由消费方自画),那样写会整条漏掉它。
186
+ */
187
+ itemCard?: boolean;
136
188
  /** 传入时容器限高滚动(内部 overflowY: auto);数字 = px,字符串 = CSS 长度(如 "100vh") */
137
189
  maxHeight?: number | string;
138
190
  /** opt-in 触摸下拉刷新(默认关) */
@@ -167,12 +219,36 @@ export interface DataGridViewProps<T extends Record<string, any>, SQ extends Rec
167
219
  * (24 栅格,如 `{ xs: 24, sm: 12, md: 8, lg: 6, xl: 4 }`,列数 = 24 / span)。
168
220
  */
169
221
  gridColumns?: number | GridColumnsConfig;
222
+ /**
223
+ * item 间距(px,横纵同值)。缺省取间距阶梯的**模块档**(默认 8),与 `DataListView` 同源。
224
+ *
225
+ * ⚠️ **原先写死 `12`**(连同行间距的 `padding-bottom`)—— 那是**呼吸档**(卡片内边距)
226
+ * 的值,用在「卡与卡之间」是档位用错;归位到模块档后同时接上 density 缩放。
227
+ * 老页面观感会紧 4px,[MUST] 在 migrations 登记(显式传 `12` 可维持旧观感)。
228
+ */
229
+ gap?: number;
230
+ /**
231
+ * 内置卡壳(默认 `true`):border + radius + padding,走 token。
232
+ *
233
+ * 🔴 **壳已从插槽 fallback 内移到 `.data-grid-view__cell`** —— 原实现只在
234
+ * 「没给 `#custom-view-item`」时才有壳,而真实业务几乎总要给插槽 ⇒ 一给插槽就没壳。
235
+ * 落在 cell 上后**给不给插槽都有壳**,且 DOM 层级恒定(消费方的 `:deep()` 不会跟着变)。
236
+ */
237
+ card?: boolean;
170
238
  /**
171
239
  * 自持面(默认 `true`):面色 + 内呼吸 + 圆角,单独用也观感一致。
172
240
  * 置于 `ModalConfirm` 正文时经上下文自动取 `false`;显式传值恒优先。
173
241
  * 详见 `hooks/use-surface.ts`。
174
242
  */
175
243
  surface?: boolean;
244
+ /**
245
+ * **项自己已经成卡**(面与面不叠,p4wrtn)。为真时容器**只撤面色、不撤呼吸与圆角** ——
246
+ * 呼吸计入高度账(与可用高扣减同源),撤了会连带改 refine 的 reserve。
247
+ *
248
+ * 🔴 判据 [MUST NOT] 收窄成「`card === true`」:`InfiniteListView` 没有 `card`
249
+ * (卡由消费方自画),那样写会整条漏掉它。
250
+ */
251
+ itemCard?: boolean;
176
252
  /**
177
253
  * 数据区最大高度;与 refine 二选一作为高度基准。
178
254
  * 数字 = px;字符串 = CSS 长度(默认 "100vh" = 满视口高,等价视口高度限高,
@@ -0,0 +1,42 @@
1
+ import { ComputedRef, CSSProperties } from 'vue';
2
+ import { DataViewGridColumns } from './types';
3
+ /** {@link useDataViewGridLayout} 入参(全部惰性 getter,保持响应式) */
4
+ export interface UseDataViewGridLayoutOptions {
5
+ /** 列数配置;`undefined` = 不成网格 */
6
+ gridColumns: () => DataViewGridColumns | undefined;
7
+ /** 显式间距(px);`undefined` = 取间距阶梯模块档 */
8
+ gap: () => number | undefined;
9
+ }
10
+ /** {@link useDataViewGridLayout} 返回 */
11
+ export interface UseDataViewGridLayoutReturn {
12
+ /** 生效间距(px):显式 `gap` > 间距阶梯**模块档** */
13
+ gridGap: ComputedRef<number>;
14
+ /** `grid-template-columns` 值;`gridColumns` 未传 → `undefined` */
15
+ gridTemplateColumns: ComputedRef<string | undefined>;
16
+ /** 网格容器样式;不成网格时 `undefined`(调用方原样透给 `:style`) */
17
+ gridStyle: ComputedRef<CSSProperties | undefined>;
18
+ /**
19
+ * 内置卡壳的内呼吸(px)= 间距阶梯的**呼吸档**(×1.5,默认 12)。
20
+ * 🔴 [MUST NOT] 改读 `--dc-core-content-gap` —— 那是 huhyx7 明令废掉的第二来源,
21
+ * 与 gap 各随不同轴变动,最松密度档会出现「卡内 20 ≥ 外圈 20 > 卡间 8」的乱序。
22
+ * 与 `hooks/use-surface.ts` 同档同源(数据区自持面的内呼吸也是这一档)。
23
+ */
24
+ cardPad: ComputedRef<number>;
25
+ }
26
+ /**
27
+ * 卡片网格布局(两条卡片路径共用)——列数 + 间距的**唯一解析口**。
28
+ *
29
+ * 🔴 **存在的理由 = 两条路径的语义必须逐字一致**:`DataGridView`(存量累加)与
30
+ * `DataListView`(分页)都要「按断点算列数」,各写一份必然漂移 —— 同一个页面切
31
+ * viewMode 时列数会跳。断点换算复用 `resolveGridColumnsByBreakpoint`(el-col span 制
32
+ * 24 栅格),[MUST NOT] 在任一路径另造一套。
33
+ *
34
+ * **间距缺省取「模块档」(×1,默认 8)而非历史写死的 12**:`grid` 的 gap 是
35
+ * **卡与卡之间**,正是间距阶梯里模块档的定义;写死的 12 是**呼吸档**(卡片内边距)的值,
36
+ * 属档位用错。归位后同时接上 density 缩放(compact/cozy/comfortable ×0.75/×1/×1.5)。
37
+ *
38
+ * ⚠️ **流体档 `{ min }` 只该给无虚拟化的路径用**:它的列数由浏览器算、JS 拿不到,
39
+ * 而 `DataGridView` 要按列数把存量 chunk 成等长的行做虚拟化 ⇒ 那条路径 [MUST NOT] 放开它
40
+ * (类型层已在各自 props 上收窄,本函数只负责「给了就认」)。
41
+ */
42
+ export declare const useDataViewGridLayout: (options: UseDataViewGridLayoutOptions) => UseDataViewGridLayoutReturn;
@@ -0,0 +1,44 @@
1
+ import { CSSProperties, Ref } from 'vue';
2
+ /** {@link useDataViewMasonry} 入参(全部惰性 getter,保持响应式) */
3
+ export interface UseDataViewMasonryOptions {
4
+ /** 开关(`props.masonry`);关时本 hook 恒等于不存在 */
5
+ enabled: () => boolean;
6
+ /** 网格容器元素 */
7
+ container: () => HTMLElement | undefined;
8
+ /** 生效间距(px),与网格的 gap 同源 */
9
+ gap: () => number;
10
+ /** 数据引用(变了即重测——翻页 / 换筛选) */
11
+ data: () => unknown;
12
+ }
13
+ /** {@link useDataViewMasonry} 返回 */
14
+ export interface UseDataViewMasonryReturn {
15
+ /** 各项跨度(按 DOM 序);未测到的项为 `undefined`,由 CSS 兜底跨度接住 */
16
+ masonrySpans: Ref<(number | undefined)[]>;
17
+ /** 容器附加样式;关闭时 `undefined` */
18
+ masonryContainerStyle: Ref<CSSProperties | undefined>;
19
+ }
20
+ /**
21
+ * 瀑布流装箱(非主干增强,规则 22 同级 hook 收纳)——删除本功能 =
22
+ * 删本文件 + 组件里那行委托 + 模板挂点,主干零残留。
23
+ *
24
+ * **为什么是 JS**(条目已实证,[MUST NOT] 再判一遍):`columns` 多列**竖着填**
25
+ * (1,2,3 落第一列),按时间 / 热度排序的列表会被打乱顺序;`masonry` 规范未定稿、
26
+ * Chrome 不支持;`grid-row: span N` 的跨度是整数行,仍要先知道卡片像素高。
27
+ * ⇒ 走 `grid-auto-rows: <单位>` + 每项 `grid-row-end: span N`,**顺序仍是行优先**。
28
+ *
29
+ * 🔴 **五个坑的守法**(全都不报错、只表现为「看着有点怪」):
30
+ * 1. **重叠** —— 没拿到跨度的项默认只占 1 行。守法 = CSS 给**兜底跨度**(见组件样式),
31
+ * 本 hook 对未测到的项返回 `undefined`(不写 inline span)⇒ 退回那条兜底。
32
+ * 增强失败只该「不够好看」,[MUST NOT] 变成布局坏掉。
33
+ * 2. **跨度永远不写** —— 容器在数据到达前后被换成另一个元素,挂载时抓的 ref 成了游离节点。
34
+ * 守法 = 容器走 **getter 每次现读**,[MUST NOT] 在 setup 里把 el 存成常量。
35
+ * 3. **跨度写了不生效** —— 写在卡片上而网格项是外层盒。本仓内部实现**自己就持有网格项**
36
+ * (`.data-list-view-item`),跨度直接写它身上 ⇒ 这条坑在此天然不存在。
37
+ * 4. **卡底多一截空白** —— 用「列宽 × 比例 + 文字区估值」算高会飘。守法 = **直接量**
38
+ * 项的实际高度。⚠️ 量的前提是项**不被拉伸**:组件在瀑布流态给项 `align-self: start`,
39
+ * 否则项盒会被撑满跨度区域、量出来的恒等于写进去的 ⇒ 自我循环、永不收敛。
40
+ * 5. **翻页后新卡全用兜底** —— 观察者挂上**之前**已插入的那批永远不会被报告。
41
+ * 守法 = 每次重测都**重新遍历当前子节点并重新 observe**(`observe` 对同一元素幂等),
42
+ * 且 `data` 变化后 `nextTick` 立刻补跑一次。
43
+ */
44
+ export declare const useDataViewMasonry: (options: UseDataViewMasonryOptions) => UseDataViewMasonryReturn;
@@ -1,4 +1,4 @@
1
- import { ComponentPublicInstance } from 'vue';
1
+ import { CSSProperties, ComponentPublicInstance } from 'vue';
2
2
  import { BadgeKeyInput } from './use-badge';
3
3
  type __VLS_Props = {
4
4
  /**
@@ -83,7 +83,7 @@ declare function __VLS_template(): {
83
83
  value: string | number;
84
84
  max: number;
85
85
  showZero: boolean;
86
- badgeStyle: string | false | import('vue').CSSProperties | import('vue').StyleValue[] | null;
86
+ badgeStyle: string | false | CSSProperties | import('vue').StyleValue[] | null;
87
87
  }, {}, string, {}, import('vue').GlobalComponents, import('vue').GlobalDirectives, string, import('vue').ComponentProvideOptions> & {
88
88
  beforeCreate?: (() => void) | (() => void)[];
89
89
  created?: (() => void) | (() => void)[];
@@ -110,7 +110,7 @@ declare function __VLS_template(): {
110
110
  value: string | number;
111
111
  max: number;
112
112
  showZero: boolean;
113
- badgeStyle: string | false | import('vue').CSSProperties | import('vue').StyleValue[] | null;
113
+ badgeStyle: string | false | CSSProperties | import('vue').StyleValue[] | null;
114
114
  }> & Omit<Readonly<import('element-plus').BadgeProps> & Readonly<{}>, "offset" | "type" | "value" | "max" | "content" | "showZero" | "badgeStyle"> & {
115
115
  content: string;
116
116
  } & {} & import('vue').ComponentCustomProperties & {} & {
@@ -162,7 +162,7 @@ declare const __VLS_component: import('vue').DefineComponent<__VLS_Props, {}, {}
162
162
  value: string | number;
163
163
  max: number;
164
164
  showZero: boolean;
165
- badgeStyle: string | false | import('vue').CSSProperties | import('vue').StyleValue[] | null;
165
+ badgeStyle: string | false | CSSProperties | import('vue').StyleValue[] | null;
166
166
  }, {}, string, {}, import('vue').GlobalComponents, import('vue').GlobalDirectives, string, import('vue').ComponentProvideOptions> & {
167
167
  beforeCreate?: (() => void) | (() => void)[];
168
168
  created?: (() => void) | (() => void)[];
@@ -189,7 +189,7 @@ declare const __VLS_component: import('vue').DefineComponent<__VLS_Props, {}, {}
189
189
  value: string | number;
190
190
  max: number;
191
191
  showZero: boolean;
192
- badgeStyle: string | false | import('vue').CSSProperties | import('vue').StyleValue[] | null;
192
+ badgeStyle: string | false | CSSProperties | import('vue').StyleValue[] | null;
193
193
  }> & Omit<Readonly<import('element-plus').BadgeProps> & Readonly<{}>, "offset" | "type" | "value" | "max" | "content" | "showZero" | "badgeStyle"> & {
194
194
  content: string;
195
195
  } & {} & import('vue').ComponentCustomProperties & {} & {
@@ -6,6 +6,7 @@ declare function __VLS_template(): {
6
6
  default?(_: {
7
7
  viewportHeight: number;
8
8
  }): any;
9
+ footer?(_: {}): any;
9
10
  };
10
11
  refs: {};
11
12
  rootEl: any;
@@ -36,6 +36,12 @@ export interface BadgeResolved {
36
36
  icon?: Component;
37
37
  /** 完整文案——图标档的悬浮气泡用它把语义补回来 */
38
38
  label?: string;
39
+ /**
40
+ * 图标缩放(逐档可选,1 = 原尺寸)。
41
+ * 🔴 [MUST] 留在**预设的逐档字段**里,[MUST NOT] 提成全局常量或只给某一档打补丁 ——
42
+ * 七档全图标化之后,后续还会有别的档需要同样处理(甲方 2026-09-18 明示)。
43
+ */
44
+ iconScale?: number;
39
45
  /**
40
46
  * 纯锚点档(`kind: "anchor"`):角标**不显示**,但 DOM 挂点照常渲染。
41
47
  *
@@ -31,9 +31,27 @@ declare const _default: <T extends Record<string, any>, R = any>(__VLS_props: No
31
31
  attrs: any;
32
32
  slots: Readonly<{
33
33
  detail?: (scope: AppPageListDetailDetailScope<T, R>) => unknown;
34
+ /**
35
+ * 详情区**内部底边**(透到内置 `ViewLayout` 的 `#bottom`):`refine` 开时钉在底、
36
+ * 不随内容滚 —— 放「提交 / 审核这一条」的固定操作条。scope 与 `#detail` 完全一致。
37
+ *
38
+ * 🔴 **前提是传了 `detailApi`**:本槽透到的是内置 `ViewLayout`,不传 `detailApi` 就没有
39
+ * 那个容器 ⇒ 本槽无落点(与 `viewLayoutProps` 同一条边界)。详情数据业务自持时,
40
+ * 底部条自己写在 `#detail` 末尾。
41
+ */
42
+ detailBottom?: (scope: AppPageListDetailDetailScope<T, R>) => unknown;
34
43
  empty?: (scope: AppPageListDetailEmptyScope) => unknown;
35
44
  }> & {
36
45
  detail?: (scope: AppPageListDetailDetailScope<T, R>) => unknown;
46
+ /**
47
+ * 详情区**内部底边**(透到内置 `ViewLayout` 的 `#bottom`):`refine` 开时钉在底、
48
+ * 不随内容滚 —— 放「提交 / 审核这一条」的固定操作条。scope 与 `#detail` 完全一致。
49
+ *
50
+ * 🔴 **前提是传了 `detailApi`**:本槽透到的是内置 `ViewLayout`,不传 `detailApi` 就没有
51
+ * 那个容器 ⇒ 本槽无落点(与 `viewLayoutProps` 同一条边界)。详情数据业务自持时,
52
+ * 底部条自己写在 `#detail` 末尾。
53
+ */
54
+ detailBottom?: (scope: AppPageListDetailDetailScope<T, R>) => unknown;
37
55
  empty?: (scope: AppPageListDetailEmptyScope) => unknown;
38
56
  };
39
57
  emit: {};
@@ -13,6 +13,16 @@ declare const _default: <T extends Record<string, any>, R = any>(__VLS_props: No
13
13
  slots: Readonly<{
14
14
  list?: (scope: AppPageListDetailListScope<T>) => unknown;
15
15
  detail?: (scope: AppPageListDetailDetailScope<T, R>) => unknown;
16
+ /**
17
+ * 详情区**内部底边** —— 逐层透到内置 `ViewLayout` 的 `#bottom`:
18
+ * split 档钉在详情区底 / sheet 档钉在抽屉底,内容再长也不滚走。放「提交 / 审核**这一条**」
19
+ * 的固定操作条,scope 与 `#detail` 完全一致(含 `id` / `record` / 导航句柄)。
20
+ *
21
+ * 🔴 与下面的 `#bottom` **同名不同物**:那个挂在 `AppPage` 上、是**页面级**四向悬浮槽
22
+ * (覆盖整页底边,列表也在它上方)。判据:对「当前这一条」的操作放本槽,对整页的放 `#bottom`。
23
+ * 前提是传了 `detailApi`(本槽透到的是内置 `ViewLayout`,没有它就没有那个容器)。
24
+ */
25
+ detailBottom?: (scope: AppPageListDetailDetailScope<T, R>) => unknown;
16
26
  empty?: (scope: AppPageListDetailEmptyScope) => unknown;
17
27
  top?: () => unknown;
18
28
  bottom?: () => unknown;
@@ -20,6 +30,16 @@ declare const _default: <T extends Record<string, any>, R = any>(__VLS_props: No
20
30
  }> & {
21
31
  list?: (scope: AppPageListDetailListScope<T>) => unknown;
22
32
  detail?: (scope: AppPageListDetailDetailScope<T, R>) => unknown;
33
+ /**
34
+ * 详情区**内部底边** —— 逐层透到内置 `ViewLayout` 的 `#bottom`:
35
+ * split 档钉在详情区底 / sheet 档钉在抽屉底,内容再长也不滚走。放「提交 / 审核**这一条**」
36
+ * 的固定操作条,scope 与 `#detail` 完全一致(含 `id` / `record` / 导航句柄)。
37
+ *
38
+ * 🔴 与下面的 `#bottom` **同名不同物**:那个挂在 `AppPage` 上、是**页面级**四向悬浮槽
39
+ * (覆盖整页底边,列表也在它上方)。判据:对「当前这一条」的操作放本槽,对整页的放 `#bottom`。
40
+ * 前提是传了 `detailApi`(本槽透到的是内置 `ViewLayout`,没有它就没有那个容器)。
41
+ */
42
+ detailBottom?: (scope: AppPageListDetailDetailScope<T, R>) => unknown;
23
43
  empty?: (scope: AppPageListDetailEmptyScope) => unknown;
24
44
  top?: () => unknown;
25
45
  bottom?: () => unknown;
@@ -19,6 +19,8 @@ declare const _default: <T extends Record<string, any>, R = any>(__VLS_props: No
19
19
  slots: Readonly<{
20
20
  list?: (scope: Omit<AppPageListDetailListScope<T>, "resolvedMode">) => unknown;
21
21
  detail?: (scope: AppPageListDetailDetailScope<T, R>) => unknown;
22
+ /** 详情区内部底边(透到 `AppPageDetail` → `ViewLayout#bottom`);scope 同 `#detail` */
23
+ detailBottom?: (scope: AppPageListDetailDetailScope<T, R>) => unknown;
22
24
  empty?: (scope: AppPageListDetailEmptyScope) => unknown;
23
25
  top?: () => unknown;
24
26
  bottom?: () => unknown;
@@ -26,6 +28,8 @@ declare const _default: <T extends Record<string, any>, R = any>(__VLS_props: No
26
28
  }> & {
27
29
  list?: (scope: Omit<AppPageListDetailListScope<T>, "resolvedMode">) => unknown;
28
30
  detail?: (scope: AppPageListDetailDetailScope<T, R>) => unknown;
31
+ /** 详情区内部底边(透到 `AppPageDetail` → `ViewLayout#bottom`);scope 同 `#detail` */
32
+ detailBottom?: (scope: AppPageListDetailDetailScope<T, R>) => unknown;
29
33
  empty?: (scope: AppPageListDetailEmptyScope) => unknown;
30
34
  top?: () => unknown;
31
35
  bottom?: () => unknown;
@@ -22,6 +22,8 @@ declare const _default: <T extends Record<string, any>, R = any>(__VLS_props: No
22
22
  slots: Readonly<{
23
23
  list?: (scope: Omit<AppPageListDetailListScope<T>, "resolvedMode">) => unknown;
24
24
  detail?: (scope: AppPageListDetailDetailScope<T, R>) => unknown;
25
+ /** 详情区内部底边(透到 `AppPageDetail` → `ViewLayout#bottom`);scope 同 `#detail` */
26
+ detailBottom?: (scope: AppPageListDetailDetailScope<T, R>) => unknown;
25
27
  empty?: (scope: AppPageListDetailEmptyScope) => unknown;
26
28
  top?: () => unknown;
27
29
  bottom?: () => unknown;
@@ -29,6 +31,8 @@ declare const _default: <T extends Record<string, any>, R = any>(__VLS_props: No
29
31
  }> & {
30
32
  list?: (scope: Omit<AppPageListDetailListScope<T>, "resolvedMode">) => unknown;
31
33
  detail?: (scope: AppPageListDetailDetailScope<T, R>) => unknown;
34
+ /** 详情区内部底边(透到 `AppPageDetail` → `ViewLayout#bottom`);scope 同 `#detail` */
35
+ detailBottom?: (scope: AppPageListDetailDetailScope<T, R>) => unknown;
32
36
  empty?: (scope: AppPageListDetailEmptyScope) => unknown;
33
37
  top?: () => unknown;
34
38
  bottom?: () => unknown;
@@ -200,6 +200,14 @@ F extends Record<string, any>> {
200
200
  * 暗色下二次成面会凹);显式传值恒优先。
201
201
  */
202
202
  surface?: boolean;
203
+ /**
204
+ * **项自己已经成卡**(面与面不叠,p4wrtn)。为真时容器**只撤面色、不撤呼吸与圆角** ——
205
+ * 呼吸计入高度账(与可用高扣减同源),撤了会连带改 refine 的 reserve。
206
+ *
207
+ * 🔴 判据 [MUST NOT] 收窄成「`card === true`」:`InfiniteListView` 没有 `card`
208
+ * (卡由消费方自画),那样写会整条漏掉它。
209
+ */
210
+ itemCard?: boolean;
203
211
  /** 展示分页器 */
204
212
  showPager?: boolean;
205
213
  /**
@@ -19,6 +19,21 @@ declare const _default: <P extends Record<string, any> = Record<string, any>, R
19
19
  data: R | undefined;
20
20
  loading: boolean;
21
21
  }) => VNode[];
22
+ /**
23
+ * 底部区插槽;不传即完全不渲染([MUST NOT] 留空盒占 reserve)。
24
+ * - `refine` 开 → 进 `HeightProvider` 的 `#footer` 槽:**固定在底部**,量高计入 reserve;
25
+ * - `refine` 关 → **平铺**在内容之后,按自身尺寸排布。
26
+ * scope = `{ data, loading, fetchSeq }`(三者都是本组件拉取的产物,setup 里取不到,
27
+ * [MUST] 由 scope 下发)。比 `#header` 多一个 `fetchSeq`:本槽是**放操作条**的地方,
28
+ * 提交后常要判「详情真的重拉成功了」(失败不递增,[MUST NOT] 用 `loading` 的
29
+ * `true→false` 代替);也让 `AppPageListDetailLayout` 的 `#detailBottom` 能原样复用
30
+ * `#detail` 那份 scope,[MUST NOT] 为凑类型编一个恒 0 的假 `fetchSeq`。
31
+ */
32
+ bottom?: (scope: {
33
+ data: R | undefined;
34
+ loading: boolean;
35
+ fetchSeq: number;
36
+ }) => VNode[];
22
37
  }> & {
23
38
  default: (scope: ViewLayoutScope<R>) => VNode[];
24
39
  /**
@@ -30,6 +45,21 @@ declare const _default: <P extends Record<string, any> = Record<string, any>, R
30
45
  data: R | undefined;
31
46
  loading: boolean;
32
47
  }) => VNode[];
48
+ /**
49
+ * 底部区插槽;不传即完全不渲染([MUST NOT] 留空盒占 reserve)。
50
+ * - `refine` 开 → 进 `HeightProvider` 的 `#footer` 槽:**固定在底部**,量高计入 reserve;
51
+ * - `refine` 关 → **平铺**在内容之后,按自身尺寸排布。
52
+ * scope = `{ data, loading, fetchSeq }`(三者都是本组件拉取的产物,setup 里取不到,
53
+ * [MUST] 由 scope 下发)。比 `#header` 多一个 `fetchSeq`:本槽是**放操作条**的地方,
54
+ * 提交后常要判「详情真的重拉成功了」(失败不递增,[MUST NOT] 用 `loading` 的
55
+ * `true→false` 代替);也让 `AppPageListDetailLayout` 的 `#detailBottom` 能原样复用
56
+ * `#detail` 那份 scope,[MUST NOT] 为凑类型编一个恒 0 的假 `fetchSeq`。
57
+ */
58
+ bottom?: (scope: {
59
+ data: R | undefined;
60
+ loading: boolean;
61
+ fetchSeq: number;
62
+ }) => VNode[];
33
63
  };
34
64
  emit: (evt: "update:isAutoRefresh", value: boolean) => void;
35
65
  }>) => import('vue').VNode & {
@@ -87,6 +87,18 @@ export interface ViewLayoutProps<P = Record<string, any>, R = any> {
87
87
  parentChannel?: string;
88
88
  /** 内容区可用高兜底下限(px) */
89
89
  minHeight?: number;
90
+ /**
91
+ * 内容盒**撑满可用高**(默认 `false`,仅 `refine=true` 时有意义)。
92
+ *
93
+ * 关(默认):内容盒只有 `max-height` 上限,内容多短盒子就多矮 —— 与本 prop 引入前逐字一致。
94
+ * 开:额外补一条同值 `min-height` ⇒ 上下界重合 = 定高。用途 = **让 `#bottom` 贴容器底**:
95
+ * 上限式下内容稀疏时底边只能跟在内容屁股后面浮在半空,定高后它恒落在预算下沿。
96
+ *
97
+ * 同名同义于 `TableMain.fillHeight`(那边是让分页器被顶到容器底),[MUST NOT] 另造名字。
98
+ * ⚠️ 代价是内容短时盒内留白 —— 这是定高的一体两面,故设计成 **opt-in**:
99
+ * [MUST NOT] 改成默认开 / 改写 `max-height` 为 `height`,那会波及所有 refine 页面。
100
+ */
101
+ fillHeight?: boolean;
90
102
  /** 是否显示自动刷新开关(默认 true) */
91
103
  showAutoRefresh?: boolean;
92
104
  /** 是否显示手动刷新按钮(默认 true) */
@@ -3,6 +3,16 @@ import { ComputedRef } from 'vue';
3
3
  export interface UseSurfaceReturn {
4
4
  /** 最终是否成面(显式 prop > 上下文推导 > 默认 true) */
5
5
  surfaceActive: ComputedRef<boolean>;
6
+ /**
7
+ * 是否**铺面色**(= 成面 且 项自己没成卡)。
8
+ *
9
+ * 🔴 **面与面不叠**(p4wrtn):项自带卡片时容器再铺一层同色面,gap 漏出的就是与卡片
10
+ * **同一个色**,视觉上「一整片白 + 若干 1px 细框」,卡片不成其为卡片(实测两处
11
+ * `backgroundColor` 完全相同)。故项成卡时**只撤色、不撤呼吸** ——
12
+ * 🔴 [MUST NOT] 连 `surfacePad` 一起撤:呼吸计入高度账(与可用高扣减同源),
13
+ * 撤了会连带改 refine 的 reserve、整页溢出。
14
+ */
15
+ surfaceBgActive: ComputedRef<boolean>;
6
16
  /** 卡内呼吸数值(px);关面时 0。样式与高度账**共用此一处** */
7
17
  surfacePad: ComputedRef<number>;
8
18
  /** 呼吸的 px 串(供 scoped CSS `v-bind`),与 {@link UseSurfaceReturn.surfacePad} 同源 */
@@ -31,4 +41,5 @@ export interface UseSurfaceReturn {
31
41
  */
32
42
  export declare const useSurface: <P extends {
33
43
  surface?: boolean;
44
+ itemCard?: boolean;
34
45
  }>(getProps: () => P) => UseSurfaceReturn;
package/types/index.d.ts CHANGED
@@ -3,7 +3,6 @@ export { InfiniteListView, DataGridView } from './components/data-view';
3
3
  export type { DataGridViewInstance, DataGridViewPageInfo, DataGridViewProps, InfiniteListViewConfig, InfiniteListViewInstance, InfiniteListViewProps, } from './components/data-view';
4
4
  export * from './components/menu';
5
5
  export * from './components/display';
6
- export * from './components/icon';
7
6
  export * from './components/misc';
8
7
  export * from './components/modal';
9
8
  export * from './components/table';
@@ -1,6 +1,6 @@
1
1
  declare const _default: {
2
2
  "name": "@done-coding/admin-core",
3
- "version": "0.28.1-alpha.0",
3
+ "version": "0.29.1-alpha.0",
4
4
  "description": "内部前端库"
5
5
  };
6
6
 
@@ -1,26 +0,0 @@
1
- import { defineComponent, openBlock, createElementBlock, createElementVNode } from "vue";
2
- const _hoisted_1 = {
3
- class: "dc-icon-hammer icon-hammer",
4
- viewBox: "0 0 16 16",
5
- width: "1em",
6
- height: "1em",
7
- xmlns: "http://www.w3.org/2000/svg",
8
- "aria-hidden": "true",
9
- focusable: "false"
10
- };
11
- const _sfc_main = /* @__PURE__ */ defineComponent({
12
- __name: "IconHammer",
13
- setup(__props) {
14
- return (_ctx, _cache) => {
15
- return openBlock(), createElementBlock("svg", _hoisted_1, [..._cache[0] || (_cache[0] = [
16
- createElementVNode("path", {
17
- fill: "currentColor",
18
- d: "M9.972 2.508a.5.5 0 0 0-.16-.556l-.178-.129a5 5 0 0 0-2.076-.783C6.215.862 4.504 1.229 2.84 3.133H1.786a.5.5 0 0 0-.354.147L.146 4.567a.5.5 0 0 0 0 .706l2.571 2.579a.5.5 0 0 0 .708 0l1.286-1.29a.5.5 0 0 0 .146-.353V5.57l8.387 8.873A.5.5 0 0 0 14 14.5l1.5-1.5a.5.5 0 0 0 .017-.689l-9.129-8.63c.747-.456 1.772-.839 3.112-.839a.5.5 0 0 0 .472-.334"
19
- }, null, -1)
20
- ])]);
21
- };
22
- }
23
- });
24
- export {
25
- _sfc_main as default
26
- };
@@ -1,4 +0,0 @@
1
- import _sfc_main from "./IconHammer.vue.mjs";
2
- export {
3
- _sfc_main as default
4
- };
@@ -1,38 +0,0 @@
1
- # components/icon — 图标族
2
-
3
- core 自带的图标组件族。**只收 element-plus 图标集缺失、且语义上非它不可的那几个**——
4
- [MUST NOT] 把 EP 已有的图标在这里再画一遍(那是纯重复,且两套观感会打架)。
5
-
6
- ## 准入判据
7
-
8
- 新增一个图标前 [MUST] 先答这两问:
9
-
10
- 1. **EP 图标集里真的没有吗?** 全量清单见 `@element-plus/icons-vue`。有就直接用 EP 的。
11
- 2. **换一个近似的 EP 图标真的不行吗?** 「近似但会被读错」才算不行(如 `Tools` 被读成设置),
12
- 「不够好看」不算。
13
-
14
- ## 优先取开源图标集的形,[MUST NOT] 手画
15
-
16
- 小尺寸图标的辨识度高度依赖剪影,手画的几何形在 12px 下几乎必然糊(实测:手画的轴对齐
17
- T 形锤被甲方判「太丑」,换成斜置羊角锤即可读)。故 [MUST] 先从成熟开源集(Bootstrap Icons /
18
- Lucide / Material Symbols 等,许可证需 MIT / ISC / Apache-2.0 一类)取被大量验证过的形,
19
- **只抄单条 path、[MUST NOT] 引整包依赖**(我们一次只要一个图标)。
20
-
21
- [MUST] 在组件注释里写明**来源 + 许可证 + 版权行**。风格上优先取 **fill 实心**版本——
22
- EP 图标是实心的,描边版(如 Lucide)在 12px 下偏细、与 EP 混排会打架。
23
-
24
- ## 写作约定
25
-
26
- - **颜色 [MUST] 用 `fill="currentColor"`**:继承父级 `color`,天然随主题风格 / 亮暗 / 语义色档走。
27
- [MUST NOT] 写死色值、[MUST NOT] 自造 CSS 变量(规则 14)。
28
- - **尺寸 [MUST] 用 `width/height="1em"`**:外面套 `ElIcon` 调 `font-size` 即可缩放,
29
- [MUST NOT] 写死 px。`viewBox` **随图标源**,不强求与 EP 的 1024 一致——渲染尺寸由 1em 决定,
30
- 换算坐标只会徒增手抄出错的风险。
31
- - **根元素 [MUST] 带 `dc-<组件名-kebab>` 类**(规则 17),与内部裸类并存。
32
- - `aria-hidden="true"` + `focusable="false"`:图标是装饰,语义由宿主(或悬浮气泡)承担。
33
-
34
- ## 清单
35
-
36
- | 组件 | 用途 | 为什么不用 EP 的 |
37
- |---|---|---|
38
- | `IconHammer` | 施工 / 开发中(`bridge.badge` 的 `wip` 档) | EP 无锤子;最接近的 `Tools` 是扳手+齿轮,被读成「设置」。取自 Bootstrap Icons `hammer`(MIT) |
@@ -1,2 +0,0 @@
1
- declare const _default: import('vue').DefineComponent<{}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, SVGSVGElement>;
2
- export default _default;
@@ -1,7 +0,0 @@
1
- import { default as IconHammer } from './IconHammer.vue';
2
- export {
3
- /**
4
- * 锤子图标(施工 / 开发中)。EP 图标集无锤子,最接近的 `Tools` 会被读成「设置」。
5
- * `currentColor` + `1em`:颜色随父级、尺寸随字号,套 `ElIcon` 即可控。
6
- */
7
- IconHammer, };