draggable 组件

1.新建一个draggable文件夹
2.文件夹内的目录结构

3.此下是每个文件中的内容 首先是index.vue文件
<template>
<div>
<el-container class="container-main">
<!-- 左侧 -->
<el-aside width="350px" class="main-right">
<el-header class="header-title">常用组件</el-header>
<draggable
:list="CommonUserComponents"
v-bind="{
group: {
name: 'people',
pull: 'clone',
put: false
},
sort: false,
ghostClass: 'ghostClass'
}"
:move="onMove"
class="draggable-container"
>
<el-tag
v-for="(item, index) in CommonUserComponents"
:key="index"
effect="dark"
style="width: 100%"
>
<i :class="item.icon"></i> {{ item.name }}
</el-tag>
</draggable>
</el-aside>
<!-- 中间 -->
<el-container>
<el-header class="main-bottom header-padding">
<!-- 清空按钮 -->
<el-tag
effect="plain"
type="danger"
class="header-tags"
@click="clearWidetConfit"
><i class="el-icon-delete"></i><span>清空</span>
</el-tag>
<!-- 导入json -->
<el-tag
effect="plain"
type=""
class="header-tags"
@click="setFormJson"
><i class="el-icon-connection"></i><span>导入JSON</span>
</el-tag>
<!-- 生成JSON -->
<el-tag
type=""
effect="plain"
class="header-tags"
@click="saveWidetConfit"
><i class="el-icon-document"></i><span>生成JSON</span>
</el-tag>
<!-- 表单预览 -->
<el-tag effect="plain" type="" class="header-tags" @click="showDialog"
><i class="el-icon-help"></i><span>表单预览</span>
</el-tag>
<!-- 示例DEMO -->
<el-tag type="" @click="hrefDemo" effect="plain" class="header-tags"
><i class="el-icon-star-off"></i><span>示例DEMO</span>
</el-tag>
</el-header>
<el-main class="box-padding">
<div class="widget-form-container">
<!-- 表单展示组件,传递当亲拖拽的表单信息 -->
<!-- sync修饰符表示子父组件传递的参数是双向绑定的 -->
<widgeform
ref="configFormData"
:configFormData="configFormData"
:select.sync="widgetFormSelect"
></widgeform>
<div class="biaoge"></div>
</div>
</el-main>
</el-container>
<!-- 右侧 -->
<el-aside width="350px" class="main-left">
<el-tabs v-model="activeName" style="margin-top: -4px">
<el-tab-pane label="组件设置" name="first">
<widgetconfig :eleItem.sync="widgetFormSelect"></widgetconfig>
</el-tab-pane>
<el-tab-pane label="表单属性" name="second">
<formconfig :formdata="configFormData.config"></formconfig>
</el-tab-pane>
</el-tabs>
</el-aside>
</el-container>
<!-- 预览弹出框 -->
<el-dialog
title="表单预览"
:visible.sync="dialogVisible"
width="70%"
top="5vh"
>
<dialogform ref="dialogForm"></dialogform>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="getDialogForm">获取数据</el-button>
</span>
</el-dialog>
<!-- 生成json框 -->
<el-dialog :title="dialogTitle" :visible.sync="jsonDialog" top="5vh">
<div v-if="!jsonTextareaReadonly">
JSON格式如下,直接复制生成的json覆盖此处代码点击确定即可
</div>
<div style="max-height: 400px; overflow-y: scroll">
<el-input
type="textarea"
autosize
:readonly="jsonTextareaReadonly"
v-model="jsonmsg"
>
</el-input>
</div>
<span slot="footer" class="dialog-footer" v-if="!jsonTextareaReadonly">
<el-button @click="jsonDialog = false">取 消</el-button>
<el-button type="primary" @click="setJsonBtn">确 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import draggable from 'vuedraggable';
import widgeform from './widgetForm';
import widgetconfig from './widgetConfig';
import dialogform from './dialogForm';
import formconfig from './formConfig';
import { copy as util_Copy } from './util/clone';
import { CommonUserComponents } from './componentsConfig';
export default {
components: {
draggable: draggable,
widgeform: widgeform,
widgetconfig: widgetconfig,
dialogform: dialogform,
formconfig: formconfig
},
data() {
return {
// 自定义表单的json数据
CommonUserComponents,
// 拖拽展示的数据
configFormData: {
list: [],
config: {
labelWidth: 100,
labelPosition: 'right',
size: 'small'
}
},
widgetFormSelect: {
key: null,
options: {
placeholder: null
}
},
// 预览弹框是否显示
dialogVisible: false,
// 生成json弹框
jsonDialog: false,
// 生成的json语句
jsonmsg: '',
// 弹框标题
dialogTitle: '生成JSON',
// 右侧头部标签栏
activeName: 'first',
// 弹出文本域是否可编辑,默认不可编辑
jsonTextareaReadonly: true
};
},
methods: {
// 是否可以被拖拽
onMove() {
return true;
},
// 保存方法
saveWidetConfit() {
this.dialogTitle = '生成JSON';
this.jsonTextareaReadonly = true;
this.jsonDialog = true;
this.jsonmsg = JSON.stringify(this.configFormData, null, 1);
},
// 清空方法
clearWidetConfit() {
this.configFormData = {
list: [],
config: {
labelWidth: 100,
labelPosition: 'right',
size: 'small'
}
};
this.widgetFormSelect = {
key: null,
options: {
placeholder: null
}
};
},
// 点击预览方法
showDialog() {
if (this.configFormData.list.length === 0) {
this.$message('请先拖拽组件');
return;
}
// 弹出预览框
this.dialogVisible = true;
// 异步调用弹框的方法
setTimeout(() => {
// 异步调用弹框中的方法传递表单数据
this.$refs.dialogForm.setFormVal(util_Copy(this.configFormData));
});
},
// 读取预览表单的数据
getDialogForm() {
// 读取表单生成器中的getFormVal方法获取表单填写的数据
this.$refs.dialogForm.getFormVal().then((data) => {
this.dialogTitle = '表单数据';
this.jsonTextareaReadonly = true;
this.jsonDialog = true;
this.jsonmsg = JSON.stringify(data, null, 1);
});
},
// 点击示例DEMO按钮
hrefDemo() {
this.$router.push({ path: '/demo' });
},
// 导入json方法
setFormJson() {
this.dialogTitle = '导入JSON';
this.jsonTextareaReadonly = false;
this.jsonDialog = true;
this.jsonmsg = JSON.stringify(
{
list: [],
config: {
labelWidth: 100,
labelPosition: 'right',
size: 'small'
}
},
null,
1
);
},
// 确定导入json
setJsonBtn() {
try {
this.initJson(this.jsonmsg);
this.jsonDialog = false;
} catch (error) {
this.$message('导入JSON有误');
}
},
// 初始化json,接收表单json数据,根据json数据自动渲染表单页面
initJson(strJson) {
this.configFormData = JSON.parse(strJson);
this.widgetFormSelect = this.configFormData.list[0];
}
}
};
</script>
<style>
.biaoge {
margin: 10px;
border: 1px dashed #999;
height: 30vh;
/* padding-right: 5px; */
}
.container-main {
height: 100vh;
}
.header-title {
width: 100%;
height: 35px !important;
line-height: 25px !important;
padding: 0px !important;
border-bottom: 1px solid #999999;
}
.main-right {
border-right: 1px solid #999;
padding: 10px;
}
.draggable-container {
cursor: move;
margin-top: 10px;
/* 分栏布局 */
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-auto-rows: 25px;
gap: 20px;
}
.main-bottom {
border-bottom: 1px solid #999;
height: 45px !important;
line-height: 45px;
}
.main-left {
border-left: 1px solid #999;
padding: 10px;
}
.header-padding {
position: relative;
padding: 0px !important;
text-align: right;
}
.box-padding {
padding: 0px !important;
position: relative;
overflow-y: auto;
}
.widget-form-container {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.ghostClass {
border: 2px solid #409eff !important;
}
.header-tags {
margin-right: 10px;
cursor: pointer;
}
.header-tags:nth-child(1) {
position: absolute;
left: 10px;
top: 8px;
}
</style>
- 下面是补全index.vue里面引用的各个组件文件
1)widgetForm.vue
<template>
<div class="main-form-box">
<!-- 拖拽为空时显示 -->
<div class="null-form" v-if="configFormData.list.length === 0">
<i class="el-icon-files null-icon"></i>
<div>将左侧组件拽到此处</div>
</div>
<el-form
:size="configFormData.config.size"
:label-position="configFormData.config.labelPosition"
:label-width="configFormData.config.labelWidth + 'px'"
>
<!-- 拖拽展示组件 -->
<draggable
v-model="configFormData.list"
v-bind="{ group: 'people', animation: 200 }"
@add="handleWidgetAdd"
class="container-form"
handle=".movetag"
>
<!-- 循环展示拖拽的组件 -->
<div
v-for="(item, index) in configFormData.list"
:key="index"
class="formitem-style"
>
<!-- 栅格布局 -->
<template v-if="item.type === 'grid'">
<el-row
v-if="item && item.key"
type="flex"
:gutter="item.options.gutter"
:justify="item.options.justify"
:align="item.options.align"
@click.native="handleSelectWidget(index)"
class="widget-col"
:class="{ active: selectWidget.key === item.key }"
>
<el-col
v-for="(col, colIndex) in item.columns"
:key="colIndex"
:span="col.span ? col.span : 0"
>
<draggable
v-model="col.list"
:no-transition-on-drag="false"
v-bind="{
group: 'people',
animation: 200,
handle: '.drag-widget'
}"
class="widget-col-list"
@add="handleWidgetColAdd($event, item, colIndex)"
handle=".drag-widget"
>
<template v-for="(el, i) in col.list">
<widgetformitem
:key="i"
v-if="el && el.key"
:select.sync="selectWidget"
:eleItem="el"
:eleIndex="i"
:listdata="col"
></widgetformitem>
</template>
</draggable>
</el-col>
<!-- 删除 -->
<div
class="widget-col-action"
v-if="selectWidget.key === item.key"
>
<el-tag
class="grid-tag"
effect="dark"
@click="removeWidgetElement(index)"
>
<i class="el-icon-delete"></i
></el-tag>
<el-tag effect="dark" class="grid-tag drag-widget">
<i class="el-icon-rank"></i>
</el-tag>
</div>
</el-row>
</template>
<template v-else>
<widgetformitem
v-if="item && item.key"
:select.sync="selectWidget"
:eleItem="item"
:eleIndex="index"
:listdata="configFormData"
></widgetformitem>
</template>
</div>
</draggable>
</el-form>
</div>
</template>
<script>
import draggable from 'vuedraggable';
// 每个表单数据
import widgetformitem from './widgetFormItem';
import { copy as util_Copy } from './util/clone';
export default {
components: {
draggable: draggable,
widgetformitem: widgetformitem
},
// 接收拖拽时传递过来的数据
props: ['configFormData', 'select'],
data() {
return {
// 拖拽的表单
selectWidget: this.select
};
},
methods: {
// 拖拽完成事件
handleWidgetAdd(e) {
// 获取当前拖拽的元素在放置栏中的下标
const newIndex = e.newIndex;
// 设置元素唯一key值
const key = `${Date.parse(new Date())}_${Math.ceil(
Math.random() * 99999
)}`;
// 拖拽完成后往当前元素的options添加remoteFunc,options平级添加key,model
this.$set(this.configFormData.list, newIndex, {
// 解构语法解构当前数据达到深拷贝效果,改变数据不会影响原有数据
...this.configFormData.list[newIndex],
// 同名属性覆盖原有属性
options: {
...this.configFormData.list[newIndex].options,
remoteFunc: 'func_' + key
},
// 新增属性key
key,
// 新增属性model
model: this.configFormData.list[newIndex].type + '_' + key,
rules: []
});
// 深拷贝数据,使重复组件之前相互不受影响
this.$set(
this.configFormData.list,
newIndex,
util_Copy(this.configFormData.list[newIndex])
);
// 获取拖拽的表单数据,子父组件数据双向绑定实时改变右侧配置
this.selectWidget = this.configFormData.list[newIndex];
},
// 点击栅格布局组件触发
handleSelectWidget(index) {
this.selectWidget = this.configFormData.list[index];
},
// 栅格布局删除组件方法
removeWidgetElement(index) {
if (this.configFormData.list.length - 1 === index) {
if (index === 0) {
this.selectWidget = {
key: null,
options: {
placeholder: null
}
};
console.log(this.eleItem);
} else {
this.selectWidget = this.configFormData.list[index - 1];
}
} else {
this.selectWidget = this.configFormData.list[index + 1];
}
this.$nextTick(() => {
this.configFormData.list.splice(index, 1);
});
},
// 栅格布局拖拽完成事件
handleWidgetColAdd($event, row, colIndex) {
const newIndex = $event.newIndex;
const oldIndex = $event.oldIndex;
const item = $event.item;
// 设置元素唯一key值
const key = `${Date.parse(new Date())}_${Math.ceil(
Math.random() * 99999
)}`;
// 拖拽完成后往当前元素的options添加remoteFunc,options平级添加key,model
this.$set(row.columns[colIndex].list, newIndex, {
// 解构语法解构当前数据达到深拷贝效果,改变数据不会影响原有数据
...row.columns[colIndex].list[newIndex],
// 同名属性覆盖原有属性
options: {
...row.columns[colIndex].list[newIndex].options,
remoteFunc: 'func_' + key
},
// 新增属性key
key,
// 新增属性model
model: row.columns[colIndex].list[newIndex].type + '_' + key,
rules: []
});
// 深拷贝数据,使重复组件之前相互不受影响
this.$set(
row.columns[colIndex].list,
newIndex,
util_Copy(row.columns[colIndex].list[newIndex])
);
// 获取拖拽的表单数据,子父组件数据双向绑定实时改变右侧配置
this.selectWidget = row.columns[colIndex].list[newIndex];
}
},
watch: {
select(itemdata) {
this.selectWidget = itemdata;
},
selectWidget: {
handler(data) {
this.$emit('update:select', data);
}
}
}
};
</script>
<style scoped lang="scss">
.main-form-box {
position: relative;
}
.null-form {
position: absolute;
width: 100%;
height: 100%;
display: grid;
grid-template-columns: 1fr;
grid-template-rows: 1fr 1fr;
justify-items: center;
color: #999999;
}
.null-icon {
display: grid;
align-items: end;
font-size: 93px;
}
.container-form {
margin: 10px;
border: 1px dashed #999;
height: 30vh;
padding-right: 5px;
}
.formitem-style {
margin: 5px;
border: 1px dashed #999;
}
.view-operations {
display: none;
}
.widget-view-grid {
margin-bottom: 0px !important;
height: 30px;
}
.widget-col {
padding-bottom: 0;
padding: 5px;
background-color: rgba(253, 246, 236, 0.3);
&.active {
outline: 2px solid #e6a23c;
}
&:hove {
background: #fdf6ec;
outline: 1px solid #e6a23c;
outline-offset: 0px;
}
&.active {
outline: 2px solid #e6a23c;
border: 1px solid #e6a23c;
outline-offset: 0;
}
.el-col {
min-height: 50px;
}
.widget-col-action {
position: absolute;
bottom: 0;
right: 0;
display: flex;
cursor: pointer;
}
.grid-tag {
background: #e6a23c;
border: 1px solid #e6a23c;
}
}
.widget-col-list {
min-height: 50px;
border: 1px dashed #ccc;
background: #fff;
}
</style>
2)widgetConfig.vue
<template>
<div>
<div v-if="eleItem && eleItem.key">
<el-form size="mini" label-position="top">
<!-- 表单名称 -->
<el-form-item label="标题" class="form-borderbottom">
<el-input
v-model="eleItem.name"
:disabled="eleItem.options.nameDisabled"
></el-input>
</el-form-item>
<!-- 表单绑定的model -->
<el-form-item label="数据绑定字段" class="form-borderbottom">
<el-input v-model="eleItem.model"></el-input>
</el-form-item>
<!-- 设置表单宽度 -->
<template v-if="eleItem.options.hasOwnProperty('width')">
<el-form-item label="表单宽度" class="form-borderbottom">
<el-input v-model="eleItem.options.width"></el-input>
</el-form-item>
</template>
<!-- 表单提示语句 -->
<template v-if="eleItem.options.placeholder">
<el-form-item label="提示语句" class="form-borderbottom">
<el-input v-model="eleItem.options.placeholder"></el-input>
</el-form-item>
</template>
<!-- 多行文本 -->
<template v-if="eleItem.type === 'textarea'">
<el-form-item label="行数" class="form-borderbottom">
<el-input
type="number"
min="1"
v-model="eleItem.options.rows"
></el-input>
</el-form-item>
</template>
<!-- 输入框 -->
<template v-if="eleItem.type === 'input'">
<!-- 是否是密码 -->
<el-form-item label="密码框" class="form-borderbottom">
<el-switch
v-model="eleItem.options.password"
active-text="是"
inactive-text="否"
>
</el-switch>
</el-form-item>
</template>
<!-- 多选框组 -->
<template v-if="eleItem.type === 'checkbox'">
<!-- 最大选择个数 -->
<el-form-item label="最大选择个数" class="form-borderbottom">
<el-input
v-model="eleItem.options.max"
placeholder="请输入最大选择个数"
type="number"
>
</el-input>
</el-form-item>
</template>
<!-- 计数器 -->
<template v-if="eleItem.type === 'inputNumber'">
<!-- 最小值 -->
<el-form-item label="最小值" class="form-borderbottom">
<el-input
v-model.number="eleItem.options.min"
placeholder="请输入最小值"
type="number"
>
</el-input>
</el-form-item>
<!-- 最大值 -->
<el-form-item label="最大值" class="form-borderbottom">
<el-input
v-model.number="eleItem.options.max"
placeholder="请输入最大值"
type="number"
>
</el-input>
</el-form-item>
<!-- 控制按钮位置 -->
<el-form-item label="控制按钮位置" class="form-borderbottom">
<el-radio-group v-model="eleItem.options.position">
<el-radio label="">默认</el-radio>
<el-radio label="right">右侧</el-radio>
</el-radio-group>
</el-form-item>
</template>
<!-- 下拉框 -->
<template v-if="eleItem.type === 'select'">
<!-- 是否可多选 -->
<el-form-item label="是否可多选" class="form-borderbottom">
<el-switch
v-model="eleItem.options.multiple"
active-text="是"
inactive-text="否"
>
</el-switch>
</el-form-item>
</template>
<!-- 滑块 -->
<template v-if="eleItem.type === 'slider'">
<!-- 默认值 -->
<el-form-item label="默认值" class="form-borderbottom">
<el-input
v-model.number="eleItem.options.defaultValue"
type="number"
placeholder="请输入默认值"
>
</el-input>
</el-form-item>
<!-- 最小值 -->
<el-form-item label="最小值" class="form-borderbottom">
<el-input
v-model.number="eleItem.options.min"
placeholder="请输入最小值"
type="number"
>
</el-input>
</el-form-item>
<!-- 最大值 -->
<el-form-item label="最大值" class="form-borderbottom">
<el-input
v-model.number="eleItem.options.max"
placeholder="请输入最大值"
type="number"
>
</el-input>
</el-form-item>
</template>
<!-- 评分 -->
<template v-if="eleItem.type === 'rate'">
<!-- 默认值 -->
<el-form-item label="默认值" class="form-borderbottom">
<el-input
v-model.number="eleItem.options.defaultValue"
type="number"
placeholder="请输入默认值"
>
</el-input>
</el-form-item>
<!-- 最大值 -->
<el-form-item label="最大值" class="form-borderbottom">
<el-input
v-model.number="eleItem.options.max"
placeholder="请输入最大值"
type="number"
>
</el-input>
</el-form-item>
<!-- 辅助文字 -->
<el-form-item label="辅助文字" class="form-borderbottom">
<el-switch
v-model="eleItem.options.text"
active-text="是"
inactive-text="否"
>
</el-switch>
</el-form-item>
</template>
<!-- 日期选择器 -->
<template v-if="eleItem.type === 'datePicker'">
<!-- 可选时间 -->
<el-form-item label="时间类型" class="form-borderbottom">
<el-radio-group
@change="changeDateType"
v-model="eleItem.options.type"
class="date-type-group"
>
<el-radio label="date">只选择日期</el-radio>
<el-radio label="datetime">选择日期和时间</el-radio>
<el-radio label="daterange">选择日期范围</el-radio>
</el-radio-group>
</el-form-item>
</template>
<!-- 文字 -->
<template v-if="eleItem.type === 'text'">
<!-- 编辑文字 -->
<el-form-item label="编辑文字" class="form-borderbottom">
<el-input
v-model="eleItem.options.defaultValue"
placeholder="请输入文字"
type="textarea"
autosize
>
</el-input>
</el-form-item>
<!-- 位置 -->
<el-form-item label="位置" class="form-borderbottom">
<el-radio-group v-model="eleItem.options.position">
<el-radio label="">靠左对齐</el-radio>
<el-radio label="center">居中对齐</el-radio>
<el-radio label="end" style="margin-top: 10px">靠右对齐</el-radio>
</el-radio-group>
</el-form-item>
<!-- 字体颜色 -->
<el-form-item label="字体颜色" class="form-borderbottom">
<el-color-picker
@active-change="changeTextColor"
v-model="eleItem.options.color"
></el-color-picker>
</el-form-item>
<!-- 字体大小 -->
<el-form-item label="字体大小" class="form-borderbottom">
<el-input-number
v-model="eleItem.options.size"
:min="1"
label="字体大小"
></el-input-number>
</el-form-item>
<!-- 字体粗细 -->
<el-form-item label="字体粗细" class="form-borderbottom">
<el-radio-group v-model="eleItem.options.weight">
<el-radio label="">默认</el-radio>
<el-radio label="700">加粗</el-radio>
</el-radio-group>
</el-form-item>
<!-- 字体倾斜 -->
<el-form-item label="字体倾斜" class="form-borderbottom">
<el-radio-group v-model="eleItem.options.style">
<el-radio label="">默认</el-radio>
<el-radio label="italic">倾斜</el-radio>
</el-radio-group>
</el-form-item>
<!-- 首行缩进 -->
<el-form-item label="首行缩进" class="form-borderbottom">
<el-input-number
:min="0"
v-model="eleItem.options.indent"
label="首行缩进"
></el-input-number>
</el-form-item>
<!-- 字体缩进 -->
<el-form-item label="字体缩进" class="form-borderbottom">
<el-input-number
:min="0"
v-model="eleItem.options.leftPadding"
label="字体缩进"
></el-input-number>
</el-form-item>
<!-- 字体行间距 -->
<el-form-item label="字体行间距" class="form-borderbottom">
<el-input-number
:min="0"
v-model="eleItem.options.lineHeight"
label="字体行间距"
></el-input-number>
</el-form-item>
</template>
<!-- 分割线 -->
<template v-if="eleItem.type === 'divider'">
<!-- 分割线文案 -->
<el-form-item label="分割线文案" class="form-borderbottom">
<el-input
v-model="eleItem.options.defaultValue"
placeholder="分割线文案"
></el-input>
</el-form-item>
<!-- 文案位置 -->
<el-form-item
label="文案位置"
class="form-borderbottom"
v-if="eleItem.options.defaultValue"
>
<el-radio-group v-model="eleItem.options.position">
<el-radio label="left">靠左对齐</el-radio>
<el-radio label="center">居中对齐</el-radio>
<el-radio label="right" style="margin-top: 10px"
>靠右对齐</el-radio
>
</el-radio-group>
</el-form-item>
</template>
<!-- 多组件共享配置:单选框和多选框和下拉框 -->
<template
v-if="
eleItem.type === 'radio' ||
eleItem.type === 'checkbox' ||
eleItem.type === 'select'
"
>
<el-form-item label="是否显示标签" class="form-borderbottom">
<el-switch
v-model="eleItem.options.isTag"
active-text="是"
inactive-text="否"
>
</el-switch>
</el-form-item>
<el-form-item label="选项组" class="form-borderbottom">
<draggable
v-model="eleItem.options.valueData"
animation="300"
class="dragg-ui"
handle=".i-success"
ghostClass="ghost"
>
<li
v-for="(item, index) in eleItem.options.valueData"
:key="index"
>
<div class="value-label-input">
<!-- 设置显示的值 -->
<el-input
v-model="item.value"
:class="{ value_input: !eleItem.options.isTag }"
></el-input>
<!-- 设置绑定的值 -->
<el-input
v-if="eleItem.options.isTag"
v-model="item.label"
></el-input>
</div>
<i class="el-icon-rank i-success"></i>
<i
class="el-icon-delete i-danger"
@click="removeEleItemValueData(index)"
></i>
</li>
</draggable>
<el-button type="text config-addbtn" @click="addEleItemValueData"
>添加选项</el-button
>
<el-button type="text config-addbtn" @click="addMultipleValueData"
>批量添加</el-button
>
</el-form-item>
</template>
<!-- 组件共享配置 : 是否添加边框 -->
<template
v-if="eleItem.type === 'radio' || eleItem.type === 'checkbox'"
>
<!-- 布局方法 -->
<el-form-item label="布局方法" class="form-borderbottom">
<el-radio-group v-model="eleItem.options.inline">
<el-radio label="inline-block">行内</el-radio>
<el-radio label="block">块级</el-radio>
</el-radio-group>
</el-form-item>
</template>
<!-- 组件公共配置项目 : 最大输入长度 -->
<template v-if="eleItem.options.hasOwnProperty('maxlength')">
<el-form-item label="最大输入长度" class="form-borderbottom">
<el-input
type="number"
placeholder="请输入最大输入长度"
v-model="eleItem.options.maxlength"
>
</el-input>
</el-form-item>
</template>
<!-- 组件公共配置项目 :是否必填 -->
<template v-if="eleItem.options.hasOwnProperty('required')">
<el-form-item label="是否必填" class="form-borderbottom">
<el-switch
v-model="eleItem.options.required"
active-text="是"
inactive-text="否"
>
</el-switch>
</el-form-item>
<!-- 错误提示语句 -->
<el-form-item
v-if="eleItem.options.required"
label="自定义错误提示语句"
class="form-borderbottom"
>
<el-input
v-model="eleItem.options.requiredMsg"
placeholder="自定义错误提示语句"
>
</el-input>
</el-form-item>
</template>
<!-- 组件公共配置项目 : 是否禁用 -->
<el-form-item
label="是否禁用"
class="form-borderbottom"
v-if="eleItem.type !== 'text' && eleItem.type !== 'divider'"
>
<el-switch
v-model="eleItem.options.disabled"
active-text="是"
inactive-text="否"
>
</el-switch>
</el-form-item>
<!-- 组件公共配置项目 : 是否可清空 -->
<template v-if="eleItem.options.hasOwnProperty('clearable')">
<el-form-item label="是否可清空" class="form-borderbottom">
<el-switch
v-model="eleItem.options.clearable"
active-text="是"
inactive-text="否"
>
</el-switch>
</el-form-item>
</template>
</el-form>
</div>
<!-- 批量添加选项弹框 -->
<el-dialog title="批量添加选项" :visible.sync="addMultipleStatus" top="5vh">
<div class="addHeaderTitle">
每行代表一个选项,可以添加多个选项<span>(已自动过滤重复项)</span>。
</div>
<el-input
type="textarea"
autosize
:autosize="{ minRows: 3, maxRows: 17 }"
placeholder="请输入内容"
v-model="eleItemValueData"
>
</el-input>
<span slot="footer" class="dialog-footer">
<el-button @click="addMultipleStatus = false">取 消</el-button>
<el-button type="primary" @click="saveAddMultiple">确 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import draggable from "vuedraggable";
export default {
components: {
draggable: draggable,
},
props: ["eleItem"],
data() {
return {
// 批量添加弹框
addMultipleStatus: false,
eleItemValueData: "",
};
},
methods: {
// 删除选项
removeEleItemValueData(index) {
this.eleItem.options.valueData.splice(index, 1);
},
// 添加选项
addEleItemValueData() {
// 随机生成4位数防止报key重复错误
let random = Math.floor(Math.random() * 9999);
this.eleItem.options.valueData.push({
value: "新选项" + random,
label: "新选项" + random,
});
},
// 弹出批量添加选项框方法
addMultipleValueData() {
this.addMultipleStatus = true;
this.eleItemValueData = "";
},
// 确认批量添加选项方法
saveAddMultiple() {
if (!this.eleItemValueData) {
this.$message({
message: "请输入内容",
type: "warning",
});
return;
}
let reg = /(\s*)(.+)(\s*)/g;
let values = [];
this.eleItemValueData.replace(reg, (...args) => {
values.push(args[2]);
});
values = [...new Set(values)];
values.forEach((item) => {
this.eleItem.options.valueData.push({
value: item,
label: item,
});
});
this.addMultipleStatus = false;
},
// 改变日期选择器的类型触发
changeDateType(e) {
this.eleItem.options.valueFormat =
e === "datetime" ? "yyyy-MM-dd HH:mm:ss" : "yyyy-MM-dd";
},
// 改变文字颜色是实时改变页面中的文字颜色
changeTextColor(e) {
this.eleItem.options.color = e;
},
},
watch: {
eleItem: {
handler(data) {
// 不需要展示标题的组件集合
let noShowNameData = ["text", "divider"];
if (noShowNameData.some((item) => item === data.type)) {
data.name = "";
}
this.$emit("update:eleItem", data);
},
},
},
};
</script>
<style scoped>
.date-type-group {
display: grid;
grid-template-columns: 1fr;
gap: 10px;
}
.value-label-input {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 5px;
}
.value_input {
grid-column-start: span 2;
}
.el-form-item--mini > .el-form-item__label {
padding: 0px !important;
}
.form-borderbottom {
margin-bottom: 15px !important;
padding-bottom: 8px;
border-bottom: 1px solid #e1e1e1;
}
form-item--mini .el-form-item__label {
margin-bottom: -10px !important;
line-height: 28px !important;
}
li {
list-style-type: none;
}
.dragg-ui {
display: grid;
grid-auto-columns: 1fr;
gap: 5px;
}
.dragg-ui > li {
display: grid;
grid-template-columns: 5fr 1fr 1fr;
justify-items: right;
align-items: center;
}
.i-success {
padding: 4px;
border-radius: 50%;
color: rgb(255, 255, 255);
background-color: rgb(64, 158, 255);
border-color: rgb(64, 158, 255);
}
.i-danger {
padding: 4px;
border-radius: 50%;
color: rgb(255, 255, 255);
background-color: rgb(245, 108, 108);
border-color: rgb(245, 108, 108);
}
.ghost {
height: 28px;
border: 1px dashed #0f79e2;
background-color: #add3f8;
}
.ghost > * {
display: none !important;
}
.config-addbtn {
text-align: left !important;
}
.config-title {
width: 100%;
height: 35px !important;
line-height: 25px !important;
padding: 0px !important;
border-bottom: 1px solid #999999;
}
.addHeaderTitle {
margin-bottom: 10px;
}
.addHeaderTitle > span {
color: #999999;
font-size: 10px;
}
</style>
3)dialogForm.vue
<template>
<div v-if="eleList">
<el-form
:size="eleList.config.size"
:label-position="eleList.config.labelPosition"
:label-width="eleList.config.labelWidth + 'px'"
>
<!-- 循环展示拖拽的组件 -->
<div
v-for="(item, index) in eleList.list"
:key="index"
class="formitem-style"
>
<el-form-item :label="item.name" :required="item.options.required">
<dialogformitems
:eleItem="item"
:eleConfig="eleList.config"
></dialogformitems>
</el-form-item>
</div>
</el-form>
</div>
</template>
<script>
import dialogformitems from "./dialogFormItems";
export default {
components: {
dialogformitems: dialogformitems,
},
data() {
return {
eleList: null,
formsVal: {},
};
},
methods: {
// 获取到页面数据
setFormVal(data) {
this.eleList = data;
},
// 表单验证方法
valueCheck() {
const promises = [];
for (const key of this.eleList.list) {
if (key.options.required) {
if (key.options.defaultValue instanceof Array) {
if (key.options.defaultValue.length === 0) {
if (key.options.requiredMsg) {
promises.push(Promise.reject(key.options.requiredMsg));
} else {
promises.push(Promise.reject(`${key.name}必填`));
}
}
} else {
if (!key.options.defaultValue) {
if (key.options.requiredMsg) {
promises.push(Promise.reject(key.options.requiredMsg));
} else {
promises.push(Promise.reject(`${key.name}必填`));
}
}
}
} else {
promises.push(Promise.resolve());
}
}
return promises;
},
getFormVal() {
return new Promise((resolve, reject) => {
Promise.all(this.valueCheck())
.then((res) => {
// 读取数据前先清空表单数据
this.formsVal = {};
// 循环读取表单数据
for (const key of this.eleList.list) {
Object.assign(this.formsVal, {
[key.model]: key.options.defaultValue,
});
}
resolve(this.formsVal);
})
.catch((err) => {
this.$message.error(err);
reject();
});
});
},
},
};
</script>
4)formConfig.vue
<template>
<div>
<el-form label-position="top" size="mini">
<el-form-item label="标签对齐方式" class="form-borderbottom">
<el-radio-group v-model="formdata.labelPosition">
<div class="positon-group">
<el-radio label="right">右对齐(默认值)</el-radio>
<el-radio label="top">顶部对齐</el-radio>
<el-radio label="left">左对齐</el-radio>
</div>
</el-radio-group>
</el-form-item>
<el-form-item label="组件尺寸" class="form-borderbottom">
<el-radio-group v-model="formdata.size">
<div class="positon-group">
<el-radio label="medium">大</el-radio>
<el-radio label="small">中(默认值)</el-radio>
<el-radio label="mini">小</el-radio>
</div>
</el-radio-group>
</el-form-item>
<el-form-item label="表单字段宽度(单位:px)" class="form-borderbottom">
<el-input
v-model.number="formdata.labelWidth"
type="number"
min="10"
></el-input>
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
props: ["formdata"],
};
</script>
<style scoped>
.form-borderbottom {
margin-bottom: 15px !important;
padding-bottom: 8px;
border-bottom: 1px solid #e1e1e1;
}
.positon-group {
display: grid !important;
grid-template-columns: 1fr;
gap: 10px;
}
</style>
5)componentsConfig.js
export const CommonUserComponents = [{
type: "input",
name: "单行文本",
icon: "el-icon-share",
options: {
width: "100%",
placeholder: "请输入单行文本",
defaultValue: "",
required: false,
clearable: false,
maxlength: ""
}
},
{
type: "textarea",
name: "多行行文本",
icon: "el-icon-share",
options: {
width: "100%",
rows: 2,
placeholder: "请输入多行行文本",
defaultValue: "",
required: false,
maxlength: ""
}
},
{
type: "radio",
name: "单选框组",
icon: "el-icon-share",
options: {
inline: "inline-block",
valueData: [{
value: '选项1',
label: '选项1'
},
{
value: '选项2',
label: '选项2'
}
],
defaultValue: "",
required: false
}
},
{
type: "checkbox",
name: "多选框组",
icon: "el-icon-share",
options: {
inline: "inline-block",
valueData: [{
value: '选项1',
label: '选项1'
},
{
value: '选项2',
label: '选项2'
}
],
defaultValue: [],
required: false
}
},
{
type: "inputNumber",
name: "计数器",
icon: "el-icon-share",
options: {
defaultValue: 0,
min: 0,
max: 100,
required: false,
position: ""
}
},
{
type: "select",
name: "下拉框",
icon: "el-icon-share",
options: {
width: "100%",
required: false,
defaultValue: "",
clearable: false,
valueData: [{
value: '选项1',
label: '选项1'
},
{
value: '选项2',
label: '选项2'
}
],
}
},
{
type: "slider",
name: "滑块",
icon: "el-icon-share",
options: {
required: false,
defaultValue: 0,
min: 0,
max: 100
}
},
{
type: "rate",
name: "评分",
icon: "el-icon-share",
options: {
required: false,
defaultValue: 0,
max: 5
}
},
{
type: "timePicker",
name: "时间选择器",
icon: "el-icon-share",
options: {
width: "100%",
required: false,
defaultValue: "",
clearable: false,
}
},
{
type: "datePicker",
name: "日期选择器",
icon: "el-icon-share",
options: {
width: "100%",
required: false,
clearable: false,
defaultValue: "",
type: "date",
valueFormat: "yyyy-MM-dd"
}
},
{
type: "text",
name: "文字",
icon: "el-icon-share",
options: {
nameDisabled: true,
defaultValue: "默认文字",
position: "",
lineHeight: 25,
size: 14,
leftPadding: 0,
color: "#000000",
weight: '',
style: '',
indent: 0
}
},
{
type: "divider",
name: "分割线",
icon: "el-icon-share",
options: {
nameDisabled: true,
defaultValue: "",
position: 'center'
}
},
// {
// type: "grid",
// name: "网格布局",
// icon: "el-icon-share",
// columns: [{
// span: 12,
// list: []
// },
// {
// span: 12,
// list: []
// }
// ],
// options: {
// gutter: 0,
// justify: "start",
// align: 'top'
// }
// }
]
- 文件夹内新建一个util文件夹 并新建一个clone.js文件
export const copy = (obj) => {
// 先判断拷贝目标是对象还是数组,用instanceof判断原型是Array还是Object
let res = obj instanceof Array ? [] : {};
for (const [key, value] of Object.entries(obj)) {
res[key] = typeof value === "object" ? copy(value) : value;
}
return res
// return JSON.parse(JSON.stringify(obj));
}
此上index.vue里面的文件就补全了 但是引用的文件里还有音容的其他文件
1)dialogForm.vue里面引用的dialogFormItems.vue
<template>
<div>
<!-- 单行文本 -->
<template v-if="eleItem.type === 'input'">
<el-input
v-model="eleItem.options.defaultValue"
:placeholder="eleItem.options.placeholder"
:style="{ width: eleItem.options.width }"
:disabled="eleItem.options.disabled"
:clearable="eleItem.options.clearable"
:show-password="eleItem.options.password"
:maxlength="eleItem.options.maxlength"
show-word-limit
></el-input>
</template>
<!-- 多行文本 -->
<template v-if="eleItem.type === 'textarea'">
<el-input
type="textarea"
:style="{ width: eleItem.options.width }"
:rows="eleItem.options.rows"
v-model="eleItem.options.defaultValue"
:placeholder="eleItem.options.placeholder"
:disabled="eleItem.options.disabled"
:maxlength="eleItem.options.maxlength"
show-word-limit
>
</el-input>
</template>
<!-- 单选 -->
<template v-if="eleItem.type === 'radio'">
<el-radio-group v-model="eleItem.options.defaultValue">
<el-radio
v-for="(item, index) in eleItem.options.valueData"
:key="index"
:label="item.label"
:style="{ display: eleItem.options.inline }"
:class="{ radioLineHeight: !eleItem.options.border }"
:disabled="eleItem.options.disabled"
:border="eleItem.options.border"
>{{ item.value }}</el-radio
>
</el-radio-group>
</template>
<!-- 多选 -->
<template v-if="eleItem.type === 'checkbox'">
<el-checkbox-group
v-model="eleItem.options.defaultValue"
:max="eleItem.options.max"
>
<el-checkbox
v-for="(item, index) in eleItem.options.valueData"
:key="index"
:label="item.label"
:style="{ display: eleItem.options.inline }"
:disabled="eleItem.options.disabled"
:border="eleItem.options.border"
>{{ item.value }}</el-checkbox
>
</el-checkbox-group>
</template>
<!-- 计数器 -->
<template v-if="eleItem.type === 'inputNumber'">
<el-input-number
v-model="eleItem.options.defaultValue"
:min="eleItem.options.min"
:max="eleItem.options.max"
:controls-position="eleItem.options.position"
:disabled="eleItem.options.disabled"
></el-input-number>
</template>
<!-- 下拉框 -->
<template v-if="eleItem.type === 'select'">
<el-select
v-model="eleItem.options.defaultValue"
placeholder="请选择一个选项"
:style="{ width: eleItem.options.width }"
:multiple="eleItem.options.multiple"
:clearable="eleItem.options.clearable"
:disabled="eleItem.options.disabled"
>
<el-option
v-for="item in eleItem.options.valueData"
:key="item.label"
:label="item.value"
:value="item.label"
>
</el-option>
</el-select>
</template>
<!-- 滑块 -->
<template v-if="eleItem.type === 'slider'">
<el-slider
v-model="eleItem.options.defaultValue"
:disabled="eleItem.options.disabled"
:min="eleItem.options.min"
:max="eleItem.options.max"
></el-slider>
</template>
<!-- 评分 -->
<template v-if="eleItem.type === 'rate'">
<el-rate
v-model="eleItem.options.defaultValue"
:max="eleItem.options.max"
:disabled="eleItem.options.disabled"
:show-text="eleItem.options.text"
style="margin-top: 6px"
></el-rate>
</template>
<!-- 时间选择器 -->
<template v-if="eleItem.type === 'timePicker'">
<el-time-picker
:style="{ width: eleItem.options.width }"
v-model="eleItem.options.defaultValue"
placeholder="选择时间"
:disabled="eleItem.options.disabled"
:clearable="eleItem.options.clearable"
:default-value="new Date()"
value-format="HH:mm:ss"
format="HH:mm:ss"
>
</el-time-picker>
</template>
<!-- 日期选择器 -->
<template v-if="eleItem.type === 'datePicker'">
<el-date-picker
v-model="eleItem.options.defaultValue"
placeholder="选择日期"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
:value-format="eleItem.options.valueFormat"
:default-value="new Date()"
:style="{ width: eleItem.options.width }"
:type="eleItem.options.type"
:disabled="eleItem.options.disabled"
:clearable="eleItem.options.clearable"
>
</el-date-picker>
</template>
<!-- 文字 -->
<template v-if="eleItem.type === 'text'">
<div
:class="{ 'form-text': eleConfig.labelPosition !== 'top' }"
:style="{
display: 'grid',
'justify-content': eleItem.options.position,
'font-size': eleItem.options.size + 'px',
color: eleItem.options.color,
'line-height': eleItem.options.lineHeight + 'px',
'font-weight': eleItem.options.weight,
}"
>
<div
:style="{
'padding-left': eleItem.options.leftPadding + 'px',
'font-style': eleItem.options.style,
'text-indent': eleItem.options.indent + 'em',
}"
>
{{ eleItem.options.defaultValue }}
</div>
</div>
</template>
<!-- 分割线 -->
<template v-if="eleItem.type === 'divider'">
<div :class="{ 'form-text': eleConfig.labelPosition !== 'top' }">
<el-divider :content-position="eleItem.options.position">
{{ eleItem.options.defaultValue }}
</el-divider>
</div>
</template>
</div>
</template>
<script>
export default {
props: ["eleItem", "eleConfig"],
};
</script>
<style scoped>
.radioLineHeight {
line-height: 32px;
}
.form-text {
margin-left: -100px;
font-style: unset;
}
</style>
2)widgetForm.vue引用的 widgetFormItem.vue
<template>
<el-form-item
v-if="eleItem && eleItem.key"
:label="eleItem.name"
class="widget-view"
:class="{ active: selectWidget.key === eleItem.key }"
@click.native.stop="handleSelectWidget()"
:required="eleItem.options.required"
>
<!-- 单行文本 -->
<template v-if="eleItem.type === 'input'">
<el-input
v-model="eleItem.options.defaultValue"
:style="{ width: eleItem.options.width }"
:placeholder="eleItem.options.placeholder"
:disabled="eleItem.options.disabled"
:show-password="eleItem.options.password"
:clearable="eleItem.options.clearable"
:maxlength="eleItem.options.maxlength"
show-word-limit
readonly
></el-input>
</template>
<!-- 多行文本 -->
<template v-if="eleItem.type === 'textarea'">
<el-input
type="textarea"
readonly
:style="{ width: eleItem.options.width }"
:rows="eleItem.options.rows"
v-model="eleItem.options.defaultValue"
:placeholder="eleItem.options.placeholder"
:disabled="eleItem.options.disabled"
:maxlength="eleItem.options.maxlength"
show-word-limit
>
</el-input>
</template>
<!-- 单选 -->
<template v-if="eleItem.type === 'radio'">
<el-radio-group v-model="eleItem.options.defaultValue">
<el-radio
v-for="(item, index) in eleItem.options.valueData"
:key="index"
:label="item.label"
:style="{ display: eleItem.options.inline }"
:class="{ radioLineHeight: !eleItem.options.border }"
:disabled="eleItem.options.disabled"
:border="eleItem.options.border"
>{{ item.value }}</el-radio
>
</el-radio-group>
</template>
<!-- 多选 -->
<template v-if="eleItem.type === 'checkbox'">
<el-checkbox-group
v-model="eleItem.options.defaultValue"
:max="eleItem.options.max"
>
<el-checkbox
v-for="(item, index) in eleItem.options.valueData"
:key="index"
:label="item.value"
:style="{ display: eleItem.options.inline }"
:disabled="eleItem.options.disabled"
:border="eleItem.options.border"
>{{ item.value }}</el-checkbox
>
</el-checkbox-group>
</template>
<!-- 计数器 -->
<template v-if="eleItem.type === 'inputNumber'">
<el-input-number
v-model="eleItem.options.defaultValue"
:min="eleItem.options.min"
:max="eleItem.options.max"
:controls-position="eleItem.options.position"
:disabled="eleItem.options.disabled"
></el-input-number>
</template>
<!-- 下拉框 -->
<template v-if="eleItem.type === 'select'">
<el-select
v-model="eleItem.options.defaultValue"
placeholder="请选择一个选项"
:style="{ width: eleItem.options.width }"
:multiple="eleItem.options.multiple"
:clearable="eleItem.options.clearable"
:disabled="eleItem.options.disabled"
>
<el-option
v-for="item in eleItem.options.valueData"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</template>
<!-- 滑块 -->
<template v-if="eleItem.type === 'slider'">
<el-slider
v-model="eleItem.options.defaultValue"
:disabled="eleItem.options.disabled"
:min="eleItem.options.min"
:max="eleItem.options.max"
></el-slider>
</template>
<!-- 评分 -->
<template v-if="eleItem.type === 'rate'">
<el-rate
v-model="eleItem.options.defaultValue"
:max="eleItem.options.max"
:disabled="eleItem.options.disabled"
:show-text="eleItem.options.text"
style="margin-top: 6px"
></el-rate>
</template>
<!-- 时间选择器 -->
<template v-if="eleItem.type === 'timePicker'">
<el-time-picker
:style="{ width: eleItem.options.width }"
v-model="eleItem.options.defaultValue"
placeholder="选择时间"
:disabled="eleItem.options.disabled"
:clearable="eleItem.options.clearable"
:default-value="new Date()"
value-format="HH:mm:ss"
format="HH:mm:ss"
>
</el-time-picker>
</template>
<!-- 日期选择器 -->
<template v-if="eleItem.type === 'datePicker'">
<el-date-picker
v-model="eleItem.options.defaultValue"
placeholder="选择日期"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
:value-format="eleItem.options.valueFormat"
:default-value="new Date()"
:style="{ width: eleItem.options.width }"
:type="eleItem.options.type"
:disabled="eleItem.options.disabled"
:clearable="eleItem.options.clearable"
>
</el-date-picker>
</template>
<!-- 文字 -->
<template v-if="eleItem.type === 'text'">
<div
:class="{ 'form-text': listdata.config.labelPosition !== 'top' }"
:style="{
display: 'grid',
'justify-content': eleItem.options.position,
'font-size': eleItem.options.size + 'px',
color: eleItem.options.color,
'line-height': eleItem.options.lineHeight + 'px',
'font-weight': eleItem.options.weight,
}"
>
<div
:style="{
'padding-left': eleItem.options.leftPadding + 'px',
'font-style': eleItem.options.style,
'text-indent': eleItem.options.indent + 'em',
}"
>
{{ eleItem.options.defaultValue }}
</div>
</div>
</template>
<!-- 分割线 -->
<template v-if="eleItem.type === 'divider'">
<div :class="{ 'form-text': listdata.config.labelPosition !== 'top' }">
<el-divider :content-position="eleItem.options.position">
{{ eleItem.options.defaultValue }}
</el-divider>
</div>
</template>
<!-- 组件操作按钮 -->
<div class="view-operations">
<!-- 移动 -->
<div>
<el-tag effect="dark" class="movetag">
<i class="el-icon-rank"></i>
</el-tag>
</div>
<!-- 删除 -->
<div>
<el-tag effect="dark" @click="removeWidgetElement()">
<i class="el-icon-delete"></i
></el-tag>
</div>
</div>
</el-form-item>
</template>
<script>
import draggable from "vuedraggable";
export default {
components: {
draggable: draggable,
},
props: ["select", "eleItem", "eleIndex", "listdata"],
data() {
return {
selectWidget: this.select,
};
},
methods: {
// 点击不同的组件触发
handleSelectWidget() {
this.selectWidget = this.eleItem;
},
// 删除组件方法
removeWidgetElement() {
const index = this.eleIndex;
if (this.listdata.list.length - 1 === index) {
if (index === 0) {
this.selectWidget = {
key: null,
options: {
placeholder: null,
},
};
console.log(this.eleItem);
} else {
this.selectWidget = this.listdata.list[index - 1];
}
} else {
this.selectWidget = this.listdata.list[index + 1];
}
this.$nextTick(() => {
this.listdata.list.splice(index, 1);
});
},
},
watch: {
select(itemdata) {
this.selectWidget = itemdata;
},
selectWidget: {
handler(data) {
this.$emit("update:select", data);
},
},
},
};
</script>
<style scoped>
.view-operations {
display: none;
}
.widget-view {
margin-bottom: 0px !important;
}
.active {
border: 2px solid #409eff !important;
}
.active .view-operations {
position: absolute;
bottom: -5px;
right: 0;
display: flex;
cursor: pointer;
}
.grid-template {
margin-left: -100px !important;
}
.grid-template > .columns {
border: 2px solid #9999;
height: 50px;
}
.radioLineHeight {
line-height: 32px;
}
.form-text {
margin-left: -100px;
}
</style>

浙公网安备 33010602011771号