You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

1430 lines
56 KiB

<template>
<div class="right-board">
<el-tabs v-model="currentTab"
class="center-tabs">
<el-tab-pane label="组件属性"
name="field" />
</el-tabs>
<div class="field-box">
<el-scrollbar class="right-scrollbar">
<!-- 组件属性 -->
<el-form v-show="currentTab === 'field' && showField"
label-width="90px"
size="small">
<el-form-item v-if="activeData.__config__.changeTag"
label="组件类型">
<el-select v-model="activeData.__config__.tagIcon"
:style="{ width: '100%' }"
placeholder="请选择组件类型"
@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 :name="item.__config__.tagIcon"
class="node-icon" />
<!-- <svg-icon class="node-icon" :icon-class="item.__config__.tagIcon" />-->
<span>
{{ item.__config__.label
}}{{ item.__config__.tagIcon }}</span>
</el-option>
</el-option-group>
</el-select>
</el-form-item>
<!-- <el-form-item v-if="activeData.__vModel__!==undefined" label="字段名">-->
<!-- <el-input v-model="activeData.__vModel__" placeholder="请输入字段名(v-model)" />-->
<!-- </el-form-item>-->
<el-form-item v-if="activeData.__config__.componentName !== undefined"
label="组件名">
{{ activeData.__config__.componentName }}
</el-form-item>
<el-form-item v-if="
activeData.__config__.label !== undefined &&
activeData.__config__.showLabel !== false
"
label="标题">
<el-input v-model="activeData.__config__.label"
placeholder="请输入标题"
@input="changeRenderKey" />
</el-form-item>
<el-form-item v-if="activeData.placeholder !== undefined"
label="占位提示">
<el-input v-model="activeData.placeholder"
placeholder="请输入占位提示"
@input="changeRenderKey" />
</el-form-item>
<el-form-item v-if="activeData['start-placeholder'] !== undefined"
label="开始占位">
<el-input v-model="activeData['start-placeholder']"
placeholder="请输入占位提示" />
</el-form-item>
<el-form-item v-if="activeData['end-placeholder'] !== undefined"
label="结束占位">
<el-input v-model="activeData['end-placeholder']"
placeholder="请输入占位提示" />
</el-form-item>
<el-form-item v-if="activeData.__config__.span !== undefined"
label="表单栅格">
<el-slider v-model="activeData.__config__.span"
:marks="{ 12: '' }"
:max="24"
:min="1"
@change="spanChange" />
</el-form-item>
<el-form-item v-if="
activeData.__config__.layout === 'rowFormItem' &&
activeData.gutter !== undefined
"
label="栅格间隔">
<el-input-number v-model="activeData.gutter"
:min="0"
placeholder="栅格间隔" />
</el-form-item>
<el-form-item v-if="
activeData.__config__.layout === 'rowFormItem' &&
activeData.type !== undefined
"
label="布局模式">
<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="水平排列">
<el-select v-model="activeData.justify"
:style="{ width: '100%' }"
placeholder="请选择水平排列">
<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="垂直排列">
<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="标签宽度">-->
<!-- <el-input v-model.number="activeData.__config__.labelWidth" type="number"-->
<!-- placeholder="请输入标签宽度"/>-->
<!-- </el-form-item>-->
<!-- <el-form-item v-if="activeData.style&&activeData.style.width!==undefined" label="组件宽度">-->
<!-- <el-input v-model="activeData.style.width" placeholder="请输入组件宽度" clearable/>-->
<!-- </el-form-item>-->
<el-form-item v-if="
activeData.__vModel__ !== undefined &&
activeData.__config__.showDefaultValue !== false
"
label="默认值">
<el-input :value="setDefaultValue(activeData.__config__.defaultValue)"
placeholder="请输入默认值"
@input="onDefaultValueInput" />
</el-form-item>
<el-form-item v-if="activeData.__config__.tag === 'el-checkbox-group'"
label="至少应选">
<el-input-number :min="0"
:value="activeData.min"
placeholder="至少应选"
@input="$set(activeData, 'min', $event ? $event : undefined)" />
</el-form-item>
<el-form-item v-if="activeData.__config__.tag === 'el-checkbox-group'"
label="最多可选">
<el-input-number :min="0"
:value="activeData.max"
placeholder="最多可选"
@input="$set(activeData, 'max', $event ? $event : undefined)" />
</el-form-item>
<el-form-item v-if="
activeData.__slot__ && activeData.__slot__.prepend !== undefined
"
label="前缀">
<el-input v-model="activeData.__slot__.prepend"
placeholder="请输入前缀" />
</el-form-item>
<el-form-item v-if="
activeData.__slot__ && activeData.__slot__.append !== undefined
"
label="后缀">
<el-input v-model="activeData.__slot__.append"
placeholder="请输入后缀" />
</el-form-item>
<el-form-item v-if="activeData['prefix-icon'] !== undefined"
label="前图标">
<el-input v-model="activeData['prefix-icon']"
placeholder="请输入前图标名称">
<el-button slot="append"
icon="el-icon-thumb"
@click="openIconsDialog('prefix-icon')">
选择
</el-button>
</el-input>
</el-form-item>
<el-form-item v-if="activeData['suffix-icon'] !== undefined"
label="后图标">
<el-input v-model="activeData['suffix-icon']"
placeholder="请输入后图标名称">
<el-button slot="append"
icon="el-icon-thumb"
@click="openIconsDialog('suffix-icon')">
选择
</el-button>
</el-input>
</el-form-item>
<el-form-item v-if="
activeData['icon'] !== undefined &&
activeData.__config__.tag === 'el-button'
"
label="按钮图标">
<el-input v-model="activeData['icon']"
placeholder="请输入按钮图标名称">
<el-button slot="append"
icon="el-icon-thumb"
@click="openIconsDialog('icon')">
选择
</el-button>
</el-input>
</el-form-item>
<el-form-item v-if="activeData.__config__.tag === 'el-cascader'"
label="选项分隔符">
<el-input v-model="activeData.separator"
placeholder="请输入选项分隔符" />
</el-form-item>
<el-form-item v-if="activeData.autosize !== undefined"
label="最小行数">
<el-input-number v-model="activeData.autosize.minRows"
:min="1"
placeholder="最小行数" />
</el-form-item>
<el-form-item v-if="activeData.autosize !== undefined"
label="最大行数">
<el-input-number v-model="activeData.autosize.maxRows"
:min="1"
placeholder="最大行数" />
</el-form-item>
<el-form-item v-if="isShowMin"
label="最小值">
<el-input-number v-model="activeData.min"
placeholder="最小值" />
</el-form-item>
<el-form-item v-if="isShowMax"
label="最大值">
<el-input-number v-model="activeData.max"
:max="activeData.maxLimit?activeData.maxLimit:undefined"
placeholder="最大值" />
</el-form-item>
<el-form-item v-if="activeData.height !== undefined"
label="组件高度">
<el-input-number v-model="activeData.height"
placeholder="高度"
@input="changeRenderKey" />
</el-form-item>
<el-form-item v-if="isShowStep"
label="步长">
<el-input-number v-model="activeData.step"
placeholder="步数" />
</el-form-item>
<el-form-item v-if="activeData.__config__.tag === 'el-input-number'"
label="精度">
<el-input-number v-model="activeData.precision"
:min="0"
placeholder="精度" />
</el-form-item>
<el-form-item v-if="activeData.__config__.tag === 'el-input-number'"
label="按钮位置">
<el-radio-group v-model="activeData['controls-position']">
<el-radio-button label=""> 默认 </el-radio-button>
<el-radio-button label="right"> 右侧 </el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item v-if="activeData.maxlength !== undefined"
label="最多输入">
<el-input v-model="activeData.maxlength"
placeholder="请输入字符长度">
<template slot="append"> 个字符 </template>
</el-input>
</el-form-item>
<el-form-item v-if="activeData['active-text'] !== undefined"
label="开启提示">
<el-input v-model="activeData['active-text']"
placeholder="请输入开启提示" />
</el-form-item>
<el-form-item v-if="activeData['inactive-text'] !== undefined"
label="关闭提示">
<el-input v-model="activeData['inactive-text']"
placeholder="请输入关闭提示" />
</el-form-item>
<el-form-item v-if="activeData['show-active-value']"
label="开启值">
<el-input :value="setDefaultValue(activeData['active-value'])"
placeholder="请输入开启值"
@input="onSwitchValueInput($event, 'active-value')" />
</el-form-item>
<el-form-item v-if="activeData['show-inactive-value']"
label="关闭值">
<el-input :value="setDefaultValue(activeData['inactive-value'])"
placeholder="请输入关闭值"
@input="onSwitchValueInput($event, 'inactive-value')" />
</el-form-item>
<el-form-item v-if="
activeData.type !== undefined &&
'el-date-picker' === activeData.__config__.tag
"
label="时间类型">
<el-select v-model="activeData.type"
:style="{ width: '100%' }"
placeholder="请选择时间类型"
@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="文件字段名">-->
<!-- <el-input v-model="activeData.name" placeholder="请输入上传文件字段名" />-->
<!-- </el-form-item>-->
<el-form-item v-if="activeData.accept !== undefined"
label="文件类型">
<el-select v-model="activeData.accept"
:style="{ width: '100%' }"
clearable
placeholder="请选择文件类型">
<el-option label="图片"
value="image/*" />
<el-option label="视频"
value="video/*" />
<el-option label="音频"
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="文件大小">
<el-input v-model.number="activeData.__config__.fileSize"
placeholder="请输入文件大小">
<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="上传地址">-->
<!-- <el-input v-model="activeData.action" placeholder="请输入上传地址" clearable />-->
<!-- </el-form-item>-->
<el-form-item v-if="activeData['list-type'] !== undefined"
label="列表类型">
<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="按钮类型">
<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="按钮文字">
<el-input v-model="activeData.__config__.buttonText"
placeholder="请输入按钮文字" />
</el-form-item>
<el-form-item v-if="activeData.__config__.tag === 'el-button'"
label="按钮文字">
<el-input v-model="activeData.__slot__.default"
placeholder="请输入按钮文字" />
</el-form-item>
<el-form-item v-if="activeData['range-separator'] !== undefined"
label="分隔符">
<el-input v-model="activeData['range-separator']"
placeholder="请输入分隔符" />
</el-form-item>
<el-form-item v-if="activeData['picker-options'] !== undefined"
label="时间段">
<el-input v-model="activeData['picker-options'].selectableRange"
placeholder="请输入时间段" />
</el-form-item>
<el-form-item v-if="activeData.format !== undefined"
label="时间格式">
<el-input :value="activeData.format"
placeholder="请输入时间格式"
@input="setTimeValue($event)" />
</el-form-item>
<template v-if="
['el-checkbox-group', 'el-radio-group', 'el-select'].indexOf(
activeData.__config__.tag
) > -1
">
<el-divider>选项</el-divider>
<draggable :animation="340"
:list="activeData.__slot__.options"
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="选项名"
size="small" />
<!-- <el-input-->
<!-- placeholder="选项值"-->
<!-- 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 icon="el-icon-circle-plus-outline"
style="padding-bottom: 0"
type="text"
@click="addSelectItem">
添加选项
</el-button>
<el-button icon="el-icon-document-copy"
style="padding-bottom: 0"
type="text"
@click="blukAddSelectItems">
批量贴入
</el-button>
<el-button v-if="
['el-checkbox-group', 'el-radio-group'].indexOf(
activeData.__config__.tag
) > -1
"
icon="el-icon-circle-plus-outline"
style="padding-bottom: 0"
type="text"
@click="addSelectOtherItem">
添加其他
</el-button>
</div>
<el-divider />
</template>
<template v-if="['el-carousel'].indexOf(activeData.__config__.tag) > -1">
<el-divider>选项</el-divider>
<draggable :animation="340"
:list="activeData.__slot__.options"
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>
<div class="width-full">
<div class="flex-row">
<el-input v-model="item.label"
placeholder="选项名"
size="small" />
<div class="close-btn select-line-icon"
@click="activeData.__slot__.options.splice(index, 1)">
<i class="el-icon-remove-outline" />
</div>
</div>
<div class="flex-row">
<el-input v-model="item.image"
placeholder="图片"
size="small" />
<el-upload ref="logoUpload"
:action="getUploadUrl"
:headers="getUploadHeader"
:on-progress="uploadProgressHandle"
:on-success="
(response, file, fileList) => {
item.image = response.data;
$set(activeData.__slot__.options, index, item);
closeUploadProgressHandle();
}
"
:show-file-list="false"
accept=".jpg,.jpeg,.png,.gif,.bmp,.JPG,.JPEG,.PBG,.GIF,.BMP"
style="text-align: center">
<div slot="trigger"
class="select-line-icon">
<i class="el-icon-upload" />
</div>
</el-upload>
</div>
</div>
</div>
</draggable>
<div style="margin-left: 20px">
<el-button icon="el-icon-circle-plus-outline"
style="padding-bottom: 0"
type="text"
@click="addImageCarouselItem">
添加选项
</el-button>
</div>
<el-divider />
</template>
<template v-if="['image-select'].indexOf(activeData.__config__.tag) > -1">
<el-divider>选项</el-divider>
<draggable :animation="340"
:list="activeData.options"
group="selectItem"
handle=".option-drag">
<div v-for="(item, index) in activeData.options"
:key="index"
class="select-item">
<div class="select-line-icon option-drag">
<i class="el-icon-s-operation" />
</div>
<div class="width-full">
<div class="flex-row">
<el-input v-model="item.label"
placeholder="选项名"
size="small" />
<div class="close-btn select-line-icon"
@click="activeData.options.splice(index, 1)">
<i class="el-icon-remove-outline" />
</div>
</div>
<div class="flex-row">
<el-input v-model="item.image"
placeholder="图片"
size="small" />
<el-upload ref="logoUpload"
:action="getUploadUrl"
:headers="getUploadHeader"
:on-progress="uploadProgressHandle"
:on-success="
(response, file, fileList) => {
item.image = response.data;
$set(activeData.options, index, item);
closeUploadProgressHandle();
}
"
:show-file-list="false"
accept=".jpg,.jpeg,.png,.gif,.bmp,.JPG,.JPEG,.PBG,.GIF,.BMP"
style="text-align: center">
<div slot="trigger"
class="select-line-icon">
<i class="el-icon-upload" />
</div>
</el-upload>
</div>
</div>
</div>
</draggable>
<div style="margin-left: 20px">
<el-button icon="el-icon-circle-plus-outline"
style="padding-bottom: 0"
type="text"
@click="addImageSelectItem">
添加选项
</el-button>
</div>
<el-divider />
</template>
<template v-if="['el-cascader'].indexOf(activeData.__config__.tag) > -1">
<el-divider>选项</el-divider>
<!-- <el-form-item label="数据类型">-->
<!-- <el-radio-group v-model="activeData.__config__.dataType" size="small">-->
<!-- <el-radio-button label="dynamic">-->
<!-- 动态数据-->
<!-- </el-radio-button>-->
<!-- <el-radio-button label="static">-->
<!-- 静态数据-->
<!-- </el-radio-button>-->
<!-- </el-radio-group>-->
<!-- </el-form-item>-->
<!-- <template v-if="activeData.__config__.dataType === 'dynamic'">-->
<!-- <el-form-item label="接口地址">-->
<!-- <el-input-->
<!-- v-model="activeData.__config__.url"-->
<!-- :title="activeData.__config__.url"-->
<!-- placeholder="请输入接口地址"-->
<!-- clearable-->
<!-- >-->
<!-- <el-select-->
<!-- slot="prepend"-->
<!-- v-model="activeData.__config__.method"-->
<!-- :style="{width: '85px'}"-->
<!-- >-->
<!-- <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="数据位置">-->
<!-- <el-input v-model="activeData.__config__.dataKey" placeholder="请输入标签键名" />-->
<!-- </el-form-item>-->
<!-- <el-form-item label="标签键名">-->
<!-- <el-input v-model="activeData.props.props.label" placeholder="请输入标签键名" />-->
<!-- </el-form-item>-->
<!-- <el-form-item label="值键名">-->
<!-- <el-input v-model="activeData.props.props.value" placeholder="请输入值键名" />-->
<!-- </el-form-item>-->
<!-- <el-form-item label="子级键名">-->
<!-- <el-input v-model="activeData.props.props.children" placeholder="请输入子级键名" />-->
<!-- </el-form-item>-->
<!-- </template>-->
<!-- 级联选择静态树 -->
<el-tree v-if="activeData.__config__.dataType === 'static'"
:data="activeData.options"
:expand-on-click-node="false"
:render-content="renderContent"
:draggable=true
node-key="id" />
<div v-if="activeData.__config__.dataType === 'static'"
style="margin-left: 20px">
<el-button icon="el-icon-circle-plus-outline"
style="padding-bottom: 0"
type="text"
@click="addTreeItem">
添加父级
</el-button>
</div>
<el-divider />
</template>
<el-form-item v-if="activeData.__config__.optionType !== undefined"
label="选项样式">
<el-radio-group v-model="activeData.__config__.optionType">
<el-radio-button label="default"> 默认 </el-radio-button>
<el-radio-button label="button"> 按钮 </el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item v-if="activeData['active-color'] !== undefined"
label="开启颜色">
<el-color-picker v-model="activeData['active-color']" />
</el-form-item>
<el-form-item v-if="activeData['inactive-color'] !== undefined"
label="关闭颜色">
<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="显示标签">
<el-switch v-model="activeData.__config__.showLabel" />
</el-form-item>
<el-form-item v-if="activeData.branding !== undefined"
label="品牌烙印">
<el-switch v-model="activeData.branding"
@input="changeRenderKey" />
</el-form-item>
<el-form-item v-if="activeData['show-allow-half'] "
label="允许半选">
<el-switch v-model="activeData['allow-half']" />
</el-form-item>
<el-form-item v-if="activeData['show-text'] !== undefined"
label="辅助文字">
<el-switch v-model="activeData['show-text']"
@change="rateTextChange" />
</el-form-item>
<el-form-item v-if="activeData['show-score'] !== undefined"
label="显示分数">
<el-switch v-model="activeData['show-score']"
@change="rateScoreChange" />
</el-form-item>
<el-form-item v-if="activeData['show-stops'] !== undefined"
label="显示间断点">
<el-switch v-model="activeData['show-stops']" />
</el-form-item>
<el-form-item v-if="activeData.range !== undefined"
label="范围选择">
<el-switch v-model="activeData.range"
@change="rangeChange" />
</el-form-item>
<el-form-item v-if="activeData.__config__.tag === 'el-color-picker'"
label="颜色格式">
<el-select v-model="activeData['color-format']"
:style="{ width: '100%' }"
clearable
placeholder="请选择颜色格式"
@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__.border ||
activeData.__config__.tag === 'el-color-picker' ||
activeData.__config__.tag === 'el-button')
"
label="组件尺寸">
<el-radio-group v-model="activeData.size">
<el-radio-button label="medium"> 中等 </el-radio-button>
<el-radio-button label="small"> 较小 </el-radio-button>
<el-radio-button label="mini"> 迷你 </el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item v-if="activeData['show-word-limit'] !== undefined"
label="输入统计">
<el-switch v-model="activeData['show-word-limit']" />
</el-form-item>
<el-form-item v-if="activeData.__config__.tag === 'el-input-number'"
label="严格步数">
<el-switch v-model="activeData['step-strictly']" />
</el-form-item>
<!-- <el-form-item-->
<!-- v-if="activeData.__config__.tag === 'el-cascader'"-->
<!-- label="任选层级"-->
<!-- >-->
<!-- <el-switch v-model="activeData.props.props.checkStrictly" />-->
<!-- </el-form-item>-->
<el-form-item v-if="activeData.__config__.tag === 'el-cascader'"
label="是否多选">
<el-switch v-model="activeData.props.props.multiple" />
</el-form-item>
<el-form-item v-if="activeData.__config__.tag === 'el-cascader'"
label="展示全路径">
<el-switch v-model="activeData['show-all-levels']" />
</el-form-item>
<el-form-item v-if="activeData.__config__.tag === 'el-cascader'"
label="可否筛选">
<el-switch v-model="activeData.filterable" />
</el-form-item>
<el-form-item v-if="activeData.clearable !== undefined"
label="能否清空">
<el-switch v-model="activeData.clearable" />
</el-form-item>
<el-form-item v-if="activeData.__config__.showTip !== undefined"
label="显示提示">
<el-switch v-model="activeData.__config__.showTip" />
</el-form-item>
<el-form-item v-if="activeData.__config__.tag === 'el-upload'"
label="多选文件">
<el-switch v-model="activeData.multiple" />
</el-form-item>
<el-form-item v-if="activeData.__config__.tag === 'el-upload'"
label="文件个数">
<el-input-number v-model="activeData.limit" />
</el-form-item>
<!-- <el-form-item v-if="activeData['auto-upload'] !== undefined" label="自动上传">-->
<!-- <el-switch v-model="activeData['auto-upload']" />-->
<!-- </el-form-item>-->
<el-form-item v-if="activeData.readonly !== undefined"
label="是否只读">
<el-switch v-model="activeData.readonly" />
</el-form-item>
<!-- <el-form-item-->
<!-- v-if="activeData.disabled !== undefined"-->
<!-- label="是否禁用"-->
<!-- >-->
<!-- <el-switch v-model="activeData.disabled" />-->
<!-- </el-form-item>-->
<el-form-item v-if="activeData.__config__.tag === 'el-select'"
label="能否搜索">
<el-switch v-model="activeData.filterable" />
</el-form-item>
<el-form-item v-if="activeData.__config__.tag === 'el-select'"
label="是否多选">
<el-switch v-model="activeData.multiple"
@change="multipleChange" />
</el-form-item>
<el-form-item v-if="activeData['color'] !== undefined"
label="颜色">
<el-color-picker v-model="activeData['color']" />
</el-form-item>
<el-form-item v-if="activeData['textAlign'] !== undefined"
label="对齐方式">
<el-radio-group v-model="activeData.textAlign">
<el-radio-button label="left"> 左对齐 </el-radio-button>
<el-radio-button label="center"> 居中 </el-radio-button>
<el-radio-button label="right"> 右对齐 </el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item v-if="activeData.__config__.tag === 'el-image'"
label="图片地址">
<el-input v-model="activeData.src"
placeholder="请输入图片url地址" />
<el-upload ref="logoUpload"
:action="getUploadUrl"
:headers="getUploadHeader"
:on-progress="uploadProgressHandle"
:on-success="
(response, file, fileList) => {
activeData.src = response.data;
closeUploadProgressHandle();
}
"
:show-file-list="false"
accept=".jpg,.jpeg,.png,.gif,.bmp,.JPG,.JPEG,.PBG,.GIF,.BMP"
style="text-align: center">
<el-button slot="trigger"
size="small"
type="text">点击上传图片 *</el-button>
</el-upload>
</el-form-item>
<el-form-item v-if="
activeData.__config__.required !== undefined &&
activeData.__config__.showRequired !== false
"
label="是否必填">
<el-switch v-model="activeData.__config__.required" />
</el-form-item>
<template v-if="activeData.__config__.layoutTree">
<el-divider>布局结构树</el-divider>
<el-tree :data="[activeData.__config__]"
:props="layoutTreeProps"
default-expand-all
:draggable=true
node-key="renderKey">
<span slot-scope="{ node, data }">
<span class="node-label">
<svg-icon :name="
data.__config__ ? data.__config__.tagIcon : data.tagIcon
"
class="node-icon" />
{{ node.label }}
</span>
</span>
</el-tree>
</template>
<template v-if="
Array.isArray(activeData.__config__.regList) &&
activeData.__config__.showRegList !== false
">
<el-divider>正则校验</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="表达式">
<el-input v-model="item.pattern"
placeholder="请输入正则" />
</el-form-item>
<el-form-item label="错误提示"
style="margin-bottom: 0">
<el-input v-model="item.message"
placeholder="请输入错误提示" />
</el-form-item>
</div>
<div style="margin-left: 20px">
<el-button icon="el-icon-circle-plus-outline"
type="text"
@click="addReg">
添加规则
</el-button>
</div>
</template>
</el-form>
<el-form v-show="currentTab === 'form'"
label-width="90px"
size="small">
<el-form-item label="表单名">
<el-input v-model="formConf.formRef"
placeholder="请输入表单名(ref)" />
</el-form-item>
<el-form-item label="表单模型">
<el-input v-model="formConf.formModel"
placeholder="请输入数据模型" />
</el-form-item>
<el-form-item label="校验模型">
<el-input v-model="formConf.formRules"
placeholder="请输入校验模型" />
</el-form-item>
<el-form-item label="表单尺寸">
<el-radio-group v-model="formConf.size">
<el-radio-button label="medium"> 中等 </el-radio-button>
<el-radio-button label="small"> 较小 </el-radio-button>
<el-radio-button label="mini"> 迷你 </el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="标签对齐">
<el-radio-group v-model="formConf.labelPosition">
<el-radio-button label="left"> 左对齐 </el-radio-button>
<el-radio-button label="right"> 右对齐 </el-radio-button>
<el-radio-button label="top"> 顶部对齐 </el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="标签宽度">
<el-input v-model.number="formConf.labelWidth"
placeholder="请输入标签宽度"
type="number" />
</el-form-item>
<el-form-item label="栅格间隔">
<el-input-number v-model="formConf.gutter"
:min="0"
placeholder="栅格间隔" />
</el-form-item>
<el-form-item label="禁用表单">
<el-switch v-model="formConf.disabled" />
</el-form-item>
<el-form-item label="表单按钮">
<el-switch v-model="formConf.formBtns" />
</el-form-item>
<el-form-item label="显示未选中组件边框">
<el-switch v-model="formConf.unFocusedComponentBorder" />
</el-form-item>
</el-form>
</el-scrollbar>
</div>
<treeNode-dialog :visible.sync="dialogVisible"
title="添加选项"
@commit="addNode" />
<icons-dialog :current="activeData[currentIconModel]"
:visible.sync="iconsVisible"
@select="setIcon" />
</div>
</template>
<script>
import { isArray } from "util";
import TreeNodeDialog from "@/views/form/editor/TreeNodeDialog";
import { isNumberStr } from "@/utils";
import IconsDialog from "./IconsDialog";
import {
imageComponents,
inputComponents,
selectComponents,
} from "@/components/generator/config";
import { saveFormConf } from "@/utils/db";
import { debounce } from "throttle-debounce";
import draggable from "vuedraggable";
import _ from "lodash";
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,
draggable,
IconsDialog,
},
props: ["showField", "activeData", "formConf"],
data () {
return {
loading: null,
currentTab: "field",
currentNode: null,
currentPID: Number,
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: {
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: "输入型组件",
options: inputComponents,
},
{
label: "图片型组件",
options: imageComponents,
},
{
label: "选择型组件",
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"].indexOf(this.activeTag) > -1
);
},
isShowStep () {
return ["el-input-number", "el-slider"].indexOf(this.activeTag) > -1;
},
getUploadHeader () {
return {
token: this.$store.getters["user/isLogin"],
};
},
getUploadUrl () {
return `${process.env.VUE_APP_API_ROOT}/user/file/upload`;
},
},
watch: {
formConf: {
handler (val) {
saveFormConf(val);
},
deep: true,
},
activeData: {
handler (newValue, oldValue) {
// 切换选中时不触发
if (newValue.__config__.formId === oldValue.__config__.formId) {
if (newValue) {
this.dataChange(newValue);
}
}
},
deep: true,
},
},
methods: {
addReg () {
this.activeData.__config__.regList.push({
pattern: "",
message: "",
});
},
addSelectItem () {
let lastItem = _.last(this.activeData.__slot__.options);
this.activeData.__slot__.options.push({
label: "",
value: lastItem
? lastItem.value === 0
? _.max(
_.values(
this.activeData.__slot__.options.map((item) => item.value)
)
) + 1
: lastItem.value + 1
: 1,
});
},
async blukAddSelectItems () {
let arrStrs = await navigator.clipboard.readText();
let arr = arrStrs.split("\n");
if (arr.length > 1) {
const options = [];
for (let index = 0; index < arr.length; index++) {
const element = arr[index];
if (element?.length > 0) {
options.push({
label: element,
value: index + 1,
});
}
}
this.activeData.__slot__.options = options;
}
},
addImageSelectItem () {
let lastItem = _.last(this.activeData.options);
this.activeData.options.push({
label: "",
image: "",
value: lastItem ? lastItem.value + 1 : 1,
});
},
addImageCarouselItem () {
let lastItem = _.last(this.activeData.__slot__.options);
this.activeData.__slot__.options.push({
label: "",
image: "",
value: lastItem ? lastItem.value + 1 : 1,
});
},
addSelectOtherItem () {
let item = this.activeData.__slot__.options.find((item) => {
return item.value == 0;
});
if (item) {
return;
}
this.activeData.__slot__.options.push({
label: "其他",
value: 0,
});
},
uploadProgressHandle () {
this.loading = this.$loading({
lock: true,
text: "上传中",
spinner: "el-icon-loading",
background: "rgba(0, 0, 0, 0.7)",
});
},
closeUploadProgressHandle () {
setTimeout(() => {
this.loading.close();
}, 100);
},
addTreeItem () {
++this.idGlobal;
this.currentPID = 0
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.currentPID = data.id
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) {
debugger
data.pid = this.currentPID
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);
},
dataChange: debounce(430, false, function (val) {
this.$emit("data-change", val);
}),
changeRenderKey () {
if (needRerenderList.includes(this.activeData.__config__.tag)) {
this.activeData.__config__.renderKey = +new Date();
}
},
},
};
</script>
<style lang="scss" scoped>
@import "@/assets/styles/form/index";
.right-board {
width: 350px;
position: absolute;
right: 0px;
top: 0;
padding-top: 3px;
background-color: #fff;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
.field-box {
position: relative;
height: calc(100vh - 70px);
box-sizing: border-box;
overflow: hidden;
}
.el-scrollbar {
height: 100%;
padding-bottom: 50px;
}
}
.select-item {
display: flex;
border: 1px dashed #fff;
box-sizing: border-box;
align-items: center;
& .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;
}
}
.node-label {
font-size: 14px;
}
.node-icon {
color: #bebfc3;
}
</style>