Skip to content

Commit 0d615ab

Browse files
committed
feat(@0.8.9): 优化GenerateFormItem内部绑定逻辑
1 parent e9b0b1b commit 0d615ab

File tree

5 files changed

+54
-64
lines changed

5 files changed

+54
-64
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "element-pro-crud",
3-
"version": "0.8.8-17",
3+
"version": "0.8.9",
44
"author": "BoBo<[email protected]>",
55
"main": "lib/ProCrud.umd.min.js",
66
"files": [

src/component/form-designer/src/GenerateForm.vue

-1
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,6 @@ export default class GenerateForm extends Vue {
303303
field.rules.push({
304304
message: `${field.name}必须填写`,
305305
required: true,
306-
trigger: 'blur',
307306
});
308307
}
309308
}

src/component/form-designer/src/GenerateFormItem.vue

+26-56
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
-->
1010
<template>
1111
<el-form-item :rules="widget.rules || []"
12-
:prop="widget.type == 'button' ? undefined : widget.model"
12+
:prop="formElement.includes(widget.type) ? widget.model : undefined"
1313
:label-width="widget.options.hiddenLabel ? '0' : labelWidth"
1414
:class="widget.options.className">
1515
<template #label>
@@ -31,7 +31,7 @@
3131
<el-input
3232
v-if="['number', 'integer', 'float'].includes(widget.options.dataType)"
3333
:type="widget.options.dataType"
34-
v-model.number="dataModel"
34+
v-model.number="models[widget.model]"
3535
:placeholder="widget.options.placeholder"
3636
:readonly="readOnly || widget.options.readonly"
3737
:disabled="readOnly || widget.options.disabled"
@@ -40,7 +40,7 @@
4040
<el-input
4141
v-else
4242
type="text"
43-
v-model="dataModel"
43+
v-model="models[widget.model]"
4444
:show-word-limit="widget.options.showWordLimit"
4545
:maxlength="widget.options.maxLength"
4646
:placeholder="widget.options.placeholder"
@@ -82,11 +82,11 @@
8282
</h3>
8383
</template>
8484
<template v-if="widget.type == 'label'">
85-
<p>{{ dataModel }}</p>
85+
<p>{{ models[widget.model] }}</p>
8686
</template>
8787
<template v-if="widget.type == 'select'">
8888
<el-select
89-
v-model="dataModel"
89+
v-model="models[widget.model]"
9090
default-first-option
9191
:disabled="readOnly || widget.options.disabled"
9292
:readonly="readOnly || widget.options.readonly"
@@ -107,7 +107,7 @@
107107
<el-input
108108
type="textarea"
109109
:autosize="{ minRows: 5 }"
110-
v-model="dataModel"
110+
v-model="models[widget.model]"
111111
:show-word-limit="widget.options.showWordLimit"
112112
:maxlength="widget.options.maxLength"
113113
:disabled="readOnly || widget.options.disabled"
@@ -119,7 +119,7 @@
119119

120120
<template v-if="widget.type == 'number'">
121121
<el-input-number
122-
v-model="dataModel"
122+
v-model="models[widget.model]"
123123
:style="{ width: widget.options.width }"
124124
:step="widget.options.step"
125125
:disabled="readOnly || widget.options.disabled"
@@ -129,15 +129,15 @@
129129
</template>
130130

131131
<template v-if="widget.type == 'radio'">
132-
<el-radio-group v-model="dataModel" :style="{ width: widget.options.width }" :disabled="readOnly || widget.options.disabled">
132+
<el-radio-group v-model="models[widget.model]" :style="{ width: widget.options.width }" :disabled="readOnly || widget.options.disabled">
133133
<el-radio :style="{ display: widget.options.inline ? 'inline-block' : 'block' }" :label="item.value" v-for="(item, index) in optionsList" :key="index">
134134
<template v-if="widget.options.showLabel">{{ item.label }}</template>
135135
</el-radio>
136136
</el-radio-group>
137137
</template>
138138

139139
<template v-if="widget.type == 'checkbox'">
140-
<el-checkbox-group v-model="dataModel" :style="{ width: widget.options.width }">
140+
<el-checkbox-group v-model="models[widget.model]" :style="{ width: widget.options.width }">
141141
<template v-if="!widget.options.buttonStyle">
142142
<el-checkbox
143143
:style="{ display: widget.options.inline ? 'inline-block' : 'block' }"
@@ -158,7 +158,7 @@
158158

159159
<template v-if="widget.type == 'time'">
160160
<el-time-picker
161-
v-model="dataModel"
161+
v-model="models[widget.model]"
162162
:is-range="widget.options.isRange"
163163
:placeholder="widget.options.placeholder"
164164
:start-placeholder="widget.options.startPlaceholder"
@@ -176,7 +176,7 @@
176176

177177
<template v-if="widget.type == 'date'">
178178
<el-date-picker
179-
v-model="dataModel"
179+
v-model="models[widget.model]"
180180
:type="widget.options.type"
181181
:placeholder="widget.options.placeholder"
182182
:start-placeholder="widget.options.startPlaceholder"
@@ -195,20 +195,20 @@
195195
</template>
196196

197197
<template v-if="widget.type == 'rate'">
198-
<el-rate v-model="dataModel" :max="widget.options.max" :disabled="readOnly || widget.options.disabled" :allow-half="widget.options.allowHalf"></el-rate>
198+
<el-rate v-model="models[widget.model]" :max="widget.options.max" :disabled="readOnly || widget.options.disabled" :allow-half="widget.options.allowHalf"></el-rate>
199199
</template>
200200

201201
<template v-if="widget.type == 'color'">
202-
<el-color-picker v-model="dataModel" :disabled="readOnly || widget.options.disabled" :show-alpha="widget.options.showAlpha"></el-color-picker>
202+
<el-color-picker v-model="models[widget.model]" :disabled="readOnly || widget.options.disabled" :show-alpha="widget.options.showAlpha"></el-color-picker>
203203
</template>
204204

205205
<template v-if="widget.type == 'switch'">
206-
<el-switch v-model="dataModel" :disabled="readOnly || widget.options.disabled"> </el-switch>
206+
<el-switch v-model="models[widget.model]" :disabled="readOnly || widget.options.disabled"> </el-switch>
207207
</template>
208208

209209
<template v-if="widget.type == 'slider'">
210210
<el-slider
211-
v-model="dataModel"
211+
v-model="models[widget.model]"
212212
:min="widget.options.min"
213213
:max="widget.options.max"
214214
:disabled="readOnly || widget.options.disabled"
@@ -221,17 +221,17 @@
221221
<template v-if="widget.type == 'cascader'">
222222
<el-cascader
223223
ref="cascader"
224+
v-model="models[widget.model]"
224225
@visible-change="elCascaderOnlick"
225226
@expand-change="elCascaderOnlick"
226-
v-model="dataModel"
227227
:disabled="readOnly || widget.options.disabled"
228228
:clearable="widget.options.clearable"
229229
:placeholder="widget.options.placeholder"
230230
:style="{ width: widget.options.width }"
231231
:separator="widget.options.separator == null ? '/' : widget.options.separator"
232232
:options="optionsList"
233233
filterable
234-
:props="{ checkStrictly: widget.options.checkStrictly, multiple: widget.options.multiple }"
234+
:props="{ checkStrictly: widget.options.checkStrictly, multiple: widget.options.multiple,expandTrigger: 'hover' }"
235235
>
236236
</el-cascader>
237237
</template>
@@ -258,7 +258,7 @@
258258
<!-- 目前暂时提供了几个常用props,有更多需要自行拓展 -->
259259
<!-- 官网:https://vue-treeselect.js.org -->
260260
<TreeSelect
261-
v-model="dataModel"
261+
v-model="models[widget.model]"
262262
v-if="visible"
263263
:placeholder="widget.options.placeholder"
264264
:maxHeight="+widget.options.maxHeight"
@@ -286,7 +286,7 @@
286286
</TreeSelect>
287287
</template>
288288
<template v-if="widget.type == 'richtext'">
289-
<Tinymce :height="400" v-model="dataModel" :readonly="readOnly || widget.options.readonly"></Tinymce>
289+
<Tinymce :height="400" v-model="models[widget.model]" :readonly="readOnly || widget.options.readonly"></Tinymce>
290290
</template>
291291
<template v-if="widget.type == 'upload'">
292292
<!-- 附件上传(注意初始值prefill必须传入id) -->
@@ -299,7 +299,7 @@
299299
></FileUpload>
300300
</template>
301301
<template v-if="widget.type === 'avatar'">
302-
<AvatarUpload :readOnly="readOnly" :widget="widget" v-model="dataModel"></AvatarUpload>
302+
<AvatarUpload :readOnly="readOnly" :widget="widget" v-model="models[widget.model]"></AvatarUpload>
303303
</template>
304304
<template v-if="widget.type === 'form'">
305305
<GenerateSubForm :widget="widget"></GenerateSubForm>
@@ -356,6 +356,7 @@ import pieChart from './components/Charts/pieChart.vue';
356356
import Echarts from './components/Charts/Echarts.vue';
357357
import GenerateTabs from './components/Tabs/GenerateTabs.vue';
358358
import AvatarUpload from './components/AvatarUpload/AvatarUpload.vue';
359+
import { formElement } from './componentsConfig';
359360

360361
@Component({
361362
components: {
@@ -412,27 +413,16 @@ export default class GenerateFormItem extends Vue {
412413
})
413414
readOnly!: boolean
414415

415-
416-
// 当前组件对象
417-
dataModel: string | number | null | object = this.models[this.widget.model] || null
418-
419416
copyOption: any = [] // 备份一份初始选项
420417

421418
visible = false
422419

423420
normalizer: any
424421

422+
formElement = formElement
423+
425424
initData() {
426425
const { type, model } = this.widget;
427-
// if (this.model) {
428-
// // 多选组件需要初始化值为数组
429-
// if (this.widget.options.multiple || 'cascader,checkbox'.includes(type)) {
430-
// this.dataModel = typeof this.model === 'string' ? this.model.split(',') : this.model;
431-
// } else {
432-
// this.dataModel = this.model;
433-
// }
434-
// return;
435-
// }
436426
let normalizer;
437427
// tree-select组件初始化
438428
if (type === 'treeselect') {
@@ -463,7 +453,6 @@ export default class GenerateFormItem extends Vue {
463453
}
464454
}
465455
this.normalizer = normalizer;
466-
this.dataModel = this.models[model];
467456
}
468457

469458
created() {
@@ -680,7 +669,9 @@ export default class GenerateFormItem extends Vue {
680669
document.querySelectorAll('.el-cascader-node__label').forEach((el) => {
681670
// eslint-disable-next-line func-names
682671
(el as any).onclick = function () {
683-
this.previousElementSibling.click();
672+
if (this.previousElementSibling) {
673+
this.previousElementSibling.click();
674+
}
684675
that.$refs.cascader.dropDownVisible = false;
685676
};
686677
});
@@ -709,27 +700,6 @@ export default class GenerateFormItem extends Vue {
709700
this.$emit('selection-change', selection);
710701
}
711702

712-
@Watch('dataModel')
713-
dataModelHandler(val) {
714-
this.$set(this.models, this.widget.model, val);
715-
this.$emit('change', val);
716-
}
717-
718-
@Watch('models', {
719-
deep: true,
720-
})
721-
modelsHandler(val) {
722-
const updateVal = val[this.widget.model];
723-
if (updateVal !== this.dataModel) {
724-
if (this.widget.options.multiple || 'cascader,checkbox'.includes(this.widget.type)) {
725-
const value = val[this.widget.model];
726-
this.dataModel = typeof value === 'string' ? value.split(',') : value;
727-
} else {
728-
this.dataModel = val[this.widget.model];
729-
}
730-
}
731-
}
732-
733703
// 如果表格预设参数发生变化 自动刷新表格
734704
@Watch('getTableParams', {
735705
deep: true,

src/component/form-designer/src/WidgetConfig.vue

+4-4
Original file line numberDiff line numberDiff line change
@@ -203,9 +203,6 @@
203203
</Draggable>
204204
</el-checkbox-group>
205205
</template>
206-
<template v-if="elementConfig.type == 'cascader'">
207-
<el-input type="textarea" v-model="elementConfig.options.options"></el-input>
208-
</template>
209206
<div style="margin-left: 22px;" v-if="elementConfig.type !== 'cascader'">
210207
<el-button size="mini" type="text" @click="handleAddOption">添加选项</el-button>
211208
<el-button size="mini" type="text" @click="handleClearOption">清除默认选中项</el-button>
@@ -710,7 +707,10 @@ export default {
710707
},
711708
validateRequired(val) {
712709
if (val) {
713-
this.validator.required = { required: true, message: `${this.elementConfig.name}必须填写` };
710+
this.validator.required = {
711+
required: true,
712+
message: `${this.elementConfig.name}必须填写`,
713+
};
714714
} else {
715715
this.validator.required = null;
716716
}

src/component/form-designer/src/componentsConfig.ts

+23-2
Original file line numberDiff line numberDiff line change
@@ -307,13 +307,31 @@ export const basicComponents = [
307307
width: '100%',
308308
separator: '/',
309309
placeholder: '',
310+
required: false,
310311
multiple: false,
311312
disabled: false,
312313
clearable: false,
313314
checkStrictly: false,
314315
remote: 'static',
315316
remoteOptions: [],
316-
options: [],
317+
options: [
318+
{
319+
value: 'A',
320+
label: 'A',
321+
children: [
322+
{
323+
value: 'AA',
324+
label: 'AA',
325+
children: [
326+
{
327+
value: 'AAA',
328+
label: 'AAA',
329+
},
330+
],
331+
},
332+
],
333+
},
334+
],
317335
props: {
318336
value: 'value',
319337
label: 'label',
@@ -392,6 +410,7 @@ export const basicComponents = [
392410
defaultValue: '',
393411
readonly: false,
394412
hiddenLabel: false,
413+
required: false,
395414
},
396415
},
397416
];
@@ -488,7 +507,6 @@ export const advanceComponents = [
488507
},
489508
},
490509
];
491-
492510
export const layoutComponents = [
493511
{
494512
type: 'grid',
@@ -659,3 +677,6 @@ export const elementComponentConfig = {
659677
],
660678
},
661679
};
680+
681+
// 表单类组件枚举
682+
export const formElement = ['input', 'textarea', 'number', 'radio', 'checkbox', 'date', 'date', 'rate', 'color', 'select', 'switch', 'slider', 'cascader', 'treeselect', 'richtext'];

0 commit comments

Comments
 (0)