1. 成图
2. 介绍
就是简单拖拉拽来做个规则运算器,具体运算规则、校验规则自己加。
3. 代码
HTML代码
<template>
<div class="red-cont">
<div class="red-top">
<div
class="red-top-left"
>
<div class="red-showarea">
<div class="red-showarea-title">公式展示</div>
<div class="red-showarea-list">
<span
v-for="(item, index) in valueList"
:key="index"
>{{ item.label }}</span>
</div>
</div>
<div class="red-ctrlarea user-no-select">
<div class="red-ctrlarea-title">公式编辑</div>
<div
class="red-ctrlarea-list"
@drop="handleDrop"
@dragleave="handleDragLeave($event)"
@dragover.stop.prevent="handleDragOver($event)"
>
<div v-if="valueList.length === 0" class="red-ctrlarea-hint">
请拖曳字段、数字或操作符到编辑区域
</div>
<div
v-for="(item, index) in valueList"
:key="item.id"
:class="[
'red-ctrl-item',
index === draggingOverIndex - 1 ? 'red-ctrl-inject-before' : '',
index === draggingOverIndex ? 'red-ctrl-inject-after' : ''
]"
@drop.stop.prevent="handleDrop"
@dragover.stop.prevent="handleDragOver($event, index)"
>
<div
class="red-ctrl-item-cont"
draggable="true"
@dragstart="handleDragStart($event, item, item.type)"
>
<div :alt="item.label">{{ item.label }}</div>
<i
class="el-icon-circle-close red-ctrl-item-close"
@click="removeValueItem(item, index)"
/>
</div>
</div>
</div>
</div>
</div>
<div class="red-top-right user-no-select">
<div class="red-paramtype">
<el-select v-model="paramType">
<el-option
v-for="item in paramTypeOptions"
:key="item.value"
:label="item.label"
:disabled="item.disabled"
:value="item.value"
/>
</el-select>
</div>
<div class="red-paramoptions">
<div
v-for="(item, index) in paramOptions"
:key="index"
class="red-paramoptions-item"
draggable="true"
@dragstart="handleDragStart($event, item, paramType)"
>
{{ item.label }}
</div>
</div>
</div>
</div>
<div class="red-bottom user-no-select">
<div class="red-bottom-left">
<div
v-for="(item, index) in sourceList"
:key="index"
class="red-source-item"
draggable="true"
@dragstart="handleDragStart($event, item, 'ctrl')"
>
{{ item.label }}
</div>
</div>
<div
class="red-clear"
@click="clearValueList"
>清<br>空</div>
</div>
</div>
</template>
VUE2的代码
export default {
components: {},
props: {},
data() {
return {
paramType: 'field',
paramTypeOptions: [
{ value: 'field', label: '字段' },
{ value: 'attribute', label: '机组属性', disabled: true }
],
paramOptions: [
{ value: Math.random(), label: '字段1' },
{ value: Math.random(), label: '字段2' },
{ value: Math.random(), label: '字段3' },
{ value: Math.random(), label: '字段4' },
{ value: Math.random(), label: '字段5' }
],
valueList: [],
sourceList: [
{ label: '1', value: '1' },
{ label: '2', value: '2' },
{ label: '3', value: '3' },
{ label: '4', value: '4' },
{ label: '5', value: '5' },
{ label: '6', value: '6' },
{ label: '7', value: '7' },
{ label: '8', value: '8' },
{ label: '9', value: '9' },
{ label: '0', value: '0' },
{ label: '00', value: '00' },
{ label: '(', value: '(' },
{ label: ')', value: ')' },
{ label: '.', value: '.' },
{ label: '+', value: '+' },
{ label: '-', value: '-' },
{ label: '*', value: '*' },
{ label: '/', value: '/' },
{ label: '>', value: '>' },
{ label: '<', value: '<' },
{ label: '==', value: '==' },
{ label: '>=', value: '>=' },
{ label: '<=', value: '<=' },
{ label: '!', value: '!' },
{ label: '||', value: '||' },
{ label: '&&', value: '&&' }
],
draggingIndex: null,
draggingOverIndex: null
};
},
created() {},
methods: {
clearValueList() {
this.valueList.splice(0, this.valueList.length);
},
handleDragLeave(e) {
console.log('tree drag leave: ', e);
this.draggingOverIndex = null;
},
handleDrop(e) {
const data = JSON.parse(e.dataTransfer.getData('text/plain'));
const { valueList, draggingOverIndex } = this;
const item = Object.assign({}, data, {
id: Math.random().toString(36).substr(2, 9)
});
if (typeof draggingOverIndex === 'number') {
valueList.splice(draggingOverIndex, 0, item);
const dataIndex = valueList.findIndex(item => item.id === data.id);
if (dataIndex !== -1) {
valueList.splice(dataIndex, 1);
} else {
//
}
} else {
const dataIndex = valueList.findIndex(item => item.id === data.id);
if (dataIndex !== -1) {
valueList.splice(dataIndex, 1);
} else {
//
}
valueList.push(item);
}
this.draggingOverIndex = null;
},
handleDragOver(e, targetIndex) {
console.log('handleDragOver', e, targetIndex);
this.draggingOverIndex = targetIndex;
},
handleDragStart(e, item, type) {
e.dataTransfer.setData('text/plain', JSON.stringify(Object.assign({
type: type
}, item)));
},
removeValueItem(item, index) {
this.valueList.splice(index, 1);
}
}
};
less/scss代码
.red-cont{
display: flex;
height: 100%;
overflow: hidden;
flex-direction: column;
}
.red-top{
flex: 1;
overflow: hidden;
display: flex;
align-items: stretch;
justify-content: space-between;
}
.red-top-left{
flex: 1;
overflow: hidden;
}
.red-showarea{
display: flex;
flex-direction: column;
height: 35%;
}
.red-showarea-title{
flex-shrink: 0;
}
.red-showarea-list{
flex: 1;
overflow: auto;
padding: 10px;
}
.red-ctrlarea{
display: flex;
flex-direction: column;
height: 65%;
}
.red-ctrlarea-title{
flex-shrink: 0;
}
.red-ctrlarea-hint{
padding: 10px;
color: #ccc;
}
.red-ctrlarea-list{
flex: 1;
overflow-x: hidden;
overflow-y: auto;
border: 1px dashed #ccc;
display: flex;
flex-wrap: wrap;
align-content: flex-start;
}
.red-ctrl-item{
padding-left: 10px;
padding-top: 10px;
max-width: 200px;
}
.red-ctrl-inject-before{
&>.red-ctrl-item-cont{
border-right: 1px dashed #ccc;
}
}
.red-ctrl-inject-after{
&>.red-ctrl-item-cont{
border-left: 1px dashed #ccc;
}
}
.red-ctrl-item-cont{
padding: 5px;
position: relative;
cursor: grab;
border: 1px solid transparent;
&>div{
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
.red-ctrl-item-close{
position: absolute;
top: -5px;
right: -5px;
cursor: pointer;
}
.red-paramtype{
flex-shrink: 0;
padding: 10px;
.el-select{
width: 100%;
}
}
.red-paramoptions{
flex: 1;
padding: 10px;
overflow: auto;
}
.red-paramoptions-item{
padding: 5px;
cursor: grab;
&:hover{
background-color: #ccc;
}
}
.red-bottom{
flex-shrink: 0;
height: 200px;
display: flex;
align-items: center;
}
.red-bottom-left{
flex: 1;
display: flex;
flex-wrap: wrap;
padding: 1px;
}
.red-clear{
padding: 10px;
border: 1px solid #fff;
cursor: grab;
}
.red-source-item{
width: 50px;
height: 50px;
line-height: 50px;
text-align: center;
margin: 5px;
background-color: #ccc;
cursor: grab;
}