@qin-ui/antd-vue-pro 2.3.3 → 2.4.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 (166) hide show
  1. package/README.md +7 -5
  2. package/api.json +1 -25
  3. package/es/__tests__/BaseField.spec.d.ts +2 -0
  4. package/es/__tests__/BaseField.spec.d.ts.map +1 -0
  5. package/es/__tests__/BaseFormItem.spec.d.ts +2 -0
  6. package/es/__tests__/BaseFormItem.spec.d.ts.map +1 -0
  7. package/es/__tests__/ProForm.spec.d.ts +2 -0
  8. package/es/__tests__/ProForm.spec.d.ts.map +1 -0
  9. package/es/__tests__/ProTable.spec.d.ts +2 -0
  10. package/es/__tests__/ProTable.spec.d.ts.map +1 -0
  11. package/es/__tests__/SearchForm.spec.d.ts +2 -0
  12. package/es/__tests__/SearchForm.spec.d.ts.map +1 -0
  13. package/es/__tests__/controls.spec.d.ts +2 -0
  14. package/es/__tests__/controls.spec.d.ts.map +1 -0
  15. package/es/__tests__/helpers/fixtures.d.ts +15 -0
  16. package/es/__tests__/helpers/fixtures.d.ts.map +1 -0
  17. package/es/__tests__/helpers/mount.d.ts +38 -0
  18. package/es/__tests__/helpers/mount.d.ts.map +1 -0
  19. package/es/__tests__/hooks-locale.spec.d.ts +2 -0
  20. package/es/__tests__/hooks-locale.spec.d.ts.map +1 -0
  21. package/es/__tests__/index.spec.d.ts +2 -0
  22. package/es/__tests__/index.spec.d.ts.map +1 -0
  23. package/es/__tests__/integration.spec.d.ts +2 -0
  24. package/es/__tests__/integration.spec.d.ts.map +1 -0
  25. package/es/__tests__/setup.d.ts +14 -0
  26. package/es/__tests__/setup.d.ts.map +1 -0
  27. package/es/antd-vue-pro.css +13 -13
  28. package/es/index.js +435 -319
  29. package/es/index.js.map +1 -1
  30. package/es/{components → src/components}/component-provider/components/index.vue.d.ts +5 -1
  31. package/es/src/components/component-provider/components/index.vue.d.ts.map +1 -0
  32. package/es/src/components/component-provider/constants/index.d.ts.map +1 -0
  33. package/es/src/components/component-provider/index.d.ts.map +1 -0
  34. package/es/src/components/component-provider/types/index.d.ts.map +1 -0
  35. package/es/{components → src/components}/form/components/BaseField/index.vue.d.ts +4 -1
  36. package/es/src/components/form/components/BaseField/index.vue.d.ts.map +1 -0
  37. package/es/src/components/form/components/BaseField/utils/index.d.ts +5 -0
  38. package/es/src/components/form/components/BaseField/utils/index.d.ts.map +1 -0
  39. package/es/{components → src/components}/form/components/BaseFormItem/index.vue.d.ts +5 -1
  40. package/es/src/components/form/components/BaseFormItem/index.vue.d.ts.map +1 -0
  41. package/es/{components → src/components}/form/components/ContainerFragment/index.vue.d.ts +3 -1
  42. package/es/src/components/form/components/ContainerFragment/index.vue.d.ts.map +1 -0
  43. package/es/src/components/form/components/ProForm/index.vue.d.ts.map +1 -0
  44. package/es/src/components/form/components/SlotComponent/index.vue.d.ts +11 -0
  45. package/es/src/components/form/components/SlotComponent/index.vue.d.ts.map +1 -0
  46. package/es/src/components/form/components/index.d.ts.map +1 -0
  47. package/es/{components → src/components}/form/constants/index.d.ts +1 -1
  48. package/es/src/components/form/constants/index.d.ts.map +1 -0
  49. package/es/src/components/form/hooks/index.d.ts.map +1 -0
  50. package/es/src/components/form/hooks/useFields.d.ts.map +1 -0
  51. package/es/src/components/form/hooks/useForm.d.ts.map +1 -0
  52. package/es/src/components/form/hooks/useFormRef.d.ts.map +1 -0
  53. package/es/src/components/form/hooks/useGroupFieldAttrs.d.ts +22 -0
  54. package/es/src/components/form/hooks/useGroupFieldAttrs.d.ts.map +1 -0
  55. package/es/src/components/form/index.d.ts.map +1 -0
  56. package/es/{components → src/components}/form/types/index.d.ts +26 -2
  57. package/es/src/components/form/types/index.d.ts.map +1 -0
  58. package/es/{components → src/components}/table/components/ColumnControl.vue.d.ts +4 -1
  59. package/es/src/components/table/components/ColumnControl.vue.d.ts.map +1 -0
  60. package/es/src/components/table/components/DefaultSearchFormContainer.vue.d.ts.map +1 -0
  61. package/es/src/components/table/components/DefaultTableContainer.vue.d.ts.map +1 -0
  62. package/es/{components → src/components}/table/components/ProTable.vue.d.ts +0 -2
  63. package/es/src/components/table/components/ProTable.vue.d.ts.map +1 -0
  64. package/es/{components → src/components}/table/components/SearchForm.vue.d.ts +14 -4
  65. package/es/src/components/table/components/SearchForm.vue.d.ts.map +1 -0
  66. package/es/src/components/table/components/SizeControl.vue.d.ts.map +1 -0
  67. package/es/src/components/table/components/icons/ColumnHeightOutlined.vue.d.ts.map +1 -0
  68. package/es/src/components/table/components/icons/DownOutlined.vue.d.ts.map +1 -0
  69. package/es/src/components/table/components/icons/FilterOutlined.vue.d.ts.map +1 -0
  70. package/es/src/components/table/components/index.d.ts.map +1 -0
  71. package/es/src/components/table/hooks/index.d.ts.map +1 -0
  72. package/es/src/components/table/hooks/useTable.d.ts.map +1 -0
  73. package/es/src/components/table/index.d.ts.map +1 -0
  74. package/es/src/components/table/types/index.d.ts.map +1 -0
  75. package/es/{index.d.ts → src/index.d.ts} +1 -1
  76. package/es/src/index.d.ts.map +1 -0
  77. package/es/src/locale/index.d.ts.map +1 -0
  78. package/es/src/shared/core/index.d.ts +6 -0
  79. package/es/src/shared/core/index.d.ts.map +1 -0
  80. package/es/src/shared/ui/index.d.ts.map +1 -0
  81. package/package.json +8 -3
  82. package/src/components/component-provider/components/index.vue +37 -8
  83. package/src/components/component-provider/constants/index.ts +2 -1
  84. package/src/components/form/components/BaseField/index.vue +61 -34
  85. package/src/components/form/components/BaseField/utils/index.ts +6 -11
  86. package/src/components/form/components/BaseFormItem/index.vue +91 -94
  87. package/src/components/form/components/ContainerFragment/index.vue +4 -2
  88. package/src/components/form/components/ProForm/index.vue +70 -18
  89. package/src/components/form/components/SlotComponent/index.vue +6 -4
  90. package/src/components/form/constants/index.ts +1 -5
  91. package/src/components/form/hooks/useGroupFieldAttrs.ts +126 -0
  92. package/src/components/form/types/index.ts +26 -2
  93. package/src/components/table/components/ColumnControl.vue +16 -15
  94. package/src/components/table/components/ProTable.vue +92 -65
  95. package/src/components/table/components/SearchForm.vue +80 -59
  96. package/src/components/table/components/SizeControl.vue +4 -2
  97. package/src/index.ts +1 -1
  98. package/src/shared/core/index.ts +4 -2
  99. package/es/components/component-provider/components/index.vue.d.ts.map +0 -1
  100. package/es/components/component-provider/constants/index.d.ts.map +0 -1
  101. package/es/components/component-provider/index.d.ts.map +0 -1
  102. package/es/components/component-provider/types/index.d.ts.map +0 -1
  103. package/es/components/form/components/BaseField/index.vue.d.ts.map +0 -1
  104. package/es/components/form/components/BaseField/utils/index.d.ts +0 -5
  105. package/es/components/form/components/BaseField/utils/index.d.ts.map +0 -1
  106. package/es/components/form/components/BaseFormItem/index.vue.d.ts.map +0 -1
  107. package/es/components/form/components/ContainerFragment/index.vue.d.ts.map +0 -1
  108. package/es/components/form/components/GroupedFieldAttrs/index.vue.d.ts +0 -29
  109. package/es/components/form/components/GroupedFieldAttrs/index.vue.d.ts.map +0 -1
  110. package/es/components/form/components/PathProvider/index.vue.d.ts +0 -24
  111. package/es/components/form/components/PathProvider/index.vue.d.ts.map +0 -1
  112. package/es/components/form/components/ProForm/index.vue.d.ts.map +0 -1
  113. package/es/components/form/components/SlotComponent/index.vue.d.ts +0 -7
  114. package/es/components/form/components/SlotComponent/index.vue.d.ts.map +0 -1
  115. package/es/components/form/components/index.d.ts.map +0 -1
  116. package/es/components/form/constants/index.d.ts.map +0 -1
  117. package/es/components/form/hooks/index.d.ts.map +0 -1
  118. package/es/components/form/hooks/useFields.d.ts.map +0 -1
  119. package/es/components/form/hooks/useForm.d.ts.map +0 -1
  120. package/es/components/form/hooks/useFormRef.d.ts.map +0 -1
  121. package/es/components/form/index.d.ts.map +0 -1
  122. package/es/components/form/types/index.d.ts.map +0 -1
  123. package/es/components/table/components/ColumnControl.vue.d.ts.map +0 -1
  124. package/es/components/table/components/DefaultSearchFormContainer.vue.d.ts.map +0 -1
  125. package/es/components/table/components/DefaultTableContainer.vue.d.ts.map +0 -1
  126. package/es/components/table/components/ProTable.vue.d.ts.map +0 -1
  127. package/es/components/table/components/SearchForm.vue.d.ts.map +0 -1
  128. package/es/components/table/components/SizeControl.vue.d.ts.map +0 -1
  129. package/es/components/table/components/icons/ColumnHeightOutlined.vue.d.ts.map +0 -1
  130. package/es/components/table/components/icons/DownOutlined.vue.d.ts.map +0 -1
  131. package/es/components/table/components/icons/FilterOutlined.vue.d.ts.map +0 -1
  132. package/es/components/table/components/index.d.ts.map +0 -1
  133. package/es/components/table/hooks/index.d.ts.map +0 -1
  134. package/es/components/table/hooks/useTable.d.ts.map +0 -1
  135. package/es/components/table/index.d.ts.map +0 -1
  136. package/es/components/table/types/index.d.ts.map +0 -1
  137. package/es/index.d.ts.map +0 -1
  138. package/es/locale/index.d.ts.map +0 -1
  139. package/es/shared/core/index.d.ts +0 -6
  140. package/es/shared/core/index.d.ts.map +0 -1
  141. package/es/shared/ui/index.d.ts.map +0 -1
  142. package/src/components/form/components/GroupedFieldAttrs/index.vue +0 -118
  143. package/src/components/form/components/PathProvider/index.vue +0 -19
  144. /package/es/{components → src/components}/component-provider/constants/index.d.ts +0 -0
  145. /package/es/{components → src/components}/component-provider/index.d.ts +0 -0
  146. /package/es/{components → src/components}/component-provider/types/index.d.ts +0 -0
  147. /package/es/{components → src/components}/form/components/ProForm/index.vue.d.ts +0 -0
  148. /package/es/{components → src/components}/form/components/index.d.ts +0 -0
  149. /package/es/{components → src/components}/form/hooks/index.d.ts +0 -0
  150. /package/es/{components → src/components}/form/hooks/useFields.d.ts +0 -0
  151. /package/es/{components → src/components}/form/hooks/useForm.d.ts +0 -0
  152. /package/es/{components → src/components}/form/hooks/useFormRef.d.ts +0 -0
  153. /package/es/{components → src/components}/form/index.d.ts +0 -0
  154. /package/es/{components → src/components}/table/components/DefaultSearchFormContainer.vue.d.ts +0 -0
  155. /package/es/{components → src/components}/table/components/DefaultTableContainer.vue.d.ts +0 -0
  156. /package/es/{components → src/components}/table/components/SizeControl.vue.d.ts +0 -0
  157. /package/es/{components → src/components}/table/components/icons/ColumnHeightOutlined.vue.d.ts +0 -0
  158. /package/es/{components → src/components}/table/components/icons/DownOutlined.vue.d.ts +0 -0
  159. /package/es/{components → src/components}/table/components/icons/FilterOutlined.vue.d.ts +0 -0
  160. /package/es/{components → src/components}/table/components/index.d.ts +0 -0
  161. /package/es/{components → src/components}/table/hooks/index.d.ts +0 -0
  162. /package/es/{components → src/components}/table/hooks/useTable.d.ts +0 -0
  163. /package/es/{components → src/components}/table/index.d.ts +0 -0
  164. /package/es/{components → src/components}/table/types/index.d.ts +0 -0
  165. /package/es/{locale → src/locale}/index.d.ts +0 -0
  166. /package/es/{shared → src/shared}/ui/index.d.ts +0 -0
