@qin-ui/antd-vue-pro 2.2.3 → 2.3.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.
- package/AI-CONTEXT.md +89 -251
- package/README.md +27 -26
- package/api.json +7 -1
- package/bin/init-ai.mjs +133 -41
- package/es/antd-vue-pro.css +13 -13
- package/es/components/component-provider/components/index.vue.d.ts +8 -0
- package/es/components/component-provider/components/index.vue.d.ts.map +1 -1
- package/es/components/component-provider/constants/index.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 +3 -1
- package/es/components/form/components/BaseField/utils/index.d.ts.map +1 -1
- package/es/components/table/components/ColumnControl.vue.d.ts +2 -1
- package/es/components/table/components/ColumnControl.vue.d.ts.map +1 -1
- package/es/components/table/components/ProTable.vue.d.ts +3 -2
- package/es/components/table/components/ProTable.vue.d.ts.map +1 -1
- package/es/components/table/components/SearchForm.vue.d.ts.map +1 -1
- package/es/components/table/components/SizeControl.vue.d.ts.map +1 -1
- package/es/components/table/types/index.d.ts +25 -0
- package/es/components/table/types/index.d.ts.map +1 -1
- package/es/index.d.ts +1 -0
- package/es/index.d.ts.map +1 -1
- package/es/index.js +200 -103
- package/es/index.js.map +1 -1
- package/es/locale/index.d.ts +28 -0
- package/es/locale/index.d.ts.map +1 -0
- package/package.json +3 -3
- package/src/components/component-provider/components/index.vue +16 -1
- package/src/components/component-provider/constants/index.ts +4 -7
- package/src/components/form/components/BaseField/index.vue +10 -4
- package/src/components/form/components/BaseField/utils/index.ts +33 -3
- package/src/components/table/components/ColumnControl.vue +91 -38
- package/src/components/table/components/ProTable.vue +47 -13
- package/src/components/table/components/SearchForm.vue +6 -3
- package/src/components/table/components/SizeControl.vue +9 -5
- package/src/components/table/types/index.ts +26 -0
- package/src/index.ts +1 -0
- package/src/locale/index.ts +71 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qin-ui/antd-vue-pro",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"description": "二次封装antd vue组件",
|
|
5
5
|
"bin": {
|
|
6
6
|
"antd-vue-pro": "./bin/init-ai.mjs"
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"scroll-into-view-if-needed": "^3.1.0",
|
|
45
45
|
"vue-component-type-helpers": "^3.2.5",
|
|
46
|
-
"@qin-ui/pro-components-core": "^1.0
|
|
46
|
+
"@qin-ui/pro-components-core": "^1.1.0"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"ant-design-vue": "^4"
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
"pro-table"
|
|
73
73
|
],
|
|
74
74
|
"scripts": {
|
|
75
|
-
"prebuild": "tsx ../../scripts/generate-api-json.ts antd-vue-pro",
|
|
75
|
+
"prebuild": "tsx ../../scripts/generate-api-json.ts antd-vue-pro && tsx ../../scripts/generate-init-ai.ts antd-vue-pro",
|
|
76
76
|
"build": "vue-tsc --noEmit && vite build"
|
|
77
77
|
}
|
|
78
78
|
}
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
*
|
|
10
10
|
* @param {ComponentVars} [componentVars] - 组件全局配置变量
|
|
11
11
|
* @param {Record<ComponentName, any>} [componentMap] - 自定义组件映射,用于替换或扩展内置组件
|
|
12
|
+
* @param {Partial<ProLocale>} [locale] - 内置文案覆盖,可覆盖任意 locale 文案(如查询/重置/序号/占位符等)
|
|
12
13
|
*
|
|
13
14
|
* @slot default - 需要应用全局配置的子组件内容
|
|
14
15
|
*
|
|
@@ -29,9 +30,10 @@
|
|
|
29
30
|
*/
|
|
30
31
|
import { ComponentVars } from '../types';
|
|
31
32
|
import { INJECT_COMPONENTS, ensureInjectConfig } from '../constants';
|
|
32
|
-
import { provide } from 'vue';
|
|
33
|
+
import { computed, provide } from 'vue';
|
|
33
34
|
import { getObject } from '../../../shared/core';
|
|
34
35
|
import { ComponentName } from '../../form/constants';
|
|
36
|
+
import { LOCALE_INJECT_KEY, type ProLocale } from '../../../locale';
|
|
35
37
|
|
|
36
38
|
type ComponentMap = Partial<Record<ComponentName, any>>;
|
|
37
39
|
|
|
@@ -53,6 +55,13 @@ type Props = {
|
|
|
53
55
|
* @example { 'input': MyCustomInput, 'select': MyCustomSelect }
|
|
54
56
|
*/
|
|
55
57
|
componentMap?: ComponentMap;
|
|
58
|
+
/**
|
|
59
|
+
* @description 内置文案覆盖
|
|
60
|
+
* 可覆盖任意 locale 文案(如查询/重置/序号/占位符等),
|
|
61
|
+
* 未覆盖的文案默认跟随宿主组件库语言自动切换
|
|
62
|
+
* @example { 'table.query': '搜索' }
|
|
63
|
+
*/
|
|
64
|
+
locale?: Partial<ProLocale>;
|
|
56
65
|
};
|
|
57
66
|
|
|
58
67
|
const props = defineProps<Props>();
|
|
@@ -74,6 +83,12 @@ if (props.componentVars) {
|
|
|
74
83
|
if (props.componentMap) {
|
|
75
84
|
provide(INJECT_COMPONENTS, props.componentMap);
|
|
76
85
|
}
|
|
86
|
+
|
|
87
|
+
// 注入内置文案覆盖,useLocale 在解析文案时会优先使用
|
|
88
|
+
provide(
|
|
89
|
+
LOCALE_INJECT_KEY,
|
|
90
|
+
computed(() => props.locale)
|
|
91
|
+
);
|
|
77
92
|
</script>
|
|
78
93
|
|
|
79
94
|
<template>
|
|
@@ -23,7 +23,6 @@ export const INJECT_CONFIG: {
|
|
|
23
23
|
injectionKey: Symbol(''),
|
|
24
24
|
default: {
|
|
25
25
|
pagination: {
|
|
26
|
-
showTotal: total => `共 ${total} 条`,
|
|
27
26
|
showSizeChanger: true,
|
|
28
27
|
pageSizeOptions: ['10', '20', '30', '40', '50', '100'],
|
|
29
28
|
showQuickJumper: true,
|
|
@@ -47,7 +46,7 @@ export const INJECT_CONFIG: {
|
|
|
47
46
|
// field
|
|
48
47
|
input: {
|
|
49
48
|
injectionKey: Symbol(''),
|
|
50
|
-
default: { maxlength: 100, allowClear: true
|
|
49
|
+
default: { maxlength: 100, allowClear: true },
|
|
51
50
|
},
|
|
52
51
|
textarea: {
|
|
53
52
|
injectionKey: Symbol(''),
|
|
@@ -56,12 +55,11 @@ export const INJECT_CONFIG: {
|
|
|
56
55
|
autoSize: { minRows: 3, maxRows: 6 },
|
|
57
56
|
showCount: true,
|
|
58
57
|
allowClear: true,
|
|
59
|
-
placeholder: '请输入',
|
|
60
58
|
},
|
|
61
59
|
},
|
|
62
60
|
'input-password': {
|
|
63
61
|
injectionKey: Symbol(''),
|
|
64
|
-
default: { maxlength: 100, allowClear: true
|
|
62
|
+
default: { maxlength: 100, allowClear: true },
|
|
65
63
|
},
|
|
66
64
|
'input-search': {
|
|
67
65
|
injectionKey: Symbol(''),
|
|
@@ -73,17 +71,16 @@ export const INJECT_CONFIG: {
|
|
|
73
71
|
max: 10 ** 15 - 1,
|
|
74
72
|
min: -(10 ** 15 + 1),
|
|
75
73
|
controls: false,
|
|
76
|
-
placeholder: '请输入',
|
|
77
74
|
style: { width: '100%' },
|
|
78
75
|
},
|
|
79
76
|
},
|
|
80
77
|
select: {
|
|
81
78
|
injectionKey: Symbol(''),
|
|
82
|
-
default: { allowClear: true,
|
|
79
|
+
default: { allowClear: true, getPopupContainer },
|
|
83
80
|
},
|
|
84
81
|
cascader: {
|
|
85
82
|
injectionKey: Symbol(''),
|
|
86
|
-
default: { allowClear: true,
|
|
83
|
+
default: { allowClear: true, getPopupContainer },
|
|
87
84
|
},
|
|
88
85
|
'date-picker': {
|
|
89
86
|
injectionKey: Symbol(''),
|
|
@@ -46,6 +46,7 @@ import { componentMap, TeleportComponentNamePrefix } from '../../constants';
|
|
|
46
46
|
import { INJECT_COMPONENTS } from '../../../component-provider/constants';
|
|
47
47
|
import { useForm } from '../../hooks/useForm';
|
|
48
48
|
import { getInitProps } from './utils';
|
|
49
|
+
import { useLocale } from '../../../../locale';
|
|
49
50
|
|
|
50
51
|
defineOptions({ name: 'BaseField', inheritAttrs: false });
|
|
51
52
|
|
|
@@ -55,6 +56,8 @@ type Props = {
|
|
|
55
56
|
};
|
|
56
57
|
const { component = undefined, path = '' } = defineProps<Props>();
|
|
57
58
|
|
|
59
|
+
const { t } = useLocale();
|
|
60
|
+
|
|
58
61
|
const form = useForm(false);
|
|
59
62
|
const { getFormData, setFormData } = form;
|
|
60
63
|
|
|
@@ -106,10 +109,13 @@ const parentDisabled = useInjectDisabled();
|
|
|
106
109
|
* 属性分为三类:绑定属性(v-model)、组件属性(传递给组件)、插槽(动态渲染)
|
|
107
110
|
*/
|
|
108
111
|
const groupedAttrs = computed(() => {
|
|
109
|
-
const initProps = getInitProps(
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
112
|
+
const initProps = getInitProps(
|
|
113
|
+
{
|
|
114
|
+
component: component,
|
|
115
|
+
picker: attrs.picker,
|
|
116
|
+
} as Field,
|
|
117
|
+
t
|
|
118
|
+
);
|
|
113
119
|
const mergedProps = mergeProps(
|
|
114
120
|
initProps,
|
|
115
121
|
attrs,
|
|
@@ -2,15 +2,45 @@ import { Field } from '../../../types';
|
|
|
2
2
|
import { getInjectConfig } from '../../../../component-provider/constants';
|
|
3
3
|
import { inject } from 'vue';
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
type LocaleT = (
|
|
6
|
+
key: string,
|
|
7
|
+
params?: Record<string, string | number>
|
|
8
|
+
) => string;
|
|
9
|
+
|
|
10
|
+
/** 组件的占位符对应的 locale key */
|
|
11
|
+
const PLACEHOLDER_KEYS: Record<string, string> = {
|
|
12
|
+
input: 'input.placeholder',
|
|
13
|
+
textarea: 'input.placeholder',
|
|
14
|
+
'input-password': 'input.placeholder',
|
|
15
|
+
'input-number': 'input.placeholder',
|
|
16
|
+
select: 'select.placeholder',
|
|
17
|
+
cascader: 'select.placeholder',
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* 根据组件 key 兜底生成 locale 占位符
|
|
22
|
+
*
|
|
23
|
+
* @description 用户通过 componentVars 或字段属性显式设置了占位符时不再兜底。
|
|
24
|
+
*/
|
|
25
|
+
const getPlaceholderProps = (
|
|
26
|
+
key: string,
|
|
27
|
+
injectProps: Record<string, any>,
|
|
28
|
+
t: LocaleT
|
|
29
|
+
): Record<string, string> => {
|
|
30
|
+
const placeholderKey = PLACEHOLDER_KEYS[key];
|
|
31
|
+
if (!placeholderKey || injectProps.placeholder !== undefined) return {};
|
|
32
|
+
return { placeholder: t(placeholderKey) };
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export const getInitProps = (field: Field, t: LocaleT): Record<string, any> => {
|
|
6
36
|
const { component } = field as any;
|
|
7
37
|
const picker = component === 'date-picker' ? '' : (field as any).picker;
|
|
8
38
|
if (typeof component === 'string') {
|
|
9
39
|
const k = [component, picker].filter(Boolean).join('.');
|
|
10
40
|
const config = getInjectConfig(k);
|
|
11
|
-
if (!config) return {};
|
|
41
|
+
if (!config) return getPlaceholderProps(k, {}, t);
|
|
12
42
|
const injectProps = inject(config.injectionKey, config.default);
|
|
13
|
-
return injectProps;
|
|
43
|
+
return { ...injectProps, ...getPlaceholderProps(k, injectProps, t) };
|
|
14
44
|
}
|
|
15
45
|
return {};
|
|
16
46
|
};
|
|
@@ -7,16 +7,24 @@ import {
|
|
|
7
7
|
MenuItem,
|
|
8
8
|
Checkbox,
|
|
9
9
|
} from '../../../shared/ui';
|
|
10
|
-
import { computed, ref, watch } from 'vue';
|
|
11
|
-
import type { Columns } from '../types';
|
|
10
|
+
import { computed, onMounted, ref, watch } from 'vue';
|
|
11
|
+
import type { Columns, ColumnControlConfig } from '../types';
|
|
12
12
|
import { type Table } from '../hooks/useTable';
|
|
13
13
|
import FilterOutlined from './icons/FilterOutlined.vue';
|
|
14
|
+
import { useLocale } from '../../../locale';
|
|
14
15
|
|
|
15
16
|
type Props = {
|
|
16
17
|
columns: Columns;
|
|
17
18
|
table?: Table;
|
|
19
|
+
columnControl?: ColumnControlConfig;
|
|
18
20
|
};
|
|
19
|
-
const {
|
|
21
|
+
const {
|
|
22
|
+
columns,
|
|
23
|
+
table = undefined,
|
|
24
|
+
columnControl = undefined,
|
|
25
|
+
} = defineProps<Props>();
|
|
26
|
+
|
|
27
|
+
const { t } = useLocale();
|
|
20
28
|
|
|
21
29
|
const open = ref(false);
|
|
22
30
|
|
|
@@ -24,29 +32,46 @@ const checkAll = ref(false);
|
|
|
24
32
|
const indeterminate = ref(false);
|
|
25
33
|
|
|
26
34
|
const checkedColumnsOptions = computed<
|
|
27
|
-
Array<{
|
|
35
|
+
Array<{
|
|
36
|
+
label: string;
|
|
37
|
+
value: string;
|
|
38
|
+
checked: boolean;
|
|
39
|
+
disabled: boolean;
|
|
40
|
+
}>
|
|
28
41
|
>(() =>
|
|
29
|
-
columns.flatMap(item =>
|
|
30
|
-
item.key
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
42
|
+
columns.flatMap(item => {
|
|
43
|
+
if (!item.key || !item.title) return [];
|
|
44
|
+
const key = item.key as string;
|
|
45
|
+
if (columnControl?.excludedKeys?.some(ek => String(ek) === key)) return [];
|
|
46
|
+
const disabled =
|
|
47
|
+
columnControl?.disabledKeys?.some(dk => String(dk) === key) ?? false;
|
|
48
|
+
// labels 优先;title 为字符串时直接使用;vnode 等其他类型降级为 key,避免渲染异常
|
|
49
|
+
const label =
|
|
50
|
+
(columnControl?.labels?.[key] as string) ??
|
|
51
|
+
(typeof item.title === 'string' ? item.title : key);
|
|
52
|
+
return {
|
|
53
|
+
label,
|
|
54
|
+
value: key,
|
|
55
|
+
checked: !item.hidden || disabled,
|
|
56
|
+
disabled,
|
|
57
|
+
};
|
|
58
|
+
})
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
/** 可被用户勾选/取消的列(非 disabled) */
|
|
62
|
+
const controllableOptions = computed(() =>
|
|
63
|
+
checkedColumnsOptions.value.filter(item => !item.disabled)
|
|
38
64
|
);
|
|
39
65
|
|
|
40
66
|
const checkedColumnKeys = computed({
|
|
41
67
|
get() {
|
|
42
|
-
return (
|
|
43
|
-
|
|
44
|
-
item.checked ? item.value : []
|
|
45
|
-
) || []
|
|
68
|
+
return checkedColumnsOptions.value.flatMap(item =>
|
|
69
|
+
item.checked ? item.value : []
|
|
46
70
|
);
|
|
47
71
|
},
|
|
48
72
|
set(val) {
|
|
49
|
-
checkedColumnsOptions.value
|
|
73
|
+
checkedColumnsOptions.value.forEach(item => {
|
|
74
|
+
if (item.disabled) return;
|
|
50
75
|
table?.setColumn?.(item.value, {
|
|
51
76
|
hidden: !val.includes(item.value),
|
|
52
77
|
});
|
|
@@ -54,14 +79,17 @@ const checkedColumnKeys = computed({
|
|
|
54
79
|
},
|
|
55
80
|
});
|
|
56
81
|
|
|
57
|
-
const onCheckAllChange = (
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
82
|
+
const onCheckAllChange = () => {
|
|
83
|
+
// 整行点击触发:当前全选则取消全选,否则全选可控列
|
|
84
|
+
checkedColumnKeys.value = checkAll.value
|
|
85
|
+
? []
|
|
86
|
+
: controllableOptions.value.map(item => item.value);
|
|
61
87
|
indeterminate.value = false;
|
|
62
88
|
};
|
|
63
89
|
|
|
64
90
|
const checkColumnsMenuItemClick = (val: string) => {
|
|
91
|
+
const item = checkedColumnsOptions.value.find(o => o.value === val);
|
|
92
|
+
if (item?.disabled) return;
|
|
65
93
|
if (checkedColumnKeys.value.includes(val)) {
|
|
66
94
|
checkedColumnKeys.value = checkedColumnKeys.value.filter(
|
|
67
95
|
item => item !== val
|
|
@@ -73,13 +101,36 @@ const checkColumnsMenuItemClick = (val: string) => {
|
|
|
73
101
|
|
|
74
102
|
watch(
|
|
75
103
|
checkedColumnKeys,
|
|
76
|
-
|
|
104
|
+
() => {
|
|
105
|
+
const controllableChecked = controllableOptions.value.filter(
|
|
106
|
+
item => item.checked
|
|
107
|
+
);
|
|
77
108
|
indeterminate.value =
|
|
78
|
-
!!
|
|
79
|
-
|
|
109
|
+
!!controllableChecked.length &&
|
|
110
|
+
controllableChecked.length < controllableOptions.value.length;
|
|
111
|
+
checkAll.value =
|
|
112
|
+
controllableChecked.length === controllableOptions.value.length &&
|
|
113
|
+
controllableOptions.value.length > 0;
|
|
80
114
|
},
|
|
81
115
|
{ immediate: true }
|
|
82
116
|
);
|
|
117
|
+
|
|
118
|
+
// 强制 disabledKeys 列始终展示
|
|
119
|
+
onMounted(() => {
|
|
120
|
+
columnControl?.disabledKeys?.forEach(key => {
|
|
121
|
+
table?.setColumn?.(String(key), { hidden: false });
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
watch(
|
|
126
|
+
() => columnControl?.disabledKeys,
|
|
127
|
+
keys => {
|
|
128
|
+
keys?.forEach(key => {
|
|
129
|
+
table?.setColumn?.(String(key), { hidden: false });
|
|
130
|
+
});
|
|
131
|
+
},
|
|
132
|
+
{ deep: true }
|
|
133
|
+
);
|
|
83
134
|
</script>
|
|
84
135
|
|
|
85
136
|
<template>
|
|
@@ -92,25 +143,27 @@ watch(
|
|
|
92
143
|
style="min-width: 100px; max-height: 500px; overflow-y: scroll"
|
|
93
144
|
:selectable="false"
|
|
94
145
|
>
|
|
95
|
-
<MenuItem
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
146
|
+
<MenuItem
|
|
147
|
+
v-if="!columnControl?.disableCheckAll"
|
|
148
|
+
:key="0"
|
|
149
|
+
@click="onCheckAllChange"
|
|
150
|
+
>
|
|
151
|
+
<Checkbox
|
|
152
|
+
:checked="checkAll"
|
|
153
|
+
:indeterminate="indeterminate"
|
|
154
|
+
style="width: 100%"
|
|
155
|
+
>
|
|
156
|
+
{{ t('table.selectAll') }}
|
|
157
|
+
</Checkbox>
|
|
105
158
|
</MenuItem>
|
|
106
|
-
<MenuDivider />
|
|
159
|
+
<MenuDivider v-if="!columnControl?.disableCheckAll" />
|
|
107
160
|
<MenuItem
|
|
108
161
|
v-for="item of checkedColumnsOptions"
|
|
109
162
|
:key="item.value"
|
|
110
163
|
@click="checkColumnsMenuItemClick(item.value)"
|
|
111
164
|
>
|
|
112
|
-
<Checkbox :checked="
|
|
113
|
-
<div
|
|
165
|
+
<Checkbox :checked="item.checked" :disabled="item.disabled">
|
|
166
|
+
<div>{{ item.label }}</div>
|
|
114
167
|
</Checkbox>
|
|
115
168
|
</MenuItem>
|
|
116
169
|
</Menu>
|
|
@@ -53,7 +53,13 @@ import type { ContainerComponent } from '../../form/types';
|
|
|
53
53
|
import SearchForm from './SearchForm.vue';
|
|
54
54
|
import { SearchFormProps } from './SearchForm.vue';
|
|
55
55
|
import type { Table } from '../hooks/useTable';
|
|
56
|
-
import {
|
|
56
|
+
import { useLocale } from '../../../locale';
|
|
57
|
+
import {
|
|
58
|
+
camelizeProperties,
|
|
59
|
+
getObject,
|
|
60
|
+
pick,
|
|
61
|
+
Path,
|
|
62
|
+
} from '../../../shared/core';
|
|
57
63
|
import { ComponentSlots } from 'vue-component-type-helpers';
|
|
58
64
|
import {
|
|
59
65
|
DefaultSearchFormContainer,
|
|
@@ -61,11 +67,14 @@ import {
|
|
|
61
67
|
SizeControl,
|
|
62
68
|
ColumnControl,
|
|
63
69
|
} from '.';
|
|
64
|
-
import { Column, Columns } from '../types';
|
|
70
|
+
import { Column, Columns, ColumnControlConfig } from '../types';
|
|
65
71
|
|
|
66
72
|
defineOptions({ name: 'ProTable', inheritAttrs: false });
|
|
67
73
|
|
|
68
|
-
type Control = {
|
|
74
|
+
type Control = {
|
|
75
|
+
sizeControl: boolean;
|
|
76
|
+
columnControl: boolean | ColumnControlConfig<Path<RecordType>>;
|
|
77
|
+
};
|
|
69
78
|
|
|
70
79
|
type SearchFormConfig = Omit<SearchFormProps, 'form'> & {
|
|
71
80
|
// 是否隐藏搜索表单
|
|
@@ -101,6 +110,8 @@ const {
|
|
|
101
110
|
searchFormConfig = undefined,
|
|
102
111
|
} = defineProps<Props>();
|
|
103
112
|
|
|
113
|
+
const { t } = useLocale();
|
|
114
|
+
|
|
104
115
|
const config = INJECT_CONFIG['pro-table'];
|
|
105
116
|
const injectProps = inject(config.injectionKey, config.default);
|
|
106
117
|
|
|
@@ -197,17 +208,19 @@ const computedTableContainer = computed(() => {
|
|
|
197
208
|
type ReturnGenericParameterTypes<V> = V extends Table<any, infer R> ? R : never;
|
|
198
209
|
type RecordType = ReturnGenericParameterTypes<T>;
|
|
199
210
|
|
|
200
|
-
const indexColumn: ColumnType
|
|
201
|
-
title: '
|
|
211
|
+
const indexColumn = (): ColumnType => ({
|
|
212
|
+
title: t('table.index'),
|
|
202
213
|
dataIndex: '_index',
|
|
203
214
|
width: 80,
|
|
204
215
|
customRender: ({ index }) => index + 1,
|
|
205
|
-
};
|
|
216
|
+
});
|
|
206
217
|
|
|
207
218
|
const computedColumns = computed(
|
|
208
219
|
() =>
|
|
209
220
|
[
|
|
210
|
-
...((addIndexColumn ?? injectProps.addIndexColumn)
|
|
221
|
+
...((addIndexColumn ?? injectProps.addIndexColumn)
|
|
222
|
+
? [indexColumn()]
|
|
223
|
+
: []),
|
|
211
224
|
...(tableAttrs.value.columns ?? columns?.value ?? ([] as any)).flatMap(
|
|
212
225
|
(item: ColumnType<RecordType>, index: number) => {
|
|
213
226
|
if (item.key) return [{ ...item, key: item.key }];
|
|
@@ -237,6 +250,12 @@ const computedPagination = computed<PaginationProps | false>(() => {
|
|
|
237
250
|
...injectAttrs.pagination,
|
|
238
251
|
...pageParam,
|
|
239
252
|
...tableAttrs.value.pagination,
|
|
253
|
+
showTotal:
|
|
254
|
+
tableAttrs.value.pagination?.showTotal ??
|
|
255
|
+
(injectAttrs.pagination === false
|
|
256
|
+
? undefined
|
|
257
|
+
: injectAttrs.pagination?.showTotal) ??
|
|
258
|
+
((total: number) => t('pagination.total', { total })),
|
|
240
259
|
};
|
|
241
260
|
});
|
|
242
261
|
|
|
@@ -255,12 +274,23 @@ const showSearch = computed(() => {
|
|
|
255
274
|
);
|
|
256
275
|
});
|
|
257
276
|
|
|
258
|
-
const computedControl = computed<
|
|
277
|
+
const computedControl = computed<{
|
|
278
|
+
sizeControl: boolean;
|
|
279
|
+
columnControl: boolean | ColumnControlConfig<Path<RecordType>>;
|
|
280
|
+
}>(() => {
|
|
259
281
|
const mergedControl = control ?? injectProps.control;
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
282
|
+
if (typeof mergedControl === 'boolean') {
|
|
283
|
+
return { sizeControl: mergedControl, columnControl: mergedControl };
|
|
284
|
+
}
|
|
285
|
+
const c = mergedControl as Control;
|
|
286
|
+
const sizeControl = c.sizeControl ?? true;
|
|
287
|
+
const columnControl = c.columnControl ?? true;
|
|
288
|
+
return { sizeControl: !!sizeControl, columnControl };
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
const columnControlConfig = computed(() => {
|
|
292
|
+
const cc = computedControl.value.columnControl;
|
|
293
|
+
return typeof cc === 'object' ? cc : undefined;
|
|
264
294
|
});
|
|
265
295
|
|
|
266
296
|
onMounted(() => {
|
|
@@ -305,7 +335,11 @@ onMounted(() => {
|
|
|
305
335
|
v-if="computedControl.columnControl"
|
|
306
336
|
class="pro-table_header_column-control"
|
|
307
337
|
>
|
|
308
|
-
<ColumnControl
|
|
338
|
+
<ColumnControl
|
|
339
|
+
:columns="computedColumns as any"
|
|
340
|
+
:table="table"
|
|
341
|
+
:column-control="columnControlConfig"
|
|
342
|
+
/>
|
|
309
343
|
</div>
|
|
310
344
|
</div>
|
|
311
345
|
|
|
@@ -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,
|
|
@@ -230,7 +233,7 @@ const onSearch = () => {
|
|
|
230
233
|
v-else
|
|
231
234
|
class="pro-table_search-form_reset-button"
|
|
232
235
|
@click="onReset"
|
|
233
|
-
|
|
236
|
+
>{{ t('table.reset') }}</Button
|
|
234
237
|
>
|
|
235
238
|
</template>
|
|
236
239
|
</slot>
|
|
@@ -243,7 +246,7 @@ const onSearch = () => {
|
|
|
243
246
|
type="primary"
|
|
244
247
|
html-type="submit"
|
|
245
248
|
@click="onSearch"
|
|
246
|
-
|
|
249
|
+
>{{ t('table.query') }}
|
|
247
250
|
</Button>
|
|
248
251
|
</template>
|
|
249
252
|
</slot>
|
|
@@ -261,7 +264,7 @@ const onSearch = () => {
|
|
|
261
264
|
class="pro-table_search-form_expand-toggle-button"
|
|
262
265
|
@click="changeExpandStatus"
|
|
263
266
|
>
|
|
264
|
-
{{ expandStatus ? '
|
|
267
|
+
{{ expandStatus ? t('table.collapse') : t('table.expand') }}
|
|
265
268
|
<DownOutlined
|
|
266
269
|
class="transition"
|
|
267
270
|
style="margin-left: 4px"
|
|
@@ -8,9 +8,13 @@ import {
|
|
|
8
8
|
useConfigContextInject,
|
|
9
9
|
} from '../../../shared/ui';
|
|
10
10
|
import ColumnHeightOutlined from './icons/ColumnHeightOutlined.vue';
|
|
11
|
+
import { computed } from 'vue';
|
|
12
|
+
import { useLocale } from '../../../locale';
|
|
11
13
|
|
|
12
14
|
type Size = TableProps['size'];
|
|
13
15
|
|
|
16
|
+
const { t } = useLocale();
|
|
17
|
+
|
|
14
18
|
const configContext = useConfigContextInject();
|
|
15
19
|
|
|
16
20
|
const size = defineModel<Size>('size');
|
|
@@ -21,11 +25,11 @@ const onSizeChange = (val: any) => {
|
|
|
21
25
|
size.value = val.key;
|
|
22
26
|
};
|
|
23
27
|
|
|
24
|
-
const sizeOptions
|
|
25
|
-
{ label: '
|
|
26
|
-
{ label: '
|
|
27
|
-
{ label: '
|
|
28
|
-
];
|
|
28
|
+
const sizeOptions = computed<Array<MenuItemType>>(() => [
|
|
29
|
+
{ label: t('table.sizeDefault'), key: 'large' },
|
|
30
|
+
{ label: t('table.sizeMiddle'), key: 'middle' },
|
|
31
|
+
{ label: t('table.sizeCompact'), key: 'small' },
|
|
32
|
+
]);
|
|
29
33
|
</script>
|
|
30
34
|
|
|
31
35
|
<template>
|
|
@@ -72,3 +72,29 @@ export type Column<D extends Data = Data> = Omit<
|
|
|
72
72
|
* ```
|
|
73
73
|
*/
|
|
74
74
|
export type Columns<D extends Data = Data> = Array<Column<D>>;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* 列控制配置(用于 control.columnControl)
|
|
78
|
+
*
|
|
79
|
+
* @template K - 列 key 类型,ProTable 中传入 Path<RecordType> 获得自动补全
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```ts
|
|
83
|
+
* const config: ColumnControlConfig<'name' | 'age'> = {
|
|
84
|
+
* labels: { name: '姓名', age: '年龄' },
|
|
85
|
+
* excludedKeys: [],
|
|
86
|
+
* disabledKeys: ['name'],
|
|
87
|
+
* disableCheckAll: false,
|
|
88
|
+
* }
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
export type ColumnControlConfig<K extends string | number = string | number> = {
|
|
92
|
+
/** 列在下拉中的显示名称映射,key 为列 key/dataIndex,用于 title 为 vnode 时无法正常渲染 */
|
|
93
|
+
labels?: Partial<Record<K, string>>;
|
|
94
|
+
/** 不在下拉中出现的列 keys(始终展示,不参与勾选) */
|
|
95
|
+
excludedKeys?: K[];
|
|
96
|
+
/** 在下拉中显示但不可取消勾选的列 keys(始终展示,始终勾选) */
|
|
97
|
+
disabledKeys?: K[];
|
|
98
|
+
/** 禁用全选/取消全选 */
|
|
99
|
+
disableCheckAll?: boolean;
|
|
100
|
+
};
|
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 驱动的表单组件,基于 antd-vue Form 封装
|