表单构建
This commit is contained in:
parent
b363f2ffaa
commit
62b0743abd
|
|
@ -4,7 +4,8 @@
|
||||||
<el-main class="h100">
|
<el-main class="h100">
|
||||||
<el-form class="h100" :label-position="config.labelPosition" :label-width="config.labelWidth"
|
<el-form class="h100" :label-position="config.labelPosition" :label-width="config.labelWidth"
|
||||||
:size="config.size" :disabled="config.disabled">
|
:size="config.size" :disabled="config.disabled">
|
||||||
<drag :fields="fields" @change="changeHandle" name="page" v-model:curId="curId"/>
|
<drag :fields="fields" @change="changeHandle" name="page" v-model:curKey="curKey"
|
||||||
|
v-model:counter="counter"/>
|
||||||
</el-form>
|
</el-form>
|
||||||
</el-main>
|
</el-main>
|
||||||
</el-scrollbar>
|
</el-scrollbar>
|
||||||
|
|
@ -12,16 +13,27 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import {ref} from "vue"
|
import {computed, ref} from "vue"
|
||||||
import drag from "./drag.vue"
|
import drag from "./drag.vue"
|
||||||
|
|
||||||
defineExpose({clickAddComp})
|
defineExpose({clickAddComp})
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
fields: {type: Array, default: []},
|
fields: {type: Array, default: []},
|
||||||
config: {type: Object, default: {}}
|
config: {type: Object, default: {}},
|
||||||
|
counter: {type: Number, default: 0}
|
||||||
|
})
|
||||||
|
const emit = defineEmits(['change', "update:counter"])
|
||||||
|
let curKey = ref("")
|
||||||
|
|
||||||
|
const counter = computed({
|
||||||
|
get() {
|
||||||
|
return props.counter
|
||||||
|
},
|
||||||
|
set(value) {
|
||||||
|
emit('update:counter', value)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
const emit = defineEmits(['change'])
|
|
||||||
let curId = ref("")
|
|
||||||
|
|
||||||
// 添加项时
|
// 添加项时
|
||||||
function clickAddComp(e) {
|
function clickAddComp(e) {
|
||||||
|
|
|
||||||
|
|
@ -188,6 +188,7 @@ export const fieldEditors = {
|
||||||
{key: 'props.disabled', label: '是否禁用', type: 'switch'},
|
{key: 'props.disabled', label: '是否禁用', type: 'switch'},
|
||||||
],
|
],
|
||||||
button: [
|
button: [
|
||||||
|
{key: 'labelWidth', label: '标签宽度', type: 'number'},
|
||||||
{key: 'btnText', label: '按钮文字', type: 'input'},
|
{key: 'btnText', label: '按钮文字', type: 'input'},
|
||||||
{
|
{
|
||||||
key: 'props.type', label: '按钮类型', type: 'select', options: [
|
key: 'props.type', label: '按钮类型', type: 'select', options: [
|
||||||
|
|
@ -205,6 +206,9 @@ export const fieldEditors = {
|
||||||
{key: 'props.round', label: '圆角按钮', type: 'switch'},
|
{key: 'props.round', label: '圆角按钮', type: 'switch'},
|
||||||
{key: 'props.circle', label: '圆形按钮', type: 'switch'},
|
{key: 'props.circle', label: '圆形按钮', type: 'switch'},
|
||||||
{key: 'props.disabled', label: '是否禁用', type: 'switch'},
|
{key: 'props.disabled', label: '是否禁用', type: 'switch'},
|
||||||
|
],
|
||||||
|
layout: [
|
||||||
|
{key: 'props.gutter', label: '分栏间隔', type: 'number'},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
// 'year' | 'years' |'month' | 'months' | 'date' | 'dates' | 'datetime' | 'week' | 'datetimerange' | 'daterange' | 'monthrange' | 'yearrange'
|
// 'year' | 'years' |'month' | 'months' | 'date' | 'dates' | 'datetime' | 'week' | 'datetimerange' | 'daterange' | 'monthrange' | 'yearrange'
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,26 @@
|
||||||
<template>
|
<template>
|
||||||
<draggable :list="fields" :scroll="true" animation="200" item-key="id" class="w100 h100"
|
<draggable :list="fields" :scroll="true" animation="200" item-key="id" class="w100 h100"
|
||||||
:group="group" @update:list="fields = $event" @add="addComp" @sort="sortComp"
|
:group="group" @update:list="fields = $event" @add="addComp" @sort="sortComp"
|
||||||
ghostClass="ghostClass" :class="{empty: fields.length === 0}">
|
ghostClass="ghostClass" :class="{empty: fields.length === 0, layout: isRow}">
|
||||||
<template #item="{ element, index }">
|
<template #item="{ element, index }">
|
||||||
<div class="box w100">
|
<el-col :span="element.span || 24" class="col">
|
||||||
<el-row v-if="element.name === 'layout'" class="item row" :class="{'active': curr===element.field}"
|
<el-row v-if="element.name === 'layout'" class="item row" :class="{'active': curr===element.id}"
|
||||||
@click.stop="clickComp(element)" v-bind="element.props">
|
@click.stop="clickComp(element)" v-bind="element.props">
|
||||||
<span class="name">{{ element.field }}</span>
|
<span class="name">{{ element.field_name }}</span>
|
||||||
<drag :fields="element.children" @change="changeHandle" :name="element.field" v-model:curId="curr"/>
|
<drag :fields="element.children" v-model:curKey="curr" :name="element.field_name"
|
||||||
|
:is-row="true" v-model:counter="counter" @change="changeHandle"/>
|
||||||
</el-row>
|
</el-row>
|
||||||
<item v-else class="item" :class="{'active': curr===element.field}" :field="element"
|
<item v-else class="item" :class="{'active': curr===element.id}" :field="element"
|
||||||
@click.stop="clickComp(element)"/>
|
@click.stop="clickComp(element)"/>
|
||||||
<div v-if="curr===element.field" class="tools-box">
|
<div v-if="curr===element.id" class="tools-box">
|
||||||
<el-icon size="22" class="icon-box remove" @click="delComp(index)">
|
<el-icon size="22" class="icon-box remove" @click.stop="delComp(index)">
|
||||||
<component :is="'pi-icon-shan-chu'"/>
|
<component :is="'pi-icon-shan-chu'"/>
|
||||||
</el-icon>
|
</el-icon>
|
||||||
<el-icon size="20" class="icon-box copy ml5" @click="copyComp(index)">
|
<el-icon size="20" class="icon-box copy ml5" @click.stop="copyComp(index)">
|
||||||
<component :is="'pi-icon-fu-zhi'"/>
|
<component :is="'pi-icon-fu-zhi'"/>
|
||||||
</el-icon>
|
</el-icon>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</el-col>
|
||||||
</template>
|
</template>
|
||||||
</draggable>
|
</draggable>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -27,25 +28,36 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import draggable from 'vuedraggable'
|
import draggable from 'vuedraggable'
|
||||||
import {computed, nextTick} from "vue"
|
import {computed, nextTick} from "vue"
|
||||||
import tools from "@/utils/tools"
|
|
||||||
import item from "./item.vue"
|
import item from "./item.vue"
|
||||||
import drag from "./drag.vue"
|
import drag from "./drag.vue"
|
||||||
|
import tools from "@/utils/tools.js"
|
||||||
|
|
||||||
const emit = defineEmits(['change', 'update:curId'])
|
const emit = defineEmits(['change', 'update:curKey', 'update:counter'])
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
fields: {type: Array, default: []},
|
fields: {type: Array, default: []},
|
||||||
name: {type: String, default: 'page'},
|
curKey: {type: String, default: ''},
|
||||||
curId: {type: String, default: ''},
|
isRow: {type: Boolean, default: false},
|
||||||
|
counter: {type: Number, default: 0},
|
||||||
|
name: {type: String, default: 'page'}
|
||||||
})
|
})
|
||||||
|
|
||||||
const group = {name: props.name, pull: true, put: true}
|
const group = {name: props.name, pull: true, put: true}
|
||||||
const curr = computed({
|
const curr = computed({
|
||||||
get() {
|
get() {
|
||||||
return props.curId
|
return props.curKey
|
||||||
},
|
},
|
||||||
set(value) {
|
set(value) {
|
||||||
emit('update:curId', value)
|
emit('update:curKey', value)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const counter = computed({
|
||||||
|
get() {
|
||||||
|
return props.counter
|
||||||
|
},
|
||||||
|
set(value) {
|
||||||
|
emit('update:counter', value)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -53,7 +65,7 @@ const curr = computed({
|
||||||
function sortComp(e) {
|
function sortComp(e) {
|
||||||
let element = props.fields[e.newIndex]
|
let element = props.fields[e.newIndex]
|
||||||
if (element) {
|
if (element) {
|
||||||
curr.value = element.field
|
curr.value = element.id
|
||||||
emit('change', element)
|
emit('change', element)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -61,16 +73,19 @@ function sortComp(e) {
|
||||||
// 添加项时
|
// 添加项时
|
||||||
function addComp(e) {
|
function addComp(e) {
|
||||||
let element = props.fields[e.newIndex]
|
let element = props.fields[e.newIndex]
|
||||||
curr.value = element.field
|
if (props.isRow) {
|
||||||
|
element.span = 12
|
||||||
|
}
|
||||||
|
curr.value = element.id
|
||||||
emit('change', element)
|
emit('change', element)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 选中项
|
// 选中项
|
||||||
function clickComp(element) {
|
function clickComp(element) {
|
||||||
if (curr.value === element.field) {
|
if (curr.value === element.id) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
curr.value = element.field
|
curr.value = element.id
|
||||||
emit('change', element)
|
emit('change', element)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -91,7 +106,7 @@ function delComp(index) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let element = props.fields[i] || {}
|
let element = props.fields[i] || {}
|
||||||
curr.value = element.field || null
|
curr.value = element.id || null
|
||||||
emit('change', element)
|
emit('change', element)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -100,23 +115,21 @@ function copyComp(index) {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
// 复制当前元素到尾部
|
// 复制当前元素到尾部
|
||||||
const tmp = JSON.parse(JSON.stringify(props.fields[index]))
|
const tmp = JSON.parse(JSON.stringify(props.fields[index]))
|
||||||
tmp.field = increaseNum(tmp.field)
|
tmp.field_name = increaseNum(tmp.field_name)
|
||||||
|
tmp.id = increaseNum(tmp.id)
|
||||||
|
counter.value++
|
||||||
props.fields.push(tmp)
|
props.fields.push(tmp)
|
||||||
// 将复制的元素移动到当前元素下边
|
// 将复制的元素移动到当前元素下边
|
||||||
tools.array.zIndexTo(props.fields, props.fields.length - 1, index + 1)
|
tools.array.zIndexTo(props.fields, props.fields.length - 1, index + 1)
|
||||||
let element = props.fields[index + 1]
|
let element = props.fields[index + 1]
|
||||||
element.field = increaseNum(element.field)
|
curr.value = element.id
|
||||||
curr.value = element.field
|
|
||||||
emit('change', element)
|
emit('change', element)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function increaseNum(str) {
|
function increaseNum(str) {
|
||||||
return str.replace(/(\d+)(?!.*\d)/, (match) => {
|
return str.replace(/(\d+)(?!.*\d)/, () => {
|
||||||
// 处理前导 0
|
return props.counter.toString();
|
||||||
const len = match.length;
|
|
||||||
const num = (parseInt(match, 10) + 1).toString();
|
|
||||||
return num.padStart(len, '0');
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -139,6 +152,10 @@ function changeHandle(e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:deep(.el-form-item,.el-form-item--default) {
|
||||||
|
margin-bottom: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
.w100 {
|
.w100 {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
@ -149,6 +166,11 @@ function changeHandle(e) {
|
||||||
|
|
||||||
.empty {
|
.empty {
|
||||||
padding: 40px 0;
|
padding: 40px 0;
|
||||||
|
display: block !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout {
|
||||||
|
display: contents;
|
||||||
}
|
}
|
||||||
|
|
||||||
.active {
|
.active {
|
||||||
|
|
@ -156,61 +178,60 @@ function changeHandle(e) {
|
||||||
color: #787be8;
|
color: #787be8;
|
||||||
}
|
}
|
||||||
|
|
||||||
.box {
|
.col {
|
||||||
position: relative;
|
position: relative;
|
||||||
cursor: pointer;
|
}
|
||||||
|
|
||||||
.item {
|
.item {
|
||||||
padding: 12px 10px;
|
padding: 12px 10px;
|
||||||
border: 1px;
|
border: 1px;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
margin-bottom: 18px !important;
|
||||||
|
}
|
||||||
|
|
||||||
.row {
|
.row {
|
||||||
border: 1px dashed #c1c1c1;
|
border: 1px dashed #c1c1c1;
|
||||||
margin-bottom: 18px;
|
padding: 20px 12px;
|
||||||
padding: 20px 12px;
|
|
||||||
|
|
||||||
.name {
|
.name {
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
font-size: 12px;
|
|
||||||
color: #bbb;
|
|
||||||
display: inline-block;
|
|
||||||
padding: 0 6px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.tools-box {
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 10px;
|
top: 0;
|
||||||
top: -16px;
|
left: 0;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #bbb;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 5px;
|
padding: 0 6px;
|
||||||
border-radius: 4px;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.icon-box {
|
.tools-box {
|
||||||
cursor: pointer;
|
position: absolute;
|
||||||
}
|
right: 10px;
|
||||||
|
top: -16px;
|
||||||
|
display: inline-block;
|
||||||
|
padding: 5px;
|
||||||
|
border-radius: 4px;
|
||||||
|
|
||||||
.icon-box.remove {
|
.icon-box {
|
||||||
color: var(--el-color-danger);
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-box.copy {
|
.icon-box.remove {
|
||||||
color: var(--el-color-primary);
|
color: var(--el-color-danger);
|
||||||
}
|
}
|
||||||
|
|
||||||
.ml5 {
|
.icon-box.copy {
|
||||||
margin-left: 5px;
|
color: var(--el-color-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.disabled {
|
.ml5 {
|
||||||
cursor: no-drop;
|
margin-left: 5px;
|
||||||
color: #c3c3c3;
|
}
|
||||||
}
|
|
||||||
|
.disabled {
|
||||||
|
cursor: no-drop;
|
||||||
|
color: #c3c3c3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
<template>
|
<template>
|
||||||
<el-container class="pi-panel">
|
<el-container class="pi-panel">
|
||||||
<el-main class="main">
|
<el-main class="main">
|
||||||
<left-panel @addField="addField"></left-panel>
|
<left-panel @addField="addField" v-model:counter="counter"></left-panel>
|
||||||
<el-divider direction="vertical" style="height: 100%"/>
|
<el-divider direction="vertical" style="height: 100%"/>
|
||||||
<center-panel ref="centerRef" :fields="fields" :config="config" @change="setField"></center-panel>
|
<center-panel ref="centerRef" :fields="fields" :config="config" @change="setField"
|
||||||
|
v-model:counter="counter"></center-panel>
|
||||||
<el-divider direction="vertical" style="height: 100%"/>
|
<el-divider direction="vertical" style="height: 100%"/>
|
||||||
<right-panel :config="config" :curField="curField" @save="tempSave"></right-panel>
|
<right-panel :config="config" :curField="curField" @save="tempSave"></right-panel>
|
||||||
</el-main>
|
</el-main>
|
||||||
|
|
@ -30,14 +31,19 @@ let config = ref({
|
||||||
disabled: false
|
disabled: false
|
||||||
})
|
})
|
||||||
let curField = ref({})
|
let curField = ref({})
|
||||||
|
let counter = ref(0)
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
fields.value = tools.data.get("FORM-DATA") || []
|
fields.value = tools.data.get("FORM-FIELDS-DATA") || []
|
||||||
|
const _config = tools.data.get("FORM-CONFIG-DATA")
|
||||||
|
if (_config) {
|
||||||
|
config.value = _config
|
||||||
|
}
|
||||||
|
counter.value = tools.data.get("FORM-COUNTER-DATA") || 0
|
||||||
})
|
})
|
||||||
|
|
||||||
function setField(v) {
|
function setField(v) {
|
||||||
curField.value = v
|
curField.value = v
|
||||||
curField.value.field = v.id
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function addField(e) {
|
function addField(e) {
|
||||||
|
|
@ -46,7 +52,9 @@ function addField(e) {
|
||||||
|
|
||||||
function tempSave() {
|
function tempSave() {
|
||||||
console.log("保存参数", fields.value)
|
console.log("保存参数", fields.value)
|
||||||
tools.data.set("FORM-DATA", fields.value)
|
tools.data.set("FORM-FIELDS-DATA", fields.value)
|
||||||
|
tools.data.set("FORM-CONFIG-DATA", config.value)
|
||||||
|
tools.data.set("FORM-COUNTER-DATA", counter.value)
|
||||||
proxy.$message.success("保存成功")
|
proxy.$message.success("保存成功")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<el-form-item :label="field.title" :required="field.required">
|
<el-form-item :label="field.title" :required="field.required" :label-width="field.labelWidth">
|
||||||
<component :is="getComponent(field.name)" v-model="field.value" v-bind="field.props"
|
<component :is="getComponent(field.name)" v-model="field.value" v-bind="field.props"
|
||||||
:style="{width: field.width}">
|
:style="{width: field.width}">
|
||||||
<template v-if="field.name === 'select'" #default>
|
<template v-if="field.name === 'select'" #default>
|
||||||
|
|
@ -13,7 +13,8 @@
|
||||||
<template v-else-if="field.name === 'checkbox'" #default>
|
<template v-else-if="field.name === 'checkbox'" #default>
|
||||||
<el-checkbox-button v-if="field.style === 'button'" v-for="(op, idx) in field.options" :key="idx"
|
<el-checkbox-button v-if="field.style === 'button'" v-for="(op, idx) in field.options" :key="idx"
|
||||||
:label="op.label" :value="op.value"/>
|
:label="op.label" :value="op.value"/>
|
||||||
<el-checkbox v-else v-for="(op, id) in field.options" :key="id" :label="op.label" :value="op.value"/>
|
<el-checkbox v-else v-for="(op, id) in field.options" :key="id" :label="op.label"
|
||||||
|
:value="op.value"/>
|
||||||
</template>
|
</template>
|
||||||
<template
|
<template
|
||||||
v-if="field.name === 'upload' && (field.props.listType === 'text' || field.props.listType === 'picture')"
|
v-if="field.name === 'upload' && (field.props.listType === 'text' || field.props.listType === 'picture')"
|
||||||
|
|
@ -33,8 +34,7 @@
|
||||||
{{ field.tip }}
|
{{ field.tip }}
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-if="field.name === 'button' && field.btnText"
|
<template v-if="field.name === 'button' && field.btnText" #default>
|
||||||
#default>
|
|
||||||
{{ field.btnText }}
|
{{ field.btnText }}
|
||||||
</template>
|
</template>
|
||||||
</component>
|
</component>
|
||||||
|
|
@ -49,6 +49,6 @@ const props = defineProps({
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
输入组件
|
输入组件
|
||||||
</el-text>
|
</el-text>
|
||||||
</div>
|
</div>
|
||||||
<draggable v-model="inputComps" animation="200" item-key="id" class="go-base" :group="group" :sort="false"
|
<draggable v-model="inputComps" animation="200" item-key="name" class="go-base" :group="group" :sort="false"
|
||||||
:clone="cloneField">
|
:clone="cloneField">
|
||||||
<template #item="{ element }">
|
<template #item="{ element }">
|
||||||
<div class="item" @click="handleClick(element)">
|
<div class="item" @click="handleClick(element)">
|
||||||
|
|
@ -31,7 +31,7 @@
|
||||||
选择组件
|
选择组件
|
||||||
</el-text>
|
</el-text>
|
||||||
</div>
|
</div>
|
||||||
<draggable v-model="choiceComps" animation="200" item-key="id" class="go-base" :group="group" :sort="false"
|
<draggable v-model="choiceComps" animation="200" item-key="name" class="go-base" :group="group" :sort="false"
|
||||||
:clone="cloneField">
|
:clone="cloneField">
|
||||||
<template #item="{ element }">
|
<template #item="{ element }">
|
||||||
<div class="item" @click="handleClick(element)">
|
<div class="item" @click="handleClick(element)">
|
||||||
|
|
@ -53,7 +53,7 @@
|
||||||
布局组件
|
布局组件
|
||||||
</el-text>
|
</el-text>
|
||||||
</div>
|
</div>
|
||||||
<draggable v-model="layoutComps" animation="200" item-key="id" class="go-base" :group="group" :sort="false"
|
<draggable v-model="layoutComps" animation="200" item-key="name" class="go-base" :group="group" :sort="false"
|
||||||
:clone="cloneField">
|
:clone="cloneField">
|
||||||
<template #item="{ element }">
|
<template #item="{ element }">
|
||||||
<div class="item" @click="handleClick(element)">
|
<div class="item" @click="handleClick(element)">
|
||||||
|
|
@ -73,13 +73,15 @@
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import draggable from 'vuedraggable'
|
import draggable from 'vuedraggable'
|
||||||
import {ref} from "vue"
|
import {computed, ref} from "vue"
|
||||||
|
|
||||||
const emit = defineEmits(['addField'])
|
const emit = defineEmits(['addField', 'update:counter'])
|
||||||
|
const props = defineProps({
|
||||||
|
counter: {type: Number, default: 0}
|
||||||
|
})
|
||||||
|
|
||||||
const group = {name: 'base', pull: 'clone', put: false}
|
const group = {name: 'base', pull: 'clone', put: false}
|
||||||
const inputComps = [{
|
const inputComps = [{
|
||||||
id: "i1",
|
|
||||||
title: "单行文本",
|
title: "单行文本",
|
||||||
icon: "pi-icon-line-input",
|
icon: "pi-icon-line-input",
|
||||||
name: "text",
|
name: "text",
|
||||||
|
|
@ -90,7 +92,6 @@ const inputComps = [{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
required: false
|
required: false
|
||||||
}, {
|
}, {
|
||||||
id: "i2",
|
|
||||||
title: "多行文本",
|
title: "多行文本",
|
||||||
icon: "pi-icon-multi-input",
|
icon: "pi-icon-multi-input",
|
||||||
name: "textarea",
|
name: "textarea",
|
||||||
|
|
@ -101,7 +102,6 @@ const inputComps = [{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
required: false
|
required: false
|
||||||
}, {
|
}, {
|
||||||
id: "i3",
|
|
||||||
title: "密码",
|
title: "密码",
|
||||||
icon: "pi-icon-lock",
|
icon: "pi-icon-lock",
|
||||||
name: "password",
|
name: "password",
|
||||||
|
|
@ -113,7 +113,6 @@ const inputComps = [{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
required: false
|
required: false
|
||||||
}, {
|
}, {
|
||||||
id: "i4",
|
|
||||||
title: "计数器",
|
title: "计数器",
|
||||||
icon: "pi-icon-number-input",
|
icon: "pi-icon-number-input",
|
||||||
name: "number",
|
name: "number",
|
||||||
|
|
@ -126,7 +125,6 @@ const inputComps = [{
|
||||||
value: 1
|
value: 1
|
||||||
}]
|
}]
|
||||||
const choiceComps = [{
|
const choiceComps = [{
|
||||||
id: "c1",
|
|
||||||
title: "下拉组件",
|
title: "下拉组件",
|
||||||
icon: "pi-icon-select",
|
icon: "pi-icon-select",
|
||||||
name: "select",
|
name: "select",
|
||||||
|
|
@ -136,7 +134,6 @@ const choiceComps = [{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
required: false,
|
required: false,
|
||||||
}, {
|
}, {
|
||||||
id: "c2",
|
|
||||||
title: "级联组件",
|
title: "级联组件",
|
||||||
icon: "pi-icon-cascader",
|
icon: "pi-icon-cascader",
|
||||||
name: "cascader",
|
name: "cascader",
|
||||||
|
|
@ -152,7 +149,6 @@ const choiceComps = [{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
required: false,
|
required: false,
|
||||||
}, {
|
}, {
|
||||||
id: "c3",
|
|
||||||
title: "单选组件",
|
title: "单选组件",
|
||||||
icon: "pi-icon-radio",
|
icon: "pi-icon-radio",
|
||||||
name: "radio",
|
name: "radio",
|
||||||
|
|
@ -163,7 +159,6 @@ const choiceComps = [{
|
||||||
style: '',
|
style: '',
|
||||||
required: false,
|
required: false,
|
||||||
}, {
|
}, {
|
||||||
id: "c4",
|
|
||||||
title: "多选组件",
|
title: "多选组件",
|
||||||
icon: "pi-icon-checkbox",
|
icon: "pi-icon-checkbox",
|
||||||
name: "checkbox",
|
name: "checkbox",
|
||||||
|
|
@ -173,7 +168,6 @@ const choiceComps = [{
|
||||||
style: '',
|
style: '',
|
||||||
required: false,
|
required: false,
|
||||||
}, {
|
}, {
|
||||||
id: "c5",
|
|
||||||
title: "开关",
|
title: "开关",
|
||||||
icon: "pi-icon-switch",
|
icon: "pi-icon-switch",
|
||||||
name: "switch",
|
name: "switch",
|
||||||
|
|
@ -181,7 +175,6 @@ const choiceComps = [{
|
||||||
rules: [],
|
rules: [],
|
||||||
required: false,
|
required: false,
|
||||||
}, {
|
}, {
|
||||||
id: "c6",
|
|
||||||
title: "滑块",
|
title: "滑块",
|
||||||
icon: "pi-icon-slider",
|
icon: "pi-icon-slider",
|
||||||
name: "slider",
|
name: "slider",
|
||||||
|
|
@ -190,7 +183,6 @@ const choiceComps = [{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
required: false,
|
required: false,
|
||||||
}, {
|
}, {
|
||||||
id: "c7",
|
|
||||||
title: "时间选择",
|
title: "时间选择",
|
||||||
icon: "pi-icon-time-picker",
|
icon: "pi-icon-time-picker",
|
||||||
name: "time",
|
name: "time",
|
||||||
|
|
@ -200,7 +192,6 @@ const choiceComps = [{
|
||||||
},
|
},
|
||||||
rules: []
|
rules: []
|
||||||
}, {
|
}, {
|
||||||
id: "c8",
|
|
||||||
title: "时间范围",
|
title: "时间范围",
|
||||||
icon: "pi-icon-time-range",
|
icon: "pi-icon-time-range",
|
||||||
name: "timerange",
|
name: "timerange",
|
||||||
|
|
@ -213,7 +204,6 @@ const choiceComps = [{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
required: false,
|
required: false,
|
||||||
}, {
|
}, {
|
||||||
id: "c9",
|
|
||||||
title: "日期选择",
|
title: "日期选择",
|
||||||
icon: "pi-icon-date-picker",
|
icon: "pi-icon-date-picker",
|
||||||
name: "date",
|
name: "date",
|
||||||
|
|
@ -226,7 +216,6 @@ const choiceComps = [{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
required: false,
|
required: false,
|
||||||
}, {
|
}, {
|
||||||
id: "c10",
|
|
||||||
title: "日期范围",
|
title: "日期范围",
|
||||||
icon: "pi-icon-date-range",
|
icon: "pi-icon-date-range",
|
||||||
name: "daterange",
|
name: "daterange",
|
||||||
|
|
@ -239,7 +228,6 @@ const choiceComps = [{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
required: false,
|
required: false,
|
||||||
}, {
|
}, {
|
||||||
id: "c11",
|
|
||||||
title: "评分",
|
title: "评分",
|
||||||
icon: "pi-icon-rate",
|
icon: "pi-icon-rate",
|
||||||
name: "rate",
|
name: "rate",
|
||||||
|
|
@ -247,7 +235,6 @@ const choiceComps = [{
|
||||||
rules: [],
|
rules: [],
|
||||||
required: false,
|
required: false,
|
||||||
}, {
|
}, {
|
||||||
id: "c12",
|
|
||||||
title: "颜色选择",
|
title: "颜色选择",
|
||||||
icon: "pi-icon-color-picker",
|
icon: "pi-icon-color-picker",
|
||||||
name: "color",
|
name: "color",
|
||||||
|
|
@ -255,7 +242,6 @@ const choiceComps = [{
|
||||||
rules: [],
|
rules: [],
|
||||||
required: false,
|
required: false,
|
||||||
}, {
|
}, {
|
||||||
id: 'c13',
|
|
||||||
title: "上传",
|
title: "上传",
|
||||||
icon: "pi-icon-upload-file",
|
icon: "pi-icon-upload-file",
|
||||||
name: "upload",
|
name: "upload",
|
||||||
|
|
@ -268,7 +254,6 @@ const choiceComps = [{
|
||||||
btnText: "点击上传"
|
btnText: "点击上传"
|
||||||
}]
|
}]
|
||||||
const layoutComps = [{
|
const layoutComps = [{
|
||||||
id: 'row',
|
|
||||||
title: "行容器",
|
title: "行容器",
|
||||||
icon: "pi-icon-row-layout",
|
icon: "pi-icon-row-layout",
|
||||||
name: "layout",
|
name: "layout",
|
||||||
|
|
@ -277,7 +262,6 @@ const layoutComps = [{
|
||||||
},
|
},
|
||||||
children: []
|
children: []
|
||||||
}, {
|
}, {
|
||||||
id: 'l2',
|
|
||||||
title: "按钮",
|
title: "按钮",
|
||||||
icon: "pi-icon-button",
|
icon: "pi-icon-button",
|
||||||
name: "button",
|
name: "button",
|
||||||
|
|
@ -286,13 +270,20 @@ const layoutComps = [{
|
||||||
},
|
},
|
||||||
btnText: "按钮文字"
|
btnText: "按钮文字"
|
||||||
}];
|
}];
|
||||||
let num = ref(100)
|
const counter = computed({
|
||||||
|
get() {
|
||||||
|
return props.counter
|
||||||
|
},
|
||||||
|
set(value) {
|
||||||
|
emit('update:counter', value)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
function cloneField(e) {
|
function cloneField(e) {
|
||||||
const field = JSON.parse(JSON.stringify(e));
|
const field = JSON.parse(JSON.stringify(e));
|
||||||
field.id = field.id + num.value;
|
field.field_name = field.name + "_" + counter.value;
|
||||||
field.index = num.value
|
field.id = field.name + counter.value
|
||||||
num.value++
|
counter.value++
|
||||||
return field
|
return field
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,15 +4,18 @@
|
||||||
<el-tabs v-model="activeName" stretch>
|
<el-tabs v-model="activeName" stretch>
|
||||||
<el-tab-pane label="组件属性" name="field">
|
<el-tab-pane label="组件属性" name="field">
|
||||||
<el-form v-model="fForm" label-width="90px">
|
<el-form v-model="fForm" label-width="90px">
|
||||||
<el-form-item v-if="fForm.name !== 'button'" label="字段名" prop="field">
|
<el-form-item v-if="fForm.name !== 'button' && fForm.name !== 'layout'" label="字段名" prop="field_name">
|
||||||
<el-input v-model="fForm.field"></el-input>
|
<el-input v-model="fForm.field_name"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="标题" prop="title">
|
<el-form-item v-if="fForm.name !== 'layout'" label="标题" prop="title">
|
||||||
<el-input v-model="fForm.title"></el-input>
|
<el-input v-model="fForm.title"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item v-if="fForm.name !== 'button'" label="默认值" prop="value">
|
<el-form-item v-if="fForm.name !== 'button' && fForm.name !== 'layout'" label="默认值" prop="value">
|
||||||
<el-input v-model="fForm.value"></el-input>
|
<el-input v-model="fForm.value"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item v-if="fForm.span !== undefined" label="栅格列数" prop="span">
|
||||||
|
<el-slider v-model="fForm.span" :min="1" :max="24"/>
|
||||||
|
</el-form-item>
|
||||||
<template v-for="item in fieldEditors[fForm.name] || []" :key="item.key">
|
<template v-for="item in fieldEditors[fForm.name] || []" :key="item.key">
|
||||||
<el-form-item :label="item.label">
|
<el-form-item :label="item.label">
|
||||||
<el-input
|
<el-input
|
||||||
|
|
@ -69,17 +72,19 @@
|
||||||
</template>
|
</template>
|
||||||
</pi-draggable>
|
</pi-draggable>
|
||||||
</template>
|
</template>
|
||||||
<el-divider>正则校验</el-divider>
|
<template v-if="fForm.name !== 'button' && fForm.name !== 'layout'">
|
||||||
<pi-draggable v-model="fForm.rules" item-key="regex" :template="{regex:'',message:''}">
|
<el-divider>正则校验</el-divider>
|
||||||
<template #default="scope">
|
<pi-draggable v-model="fForm.rules" item-key="regex" :template="{regex:'',message:''}">
|
||||||
<el-form-item label="表达式">
|
<template #default="scope">
|
||||||
<el-input v-model="scope.element.regex"/>
|
<el-form-item label="表达式">
|
||||||
</el-form-item>
|
<el-input v-model="scope.element.regex"/>
|
||||||
<el-form-item label="错误提示">
|
</el-form-item>
|
||||||
<el-input v-model="scope.element.message"/>
|
<el-form-item label="错误提示">
|
||||||
</el-form-item>
|
<el-input v-model="scope.element.message"/>
|
||||||
</template>
|
</el-form-item>
|
||||||
</pi-draggable>
|
</template>
|
||||||
|
</pi-draggable>
|
||||||
|
</template>
|
||||||
</el-form>
|
</el-form>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane label="表单属性" name="form">
|
<el-tab-pane label="表单属性" name="form">
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue