表单构建

This commit is contained in:
zhang zhuo 2025-11-26 18:12:56 +08:00
parent f06cfbfda6
commit 013ebbbf13
8 changed files with 524 additions and 202 deletions

View File

@ -0,0 +1,3 @@
<template>
<svg t="1764150592466" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5627" width="256" height="256"><path d="M446.5664 0H332.8v113.7664h113.7664V0z m0 227.5584H332.8v113.7664h113.7664V227.584zM332.8 455.1168h113.7664v113.7664H332.8v-113.7664z m113.7664 227.5584H332.8v113.7664h113.7664v-113.7664zM332.8 910.2336h113.7664V1024H332.8v-113.7664zM674.1248 0H560.384v113.7664h113.7664V0zM560.384 227.5584h113.7664v113.7664H560.384V227.584z m113.7664 227.5584H560.384v113.7664h113.7664v-113.7664zM560.384 682.6752h113.7664v113.7664H560.384v-113.7664z m113.7664 227.5584H560.384V1024h113.7664v-113.7664z" p-id="5628"></path></svg>
</template>

View File

@ -0,0 +1,97 @@
<template>
<section>
<draggable v-model="value" :item-key="itemKey" animation="200" :group="group" handle=".item-rank">
<template #item="{ element, index }">
<div class="draggable-item">
<div class="item-content">
<el-icon size="50" class="item-rank">
<component :is="'pi-icon-move-area'"/>
</el-icon>
<div class="item-value">
<slot v-bind="{ element, index }"></slot>
</div>
</div>
<el-icon v-if="showDel" size="28" class="item-close" @click="remove(index)">
<component :is="'el-icon-CircleCloseFilled'"/>
</el-icon>
</div>
</template>
</draggable>
<div v-if="showAdd" class="add">
<el-link :underline="false" type="primary" icon="el-icon-circle-plus" @click="add">添加规则</el-link>
</div>
</section>
</template>
<script setup>
import draggable from 'vuedraggable'
import {computed} from "vue";
defineOptions({
name: "piDraggable"
})
const emit = defineEmits(['update:modelValue'])
const props = defineProps({
modelValue: {type: Array},
group: {type: Object},
itemKey: {type: String, default: "index"},
showAdd: {type: Boolean, default: true},
showDel: {type: Boolean, default: true},
template: {type: Object, default: {}}
})
const value = computed({
get() {
return props.modelValue
},
set(value) {
emit('update:modelValue', value)
}
})
function remove(element, index) {
value.value.splice(index, 1)
}
function add() {
value.value.push(JSON.parse(JSON.stringify(props.template)))
}
</script>
<style lang="scss" scoped>
.draggable-item {
margin: 0 10px 15px 0;
position: relative;
.item-content {
display: flex;
align-items: center;
padding: 10px;
border: 1px solid #eeeeee;
border-radius: 8px;
}
.item-rank {
cursor: move;
color: #9E9E9E;
width: 50px;
}
.item-value {
flex: 1;
}
.item-close {
position: absolute;
cursor: pointer;
color: #9E9E9E;
top: -14px;
right: -12px;
}
}
.add {
padding: 0 10px 10px 20px;
}
</style>

View File

