@qin-ui/element-plus-pro 1.4.3 → 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.
@@ -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,EAET,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"}
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",
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.1.1"
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,获取或创建对应的 inject 配置
78
- * 将用户提供的值合并到默认值上,剔除该注入项的不可注入键后通过 provide 响应式注入到子组件树
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
- ...config.default,
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(() => (props.componentVars as Record<string, any>) ?? {})
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(() => props.componentMap)
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(() => props.locale)
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
- * 全局默认配置注入:key = 组件名 + type 修饰段,inject 须在 setup 同步期调用。
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 injectConfigKey =
90
- typeof props.component === 'string'
91
- ? [props.component, typeVal].filter(Boolean).join('.')
92
- : '';
93
- const componentInjectConfig = injectConfigKey
94
- ? getInjectConfig(injectConfigKey)
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 rawInjectComponentProps = componentInjectConfig
97
- ? inject(componentInjectConfig.injectionKey, componentInjectConfig.default)
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
- ...(toValue(rawInjectComponentProps) || {}),
154
- ...getObject(toValue(componentVars)?.[injectConfigKey]),
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
- attrs,
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 组件名由 `component` 与 `type` 拼接(如 `input.password`);`component` 非字符串时返回空记录。
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 k = [component, type].filter(Boolean).join('.');
82
- return { ...injectProps, ...getPlaceholderProps(k, injectProps, t) };
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
  };
@@ -105,7 +105,14 @@ const fields = computed(() => {
105
105
  return (Array.isArray(f) ? f : f?.value) ?? [];
106
106
  });
107
107
  const formData = computed(() => currentForm.value?.formData);
108
- const setFormRef = (el: any) => currentForm.value?.setFormRef?.(el);
108
+ /*
109
+ * ref 回调按渲染期实例路由:卸载回调(null)写回该子树所属表单,
110
+ * 运行期替换 :form 后旧实例的 formRef 同步清空
111
+ */
112
+ const formRefSetter = computed(() => {
113
+ const form = currentForm.value;
114
+ return (el: any) => form?.setFormRef?.(el);
115
+ });
109
116
 
110
117
  /*
111
118
  * formKey 子树重挂载契约:以 WeakMap 为每个 form 实例生成自增 key,绑定到原生 Form 的 :key
@@ -172,7 +179,7 @@ provide(InjectionFormSlotsKey, formSlotsRef);
172
179
  <!-- el-form 渲染原生 form 元素,拦截回车触发的默认提交 -->
173
180
  <ElForm
174
181
  :key="formKey"
175
- :ref="setFormRef"
182
+ :ref="formRefSetter"
176
183
  :model="formData"
177
184
  v-bind="formAttrs"
178
185
  class="pro-form"
@@ -87,6 +87,7 @@ import { useLocale } from '../../../locale';
87
87
  import type { Path } from '../../../shared/core';
88
88
  import {
89
89
  camelizeProperties,
90
+ callListeners,
90
91
  getObject,
91
92
  isObjectItem,
92
93
  isPlainObject,
@@ -243,16 +244,21 @@ const _search = async () => {
243
244
  if (props.search && attrs.onSearch) {
244
245
  warnSearchConfig('duplicate');
245
246
  }
246
- if (!search) return;
247
- const searchPromise = search();
248
- if (!isPromise(searchPromise)) {
247
+ const results = callListeners(search);
248
+ if (!results.length) return;
249
+ const promises = results.filter(isPromise);
250
+ if (!promises.length) {
249
251
  warnSearchConfig('not-promise');
250
252
  return;
251
253
  }
252
254
  const seq = ++searchSequence;
253
255
  loading.value = true;
254
256
  try {
255
- await searchPromise;
257
+ const settled = await Promise.allSettled(promises);
258
+ const rejected = settled.find(item => item.status === 'rejected') as
259
+ | PromiseRejectedResult
260
+ | undefined;
261
+ if (rejected) throw rejected.reason;
256
262
  } finally {
257
263
  if (seq === searchSequence) {
258
264
  loading.value = false;
@@ -472,7 +478,7 @@ const onSizeChange = (pageSize: number) => {
472
478
 
473
479
  const onPaginationChange = (currentPage: number, pageSize: number) => {
474
480
  // 透传 el-pagination change 回调
475
- attrs.onChange?.(currentPage, pageSize);
481
+ callListeners(attrs.onChange, currentPage, pageSize);
476
482
  };
477
483
 
478
484
  const searchFormVisible = computed(() => {
@@ -59,6 +59,7 @@ export type Column<D extends Data = Data> = Partial<
59
59
  * 列是否隐藏;支持布尔、Ref 与 ComputedRef 形式,渲染期按 `toValue` 取值
60
60
  *
61
61
  * 分组列的子列同样参与过滤(递归生效)。
62
+ * 只读 ref(如 `computed`)经 `setColumn` 写入时会被普通值替换,可写 ref 保持绑定。
62
63
  */
63
64
  hidden?: MaybeRefOrComputedRef<boolean>;
64
65
  /** 自定义渲染函数 */
@@ -23,6 +23,7 @@ export {
23
23
  InjectionFormSlotsKey,
24
24
  // utils
25
25
  getObject,
26
+ mergeComponentVars,
26
27
  omitBy,
27
28
  get,
28
29
  set,
@@ -35,6 +36,7 @@ export {
35
36
  isPlainObject,
36
37
  isObjectItem,
37
38
  isPromise,
39
+ callListeners,
38
40
  // locale
39
41
  zhCN,
40
42
  zhTW,