@qin-ui/element-plus-pro 1.1.4 → 1.2.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 (48) hide show
  1. package/AI-CONTEXT.md +19 -8
  2. package/api.json +7 -1
  3. package/es/components/component-provider/components/index.vue.d.ts +6 -0
  4. package/es/components/component-provider/components/index.vue.d.ts.map +1 -1
  5. package/es/components/component-provider/constants/index.d.ts.map +1 -1
  6. package/es/components/form/components/BaseField/index.vue.d.ts.map +1 -1
  7. package/es/components/form/components/BaseField/utils/index.d.ts +3 -1
  8. package/es/components/form/components/BaseField/utils/index.d.ts.map +1 -1
  9. package/es/components/table/components/ColumnControl.vue.d.ts +2 -1
  10. package/es/components/table/components/ColumnControl.vue.d.ts.map +1 -1
  11. package/es/components/table/components/ProTable.vue.d.ts +3 -2
  12. package/es/components/table/components/ProTable.vue.d.ts.map +1 -1
  13. package/es/components/table/components/SearchForm.vue.d.ts.map +1 -1
  14. package/es/components/table/components/SizeControl.vue.d.ts.map +1 -1
  15. package/es/components/table/components/TableColumnRenderer.vue.d.ts.map +1 -1
  16. package/es/components/table/types/index.d.ts +24 -2
  17. package/es/components/table/types/index.d.ts.map +1 -1
  18. package/es/components/table/useTable.d.ts.map +1 -1
  19. package/es/element-plus-pro.css +13 -13
  20. package/es/index.d.ts +1 -0
  21. package/es/index.d.ts.map +1 -1
  22. package/es/index.js +287 -130
  23. package/es/index.js.map +1 -1
  24. package/es/locale/en-US.d.ts +26 -0
  25. package/es/locale/en-US.d.ts.map +1 -0
  26. package/es/locale/index.d.ts +31 -0
  27. package/es/locale/index.d.ts.map +1 -0
  28. package/es/locale/zh-CN.d.ts +26 -0
  29. package/es/locale/zh-CN.d.ts.map +1 -0
  30. package/es/locale/zh-TW.d.ts +26 -0
  31. package/es/locale/zh-TW.d.ts.map +1 -0
  32. package/package.json +2 -2
  33. package/src/components/component-provider/components/index.vue +14 -1
  34. package/src/components/component-provider/constants/index.ts +20 -39
  35. package/src/components/form/components/BaseField/index.vue +10 -4
  36. package/src/components/form/components/BaseField/utils/index.ts +66 -3
  37. package/src/components/table/components/ColumnControl.vue +83 -20
  38. package/src/components/table/components/ProTable.vue +38 -15
  39. package/src/components/table/components/SearchForm.vue +6 -3
  40. package/src/components/table/components/SizeControl.vue +9 -5
  41. package/src/components/table/components/TableColumnRenderer.vue +1 -5
  42. package/src/components/table/types/index.ts +25 -8
  43. package/src/components/table/useTable.ts +11 -1
  44. package/src/index.ts +1 -0
  45. package/src/locale/en-US.ts +21 -0
  46. package/src/locale/index.ts +68 -0
  47. package/src/locale/zh-CN.ts +21 -0
  48. package/src/locale/zh-TW.ts +21 -0
@@ -55,19 +55,28 @@ import type { ContainerComponent } from '../../form/types';
55
55
  import SearchForm from './SearchForm.vue';
56
56
  import type { SearchFormProps } from './SearchForm.vue';
57
57
  import type { Table } from '../useTable';
58
- import { camelizeProperties, getObject, pick } from '../../../shared/core';
58
+ import { useLocale } from '../../../locale';
59
+ import {
60
+ camelizeProperties,
61
+ getObject,
62
+ pick,
63
+ Path,
64
+ } from '../../../shared/core';
59
65
  import {
60
66
  DefaultSearchFormContainer,
61
67
  DefaultTableContainer,
62
68
  SizeControl,
63
69
  ColumnControl,
64
70
  } from '.';
65
- import type { Columns } from '../types';
71
+ import type { Columns, ColumnControlConfig } from '../types';
66
72
  import TableColumnRenderer from './TableColumnRenderer.vue';