@@ -0,0 +1,126 @@
1
+ import { computed, inject, mergeProps, toValue, type ComputedRef } from 'vue';
2
+ import {
3
+ formItemProps,
4
+ gridItemProps,
5
+ type FormItemProps,
6
+ type GridItemProps,
7
+ } from '../../../shared/ui';
8
+ import { isPlainObject } from '../../../shared/core';
9
+ import { INJECT_CONFIG } from '../../component-provider/constants';
10
+ import { FORM_ITEM_SLOT_KEYS } from '../constants';
11
+ import type { Base, Field } from '../types';
12
+
13
+ const formItemPropKeys = Object.keys(formItemProps()).concat([
14
+ 'formItemContainer',
15
+ ]);
16
+ const gridItemPropKeys = Object.keys(gridItemProps());
17
+
18
+ export interface GroupedField {
19
+ path: string;
20
+ gridItemProps: GridItemProps;
21
+ formItemProps: FormItemProps;
22
+ formItemSlots: Record<(typeof FORM_ITEM_SLOT_KEYS)[number], any>;
23
+ componentProps: Record<string, any>;
24
+ formItemContainer?: Base['formItemContainer'];
25
+ rawField: Field;
26
+ }
27
+
28
+ /**
29
+ * 将 fields 配置数组逐个拆分为 grid / formItem / component / slots 分组。
30
+ *
31
+ * @description
32
+ * 1. 响应式集成 ProComponentProvider 的 `pro-form-item` 全局变量配置;
33
+ * 2. 剥离 `extraProps`(用户自定义字段标识袋):保留在字段原始对象上供业务层存取,渲染层经解构剥离,避免落入 componentProps 透传为无效 DOM 属性。
34
+ */
35
+ export function useGroupFieldAttrs(validFields: ComputedRef<Field[]>) {
36
+ const config = INJECT_CONFIG['pro-form-item'];
37
+ const injectFormItemProps = inject(config.injectionKey, config.default);
38
+
39
+ return computed<GroupedField[]>(() => {
40
+ const rawInject = toValue(injectFormItemProps) || {};
41
+ return validFields.value.map(field => {
42
+ let gridItemProps: Record<string, any> = {};
43
+ let formItemProps: Record<string, any> = {};
44
+ const componentProps: Record<string, any> = { slots: {} };
45
+ const formItemSlots: Record<string, any> = {};
46
+
47
+ if (isPlainObject(field)) {
48
+ // prettier-ignore
49
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
50
+ const { path, name, fields, formItemClass, formItemStyle, hidden, span, getFormItemRef, getComponentRef, getFormItemComputedProps, getComponentComputedProps, slots = {}, formItemDataAttrs = {}, componentDataAttrs = {}, extraProps, formItemContainer, ...rest } =
51
+ field as any;
52
+
53
+ const {
54
+ class: injectClassName,
55
+ style: injectStyle,
56
+ span: injectSpan,
57
+ xs,
58
+ sm,
59
+ md,
60
+ lg,
61
+ xl,
62
+ xxl,
63
+ ...injectRest
64
+ } = rawInject;
65
+
66
+ // 字段显式 span 优先,否则回退注入配置的响应式断点
67
+ const initGridItemProps =
68
+ span || span === 0
69
+ ? { span }
70
+ : { xs, sm, md, lg, xl, xxl, span: injectSpan };
71
+
72
+ gridItemProps = fields ? { span: span ?? 24 } : initGridItemProps;
73
+ formItemProps = mergeProps(
74
+ injectRest,
75
+ { class: injectClassName, style: injectStyle },
76
+ { class: toValue(formItemClass), style: toValue(formItemStyle) },
77
+ formItemDataAttrs
78
+ );
79
+
80
+ Object.keys(rest).forEach(k => {
81
+ if (gridItemPropKeys.includes(k)) {
82
+ gridItemProps[k] = rest[k];
83
+ } else if (formItemPropKeys.includes(k)) {
84
+ formItemProps[k] = rest[k];
85
+ } else {
86
+ componentProps[k] = rest[k];
87
+ }
88
+ });
89
+
90
+ Object.assign(componentProps, componentDataAttrs);
91
+ Object.keys(slots).forEach(k => {
92
+ if (FORM_ITEM_SLOT_KEYS.includes(k as any)) {
93
+ formItemSlots[k] = slots[k];
94
+ } else {
95
+ componentProps.slots[k] = slots[k];
96
+ }
97
+ });
98
+
99
+ const raw = (toValue(name) ?? toValue(path)) as
100
+ | string
101
+ | number[]
102
+ | undefined;
103
+ return {
104
+ path: Array.isArray(raw) ? raw.join('.') : (raw as string) || '',
105
+ gridItemProps: gridItemProps as GridItemProps,
106
+ formItemProps: formItemProps as any,
107
+ formItemSlots,
108
+ componentProps,
109
+ formItemContainer,
110
+ rawField: field,
111
+ };
112
+ }
113
+
114
+ const raw =
115
+ toValue((field as any)?.name) ?? toValue((field as any)?.path);
116
+ return {
117
+ path: Array.isArray(raw) ? raw.join('.') : (raw as string) || '',
118
+ gridItemProps: gridItemProps as GridItemProps,
119
+ formItemProps: formItemProps as any,
120
+ formItemSlots,
121
+ componentProps,
122
+ rawField: field,
123
+ };
124
+ });
125
+ });
126
+ }
@@ -30,9 +30,33 @@ export type VModelProps<T = any> = {
30
30
  'onUpdate:value'?: (val: T) => void;
31
31
  };
