@qin-ui/antd-vue-pro 2.3.4 → 2.4.1

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 (164) 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__/cross-package.spec.d.ts +2 -0
  16. package/es/__tests__/cross-package.spec.d.ts.map +1 -0
  17. package/es/__tests__/helpers/fixtures.d.ts +15 -0
  18. package/es/__tests__/helpers/fixtures.d.ts.map +1 -0
  19. package/es/__tests__/helpers/mount.d.ts +38 -0
  20. package/es/__tests__/helpers/mount.d.ts.map +1 -0
  21. package/es/__tests__/hooks-locale.spec.d.ts +2 -0
  22. package/es/__tests__/hooks-locale.spec.d.ts.map +1 -0
  23. package/es/__tests__/index.spec.d.ts +2 -0
  24. package/es/__tests__/index.spec.d.ts.map +1 -0
  25. package/es/__tests__/integration.spec.d.ts +2 -0
  26. package/es/__tests__/integration.spec.d.ts.map +1 -0
  27. package/es/__tests__/setup.d.ts +14 -0
  28. package/es/__tests__/setup.d.ts.map +1 -0
  29. package/es/antd-vue-pro.css +13 -13
  30. package/es/index.js +369 -362
  31. package/es/index.js.map +1 -1
  32. package/es/{components → src/components}/component-provider/components/index.vue.d.ts +5 -1
  33. package/es/src/components/component-provider/components/index.vue.d.ts.map +1 -0
  34. package/es/{components → src/components}/component-provider/constants/index.d.ts +2 -2
  35. package/es/src/components/component-provider/constants/index.d.ts.map +1 -0
  36. package/es/src/components/component-provider/index.d.ts.map +1 -0
  37. package/es/src/components/component-provider/types/index.d.ts.map +1 -0
  38. package/es/{components → src/components}/form/components/BaseField/index.vue.d.ts +4 -1
  39. package/es/src/components/form/components/BaseField/index.vue.d.ts.map +1 -0
  40. package/es/src/components/form/components/BaseField/utils/index.d.ts +6 -0
  41. package/es/src/components/form/components/BaseField/utils/index.d.ts.map +1 -0
  42. package/es/{components → src/components}/form/components/BaseFormItem/index.vue.d.ts +5 -1
  43. package/es/src/components/form/components/BaseFormItem/index.vue.d.ts.map +1 -0
  44. package/es/{components → src/components}/form/components/ContainerFragment/index.vue.d.ts +3 -1
  45. package/es/src/components/form/components/ContainerFragment/index.vue.d.ts.map +1 -0
  46. package/es/src/components/form/components/ProForm/index.vue.d.ts.map +1 -0
  47. package/es/src/components/form/components/SlotComponent/index.vue.d.ts +11 -0
  48. package/es/src/components/form/components/SlotComponent/index.vue.d.ts.map +1 -0
  49. package/es/src/components/form/components/index.d.ts.map +1 -0
  50. package/es/src/components/form/constants/index.d.ts.map +1 -0
  51. package/es/src/components/form/hooks/index.d.ts.map +1 -0
  52. package/es/src/components/form/hooks/useFields.d.ts.map +1 -0
  53. package/es/src/components/form/hooks/useForm.d.ts.map +1 -0
  54. package/es/src/components/form/hooks/useFormRef.d.ts.map +1 -0
  55. package/es/{components → src/components}/form/hooks/useGroupFieldAttrs.d.ts +4 -0
  56. package/es/src/components/form/hooks/useGroupFieldAttrs.d.ts.map +1 -0
  57. package/es/src/components/form/index.d.ts.map +1 -0
  58. package/es/{components → src/components}/form/types/index.d.ts +26 -2
  59. package/es/src/components/form/types/index.d.ts.map +1 -0
  60. package/es/{components → src/components}/table/components/ColumnControl.vue.d.ts +4 -1
  61. package/es/src/components/table/components/ColumnControl.vue.d.ts.map +1 -0
  62. package/es/src/components/table/components/DefaultSearchFormContainer.vue.d.ts.map +1 -0
  63. package/es/src/components/table/components/DefaultTableContainer.vue.d.ts.map +1 -0
  64. package/es/{components → src/components}/table/components/ProTable.vue.d.ts +4 -3
  65. package/es/src/components/table/components/ProTable.vue.d.ts.map +1 -0
  66. package/es/{components → src/components}/table/components/SearchForm.vue.d.ts +14 -4
  67. package/es/src/components/table/components/SearchForm.vue.d.ts.map +1 -0
  68. package/es/src/components/table/components/SizeControl.vue.d.ts.map +1 -0
  69. package/es/src/components/table/components/icons/ColumnHeightOutlined.vue.d.ts.map +1 -0
  70. package/es/src/components/table/components/icons/DownOutlined.vue.d.ts.map +1 -0
  71. package/es/src/components/table/components/icons/FilterOutlined.vue.d.ts.map +1 -0
  72. package/es/src/components/table/components/index.d.ts.map +1 -0
  73. package/es/src/components/table/hooks/index.d.ts.map +1 -0
  74. package/es/src/components/table/hooks/useTable.d.ts.map +1 -0
  75. package/es/src/components/table/index.d.ts.map +1 -0
  76. package/es/{components → src/components}/table/types/index.d.ts +1 -1
  77. package/es/src/components/table/types/index.d.ts.map +1 -0
  78. package/es/{index.d.ts → src/index.d.ts} +1 -1
  79. package/es/src/index.d.ts.map +1 -0
  80. package/es/{locale → src/locale}/index.d.ts +1 -1
  81. package/es/src/locale/index.d.ts.map +1 -0
  82. package/es/src/shared/core/index.d.ts +6 -0
  83. package/es/src/shared/core/index.d.ts.map +1 -0
  84. package/es/src/shared/ui/index.d.ts.map +1 -0
  85. package/package.json +8 -3
  86. package/src/components/component-provider/components/index.vue +41 -11
  87. package/src/components/component-provider/constants/index.ts +6 -4
  88. package/src/components/form/components/BaseField/index.vue +61 -37
  89. package/src/components/form/components/BaseField/utils/index.ts +17 -11
  90. package/src/components/form/components/BaseFormItem/index.vue +47 -33
  91. package/src/components/form/components/ContainerFragment/index.vue +4 -2
  92. package/src/components/form/components/ProForm/index.vue +72 -20
  93. package/src/components/form/components/SlotComponent/index.vue +6 -4
  94. package/src/components/form/hooks/useGroupFieldAttrs.ts +16 -4
  95. package/src/components/form/types/index.ts +26 -2
  96. package/src/components/table/components/ColumnControl.vue +17 -22
  97. package/src/components/table/components/ProTable.vue +129 -83
  98. package/src/components/table/components/SearchForm.vue +45 -198
  99. package/src/components/table/components/SizeControl.vue +4 -2
  100. package/src/components/table/types/index.ts +1 -1
  101. package/src/index.ts +1 -1
  102. package/src/locale/index.ts +1 -1
  103. package/src/shared/core/index.ts +15 -1
  104. package/es/components/component-provider/components/index.vue.d.ts.map +0 -1
  105. package/es/components/component-provider/constants/index.d.ts.map +0 -1
  106. package/es/components/component-provider/index.d.ts.map +0 -1
  107. package/es/components/component-provider/types/index.d.ts.map +0 -1
  108. package/es/components/form/components/BaseField/index.vue.d.ts.map +0 -1
  109. package/es/components/form/components/BaseField/utils/index.d.ts +0 -5
  110. package/es/components/form/components/BaseField/utils/index.d.ts.map +0 -1
  111. package/es/components/form/components/BaseFormItem/index.vue.d.ts.map +0 -1
  112. package/es/components/form/components/ContainerFragment/index.vue.d.ts.map +0 -1
  113. package/es/components/form/components/ProForm/index.vue.d.ts.map +0 -1
  114. package/es/components/form/components/SlotComponent/index.vue.d.ts +0 -7
  115. package/es/components/form/components/SlotComponent/index.vue.d.ts.map +0 -1
  116. package/es/components/form/components/index.d.ts.map +0 -1
  117. package/es/components/form/constants/index.d.ts.map +0 -1
  118. package/es/components/form/hooks/index.d.ts.map +0 -1
  119. package/es/components/form/hooks/useFields.d.ts.map +0 -1
  120. package/es/components/form/hooks/useForm.d.ts.map +0 -1
  121. package/es/components/form/hooks/useFormRef.d.ts.map +0 -1
  122. package/es/components/form/hooks/useGroupFieldAttrs.d.ts.map +0 -1
  123. package/es/components/form/index.d.ts.map +0 -1
  124. package/es/components/form/types/index.d.ts.map +0 -1
  125. package/es/components/table/components/ColumnControl.vue.d.ts.map +0 -1
  126. package/es/components/table/components/DefaultSearchFormContainer.vue.d.ts.map +0 -1
  127. package/es/components/table/components/DefaultTableContainer.vue.d.ts.map +0 -1
  128. package/es/components/table/components/ProTable.vue.d.ts.map +0 -1
  129. package/es/components/table/components/SearchForm.vue.d.ts.map +0 -1
  130. package/es/components/table/components/SizeControl.vue.d.ts.map +0 -1
  131. package/es/components/table/components/icons/ColumnHeightOutlined.vue.d.ts.map +0 -1
  132. package/es/components/table/components/icons/DownOutlined.vue.d.ts.map +0 -1
  133. package/es/components/table/components/icons/FilterOutlined.vue.d.ts.map +0 -1
  134. package/es/components/table/components/index.d.ts.map +0 -1
  135. package/es/components/table/hooks/index.d.ts.map +0 -1
  136. package/es/components/table/hooks/useTable.d.ts.map +0 -1
  137. package/es/components/table/index.d.ts.map +0 -1
  138. package/es/components/table/types/index.d.ts.map +0 -1
  139. package/es/index.d.ts.map +0 -1
  140. package/es/locale/index.d.ts.map +0 -1
  141. package/es/shared/core/index.d.ts +0 -6
  142. package/es/shared/core/index.d.ts.map +0 -1
  143. package/es/shared/ui/index.d.ts.map +0 -1
  144. /package/es/{components → src/components}/component-provider/index.d.ts +0 -0
  145. /package/es/{components → src/components}/component-provider/types/index.d.ts +0 -0
  146. /package/es/{components → src/components}/form/components/ProForm/index.vue.d.ts +0 -0
  147. /package/es/{components → src/components}/form/components/index.d.ts +0 -0
  148. /package/es/{components → src/components}/form/constants/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/{shared → src/shared}/ui/index.d.ts +0 -0