67
73
 
68
74
  defineOptions({ name: 'ProTable', inheritAttrs: false });
69
75
 
70
- type Control = { sizeControl: boolean; columnControl: boolean };
76
+ type Control = {
77
+ sizeControl: boolean;
78
+ columnControl: boolean | ColumnControlConfig<Path<RecordType>>;
79
+ };
71
80
 
72
81
  type SearchFormConfig = Omit<SearchFormProps, 'form'> & {
73
82
  // 是否隐藏搜索表单
@@ -112,6 +121,8 @@ const {
112
121
  pagination = undefined,
113
122
  } = defineProps<Props>();
114
123
 
124
+ const { t } = useLocale();
125
+
115
126
  const config = INJECT_CONFIG['pro-table'];
116
127
  const injectProps = inject(config.injectionKey, config.default) as any;
117
128
 
@@ -215,11 +226,6 @@ const normalizedRawColumns = computed(() => {
215
226
  if (current.label === undefined && current.title !== undefined) {
216
227
  current.label = current.title;
217
228
  }
218
- if (current.prop === undefined && current.dataIndex !== undefined) {
219
- current.prop = Array.isArray(current.dataIndex)
220
- ? current.dataIndex.join('.')
221
- : current.dataIndex;
222
- }
223
229
  if (current.key === undefined) {
224
230
  current.key =
225
231
  current.prop ??
@@ -235,7 +241,7 @@ const normalizedRawColumns = computed(() => {
235
241
  {
236
242
  key: '_index',
237
243
  type: 'index',
238
- label: '序号',
244
+ label: t('table.index'),
239
245
  width: 80,
240
246
  },
241
247
  ...normalized,
@@ -295,12 +301,23 @@ const showSearch = computed(() => {
295
301
  );
296
302
  });
297
303
 
298
- const computedControl = computed<Control>(() => {
304
+ const computedControl = computed<{
305
+ sizeControl: boolean;
306
+ columnControl: boolean | ColumnControlConfig<Path<RecordType>>;
307
+ }>(() => {
299
308
  const mergedControl = control ?? injectProps.control;
300
- const sizeControl = (mergedControl as Control)?.sizeControl ?? mergedControl;
301
- const columnControl =
302
- (mergedControl as Control)?.columnControl ?? mergedControl;
303
- return { sizeControl: !!sizeControl, columnControl: !!columnControl };
309
+ if (typeof mergedControl === 'boolean') {
310
+ return { sizeControl: mergedControl, columnControl: mergedControl };
311
+ }
312
+ const c = mergedControl as Control;
313
+ const sizeControl = c.sizeControl ?? true;
314
+ const columnControl = c.columnControl ?? true;
315
+ return { sizeControl: !!sizeControl, columnControl };
316
+ });
317
+
318
+ const columnControlConfig = computed(() => {
319
+ const cc = computedControl.value.columnControl;
320
+ return typeof cc === 'object' ? cc : undefined;
304
321
  });
305
322
 
306
323
  const resolvedSize = computed(() => {
@@ -357,7 +374,13 @@ onMounted(() => {
357
374
  v-if="computedControl.columnControl"
358
375
  class="pro-table_header_column-control"
359
376
  >
360
- <ColumnControl :columns="normalizedRawColumns" :table="table" />
377
+ <ColumnControl
378
+ :columns="
379
+ normalizedRawColumns.filter(item => item.key !== '_index')
380
+ "
381
+ :table="table"
382
+ :column-control="columnControlConfig"
383
+ />
361
384
  </div>
362
385
  </div>
363
386
 
@@ -69,9 +69,12 @@ import {
69
69
  import ProForm from '../../form';
70
70
  import { type Form } from '../../form';
71
71
  import DownOutlined from './icons/DownOutlined.vue';
72
+ import { useLocale } from '../../../locale';
72
73
 
73
74
  defineOptions({ name: 'SearchForm' });
74
75
 
76
+ const { t } = useLocale();
77
+
75
78
  const {
76
79
  layout = 'grid',
77
80
  expand = true,
@@ -236,7 +239,7 @@ const onSearch = () => {
236
239
  v-else
237
240
  class="pro-table_search-form_reset-button"
238
241
  @click="onReset"
239
- >重置</Button
242
+ >{{ t('table.reset') }}</Button
240
243
  >
241
244
  </template>
242
245
  </slot>
@@ -250,7 +253,7 @@ const onSearch = () => {
250
253
  native-type="submit"
251
254
  @click="onSearch"
252
255
  >
253
- 查询
256
+ {{ t('table.query') }}
254
257
  </Button>
255
258
  </template>
256
259
  </slot>
@@ -268,7 +271,7 @@ const onSearch = () => {
268
271
  class="pro-table_search-form_expand-toggle-button"
269
272
  @click="changeExpandStatus"
270
273
  >
271
- {{ expandStatus ? '收起' : '展开' }}
274
+ {{ expandStatus ? t('table.collapse') : t('table.expand') }}
272
275
  <DownOutlined
273
276
  class="transition"
274
277
  style="margin-left: 4px"
@@ -7,18 +7,22 @@ import {
7
7
  type TableProps,
8
8
  } from '../../../shared/ui';
9
9
  import ColumnHeightOutlined from './icons/ColumnHeightOutlined.vue';
10
+ import { computed } from 'vue';
11
+ import { useLocale } from '../../../locale';
10
12
 
11
13
  type Size = TableProps['size'];
12
14
 
15
+ const { t } = useLocale();
16
+
13
17
  const size = defineModel<Size>('size');
14
18
 
15
19
  size.value = size.value ?? 'default';
16
20
 
17
- const items: Array<{ label: string; key: NonNullable<Size> }> = [
18
- { label: '默认', key: 'default' },
19
- { label: '中等', key: 'large' },
20
- { label: '紧凑', key: 'small' },
21
- ];
21
+ const items = computed<Array<{ label: string; key: NonNullable<Size> }>>(() => [
22
+ { label: t('table.sizeDefault'), key: 'default' },
23
+ { label: t('table.sizeMiddle'), key: 'large' },
24
+ { label: t('table.sizeCompact'), key: 'small' },
25
+ ]);
22
26
  </script>
23
27
 
24
28
  <template>
@@ -34,11 +34,7 @@ const normalizedColumns = computed(() => {
34
34
  const getColumnProps = (column: Column<D>) => {
35
35
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
36
36
  const { hidden, render, key, ...rest } = column;
37
- const prop = Array.isArray(column.prop)
38
- ? column.prop.join('.')
39
- : column.prop
40
- ? String(column.prop)
41
- : undefined;
37
+ const prop = column.prop ? String(column.prop) : undefined;
42
38
  return {
43
39
  ...rest,
44
40
  prop,
@@ -1,11 +1,5 @@
1
1
  import type { ColumnType } from '../../../shared/ui';
2
- import {
3
- Data,
4
- ExtendWithAny,
5
- KeyExpandString,
6
- Paths,
7
- Path,
8
- } from '../../../shared/core';
2
+ import { Data, ExtendWithAny, Path } from '../../../shared/core';
9
3
 
10
4
  type BivariantRender<D extends Data = Data> = {
11
5
  bivarianceHack(scope: ColumnScope<D>): any;
@@ -61,7 +55,7 @@ export type Column<D extends Data = Data> = Partial<
61
55
  * Element Plus 使用 prop 而非 dataIndex
62
56
  * @example 'name' | 'address.city'
63
57
  */
64
- prop?: KeyExpandString<Extract<keyof D, string>> | Paths<D>;
58
+ prop?: Path<D>;
65
59
  /** 是否隐藏该列 */
66
60
  hidden?: boolean;
67
61
  /** 自定义渲染函数 */
@@ -75,3 +69,26 @@ export type Column<D extends Data = Data> = Partial<
75
69
  * @public
76
70
  */
77
71
  export type Columns<D extends Data = Data> = Array<Column<D>>;
72
+
73
+ /**
74
+ * 列控制配置(用于 control.columnControl)
75
+ *
76
+ * @template K - 列 key 类型,ProTable 中传入 Path<RecordType> 获得自动补全
77
+ *
78
+ * @example
79
+ * ```ts
80
+ * const config: ColumnControlConfig<'name' | 'age'> = {
81
+ * excludedKeys: [],
82
+ * disabledKeys: ['name'],
83
+ * disableCheckAll: false,
84
+ * }
85
+ * ```
86
+ */
87
+ export type ColumnControlConfig<K extends string | number = string | number> = {
88
+ /** 不在下拉中出现的列 keys(始终展示,不参与勾选) */
89
+ excludedKeys?: K[];
90
+ /** 在下拉中显示但不可取消勾选的列 keys(始终展示,始终勾选) */
91
+ disabledKeys?: K[];
92
+ /** 禁用全选/取消全选 */
93
+ disableCheckAll?: boolean;
94
+ };
@@ -128,10 +128,20 @@ export function useTable<
128
128
  D extends Data = Data,
129
129
  T extends Data = ExtendWithAny<D>,
130
130
  >(params: UseTableParams<D, T> = {}): Table<D, T> {
131
- const { data, ...rest } = params;
131
+ const { data, columns, ...rest } = params;
132
132
  const coreTable = (coreUseTable as any)({
133
133
  ...rest,
134
134
  dataSource: data,
135
+ // 补齐列 key(key ?? prop ?? columnKey),
136
+ // 使 setColumn 等按 key 匹配的 API 对 Element Plus 的 prop 列生效
137
+ columns: columns?.map(column => {
138
+ if (column.key !== undefined && column.key !== null) return column;
139
+ const prop = column.prop;
140
+ const fallback =
141
+ prop ??
142
+ (typeof column.columnKey === 'string' ? column.columnKey : undefined);
143
+ return { ...column, key: fallback };
144
+ }),
135
145
  }) as _Table<D, T, Column<T>>;
136
146
 
137
147
  const { dataSource, ...tableWithoutDataSource } = coreTable as any;
package/src/index.ts CHANGED
@@ -6,6 +6,7 @@ import ProComponentProvider from './components/component-provider';
6
6
  export * from './components/form';
7
7
  export * from './components/table';
8
8
  export * from './components/component-provider';
9
+ export * from './locale';
9
10
 
10
11
  /**
11
12
  * Schema 驱动的表单组件,基于 element-plus Form 封装
@@ -0,0 +1,21 @@
1
+ /**
2
+ * element-plus-pro language pack (English)
3
+ *
4
+ * @description Extends the core language pack with element-plus specific
5
+ * date/time picker placeholder texts.
6
+ */
7
+ import { enUS } from '@qin-ui/pro-components-core';
8
+
9
+ export default {
10
+ ...enUS,
11
+ // Date/time picker placeholders (defaults of date-picker.* in INJECT_CONFIG)
12
+ 'date-picker.placeholder': 'Please select',
13
+ 'date-picker.start': 'Start date',
14
+ 'date-picker.end': 'End date',
15
+ 'date-picker.startMonth': 'Start month',
16
+ 'date-picker.endMonth': 'End month',
17
+ 'date-picker.startYear': 'Start year',
18
+ 'date-picker.endYear': 'End year',
19
+ 'date-picker.startTime': 'Start time',
20
+ 'date-picker.endTime': 'End time',
21
+ } as const;
@@ -0,0 +1,68 @@
1
+ /**
2
+ * element-plus-pro locale 模块
3
+ *
4
+ * @description 提供 useLocale 组合式函数与语言包。
5
+ * 语言自动跟随宿主应用的 element-plus `el-config-provider` locale 切换,
6
+ * 也可通过 ProComponentProvider 的 `locale` prop 覆盖任意文案。
7
+ */
8
+ import {
9
+ computed,
10
+ inject,
11
+ toValue,
12
+ type InjectionKey,
13
+ type MaybeRef,
14
+ } from 'vue';
15
+ import { useLocale as useElLocale } from 'element-plus';
16
+ import {
17
+ format,
18
+ resolveLocaleName,
19
+ type ProLocaleName,
20
+ } from '@qin-ui/pro-components-core';
21
+ import zhCN from './zh-CN';
22
+ import zhTW from './zh-TW';
23
+ import enUS from './en-US';
24
+
25
+ export { zhCN, zhTW, enUS };
26
+
27
+ export type ProLocale = typeof zhCN;
28
+
29
+ /** ProComponentProvider 通过该 key 注入局部覆盖文案 */
30
+ export const LOCALE_INJECT_KEY: InjectionKey<
31
+ MaybeRef<Partial<ProLocale> | undefined>
32
+ > = Symbol('pro-locale');
33
+
34
+ /**
35
+ * 获取响应式 locale 文案
36
+ *
37
+ * @description 返回 `t` 翻译函数与当前语言名。
38
+ * `t` 在 computed / 模板中调用时会随宿主语言切换自动更新。
39
+ *
40
+ * @returns
41
+ * - `t(key, params?)` - 翻译函数,支持 `{placeholder}` 参数
42
+ * - `lang` - 当前解析出的语言名('zh-CN' | 'zh-TW' | 'en-US')
43
+ *
44
+ * @example
45
+ * ```ts
46
+ * const { t } = useLocale();
47
+ * t('table.query') // '查询' / '查詢' / 'Search'
48
+ * t('pagination.total', { total: 100 }) // '共 100 条'
49
+ * ```
50
+ */
51
+ export const useLocale = () => {
52
+ const { lang: elLang } = useElLocale();
53
+ const override = inject(LOCALE_INJECT_KEY, undefined);
54
+
55
+ const lang = computed<ProLocaleName>(() => resolveLocaleName(elLang.value));
56
+ const pack = computed<Record<string, string>>(() =>
57
+ lang.value === 'zh-TW' ? zhTW : lang.value === 'en-US' ? enUS : zhCN
58
+ );
59
+
60
+ const t = (key: string, params?: Record<string, string | number>): string => {
61
+ const overrides = toValue(override) as Record<string, string> | undefined;
62
+ const text =
63
+ overrides?.[key] ?? (pack.value as Record<string, string>)[key] ?? key;
64
+ return format(text, params);
65
+ };
66
+
67
+ return { t, lang };
68
+ };
@@ -0,0 +1,21 @@
1
+ /**
2
+ * element-plus-pro 语言包(简体中文)
3
+ *
4
+ * @description 在 core 通用语言包基础上,扩展 element-plus 特有的
5
+ * 日期/时间组件占位符文案。
6
+ */
7
+ import { zhCN } from '@qin-ui/pro-components-core';
8
+
9
+ export default {
10
+ ...zhCN,
11
+ // 日期/时间选择器占位符(对应 INJECT_CONFIG 中 date-picker.* 的占位默认值)
12
+ 'date-picker.placeholder': '请选择',
13
+ 'date-picker.start': '开始日期',
14
+ 'date-picker.end': '结束日期',
15
+ 'date-picker.startMonth': '开始月份',
16
+ 'date-picker.endMonth': '结束月份',
17
+ 'date-picker.startYear': '开始年份',
18
+ 'date-picker.endYear': '结束年份',
19
+ 'date-picker.startTime': '开始时间',
20
+ 'date-picker.endTime': '结束时间',
21
+ } as const;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * element-plus-pro 语言包(繁體中文)
3
+ *
4
+ * @description 在 core 通用語言包基礎上,擴展 element-plus 特有的
5
+ * 日期/時間元件佔位符文案。
6
+ */
7
+ import { zhTW } from '@qin-ui/pro-components-core';
8
+
9
+ export default {
10
+ ...zhTW,
11
+ // 日期/時間選擇器佔位符(對應 INJECT_CONFIG 中 date-picker.* 的佔位預設值)
12
+ 'date-picker.placeholder': '請選擇',
13
+ 'date-picker.start': '開始日期',
14
+ 'date-picker.end': '結束日期',
15
+ 'date-picker.startMonth': '開始月份',
16
+ 'date-picker.endMonth': '結束月份',
17
+ 'date-picker.startYear': '開始年份',
18
+ 'date-picker.endYear': '結束年份',
19
+ 'date-picker.startTime': '開始時間',
20
+ 'date-picker.endTime': '結束時間',
21
+ } as const;