@ebiz/designer-components 0.1.38 → 0.1.39
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/dist/designer-components.css +1 -1
- package/dist/index.mjs +8253 -8020
- package/package.json +1 -1
- package/src/components/senior/EbizSForm/TABLE_USAGE.md +1 -0
- package/src/components/senior/EbizSForm/item.vue +321 -4
- package/src/views/EbizSForm/index.vue +8 -2
- package/src/views/EbizSFormItemTableDemo.vue +1 -0
- package/src/views/EbizSFormTableDemo.vue +1 -0
package/package.json
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -121,6 +121,103 @@
|
|
|
121
121
|
@change="handleChange" />
|
|
122
122
|
</template>
|
|
123
123
|
|
|
124
|
+
<!-- 子表格 -->
|
|
125
|
+
<template v-else-if="type === 'table'">
|
|
126
|
+
<div class="ebiz-form-table">
|
|
127
|
+
<t-space direction="vertical" style="width: 100%;">
|
|
128
|
+
<!-- 添加按钮 -->
|
|
129
|
+
<div>
|
|
130
|
+
<t-button theme="primary" variant="outline" @click="addTableRow" :disabled="disabled">
|
|
131
|
+
<template #icon>
|
|
132
|
+
<svg width="16" height="16" viewBox="0 0 16 16" fill="none">
|
|
133
|
+
<path d="M8 1V15M1 8H15" stroke="currentColor" stroke-width="1.5"
|
|
134
|
+
stroke-linecap="round" />
|
|
135
|
+
</svg>
|
|
136
|
+
</template>
|
|
137
|
+
{{ addButtonText }}
|
|
138
|
+
</t-button>
|
|
139
|
+
</div>
|
|
140
|
+
|
|
141
|
+
<!-- 表格 -->
|
|
142
|
+
<t-table :data="computedModelValue" :columns="computedTableColumns" :pagination="false" row-key="__id"
|
|
143
|
+
size="small" bordered :empty="'暂无数据'" >
|
|
144
|
+
<!-- 序号列 -->
|
|
145
|
+
<template #index="{ rowIndex }">
|
|
146
|
+
{{ rowIndex + 1 }}
|
|
147
|
+
</template>
|
|
148
|
+
|
|
149
|
+
<!-- 动态渲染每个数据列 -->
|
|
150
|
+
<template v-for="col in tableColumns" :key="col.key" #[col.key]="{ row, rowIndex }">
|
|
151
|
+
<!-- 输入框 -->
|
|
152
|
+
<t-input v-if="!col.type || col.type === 'input'" v-model="row[col.key]"
|
|
153
|
+
:disabled="disabled" :placeholder="col.placeholder || `请输入${col.name}`"
|
|
154
|
+
:clearable="col.clearable !== false" :maxlength="col.maxlength"
|
|
155
|
+
@update:model-value="(value) => updateTableCell(rowIndex, col.key, value)" />
|
|
156
|
+
|
|
157
|
+
<!-- 数字输入框 -->
|
|
158
|
+
<t-input-number v-else-if="col.type === 'number'" v-model="row[col.key]"
|
|
159
|
+
:disabled="disabled" :placeholder="col.placeholder || `请输入${col.name}`"
|
|
160
|
+
:min="col.min" :max="col.max" :step="col.step || 1"
|
|
161
|
+
:decimal-places="col.decimalPlaces"
|
|
162
|
+
@update:model-value="(value) => updateTableCell(rowIndex, col.key, value)" />
|
|
163
|
+
|
|
164
|
+
<!-- 选择器 -->
|
|
165
|
+
<t-select v-else-if="col.type === 'select'" v-model="row[col.key]"
|
|
166
|
+
:disabled="disabled" :placeholder="col.placeholder || `请选择${col.name}`"
|
|
167
|
+
:options="col.options || []" :clearable="col.clearable !== false"
|
|
168
|
+
:filterable="col.filterable" :multiple="col.multiple"
|
|
169
|
+
@update:model-value="(value) => updateTableCell(rowIndex, col.key, value)" />
|
|
170
|
+
|
|
171
|
+
<!-- 日期选择器 -->
|
|
172
|
+
<t-date-picker v-else-if="col.type === 'date'" v-model="row[col.key]"
|
|
173
|
+
:disabled="disabled" :placeholder="col.placeholder || `请选择${col.name}`"
|
|
174
|
+
:format="col.format || 'YYYY-MM-DD'" :clearable="col.clearable !== false"
|
|
175
|
+
@update:model-value="(value) => updateTableCell(rowIndex, col.key, value)" />
|
|
176
|
+
|
|
177
|
+
<!-- 日期时间选择器 -->
|
|
178
|
+
<t-date-picker v-else-if="col.type === 'datetime'" v-model="row[col.key]"
|
|
179
|
+
:disabled="disabled" :placeholder="col.placeholder || `请选择${col.name}`"
|
|
180
|
+
:format="col.format || 'YYYY-MM-DD HH:mm:ss'" enable-time-picker
|
|
181
|
+
:clearable="col.clearable !== false"
|
|
182
|
+
@update:model-value="(value) => updateTableCell(rowIndex, col.key, value)" />
|
|
183
|
+
|
|
184
|
+
<!-- 开关 -->
|
|
185
|
+
<t-switch v-else-if="col.type === 'switch'" v-model="row[col.key]"
|
|
186
|
+
:disabled="disabled"
|
|
187
|
+
@update:model-value="(value) => updateTableCell(rowIndex, col.key, value)" />
|
|
188
|
+
|
|
189
|
+
<!-- 文本域 -->
|
|
190
|
+
<t-textarea v-else-if="col.type === 'textarea'" v-model="row[col.key]"
|
|
191
|
+
:disabled="disabled" :placeholder="col.placeholder || `请输入${col.name}`"
|
|
192
|
+
:autosize="col.autosize || { minRows: 2, maxRows: 4 }" :maxlength="col.maxlength"
|
|
193
|
+
@update:model-value="(value) => updateTableCell(rowIndex, col.key, value)" />
|
|
194
|
+
|
|
195
|
+
<!-- 单选框组 -->
|
|
196
|
+
<t-radio-group v-else-if="col.type === 'radio'" v-model="row[col.key]"
|
|
197
|
+
:disabled="disabled" :options="col.options || []"
|
|
198
|
+
@update:model-value="(value) => updateTableCell(rowIndex, col.key, value)" />
|
|
199
|
+
|
|
200
|
+
<!-- 复选框组 -->
|
|
201
|
+
<t-checkbox-group v-else-if="col.type === 'checkbox'" v-model="row[col.key]"
|
|
202
|
+
:disabled="disabled" :options="col.options || []" :max="col.max"
|
|
203
|
+
@update:model-value="(value) => updateTableCell(rowIndex, col.key, value)" />
|
|
204
|
+
|
|
205
|
+
<!-- 默认文本显示 -->
|
|
206
|
+
<span v-else>{{ row[col.key] || '' }}</span>
|
|
207
|
+
</template>
|
|
208
|
+
|
|
209
|
+
<!-- 操作列 -->
|
|
210
|
+
<template v-if="showTableActions" #actions="{ rowIndex }">
|
|
211
|
+
<t-button theme="danger" variant="text" size="small" :disabled="disabled"
|
|
212
|
+
@click="removeTableRow(rowIndex)">
|
|
213
|
+
删除
|
|
214
|
+
</t-button>
|
|
215
|
+
</template>
|
|
216
|
+
</t-table>
|
|
217
|
+
</t-space>
|
|
218
|
+
</div>
|
|
219
|
+
</template>
|
|
220
|
+
|
|
124
221
|
<!-- 默认插槽,用于自定义控件 -->
|
|
125
222
|
<template v-else>
|
|
126
223
|
</template>
|
|
@@ -132,7 +229,7 @@
|
|
|
132
229
|
<script>
|
|
133
230
|
/**
|
|
134
231
|
* @displayName PC端表单项
|
|
135
|
-
* @description PC端表单项组件,基于TDesign FormItem
|
|
232
|
+
* @description PC端表单项组件,基于TDesign FormItem封装,支持多种控件类型,包括子表格功能
|
|
136
233
|
* @category 表单组件
|
|
137
234
|
* @name EbizSFormItem
|
|
138
235
|
*/
|
|
@@ -157,7 +254,10 @@ import {
|
|
|
157
254
|
Slider as TSlider,
|
|
158
255
|
Cascader as TCascader,
|
|
159
256
|
TreeSelect as TTreeSelect,
|
|
160
|
-
ColorPicker as TColorPicker
|
|
257
|
+
ColorPicker as TColorPicker,
|
|
258
|
+
Table as TTable,
|
|
259
|
+
Button as TButton,
|
|
260
|
+
Space as TSpace
|
|
161
261
|
} from 'tdesign-vue-next';
|
|
162
262
|
import EbizRemoteSelect from '../../EbizRemoteSelect.vue';
|
|
163
263
|
import EbizEmployeeSelector from '../../EbizEmployeeSelector.vue';
|
|
@@ -167,7 +267,7 @@ import { EbizUpload } from '../../../index.js'
|
|
|
167
267
|
const props = defineProps({
|
|
168
268
|
/**
|
|
169
269
|
* 组件类型
|
|
170
|
-
* @options input|number|textarea|select|date|datetime|time|radio|checkbox|switch|slider|upload|cascader|tree-select|color-picker|employee|dept
|
|
270
|
+
* @options input|number|textarea|select|date|datetime|time|radio|checkbox|switch|slider|upload|cascader|tree-select|color-picker|employee|dept|table
|
|
171
271
|
*/
|
|
172
272
|
type: {
|
|
173
273
|
type: String,
|
|
@@ -175,7 +275,7 @@ const props = defineProps({
|
|
|
175
275
|
validator: (val) => [
|
|
176
276
|
'input', 'number', 'textarea', 'select', 'date', 'datetime', 'time', 'radio',
|
|
177
277
|
'checkbox', 'switch', 'slider', 'upload', 'cascader', 'tree-select',
|
|
178
|
-
'color-picker', 'employee', 'dept'
|
|
278
|
+
'color-picker', 'employee', 'dept', 'table'
|
|
179
279
|
].includes(val)
|
|
180
280
|
},
|
|
181
281
|
/**
|
|
@@ -523,6 +623,32 @@ const props = defineProps({
|
|
|
523
623
|
companyId: {
|
|
524
624
|
type: [String, Number],
|
|
525
625
|
default: undefined
|
|
626
|
+
},
|
|
627
|
+
/**
|
|
628
|
+
* 子表格列配置,用于table类型
|
|
629
|
+
* 示例:[
|
|
630
|
+
* {name:'名称', key:'name', type:'input', width:150},
|
|
631
|
+
* {name:'类型', key:'type', type:'select', options:[{label:'选项1', value:'1'}]},
|
|
632
|
+
* {name:'数量', key:'num', type:'number', min:0, max:999}
|
|
633
|
+
* ]
|
|
634
|
+
*/
|
|
635
|
+
tableColumns: {
|
|
636
|
+
type: Array,
|
|
637
|
+
default: () => []
|
|
638
|
+
},
|
|
639
|
+
/**
|
|
640
|
+
* 子表格是否显示操作列
|
|
641
|
+
*/
|
|
642
|
+
showTableActions: {
|
|
643
|
+
type: Boolean,
|
|
644
|
+
default: true
|
|
645
|
+
},
|
|
646
|
+
/**
|
|
647
|
+
* 子表格新增按钮文本
|
|
648
|
+
*/
|
|
649
|
+
addButtonText: {
|
|
650
|
+
type: String,
|
|
651
|
+
default: '添加数据'
|
|
526
652
|
}
|
|
527
653
|
});
|
|
528
654
|
|
|
@@ -536,10 +662,48 @@ const emit = defineEmits([
|
|
|
536
662
|
const computedModelValue = computed({
|
|
537
663
|
get: () => props.modelValue,
|
|
538
664
|
set: (val) => {
|
|
665
|
+
console.log("val",val)
|
|
539
666
|
emit('update:modelValue', val);
|
|
540
667
|
}
|
|
541
668
|
});
|
|
542
669
|
|
|
670
|
+
// 表格列配置计算属性
|
|
671
|
+
const computedTableColumns = computed(() => {
|
|
672
|
+
if (props.type !== 'table' || !props.tableColumns?.length) return [];
|
|
673
|
+
|
|
674
|
+
const columns = [];
|
|
675
|
+
|
|
676
|
+
// 添加序号列
|
|
677
|
+
columns.push({
|
|
678
|
+
colKey: 'index',
|
|
679
|
+
title: '序号',
|
|
680
|
+
width: 80,
|
|
681
|
+
align: 'center'
|
|
682
|
+
});
|
|
683
|
+
|
|
684
|
+
// 添加用户配置的列
|
|
685
|
+
const userColumns = props.tableColumns.map(col => ({
|
|
686
|
+
colKey: col.key,
|
|
687
|
+
title: col.name,
|
|
688
|
+
width: col.width || undefined,
|
|
689
|
+
align: col.align || 'left'
|
|
690
|
+
}));
|
|
691
|
+
|
|
692
|
+
columns.push(...userColumns);
|
|
693
|
+
|
|
694
|
+
// 添加操作列
|
|
695
|
+
if (props.showTableActions) {
|
|
696
|
+
columns.push({
|
|
697
|
+
colKey: 'actions',
|
|
698
|
+
title: '操作',
|
|
699
|
+
width: 80,
|
|
700
|
+
align: 'center'
|
|
701
|
+
});
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
return columns;
|
|
705
|
+
});
|
|
706
|
+
|
|
543
707
|
/**
|
|
544
708
|
* 值变更事件
|
|
545
709
|
* @param {*} val 新值
|
|
@@ -555,10 +719,163 @@ const handleChange = (val) => {
|
|
|
555
719
|
const handleValidate = (validateResult) => {
|
|
556
720
|
emit('validate', validateResult);
|
|
557
721
|
};
|
|
722
|
+
|
|
723
|
+
/**
|
|
724
|
+
* 添加表格行
|
|
725
|
+
*/
|
|
726
|
+
const addTableRow = () => {
|
|
727
|
+
|
|
728
|
+
const currentData = computedModelValue.value || [];
|
|
729
|
+
const newRow = {};
|
|
730
|
+
|
|
731
|
+
// 根据表格列配置初始化新行数据
|
|
732
|
+
props.tableColumns.forEach(col => {
|
|
733
|
+
// 根据列类型设置默认值
|
|
734
|
+
switch (col.type) {
|
|
735
|
+
case 'number':
|
|
736
|
+
newRow[col.key] = col.defaultValue || 0;
|
|
737
|
+
break;
|
|
738
|
+
case 'switch':
|
|
739
|
+
newRow[col.key] = col.defaultValue || false;
|
|
740
|
+
break;
|
|
741
|
+
case 'checkbox':
|
|
742
|
+
newRow[col.key] = col.defaultValue || [];
|
|
743
|
+
break;
|
|
744
|
+
case 'select':
|
|
745
|
+
if (col.multiple) {
|
|
746
|
+
newRow[col.key] = col.defaultValue || [];
|
|
747
|
+
} else {
|
|
748
|
+
newRow[col.key] = col.defaultValue || '';
|
|
749
|
+
}
|
|
750
|
+
break;
|
|
751
|
+
default:
|
|
752
|
+
newRow[col.key] = col.defaultValue || '';
|
|
753
|
+
break;
|
|
754
|
+
}
|
|
755
|
+
});
|
|
756
|
+
|
|
757
|
+
|
|
758
|
+
const newData = [...currentData, newRow];
|
|
759
|
+
computedModelValue.value = JSON.parse(JSON.stringify(newData));
|
|
760
|
+
|
|
761
|
+
handleChange(newData.map(({ __id, ...item }) => item));
|
|
762
|
+
};
|
|
763
|
+
|
|
764
|
+
/**
|
|
765
|
+
* 删除表格行
|
|
766
|
+
* @param {number} rowIndex 行索引
|
|
767
|
+
*/
|
|
768
|
+
const removeTableRow = (rowIndex) => {
|
|
769
|
+
if (props.type !== 'table') return;
|
|
770
|
+
|
|
771
|
+
const currentData = [...(computedModelValue.value || [])];
|
|
772
|
+
currentData.splice(rowIndex, 1);
|
|
773
|
+
|
|
774
|
+
computedModelValue.value = currentData;
|
|
775
|
+
handleChange(currentData.map(({ __id, ...item }) => item));
|
|
776
|
+
};
|
|
777
|
+
|
|
778
|
+
/**
|
|
779
|
+
* 更新表格单元格数据
|
|
780
|
+
* @param {number} rowIndex 行索引
|
|
781
|
+
* @param {string} colKey 列键名
|
|
782
|
+
* @param {*} value 新值
|
|
783
|
+
*/
|
|
784
|
+
const updateTableCell = (rowIndex, colKey, value) => {
|
|
785
|
+
if (props.type !== 'table') return;
|
|
786
|
+
|
|
787
|
+
const currentData = [...(computedModelValue.value || [])];
|
|
788
|
+
if (currentData[rowIndex]) {
|
|
789
|
+
currentData[rowIndex] = {
|
|
790
|
+
...currentData[rowIndex],
|
|
791
|
+
[colKey]: value
|
|
792
|
+
};
|
|
793
|
+
|
|
794
|
+
computedModelValue.value = currentData;
|
|
795
|
+
handleChange(currentData.map(({ __id, ...item }) => item));
|
|
796
|
+
}
|
|
797
|
+
};
|
|
558
798
|
</script>
|
|
559
799
|
|
|
560
800
|
<style scoped>
|
|
561
801
|
.custom-control {
|
|
562
802
|
width: 100%;
|
|
563
803
|
}
|
|
804
|
+
|
|
805
|
+
.ebiz-form-table {
|
|
806
|
+
width: 100%;
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
.ebiz-form-table :deep(.t-table) {
|
|
810
|
+
border: 1px solid var(--td-border-level-1-color);
|
|
811
|
+
border-radius: var(--td-radius-default);
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
.ebiz-form-table :deep(.t-table td) {
|
|
815
|
+
padding: 8px 12px;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
.ebiz-form-table :deep(.t-table th) {
|
|
819
|
+
background-color: var(--td-bg-color-secondarycontainer);
|
|
820
|
+
font-weight: 500;
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
.ebiz-form-table :deep(.t-input) {
|
|
824
|
+
border: none;
|
|
825
|
+
box-shadow: none;
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
.ebiz-form-table :deep(.t-input:focus-within) {
|
|
829
|
+
border: 1px solid var(--td-brand-color);
|
|
830
|
+
box-shadow: 0 0 0 2px var(--td-brand-color-focus);
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
.ebiz-form-table :deep(.t-input-number) {
|
|
834
|
+
border: none;
|
|
835
|
+
box-shadow: none;
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
.ebiz-form-table :deep(.t-input-number:focus-within) {
|
|
839
|
+
border: 1px solid var(--td-brand-color);
|
|
840
|
+
box-shadow: 0 0 0 2px var(--td-brand-color-focus);
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
.ebiz-form-table :deep(.t-select) {
|
|
844
|
+
border: none;
|
|
845
|
+
box-shadow: none;
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
.ebiz-form-table :deep(.t-select:focus-within) {
|
|
849
|
+
border: 1px solid var(--td-brand-color);
|
|
850
|
+
box-shadow: 0 0 0 2px var(--td-brand-color-focus);
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
.ebiz-form-table :deep(.t-date-picker) {
|
|
854
|
+
border: none;
|
|
855
|
+
box-shadow: none;
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
.ebiz-form-table :deep(.t-date-picker:focus-within) {
|
|
859
|
+
border: 1px solid var(--td-brand-color);
|
|
860
|
+
box-shadow: 0 0 0 2px var(--td-brand-color-focus);
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
.ebiz-form-table :deep(.t-textarea) {
|
|
864
|
+
border: none;
|
|
865
|
+
box-shadow: none;
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
.ebiz-form-table :deep(.t-textarea:focus-within) {
|
|
869
|
+
border: 1px solid var(--td-brand-color);
|
|
870
|
+
box-shadow: 0 0 0 2px var(--td-brand-color-focus);
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
.ebiz-form-table :deep(.t-switch) {
|
|
874
|
+
justify-content: center;
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
.ebiz-form-table :deep(.t-radio-group),
|
|
878
|
+
.ebiz-form-table :deep(.t-checkbox-group) {
|
|
879
|
+
justify-content: center;
|
|
880
|
+
}
|
|
564
881
|
</style>
|
|
@@ -17,7 +17,11 @@
|
|
|
17
17
|
<ebiz-s-form-item label="爱好" name="hobbies" type="checkbox" :options="hobbyOptions"></ebiz-s-form-item>
|
|
18
18
|
<ebiz-s-form-item label="职业" name="occupation" type="select" :options="occupationOptions"></ebiz-s-form-item>
|
|
19
19
|
<ebiz-s-form-item label="出生日期" name="birthday" type="date"></ebiz-s-form-item>
|
|
20
|
-
|
|
20
|
+
{{ formData.bio }}
|
|
21
|
+
<ebiz-s-form-item v-model="formData.bio" label="简介" name="bio" type="table" :tableColumns="[
|
|
22
|
+
{ name: '名称', key: 'name' },
|
|
23
|
+
{ name: '数量', key: 'num' }
|
|
24
|
+
]" placeholder="请输入个人简介"></ebiz-s-form-item>
|
|
21
25
|
</ebiz-s-form>
|
|
22
26
|
</div>
|
|
23
27
|
</div>
|
|
@@ -127,6 +131,8 @@ export default {
|
|
|
127
131
|
const editFormRef = ref(null);
|
|
128
132
|
const methodFormRef = ref(null);
|
|
129
133
|
|
|
134
|
+
const tableColumns = reactive();
|
|
135
|
+
|
|
130
136
|
// 基础表单数据
|
|
131
137
|
const formData = reactive({
|
|
132
138
|
name: '',
|
|
@@ -135,7 +141,7 @@ export default {
|
|
|
135
141
|
hobbies: [],
|
|
136
142
|
occupation: '',
|
|
137
143
|
birthday: '',
|
|
138
|
-
bio: ''
|
|
144
|
+
bio: [{name: '123', num: 123}]
|
|
139
145
|
});
|
|
140
146
|
|
|
141
147
|
// 表单验证规则
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|