表单构建
This commit is contained in:
parent
f06cfbfda6
commit
013ebbbf13
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
Loading…
Reference in New Issue