@@ -7,7 +7,7 @@ import {
7
7
  MenuItem,
8
8
  Checkbox,
9
9
  } from '../../../shared/ui';
10
- import { computed, onMounted, ref, watch } from 'vue';
10
+ import { computed, ref, watch } from 'vue';
11
11
  import type { Columns, ColumnControlConfig } from '../types';
12
12
  import { type Table } from '../hooks/useTable';
13
13
  import FilterOutlined from './icons/FilterOutlined.vue';
@@ -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
  });
@@ -120,21 +121,15 @@ watch(
120
121
  { immediate: true }
121
122
  );
122
123
 
123
- // 强制 disabledKeys 列始终展示
124
- onMounted(() => {
125
- columnControl?.disabledKeys?.forEach(key => {
126
- table?.setColumn?.(String(key), { hidden: false });
127
- });
128
- });
129
-
124
+ // disabledKeys 指定的列始终强制展示
130
125
  watch(
131
- () => columnControl?.disabledKeys,
126
+ () => props.columnControl?.disabledKeys,
132
127
  keys => {
133
128
  keys?.forEach(key => {
134
- table?.setColumn?.(String(key), { hidden: false });
129
+ props.table?.setColumn?.(String(key), { hidden: false });
135
130
  });
136
131
  },
137
- { deep: true }
132
+ { immediate: true, deep: true }
138
133
  );
139
134
  </script>
140
135
 
@@ -149,7 +144,7 @@ watch(
149
144
  :selectable="false"
150
145
  >
151
146
  <MenuItem
152
- v-if="!columnControl?.disableCheckAll"
147
+ v-if="!props.columnControl?.disableCheckAll"
153
148
  :key="0"
154
149
  @click="onCheckAllChange"
155
150
  >
@@ -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';
@@ -71,6 +74,8 @@ import { Column, Columns, ColumnControlConfig } from '../types';
71
74
 
72
75
  defineOptions({ name: 'ProTable', inheritAttrs: false });
73
76
 
77
+ const tableProperties = Object.keys(tableProps());
78
+
74
79
  type Control = {
75
80
  sizeControl: boolean;
76
81
  columnControl: boolean | ColumnControlConfig<Path<RecordType>>;
@@ -100,74 +105,84 @@ type Props = {
100
105
  tableContainer?: ContainerComponent | false;
101
106
  } & /* @vue-ignore */ TableProps;
102
107
 
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>();
108
+ const props = withDefaults(defineProps<Props>(), {
109
+ table: undefined,
110
+ search: undefined,
111
+ addIndexColumn: undefined,
112
+ immediateSearch: undefined,
113
+ control: undefined,
114
+ searchFormConfig: undefined,
115
+ tableContainer: undefined,
116
+ });
112
117
 
113
118
  const { t } = useLocale();
114
119
 
115
120
  const config = INJECT_CONFIG['pro-table'];
116
- const injectProps = inject(config.injectionKey, config.default);
117
-
118
- const tableProperties = Object.keys(tableProps());
121
+ const injectPropsRaw = inject(config.injectionKey, config.default);
122
+ const injectProps = computed(() => toValue(injectPropsRaw) || {});
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
- // 核心搜索方法:设置 loading 状态,调用外部 search 函数
148
+ // 递增序号做请求竞态守卫,仅最新一次请求可变更 loading
149
+ let searchSequence = 0;
146
150
  const _search = async () => {
151
+ const seq = ++searchSequence;
152
+ const searchPromise = (props.search || attrs.onSearch)?.();
153
+ if (!isPromise(searchPromise)) return;
154
+ loading.value = true;
147
155
  try {
148
- loading.value = true;
149
- await search?.();
156
+ await searchPromise;
150
157
  } finally {
151
- loading.value = false;
158
+ if (seq === searchSequence) {
159
+ loading.value = false;
160
+ }
152
161
  }
153
162
  };
154
163
 
155
164
  // 重置:恢复查询参数到初始值,重新搜索
156
165
  const reset = () => {
157
- table?.resetQueryParams();
166
+ props.table?.resetQueryParams?.();
158
167
  nextTick(() => {
159
168
  _search();
160
169
  });
161
170
  };
162
171
 
172
+ const customSlotNames = [
173
+ 'search-form',
174
+ 'button-bar',
175
+ 'toolbar',
176
+ 'table',
177
+ ] as const;
178
+
163
179
  type CustomSlots = Readonly<
164
- Partial<Record<'search-form' | 'button-bar' | 'toolbar' | 'table', Slot>>
180
+ Partial<Record<(typeof customSlotNames)[number], Slot>>
165
181
  >;
166
182
  type TableSlots = Omit<ComponentSlots<typeof ATable>, 'bodyCell'> &
167
183
  Readonly<{
168
184
  bodyCell?: (props: {
169
185
  text: any;
170
- value: any;
171
186
  record: RecordType;
172
187
  index: number;
173
188
  column: Column<RecordType>;
@@ -176,23 +191,19 @@ type TableSlots = Omit<ComponentSlots<typeof ATable>, 'bodyCell'> &
176
191
  type Slots = Omit<TableSlots & CustomSlots, 'default'>;
177
192
 
178
193
  const slots = defineSlots<Slots>();
179
- const {
180
- 'search-form': searchFormSlot,
181
- 'button-bar': buttonBarSlot,
182
- toolbar: toolbarSlot,
183
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
184
- table: tableSlot,
185
- ...tableSlots
186
- } = slots;
194
+ const forwardedSlotNames = () =>
195
+ (Object.keys(slots) as Array<Extract<keyof Slots, string>>).filter(
196
+ name => !customSlotNames.includes(name as any)
197
+ );
187
198
 
188
199
  const searchPage1st = () => {
189
- setPageParam?.({ current: 1 });
200
+ props.table?.setPageParam?.({ current: 1 });
190
201
  _search();
191
202
  };
192
203
 
193
204
  const computedTableProps = computed<TableProps>(() => {
194
205
  return {
195
- ...injectAttrs,
206
+ ...injectAttrs.value,
196
207
  ...tableAttrs.value,
197
208
  pagination: undefined,
198
209
  onChange: undefined,
@@ -201,65 +212,92 @@ const computedTableProps = computed<TableProps>(() => {
201
212
 
202
213
  const computedTableContainer = computed(() => {
203
214
  const container =
204
- tableContainer ?? injectProps.tableContainer ?? DefaultTableContainer;
215
+ props.tableContainer ??
216
+ injectProps.value.tableContainer ??
217
+ DefaultTableContainer;
205
218
  return container ? container : undefined;
206
219
  });
207
220
 
208
221
  type ReturnGenericParameterTypes<V> = V extends Table<any, infer R> ? R : never;
209
222
  type RecordType = ReturnGenericParameterTypes<T>;
210
223
 
211
- const indexColumn = (): ColumnType => ({
224
+ // 序号列随分页偏移:第 n 页首行序号 = (n-1)*pageSize + i + 1(无分页时退化为 index+1)
225
+ const getIndex = (i: number) => {
226
+ const pageParam = props.table?.pageParam;
227
+ if (pageParam && computedPagination.value !== false) {
228
+ const current = pageParam.current ?? 1;
229
+ const pageSize = pageParam.pageSize ?? 10;
230
+ return (current - 1) * pageSize + i + 1;
231
+ }
232
+ return i + 1;
233
+ };
234
+
235
+ const indexColumn = computed<ColumnType>(() => ({
212
236
  title: t('table.index'),
213
237
  dataIndex: '_index',
238
+ key: '_index',
214
239
  width: 80,
215
- customRender: ({ index }) => index + 1,
240
+ customRender: ({ index }) => getIndex(index),
241
+ }));
242
+
243
+ const computedColumns = computed<Columns<RecordType>>(() => {
244
+ const cols = (tableAttrs.value.columns ??
245
+ toValue(props.table?.columns) ??
246
+ []) as any;
247
+ const needIndex = props.addIndexColumn ?? injectProps.value.addIndexColumn;
248
+ return needIndex ? [indexColumn.value, ...cols] : cols;
216
249
  });
217
250
 
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
251
  const visibleComputedColumns = computed(() => {
229
252
  return computedColumns.value.filter(item => !(item as Column).hidden);
230
253
  });
231
254
 
232
255
  const computedDataSource = computed<RecordType[]>(() => {
233
- return (tableAttrs.value.dataSource as any[]) ?? dataSource?.value;
256
+ return tableAttrs.value.dataSource ?? toValue(props.table?.dataSource) ?? [];
234
257
  });
235
258
 
259
+ // 分页优先级:tableAttrs 显式配置 > provider 全局配置 > 默认合成
236
260
  const computedPagination = computed<PaginationProps | false>(() => {
237
261
  if (tableAttrs.value.pagination === false) return false;
262
+ if (isPlainObject(tableAttrs.value.pagination)) {
263
+ const globalPagination =
264
+ injectAttrs.value.pagination === false
265
+ ? {}
266
+ : injectAttrs.value.pagination;
267
+ return {
268
+ ...globalPagination,
269
+ ...props.table?.pageParam,
270
+ ...tableAttrs.value.pagination,
271
+ showTotal:
272
+ tableAttrs.value.pagination?.showTotal ??
273
+ globalPagination?.showTotal ??
274
+ ((total: number) => t('pagination.total', { total })),
275
+ };
276
+ }
277
+ if (injectAttrs.value.pagination === false) return false;
238
278
  return {
239
- ...injectAttrs.pagination,
240
- ...pageParam,
241
- ...tableAttrs.value.pagination,
279
+ ...injectAttrs.value.pagination,
280
+ ...props.table?.pageParam,
242
281
  showTotal:
243
- tableAttrs.value.pagination?.showTotal ??
244
- (injectAttrs.pagination === false
245
- ? undefined
246
- : injectAttrs.pagination?.showTotal) ??
282
+ injectAttrs.value.pagination?.showTotal ??
247
283
  ((total: number) => t('pagination.total', { total })),
248
284
  };
249
285
  });
250
286
 
251
287
  const onTableChange: TableProps['onChange'] = (...args) => {
252
- setPageParam?.(args[0]);
288
+ props.table?.setPageParam?.(args[0]);
253
289
  attrs.onChange?.(...args);
254
290
  _search();
255
291
  };
256
292
 
257
- const showSearch = computed(() => {
293
+ const searchFormVisible = computed(() => {
294
+ const searchFields = props.table?.searchForm?.fields;
295
+ const fieldList =
296
+ (Array.isArray(searchFields) ? searchFields : searchFields?.value) ?? [];
258
297
  return !!(
259
- searchFormSlot ||
260
- (computedSearchFormConfig.value?.hidden !== true &&
261
- searchForm &&
262
- searchForm.fields.value.filter(item => !item.hidden)?.length > 0)
298
+ computedSearchFormConfig.value?.hidden !== true &&
299
+ props.table?.searchForm &&
300
+ fieldList.filter(item => !toValue(item.hidden)).length > 0
263
301
  );
264
302
  });
265
303
 
@@ -267,14 +305,17 @@ const computedControl = computed<{
267
305
  sizeControl: boolean;
268
306
  columnControl: boolean | ColumnControlConfig<Path<RecordType>>;
269
307
  }>(() => {
270
- const mergedControl = control ?? injectProps.control;
271
- if (typeof mergedControl === 'boolean') {
272
- return { sizeControl: mergedControl, columnControl: mergedControl };
308
+ const controlConfig = props.control ?? injectProps.value.control;
309
+ if (controlConfig === true) {
310
+ return { sizeControl: true, columnControl: true };
273
311
  }
274
- const c = mergedControl as Control;
275
- const sizeControl = c.sizeControl ?? true;
276
- const columnControl = c.columnControl ?? true;
277
- return { sizeControl: !!sizeControl, columnControl };
312
+ if (controlConfig === false) {
313
+ return { sizeControl: false, columnControl: false };
314
+ }
315
+ return {
316
+ sizeControl: !!controlConfig?.sizeControl,
317
+ columnControl: controlConfig?.columnControl ?? false,
318
+ };
278
319
  });
279
320
 
280
321
  const columnControlConfig = computed(() => {
@@ -283,22 +324,27 @@ const columnControlConfig = computed(() => {
283
324
  });
284
325
 
285
326
  onMounted(() => {
286
- if (immediateSearch ?? injectProps.immediateSearch) {
327
+ if (props.immediateSearch ?? injectProps.value.immediateSearch) {
287
328
  _search();
288
329
  }
289
330
  });
331
+
332
+ defineExpose({
333
+ /** 手动触发一次查询(与内部搜索共用 loading 竞态守卫),便于外部刷新列表 */
334
+ search: _search,
335
+ });
290
336
  </script>
291
337
 
292
338
  <template>
293
339
  <div class="pro-table" :class="attrs.class" :style="attrs.style">
294
340
  <ContainerFragment
295
- v-if="showSearch"
341
+ v-if="searchFormVisible || $slots['search-form']"
296
342
  :component="computedSearchFormConfig.container"
297
343
  >
298
344
  <slot name="search-form">
299
345
  <SearchForm
300
- v-if="searchForm"
301
- :form="searchForm"
346
+ v-if="props.table?.searchForm"
347
+ :form="props.table.searchForm"
302
348
  v-bind="computedSearchFormConfig"
303
349
  @search="searchPage1st"
304
350
  @reset="reset"
@@ -308,10 +354,10 @@ onMounted(() => {
308
354
 
309
355
  <ContainerFragment :component="computedTableContainer">
310
356
  <div class="pro-table_header">
311
- <div v-if="buttonBarSlot" class="pro-table_header_button-bar">
357
+ <div v-if="$slots['button-bar']" class="pro-table_header_button-bar">
312
358
  <slot name="button-bar" />
313
359
  </div>
314
- <div v-if="toolbarSlot" class="pro-table_header_toolbar">
360
+ <div v-if="$slots['toolbar']" class="pro-table_header_toolbar">
315
361
  <slot name="toolbar" />
316
362
  </div>
317
363
  <div
@@ -325,8 +371,8 @@ onMounted(() => {
325
371
  class="pro-table_header_column-control"
326
372
  >
327
373
  <ColumnControl
328
- :columns="computedColumns as any"
329
- :table="table"
374
+ :columns="computedColumns"
375
+ :table="props.table"
330
376
  :column-control="columnControlConfig"
331
377
  />
332
378
  </div>
@@ -344,7 +390,7 @@ onMounted(() => {
344
390
  @change="onTableChange"
345
391
  >
346
392
  <template
347
- v-for="(_, name) of tableSlots"
393
+ v-for="name of forwardedSlotNames()"
348
394
  :key="name"
349
395
  #[name]="scoped"
350
396
  >