32
32
 
33
+ /**
34
+ * 字段值格式化/转换处理器
35
+ *
36
+ * @description 支持函数形态或包含 get/set 方法的对象形态。
37
+ *
38
+ * ### 行为与契约说明
39
+ * 1. **旧值参数按需注入**:底层基于函数的形参声明个数(`fn.length > 1`)决定是否读取旧值。若转换逻辑需要使用旧值,请显式声明两个形参 `(val, oldVal) => ...`(请勿使用默认参数或 `...args` 剩余参数,否则 `fn.length` 无法正确识别);
40
+ * 2. **只读快照副本**:传入的 `oldVal` 为只读快照副本,不得依赖原地修改写回;仅当 formatter 声明双形参时才克隆旧值,单参转换零开销。
41
+ *
42
+ * @example
43
+ * ```ts
44
+ * // 1. 单参数转换(常见):无需旧值,零多余开销
45
+ * valueFormatter: (val) => val?.trim()
46
+ *
47
+ * // 2. 双参数转换:需要基于旧值做对比或回退
48
+ * valueFormatter: (val, oldVal) => (isValid(val) ? val : oldVal)
49
+ *
50
+ * // 3. 对象形态:分别定义读(展示)与写(存储)转换
51
+ * valueFormatter: {
52
+ * get: (val) => (val ? dayjs(val).format('YYYY-MM-DD') : ''),
53
+ * set: (val, oldVal) => (val ? dayjs(val).valueOf() : undefined),
54
+ * }
55
+ * ```
56
+ */
33
57
  export type ValueFormatter =
