Variant Form 3 增加treeSelect树形选择组件
- 1、新建VUE组件,涉及目录
- 2、在src\components\form-designer\widget-panel\widgetConfig.js 中定义tree-select组件在设置器里的属性参数。
- 3、src\utils\sfc-generator.js 增加渲染的模板,
- 4、src\utils\utils.js 下拉树使用数据源方式,数据处理与select不同,需要修改function translateOptionItems(rawData, widgetType, labelKey, valueKey)
- 5、在src\components\form-designer\form-widget\field-widget\fieldMixin.js 文件的 initOptionItems和loadOptionItemsFromDataSet 增加tree-select 数据源支持。
- 6、在src\lang\zh-CN.js等designer下的widgetLabel内语言文件增加标识
本文使用非扩展方式增加 Variant Form 3 组件,直接整合修改源码用于记录修改过程,涉及elementPlus+VUE3。
1、新建VUE组件,涉及目录
src\components\form-designer\form-widget\field-widget
treeSelect 是 tree+select 两个组件整合,做,直接可以复制 原select-widget.vue为tree-select-widget.vue。修改文件内el-select 为el-tree-select,不同的是select下拉列表与tree-select下拉树 选项生成方式不同,select 是使用el-option ,tree-select 直接使用data。
tree-select-widget.vue
<template>
<form-item-wrapper :designer="designer" :field="field" :rules="rules" :design-state="designState"
:parent-widget="parentWidget" :parent-list="parentList" :index-of-parent-list="indexOfParentList"
:sub-form-row-index="subFormRowIndex" :sub-form-col-index="subFormColIndex" :sub-form-row-id="subFormRowId">
<el-select ref="fieldEditor" v-model="fieldModel" v-show="!isReadMode" class="full-width-input"
:disabled="field.options.disabled"
:size="widgetSize"
:clearable="field.options.clearable"
:filterable="field.options.filterable"
:allow-create="field.options.allowCreate"
:default-first-option="allowDefaultFirstOption"
:automatic-dropdown="field.options.automaticDropdown"
:multiple="field.options.multiple" :limit="field.options.multipleLimit"
:placeholder="field.options.placeholder || i18nt('render.hint.selectPlaceholder')"
:remote="field.options.remote" :remote-method="remoteQuery"
@focus="handleFocusCustomEvent" @blur="handleBlurCustomEvent"
@change="handleChangeEvent">
<el-option v-for="item in field.options.optionItems" :key="item.value" :label="item.label"
:value="item.value" :disabled="item.disabled">
</el-option>
</el-select>
<template v-if="isReadMode">
<span class="readonly-mode-field">{{optionLabel}}</span>
</template>
</form-item-wrapper>
</template>
<script>
import FormItemWrapper from './form-item-wrapper'
import emitter from '@/utils/emitter'
import i18n, {translate} from "@/utils/i18n";
import fieldMixin from "@/components/form-designer/form-widget/field-widget/fieldMixin";
export default {
name: "select-widget",
componentName: 'FieldWidget', //必须固定为FieldWidget,用于接收父级组件的broadcast事件
mixins: [emitter, fieldMixin, i18n],
props: {
field: Object,
parentWidget: Object,
parentList: Array,
indexOfParentList: Number,
designer: Object,
designState: {
type: Boolean,
default: false
},
subFormRowIndex: { /* 子表单组件行索引,从0开始计数 */
type: Number,
default: -1
},
subFormColIndex: { /* 子表单组件列索引,从0开始计数 */
type: Number,
default: -1
},
subFormRowId: { /* 子表单组件行Id,唯一id且不可变 */
type: String,
default: ''
},
},
components: {
FormItemWrapper,
},
data() {
return {
oldFieldValue: null, //field组件change之前的值
fieldModel: null,
rules: [],
}
},
computed: {
allowDefaultFirstOption() {
return (!!this.field.options.filterable && !!this.field.options.allowCreate)
},
},
beforeCreate() {
/* 这里不能访问方法和属性!! */
},
created() {
/* 注意:子组件mounted在父组件created之后、父组件mounted之前触发,故子组件mounted需要用到的prop
需要在父组件created中初始化!! */
this.registerToRefList()
this.initOptionItems()
this.initFieldModel()
this.initEventHandler()
this.buildFieldRules()
this.handleOnCreated()
},
mounted() {
this.handleOnMounted()
},
beforeUnmount() {
this.unregisterFromRefList()
},
methods: {
}
}
</script>
<style lang="scss" scoped>
@import "../../../../styles/global.scss"; /* form-item-wrapper已引入,还需要重复引入吗? */
.full-width-input {
width: 100% !important;
}
</style>
2、在src\components\form-designer\widget-panel\widgetConfig.js 中定义tree-select组件在设置器里的属性参数。
{
type: 'tree-select',
icon: 'select-field',
formItemFlag: true,
options: {
name: '',
label: '',
labelAlign: '',
defaultValue: '',
placeholder: '',
columnWidth: '200px',
size: '',
labelWidth: null,
labelHidden: false,
checkStrictly: true,
disabled: false,
hidden: false,
clearable: true,
filterable: false,
allowCreate: false,
remote: false,
automaticDropdown: false, //自动下拉
multiple: false,
multipleLimit: 0,
dsEnabled: false, // 是否使用数据源数据
dsName: '', // 数据源名称
dataSetName: '', //数据集名称
labelKey: 'label',
valueKey: 'value',
optionItems: [
{value: '1',label: 'Level one 1',children: [{value: '1-1',label: 'Level two 1-1',children: [{value: '1-1-1',label: 'Level three 1-1-1',},],},],},
{value: '2',label: 'Level one 2',children: [{ value: '2-1', label: 'Level two 2-1', children: [{value: '2-1-1',label: 'Level three 2-1-1',}, ],},{ value: '2-2', label: 'Level two 2-2', children: [{value: '2-2-1',label: 'Level three 2-2-1',}, ],},], },
{value: '3',label: 'Level one 3',children: [{ value: '3-1', label: 'Level two 3-1', children: [{value: '3-1-1',label: 'Level three 3-1-1',}, ],},{ value: '3-2', label: 'Level two 3-2', children: [{value: '3-2-1',label: 'Level three 3-2-1',}, ],},], },
],
required: false,
requiredHint: '',
validation: '',
validationHint: '',
//-------------------
customClass: '', //自定义css类名
labelIconClass: null,
labelIconPosition: 'rear',
labelTooltip: null,
//-------------------
onCreated: '',
onMounted: '',
onRemoteQuery: '',
onChange: '',
onFocus: '',
onBlur: '',
onValidate: '',
},
},
3、src\utils\sfc-generator.js 增加渲染的模板,
'tree-select': (widget, formConfig, parentWidget) => {
const {vModel, disabled, size, clearable, filterable, allowCreate, defaultFirstOption, automaticDropdown,
multiple, multipleLimit, remote, placeholder,checkStrictly} = getElAttrs(widget, formConfig, parentWidget)
return `<el-tree-select ${vModel} class="full-width-input" ${disabled} ${checkStrictly} ${size} ${clearable} ${filterable}
${allowCreate} ${defaultFirstOption} ${automaticDropdown} ${multiple} ${multipleLimit} ${placeholder}
${remote}></el-tree-select>`
},
4、src\utils\utils.js 下拉树使用数据源方式,数据处理与select不同,需要修改function translateOptionItems(rawData, widgetType, labelKey, valueKey)
/**
* 替代eval
* @param {*} fun
* @returns
*/
export function gEval(fun){
let function1 = Function;
try{
return new function1('return '+fun)();
}catch(err){
return eval(fun);
}
}
/**
* 转译选择项数据
* @param rawData
* @param widgetType
* @param labelKey
* @param valueKey
* @returns {[]}
*/
export function translateOptionItems(rawData, widgetType, labelKey, valueKey) {
if (widgetType === 'cascader') { // 级联选择 树选择框 不转译
return deepClone(rawData)
}
if (widgetType === 'tree-select') { // 树选择框 不转译
let rawData1 = deepClone(rawData);
if(typeof rawData1=='string'){
return gEval(rawData1)
}
return rawData1;
}
let result = []
if (!!rawData && (rawData.length > 0)) {
rawData.forEach(ri => {
result.push({
label: ri[labelKey],
value: ri[valueKey]
})
})
}
return result
}
5、在src\components\form-designer\form-widget\field-widget\fieldMixin.js 文件的 initOptionItems和loadOptionItemsFromDataSet 增加tree-select 数据源支持。
6、在src\lang\zh-CN.js等designer下的widgetLabel内语言文件增加标识
‘tree-select’: ‘下拉树’,
经过以上6步,组件基本整合完毕了。