@ -1,9 +1,14 @@
<template>
<div class="pi-icon-select">
<div class="pi-icon-select__wrapper" :class="{'hasValue':value}" @click="open">
<el-input :prefix-icon="value||'el-icon-plus'" v-model="value" :disabled="disabled" readonly></el-input>
<div class="pi-icon-select__wrapper" :class="{'hasValue':value}" style="width: 100%;">
<el-input v-model="value" :disabled="disabled" readonly>
<template #append>
<el-icon size="22" @click="open">
<component :is="value||'el-icon-plus'"/>
</el-icon>
</template>
</el-input>
</div>
<el-text style="margin-left: 5px;">{{value}}</el-text>
<el-dialog title="图标选择器" v-model="dialogVisible" :width="760" destroy-on-close append-to-body>
<div class="pi-icon-select__dialog">
<el-form :rules="{}">
@ -21,7 +26,7 @@
<div class="pi-icon-select__list">
<el-scrollbar>
<ul @click="selectIcon">
<el-empty v-if="item.icons.length==0" :image-size="100"
<el-empty v-if="item.icons.length===0" :image-size="100"
description="未查询到相关图标"/>
<li v-for="icon in item.icons" :key="icon">
<span :data-icon="icon"></span>
@ -115,37 +120,19 @@ function search(text) {
display: inline-flex;
}
.pi-icon-select__wrapper {
cursor: pointer;
display: inline-flex;
}
.pi-icon-select__wrapper:deep(.el-input__wrapper).is-focus {
box-shadow: 0 0 0 1px var(--el-input-hover-border-color) inset;
}
.pi-icon-select__wrapper:deep(.el-input__inner) {
flex-grow: 0;
width: 0;
}
.pi-icon-select__wrapper:deep(.el-input__icon) {
margin: 0;
font-size: 16px;
}
.pi-icon-select__wrapper.hasValue:deep(.el-input__icon) {
color: var(--el-text-color-regular);
}
.pi-icon-select__wrapper:deep(.el-input-group__append, .el-input-group__prepend) {
padding: 0 10px;
}
.pi-icon-select__list {
height: 270px;
overflow: auto;
}
.pi-icon-select__list ul {
}
.pi-icon-select__list li {
display: inline-block;
width: 80px;

View File

@ -8,11 +8,11 @@
<h2>{{ form.title || "新增菜单" }}</h2>
<el-form :model="form" :rules="rules" ref="dialogForm" label-width="80px" label-position="left">
<el-form-item label="显示名称" prop="title">
<el-input v-model="form.title" clearable placeholder="菜单显示名字"></el-input>
<el-input v-model="form.title" clearable placeholder="菜单显示名字" style="width: 300px;"></el-input>
</el-form-item>
<el-form-item label="上级菜单" prop="pid">
<el-cascader ref="parentId" v-model="form.pid" :options="menuOptions" :props="menuProps"
:show-all-levels="false" placeholder="顶级菜单" clearable></el-cascader>
:show-all-levels="false" placeholder="顶级菜单" clearable style="width: 300px;"></el-cascader>
</el-form-item>
<el-form-item label="类型" prop="type">
<el-radio-group v-model="form.type">
@ -23,30 +23,30 @@
</el-radio-group>
</el-form-item>
<el-form-item v-if="form.type == 0 || form.type == 3" label="菜单图标" prop="icon">
<pi-icon v-model="form.icon" clearable></pi-icon>
<pi-icon v-model="form.icon" style="width: 300px;"></pi-icon>
</el-form-item>
<el-form-item v-if="form.type == 0" label="页面名称" prop="name">
<el-input v-model="form.name" clearable></el-input>
<el-input v-model="form.name" clearable style="width: 300px;"></el-input>
<div class="el-form-item-msg">
系统唯一且与内置组件名一致否则导致缓存失效如类型为Iframe的菜单别名将代替源地址显示在地址栏
</div>
</el-form-item>
<el-form-item v-if="form.type == 0" label="路由地址" prop="path">
<el-input v-model="form.path" clearable></el-input>
<el-input v-model="form.path" clearable style="width: 300px;"></el-input>
<div class="el-form-item-msg">首位不需要填写 "/" 自动匹配页面路径</div>
</el-form-item>
<el-form-item v-if="form.type == 0" label="是否隐藏" prop="hidden">
<el-checkbox v-model="form.hidden" :true-value="1" :false-value="0">隐藏菜单</el-checkbox>
</el-form-item>
<el-form-item v-if="form.type == 3" label="外部链接" prop="path">
<el-input v-model="form.path" clearable></el-input>
<el-input v-model="form.path" clearable style="width: 300px;"></el-input>
</el-form-item>
<el-form-item v-if="form.type == 0 || form.type == 3" label="页面顺序" prop="rank">
<el-input v-model="form.rank" clearable></el-input>
<el-input v-model="form.rank" clearable style="width: 300px;"></el-input>
<div class="el-form-item-msg">数值越大越靠前</div>
</el-form-item>
<el-form-item v-if="form.type == 2" label="请求方式" prop="method">
<el-select v-model="form.method">
<el-select v-model="form.method" style="width: 300px;">
<el-option
v-for="item in methodOptions"
:key="item.value"
@ -56,7 +56,7 @@
</el-select>
</el-form-item>
<el-form-item v-if="form.type == 1 || form.type == 2" label="权限标识" prop="flag">
<el-input v-model="form.flag" clearable></el-input>
<el-input v-model="form.flag" clearable style="width: 300px;"></el-input>
<div class="el-form-item-msg">权限分隔符":"分割</div>
</el-form-item>
<el-form-item>

View File

@ -1,33 +1,41 @@
<template>
<section class="panel">
<el-main style="height: 100%;">
<draggable :list="fields" @update:list="fields = $event" :scroll="true" animation="200" item-key="id"
class="body"
:group="group" @add="addComp" @sort="sortComp" ghostClass="ghostClass">
<template #item="{ element, index }">
<form class="box">
<el-form-item class="item" :class="{'active': curIndex===index}"
@click="clickComp(element,index)" :label="fields[index].title">
<el-input v-if="fields[index].name==='text'" v-model="fields[index].value"></el-input>
<el-input v-if="fields[index].name==='textarea'" type="textarea"
v-model="fields[index].value"></el-input>
<el-input v-if="fields[index].name==='password'" type="password"
v-model="fields[index].value" show-password></el-input>
<el-input-number v-if="fields[index].name==='number'"
v-model="fields[index].value"></el-input-number>
</el-form-item>
<div v-if="curIndex===index" class="tools-box">
<el-icon size="22" class="icon-box remove" @click="delComp(index)">
<component :is="'pi-icon-shan-chu'"/>
</el-icon>
<el-icon size="20" class="icon-box copy mt5" @click="copyComp(index)">
<component :is="'pi-icon-fu-zhi'"/>
</el-icon>
</div>
</form>
</template>
</draggable>
</el-main>
<el-scrollbar class="height-100">
<el-main class="height-100">
<el-form class="height-100" :label-position="config.labelPosition" :label-width="config.labelWidth"
:size="config.size" :disabled="config.disabled">
<draggable :list="fields" :scroll="true" animation="200" item-key="id" class="height-100"
:group="group" @update:list="fields = $event" @add="addComp" @sort="sortComp"
ghostClass="ghostClass">
<template #item="{ element, index }">
<div class="box">
<el-form-item class="item" :class="{'active': curIndex===index}"
@click="clickComp(element,index)" :label="fields[index].title"
:style="{width: fields[index].width}" :required="fields[index].required">
<el-input v-if="fields[index].name==='text'" v-model="fields[index].value"
v-bind="fields[index].props"></el-input>
<el-input v-if="fields[index].name==='textarea'" type="textarea"
v-model="fields[index].value" v-bind="fields[index].props"></el-input>
<el-input v-if="fields[index].name==='password'" type="password"
v-model="fields[index].value" v-bind="fields[index].props"
show-password></el-input>
<el-input-number v-if="fields[index].name==='number'" v-model="fields[index].value"
v-bind="fields[index].props"></el-input-number>
</el-form-item>
<div v-if="curIndex===index" class="tools-box">
<el-icon size="22" class="icon-box remove" @click="delComp(index)">
<component :is="'pi-icon-shan-chu'"/>
</el-icon>
<el-icon size="20" class="icon-box copy mt5" @click="copyComp(index)">
<component :is="'pi-icon-fu-zhi'"/>
</el-icon>
</div>
</div>
</template>
</draggable>
</el-form>
</el-main>
</el-scrollbar>
</section>
</template>
@ -40,7 +48,7 @@ const props = defineProps({
fields: {type: Array, default: []},
config: {type: Object, default: {}}
})
const emit = defineEmits(['change'])
const group = {name: 'page', pull: false, put: true}
let curIndex = ref(0)
let curComp = ref({})
@ -49,6 +57,7 @@ let curComp = ref({})
function sortComp(e) {
curIndex.value = e.newIndex
curComp.value = props.fields[e.newIndex]
emit('change', curComp.value)
}
//
@ -56,6 +65,7 @@ function addComp(e) {
let element = props.fields[e.newIndex]
curIndex.value = e.newIndex
curComp.value = element
emit('change', curComp.value)
}
//
@ -65,6 +75,7 @@ function clickComp(element, index) {
}
curIndex.value = index
curComp.value = element
emit('change', curComp.value)
}
//
@ -85,6 +96,7 @@ function delComp(index) {
}
curIndex.value = i
curComp.value = props.fields[i]
emit('change', curComp.value || {})
})
}
@ -97,6 +109,7 @@ function copyComp(index) {
tools.array.zIndexTo(props.fields, props.fields.length - 1, index + 1)
curIndex.value = index + 1
curComp.value = props.fields[index + 1]
emit('change', curComp.value)
})
}
</script>
@ -110,10 +123,6 @@ function copyComp(index) {
display: none;
}
.body {
height: 100%;
}
:deep(.ghostClass) {
.comp {
display: none;
@ -127,6 +136,14 @@ function copyComp(index) {
}
}
.height-100 {
height: 100%;
}
:deep(.el-scrollbar__view) {
height: 100%;
}
.active {
border: 1px dashed #787be8 !important;
color: #787be8;
@ -146,21 +163,24 @@ function copyComp(index) {
.tools-box {
position: absolute;
right: -25px;
right: -20px;
top: 0;
display: inline-grid;
padding: 5px 8px;
padding: 5px;
border-radius: 4px;
.icon-box {
cursor: pointer;
}
.icon-box.remove {
color: var(--el-color-danger);
}
.icon-box.copy {
color: var(--el-color-primary);
}
.mt5 {
margin-top: 5px;
}

View File

@ -3,9 +3,9 @@
<el-main class="main">
<left-panel></left-panel>
<el-divider direction="vertical" style="height: 100%"/>
<center-panel :fields="fields" :config="config"></center-panel>
<center-panel :fields="fields" :config="config" @change="setField"></center-panel>
<el-divider direction="vertical" style="height: 100%"/>
<right-panel :fields="fields" :config="config"></right-panel>
<right-panel :config="config" :curField="curField"></right-panel>
</el-main>
</el-container>
</template>
@ -17,7 +17,21 @@ import centerPanel from "./center"
import rightPanel from "./right"
let fields = ref([])
let config = ref({})
let config = ref({
ref: 'formRef',
model: 'form',
rules: 'rules',
size: 'default',
labelPosition: 'right',
labelWidth: 100,
disabled: false
})
let curField = ref({})
function setField(v) {
curField.value = v
curField.value.field = v.id
}
</script>

View File

@ -1,93 +1,95 @@
<template>
<section class="panel">
<div class="title">
<el-text>
<el-icon>
<component :is="'pi-icon-zu-jian'"/>
</el-icon>
输入组件
</el-text>
</div>
<draggable v-model="inputComps" animation="200" item-key="id" class="go-base" :group="group" :sort="false"
:clone="cloneField">
<template #item="{ element }">
<div class="item">
<div class="tips">松开鼠标组件将添加到此处</div>
<div class="comp">
<el-icon size="20">
<component :is="element.icon"/>
</el-icon>
{{ element.title }}
<el-scrollbar>
<div class="title">
<el-text>
<el-icon>
<component :is="'pi-icon-zu-jian'"/>
</el-icon>
输入组件
</el-text>
</div>
<draggable v-model="inputComps" animation="200" item-key="id" class="go-base" :group="group" :sort="false"
:clone="cloneField">
<template #item="{ element }">
<div class="item">
<div class="tips">松开鼠标组件将添加到此处</div>
<div class="comp">
<el-icon size="20">
<component :is="element.icon"/>
</el-icon>
{{ element.title }}
</div>
</div>
</div>
</template>
</draggable>
<div class="title">
<el-text>
<el-icon>
<component :is="'pi-icon-zu-jian'"/>
</el-icon>
选择组件
</el-text>
</div>
<draggable v-model="choiceComps" animation="200" item-key="id" class="go-base" :group="group" :sort="false"
:clone="cloneField">
<template #item="{ element }">
<div class="item">
<div class="tips">松开鼠标组件将添加到此处</div>
<div class="comp">
<el-icon size="20">
<component :is="element.icon"/>
</el-icon>
{{ element.title }}
</template>
</draggable>
<div class="title">
<el-text>
<el-icon>
<component :is="'pi-icon-zu-jian'"/>
</el-icon>
选择组件
</el-text>
</div>
<draggable v-model="choiceComps" animation="200" item-key="id" class="go-base" :group="group" :sort="false"
:clone="cloneField">
<template #item="{ element }">
<div class="item">
<div class="tips">松开鼠标组件将添加到此处</div>
<div class="comp">
<el-icon size="20">
<component :is="element.icon"/>
</el-icon>
{{ element.title }}
</div>
</div>
</div>
</template>
</draggable>
<div class="title">
<el-text>
<el-icon>
<component :is="'pi-icon-zu-jian'"/>
</el-icon>
布局组件
</el-text>
</div>
<draggable v-model="layoutComps" animation="200" item-key="id" class="go-base" :group="group" :sort="false"
:clone="cloneField">
<template #item="{ element }">
<div class="item">
<div class="tips">松开鼠标组件将添加到此处</div>
<div class="comp">
<el-icon size="20">
<component :is="element.icon"/>
</el-icon>
{{ element.title }}
</template>
</draggable>
<div class="title">
<el-text>
<el-icon>
<component :is="'pi-icon-zu-jian'"/>
</el-icon>
布局组件
</el-text>
</div>
<draggable v-model="layoutComps" animation="200" item-key="id" class="go-base" :group="group" :sort="false"
:clone="cloneField">
<template #item="{ element }">
<div class="item">
<div class="tips">松开鼠标组件将添加到此处</div>
<div class="comp">
<el-icon size="20">
<component :is="element.icon"/>
</el-icon>
{{ element.title }}
</div>
</div>
</div>
</template>
</draggable>
<div class="title">
<el-text>
<el-icon>
<component :is="'pi-icon-zu-jian'"/>
</el-icon>
内置组件
</el-text>
</div>
<draggable v-model="systemComps" animation="200" item-key="id" class="go-base" :group="group" :sort="false"
:clone="cloneField">
<template #item="{ element }">
<div class="item">
<div class="tips">松开鼠标组件将添加到此处</div>
<div class="comp">
<el-icon size="20">
<component :is="element.icon"/>
</el-icon>
{{ element.title }}
</template>
</draggable>
<div class="title">
<el-text>
<el-icon>
<component :is="'pi-icon-zu-jian'"/>
</el-icon>
内置组件
</el-text>
</div>
<draggable v-model="systemComps" animation="200" item-key="id" class="go-base" :group="group" :sort="false"
:clone="cloneField">
<template #item="{ element }">
<div class="item">
<div class="tips">松开鼠标组件将添加到此处</div>
<div class="comp">
<el-icon size="20">
<component :is="element.icon"/>
</el-icon>
{{ element.title }}
</div>
</div>
</div>
</template>
</draggable>
</template>
</draggable>
</el-scrollbar>
</section>
</template>
@ -101,130 +103,196 @@ const inputComps = [{
title: "单行文本",
icon: "pi-icon-line-input",
name: "text",
props: {}
props: {
placeholder: null,
labelWidth: null,
prefixIcon: null,
suffixIcon: null,
minlength: null,
maxlength: null,
clearable: false,
readonly: false,
disabled: false,
required: false,
showWordLimit: false
},
rules: [{regex: '', message: '213123'}],
width: "100%",
required: false
}, {
id: "i2",
title: "多行文本",
icon: "pi-icon-multi-input",
name: "textarea",
props: {}
props: {
placeholder: null,
labelWidth: null,
minlength: null,
maxlength: null,
readonly: false,
disabled: false,
required: false,
showWordLimit: false,
rows: 3
},
rules: [],
width: "100%",
required: false
}, {
id: "i3",
title: "密码",
icon: "pi-icon-lock",
name: "password",
props: {}
props: {
placeholder: null,
labelWidth: null,
prefixIcon: null,
suffixIcon: null,
minlength: null,
maxlength: null,
clearable: false,
readonly: false,
disabled: false,
required: false,
showWordLimit: false
},
rules: [],
width: "100%",
required: false
}, {
id: "i4",
title: "计数器",
icon: "pi-icon-number-input",
name: "number",
props: {}
props: {
placeholder: null
},
rules: [],
width: "100%",
required: false,
value: 1
}]
const choiceComps = [{
id: "c1",
title: "下拉组件",
icon: "pi-icon-select",
name: "select",
props: {}
props: {},
rules: []
}, {
id: "c2",
title: "级联组件",
icon: "pi-icon-cascader",
name: "cascader",
props: {}
props: {},
rules: []
}, {
id: "c3",
title: "单选组件",
icon: "pi-icon-radio",
name: "radio",
props: {}
props: {},
rules: []
}, {
id: "c4",
title: "多选组件",
icon: "pi-icon-checkbox",
name: "checkbox",
props: {}
props: {},
rules: []
}, {
id: "c5",
title: "开关",
icon: "pi-icon-switch",
name: "switch",
props: {}
props: {},
rules: []
}, {
id: "c6",
title: "滑块",
icon: "pi-icon-slider",
name: "slider",
props: {}
props: {},
rules: []
}, {
id: "c7",
title: "时间选择",
icon: "pi-icon-time-picker",
name: "time",
props: {}
props: {},
rules: []
}, {
id: "c8",
title: "时间范围",
icon: "pi-icon-time-range",
name: "timerange",
props: {}
props: {},
rules: []
}, {
id: "c9",
title: "日期选择",
icon: "pi-icon-date-picker",
name: "date",
props: {}
props: {},
rules: []
}, {
id: "c10",
title: "日期范围",
icon: "pi-icon-date-range",
name: "daterange",
props: {}
props: {},
rules: []
}, {
id: "c11",
title: "评分",
icon: "pi-icon-rate",
name: "rate",
props: {}
props: {},
rules: []
}, {
id: "c12",
title: "颜色选择",
icon: "pi-icon-color-picker",
name: "color",
props: {}
props: {},
rules: []
}, {
id: 'c13',
title: "上传",
icon: "pi-icon-upload-file",
name: "upload",
props: {}
props: {},
rules: []
}]
const layoutComps = [{
id: 'l1',
title: "行容器",
icon: "pi-icon-row-layout",
name: "layout",
props: {}
props: {},
rules: []
}, {
id: 'l2',
title: "按钮",
icon: "pi-icon-button",
name: "button",
props: {}
props: {},
rules: []
}];
const systemComps = [{
id: 's1',
title: "资源选择",
icon: "pi-icon-asset-choice",
name: "asset",
props: {}
props: {},
rules: []
}, {
id: 's2',
title: "图标选择",
icon: "pi-icon-icon-choice",
name: "icon",
props: {}
props: {},
rules: []
}]
let num = ref(100)
@ -252,6 +320,18 @@ function cloneField(e) {
}
}
:deep(.el-scrollbar__bar) {
display: none !important;
}
:deep(.el-scrollbar__wrap) {
scrollbar-width: none;
}
:deep(.el-scrollbar__wrap::-webkit-scrollbar) {
display: none !important;
}
.go-base {
display: flex;
justify-content: space-between;

View File

@ -1,42 +1,163 @@
<template>
<section class="panel">
<el-tabs v-model="activeName" stretch>
<el-tab-pane label="组件属性" name="field">
</el-tab-pane>
<el-tab-pane label="表单属性" name="form">
<el-form>
<el-form-item label="表单名称" prop="ref">
<el-input v-model="config.ref"></el-input>
</el-form-item>
<el-form-item label="表单模型" prop="model" required>
<el-input v-model="config.model"></el-input>
</el-form-item>
<el-form-item label="校验模型" prop="rules">
<el-input v-model="config.rules"></el-input>
</el-form-item>
<el-form-item label="校验模型" prop="rules">
<el-input v-model="config.rules"></el-input>
</el-form-item>
</el-form>
</el-tab-pane>
</el-tabs>
<el-scrollbar>
<el-tabs v-model="activeName" stretch>
<el-tab-pane label="组件属性" name="field">
<el-form v-model="fForm" label-width="90px">
<el-form-item label="字段名" prop="field">
<el-input v-model="fForm.field"></el-input>
</el-form-item>
<el-form-item label="标题" prop="title">
<el-input v-model="fForm.title"></el-input>
</el-form-item>
<el-form-item v-if="fForm.props?.placeholder !== undefined" label="占位提示"
prop="props.placeholder">
<el-input v-model="fForm.props.placeholder"></el-input>
</el-form-item>
<el-form-item v-if="fForm.props?.labelWidth !== undefined" label="标签宽度"
prop="props.labelWidth">
<el-input v-model="fForm.props.labelWidth"></el-input>
</el-form-item>
<el-form-item v-if="fForm.width !== undefined" label="组件宽度" prop="width">
<el-input v-model="fForm.width"></el-input>
</el-form-item>
<el-form-item label="默认值" prop="value">
<el-input v-model="fForm.value"></el-input>
</el-form-item>
<el-form-item v-if="fForm.props?.prefixIcon !== undefined" label="前图标"
prop="props.prefixIcon">
<pi-icon v-model="fForm.props.prefixIcon" style="width: 100%"></pi-icon>
</el-form-item>
<el-form-item v-if="fForm.props?.suffixIcon !== undefined" label="后图标"
prop="props.suffixIcon">
<pi-icon v-model="fForm.props.suffixIcon" style="width: 100%"></pi-icon>
</el-form-item>
<el-form-item v-if="fForm.props?.minlength !== undefined" label="最少输入"
prop="props.minlength">
<el-input v-model.number="fForm.props.minlength" type="number"></el-input>
</el-form-item>
<el-form-item v-if="fForm.props?.maxlength !== undefined" label="最多输入"
prop="props.maxlength">
<el-input v-model.number="fForm.props.maxlength" type="number"></el-input>
</el-form-item>
<el-form-item v-if="fForm.props?.rows !== undefined" label="默认行数" prop="props.rows">
<el-input v-model.number="fForm.props.rows" type="number"></el-input>
</el-form-item>
<el-form-item v-if="fForm.props?.showWordLimit !== undefined" label="显示字数"
prop="props.showWordLimit">
<el-switch v-model="fForm.props.showWordLimit"/>
</el-form-item>
<el-form-item v-if="fForm.props?.clearable !== undefined" label="能否清空"
prop="props.clearable">
<el-switch v-model="fForm.props.clearable"/>
</el-form-item>
<el-form-item v-if="fForm.props?.readonly !== undefined" label="是否只读" prop="props.readonly">
<el-switch v-model="fForm.props.readonly"/>
</el-form-item>
<el-form-item v-if="fForm.props?.disabled !== undefined" label="是否禁用" prop="props.disabled">
<el-switch v-model="fForm.props.disabled"/>
</el-form-item>
<el-form-item v-if="fForm.required !== undefined" label="是否必填" prop="required">
<el-switch v-model="fForm.required"/>
</el-form-item>
<el-divider>
<template #default>
正则校验
</template>
</el-divider>
<pi-draggable v-model="fForm.rules" item-key="regex">
<template #default="scope">
<el-form-item label="表达式" prop="regex">
<el-input v-model="scope.element.regex"></el-input>
</el-form-item>
<el-form-item label="错误提示" prop="message" style="margin-bottom: 0;">
<el-input v-model="scope.element.message"></el-input>
</el-form-item>
</template>
</pi-draggable>
</el-form>
</el-tab-pane>
<el-tab-pane label="表单属性" name="form">
<el-form v-model="cForm" label-width="90px">
<el-form-item label="表单名称" prop="ref">
<el-input v-model="cForm.ref"></el-input>
</el-form-item>
<el-form-item label="表单模型" prop="model">
<el-input v-model="cForm.model"></el-input>
</el-form-item>
<el-form-item label="校验模型" prop="rules">
<el-input v-model="cForm.rules"></el-input>
</el-form-item>
<el-form-item label="表单尺寸" prop="size">
<el-radio-group v-model="cForm.size">
<el-radio-button value="large">较大</el-radio-button>
<el-radio-button value="default">默认</el-radio-button>
<el-radio-button value="small">较小</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="标签对齐" prop="labelPosition">
<el-radio-group v-model="cForm.labelPosition">
<el-radio-button value="left">左对齐</el-radio-button>
<el-radio-button value="right">右对齐</el-radio-button>
<el-radio-button value="top">顶部对齐</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="标签宽度" prop="labelWidth">
<el-input-number v-model="cForm.labelWidth"/>
</el-form-item>
<el-form-item label="禁用表单" prop="disabled">
<el-switch v-model="cForm.disabled"/>
</el-form-item>
</el-form>
</el-tab-pane>
</el-tabs>
</el-scrollbar>
</section>
</template>
<script setup>
import {ref} from "vue";
import {computed, ref} from "vue";
import piIcon from "@/components/piIcon"
import piDraggable from "@/components/piDraggable"
let activeName = ref("field")
const props = defineProps({
fields: {type: Array, default: []},
curField: {type: Object, default: {}},
config: {type: Object, default: {}}
})
const emit = defineEmits(['update:modelValue'])
let cForm = computed({
get() {
return props.config
},
set(value) {
this.$emit('update:modelValue', value)
}
})
let fForm = computed({
get() {
return props.curField
},
set(value) {
this.$emit('update:modelValue', value)
}
})
</script>
<style scoped>
<style lang="scss" scoped>
.panel {
width: 350px
}
:deep(.el-scrollbar__bar) {
display: none !important;
}
:deep(.el-scrollbar__wrap) {
scrollbar-width: none;
}
:deep(.el-scrollbar__wrap::-webkit-scrollbar) {
display: none !important;
}
</style>