34
- | { (val: any, oldVal: any): any }
35
- | { get?: (val: any) => any; set?: (val: any, oldVal: any) => any };
58
+ | { (val: any, oldVal?: any): any }
59
+ | { get?: (val: any) => any; set?: (val: any, oldVal?: any) => any };
36
60
 
37
61
  /**
38
62
  * @description 自定义组件
@@ -18,11 +18,10 @@ type Props = {
18
18
  table?: Table;
19
19
  columnControl?: ColumnControlConfig;
20
20
  };
21
- const {
22
- columns,
23
- table = undefined,
24
- columnControl = undefined,
25
- } = defineProps<Props>();
21
+ const props = withDefaults(defineProps<Props>(), {
22
+ table: undefined,
23
+ columnControl: undefined,
24
+ });
26
25
 
27
26
  const { t } = useLocale();
28
27
 
@@ -39,7 +38,7 @@ const checkedColumnsOptions = computed<
39
38
  disabled: boolean;
40
39
  }>
41
40
  >(() =>
42
- columns.flatMap(item => {
41
+ props.columns.flatMap(item => {
43
42
  const rawKey =
44
43
  item.key ??
45
44
  (Array.isArray(item.dataIndex)
@@ -47,12 +46,14 @@ const checkedColumnsOptions = computed<
47
46
  : item.dataIndex);
48
47
  if (!rawKey || !item.title) return [];
49
48
  const key = String(rawKey);
50
- if (columnControl?.excludedKeys?.some(ek => String(ek) === key)) return [];
49
+ if (props.columnControl?.excludedKeys?.some(ek => String(ek) === key))
50
+ return [];
51
51
  const disabled =
52
- columnControl?.disabledKeys?.some(dk => String(dk) === key) ?? false;
52
+ props.columnControl?.disabledKeys?.some(dk => String(dk) === key) ??
53
+ false;
53
54
  // labels 优先;title 为字符串时直接使用;vnode 等其他类型降级为 key,避免渲染异常
54
55
  const label =
55
- (columnControl?.labels?.[key] as string) ??
56
+ (props.columnControl?.labels?.[key] as string) ??
56
57
  (typeof item.title === 'string' ? item.title : key);
57
58
  return {
58
59
  label,
@@ -77,7 +78,7 @@ const checkedColumnKeys = computed({
77
78
  set(val) {
78
79
  checkedColumnsOptions.value.forEach(item => {
79
80
  if (item.disabled) return;
80
- table?.setColumn?.(item.value, {
81
+ props.table?.setColumn?.(item.value, {
81
82
  hidden: !val.includes(item.value),
82
83
  });
83
84
  });
@@ -122,16 +123,16 @@ watch(
122
123
 
123
124
  // 强制 disabledKeys 列始终展示
124
125
  onMounted(() => {
125
- columnControl?.disabledKeys?.forEach(key => {
126
- table?.setColumn?.(String(key), { hidden: false });
126
+ props.columnControl?.disabledKeys?.forEach(key => {
127
+ props.table?.setColumn?.(String(key), { hidden: false });
127
128
  });
128
129
  });
129
130
 
130
131
  watch(
131
- () => columnControl?.disabledKeys,
132
+ () => props.columnControl?.disabledKeys,
132
133
  keys => {
133
134
  keys?.forEach(key => {
134
- table?.setColumn?.(String(key), { hidden: false });
135
+ props.table?.setColumn?.(String(key), { hidden: false });
135
136
  });
136
137
  },
137
138
  { deep: true }
@@ -149,7 +150,7 @@ watch(
149
150
  :selectable="false"
150
151
  >
151
152
  <MenuItem
152
- v-if="!columnControl?.disableCheckAll"
153
+ v-if="!props.columnControl?.disableCheckAll"
153
154
  :key="0"
154
155
  @click="onCheckAllChange"
155
156
  >
@@ -45,6 +45,7 @@ import {
45
45
  useAttrs,
46
46
  onMounted,
47
47
  inject,
48
+ toValue,
48
49
  type Slot,
49
50
  } from 'vue';
50
51
  import { INJECT_CONFIG } from '../../component-provider/constants';
@@ -55,9 +56,11 @@ import { SearchFormProps } from './SearchForm.vue';
55
56
  import type { Table } from '../hooks/useTable';
56
57
  import { useLocale } from '../../../locale';
57
58
  import {
58
- camelizeProperties,
59
59
  getObject,
60
+ isPlainObject,
60
61
  pick,
62
+ isPromise,
63
+ camelizeProperties,
61
64
  Path,
62
65
  } from '../../../shared/core';
63
66
  import { ComponentSlots } from 'vue-component-type-helpers';
@@ -100,61 +103,64 @@ type Props = {
100
103
  tableContainer?: ContainerComponent | false;
101
104
  } & /* @vue-ignore */ TableProps;
