<template> <div class="right-board"> <el-tabs v-model="currentTab" class="center-tabs"> <el-tab-pane :label="$t('组件属性')" name="field" /> <el-tab-pane :label="$t('表单属性')" name="form" /> </el-tabs> <div class="field-box"> <a class="document-link" target="_blank" :href="documentLink" :title="$t('查看组件文档')"> <i class="el-icon-link" /> </a> <el-scrollbar class="right-scrollbar"> <!-- 组件属性 --> <el-form v-show="currentTab==='field' && showField" size="small" label-width="90px"> <el-form-item v-if="activeData.__config__.changeTag" :label="$t('组件类型')"> <el-select v-model="activeData.__config__.tagIcon" :placeholder="$t('请选择组件类型')" :style="{width: '100%'}" @change="tagChange" > <el-option-group v-for="group in tagList" :key="group.label" :label="group.label"> <el-option v-for="item in group.options" :key="item.__config__.label" :label="item.__config__.label" :value="item.__config__.tagIcon" > <svg-icon class="node-icon" :icon-class="item.__config__.tagIcon" /> <span> {{ item.__config__.label }}</span> </el-option> </el-option-group> </el-select> </el-form-item> <el-form-item v-if="activeData.__vModel__!==undefined" :label="$t('字段名')"> <el-input v-model="activeData.__vModel__" placeholder="请输入字段名(v-model)" /> </el-form-item> <el-form-item v-if="activeData.__config__.componentName!==undefined" :label="$t('组件名')"> {{ activeData.__config__.componentName }} </el-form-item> <el-form-item v-if="activeData.__config__.label!==undefined" :label="$t('标题')"> <el-input v-model="activeData.__config__.label" :placeholder="$t('请输入标题')" @input="changeRenderKey" /> </el-form-item> <el-form-item v-if="activeData.placeholder!==undefined" :label="$t('占位提示')"> <el-input v-model="activeData.placeholder" :placeholder="$t('请输入占位提示')" @input="changeRenderKey" /> </el-form-item> <el-form-item v-if="activeData['start-placeholder']!==undefined" :label="$t('开始占位')"> <el-input v-model="activeData['start-placeholder']" :placeholder="$t('请输入占位提示')" /> </el-form-item> <el-form-item v-if="activeData['end-placeholder']!==undefined" :label="$t('结束占位')"> <el-input v-model="activeData['end-placeholder']" :placeholder="$t('请输入占位提示')" /> </el-form-item> <el-form-item v-if="activeData.__config__.span!==undefined" :label="$t('表单栅格')"> <el-slider v-model="activeData.__config__.span" :max="24" :min="1" :marks="{12:''}" @change="spanChange" /> </el-form-item> <el-form-item v-if="activeData.__config__.layout==='rowFormItem'&&activeData.gutter!==undefined" :label="$t('栅格间隔')"> <el-input-number v-model="activeData.gutter" :min="0" :placeholder="$t('栅格间隔')" /> </el-form-item> <el-form-item v-if="activeData.__config__.layout==='rowFormItem'&&activeData.type!==undefined" :label="$t('布局模式')"> <el-radio-group v-model="activeData.type"> <el-radio-button label="default" /> <el-radio-button label="flex" /> </el-radio-group> </el-form-item> <el-form-item v-if="activeData.justify!==undefined&&activeData.type==='flex'" :label="$t('水平排列')"> <el-select v-model="activeData.justify" :placeholder="$t('请选择水平排列')" :style="{width: '100%'}"> <el-option v-for="(item, index) in justifyOptions" :key="index" :label="item.label" :value="item.value" /> </el-select> </el-form-item> <el-form-item v-if="activeData.align!==undefined&&activeData.type==='flex'" :label="$t('垂直排列')"> <el-radio-group v-model="activeData.align"> <el-radio-button label="top" /> <el-radio-button label="middle" /> <el-radio-button label="bottom" /> </el-radio-group> </el-form-item> <el-form-item v-if="activeData.__config__.labelWidth!==undefined" :label="$t('标签宽度')"> <el-input v-model.number="activeData.__config__.labelWidth" type="number" :placeholder="$t('请输入标签宽度')" /> </el-form-item> <el-form-item v-if="activeData.style&&activeData.style.width!==undefined" :label="$t('组件宽度')"> <el-input v-model="activeData.style.width" :placeholder="$t('请输入组件宽度')" clearable /> </el-form-item> <el-form-item v-if="activeData.__vModel__!==undefined" :label="$t('默认值')"> <el-input :value="setDefaultValue(activeData.__config__.defaultValue)" :placeholder="$t('请输入默认值')" @input="onDefaultValueInput" /> </el-form-item> <el-form-item v-if="activeData.__config__.tag==='el-checkbox-group'" :label="$t('至少应选')"> <el-input-number :value="activeData.min" :min="0" :placeholder="$t('至少应选')" @input="$set(activeData, 'min', $event?$event:undefined)" /> </el-form-item> <el-form-item v-if="activeData.__config__.tag==='el-checkbox-group'" :label="$t('最多可选')"> <el-input-number :value="activeData.max" :min="0" :placeholder="$t('最多可选')" @input="$set(activeData, 'max', $event?$event:undefined)" /> </el-form-item> <el-form-item v-if="activeData.__slot__&&activeData.__slot__.prepend!==undefined" :label="$t('前缀')"> <el-input v-model="activeData.__slot__.prepend" :placeholder="$t('请输入前缀')" /> </el-form-item> <el-form-item v-if="activeData.__slot__&&activeData.__slot__.append!==undefined" :label="$t('后缀')"> <el-input v-model="activeData.__slot__.append" :placeholder="$t('请输入后缀')" /> </el-form-item> <el-form-item v-if="activeData['prefix-icon']!==undefined" :label="$t('前图标')"> <el-input v-model="activeData['prefix-icon']" :placeholder="$t('请输入前图标名称')"> <el-button slot="append" icon="el-icon-thumb" @click="openIconsDialog('prefix-icon')">{{ $t('选择') }}</el-button> </el-input> </el-form-item> <el-form-item v-if="activeData['suffix-icon'] !== undefined" :label="$t('后图标')"> <el-input v-model="activeData['suffix-icon']" :placeholder="$t('请输入后图标名称')"> <el-button slot="append" icon="el-icon-thumb" @click="openIconsDialog('suffix-icon')">{{ $t('选择') }}</el-button> </el-input> </el-form-item> <el-form-item v-if="activeData['icon']!==undefined && activeData.__config__.tag === 'el-button'" :label="$t('按钮图标')" > <el-input v-model="activeData['icon']" :placeholder="$t('请输入按钮图标名称')"> <el-button slot="append" icon="el-icon-thumb" @click="openIconsDialog('icon')">{{ $t('选择') }}</el-button> </el-input> </el-form-item> <el-form-item v-if="activeData.__config__.tag === 'el-cascader'" :label="$t('选项分隔符')"> <el-input v-model="activeData.separator" :placeholder="$t('请输入选项分隔符')" /> </el-form-item> <el-form-item v-if="activeData.autosize !== undefined" :label="$t('最小行数')"> <el-input-number v-model="activeData.autosize.minRows" :min="1" :placeholder="$t('最小行数')" /> </el-form-item> <el-form-item v-if="activeData.autosize !== undefined" :label="$t('最大行数')"> <el-input-number v-model="activeData.autosize.maxRows" :min="1" :placeholder="$t('最大行数')" /> </el-form-item> <el-form-item v-if="isShowMin" :label="$t('最小值')"> <el-input-number v-model="activeData.min" :placeholder="$t('最小值')" /> </el-form-item> <el-form-item v-if="isShowMax" :label="$t('最大值')"> <el-input-number v-model="activeData.max" :placeholder="$t('最大值')" /> </el-form-item> <el-form-item v-if="activeData.height!==undefined" :label="$t('组件高度')"> <el-input-number v-model="activeData.height" :placeholder="$t('高度')" @input="changeRenderKey" /> </el-form-item> <el-form-item v-if="isShowStep" :label="$t('步长')"> <el-input-number v-model="activeData.step" :placeholder="$t('步数')" /> </el-form-item> <el-form-item v-if="activeData.__config__.tag === 'el-input-number'" :label="$t('精度')"> <el-input-number v-model="activeData.precision" :min="0" :placeholder="$t('精度')" /> </el-form-item> <el-form-item v-if="activeData.__config__.tag === 'el-input-number'" :label="$t('按钮位置')"> <el-radio-group v-model="activeData['controls-position']"> <el-radio-button label="">{{ $t('默认') }}</el-radio-button> <el-radio-button label="right">{{ $t('右侧') }}</el-radio-button> </el-radio-group> </el-form-item> <el-form-item v-if="activeData.maxlength !== undefined" :label="$t('最多输入')"> <el-input v-model="activeData.maxlength" :placeholder="$t('请输入字符长度')"> <template slot="append">{{ $t('个字符') }}</template> </el-input> </el-form-item> <el-form-item v-if="activeData['active-text'] !== undefined" :label="$t('开启提示')"> <el-input v-model="activeData['active-text']" :placeholder="$t('请输入开启提示')" /> </el-form-item> <el-form-item v-if="activeData['inactive-text'] !== undefined" :label="$t('关闭提示')"> <el-input v-model="activeData['inactive-text']" :placeholder="$t('请输入关闭提示')" /> </el-form-item> <el-form-item v-if="activeData['active-value'] !== undefined" :label="$t('开启值')"> <el-input :value="setDefaultValue(activeData['active-value'])" :placeholder="$t('请输入开启值')" @input="onSwitchValueInput($event, 'active-value')" /> </el-form-item> <el-form-item v-if="activeData['inactive-value'] !== undefined" :label="$t('关闭值')"> <el-input :value="setDefaultValue(activeData['inactive-value'])" :placeholder="$t('请输入关闭值')" @input="onSwitchValueInput($event, 'inactive-value')" /> </el-form-item> <el-form-item v-if="activeData.type !== undefined && 'el-date-picker' === activeData.__config__.tag" :label="$t('时间类型')" > <el-select v-model="activeData.type" :placeholder="$t('请选择时间类型')" :style="{ width: '100%' }" @change="dateTypeChange" > <el-option v-for="(item, index) in dateOptions" :key="index" :label="item.label" :value="item.value" /> </el-select> </el-form-item> <el-form-item v-if="activeData.name !== undefined" :label="$t('文件字段名')"> <el-input v-model="activeData.name" :placeholder="$t('请输入上传文件字段名')" /> </el-form-item> <el-form-item v-if="activeData.accept !== undefined" :label="$t('文件类型')"> <el-select v-model="activeData.accept" :placeholder="$t('请选择文件类型')" :style="{ width: '100%' }" clearable > <el-option :label="$t('图片')" value="image/*" /> <el-option :label="$t('视频')" value="video/*" /> <el-option :label="$t('音频')" value="audio/*" /> <el-option label="excel" value=".xls,.xlsx" /> <el-option label="word" value=".doc,.docx" /> <el-option label="pdf" value=".pdf" /> <el-option label="txt" value=".txt" /> </el-select> </el-form-item> <el-form-item v-if="activeData.__config__.fileSize !== undefined" :label="$t('文件大小')"> <el-input v-model.number="activeData.__config__.fileSize" :placeholder="$t('请输入文件大小')"> <el-select slot="append" v-model="activeData.__config__.sizeUnit" :style="{ width: '66px' }"> <el-option label="KB" value="KB" /> <el-option label="MB" value="MB" /> <el-option label="GB" value="GB" /> </el-select> </el-input> </el-form-item> <el-form-item v-if="activeData.action !== undefined" :label="$t('上传地址')"> <el-input v-model="activeData.action" :placeholder="$t('请输入上传地址')" clearable /> </el-form-item> <el-form-item v-if="activeData['list-type'] !== undefined" :label="$t('列表类型')"> <el-radio-group v-model="activeData['list-type']" size="small"> <el-radio-button label="text"> text </el-radio-button> <el-radio-button label="picture"> picture </el-radio-button> <el-radio-button label="picture-card"> picture-card </el-radio-button> </el-radio-group> </el-form-item> <el-form-item v-if="activeData.type !== undefined && activeData.__config__.tag === 'el-button'" :label="$t('按钮类型')" > <el-select v-model="activeData.type" :style="{ width: '100%' }"> <el-option label="primary" value="primary" /> <el-option label="success" value="success" /> <el-option label="warning" value="warning" /> <el-option label="danger" value="danger" /> <el-option label="info" value="info" /> <el-option label="text" value="text" /> </el-select> </el-form-item> <el-form-item v-if="activeData.__config__.buttonText !== undefined" v-show="'picture-card' !== activeData['list-type']" :label="$t('按钮文字')" > <el-input v-model="activeData.__config__.buttonText" :placeholder="$t('请输入按钮文字')" /> </el-form-item> <el-form-item v-if="activeData.__config__.tag === 'el-button'" :label="$t('按钮文字')" > <el-input v-model="activeData.__slot__.default" :placeholder="$t('请输入按钮文字')" /> </el-form-item> <el-form-item v-if="activeData['range-separator'] !== undefined" :label="$t('分隔符')"> <el-input v-model="activeData['range-separator']" :placeholder="$t('请输入分隔符')" /> </el-form-item> <el-form-item v-if="activeData['picker-options'] !== undefined" :label="$t('时间段')"> <el-input v-model="activeData['picker-options'].selectableRange" :placeholder="$t('请输入时间段')" /> </el-form-item> <el-form-item v-if="activeData.format !== undefined" :label="$t('时间格式')"> <el-input :value="activeData.format" :placeholder="$t('请输入时间格式')" @input="setTimeValue($event)" /> </el-form-item> <template v-if="['el-checkbox-group', 'el-radio-group', 'el-select'].indexOf(activeData.__config__.tag) > -1"> <el-divider>{{ $t('选项') }}</el-divider> <draggable :list="activeData.__slot__.options" :animation="340" group="selectItem" handle=".option-drag" > <div v-for="(item, index) in activeData.__slot__.options" :key="index" class="select-item"> <div class="select-line-icon option-drag"> <i class="el-icon-s-operation" /> </div> <el-input v-model="item.label" :placeholder="$t('选项名')" size="small" /> <el-input :placeholder="$t('选项值')" size="small" :value="item.value" @input="setOptionValue(item, $event)" /> <div class="close-btn select-line-icon" @click="activeData.__slot__.options.splice(index, 1)"> <i class="el-icon-remove-outline" /> </div> </div> </draggable> <div style="margin-left: 20px;"> <el-button style="padding-bottom: 0" icon="el-icon-circle-plus-outline" type="text" @click="addSelectItem" >{{ $t('添加选项') }}</el-button> </div> <el-divider /> </template> <template v-if="['el-cascader', 'el-table'].includes(activeData.__config__.tag)"> <el-divider>{{ $t('选项') }}</el-divider> <el-form-item v-if="activeData.__config__.dataType" :label="$t('数据类型')"> <el-radio-group v-model="activeData.__config__.dataType" size="small"> <el-radio-button label="dynamic">{{ $t('动态数据') }}</el-radio-button> <el-radio-button label="static">{{ $t('静态数据') }}</el-radio-button> </el-radio-group> </el-form-item> <template v-if="activeData.__config__.dataType === 'dynamic'"> <el-form-item :label="$t('接口地址')"> <el-input v-model="activeData.__config__.url" :title="activeData.__config__.url" :placeholder="$t('请输入接口地址')" clearable @blur="$emit('fetch-data', activeData)" > <el-select slot="prepend" v-model="activeData.__config__.method" :style="{width: '85px'}" @change="$emit('fetch-data', activeData)" > <el-option label="get" value="get" /> <el-option label="post" value="post" /> <el-option label="put" value="put" /> <el-option label="delete" value="delete" /> </el-select> </el-input> </el-form-item> <el-form-item :label="$t('数据位置')"> <el-input v-model="activeData.__config__.dataPath" :placeholder="$t('请输入数据位置')" @blur="$emit('fetch-data', activeData)" /> </el-form-item> <template v-if="activeData.props && activeData.props.props"> <el-form-item :label="$t('标签键名')"> <el-input v-model="activeData.props.props.label" :placeholder="$t('请输入标签键名')" /> </el-form-item> <el-form-item :label="$t('值键名')"> <el-input v-model="activeData.props.props.value" :placeholder="$t('请输入值键名')" /> </el-form-item> <el-form-item :label="$t('子级键名')"> <el-input v-model="activeData.props.props.children" :placeholder="$t('请输入子级键名')" /> </el-form-item> </template> </template> <!-- 级联选择静态树 --> <el-tree v-if="activeData.__config__.dataType === 'static'" draggable :data="activeData.options" node-key="id" :expand-on-click-node="false" :render-content="renderContent" /> <div v-if="activeData.__config__.dataType === 'static'" style="margin-left: 20px"> <el-button style="padding-bottom: 0" icon="el-icon-circle-plus-outline" type="text" @click="addTreeItem" >{{ $t('添加父级') }}</el-button> </div> <el-divider /> </template> <el-form-item v-if="activeData.__config__.optionType !== undefined" :label="$t('选项样式')"> <el-radio-group v-model="activeData.__config__.optionType"> <el-radio-button label="default">{{ $t('默认') }}</el-radio-button> <el-radio-button label="button">{{ $t('按钮') }}</el-radio-button> </el-radio-group> </el-form-item> <el-form-item v-if="activeData['active-color'] !== undefined" :label="$t('开启颜色')"> <el-color-picker v-model="activeData['active-color']" /> </el-form-item> <el-form-item v-if="activeData['inactive-color'] !== undefined" :label="$t('关闭颜色')"> <el-color-picker v-model="activeData['inactive-color']" /> </el-form-item> <el-form-item v-if="activeData.__config__.showLabel !== undefined && activeData.__config__.labelWidth !== undefined" :label="$t('显示标签')" > <el-switch v-model="activeData.__config__.showLabel" /> </el-form-item> <el-form-item v-if="activeData.branding !== undefined" :label="$t('品牌烙印')"> <el-switch v-model="activeData.branding" @input="changeRenderKey" /> </el-form-item> <el-form-item v-if="activeData['allow-half'] !== undefined" :label="$t('允许半选')"> <el-switch v-model="activeData['allow-half']" /> </el-form-item> <el-form-item v-if="activeData['show-text'] !== undefined" :label="$t('辅助文字')"> <el-switch v-model="activeData['show-text']" @change="rateTextChange" /> </el-form-item> <el-form-item v-if="activeData['show-score'] !== undefined" :label="$t('显示分数')"> <el-switch v-model="activeData['show-score']" @change="rateScoreChange" /> </el-form-item> <el-form-item v-if="activeData['show-stops'] !== undefined" :label="$t('显示间断点')"> <el-switch v-model="activeData['show-stops']" /> </el-form-item> <el-form-item v-if="activeData.range !== undefined" :label="$t('范围选择')"> <el-switch v-model="activeData.range" @change="rangeChange" /> </el-form-item> <el-form-item v-if="activeData.__config__.border !== undefined && activeData.__config__.optionType === 'default'" :label="$t('是否带边框')" > <el-switch v-model="activeData.__config__.border" /> </el-form-item> <el-form-item v-if="activeData.__config__.tag === 'el-color-picker'" :label="$t('颜色格式')"> <el-select v-model="activeData['color-format']" :placeholder="$t('请选择颜色格式')" :style="{ width: '100%' }" clearable @change="colorFormatChange" > <el-option v-for="(item, index) in colorFormatOptions" :key="index" :label="item.label" :value="item.value" /> </el-select> </el-form-item> <el-form-item v-if="activeData.size !== undefined && (activeData.__config__.optionType === 'button' || activeData.__config__.border || activeData.__config__.tag === 'el-color-picker' || activeData.__config__.tag === 'el-button')" :label="$t('组件尺寸')" > <el-radio-group v-model="activeData.size"> <el-radio-button label="medium">{{ $t('中等') }}</el-radio-button> <el-radio-button label="small">{{ $t('较小') }}</el-radio-button> <el-radio-button label="mini">{{ $t('迷你') }}</el-radio-button> </el-radio-group> </el-form-item> <el-form-item v-if="activeData['show-word-limit'] !== undefined" :label="$t('输入统计')"> <el-switch v-model="activeData['show-word-limit']" /> </el-form-item> <el-form-item v-if="activeData.__config__.tag === 'el-input-number'" :label="$t('严格步数')"> <el-switch v-model="activeData['step-strictly']" /> </el-form-item> <el-form-item v-if="activeData.__config__.tag === 'el-cascader'" :label="$t('任选层级')"> <el-switch v-model="activeData.props.props.checkStrictly" /> </el-form-item> <el-form-item v-if="activeData.__config__.tag === 'el-cascader'" :label="$t('是否多选')"> <el-switch v-model="activeData.props.props.multiple" /> </el-form-item> <el-form-item v-if="activeData.__config__.tag === 'el-cascader'" :label="$t('展示全路径')"> <el-switch v-model="activeData['show-all-levels']" /> </el-form-item> <el-form-item v-if="activeData.__config__.tag === 'el-cascader'" :label="$t('可否筛选')"> <el-switch v-model="activeData.filterable" /> </el-form-item> <el-form-item v-if="activeData.clearable !== undefined" :label="$t('能否清空')"> <el-switch v-model="activeData.clearable" /> </el-form-item> <el-form-item v-if="activeData.__config__.showTip !== undefined" :label="$t('显示提示')"> <el-switch v-model="activeData.__config__.showTip" /> </el-form-item> <el-form-item v-if="activeData.__config__.tag === 'el-upload'" :label="$t('多选文件')"> <el-switch v-model="activeData.multiple" /> </el-form-item> <el-form-item v-if="activeData['auto-upload'] !== undefined" :label="$t('自动上传')"> <el-switch v-model="activeData['auto-upload']" /> </el-form-item> <el-form-item v-if="activeData.readonly !== undefined" :label="$t('是否只读')"> <el-switch v-model="activeData.readonly" /> </el-form-item> <el-form-item v-if="activeData.disabled !== undefined" :label="$t('是否禁用')"> <el-switch v-model="activeData.disabled" /> </el-form-item> <el-form-item v-if="activeData.__config__.tag === 'el-select'" :label="$t('能否搜索')"> <el-switch v-model="activeData.filterable" /> </el-form-item> <el-form-item v-if="activeData.__config__.tag === 'el-select'" :label="$t('是否多选')"> <el-switch v-model="activeData.multiple" @change="multipleChange" /> </el-form-item> <el-form-item v-if="activeData.__config__.required !== undefined" :label="$t('是否必填')"> <el-switch v-model="activeData.__config__.required" /> </el-form-item> <template v-if="activeData.__config__.layoutTree"> <el-divider>{{ $t('布局结构树') }}</el-divider> <el-tree :data="[activeData.__config__]" :props="layoutTreeProps" node-key="renderKey" default-expand-all draggable > <span slot-scope="{ node, data }"> <span class="node-label"> <svg-icon class="node-icon" :icon-class="data.__config__?data.__config__.tagIcon:data.tagIcon" /> {{ node.label }} </span> </span> </el-tree> </template> <template v-if="Array.isArray(activeData.__config__.regList)"> <el-divider>{{ $t('正则校验') }}</el-divider> <div v-for="(item, index) in activeData.__config__.regList" :key="index" class="reg-item" > <span class="close-btn" @click="activeData.__config__.regList.splice(index, 1)"> <i class="el-icon-close" /> </span> <el-form-item :label="$t('表达式')"> <el-input v-model="item.pattern" :placeholder="$t('请输入正则')" /> </el-form-item> <el-form-item :label="$t('错误提示')" style="margin-bottom:0"> <el-input v-model="item.message" :placeholder="$t('请输入错误提示')" /> </el-form-item> </div> <div style="margin-left: 20px"> <el-button icon="el-icon-circle-plus-outline" type="text" @click="addReg">{{ $t('添加规则') }}</el-button> </div> </template> </el-form> <!-- 表单属性 --> <el-form v-show="currentTab === 'form'" size="small" label-width="90px"> <el-form-item :label="$t('表单名')"> <el-input v-model="formConf.formRef" placeholder="请输入表单名(ref)" /> </el-form-item> <el-form-item :label="$t('表单模型')"> <el-input v-model="formConf.formModel" :placeholder="$t('请输入数据模型')" /> </el-form-item> <el-form-item :label="$t('校验模型')"> <el-input v-model="formConf.formRules" :placeholder="$t('请输入校验模型')" /> </el-form-item> <el-form-item :label="$t('表单尺寸')"> <el-radio-group v-model="formConf.size"> <el-radio-button label="medium">{{ $t('中等') }}</el-radio-button> <el-radio-button label="small">{{ $t('较小') }}</el-radio-button> <el-radio-button label="mini">{{ $t('迷你') }}</el-radio-button> </el-radio-group> </el-form-item> <el-form-item :label="$t('标签对齐')"> <el-radio-group v-model="formConf.labelPosition"> <el-radio-button label="left">{{ $t('左对齐') }}</el-radio-button> <el-radio-button label="right">{{ $t('右对齐') }}</el-radio-button> <el-radio-button label="top">{{ $t('顶部对齐') }}</el-radio-button> </el-radio-group> </el-form-item> <el-form-item :label="$t('标签宽度')"> <el-input v-model.number="formConf.labelWidth" type="number" :placeholder="$t('请输入标签宽度')" /> </el-form-item> <el-form-item :label="$t('栅格间隔')"> <el-input-number v-model="formConf.gutter" :min="0" :placeholder="$t('栅格间隔')" /> </el-form-item> <el-form-item :label="$t('禁用表单')"> <el-switch v-model="formConf.disabled" /> </el-form-item> <el-form-item :label="$t('表单按钮')"> <el-switch v-model="formConf.formBtns" /> </el-form-item> <el-form-item :label="$t('显示未选中组件边框')"> <el-switch v-model="formConf.unFocusedComponentBorder" /> </el-form-item> </el-form> </el-scrollbar> </div> <treeNode-dialog :visible.sync="dialogVisible" :title="$t('添加选项')" @commit="addNode" /> <icons-dialog :visible.sync="iconsVisible" :current="activeData[currentIconModel]" @select="setIcon" /> </div> </template> <script> import { isArray } from 'util' import TreeNodeDialog from './TreeNodeDialog' import { isNumberStr } from '@/utils/index' import IconsDialog from './IconsDialog' import { inputComponents, selectComponents, layoutComponents } from '@/components/generator/config' import { saveFormConf } from '@/utils/db' const dateTimeFormat = { date: 'yyyy-MM-dd', week: 'yyyy 第 WW 周', month: 'yyyy-MM', year: 'yyyy', datetime: 'yyyy-MM-dd HH:mm:ss', daterange: 'yyyy-MM-dd', monthrange: 'yyyy-MM', datetimerange: 'yyyy-MM-dd HH:mm:ss' } // 使changeRenderKey在目标组件改变时可用 const needRerenderList = ['tinymce'] export default { components: { TreeNodeDialog, IconsDialog }, props: ['showField', 'activeData', 'formConf'], data() { return { currentTab: 'field', currentNode: null, dialogVisible: false, iconsVisible: false, currentIconModel: null, dateTypeOptions: [ { label: '日(date)', value: 'date' }, { label: '周(week)', value: 'week' }, { label: '月(month)', value: 'month' }, { label: '年(year)', value: 'year' }, { label: '日期时间(datetime)', value: 'datetime' } ], dateRangeTypeOptions: [ { label: '日期范围(daterange)', value: 'daterange' }, { label: '月范围(monthrange)', value: 'monthrange' }, { label: '日期时间范围(datetimerange)', value: 'datetimerange' } ], colorFormatOptions: [ { label: 'hex', value: 'hex' }, { label: 'rgb', value: 'rgb' }, { label: 'rgba', value: 'rgba' }, { label: 'hsv', value: 'hsv' }, { label: 'hsl', value: 'hsl' } ], justifyOptions: [ { label: 'start', value: 'start' }, { label: 'end', value: 'end' }, { label: 'center', value: 'center' }, { label: 'space-around', value: 'space-around' }, { label: 'space-between', value: 'space-between' } ], layoutTreeProps: { label(data, node) { const config = data.__config__ return data.componentName || `${config.label}: ${data.__vModel__}` } } } }, computed: { documentLink() { return ( this.activeData.__config__.document || 'https://element.eleme.cn/#/zh-CN/component/installation' ) }, dateOptions() { if ( this.activeData.type !== undefined && this.activeData.__config__.tag === 'el-date-picker' ) { if (this.activeData['start-placeholder'] === undefined) { return this.dateTypeOptions } return this.dateRangeTypeOptions } return [] }, tagList() { return [ { label: this.$t('输入型组件'), options: inputComponents }, { label: this.$t('选择型组件'), options: selectComponents } ] }, activeTag() { return this.activeData.__config__.tag }, isShowMin() { return ['el-input-number', 'el-slider'].indexOf(this.activeTag) > -1 }, isShowMax() { return ['el-input-number', 'el-slider', 'el-rate'].indexOf(this.activeTag) > -1 }, isShowStep() { return ['el-input-number', 'el-slider'].indexOf(this.activeTag) > -1 } }, watch: { formConf: { handler(val) { saveFormConf(val) }, deep: true } }, methods: { addReg() { this.activeData.__config__.regList.push({ pattern: '', message: '' }) }, addSelectItem() { this.activeData.__slot__.options.push({ label: '', value: '' }) }, addTreeItem() { ++this.idGlobal this.dialogVisible = true this.currentNode = this.activeData.options }, renderContent(h, { node, data, store }) { return ( <div class="custom-tree-node"> <span>{node.label}</span> <span class="node-operation"> <i on-click={() => this.append(data)} class="el-icon-plus" title="添加" ></i> <i on-click={() => this.remove(node, data)} class="el-icon-delete" title="删除" ></i> </span> </div> ) }, append(data) { if (!data.children) { this.$set(data, 'children', []) } this.dialogVisible = true this.currentNode = data.children }, remove(node, data) { this.activeData.__config__.defaultValue = [] // 避免删除时报错 const { parent } = node const children = parent.data.children || parent.data const index = children.findIndex(d => d.id === data.id) children.splice(index, 1) }, addNode(data) { this.currentNode.push(data) }, setOptionValue(item, val) { item.value = isNumberStr(val) ? +val : val }, setDefaultValue(val) { if (Array.isArray(val)) { return val.join(',') } // if (['string', 'number'].indexOf(typeof val) > -1) { // return val // } if (typeof val === 'boolean') { return `${val}` } return val }, onDefaultValueInput(str) { if (isArray(this.activeData.__config__.defaultValue)) { // 数组 this.$set( this.activeData.__config__, 'defaultValue', str.split(',').map(val => (isNumberStr(val) ? +val : val)) ) } else if (['true', 'false'].indexOf(str) > -1) { // 布尔 this.$set(this.activeData.__config__, 'defaultValue', JSON.parse(str)) } else { // 字符串和数字 this.$set( this.activeData.__config__, 'defaultValue', isNumberStr(str) ? +str : str ) } }, onSwitchValueInput(val, name) { if (['true', 'false'].indexOf(val) > -1) { this.$set(this.activeData, name, JSON.parse(val)) } else { this.$set(this.activeData, name, isNumberStr(val) ? +val : val) } }, setTimeValue(val, type) { const valueFormat = type === 'week' ? dateTimeFormat.date : val this.$set(this.activeData.__config__, 'defaultValue', null) this.$set(this.activeData, 'value-format', valueFormat) this.$set(this.activeData, 'format', val) }, spanChange(val) { this.formConf.span = val }, multipleChange(val) { this.$set(this.activeData.__config__, 'defaultValue', val ? [] : '') }, dateTypeChange(val) { this.setTimeValue(dateTimeFormat[val], val) }, rangeChange(val) { this.$set( this.activeData.__config__, 'defaultValue', val ? [this.activeData.min, this.activeData.max] : this.activeData.min ) }, rateTextChange(val) { if (val) this.activeData['show-score'] = false }, rateScoreChange(val) { if (val) this.activeData['show-text'] = false }, colorFormatChange(val) { this.activeData.__config__.defaultValue = null this.activeData['show-alpha'] = val.indexOf('a') > -1 this.activeData.__config__.renderKey = +new Date() // 更新renderKey,重新渲染该组件 }, openIconsDialog(model) { this.iconsVisible = true this.currentIconModel = model }, setIcon(val) { this.activeData[this.currentIconModel] = val }, tagChange(tagIcon) { let target = inputComponents.find(item => item.__config__.tagIcon === tagIcon) if (!target) target = selectComponents.find(item => item.__config__.tagIcon === tagIcon) this.$emit('tag-change', target) }, changeRenderKey() { if (needRerenderList.includes(this.activeData.__config__.tag)) { this.activeData.__config__.renderKey = +new Date() } } } } </script> <style lang="scss" scoped> .right-board { width: 350px; position: absolute; right: 0; top: 0; padding-top: 3px; .field-box { position: relative; height: calc(100vh - 42px); box-sizing: border-box; overflow: hidden; } .el-scrollbar { height: 100%; } } .select-item { display: flex; border: 1px dashed #fff; box-sizing: border-box; & .close-btn { cursor: pointer; color: #f56c6c; } & .el-input + .el-input { margin-left: 4px; } } .select-item + .select-item { margin-top: 4px; } .select-item.sortable-chosen { border: 1px dashed #409eff; } .select-line-icon { line-height: 32px; font-size: 22px; padding: 0 4px; color: #777; } .option-drag { cursor: move; } .time-range { .el-date-editor { width: 227px; } ::v-deep .el-icon-time { display: none; } } .document-link { position: absolute; display: block; width: 26px; height: 26px; top: 0; left: 0; cursor: pointer; background: #409eff; z-index: 1; border-radius: 0 0 6px 0; text-align: center; line-height: 26px; color: #fff; font-size: 18px; } .node-label{ font-size: 14px; } .node-icon{ color: #bebfc3; } </style>