gi-component 0.0.3 → 0.0.5

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "gi-component",
3
3
  "type": "module",
4
- "version": "0.0.3",
4
+ "version": "0.0.5",
5
5
  "description": "Vue3中基于Element Plus二次封装基础组件库",
6
6
  "author": "lin",
7
7
  "license": "MIT",
@@ -1,207 +1,193 @@
1
- <template>
2
- <el-form ref="formRef" :model="form" :class="b('edit-table')">
3
- <el-table :data="form.tableData" border v-bind="attrs">
4
- <el-table-column
5
- v-for="(column, index) in props.columns"
6
- :key="column.dataIndex + index"
7
- :width="column.width"
8
- v-bind="column.columnProps"
9
- :prop="column.dataIndex"
10
- :label="column.title"
11
- :label-class-name="getLabelClassName(column)"
12
- >
13
- <template #default="scope">
14
- <el-form-item
15
- v-bind="column.formItemProps"
16
- :label="column.title"
17
- :prop="`tableData[${scope.$index}].${column.dataIndex}`"
18
- :rules="getFormItemRules(column)"
19
- >
20
- <template v-if="column.slotName">
21
- <slot :name="column.slotName" v-bind="scope"></slot>
22
- </template>
23
- <component
24
- :is="COMP_MAP[column.type] || column.type"
25
- v-else
26
- v-bind="getComponentBindProps(column)"
27
- v-model="scope.row[column.dataIndex]"
28
- class="w-full"
29
- :disabled="isDisabled(scope)"
30
- >
31
- </component>
32
- </el-form-item>
33
- </template>
34
- </el-table-column>
35
- </el-table>
36
- </el-form>
37
- </template>
38
-
39
- <script lang="ts" setup>
40
- import type { FormInstance } from 'element-plus';
41
- import type { EditTableColumnItem, EditTableColumnItemType } from './type';
42
- import type { EditTableProps } from './type.ts';
43
- import * as El from 'element-plus';
44
- import { computed, h, reactive, ref, toRaw, useAttrs, watch } from 'vue';
45
- import { useBemClass } from '../../../hooks';
46
-
47
- const props = withDefaults(defineProps<EditTableProps>(), {
48
- rowKey: 'id',
49
- data: () => [],
50
- columns: () => []
51
- });
52
-
53
- const attrs = useAttrs();
54
- const { b } = useBemClass();
55
-
56
- const COMP_MAP: Record<Exclude<EditTableColumnItemType, 'slot'>, any> = {
57
- input: El.ElInput,
58
- textarea: El.ElInput,
59
- 'input-number': El.ElInputNumber,
60
- 'input-tag': El.ElInputTag,
61
- select: El.ElSelect,
62
- 'select-v2': El.ElSelectV2,
63
- 'tree-select': El.ElTreeSelect,
64
- cascader: El.ElCascader,
65
- slider: El.ElSlider,
66
- switch: El.ElSwitch,
67
- rate: El.ElRate,
68
- 'checkbox-group': El.ElCheckboxGroup,
69
- checkbox: El.ElCheckbox,
70
- 'radio-group': El.ElRadioGroup,
71
- radio: El.ElRadio,
72
- 'date-picker': El.ElDatePicker,
73
- 'time-picker': El.ElTimePicker,
74
- 'time-select': El.ElTimeSelect,
75
- 'color-picker': El.ElColorPicker,
76
- transfer: El.ElTransfer,
77
- autocomplete: El.ElAutocomplete,
78
- upload: El.ElUpload
79
- };
80
-
81
- const formRef = ref<FormInstance | null>();
82
-
83
- /** 表单数据 */
84
- const form = computed(() => ({ tableData: props.data }));
85
-
86
- const clearable = false;
87
- /** 组件静态配置 */
88
- const STATIC_PROPS = new Map([
89
- ['input', { clearable, maxlength: 20 }],
90
- [
91
- 'textarea',
92
- {
93
- clearable,
94
- type: 'textarea',
95
- rows: 1,
96
- maxlength: 200,
97
- showWordLimit: true
98
- }
99
- ],
100
- ['input-number', {}],
101
- ['input-tag', { clearable }],
102
- ['select', { clearable }],
103
- ['select-v2', { clearable }],
104
- ['tree-select', { clearable }],
105
- ['cascader', { clearable }],
106
- ['slider', {}],
107
- ['switch', {}],
108
- ['rate', {}],
109
- ['checkbox-group', {}],
110
- ['checkbox', {}],
111
- ['radio-group', {}],
112
- ['radio', {}],
113
- ['date-picker', { clearable }],
114
- ['time-picker', { clearable }],
115
- ['time-select', { clearable }],
116
- ['color-picker', {}],
117
- ['transfer', {}],
118
- ['autocomplete', {}],
119
- ['upload', {}],
120
- ['title', {}]
121
- ]);
122
-
123
- /** 获取占位文本 */
124
- const getPlaceholder = (item: EditTableColumnItem) => {
125
- if (!item.type) return undefined;
126
- if (['input', 'input-number', 'input-tag'].includes(item.type)) {
127
- return `请输入${item.title}`;
128
- }
129
- if (['textarea'].includes(item.type)) {
130
- return `请填写${item.title}`;
131
- }
132
- if (
133
- ['select', 'select-v2', 'tree-select', 'cascader', 'time-select'].includes(
134
- item.type
135
- )
136
- ) {
137
- return `请选择${item.title}`;
138
- }
139
- if (['date-picker'].includes(item.type)) {
140
- return `请选择日期`;
141
- }
142
- if (['time-picker'].includes(item.type)) {
143
- return `请选择时间`;
144
- }
145
- return undefined;
146
- };
147
-
148
- // 组件的默认props配置
149
- function getComponentBindProps(item: EditTableColumnItem) {
150
- // 获取默认配置
151
- const defaultProps: any = STATIC_PROPS.get(item.type || '') || {};
152
- defaultProps.placeholder = getPlaceholder(item);
153
- if (item.type === 'date-picker') {
154
- defaultProps.valueFormat =
155
- item?.props?.type === 'datetime' ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD';
156
- }
157
- // 合并默认配置和自定义配置
158
- return { ...defaultProps, ...item.props };
159
- }
160
-
161
- /** 表单项校验规则 */
162
- function getFormItemRules(item: EditTableColumnItem) {
163
- if (item.required) {
164
- return [
165
- { required: true, message: `${item.title}为必填项` },
166
- ...(Array.isArray(item.rules) ? item.rules : [])
167
- ];
168
- }
169
- return item.rules;
170
- }
171
-
172
- /** 表头标题样式 */
173
- function getLabelClassName(item: EditTableColumnItem) {
174
- if (item.required) return 'column-required';
175
- return '';
176
- }
177
-
178
- /** 判断是否禁用 */
179
- const isDisabled = (p: any) => {
180
- if (typeof props?.cellDisabled === 'function') return props.cellDisabled(p);
181
- return false;
182
- };
183
-
184
- defineExpose({ formRef });
185
- </script>
186
-
187
- <style lang="scss" scoped>
188
- :deep(.el-form-item) {
189
- margin-bottom: 0;
190
-
191
- .el-form-item__label {
192
- display: none;
193
- }
194
- }
195
-
196
- :deep(.column-required) {
197
- .cell {
198
- position: relative;
199
-
200
- &::after {
201
- content: '*';
202
- color: red;
203
- margin-left: 2px;
204
- }
205
- }
206
- }
207
- </style>
1
+ <template>
2
+ <el-form ref="formRef" :model="form" :class="b('edit-table')">
3
+ <el-table :data="form.tableData" border v-bind="attrs">
4
+ <el-table-column v-for="(column, index) in props.columns" :key="column.prop + index" :width="column.width"
5
+ v-bind="column.columnProps" :prop="column.prop" :label="column.label"
6
+ :label-class-name="getLabelClassName(column)">
7
+ <template #default="scope">
8
+ <el-form-item v-bind="column.formItemProps" :label="column.label"
9
+ :prop="`tableData[${scope.$index}].${column.prop}`" :rules="getFormItemRules(column)">
10
+ <template v-if="column.slotName">
11
+ <slot :name="column.slotName" v-bind="scope"></slot>
12
+ </template>
13
+ <component :is="COMP_MAP[column.type] || column.type" v-else v-bind="getComponentBindProps(column)"
14
+ v-model="scope.row[column.prop]" class="w-full" :disabled="isDisabled(scope)">
15
+ </component>
16
+ </el-form-item>
17
+ </template>
18
+ </el-table-column>
19
+ </el-table>
20
+ </el-form>
21
+ </template>
22
+
23
+ <script lang="ts" setup>
24
+ import type { FormInstance } from 'element-plus';
25
+ import type { EditTableColumnItem, EditTableColumnItemType } from './type';
26
+ import type { EditTableProps } from './type.ts';
27
+ import * as El from 'element-plus';
28
+ import { computed, h, reactive, ref, toRaw, useAttrs, watch } from 'vue';
29
+ import { useBemClass } from '../../../hooks';
30
+ import InputSearch from '../../input-search'
31
+
32
+ const props = withDefaults(defineProps<EditTableProps>(), {
33
+ rowKey: 'id',
34
+ data: () => [],
35
+ columns: () => []
36
+ });
37
+
38
+ const attrs = useAttrs();
39
+ const { b } = useBemClass();
40
+
41
+ const COMP_MAP: Record<Exclude<EditTableColumnItemType, 'slot'>, any> = {
42
+ input: El.ElInput,
43
+ textarea: El.ElInput,
44
+ 'input-number': El.ElInputNumber,
45
+ 'input-tag': El.ElInputTag,
46
+ select: El.ElSelect,
47
+ 'select-v2': El.ElSelectV2,
48
+ 'tree-select': El.ElTreeSelect,
49
+ cascader: El.ElCascader,
50
+ slider: El.ElSlider,
51
+ switch: El.ElSwitch,
52
+ rate: El.ElRate,
53
+ 'checkbox-group': El.ElCheckboxGroup,
54
+ checkbox: El.ElCheckbox,
55
+ 'radio-group': El.ElRadioGroup,
56
+ radio: El.ElRadio,
57
+ 'date-picker': El.ElDatePicker,
58
+ 'time-picker': El.ElTimePicker,
59
+ 'time-select': El.ElTimeSelect,
60
+ 'color-picker': El.ElColorPicker,
61
+ transfer: El.ElTransfer,
62
+ autocomplete: El.ElAutocomplete,
63
+ upload: El.ElUpload,
64
+ 'input-search': InputSearch
65
+ };
66
+
67
+ const formRef = ref<FormInstance | null>();
68
+
69
+ /** 表单数据 */
70
+ const form = computed(() => ({ tableData: props.data }));
71
+
72
+ const clearable = false;
73
+ /** 组件静态配置 */
74
+ const STATIC_PROPS = new Map([
75
+ ['input', { clearable, maxlength: 20 }],
76
+ [
77
+ 'textarea',
78
+ {
79
+ clearable,
80
+ type: 'textarea',
81
+ rows: 1,
82
+ maxlength: 200,
83
+ showWordLimit: true
84
+ }
85
+ ],
86
+ ['input-number', {}],
87
+ ['input-tag', { clearable }],
88
+ ['select', { clearable }],
89
+ ['select-v2', { clearable }],
90
+ ['tree-select', { clearable }],
91
+ ['cascader', { clearable }],
92
+ ['slider', {}],
93
+ ['switch', {}],
94
+ ['rate', {}],
95
+ ['checkbox-group', {}],
96
+ ['checkbox', {}],
97
+ ['radio-group', {}],
98
+ ['radio', {}],
99
+ ['date-picker', { clearable }],
100
+ ['time-picker', { clearable }],
101
+ ['time-select', { clearable }],
102
+ ['color-picker', {}],
103
+ ['transfer', {}],
104
+ ['autocomplete', {}],
105
+ ['upload', {}],
106
+ ['title', {}]
107
+ ]);
108
+
109
+ /** 获取占位文本 */
110
+ const getPlaceholder = (item: EditTableColumnItem) => {
111
+ if (!item.type) return undefined;
112
+ if (['input', 'input-number', 'input-tag'].includes(item.type)) {
113
+ return `请输入${item.label}`;
114
+ }
115
+ if (['textarea'].includes(item.type)) {
116
+ return `请填写${item.label}`;
117
+ }
118
+ if (
119
+ ['select', 'select-v2', 'tree-select', 'cascader', 'time-select', 'input-search'].includes(
120
+ item.type
121
+ )
122
+ ) {
123
+ return `请选择${item.label}`;
124
+ }
125
+ if (['date-picker'].includes(item.type)) {
126
+ return `请选择日期`;
127
+ }
128
+ if (['time-picker'].includes(item.type)) {
129
+ return `请选择时间`;
130
+ }
131
+ return undefined;
132
+ };
133
+
134
+ // 组件的默认props配置
135
+ function getComponentBindProps(item: EditTableColumnItem) {
136
+ // 获取默认配置
137
+ const defaultProps: any = STATIC_PROPS.get(item.type || '') || {};
138
+ defaultProps.placeholder = getPlaceholder(item);
139
+ if (item.type === 'date-picker') {
140
+ defaultProps.valueFormat =
141
+ item?.componentProps?.type === 'datetime' ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD';
142
+ }
143
+ // 合并默认配置和自定义配置
144
+ return { ...defaultProps, ...item.componentProps };
145
+ }
146
+
147
+ /** 表单项校验规则 */
148
+ function getFormItemRules(item: EditTableColumnItem) {
149
+ if (item.required) {
150
+ return [
151
+ { required: true, message: `${item.label}为必填项` },
152
+ ...(Array.isArray(item.rules) ? item.rules : [])
153
+ ];
154
+ }
155
+ return item.rules;
156
+ }
157
+
158
+ /** 表头标题样式 */
159
+ function getLabelClassName(item: EditTableColumnItem) {
160
+ if (item.required) return 'column-required';
161
+ return '';
162
+ }
163
+
164
+ /** 判断是否禁用 */
165
+ const isDisabled = (p: any) => {
166
+ if (typeof props?.cellDisabled === 'function') return props.cellDisabled(p);
167
+ return false;
168
+ };
169
+
170
+ defineExpose({ formRef });
171
+ </script>
172
+
173
+ <style lang="scss" scoped>
174
+ :deep(.el-form-item) {
175
+ margin-bottom: 0;
176
+
177
+ .el-form-item__label {
178
+ display: none;
179
+ }
180
+ }
181
+
182
+ :deep(.column-required) {
183
+ .cell {
184
+ position: relative;
185
+
186
+ &::after {
187
+ content: '*';
188
+ color: red;
189
+ margin-left: 2px;
190
+ }
191
+ }
192
+ }
193
+ </style>
@@ -1,69 +1,71 @@
1
- import type * as El from 'element-plus';
2
-
3
- export type EditTableColumnItemType =
4
- | 'input'
5
- | 'textarea'
6
- | 'input-number'
7
- | 'input-tag'
8
- | 'select'
9
- | 'select-v2'
10
- | 'tree-select'
11
- | 'cascader'
12
- | 'slider'
13
- | 'switch'
14
- | 'rate'
15
- | 'checkbox-group'
16
- | 'checkbox'
17
- | 'radio-group'
18
- | 'radio'
19
- | 'date-picker'
20
- | 'time-picker'
21
- | 'time-select'
22
- | 'color-picker'
23
- | 'transfer'
24
- | 'autocomplete'
25
- | 'upload'
26
- | 'slot'
27
- | 'cecw-input-search';
28
-
29
- export interface EditTableColumnItem {
30
- type?: EditTableColumnItemType;
31
- title: string;
32
- dataIndex: string;
33
- width?: number | string;
34
- required?: boolean;
35
- rules?: El.FormItemRule[]; // 表单校验规则
36
- props?: ColumnItemProps;
37
- columnProps?: El.TableColumnInstance['$props'];
38
- formItemProps?: El.FormItemProps;
39
- slotName?: string;
40
- }
41
-
42
- export type ColumnItemProps = El.InputProps &
43
- El.InputNumberProps &
44
- El.InputTagProps &
45
- El.ISelectProps &
46
- El.ISelectV2Props &
47
- El.TreeInstance['$props'] &
48
- El.CascaderProps &
49
- El.SliderProps &
50
- El.SwitchProps &
51
- El.RateProps &
52
- El.CheckboxGroupProps &
53
- El.CheckboxProps &
54
- El.RadioGroupProps &
55
- El.RadioProps &
56
- El.DatePickerProps &
57
- El.TimePickerDefaultProps &
58
- El.TimeSelectProps &
59
- El.ColorPickerProps &
60
- El.TransferProps &
61
- El.AutocompleteProps &
62
- El.UploadProps;
63
-
64
- export interface EditTableProps {
65
- rowKey?: string;
66
- data?: any[];
67
- columns?: EditTableColumnItem[];
68
- cellDisabled?: any;
69
- }
1
+ import type * as El from 'element-plus';
2
+ import type { InputSearchInstance } from '../../input-search'
3
+
4
+ export type EditTableColumnItemType =
5
+ | 'input'
6
+ | 'textarea'
7
+ | 'input-number'
8
+ | 'input-tag'
9
+ | 'select'
10
+ | 'select-v2'
11
+ | 'tree-select'
12
+ | 'cascader'
13
+ | 'slider'
14
+ | 'switch'
15
+ | 'rate'
16
+ | 'checkbox-group'
17
+ | 'checkbox'
18
+ | 'radio-group'
19
+ | 'radio'
20
+ | 'date-picker'
21
+ | 'time-picker'
22
+ | 'time-select'
23
+ | 'color-picker'
24
+ | 'transfer'
25
+ | 'autocomplete'
26
+ | 'upload'
27
+ | 'slot'
28
+ | 'input-search';
29
+
30
+ export interface EditTableColumnItem {
31
+ type?: EditTableColumnItemType;
32
+ label: string;
33
+ prop: string;
34
+ width?: number | string;
35
+ required?: boolean;
36
+ rules?: El.FormItemRule[]; // 表单校验规则
37
+ componentProps?: ColumnItemProps;
38
+ columnProps?: El.TableColumnInstance['$props'];
39
+ formItemProps?: El.FormItemProps;
40
+ slotName?: string;
41
+ }
42
+
43
+ export type ColumnItemProps = El.InputProps &
44
+ El.InputNumberProps &
45
+ El.InputTagProps &
46
+ El.SelectProps &
47
+ El.SelectV2Props &
48
+ El.TreeInstance['$props'] &
49
+ El.CascaderProps &
50
+ El.SliderProps &
51
+ El.SwitchProps &
52
+ El.RateProps &
53
+ El.CheckboxGroupProps &
54
+ El.CheckboxProps &
55
+ El.RadioGroupProps &
56
+ El.RadioProps &
57
+ El.DatePickerProps &
58
+ El.TimePickerDefaultProps &
59
+ El.TimeSelectProps &
60
+ El.ColorPickerProps &
61
+ El.TransferProps &
62
+ El.AutocompleteProps &
63
+ El.UploadProps &
64
+ InputSearchInstance['$props']
65
+
66
+ export interface EditTableProps {
67
+ rowKey?: string;
68
+ data?: any[];
69
+ columns?: EditTableColumnItem[];
70
+ cellDisabled?: any;
71
+ }
@@ -1,49 +1,42 @@
1
- <template>
2
- <el-table-column v-bind="columnProps">
3
- <!-- 处理render函数 -->
4
- <template v-if="column.render" v-slot="scope">
5
- <component :is="column.render(scope)" />
6
- </template>
7
-
8
- <!-- 处理插槽内容 -->
9
- <template v-else-if="column.slotName" #default="scope">
10
- <slot :name="column.slotName" v-bind="scope" />
11
- </template>
12
-
13
- <!-- 递归渲染子列 -->
14
- <template v-if="column.children && column.children.length > 0">
15
- <TableColumn
16
- v-for="child in column.children"
17
- :key="child.prop || child.label"
18
- :column="child"
19
- >
20
- <!-- 将所有插槽传递给子组件 -->
21
- <template
22
- v-for="(_, slotName) in $slots"
23
- :key="slotName"
24
- #[slotName]="scope"
25
- >
26
- <slot :name="slotName" v-bind="scope" />
27
- </template>
28
- </TableColumn>
29
- </template>
30
- </el-table-column>
31
- </template>
32
-
33
- <script lang="ts" setup>
34
- import type { TableColumnItem } from './type';
35
- import { computed } from 'vue';
36
- import TableColumn from './TableColumn.vue';
37
-
38
- const props = defineProps<{
39
- column: TableColumnItem;
40
- }>();
41
-
42
- // 计算el-table-column需要的属性
43
- const columnProps = computed(() => {
44
- const { slotName, render, children, ...restProps } = props.column;
45
- return restProps;
46
- });
47
- </script>
48
-
49
- <style scoped></style>
1
+ <template>
2
+ <el-table-column v-bind="columnProps">
3
+ <!-- 处理render函数 -->
4
+ <template v-if="column.render" v-slot="scope">
5
+ <template v-if="typeof column.render(scope) === 'string'">{{ column.render(scope) }}</template>
6
+ <component v-else :is="column.render(scope)" />
7
+ </template>
8
+
9
+ <!-- 处理插槽内容 -->
10
+ <template v-else-if="column.slotName" #default="scope">
11
+ <slot :name="column.slotName" v-bind="scope" />
12
+ </template>
13
+
14
+ <!-- 递归渲染子列 -->
15
+ <template v-if="column.children && column.children.length > 0">
16
+ <TableColumn v-for="child in column.children" :key="child.prop || child.label" :column="child">
17
+ <!-- 将所有插槽传递给子组件 -->
18
+ <template v-for="(_, slotName) in $slots" :key="slotName" #[slotName]="scope">
19
+ <slot :name="slotName" v-bind="scope" />
20
+ </template>
21
+ </TableColumn>
22
+ </template>
23
+ </el-table-column>
24
+ </template>
25
+
26
+ <script lang="ts" setup>
27
+ import type { TableColumnItem } from './type';
28
+ import { computed } from 'vue';
29
+ import TableColumn from './TableColumn.vue';
30
+
31
+ const props = defineProps<{
32
+ column: TableColumnItem;
33
+ }>();
34
+
35
+ // 计算el-table-column需要的属性
36
+ const columnProps = computed(() => {
37
+ const { slotName, render, children, ...restProps } = props.column;
38
+ return restProps;
39
+ });
40
+ </script>
41
+
42
+ <style scoped></style>