102
105
 
103
- const {
104
- table = undefined,
105
- search = undefined,
106
- addIndexColumn = undefined,
107
- control = undefined,
108
- tableContainer = undefined,
109
- immediateSearch = undefined,
110
- searchFormConfig = undefined,
111
- } = defineProps<Props>();
106
+ const props = withDefaults(defineProps<Props>(), {
107
+ table: undefined,
108
+ search: undefined,
109
+ addIndexColumn: undefined,
110
+ immediateSearch: undefined,
111
+ control: undefined,
112
+ searchFormConfig: undefined,
113
+ tableContainer: undefined,
114
+ });
112
115
 
113
116
  const { t } = useLocale();
114
117
 
115
118
  const config = INJECT_CONFIG['pro-table'];
116
- const injectProps = inject(config.injectionKey, config.default);
119
+ const injectPropsRaw = inject(config.injectionKey, config.default);
120
+ const injectProps = computed(() => toValue(injectPropsRaw) || {});
117
121
 
118
122
  const tableProperties = Object.keys(tableProps());
119
123
 
120
- const injectAttrs = pick(injectProps, tableProperties) as TableProps;
124
+ const injectAttrs = computed<TableProps>(
125
+ () => pick(injectProps.value, tableProperties) as TableProps
126
+ );
121
127
 
