@qin-ui/element-plus-pro 1.4.2 → 1.4.4
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/api.json +2 -2
- package/es/components/component-provider/components/index.vue.d.ts.map +1 -1
- package/es/components/form/components/BaseField/index.vue.d.ts.map +1 -1
- package/es/components/form/components/BaseField/utils/index.d.ts +2 -1
- package/es/components/form/components/BaseField/utils/index.d.ts.map +1 -1
- package/es/components/form/components/BaseFormItem/index.vue.d.ts +60 -9
- package/es/components/form/components/BaseFormItem/index.vue.d.ts.map +1 -1
- package/es/components/form/components/BaseFormItems/index.vue.d.ts +13 -0
- package/es/components/form/components/BaseFormItems/index.vue.d.ts.map +1 -0
- package/es/components/form/components/ProForm/index.vue.d.ts.map +1 -1
- package/es/components/form/components/index.d.ts +6 -6
- package/es/components/form/components/index.d.ts.map +1 -1
- package/es/components/form/hooks/useGroupFieldAttrs.d.ts +10 -2
- package/es/components/form/hooks/useGroupFieldAttrs.d.ts.map +1 -1
- package/es/components/form/utils/fieldKey.d.ts +12 -0
- package/es/components/form/utils/fieldKey.d.ts.map +1 -1
- package/es/components/table/components/ProTable.vue.d.ts.map +1 -1
- package/es/components/table/types/index.d.ts +1 -0
- package/es/components/table/types/index.d.ts.map +1 -1
- package/es/element-plus-pro.css +8 -7
- package/es/index.js +327 -174
- package/es/index.js.map +1 -1
- package/es/shared/core/index.d.ts +1 -1
- package/es/shared/core/index.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/components/component-provider/components/index.vue +25 -8
- package/src/components/form/components/BaseField/index.vue +20 -12
- package/src/components/form/components/BaseField/utils/index.ts +8 -3
- package/src/components/form/components/BaseFormItem/index.vue +145 -176
- package/src/components/form/components/BaseFormItems/index.vue +183 -0
- package/src/components/form/components/ProForm/index.vue +13 -6
- package/src/components/form/components/index.ts +6 -6
- package/src/components/form/hooks/useGroupFieldAttrs.ts +104 -79
- package/src/components/form/utils/fieldKey.ts +64 -0
- package/src/components/table/components/ProTable.vue +11 -5
- package/src/components/table/types/index.ts +1 -0
- package/src/shared/core/index.ts +2 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 统一 re-export @qin-ui/pro-components-core,包内所有文件通过此文件引入 core 内容。
|
|
3
3
|
*/
|
|
4
|
-
export { type AdditionalMethods, localePacks, normalizeColumn, normalizeColumns, useForm, createFormProxy, useTable, useSearchFormExpand, useFields, resolveFieldIdentity, DEFAULT_FIELD_IDENTITY_KEYS, useFormData, useFormRef, useReactiveAttrs, InjectionFormKey, InjectionFormSlotsKey, getObject, omitBy, get, set, normalizePathKey, toPath, camelizeProperties, cloneDeep, pick, omit, isPlainObject, isObjectItem, isPromise, zhCN, zhTW, enUS, format, resolveLocaleName, type ProLocale, type ProLocaleName, type ProLocaleKey, type Data, type Path, type Paths, type KeyExpandString, type ExtendWithAny, type DeepPartial, type PageParam, type Fields, type Form, type Table, type UseFieldsReturn, type UseFormDataReturn, type UseFormRefReturn, } from '@qin-ui/pro-components-core';
|
|
4
|
+
export { type AdditionalMethods, localePacks, normalizeColumn, normalizeColumns, useForm, createFormProxy, useTable, useSearchFormExpand, useFields, resolveFieldIdentity, DEFAULT_FIELD_IDENTITY_KEYS, useFormData, useFormRef, useReactiveAttrs, InjectionFormKey, InjectionFormSlotsKey, getObject, mergeComponentVars, omitBy, get, set, normalizePathKey, toPath, camelizeProperties, cloneDeep, pick, omit, isPlainObject, isObjectItem, isPromise, callListeners, zhCN, zhTW, enUS, format, resolveLocaleName, type ProLocale, type ProLocaleName, type ProLocaleKey, type Data, type Path, type Paths, type KeyExpandString, type ExtendWithAny, type DeepPartial, type PageParam, type Fields, type Form, type Table, type UseFieldsReturn, type UseFormDataReturn, type UseFormRefReturn, } from '@qin-ui/pro-components-core';
|
|
5
5
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/shared/core/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAEL,KAAK,iBAAiB,EACtB,WAAW,EACX,eAAe,EACf,gBAAgB,EAEhB,OAAO,EACP,eAAe,EACf,QAAQ,EACR,mBAAmB,EACnB,SAAS,EACT,oBAAoB,EACpB,2BAA2B,EAC3B,WAAW,EACX,UAAU,EACV,gBAAgB,EAEhB,gBAAgB,EAChB,qBAAqB,EAErB,SAAS,EACT,MAAM,EACN,GAAG,EACH,GAAG,EACH,gBAAgB,EAChB,MAAM,EACN,kBAAkB,EAClB,SAAS,EACT,IAAI,EACJ,IAAI,EACJ,aAAa,EACb,YAAY,EACZ,SAAS,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/shared/core/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAEL,KAAK,iBAAiB,EACtB,WAAW,EACX,eAAe,EACf,gBAAgB,EAEhB,OAAO,EACP,eAAe,EACf,QAAQ,EACR,mBAAmB,EACnB,SAAS,EACT,oBAAoB,EACpB,2BAA2B,EAC3B,WAAW,EACX,UAAU,EACV,gBAAgB,EAEhB,gBAAgB,EAChB,qBAAqB,EAErB,SAAS,EACT,kBAAkB,EAClB,MAAM,EACN,GAAG,EACH,GAAG,EACH,gBAAgB,EAChB,MAAM,EACN,kBAAkB,EAClB,SAAS,EACT,IAAI,EACJ,IAAI,EACJ,aAAa,EACb,YAAY,EACZ,SAAS,EACT,aAAa,EAEb,IAAI,EACJ,IAAI,EACJ,IAAI,EACJ,MAAM,EACN,iBAAiB,EACjB,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,KAAK,YAAY,EAEjB,KAAK,IAAI,EACT,KAAK,IAAI,EACT,KAAK,KAAK,EACV,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,KAAK,MAAM,EACX,KAAK,IAAI,EACT,KAAK,KAAK,EACV,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,GACtB,MAAM,6BAA6B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qin-ui/element-plus-pro",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.4",
|
|
4
4
|
"description": "基于 element-plus 的二次封装组件",
|
|
5
5
|
"bin": {
|
|
6
6
|
"element-plus-pro": "./bin/init-ai.mjs"
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"vue-component-type-helpers": "^3.2.5",
|
|
43
|
-
"@qin-ui/pro-components-core": "^2.
|
|
43
|
+
"@qin-ui/pro-components-core": "^2.2.0"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@types/node": "^24",
|
|
@@ -36,8 +36,8 @@ import {
|
|
|
36
36
|
ensureInjectConfig,
|
|
37
37
|
} from '../constants';
|
|
38
38
|
import type { ComponentVars } from '../types';
|
|
39
|
-
import { computed, provide } from 'vue';
|
|
40
|
-
import { getObject, omit } from '../../../shared/core';
|
|
39
|
+
import { computed, inject, provide, toValue } from 'vue';
|
|
40
|
+
import { getObject, mergeComponentVars, omit } from '../../../shared/core';
|
|
41
41
|
import type { ComponentName } from '../../form/constants';
|
|
42
42
|
import { LOCALE_INJECT_KEY, type ProLocale } from '../../../locale';
|
|
43
43
|
|
|
@@ -74,20 +74,22 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
74
74
|
});
|
|
75
75
|
|
|
76
76
|
/*
|
|
77
|
-
* 遍历 componentVars 的每个 key
|
|
78
|
-
*
|
|
77
|
+
* 遍历 componentVars 的每个 key,读取祖先注入值与本层配置合并后向下 provide
|
|
78
|
+
* 合并顺序为内置默认值 → 祖先注入值 → 本层 componentVars,剔除该注入项的不可注入键
|
|
79
79
|
* 子组件通过 inject(config.injectionKey) 获取合并后的计算属性配置
|
|
80
80
|
*/
|
|
81
81
|
(Object.keys(INJECT_CONFIG) as Array<keyof typeof INJECT_CONFIG>).forEach(
|
|
82
82
|
key => {
|
|
83
83
|
const config = INJECT_CONFIG[key];
|
|
84
84
|
const ignored = config.ignoreProps;
|
|
85
|
+
const parentConfig = inject(config.injectionKey as any, undefined);
|
|
85
86
|
provide(
|
|
86
87
|
config.injectionKey as any,
|
|
87
88
|
computed(() =>
|
|
88
89
|
omit(
|
|
89
90
|
{
|
|
90
91
|
...config.default,
|
|
92
|
+
...(toValue(parentConfig) || {}),
|
|
91
93
|
...getObject(props.componentVars?.[key as keyof ComponentVars]),
|
|
92
94
|
},
|
|
93
95
|
ignored ?? []
|
|
@@ -102,10 +104,11 @@ if (props.componentVars) {
|
|
|
102
104
|
Object.keys(props.componentVars).forEach(key => {
|
|
103
105
|
if (!(key in INJECT_CONFIG)) {
|
|
104
106
|
const config = ensureInjectConfig(key);
|
|
107
|
+
const parentConfig = inject(config.injectionKey as any, undefined);
|
|
105
108
|
provide(
|
|
106
109
|
config.injectionKey as any,
|
|
107
110
|
computed(() => ({
|
|
108
|
-
...
|
|
111
|
+
...(toValue(parentConfig) || {}),
|
|
109
112
|
...getObject((props.componentVars as any)?.[key]),
|
|
110
113
|
}))
|
|
111
114
|
);
|
|
@@ -113,22 +116,36 @@ if (props.componentVars) {
|
|
|
113
116
|
});
|
|
114
117
|
}
|
|
115
118
|
|
|
119
|
+
const parentComponentVars = inject(INJECT_COMPONENT_VARS, undefined);
|
|
116
120
|
// 全量 componentVars:自定义组件键在运行期新增后同样可被子组件读取
|
|
117
121
|
provide(
|
|
118
122
|
INJECT_COMPONENT_VARS,
|
|
119
|
-
computed(() =>
|
|
123
|
+
computed(() =>
|
|
124
|
+
mergeComponentVars(
|
|
125
|
+
toValue(parentComponentVars),
|
|
126
|
+
props.componentVars as Record<string, any>
|
|
127
|
+
)
|
|
128
|
+
)
|
|
120
129
|
);
|
|
121
130
|
|
|
131
|
+
const parentComponents = inject(INJECT_COMPONENTS, undefined);
|
|
122
132
|
// 注入自定义组件映射,BaseField 在解析组件时会优先使用此映射
|
|
123
133
|
provide(
|
|
124
134
|
INJECT_COMPONENTS,
|
|
125
|
-
computed(() =>
|
|
135
|
+
computed(() => ({
|
|
136
|
+
...(toValue(parentComponents) || {}),
|
|
137
|
+
...(props.componentMap ?? {}),
|
|
138
|
+
}))
|
|
126
139
|
);
|
|
127
140
|
|
|
141
|
+
const parentLocale = inject(LOCALE_INJECT_KEY, undefined);
|
|
128
142
|
// 注入内置文案覆盖,useLocale 在解析文案时会优先使用
|
|
129
143
|
provide(
|
|
130
144
|
LOCALE_INJECT_KEY,
|
|
131
|
-
computed(() =>
|
|
145
|
+
computed(() => ({
|
|
146
|
+
...(toValue(parentLocale) || {}),
|
|
147
|
+
...(props.locale ?? {}),
|
|
148
|
+
}))
|
|
132
149
|
);
|
|
133
150
|
</script>
|
|
134
151
|
|
|
@@ -40,6 +40,7 @@ import {
|
|
|
40
40
|
import {
|
|
41
41
|
cloneDeep,
|
|
42
42
|
getObject,
|
|
43
|
+
omitBy,
|
|
43
44
|
useReactiveAttrs,
|
|
44
45
|
} from '../../../../shared/core';
|
|
45
46
|
import { useDisabledContext } from '../../../../shared/ui';
|
|
@@ -81,20 +82,23 @@ const componentRef = ref<any>();
|
|
|
81
82
|
const attrs: any = useReactiveAttrs();
|
|
82
83
|
|
|
83
84
|
/**
|
|
84
|
-
*
|
|
85
|
+
* 全局默认配置注入:按组件名与 type 修饰段分别解析注入通道,inject 须在 setup 同步期调用。
|
|
85
86
|
* 组件名与 `type` 仅取 setup 期初始值——运行期变更不会切换 Provider 的默认值预设
|
|
86
87
|
* (`date-picker.month` 等子类型预设需在初始渲染前确定)。
|
|
88
|
+
* `date-picker` 的 type 缺省时按 `date` 段解析子类型预设。
|
|
87
89
|
*/
|
|
88
90
|
const typeVal = attrs.type;
|
|
89
|
-
const
|
|
90
|
-
typeof props.component === 'string'
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
const
|
|
94
|
-
?
|
|
91
|
+
const baseConfigKey =
|
|
92
|
+
typeof props.component === 'string' ? props.component : '';
|
|
93
|
+
const typeConfigKey =
|
|
94
|
+
typeVal || (baseConfigKey === 'date-picker' ? 'date' : '');
|
|
95
|
+
const subtypeConfigKey =
|
|
96
|
+
baseConfigKey && typeConfigKey ? `${baseConfigKey}.${typeConfigKey}` : '';
|
|
97
|
+
const baseInjectConfig = baseConfigKey
|
|
98
|
+
? getInjectConfig(baseConfigKey)
|
|
95
99
|
: undefined;
|
|
96
|
-
const
|
|
97
|
-
?
|
|
100
|
+
const subtypeInjectConfig = subtypeConfigKey
|
|
101
|
+
? getInjectConfig(subtypeConfigKey)
|
|
98
102
|
: undefined;
|
|
99
103
|
// 全量 componentVars:运行期新增的自定义组件键由此兜底读取
|
|
100
104
|
const componentVars = inject(INJECT_COMPONENT_VARS, undefined);
|
|
@@ -149,9 +153,12 @@ const parentDisabled = useDisabledContext();
|
|
|
149
153
|
* 属性分为三类:绑定属性(v-model)、组件属性(传递给组件)、插槽(动态渲染)
|
|
150
154
|
*/
|
|
151
155
|
const groupedAttrs = computed(() => {
|
|
156
|
+
// 库内置默认(基础键 → 子类型键)之后再铺项目配置,项目配置始终覆盖库默认
|
|
152
157
|
const currentInjectProps = {
|
|
153
|
-
...(
|
|
154
|
-
...getObject(
|
|
158
|
+
...getObject(baseInjectConfig?.default),
|
|
159
|
+
...getObject(subtypeInjectConfig?.default),
|
|
160
|
+
...getObject(toValue(componentVars)?.[baseConfigKey]),
|
|
161
|
+
...getObject(toValue(componentVars)?.[subtypeConfigKey]),
|
|
155
162
|
};
|
|
156
163
|
const initProps = getInitProps(
|
|
157
164
|
{
|
|
@@ -169,7 +176,8 @@ const groupedAttrs = computed(() => {
|
|
|
169
176
|
);
|
|
170
177
|
const mergedProps = mergeProps(
|
|
171
178
|
initProps,
|
|
172
|
-
|
|
179
|
+
// 未赋值(undefined)的键不作为显式值下发,保留注入默认值与占位符兜底
|
|
180
|
+
omitBy(attrs, value => value === undefined),
|
|
173
181
|
{ class: attrs.componentClass, style: attrs.componentStyle },
|
|
174
182
|
{ disabled: effectiveDisabled },
|
|
175
183
|
{ modelProp: modelPropName }
|
|
@@ -65,7 +65,8 @@ const getPlaceholderProps = (
|
|
|
65
65
|
/**
|
|
66
66
|
* 组件初始属性:以内置默认值为底,按下发组件名补默认占位符文案
|
|
67
67
|
*
|
|
68
|
-
* @description
|
|
68
|
+
* @description 占位符按 `component` 与 `type` 拼接的键查表(如 `input.password`),
|
|
69
|
+
* 该键无占位符映射时回落到基础组件名;`component` 非字符串时返回空记录。
|
|
69
70
|
* @param {Field} field - 字段配置
|
|
70
71
|
* @param {Record<string, any>} injectProps - Provider 下发的组件默认属性
|
|
71
72
|
* @param {LocaleT} t - 取文案的翻译函数
|
|
@@ -78,8 +79,12 @@ export const getInitProps = (
|
|
|
78
79
|
): Record<string, any> => {
|
|
79
80
|
const { component, type } = field as any;
|
|
80
81
|
if (typeof component === 'string') {
|
|
81
|
-
const
|
|
82
|
-
|
|
82
|
+
const subtypeKey = [component, type].filter(Boolean).join('.');
|
|
83
|
+
const key =
|
|
84
|
+
PLACEHOLDER_KEYS[subtypeKey] || RANGE_PLACEHOLDER_KEYS[subtypeKey]
|
|
85
|
+
? subtypeKey
|
|
86
|
+
: component;
|
|
87
|
+
return { ...injectProps, ...getPlaceholderProps(key, injectProps, t) };
|
|
83
88
|
}
|
|
84
89
|
return {};
|
|
85
90
|
};
|
|
@@ -1,205 +1,174 @@
|
|
|
1
|
-
<script lang="ts"
|
|
1
|
+
<script lang="ts">
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* 单字段行渲染组件
|
|
4
4
|
*
|
|
5
5
|
* @component BaseFormItem
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
* -
|
|
9
|
-
* -
|
|
10
|
-
* - FormItem
|
|
11
|
-
* - 组件绑定(通过 BaseField 渲染具体组件)
|
|
12
|
-
* - 插槽透传(label、error 等 FormItem 插槽)
|
|
7
|
+
* 将单个字段配置渲染为栅格项、FormItem 与控件,支持:
|
|
8
|
+
* - 字段属性分流(grid / formItem / component / slots)
|
|
9
|
+
* - 嵌套字段递归渲染(交由 BaseFormItems)
|
|
10
|
+
* - FormItem / 控件实例登记
|
|
13
11
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* 1. 遍历 fields 数组,过滤 hidden 字段
|
|
17
|
-
* 2. 通过 useGroupFieldAttrs Hook 纯计算将 field 配置拆分为 gridItemProps / formItemProps / componentProps / slots
|
|
18
|
-
* 3. 递归渲染 BaseFormItem(嵌套表单)或 BaseField(输入组件)
|
|
19
|
-
* 4. 通过 ref 回调收集 FormItem 和 Component 实例,注入到 field 对象上
|
|
20
|
-
*
|
|
21
|
-
* @param {Fields} [fields] - 字段配置数组
|
|
12
|
+
* @param {Field} field - 字段配置
|
|
22
13
|
* @param {boolean | GridProps} [grid] - 是否启用网格布局
|
|
23
|
-
* @param {boolean} [disabled] -
|
|
14
|
+
* @param {boolean} [disabled] - 上层下发的禁用状态
|
|
15
|
+
* @param {Function} [setFormItemRef] - FormItem 实例登记回调
|
|
16
|
+
* @param {Function} [setComponentRef] - 控件实例登记回调
|
|
24
17
|
*
|
|
25
18
|
* @internal
|
|
26
19
|
*/
|
|
27
20
|
import {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
} from '
|
|
39
|
-
import { computed, inject, toRaw, toValue } from 'vue';
|
|
40
|
-
import type { Fields, Grid } from '../../types';
|
|
21
|
+
computed,
|
|
22
|
+
defineComponent,
|
|
23
|
+
h,
|
|
24
|
+
toValue,
|
|
25
|
+
watch,
|
|
26
|
+
type PropType,
|
|
27
|
+
type VNode,
|
|
28
|
+
} from 'vue';
|
|
29
|
+
import { normalizePathKey } from '../../../../shared/core';
|
|
30
|
+
import { FormItem, GridItem as ElGridItem } from '../../../../shared/ui';
|
|
31
|
+
import type { Field, Grid } from '../../types';
|
|
41
32
|
import BaseField from '../BaseField/index.vue';
|
|
33
|
+
import BaseFormItems from '../BaseFormItems/index.vue';
|
|
42
34
|
import SlotComponent from '../SlotComponent/index.vue';
|
|
43
|
-
import
|
|
44
|
-
|
|
45
|
-
|
|
35
|
+
import {
|
|
36
|
+
useGroupedField,
|
|
37
|
+
type GroupedField,
|
|
38
|
+
} from '../../hooks/useGroupFieldAttrs';
|
|
46
39
|
|
|
47
|
-
|
|
40
|
+
export default defineComponent({
|
|
41
|
+
name: 'BaseFormItem',
|
|
42
|
+
inheritAttrs: false,
|
|
43
|
+
props: {
|
|
44
|
+
/** 字段配置 */
|
|
45
|
+
field: { type: Object as PropType<Field>, required: true },
|
|
46
|
+
/** 是否启用网格布局 */
|
|
47
|
+
grid: {
|
|
48
|
+
type: [Boolean, Object] as PropType<Grid>,
|
|
49
|
+
default: undefined,
|
|
50
|
+
},
|
|
51
|
+
/** 上层下发的禁用状态 */
|
|
52
|
+
disabled: { type: Boolean, default: undefined },
|
|
53
|
+
/** FormItem 实例登记回调 */
|
|
54
|
+
setFormItemRef: {
|
|
55
|
+
type: Function as PropType<
|
|
56
|
+
(field: Field, el: any, getFormItemProps: () => any) => void
|
|
57
|
+
>,
|
|
58
|
+
default: undefined,
|
|
59
|
+
},
|
|
60
|
+
/** 控件实例登记回调 */
|
|
61
|
+
setComponentRef: {
|
|
62
|
+
type: Function as PropType<(field: Field, el: any) => void>,
|
|
63
|
+
default: undefined,
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
setup(props) {
|
|
67
|
+
const grouped = useGroupedField(() => props.field);
|
|
68
|
+
const enableGrid = computed(() => !!props.grid);
|
|
48
69
|
|
|
49
|
-
type
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
70
|
+
// 控件级配置身份:字符串组件名 + type 段;组件对象无 Provider 配置,使用固定值
|
|
71
|
+
const componentKey = computed(() => {
|
|
72
|
+
const field = props.field as any;
|
|
73
|
+
const component = toValue(field.component);
|
|
74
|
+
if (typeof component !== 'string') return 'component-object';
|
|
75
|
+
return `string:${component}:${toValue(field.type) ?? ''}`;
|
|
76
|
+
});
|
|
77
|
+
const effectiveDisabled = computed(
|
|
78
|
+
() => toValue(props.field.disabled) ?? props.disabled
|
|
79
|
+
);
|
|
59
80
|
|
|
60
|
-
|
|
61
|
-
|
|
81
|
+
const setItemRef = (el: any) => {
|
|
82
|
+
props.setFormItemRef?.(
|
|
83
|
+
props.field,
|
|
84
|
+
el,
|
|
85
|
+
() => grouped.value.formItemProps
|
|
86
|
+
);
|
|
87
|
+
};
|
|
62
88
|
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
field => isObjectItem(field) && !toValue((field as any).hidden)
|
|
67
|
-
)
|
|
68
|
-
);
|
|
89
|
+
const setFieldRef = (el: any) => {
|
|
90
|
+
props.setComponentRef?.(props.field, el);
|
|
91
|
+
};
|
|
69
92
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
93
|
+
// 字段对象变化后,实例访问器归属当前字段
|
|
94
|
+
watch(
|
|
95
|
+
() => props.field,
|
|
96
|
+
(next, prev) => {
|
|
97
|
+
if (!prev || prev === next) return;
|
|
98
|
+
props.setFormItemRef?.(prev, null, () => grouped.value.formItemProps);
|
|
99
|
+
props.setComponentRef?.(prev, null);
|
|
100
|
+
},
|
|
101
|
+
{ flush: 'pre' }
|
|
102
|
+
);
|
|
73
103
|
|
|
74
|
-
|
|
104
|
+
/** 按容器组件逐层包裹当前节点 */
|
|
105
|
+
const withContainer = (
|
|
106
|
+
node: VNode,
|
|
107
|
+
component: any,
|
|
108
|
+
containerProps: Record<string, any>
|
|
109
|
+
): VNode =>
|
|
110
|
+
component ? h(component, containerProps, { default: () => node }) : node;
|
|
75
111
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
112
|
+
/** 组装 FormItem 的动态插槽与默认插槽 */
|
|
113
|
+
const renderFormItemSlots = (groupedField: GroupedField) => {
|
|
114
|
+
const slots: Record<string, any> = {};
|
|
115
|
+
Object.entries(groupedField.formItemSlots).forEach(([name, slot]) => {
|
|
116
|
+
slots[name] = (scope?: Record<string, any>) =>
|
|
117
|
+
h(SlotComponent as any, {
|
|
118
|
+
path: groupedField.path,
|
|
119
|
+
component: slot,
|
|
120
|
+
...(scope || {}),
|
|
121
|
+
});
|
|
122
|
+
});
|
|
81
123
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
124
|
+
slots.default = () => {
|
|
125
|
+
const field = props.field as any;
|
|
126
|
+
if (field.fields) {
|
|
127
|
+
return h(BaseFormItems as any, {
|
|
128
|
+
grid: field.grid ?? props.grid,
|
|
129
|
+
fields: field.fields,
|
|
130
|
+
disabled: effectiveDisabled.value,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
return h(BaseField as any, {
|
|
134
|
+
key: componentKey.value,
|
|
135
|
+
ref: setFieldRef,
|
|
136
|
+
...groupedField.componentProps,
|
|
137
|
+
path: groupedField.path,
|
|
138
|
+
disabled: effectiveDisabled.value,
|
|
139
|
+
});
|
|
140
|
+
};
|
|
141
|
+
return slots;
|
|
142
|
+
};
|
|
88
143
|
|
|
89
|
-
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
144
|
+
return () => {
|
|
145
|
+
const groupedField = grouped.value;
|
|
146
|
+
let node: VNode = h(
|
|
147
|
+
FormItem as any,
|
|
148
|
+
{
|
|
149
|
+
...groupedField.formItemProps,
|
|
150
|
+
ref: setItemRef,
|
|
151
|
+
prop: normalizePathKey(groupedField.path),
|
|
152
|
+
path: groupedField.path,
|
|
153
|
+
},
|
|
154
|
+
renderFormItemSlots(groupedField)
|
|
155
|
+
);
|
|
156
|
+
node = withContainer(node, groupedField.container, {
|
|
157
|
+
path: groupedField.path,
|
|
103
158
|
});
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
console.warn(
|
|
109
|
-
'[pro-components] 字段配置对象不可写(如被 Object.freeze),getFormItemRef / getComponentRef 等实例访问器挂载失败。'
|
|
159
|
+
node = withContainer(
|
|
160
|
+
node,
|
|
161
|
+
enableGrid.value ? ElGridItem : undefined,
|
|
162
|
+
groupedField.gridItemProps
|
|
110
163
|
);
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const setFormItemRef = (field: any, el: any, formItemProps?: any) => {
|
|
116
|
-
if (!field || typeof field !== 'object') return;
|
|
117
|
-
const raw = toRaw(field);
|
|
118
|
-
if (el) {
|
|
119
|
-
formItemInstanceMap.set(raw, el);
|
|
120
|
-
defineFieldAccessors(raw, {
|
|
121
|
-
getFormItemRef: () => formItemInstanceMap.get(raw),
|
|
122
|
-
getFormItemComputedProps: () => formItemProps,
|
|
123
|
-
});
|
|
124
|
-
} else {
|
|
125
|
-
formItemInstanceMap.delete(raw);
|
|
126
|
-
delete raw.getFormItemRef;
|
|
127
|
-
delete raw.getFormItemComputedProps;
|
|
128
|
-
}
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
const setComponentRef = (field: any, el: any) => {
|
|
132
|
-
if (!field || typeof field !== 'object') return;
|
|
133
|
-
const raw = toRaw(field);
|
|
134
|
-
if (el) {
|
|
135
|
-
componentInstanceMap.set(raw, el);
|
|
136
|
-
defineFieldAccessors(raw, {
|
|
137
|
-
getComponentRef: () => componentInstanceMap.get(raw)?.getComponentRef(),
|
|
138
|
-
getComponentComputedProps: () =>
|
|
139
|
-
componentInstanceMap.get(raw)?.getComponentComputedProps(),
|
|
140
|
-
});
|
|
141
|
-
} else {
|
|
142
|
-
componentInstanceMap.delete(raw);
|
|
143
|
-
delete raw.getComponentRef;
|
|
144
|
-
delete raw.getComponentComputedProps;
|
|
145
|
-
}
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
const groupedFields = useGroupFieldAttrs(validFields);
|
|
164
|
+
return node;
|
|
165
|
+
};
|
|
166
|
+
},
|
|
167
|
+
});
|
|
149
168
|
</script>
|
|
150
169
|
|
|
151
|
-
<template>
|
|
152
|
-
<ContainerFragment
|
|
153
|
-
:component="enableGrid ? ElGrid : undefined"
|
|
154
|
-
v-bind="computedGridProps"
|
|
155
|
-
style="width: 100%"
|
|
156
|
-
>
|
|
157
|
-
<template v-for="item of groupedFields" :key="item.renderKey">
|
|
158
|
-
<ContainerFragment
|
|
159
|
-
:component="enableGrid ? ElGridItem : undefined"
|
|
160
|
-
v-bind="item.gridItemProps"
|
|
161
|
-
>
|
|
162
|
-
<ContainerFragment :component="item.container" :path="item.path">
|
|
163
|
-
<FormItem
|
|
164
|
-
v-bind="item.formItemProps"
|
|
165
|
-
:ref="el => setFormItemRef(item.rawField, el, item.formItemProps)"
|
|
166
|
-
:prop="normalizePathKey(item.path)"
|
|
167
|
-
:path="item.path"
|
|
168
|
-
>
|
|
169
|
-
<template
|
|
170
|
-
v-for="(slot, name) in item.formItemSlots"
|
|
171
|
-
:key="name"
|
|
172
|
-
#[name]="scoped"
|
|
173
|
-
>
|
|
174
|
-
<SlotComponent
|
|
175
|
-
:path="item.path"
|
|
176
|
-
:component="slot"
|
|
177
|
-
v-bind="scoped"
|
|
178
|
-
/>
|
|
179
|
-
</template>
|
|
180
|
-
<template v-if="item.rawField.fields">
|
|
181
|
-
<BaseFormItem
|
|
182
|
-
:grid="(item.rawField as any).grid ?? props.grid"
|
|
183
|
-
:fields="item.rawField.fields"
|
|
184
|
-
:disabled="toValue(item.rawField.disabled) ?? props.disabled"
|
|
185
|
-
/>
|
|
186
|
-
</template>
|
|
187
|
-
<template v-else>
|
|
188
|
-
<BaseField
|
|
189
|
-
:ref="el => setComponentRef(item.rawField, el)"
|
|
190
|
-
v-bind="item.componentProps"
|
|
191
|
-
:path="item.path"
|
|
192
|
-
:disabled="toValue(item.rawField.disabled) ?? props.disabled"
|
|
193
|
-
/>
|
|
194
|
-
</template>
|
|
195
|
-
</FormItem>
|
|
196
|
-
</ContainerFragment>
|
|
197
|
-
</ContainerFragment>
|
|
198
|
-
</template>
|
|
199
|
-
</ContainerFragment>
|
|
200
|
-
</template>
|
|
201
|
-
|
|
202
170
|
<style scoped lang="less">
|
|
171
|
+
/* 分组字段的嵌套 FormItem 间距 */
|
|
203
172
|
[class*='-form-item'] [class*='-form-item'] {
|
|
204
173
|
margin-bottom: 18px;
|
|
205
174
|
}
|