@aspire-ui/element-component-pro 1.0.26 → 1.0.28

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/dist/style.css CHANGED
@@ -1 +1 @@
1
- .ecp-pro-table[data-v-d48fd076]{padding:16px;background:#fff;width:100%;box-sizing:border-box}.ecp-pro-table[data-v-d48fd076] .el-table{width:100%!important}.ecp-pro-table__header[data-v-d48fd076]{display:flex;justify-content:space-between;align-items:center;margin-bottom:16px}.ecp-pro-table__title-wrapper[data-v-d48fd076]{display:flex;align-items:center;gap:4px}.ecp-pro-table__title[data-v-d48fd076]{font-size:16px;font-weight:600}.ecp-pro-table__help[data-v-d48fd076]{color:#909399;cursor:help}.ecp-pro-table__toolbar[data-v-d48fd076]{display:flex;align-items:center;gap:8px}.ecp-pro-table__body[data-v-d48fd076]{width:100%}.ecp-pro-table__pagination[data-v-d48fd076]{margin-top:16px;display:flex;justify-content:flex-end}.ecp-pro-table__col-help[data-v-d48fd076]{margin-left:4px;color:#909399;cursor:help}.ecp-table-action[data-v-45a58e7c],.ecp-table-action__item[data-v-45a58e7c]{display:inline-flex;align-items:center;gap:4px}.ecp-table-action__icon[data-v-45a58e7c]{margin-right:4px}.ecp-table-action__more[data-v-45a58e7c]{display:inline-flex;align-items:center}.ecp-table-action__dropdown-item[data-v-45a58e7c]{display:inline-flex;align-items:center;gap:4px}.ecp-tree-select[data-v-f30bba11]{position:relative;width:100%}.ecp-tree-select__filter-inner[data-v-f30bba11]{margin-bottom:8px}.ecp-tree-select__dropdown[data-v-f30bba11]{position:absolute;top:100%;left:0;right:0;max-height:280px;overflow:auto;background:#fff;border:1px solid #dcdfe6;border-radius:4px;margin-top:4px;z-index:1000;padding:8px}.ecp-tree-select__loading[data-v-f30bba11]{padding:24px;text-align:center;color:#909399;font-size:14px}.ecp-pro-form-item__colon[data-v-48d7960b]{margin-right:2px}.ecp-pro-form-item__help-icon[data-v-48d7960b]{margin-left:4px;color:#909399;cursor:help;font-size:14px}.ecp-pro-form-item__help-icon[data-v-48d7960b]:hover{color:#409eff}.ecp-pro-form-item__help-item[data-v-48d7960b]{margin-bottom:4px}.ecp-pro-form-item__help-item[data-v-48d7960b]:last-child{margin-bottom:0}.ecp-form-actions[data-v-489c88d2]{text-align:right}.ecp-form-actions__advance[data-v-489c88d2]{margin-right:8px}.el-icon-d-arrow-left.up[data-v-489c88d2]{transform:rotate(90deg)}.el-icon-d-arrow-left.down[data-v-489c88d2]{transform:rotate(-90deg)}.ecp-pro-form[data-v-cf7b3b35]{padding:16px;position:relative}.ecp-pro-form__advance[data-v-cf7b3b35]{margin-bottom:16px}.ecp-pro-form .ecp-pro-form_col[data-v-cf7b3b35]{position:relative;float:right}.el-icon-d-arrow-left.up[data-v-cf7b3b35]{transform:rotate(90deg)}.el-icon-d-arrow-left.down[data-v-cf7b3b35]{transform:rotate(-90deg)}.ecp-form-actions__advance[data-v-cf7b3b35]{position:absolute;bottom:0;left:50%;transform:translate(-50%,-50%)}.ecp-pro-descriptions[data-v-656036f6]{width:100%;box-sizing:border-box}.ecp-pro-descriptions__header[data-v-656036f6]{display:flex;align-items:center;justify-content:space-between;margin-bottom:12px;gap:12px}.ecp-pro-descriptions__title-wrap[data-v-656036f6]{display:flex;align-items:center;gap:6px}.ecp-pro-descriptions__title[data-v-656036f6]{font-size:16px;font-weight:600;color:#303133}.ecp-pro-descriptions__help[data-v-656036f6],.ecp-pro-descriptions__toggle[data-v-656036f6]{color:#909399}.ecp-pro-descriptions__toggle .el-icon-arrow-down[data-v-656036f6]{margin-left:4px;transition:transform .2s ease}.ecp-pro-descriptions__toggle .el-icon-arrow-down.is-expanded[data-v-656036f6]{transform:rotate(180deg)}.ecp-pro-descriptions__body[data-v-656036f6]{display:grid;border-top:1px solid #ebeef5;border-left:1px solid #ebeef5;overflow:hidden}.ecp-pro-descriptions__body.is-collapsed[data-v-656036f6]{overflow:hidden}.ecp-pro-descriptions__body[data-v-656036f6]:not(.is-bordered){border-top:0;border-left:0;gap:12px 16px}.ecp-pro-descriptions__item[data-v-656036f6]{display:flex;min-width:0;border-right:1px solid #ebeef5;border-bottom:1px solid #ebeef5}.ecp-pro-descriptions__body:not(.is-bordered) .ecp-pro-descriptions__item[data-v-656036f6]{border-right:0;border-bottom:0}.ecp-pro-descriptions__label[data-v-656036f6],.ecp-pro-descriptions__content[data-v-656036f6]{min-width:0;box-sizing:border-box;word-break:break-word}.ecp-pro-descriptions__label[data-v-656036f6]{flex:0 0 120px;padding:12px 16px;color:#606266;background:#fafafa}.ecp-pro-descriptions__content[data-v-656036f6]{flex:1;padding:12px 16px;color:#303133;background:#fff}.ecp-pro-descriptions__body:not(.is-bordered) .ecp-pro-descriptions__label[data-v-656036f6]{flex-basis:auto;padding:0;margin-right:8px;background:transparent;font-weight:500}.ecp-pro-descriptions__body:not(.is-bordered) .ecp-pro-descriptions__content[data-v-656036f6]{padding:0;background:transparent}.ecp-pro-descriptions__body.is-small .ecp-pro-descriptions__label[data-v-656036f6],.ecp-pro-descriptions__body.is-small .ecp-pro-descriptions__content[data-v-656036f6]{padding-top:8px;padding-bottom:8px;font-size:13px}@media (max-width: 767px){.ecp-pro-descriptions__item[data-v-656036f6]{flex-direction:column}.ecp-pro-descriptions__label[data-v-656036f6]{flex-basis:auto}}.ecp-collapse-container[data-v-087dba3a]{background:#fff;border-radius:14px;border:1px solid #e8eef8;box-shadow:0 10px 24px #0f2d5e0f;overflow:hidden}.ecp-collapse-container.is-ghost[data-v-087dba3a]{border-color:transparent;box-shadow:none;background:transparent}.ecp-collapse-container__header[data-v-087dba3a]{min-height:56px;padding:0 20px;display:flex;align-items:center;justify-content:space-between;gap:16px;border-bottom:1px solid #eef3fb}.ecp-collapse-container.is-ghost .ecp-collapse-container__header[data-v-087dba3a]{padding-left:0;padding-right:0}.ecp-collapse-container__header-main[data-v-087dba3a]{min-width:0;flex:1;display:flex;align-items:center}.ecp-collapse-container__title-wrap[data-v-087dba3a]{min-width:0;display:inline-flex;align-items:center;gap:8px}.ecp-collapse-container__title[data-v-087dba3a]{color:#1f2d3d;font-size:16px;font-weight:600;line-height:1.4}.ecp-collapse-container__help[data-v-087dba3a]{color:#91a3b7;font-size:14px}.ecp-collapse-container__header-extra[data-v-087dba3a]{display:inline-flex;align-items:center;justify-content:flex-end;gap:12px;flex-shrink:0}.ecp-collapse-container__toggle[data-v-087dba3a]{padding:0;color:#2f6fd3}.ecp-collapse-container__toggle i[data-v-087dba3a]{margin-left:6px;transition:transform .2s ease}.ecp-collapse-container__toggle i.is-expanded[data-v-087dba3a]{transform:rotate(180deg)}.ecp-collapse-container__body[data-v-087dba3a]{padding:20px;box-sizing:border-box}.ecp-collapse-container.is-ghost .ecp-collapse-container__body[data-v-087dba3a]{padding-left:0;padding-right:0}.ecp-collapse-container.is-header-clickable .ecp-collapse-container__header-main[data-v-087dba3a]{cursor:pointer}@media (max-width: 768px){.ecp-collapse-container__header[data-v-087dba3a]{padding:14px 16px;align-items:flex-start;flex-direction:column}.ecp-collapse-container__header-extra[data-v-087dba3a]{width:100%;justify-content:space-between}.ecp-collapse-container__body[data-v-087dba3a]{padding:16px}}.ecp-pro-table-form__form[data-v-3dfcfb4e] .el-form-item{margin-bottom:0}.ecp-pro-table-form__cell-item[data-v-3dfcfb4e]{width:100%}.ecp-pro-table-form__cell-item[data-v-3dfcfb4e] .el-form-item__content{margin-left:0!important;line-height:normal}.ecp-pro-table-form__req[data-v-3dfcfb4e]{color:#f56c6c;margin-right:2px}.ecp-pro-table-form__th-text[data-v-3dfcfb4e]{font-weight:500;color:#606266}.ecp-pro-table-form .ecp-pro-table-form__header-cell{background:#f5f7fa!important}.ecp-pro-table-form__cell-item .el-form-item__error{position:relative}
1
+ .ecp-pro-table{padding:16px;background:#fff;width:100%;box-sizing:border-box}.ecp-pro-table :deep(.el-table){width:100%!important}.ecp-pro-table__header{display:flex;justify-content:space-between;align-items:center;margin-bottom:16px}.ecp-pro-table__title-wrapper{display:flex;align-items:center;gap:4px}.ecp-pro-table__title{font-size:16px;font-weight:600}.ecp-pro-table__help{color:#909399;cursor:help}.ecp-pro-table__toolbar{display:flex;align-items:center;gap:8px}.ecp-pro-table__body{width:100%}.ecp-pro-table__pagination{margin-top:16px;display:flex;justify-content:flex-end}.ecp-pro-table__col-help{margin-left:4px;color:#909399;cursor:help}.ecp-table-action,.ecp-table-action__item{display:inline-flex;align-items:center;gap:4px}.ecp-table-action__icon{margin-right:4px}.ecp-table-action__more{display:inline-flex;align-items:center}.ecp-table-action__dropdown-item{display:inline-flex;align-items:center;gap:4px}.ecp-tree-select{position:relative;width:100%}.ecp-tree-select__filter-inner{margin-bottom:8px}.ecp-tree-select__dropdown{position:absolute;top:100%;left:0;right:0;max-height:280px;overflow:auto;background:#fff;border:1px solid #dcdfe6;border-radius:4px;margin-top:4px;z-index:1000;padding:8px}.ecp-tree-select__loading{padding:24px;text-align:center;color:#909399;font-size:14px}.ecp-pro-form-item__colon{margin-right:2px}.ecp-pro-form-item__help-icon{margin-left:4px;color:#909399;cursor:help;font-size:14px}.ecp-pro-form-item__help-icon:hover{color:#409eff}.ecp-pro-form-item__help-item{margin-bottom:4px}.ecp-pro-form-item__help-item:last-child{margin-bottom:0}.ecp-form-actions{text-align:right}.ecp-form-actions__advance{margin-right:8px}.ecp-pro-form{padding:16px;position:relative}.ecp-pro-form__advance{margin-bottom:16px}.ecp-pro-form .ecp-pro-form_col{position:relative;float:right}.el-icon-d-arrow-left.up{transform:rotate(90deg)}.el-icon-d-arrow-left.down{transform:rotate(-90deg)}.ecp-form-actions__advance{position:absolute;bottom:0;left:50%;transform:translate(-50%,-50%)}.ecp-pro-descriptions{width:100%;box-sizing:border-box}.ecp-pro-descriptions__header{display:flex;align-items:center;justify-content:space-between;margin-bottom:12px;gap:12px}.ecp-pro-descriptions__title-wrap{display:flex;align-items:center;gap:6px}.ecp-pro-descriptions__title{font-size:16px;font-weight:600;color:#303133}.ecp-pro-descriptions__help,.ecp-pro-descriptions__toggle{color:#909399}.ecp-pro-descriptions__toggle .el-icon-arrow-down{margin-left:4px;transition:transform .2s ease}.ecp-pro-descriptions__toggle .el-icon-arrow-down.is-expanded{transform:rotate(180deg)}.ecp-pro-descriptions__body{display:grid;border-top:1px solid #ebeef5;border-left:1px solid #ebeef5;overflow:hidden}.ecp-pro-descriptions__body.is-collapsed{overflow:hidden}.ecp-pro-descriptions__body:not(.is-bordered){border-top:0;border-left:0;gap:12px 16px}.ecp-pro-descriptions__item{display:flex;min-width:0;border-right:1px solid #ebeef5;border-bottom:1px solid #ebeef5}.ecp-pro-descriptions__body:not(.is-bordered) .ecp-pro-descriptions__item{border-right:0;border-bottom:0}.ecp-pro-descriptions__label,.ecp-pro-descriptions__content{min-width:0;box-sizing:border-box;word-break:break-word}.ecp-pro-descriptions__label{flex:0 0 120px;padding:12px 16px;color:#606266;background:#fafafa}.ecp-pro-descriptions__content{flex:1;padding:12px 16px;color:#303133;background:#fff}.ecp-pro-descriptions__body:not(.is-bordered) .ecp-pro-descriptions__label{flex-basis:auto;padding:0;margin-right:8px;background:transparent;font-weight:500}.ecp-pro-descriptions__body:not(.is-bordered) .ecp-pro-descriptions__content{padding:0;background:transparent}.ecp-pro-descriptions__body.is-small .ecp-pro-descriptions__label,.ecp-pro-descriptions__body.is-small .ecp-pro-descriptions__content{padding-top:8px;padding-bottom:8px;font-size:13px}@media (max-width: 767px){.ecp-pro-descriptions__item{flex-direction:column}.ecp-pro-descriptions__label{flex-basis:auto}}.ecp-collapse-container{background:#fff;border-radius:14px;border:1px solid #e8eef8;box-shadow:0 10px 24px #0f2d5e0f;overflow:hidden}.ecp-collapse-container.is-ghost{border-color:transparent;box-shadow:none;background:transparent}.ecp-collapse-container__header{min-height:56px;padding:0 20px;display:flex;align-items:center;justify-content:space-between;gap:16px;border-bottom:1px solid #eef3fb}.ecp-collapse-container.is-ghost .ecp-collapse-container__header{padding-left:0;padding-right:0}.ecp-collapse-container__header-main{min-width:0;flex:1;display:flex;align-items:center}.ecp-collapse-container__title-wrap{min-width:0;display:inline-flex;align-items:center;gap:8px}.ecp-collapse-container__title{color:#1f2d3d;font-size:16px;font-weight:600;line-height:1.4}.ecp-collapse-container__help{color:#91a3b7;font-size:14px}.ecp-collapse-container__header-extra{display:inline-flex;align-items:center;justify-content:flex-end;gap:12px;flex-shrink:0}.ecp-collapse-container__toggle{padding:0;color:#2f6fd3}.ecp-collapse-container__toggle i{margin-left:6px;transition:transform .2s ease}.ecp-collapse-container__toggle i.is-expanded{transform:rotate(180deg)}.ecp-collapse-container__body{padding:20px;box-sizing:border-box}.ecp-collapse-container.is-ghost .ecp-collapse-container__body{padding-left:0;padding-right:0}.ecp-collapse-container.is-header-clickable .ecp-collapse-container__header-main{cursor:pointer}@media (max-width: 768px){.ecp-collapse-container__header{padding:14px 16px;align-items:flex-start;flex-direction:column}.ecp-collapse-container__header-extra{width:100%;justify-content:space-between}.ecp-collapse-container__body{padding:16px}}.ecp-pro-table-form__form :deep(.el-form-item){margin-bottom:0}.ecp-pro-table-form__cell-item{width:100%}.ecp-pro-table-form__cell-item :deep(.el-form-item__content){margin-left:0!important;line-height:normal}.ecp-pro-table-form__req{color:#f56c6c;margin-right:2px}.ecp-pro-table-form__th-text{font-weight:500;color:#606266}.ecp-pro-table-form .ecp-pro-table-form__header-cell{background:#f5f7fa!important}.ecp-pro-table-form__cell-item .el-form-item__error{position:relative}
@@ -301,11 +301,12 @@ export interface ProTableFormColumn {
301
301
  * `integerDigits`、`decimalPlaces`、`rounding`、`inputLimit` 等(与 FormattedNumberInput 一致)。
302
302
  * 支持函数形式,参数为 { row, value, column },返回要合并到组件上的属性。
303
303
  */
304
- componentProps?: Record<string, unknown> | ((params: {
305
- row: Record<string, unknown>;
306
- value: unknown;
307
- column: ProTableFormColumn;
308
- }) => Record<string, unknown>);
304
+ /**
305
+ * 透传给单元格组件。`component === 'formatted-number'` 时在此传入
306
+ * `integerDigits`、`decimalPlaces`、`rounding`、`inputLimit` 等。
307
+ * 支持函数形式,参数为 { row, value, column, action },返回要合并到组件上的属性。
308
+ */
309
+ componentProps?: Record<string, unknown> | ((params: CellComponentPropsParams) => Record<string, unknown>);
309
310
  /** 动态校验规则 */
310
311
  dynamicRules?: unknown[] | ((params: {
311
312
  row: Record<string, unknown>;
@@ -359,13 +360,9 @@ export interface ProTableFormColumnChild {
359
360
  /**
360
361
  * 透传给单元格组件。`component === 'formatted-number'` 时在此传入
361
362
  * `integerDigits`、`decimalPlaces`、`rounding`、`inputLimit` 等。
362
- * 支持函数形式,参数为 { row, value, column },返回要合并到组件上的属性。
363
+ * 支持函数形式,参数为 { row, value, column, action },返回要合并到组件上的属性。
363
364
  */
364
- componentProps?: Record<string, unknown> | ((params: {
365
- row: Record<string, unknown>;
366
- value: unknown;
367
- column: ProTableFormColumnChild;
368
- }) => Record<string, unknown>);
365
+ componentProps?: Record<string, unknown> | ((params: CellComponentPropsParams) => Record<string, unknown>);
369
366
  rules?: unknown[];
370
367
  /** 动态校验规则 */
371
368
  dynamicRules?: unknown[] | ((params: {
@@ -482,3 +479,11 @@ export interface ProTableFormActionType {
482
479
  /** 获取 el-form 实例(可用于滚动、聚焦等高级操作) */
483
480
  getFormRef: () => FormInstance | null;
484
481
  }
482
+ /** componentProps 函数的参数类型 */
483
+ export interface CellComponentPropsParams {
484
+ row: Record<string, unknown>;
485
+ value: unknown;
486
+ column: ProTableFormColumn | ProTableFormColumnChild;
487
+ /** ProTableForm 操作实例,可调用 validate、addRow、removeRow 等 */
488
+ action: ProTableFormActionType;
489
+ }
@@ -0,0 +1,100 @@
1
+ # CollapseContainer 折叠容器
2
+
3
+ 参考 Vben Admin 的 `CollapseContainer` 交互习惯封装的内容容器,适合包裹表单、表格、统计卡片、详情区块等内容区域。
4
+
5
+ 支持以下能力:
6
+
7
+ - 标题区与帮助提示
8
+ - 展开 / 收起切换
9
+ - `expanded` 受控模式与 `defaultExpand` 非受控模式
10
+ - `title` / `action` 插槽
11
+ - `loading` 状态
12
+ - `ghost` 透明模式
13
+ - 折叠后自动触发 `window.resize`,便于内部表格/图表重新计算布局
14
+
15
+ ## 基础用法
16
+
17
+ ```vue
18
+ <template>
19
+ <CollapseContainer title="查询条件">
20
+ <ProForm :schemas="schemas" />
21
+ </CollapseContainer>
22
+ </template>
23
+
24
+ <script setup lang="ts">
25
+ import { CollapseContainer, ProForm } from 'element-component-pro'
26
+ import type { ProFormSchema } from 'element-component-pro'
27
+
28
+ const schemas: ProFormSchema[] = [
29
+ { field: 'name', label: '姓名', component: 'input' },
30
+ { field: 'status', label: '状态', component: 'select', componentProps: { options: [
31
+ { label: '启用', value: 1 },
32
+ { label: '禁用', value: 0 },
33
+ ] } },
34
+ ]
35
+ </script>
36
+ ```
37
+
38
+ ## 受控展开
39
+
40
+ ```vue
41
+ <template>
42
+ <CollapseContainer
43
+ title="高级筛选"
44
+ :expanded.sync="expanded"
45
+ >
46
+ <div>这里放高级筛选内容</div>
47
+ </CollapseContainer>
48
+
49
+ <el-button @click="expanded = !expanded">
50
+ 外部切换
51
+ </el-button>
52
+ </template>
53
+
54
+ <script setup lang="ts">
55
+ import { ref } from 'vue'
56
+ import { CollapseContainer } from 'element-component-pro'
57
+
58
+ const expanded = ref(true)
59
+ </script>
60
+ ```
61
+
62
+ ## Props
63
+
64
+ | 属性 | 类型 | 默认值 | 说明 |
65
+ |------|------|--------|------|
66
+ | `title` | `string` | - | 标题文案 |
67
+ | `loading` | `boolean` | `false` | 容器 loading |
68
+ | `canExpan` | `boolean` | `true` | 是否显示折叠按钮,保留 Vben Admin 命名 |
69
+ | `canExpand` | `boolean` | - | `canExpan` 的语义化别名,优先级更高 |
70
+ | `helpMessage` | `string \| string[]` | - | 标题右侧帮助提示 |
71
+ | `triggerWindowResize` | `boolean` | `true` | 展开收起后是否触发 `window.resize` |
72
+ | `expanded` | `boolean` | - | 受控展开状态 |
73
+ | `defaultExpand` | `boolean` | `true` | 非受控模式下默认是否展开 |
74
+ | `ghost` | `boolean` | `false` | 是否使用透明背景模式 |
75
+ | `expandButtonText` | `string` | `'展开'` | 展开按钮文案 |
76
+ | `collapseButtonText` | `string` | `'收起'` | 收起按钮文案 |
77
+
78
+ ## Events
79
+
80
+ | 事件 | 回调参数 | 说明 |
81
+ |------|----------|------|
82
+ | `update:expanded` | `(value: boolean)` | 受控模式同步展开状态 |
83
+ | `change` | `(value: boolean)` | 展开状态变化时触发 |
84
+ | `expand` | - | 展开时触发 |
85
+ | `collapse` | - | 收起时触发 |
86
+
87
+ ## Slots
88
+
89
+ | 名称 | 说明 |
90
+ |------|------|
91
+ | `default` | 容器主体内容 |
92
+ | `title` | 自定义标题区域 |
93
+ | `action` | 标题右侧操作区 |
94
+
95
+ ## Expose
96
+
97
+ | 方法 | 类型 | 说明 |
98
+ |------|------|------|
99
+ | `setExpanded` | `(value: boolean) => void` | 手动设置展开状态 |
100
+ | `toggleExpand` | `() => void` | 手动切换展开状态 |
@@ -0,0 +1,113 @@
1
+ # useComponentSetting 组件默认配置
2
+
3
+ 为 **ProTable、ProForm** 等组件提供统一的默认 props 配置能力:在应用入口通过 `setSetting` 设置一次,所有未显式传入的 props 将使用这些默认值。组件内部合并顺序为:**默认配置 ← 组件 props ← setProps**。
4
+
5
+ ---
6
+
7
+ ## API
8
+
9
+ ```ts
10
+ import { useComponentSetting } from 'element-component-pro'
11
+ import type { UseComponentSettingReturn } from 'element-component-pro'
12
+
13
+ const { getSetting, setSetting } = useComponentSetting()
14
+ // 返回类型为 UseComponentSettingReturn
15
+ ```
16
+
17
+ | 方法 | 类型 | 说明 |
18
+ |------|------|------|
19
+ | `getSetting` | `(componentName?: string) => Record<string, unknown>` | 获取默认配置。不传参返回全部组件的配置;传组件名(如 `'ProTable'`、`'ProForm'`)返回该组件的默认配置。 |
20
+ | `setSetting` | `(componentName: string, config: Record<string, unknown>) => void` | 设置指定组件的默认配置,与已有配置**浅合并**(不会覆盖未在 `config` 中传入的已有字段)。 |
21
+
22
+ ---
23
+
24
+ ## 基本用法
25
+
26
+ ### 设置默认配置
27
+
28
+ 通常在应用入口(如 `main.ts` 或根组件 `setup`)调用一次:
29
+
30
+ ```ts
31
+ import { useComponentSetting } from 'element-component-pro'
32
+
33
+ const { setSetting } = useComponentSetting()
34
+
35
+ // ProTable 全局默认:小尺寸、带边框、显示序号列
36
+ setSetting('ProTable', {
37
+ size: 'small',
38
+ bordered: true,
39
+ showIndexColumn: true,
40
+ })
41
+
42
+ // ProForm 全局默认
43
+ setSetting('ProForm', {
44
+ labelWidth: '140px',
45
+ size: 'small',
46
+ })
47
+ ```
48
+
49
+ 之后所有 `<ProTable>`、`<ProForm>` 若未传 `size`、`bordered`、`labelWidth` 等,将使用上述默认值。组件上显式传入的 props 会覆盖默认配置。
50
+
51
+ ### 获取当前默认配置
52
+
53
+ ```ts
54
+ const { getSetting } = useComponentSetting()
55
+
56
+ // 获取 ProTable 的默认配置
57
+ const tableDefaults = getSetting('ProTable')
58
+ // => { size: 'small', bordered: true, showIndexColumn: true }
59
+
60
+ // 获取全部组件的默认配置
61
+ const all = getSetting()
62
+ // => { ProTable: { ... }, ProForm: { ... } }
63
+ ```
64
+
65
+ ---
66
+
67
+ ## 组件名约定
68
+
69
+ | 组件名 | 说明 |
70
+ |--------|------|
71
+ | `'ProTable'` | ProTable 表格组件 |
72
+ | `'ProForm'` | ProForm 表单组件 |
73
+
74
+ 其他组件若在内部接入了 `getSetting(组件名)`,也可使用相同方式设置默认配置。
75
+
76
+ ---
77
+
78
+ ## 与 props / setProps 的优先级
79
+
80
+ 对单个组件实例而言,最终生效的 props 按以下顺序合并(后者覆盖前者):
81
+
82
+ 1. **getSetting(组件名)** 得到的默认配置
83
+ 2. 组件上直接传入的 **props**(如 `<ProTable size="medium" />`)
84
+ 3. 通过 **tableAction.setProps()** / **formAction.setProps()** 动态设置的值
85
+
86
+ 因此:默认配置 < 显式 props < 编程式 setProps。
87
+
88
+ ---
89
+
90
+ ## 示例
91
+
92
+ ```vue
93
+ <template>
94
+ <ProTable title="表格" :columns="columns" :data-source="data" row-key="id" />
95
+ </template>
96
+
97
+ <script setup lang="ts">
98
+ import { ProTable } from 'element-component-pro'
99
+ import type { ProColumn } from 'element-component-pro'
100
+
101
+ // 未传 size、bordered,将使用 useComponentSetting 中 setSetting('ProTable', { size, bordered }) 的默认值
102
+ const columns: ProColumn[] = [
103
+ { title: 'ID', dataIndex: 'id', width: 80 },
104
+ { title: '姓名', dataIndex: 'name', width: 120 },
105
+ ]
106
+ const data = [
107
+ { id: 1, name: '张三' },
108
+ { id: 2, name: '李四' },
109
+ ]
110
+ </script>
111
+ ```
112
+
113
+ 在项目示例中可打开 **「componentSettings 测试」** 页面查看完整演示。
@@ -0,0 +1,215 @@
1
+ # ProDescriptions 详情组件
2
+
3
+ 基于 Element UI 风格封装的详情展示组件,参考 [Vben Admin Description](https://doc.vvbin.cn/components/desc.html#usage),用于展示结构化只读信息,支持:
4
+
5
+ - `schema` 驱动的详情项配置
6
+ - 响应式 `column`
7
+ - `useDescription` 编程式调用
8
+ - 折叠展开
9
+ - 自定义 `render` 与具名插槽
10
+ - `field` / `dataIndex` 双写法兼容 Vben 使用习惯
11
+
12
+ ## 组件构成
13
+
14
+ - **ProDescriptions** - 主组件
15
+ - **useDescription** - Hook,返回 `register` 和 `descriptionAction`
16
+
17
+ ## 基础用法
18
+
19
+ ```vue
20
+ <template>
21
+ <ProDescriptions
22
+ title="基础示例"
23
+ :column="3"
24
+ :data="detailData"
25
+ :schema="schema"
26
+ />
27
+ </template>
28
+
29
+ <script setup lang="ts">
30
+ import { ProDescriptions } from 'element-component-pro'
31
+ import type { DescriptionSchema } from 'element-component-pro'
32
+
33
+ const detailData = {
34
+ username: 'test',
35
+ nickName: 'VB',
36
+ age: 18,
37
+ phone: '15695909xxx',
38
+ email: '190848757@qq.com',
39
+ }
40
+
41
+ const schema: DescriptionSchema[] = [
42
+ { label: '用户名', field: 'username', dataIndex: 'username' },
43
+ {
44
+ label: '昵称',
45
+ dataIndex: 'nickName',
46
+ render: (value, record) => `${record.username}-${value}`,
47
+ },
48
+ { label: '年龄', dataIndex: 'age' },
49
+ { label: '联系电话', dataIndex: 'phone' },
50
+ { label: '邮箱', dataIndex: 'email' },
51
+ ]
52
+ </script>
53
+ ```
54
+
55
+ ## useDescription
56
+
57
+ ```vue
58
+ <template>
59
+ <ProDescriptions @register="register" />
60
+ </template>
61
+
62
+ <script setup lang="ts">
63
+ import { ProDescriptions, useDescription } from 'element-component-pro'
64
+
65
+ const [register, descriptionAction] = useDescription({
66
+ title: 'useDescription',
67
+ data: {
68
+ name: '张三',
69
+ role: '管理员',
70
+ },
71
+ schema: [
72
+ { label: '姓名', dataIndex: 'name' },
73
+ { label: '角色', dataIndex: 'role' },
74
+ ],
75
+ })
76
+
77
+ const updateRole = () => {
78
+ descriptionAction.setData({ role: '访客' })
79
+ }
80
+ </script>
81
+ ```
82
+
83
+ ## Props
84
+
85
+ | 属性 | 类型 | 默认值 | 说明 |
86
+ |------|------|--------|------|
87
+ | `title` | `string` | - | 标题 |
88
+ | `helpMessage` | `string \| string[]` | - | 标题右侧帮助文案 |
89
+ | `size` | `'medium' \| 'small'` | `'medium'` | 尺寸 |
90
+ | `bordered` | `boolean` | `true` | 是否显示边框 |
91
+ | `column` | `number \| { xxl, xl, lg, md, sm, xs }` | `{ xxl: 4, xl: 3, lg: 3, md: 3, sm: 2, xs: 1 }` | 每行列数 |
92
+ | `schema` | `DescriptionSchema[]` | `[]` | 描述项配置 |
93
+ | `data` | `Record<string, unknown>` | `{}` | 数据源 |
94
+ | `emptyText` | `string` | `'-'` | 空值展示文本 |
95
+ | `useCollapse` | `boolean` | `false` | 是否启用折叠 |
96
+ | `collapseOptions` | `object` | `{ canExpand: false, defaultExpand: true, visibleRows: 1 }` | 折叠配置 |
97
+
98
+ ## DescriptionSchema
99
+
100
+ | 属性 | 类型 | 说明 |
101
+ |------|------|------|
102
+ | `label` | `string` | 标签 |
103
+ | `field` | `string` | 字段名,兼容 Vben 风格写法 |
104
+ | `dataIndex` | `string` | 字段名;未传时可回退使用 `field` |
105
+ | `span` | `number` | 所占列数 |
106
+ | `show` | `boolean \| (data) => boolean` | 是否显示 |
107
+ | `labelMinWidth` | `number` | label 最小宽度 |
108
+ | `contentMinWidth` | `number` | content 最小宽度 |
109
+ | `labelStyle` | `Record<string, string \| number>` | 标签样式 |
110
+ | `contentStyle` | `Record<string, string \| number>` | 内容样式 |
111
+ | `slot` | `string` | 自定义插槽名 |
112
+ | `render` | `(value, record) => VNode \| string \| number` | 自定义渲染 |
113
+ | `tooltip` | `boolean \| string \| object \| (params) => boolean \| string \| object` | 描述项 value tooltip,`true` 时默认展示当前值 |
114
+
115
+ ## tooltip
116
+
117
+ `tooltip` 用于给详情项 value 增加悬浮提示,适合长文本、层级较深的数组值,或需要补充业务说明的只读字段。
118
+
119
+ 支持以下几种写法:
120
+
121
+ | 写法 | 说明 |
122
+ |------|------|
123
+ | `true` | 启用 tooltip,并默认使用当前字段值作为内容 |
124
+ | `string` | 使用固定文案作为 tooltip 内容 |
125
+ | `object` | 透传给 `el-tooltip` 的 props;未传 `content` 时默认使用当前字段值 |
126
+ | `(params) => ...` | 动态返回上面任一类型,可根据 record 联动 |
127
+
128
+ `params` 包含以下字段:
129
+
130
+ - `value`:当前详情项值
131
+ - `record`:完整数据源
132
+ - `schema`:当前详情项配置
133
+
134
+ 默认行为:
135
+
136
+ - 默认 `placement` 为 `top`
137
+ - 默认 `effect` 为 `dark`
138
+ - 当 tooltip 内容为空字符串、`null`、`undefined` 或空数组时,会自动禁用 tooltip
139
+ - 数组值未显式指定 `content` 时,会按逗号拼接展示
140
+ - 对象值未显式指定 `content` 时,会自动 `JSON.stringify` 后展示
141
+
142
+ ```ts
143
+ const schema: DescriptionSchema[] = [
144
+ {
145
+ label: '联系地址',
146
+ dataIndex: 'address',
147
+ tooltip: true,
148
+ },
149
+ {
150
+ label: '账号状态',
151
+ dataIndex: 'status',
152
+ tooltip: ({ record }) => record.status === 1 ? '当前为启用状态' : '当前为禁用状态',
153
+ },
154
+ {
155
+ label: '备注',
156
+ dataIndex: 'remark',
157
+ tooltip: {
158
+ placement: 'top-start',
159
+ effect: 'light',
160
+ },
161
+ },
162
+ ]
163
+ ```
164
+
165
+ ### tooltip 常见问题
166
+
167
+ #### 1. `tooltip: true` 默认展示什么?
168
+
169
+ 默认展示当前字段真实值:
170
+
171
+ - 普通文本直接转成字符串
172
+ - 数组按逗号拼接
173
+ - 对象转成 JSON 字符串
174
+ - 空值时自动禁用 tooltip
175
+
176
+ #### 2. `render` 返回字符串时还会支持 tooltip 吗?
177
+
178
+ 支持。如果 `render` 返回的是 `string` 或 `number`,会继续套用 `tooltip` 逻辑。
179
+
180
+ 如果 `render` 返回的是自定义 VNode,则由你自己控制展示结构,此时不会额外包裹默认 tooltip。
181
+
182
+ #### 3. 适合在哪些字段上开启?
183
+
184
+ 建议优先用于:
185
+
186
+ - 长地址、备注、说明类字段
187
+ - 多选标签或数组拼接结果
188
+ - 证件号、邮箱等可能需要完整查看但页面空间有限的字段
189
+ - 需要补充业务解释的状态字段
190
+
191
+ ## collapseOptions
192
+
193
+ | 属性 | 类型 | 说明 |
194
+ |------|------|------|
195
+ | `canExpand` | `boolean` | 是否显示展开/收起按钮 |
196
+ | `defaultExpand` | `boolean` | 默认是否展开 |
197
+ | `expandButtonText` | `string` | 展开按钮文案 |
198
+ | `collapseButtonText` | `string` | 收起按钮文案 |
199
+ | `helpMessage` | `string \| string[]` | 折叠区域帮助提示 |
200
+ | `visibleRows` | `number` | 折叠时默认显示的行数 |
201
+
202
+ ## descriptionAction 方法
203
+
204
+ | 方法 | 类型 | 说明 |
205
+ |------|------|------|
206
+ | `setProps` | `(props: Partial<DescriptionProps>) => Promise<void>` | 动态更新组件 Props |
207
+ | `setData` | `(data: Record<string, unknown>) => Promise<void>` | 合并更新数据 |
208
+ | `getData` | `() => Record<string, unknown>` | 获取当前数据 |
209
+
210
+ ## Slots
211
+
212
+ | 名称 | 说明 |
213
+ |------|------|
214
+ | `[dataIndex]` | 以字段名命名的具名插槽,参数:`{ value, record, schema }` |
215
+ | `[schema.slot]` | 自定义 slot 名称,优先于 `dataIndex` |