122
128
  const computedSearchFormConfig = computed(() => {
123
129
  const container =
124
- searchFormConfig?.container ??
125
- injectProps.searchFormConfig?.container ??
130
+ props.searchFormConfig?.container ??
131
+ injectProps.value.searchFormConfig?.container ??
126
132
  DefaultSearchFormContainer;
127
133
  return {
128
- ...injectProps.searchFormConfig,
129
- ...getObject(searchFormConfig),
134
+ ...injectProps.value.searchFormConfig,
135
+ ...getObject(props.searchFormConfig),
130
136
  container: container ? container : undefined,
131
137
  };
132
138
  });
133
139
 
134
140
  const attrs: Record<string, any> = useAttrs();
135
141
  const tableAttrs = computed<TableProps>(() => {
136
- return pick(camelizeProperties(attrs), tableProperties);
142
+ return pick(camelizeProperties(attrs), tableProperties) as TableProps;
137
143
  });
138
144
 
139
- const { columns, dataSource, searchForm, pageParam, setPageParam } =
140
- table || {};
141
-
142
145
  const size = defineModel<TableProps['size']>('size');
143
- const loading = defineModel<boolean>('loading');
146
+ const loading = defineModel<boolean>('loading', { default: false });
144
147
 
145
148
  // 核心搜索方法:设置 loading 状态,调用外部 search 函数
146
149
  const _search = async () => {
147
- try {
150
+ const searchPromise = (props.search || attrs.onSearch)?.();
151
+ if (isPromise(searchPromise)) {
148
152
  loading.value = true;
149
- await search?.();
150
- } finally {
151
- loading.value = false;
153
+ try {
154
+ await searchPromise;
155
+ } finally {
156
+ loading.value = false;
157
+ }
152
158
  }
153
159
  };
154
160
 
155
161
  // 重置:恢复查询参数到初始值,重新搜索
156
162
  const reset = () => {
157
- table?.resetQueryParams();
163
+ props.table?.resetQueryParams?.();
158
164
  nextTick(() => {
159
165
  _search();
160
166
  });
@@ -167,7 +173,6 @@ type TableSlots = Omit<ComponentSlots<typeof ATable>, 'bodyCell'> &
167
173
  Readonly<{
168
174
  bodyCell?: (props: {
169
175
  text: any;
170
- value: any;
171
176
  record: RecordType;
172
177
  index: number;
173
178
  column: Column<RecordType>;
@@ -186,13 +191,13 @@ const {
186
191
  } = slots;
187
192
 
188
193
  const searchPage1st = () => {
189
- setPageParam?.({ current: 1 });
194
+ props.table?.setPageParam?.({ current: 1 });
190
195
  _search();
191
196
  };
192
197
 
193
198
  const computedTableProps = computed<TableProps>(() => {
194
199
  return {
195
- ...injectAttrs,
200
+ ...injectAttrs.value,
196
201
  ...tableAttrs.value,
197
202
  pagination: undefined,
198
203
  onChange: undefined,
@@ -201,65 +206,84 @@ const computedTableProps = computed<TableProps>(() => {
201
206
 
202
207
  const computedTableContainer = computed(() => {
203
208
  const container =
204
- tableContainer ?? injectProps.tableContainer ?? DefaultTableContainer;
209
+ props.tableContainer ??
210
+ injectProps.value.tableContainer ??
211
+ DefaultTableContainer;
205
212
  return container ? container : undefined;
206
213
  });
207
214
 
208
215
  type ReturnGenericParameterTypes<V> = V extends Table<any, infer R> ? R : never;
209
216
  type RecordType = ReturnGenericParameterTypes<T>;
210
217
 
211
- const indexColumn = (): ColumnType => ({
218
+ const renderIndex: ColumnType['customRender'] = ({ index }) => index + 1;
219
+
220
+ const indexColumn = computed<ColumnType>(() => ({
212
221
  title: t('table.index'),
213
222
  dataIndex: '_index',
223
+ key: '_index',
214
224
  width: 80,
215
- customRender: ({ index }) => index + 1,
225
+ customRender: renderIndex,
226
+ }));
227
+
228
+ const computedColumns = computed<Columns<RecordType>>(() => {
229
+ const cols = (tableAttrs.value.columns ??
230
+ toValue(props.table?.columns) ??
231
+ []) as any;
232
+ const needIndex = props.addIndexColumn ?? injectProps.value.addIndexColumn;
233
+ return needIndex ? [indexColumn.value, ...cols] : cols;
216
234
  });
217
235
 
218
- const computedColumns = computed(
219
- () =>
220
- [
221
- ...((addIndexColumn ?? injectProps.addIndexColumn)
222
- ? [indexColumn()]
223
- : []),
224
- ...(tableAttrs.value.columns ?? columns?.value ?? []),
225
- ] as Columns<RecordType>
226
- );
227
-
228
236
  const visibleComputedColumns = computed(() => {
229
237
  return computedColumns.value.filter(item => !(item as Column).hidden);
230
238
  });
231
239
 
232
240
  const computedDataSource = computed<RecordType[]>(() => {
233
- return (tableAttrs.value.dataSource as any[]) ?? dataSource?.value;
241
+ return tableAttrs.value.dataSource ?? toValue(props.table?.dataSource) ?? [];
234
242
  });
235
243
 
244
+ // 分页优先级:tableAttrs 显式配置 > provider 全局配置 > 默认合成
236
245
  const computedPagination = computed<PaginationProps | false>(() => {
237
246
  if (tableAttrs.value.pagination === false) return false;
247
+ if (isPlainObject(tableAttrs.value.pagination)) {
248
+ const globalPagination =
249
+ injectAttrs.value.pagination === false
250
+ ? {}
251
+ : injectAttrs.value.pagination;
252
+ return {
253
+ ...globalPagination,
254
+ ...props.table?.pageParam,
255
+ ...tableAttrs.value.pagination,
256
+ showTotal:
257
+ tableAttrs.value.pagination?.showTotal ??
258
+ globalPagination?.showTotal ??
259
+ ((total: number) => t('pagination.total', { total })),
260
+ };
261
+ }
262
+ if (injectAttrs.value.pagination === false) return false;
238
263
  return {
239
- ...injectAttrs.pagination,
240
- ...pageParam,
241
- ...tableAttrs.value.pagination,
264
+ ...injectAttrs.value.pagination,
265
+ ...props.table?.pageParam,
242
266
  showTotal:
243
- tableAttrs.value.pagination?.showTotal ??
244
- (injectAttrs.pagination === false
245
- ? undefined
246
- : injectAttrs.pagination?.showTotal) ??
267
+ injectAttrs.value.pagination?.showTotal ??
247
268
  ((total: number) => t('pagination.total', { total })),
248
269
  };
249
270
  });
250
271
 
251
272
  const onTableChange: TableProps['onChange'] = (...args) => {
252
- setPageParam?.(args[0]);
273
+ props.table?.setPageParam?.(args[0]);
253
274
  attrs.onChange?.(...args);
254
275
  _search();
255
276
  };
256
277
 
257
278
  const showSearch = computed(() => {
279
+ const searchFields = props.table?.searchForm?.fields;
280
+ const fieldList =
281
+ (Array.isArray(searchFields) ? searchFields : searchFields?.value) ?? [];
258
282
  return !!(
259
283
  searchFormSlot ||
260
284
  (computedSearchFormConfig.value?.hidden !== true &&
261
- searchForm &&
262
- searchForm.fields.value.filter(item => !item.hidden)?.length > 0)
285
+ props.table?.searchForm &&
286
+ fieldList.filter(item => !item.hidden).length > 0)
263
287
  );
264
288
  });
265
289
 
@@ -267,14 +291,17 @@ const computedControl = computed<{
267
291
  sizeControl: boolean;
268
292
  columnControl: boolean | ColumnControlConfig<Path<RecordType>>;
269
293
  }>(() => {
270
- const mergedControl = control ?? injectProps.control;
271
- if (typeof mergedControl === 'boolean') {
272
- return { sizeControl: mergedControl, columnControl: mergedControl };
294
+ const controlConfig = props.control ?? injectProps.value.control;
295
+ if (controlConfig === true) {
296
+ return { sizeControl: true, columnControl: true };
273
297
  }
274
- const c = mergedControl as Control;
275
- const sizeControl = c.sizeControl ?? true;
276
- const columnControl = c.columnControl ?? true;
277
- return { sizeControl: !!sizeControl, columnControl };
298
+ if (controlConfig === false) {
299
+ return { sizeControl: false, columnControl: false };
300
+ }
301
+ return {
302
+ sizeControl: !!controlConfig?.sizeControl,
303
+ columnControl: controlConfig?.columnControl ?? false,
304
+ };
278
305
  });
279
306
 
280
307
  const columnControlConfig = computed(() => {
@@ -283,7 +310,7 @@ const columnControlConfig = computed(() => {
283
310
  });
284
311
 
285
312
  onMounted(() => {
286
- if (immediateSearch ?? injectProps.immediateSearch) {
313
+ if (props.immediateSearch ?? injectProps.value.immediateSearch) {
287
314
  _search();
288
315
  }
289
316
  });
@@ -297,8 +324,8 @@ onMounted(() => {
297
324
  >
298
325
  <slot name="search-form">
299
326
  <SearchForm
300
- v-if="searchForm"
301
- :form="searchForm"
327
+ v-if="props.table?.searchForm"
328
+ :form="props.table.searchForm"
302
329
  v-bind="computedSearchFormConfig"
303
330
  @search="searchPage1st"
304
331
  @reset="reset"
@@ -325,8 +352,8 @@ onMounted(() => {
325
352
  class="pro-table_header_column-control"
326
353
  >
327
354
  <ColumnControl
328
- :columns="computedColumns as any"
329
- :table="table"
355
+ :columns="computedColumns"
356
+ :table="props.table"
330
357
  :column-control="columnControlConfig"
331
358
  />
332
359
  </div>