This commit is contained in:
parent
d91c90a685
commit
1121cb1664
|
|
@ -49,7 +49,7 @@ const value = computed({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
function remove(element, index) {
|
function remove(index) {
|
||||||
value.value.splice(index, 1)
|
value.value.splice(index, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,10 @@
|
||||||
<component :is="'pi-icon-json'"/>
|
<component :is="'pi-icon-json'"/>
|
||||||
</el-icon>
|
</el-icon>
|
||||||
</section>
|
</section>
|
||||||
<el-scrollbar style="height: calc(100% - 20px);" :class="{mobile: data.config.isMobile}">
|
<el-scrollbar style="height: calc(100% - 30px);" :class="{mobile: data.config.isMobile}">
|
||||||
<el-form class="h100 pad10" :label-position="data.config.labelPosition"
|
<el-form class="h100 pad10" :label-position="data.config.labelPosition"
|
||||||
:label-width="data.config.labelWidth" :size="data.config.size" :disabled="data.config.disabled">
|
:label-width="data.config.labelWidth" :size="data.config.size" :disabled="data.config.disabled">
|
||||||
<drag :data="data" name="page"/>
|
<drag :data="data" name="page" :field="field"/>
|
||||||
</el-form>
|
</el-form>
|
||||||
</el-scrollbar>
|
</el-scrollbar>
|
||||||
</section>
|
</section>
|
||||||
|
|
@ -39,7 +39,8 @@ import FormBuild from "./formBuild"
|
||||||
import api from "@/api/index.js";
|
import api from "@/api/index.js";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
data: {type: FormBuild, default: []}
|
data: {type: FormBuild, default: []},
|
||||||
|
field: {type: Object, default: {}}
|
||||||
})
|
})
|
||||||
const {t} = useI18n()
|
const {t} = useI18n()
|
||||||
const {proxy} = getCurrentInstance()
|
const {proxy} = getCurrentInstance()
|
||||||
|
|
@ -58,7 +59,10 @@ function empty() {
|
||||||
ElMessageBox.confirm("确定要清空所有表单数据吗", t('system.warning'), {
|
ElMessageBox.confirm("确定要清空所有表单数据吗", t('system.warning'), {
|
||||||
confirmButtonText: t('system.ok'), cancelButtonText: t('system.cancel'), type: 'warning'
|
confirmButtonText: t('system.ok'), cancelButtonText: t('system.cancel'), type: 'warning'
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
|
tools.data.remove("FORM-FIELDS")
|
||||||
|
tools.data.remove("FORM-CONFIG")
|
||||||
props.data.restData()
|
props.data.restData()
|
||||||
|
proxy.$message.success("清空成功")
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,7 @@ export const fieldEditors = {
|
||||||
{key: 'props.placeholder', label: '占位提示', type: 'input'},
|
{key: 'props.placeholder', label: '占位提示', type: 'input'},
|
||||||
{key: 'props.multiple', label: '是否多选', type: 'switch'},
|
{key: 'props.multiple', label: '是否多选', type: 'switch'},
|
||||||
{key: 'props.filterable', label: '能否筛选', type: 'switch'},
|
{key: 'props.filterable', label: '能否筛选', type: 'switch'},
|
||||||
|
{key: 'props.clearable', label: '能否清空', type: 'switch'},
|
||||||
{key: 'props.disabled', label: '是否禁用', type: 'switch'},
|
{key: 'props.disabled', label: '是否禁用', type: 'switch'},
|
||||||
],
|
],
|
||||||
cascader: [
|
cascader: [
|
||||||
|
|
@ -175,7 +176,6 @@ export const fieldEditors = {
|
||||||
],
|
],
|
||||||
time: [
|
time: [
|
||||||
{key: 'props.editable', label: '可输入', type: 'switch'},
|
{key: 'props.editable', label: '可输入', type: 'switch'},
|
||||||
{key: 'props.rangeSeparator', label: '分隔符', type: 'input'},
|
|
||||||
{key: 'props.clearable', label: '能否清空', type: 'switch'},
|
{key: 'props.clearable', label: '能否清空', type: 'switch'},
|
||||||
{key: 'props.readonly', label: '是否只读', type: 'switch'},
|
{key: 'props.readonly', label: '是否只读', type: 'switch'},
|
||||||
{key: 'props.disabled', label: '是否禁用', type: 'switch'},
|
{key: 'props.disabled', label: '是否禁用', type: 'switch'},
|
||||||
|
|
|
||||||
|
|
@ -4,15 +4,14 @@
|
||||||
ghostClass="ghostClass" :class="{empty: data.fields.length === 0, layout: isRow}">
|
ghostClass="ghostClass" :class="{empty: data.fields.length === 0, layout: isRow}">
|
||||||
<template #item="{ element, index }">
|
<template #item="{ element, index }">
|
||||||
<el-col :span="element.span || 24" class="col">
|
<el-col :span="element.span || 24" class="col">
|
||||||
<el-row v-if="element.name === 'layout'" class="item row" :class="{'active': field.id===element.id}"
|
<el-row v-if="element.name === 'layout'" class="item row" :class="{'active': field.element.id===element.id}"
|
||||||
@click.stop="clickComp(element)" v-bind="element.props">
|
@click.stop="clickComp(element)" v-bind="element.props">
|
||||||
<span class="name">{{ element.field_name }}</span>
|
<span class="name">{{ element.field_name }}</span>
|
||||||
<drag :fields="element.children" :config="data.config" :data
|
<drag :data="getChildrenData(element.children)" :field="field" :name="element.field_name" :is-row="true"/>
|
||||||
:name="element.field_name" :is-row="true"/>
|
|
||||||
</el-row>
|
</el-row>
|
||||||
<item v-else class="item" :class="{'active': field.id===element.id}" :field="element"
|
<item v-else class="item" :class="{'active': field.element.id===element.id}" :field="element"
|
||||||
@click.stop="clickComp(element)"/>
|
@click.stop="clickComp(element)"/>
|
||||||
<div v-if="field.id===element.id" class="tools-box">
|
<div v-if="field.element.id===element.id" class="tools-box">
|
||||||
<el-icon size="22" class="icon-box remove" @click.stop="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>
|
||||||
|
|
@ -27,7 +26,7 @@
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import draggable from 'vuedraggable'
|
import draggable from 'vuedraggable'
|
||||||
import {computed, nextTick} from "vue"
|
import {nextTick, reactive} from "vue"
|
||||||
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"
|
import tools from "@/utils/tools"
|
||||||
|
|
@ -35,21 +34,19 @@ import FormBuild from "./formBuild"
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
data: {type: FormBuild, default: {}},
|
data: {type: FormBuild, default: {}},
|
||||||
|
field: {type: Object, default: {}},
|
||||||
curKey: {type: String, default: ''},
|
curKey: {type: String, default: ''},
|
||||||
isRow: {type: Boolean, default: false},
|
isRow: {type: Boolean, default: false},
|
||||||
name: {type: String, default: 'page'}
|
name: {type: String, default: 'page'}
|
||||||
})
|
})
|
||||||
|
|
||||||
const group = {name: props.name, pull: true, put: true}
|
const group = {name: props.name, pull: true, put: true}
|
||||||
const field = computed(() => {
|
|
||||||
return props.data.activeField || {}
|
|
||||||
})
|
|
||||||
|
|
||||||
// 排序
|
// 排序
|
||||||
function sortComp(e) {
|
function sortComp(e) {
|
||||||
let element = props.data.fields[e.newIndex]
|
let element = props.data.fields[e.newIndex]
|
||||||
if (element) {
|
if (element) {
|
||||||
props.data.setActiveField(element)
|
props.field.element = element
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -59,15 +56,15 @@ function addComp(e) {
|
||||||
if (props.isRow) {
|
if (props.isRow) {
|
||||||
element.span = 12
|
element.span = 12
|
||||||
}
|
}
|
||||||
props.data.setActiveField(element)
|
props.field.element = element
|
||||||
}
|
}
|
||||||
|
|
||||||
// 选中项
|
// 选中项
|
||||||
function clickComp(element) {
|
function clickComp(element) {
|
||||||
if (field.value.id === element.id) {
|
if (props.field.element.id === element.id) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
props.data.setActiveField(element)
|
props.field.element = element
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除字段
|
// 删除字段
|
||||||
|
|
@ -86,8 +83,7 @@ function delComp(index) {
|
||||||
i = index
|
i = index
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let element = props.data.fields[i] || {}
|
props.field.element = props.data.fields[i] || {}
|
||||||
props.data.setActiveField(element)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -101,8 +97,7 @@ function copyComp(index) {
|
||||||
props.data.fields.push(tmp)
|
props.data.fields.push(tmp)
|
||||||
// 将复制的元素移动到当前元素下边
|
// 将复制的元素移动到当前元素下边
|
||||||
tools.array.zIndexTo(props.data.fields, props.data.fields.length - 1, index + 1)
|
tools.array.zIndexTo(props.data.fields, props.data.fields.length - 1, index + 1)
|
||||||
let element = props.data.fields[index + 1]
|
props.field.element = props.data.fields[index + 1]
|
||||||
props.data.setActiveField(element)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -111,6 +106,12 @@ function increaseNum(str) {
|
||||||
return props.data.config.counter.toString();
|
return props.data.config.counter.toString();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getChildrenData(_data) {
|
||||||
|
const _form = reactive(new FormBuild())
|
||||||
|
_form.initData(props.data.config, _data)
|
||||||
|
return _form
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,6 @@ export default class FormBuild {
|
||||||
config: Config
|
config: Config
|
||||||
// 字段信息
|
// 字段信息
|
||||||
fields: Array<any>
|
fields: Array<any>
|
||||||
// 激活字段
|
|
||||||
activeField: Object
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.config = {
|
this.config = {
|
||||||
|
|
@ -31,7 +29,6 @@ export default class FormBuild {
|
||||||
counter: 0
|
counter: 0
|
||||||
}
|
}
|
||||||
this.fields = []
|
this.fields = []
|
||||||
this.activeField = null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
restData() {
|
restData() {
|
||||||
|
|
@ -53,8 +50,4 @@ export default class FormBuild {
|
||||||
this.config = config
|
this.config = config
|
||||||
this.fields = fields
|
this.fields = fields
|
||||||
}
|
}
|
||||||
|
|
||||||
setActiveField(field: Object) {
|
|
||||||
this.activeField = field
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
<template>
|
<template>
|
||||||
<el-container class="pi-panel">
|
<el-container class="pi-panel">
|
||||||
<left-panel :data="formData"></left-panel>
|
<left-panel :data="formData"></left-panel>
|
||||||
<center-panel ref="centerRef" :data="formData"></center-panel>
|
<center-panel ref="centerRef" :data="formData" :field="field"></center-panel>
|
||||||
<right-panel :data="formData" :fieldd="field"></right-panel>
|
<right-panel :data="formData" :field="field"></right-panel>
|
||||||
</el-container>
|
</el-container>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -19,9 +19,8 @@ defineOptions({
|
||||||
})
|
})
|
||||||
|
|
||||||
const centerRef = ref(null)
|
const centerRef = ref(null)
|
||||||
|
|
||||||
let formData = reactive(new FormBuild())
|
let formData = reactive(new FormBuild())
|
||||||
let field = ref({})
|
let field = reactive({element: {}})
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
const fields = tools.data.get("FORM-FIELDS")
|
const fields = tools.data.get("FORM-FIELDS")
|
||||||
|
|
@ -30,10 +29,6 @@ onMounted(() => {
|
||||||
formData.initData(config, fields)
|
formData.initData(config, fields)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
function activeField(v) {
|
|
||||||
field.value = v
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
|
||||||
|
|
@ -3,80 +3,80 @@
|
||||||
<el-scrollbar>
|
<el-scrollbar>
|
||||||
<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 :model="field" label-width="90px">
|
<el-form :model="form" label-width="90px">
|
||||||
<el-form-item v-if="field.name !== 'button' && field.name !== 'layout'" label="字段名"
|
<el-form-item v-if="form.name !== 'button' && form.name !== 'layout'" label="字段名"
|
||||||
prop="field_name">
|
prop="field_name">
|
||||||
<el-input v-model="field.field_name"></el-input>
|
<el-input v-model="form.field_name"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item v-if="field.name !== 'layout'" label="标题" prop="title">
|
<el-form-item v-if="form.name !== 'layout'" label="标题" prop="title">
|
||||||
<el-input v-model="field.title"></el-input>
|
<el-input v-model="form.title"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item v-if="field.name !== 'button' && field.name !== 'layout'" label="默认值"
|
<el-form-item v-if="form.name !== 'button' && form.name !== 'layout'" label="默认值"
|
||||||
prop="value">
|
prop="value">
|
||||||
<el-input v-model="field.value"></el-input>
|
<el-input v-model="form.value"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item v-if="field.span !== undefined" label="栅格列数" prop="span">
|
<el-form-item v-if="form.span !== undefined" label="栅格列数" prop="span">
|
||||||
<el-slider v-model="field.span" :min="1" :max="24"/>
|
<el-slider v-model="form.span" :min="1" :max="24"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<template v-for="item in fieldEditors[field.name] || []" :key="item.key">
|
<template v-for="item in fieldEditors[form.name] || []" :key="item.key">
|
||||||
<el-form-item :label="item.label">
|
<el-form-item :label="item.label">
|
||||||
<el-input
|
<el-input
|
||||||
v-if="item.type === 'input'"
|
v-if="item.type === 'input'"
|
||||||
:model-value="getByPath(field, item.key)"
|
:model-value="getByPath(form, item.key)"
|
||||||
@input="val => setByPath(field, item.key, val)"
|
@input="val => setByPath(form, item.key, val)"
|
||||||
clearable
|
clearable
|
||||||
/>
|
/>
|
||||||
<el-input
|
<el-input
|
||||||
v-else-if="item.type === 'number'"
|
v-else-if="item.type === 'number'"
|
||||||
type="number"
|
type="number"
|
||||||
:model-value="getByPath(field, item.key)"
|
:model-value="getByPath(form, item.key)"
|
||||||
@input="val => setByPath(field, item.key, Number(val))"
|
@input="val => setByPath(form, item.key, Number(val))"
|
||||||
/>
|
/>
|
||||||
<el-switch
|
<el-switch
|
||||||
v-else-if="item.type === 'switch'"
|
v-else-if="item.type === 'switch'"
|
||||||
:model-value="getByPath(field, item.key)"
|
:model-value="getByPath(form, item.key)"
|
||||||
@change="val => setByPath(field, item.key, val)"
|
@change="val => setByPath(form, item.key, val)"
|
||||||
/>
|
/>
|
||||||
<el-color-picker v-else-if="item.type === 'color'" show-alpha
|
<el-color-picker v-else-if="item.type === 'color'" show-alpha
|
||||||
:model-value="getByPath(field, item.key)"
|
:model-value="getByPath(form, item.key)"
|
||||||
@change="val => setByPath(field, item.key, val)"/>
|
@change="val => setByPath(form, item.key, val)"/>
|
||||||
<el-radio-group v-else-if="item.type === 'radio'"
|
<el-radio-group v-else-if="item.type === 'radio'"
|
||||||
:model-value="getByPath(field, item.key)"
|
:model-value="getByPath(form, item.key)"
|
||||||
@change="val => setByPath(field, item.key, val)">
|
@change="val => setByPath(form, item.key, val)">
|
||||||
<el-radio-button v-for="op in item.options" :key="op.value"
|
<el-radio-button v-for="op in item.options" :key="op.value"
|
||||||
:value="op.value">{{ op.label }}
|
:value="op.value">{{ op.label }}
|
||||||
</el-radio-button>
|
</el-radio-button>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
<el-select v-else-if="item.type === 'select'" :model-value="getByPath(field, item.key)"
|
<el-select v-else-if="item.type === 'select'" :model-value="getByPath(form, item.key)"
|
||||||
@change="val => setByPath(field, item.key, val)">
|
@change="val => setByPath(form, item.key, val)">
|
||||||
<el-option v-for="op in item.options" :key="op.value" :value="op.value"
|
<el-option v-for="op in item.options" :key="op.value" :value="op.value"
|
||||||
:label="op.label">
|
:label="op.label">
|
||||||
</el-option>
|
</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
<pi-icon
|
<pi-icon
|
||||||
v-else-if="item.type === 'icon'"
|
v-else-if="item.type === 'icon'"
|
||||||
:model-value="getByPath(field, item.key)"
|
:model-value="getByPath(form, item.key)"
|
||||||
@update:modelValue="val => setByPath(field, item.key, val)"
|
@update:modelValue="val => setByPath(form, item.key, val)"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</template>
|
</template>
|
||||||
<el-form-item label="是否必填" v-if="field.required !== undefined">
|
<el-form-item label="是否必填" v-if="form.required !== undefined">
|
||||||
<el-switch v-model="field.required"/>
|
<el-switch v-model="form.required"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<template v-if="field.options !== undefined">
|
<template v-if="form.options !== undefined">
|
||||||
<el-divider>选项</el-divider>
|
<el-divider>选项</el-divider>
|
||||||
<pi-draggable v-model="field.options" item-key="label" :template="{label:'', value:''}">
|
<pi-draggable v-model="form.options" item-key="label" :template="{label:'', value:''}">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<div style="display:flex;">
|
<div style="display:flex;gap: 5px;">
|
||||||
<el-input v-model="scope.element.label" placeholder="label"/>
|
<el-input v-model="scope.element.label" placeholder="label"/>
|
||||||
<el-input v-model="scope.element.value" placeholder="value"/>
|
<el-input v-model="scope.element.value" placeholder="value"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</pi-draggable>
|
</pi-draggable>
|
||||||
</template>
|
</template>
|
||||||
<template v-if="field.name !== 'button' && field.name !== 'layout'">
|
<template v-if="form.name !== 'button' && form.name !== 'layout'">
|
||||||
<el-divider>正则校验</el-divider>
|
<el-divider>正则校验</el-divider>
|
||||||
<pi-draggable v-model="field.rules" item-key="regex" :template="{regex:'',message:''}">
|
<pi-draggable v-model="form.rules" item-key="regex" :template="{regex:'',message:''}">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-form-item label="表达式">
|
<el-form-item label="表达式">
|
||||||
<el-input v-model="scope.element.regex"/>
|
<el-input v-model="scope.element.regex"/>
|
||||||
|
|
@ -136,11 +136,12 @@ import FormBuild from "./formBuild";
|
||||||
|
|
||||||
const emit = defineEmits(['update:field'])
|
const emit = defineEmits(['update:field'])
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
data: {type: FormBuild, default: {}}
|
data: {type: FormBuild, default: {}},
|
||||||
|
field: {type: Object, default: {}}
|
||||||
})
|
})
|
||||||
let activeName = ref("field")
|
let activeName = ref("field")
|
||||||
const field = computed(() => {
|
let form = computed(() => {
|
||||||
return props.data.activeField || {}
|
return props.field.element
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue