|
|
@@ -2,6 +2,12 @@
|
|
|
import Vue from 'vue'
|
|
|
import guide from '@/views/guide/index'
|
|
|
import draggable from 'vuedraggable'
|
|
|
+import countryCode from '@/lib/countryCode.json'
|
|
|
+import {
|
|
|
+ pcTextArr,
|
|
|
+ pcaTextArr
|
|
|
+} from "element-china-area-data"
|
|
|
+
|
|
|
export default Vue.extend({
|
|
|
name: 'Edit',
|
|
|
components: {
|
|
|
@@ -14,48 +20,72 @@ export default Vue.extend({
|
|
|
{
|
|
|
type: 'tips',
|
|
|
label: '将我拖拽至右边试试吧',
|
|
|
- width: 2
|
|
|
+ width: 6,
|
|
|
+ required: false
|
|
|
},
|
|
|
{
|
|
|
type: 'input',
|
|
|
label: '请在下方输入内容',
|
|
|
value: '',
|
|
|
- width: 2,
|
|
|
- placeholder: '请输入'
|
|
|
+ width: 6,
|
|
|
+ placeholder: '请输入',
|
|
|
+ pattern: '^[\\s\\S]*$',
|
|
|
+ required: false
|
|
|
+ },
|
|
|
+ {
|
|
|
+ type: 'phone',
|
|
|
+ label: '请在下方输入手机号码',
|
|
|
+ value: '',
|
|
|
+ country: 'CN',
|
|
|
+ width: 6,
|
|
|
+ placeholder: '请输入手机号',
|
|
|
+ required: false
|
|
|
+ },
|
|
|
+ {
|
|
|
+ type: 'email',
|
|
|
+ label: '请在下方输入邮箱',
|
|
|
+ value: '',
|
|
|
+ width: 6,
|
|
|
+ placeholder: '请输入邮箱',
|
|
|
+ codePlaceholder: '请输入验证码',
|
|
|
+ required: false
|
|
|
},
|
|
|
{
|
|
|
type: 'select',
|
|
|
label: '请在下方选择内容',
|
|
|
value: '',
|
|
|
- width: 1,
|
|
|
+ width: 6,
|
|
|
options: [
|
|
|
{ label: '东坡肉', value: '东坡肉' },
|
|
|
{ label: '酱肘子', value: '酱肘子' },
|
|
|
{ label: '白切鸡', value: '白切鸡' }
|
|
|
],
|
|
|
- placeholder: '请选择'
|
|
|
+ placeholder: '请选择',
|
|
|
+ required: false
|
|
|
},
|
|
|
{
|
|
|
type: 'checkbox',
|
|
|
label: '请选择一至多项内容',
|
|
|
value: '',
|
|
|
- width: 1,
|
|
|
+ width: 6,
|
|
|
options: [
|
|
|
{ label: '东坡肉', value: '东坡肉' },
|
|
|
{ label: '酱肘子', value: '酱肘子' },
|
|
|
{ label: '白切鸡', value: '白切鸡' }
|
|
|
- ]
|
|
|
+ ],
|
|
|
+ required: false
|
|
|
},
|
|
|
{
|
|
|
type: 'radio',
|
|
|
label: '请选择一项内容',
|
|
|
value: '',
|
|
|
- width: 1,
|
|
|
+ width: 6,
|
|
|
options: [
|
|
|
{ label: '东坡肉', value: '东坡肉' },
|
|
|
{ label: '酱肘子', value: '酱肘子' },
|
|
|
{ label: '白切鸡', value: '白切鸡' }
|
|
|
- ]
|
|
|
+ ],
|
|
|
+ required: false
|
|
|
},
|
|
|
{
|
|
|
type: 'number',
|
|
|
@@ -64,7 +94,8 @@ export default Vue.extend({
|
|
|
min: 0,
|
|
|
step: 1,
|
|
|
value: 0,
|
|
|
- width: 1
|
|
|
+ width: 6,
|
|
|
+ required: false
|
|
|
},
|
|
|
{
|
|
|
type: 'slider',
|
|
|
@@ -73,7 +104,8 @@ export default Vue.extend({
|
|
|
min: 0,
|
|
|
step: 1,
|
|
|
value: 0,
|
|
|
- width: 1
|
|
|
+ width: 6,
|
|
|
+ required: false
|
|
|
},
|
|
|
{
|
|
|
type: 'textarea',
|
|
|
@@ -81,40 +113,55 @@ export default Vue.extend({
|
|
|
value: '',
|
|
|
maxRows: 4,
|
|
|
minRows: 2,
|
|
|
- width: 2,
|
|
|
- placeholder: '请输入'
|
|
|
+ width: 6,
|
|
|
+ placeholder: '请输入',
|
|
|
+ required: false,
|
|
|
+ pattern: '^[\\s\\S]*$'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ type: 'region',
|
|
|
+ label: '请在下方选择位置',
|
|
|
+ range: 2,
|
|
|
+ width: 6,
|
|
|
+ value: [],
|
|
|
+ placeholder: '请选择所在区域',
|
|
|
+ required: false
|
|
|
},
|
|
|
{
|
|
|
type: 'time',
|
|
|
label: '请在下方选择时间',
|
|
|
value: '',
|
|
|
- width: 2,
|
|
|
- placeholder: '请选择时间'
|
|
|
+ width: 6,
|
|
|
+ placeholder: '请选择时间',
|
|
|
+ required: false
|
|
|
},
|
|
|
{
|
|
|
type: 'timeRange',
|
|
|
label: '请在下方选择时间范围',
|
|
|
value: '',
|
|
|
- width: 2,
|
|
|
+ width: 6,
|
|
|
rangeSeparator: '至',
|
|
|
placeholder: '开始时间',
|
|
|
- endPlaceholder: '结束时间'
|
|
|
+ endPlaceholder: '结束时间',
|
|
|
+ required: false
|
|
|
},
|
|
|
{
|
|
|
type: 'date',
|
|
|
label: '请在下方选择日期',
|
|
|
value: '',
|
|
|
- width: 2,
|
|
|
- placeholder: '请选择日期'
|
|
|
+ width: 6,
|
|
|
+ placeholder: '请选择日期',
|
|
|
+ required: false
|
|
|
},
|
|
|
{
|
|
|
type: 'dateRange',
|
|
|
label: '请在下方选择日期范围',
|
|
|
value: '',
|
|
|
- width: 2,
|
|
|
+ width: 6,
|
|
|
rangeSeparator: '至',
|
|
|
placeholder: '开始日期',
|
|
|
- endPlaceholder: '结束日期'
|
|
|
+ endPlaceholder: '结束日期',
|
|
|
+ required: false
|
|
|
}
|
|
|
],
|
|
|
formData: [],
|
|
|
@@ -127,7 +174,10 @@ export default Vue.extend({
|
|
|
currentKey: '',
|
|
|
currentData: {},
|
|
|
hoverKey: '',
|
|
|
- selectInput: ''
|
|
|
+ selectInput: '',
|
|
|
+ pcTextArr,
|
|
|
+ pcaTextArr,
|
|
|
+ countryCode
|
|
|
}
|
|
|
},
|
|
|
methods: {
|
|
|
@@ -209,6 +259,25 @@ export default Vue.extend({
|
|
|
<div class="tips">{{ element.label }}</div>
|
|
|
<el-input :value="element.value" :placeholder="element.placeholder" />
|
|
|
</div>
|
|
|
+ <div v-if="element.type==='email'" :class="[element.type,'form-item']">
|
|
|
+ <div class="tips">{{ element.label }}</div>
|
|
|
+ <div>
|
|
|
+ <el-input v-model="element.value" :placeholder="element.placeholder" />
|
|
|
+ </div>
|
|
|
+ <div class="code-input">
|
|
|
+ <el-input v-model="element.value" :placeholder="element.codePlaceholder" />
|
|
|
+ <el-button>获取验证码</el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div v-if="element.type==='phone'" :class="[element.type,'form-item']">
|
|
|
+ <div class="tips">{{ element.label }}</div>
|
|
|
+ <div class="phone-input">
|
|
|
+ <el-select v-model="element.country" :placeholder="element.placeholder">
|
|
|
+ <el-option v-for="(item,index) in countryCode" :key="item.country_code+index" :label="'+'+item.phone_code+'('+item.chinese_name+')'" :value="item.country_code" />
|
|
|
+ </el-select>
|
|
|
+ <el-input v-model="element.value" :placeholder="element.placeholder" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
<div v-if="element.type==='select'" :class="[element.type,'form-item']">
|
|
|
<div class="tips">{{ element.label }}</div>
|
|
|
<el-select :value="element.value" :placeholder="element.placeholder">
|
|
|
@@ -239,6 +308,15 @@ export default Vue.extend({
|
|
|
<div class="tips">{{ element.label }}</div>
|
|
|
<el-input :value="element.value" type="textarea" :placeholder="element.placeholder" :autosize="{ minRows: element.minRows, maxRows: element.maxRows}" />
|
|
|
</div>
|
|
|
+ <div v-if="element.type==='region'" :class="[element.type,'form-item']">
|
|
|
+ <div class="tips">{{ element.label }}</div>
|
|
|
+ <el-cascader
|
|
|
+ :placeholder="element.placeholder"
|
|
|
+ size="large"
|
|
|
+ :options="element.range===2?pcTextArr:pcaTextArr"
|
|
|
+ value="element.value">
|
|
|
+ </el-cascader>
|
|
|
+ </div>
|
|
|
<div v-if="element.type==='time'" :class="[element.type,'form-item']">
|
|
|
<div class="tips">{{ element.label }}</div>
|
|
|
<el-time-picker :value="element.value" :placeholder="element.placeholder" />
|
|
|
@@ -269,7 +347,7 @@ export default Vue.extend({
|
|
|
</div>
|
|
|
<draggable v-model="formData" :group="{name:'form'}" :options="{sort:true,animation:300}" class="form-body" @start="handleStart" @end="handleEnd">
|
|
|
<transition-group class="drag-cont">
|
|
|
- <div v-for="element in formData" :key="element.key" :style="{gridColumn:'span '+element.width}" @click="choseComp(element)" @mouseenter="hover(element)" @mouseleave="blur(element)">
|
|
|
+ <div v-for="element in formData" :key="element.key" :style="{gridColumn:'span '+element.width}" :class="[element.required?'required':'']" @click="choseComp(element)" @mouseenter="hover(element)" @mouseleave="blur(element)">
|
|
|
<div v-if="element.type==='tips'" :class="[element.type,'form-item','view',{'active':element.key===hoverKey||element.key===currentKey}]">
|
|
|
<div class="tips">{{ element.label }}</div>
|
|
|
</div>
|
|
|
@@ -277,6 +355,25 @@ export default Vue.extend({
|
|
|
<div class="tips">{{ element.label }}</div>
|
|
|
<el-input :value="element.value" :placeholder="element.placeholder" />
|
|
|
</div>
|
|
|
+ <div v-if="element.type==='email'" :class="[element.type,'form-item','view',{'active':element.key===hoverKey||element.key===currentKey}]">
|
|
|
+ <div class="tips">{{ element.label }}</div>
|
|
|
+ <div>
|
|
|
+ <el-input v-model="element.value" :placeholder="element.placeholder" />
|
|
|
+ </div>
|
|
|
+ <div class="code-input">
|
|
|
+ <el-input v-model="element.value" :placeholder="element.codePlaceholder" />
|
|
|
+ <el-button>获取验证码</el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div v-if="element.type==='phone'" :class="[element.type,'form-item','view',{'active':element.key===hoverKey||element.key===currentKey}]">
|
|
|
+ <div class="tips">{{ element.label }}</div>
|
|
|
+ <div class="phone-input">
|
|
|
+ <el-select v-model="element.country" :placeholder="element.placeholder">
|
|
|
+ <el-option v-for="(item,index) in countryCode" :key="item.country_code+index" :label="'+'+item.phone_code+'('+item.chinese_name+')'" :value="item.country_code" />
|
|
|
+ </el-select>
|
|
|
+ <el-input v-model="element.value" :placeholder="element.placeholder" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
<div v-if="element.type==='select'" :class="[element.type,'form-item','view',{'active':element.key===hoverKey||element.key===currentKey}]">
|
|
|
<div class="tips">{{ element.label }}</div>
|
|
|
<el-select :value="element.value" :placeholder="element.placeholder">
|
|
|
@@ -307,6 +404,15 @@ export default Vue.extend({
|
|
|
<div class="tips">{{ element.label }}</div>
|
|
|
<el-input :value="element.value" type="textarea" :placeholder="element.placeholder" :autosize="{ minRows: element.minRows, maxRows: element.maxRows}" />
|
|
|
</div>
|
|
|
+ <div v-if="element.type==='region'" :class="[element.type,'form-item','view',{'active':element.key===hoverKey||element.key===currentKey}]">
|
|
|
+ <div class="tips">{{ element.label }}</div>
|
|
|
+ <el-cascader
|
|
|
+ :placeholder="element.placeholder"
|
|
|
+ size="large"
|
|
|
+ :options="element.range===2?pcTextArr:pcaTextArr"
|
|
|
+ value="element.value">
|
|
|
+ </el-cascader>
|
|
|
+ </div>
|
|
|
<div v-if="element.type==='time'" :class="[element.type,'form-item','view',{'active':element.key===hoverKey||element.key===currentKey}]">
|
|
|
<div class="tips">{{ element.label }}</div>
|
|
|
<el-time-picker :value="element.value" :placeholder="element.placeholder" />
|
|
|
@@ -359,7 +465,12 @@ export default Vue.extend({
|
|
|
</div>
|
|
|
<el-input v-model="currentData.label" type="textarea" placeholder="请输入表单项介绍"></el-input>
|
|
|
|
|
|
- <template v-if="['input','select','textarea','time','date'].includes(currentData.type)">
|
|
|
+ <template>
|
|
|
+ <div class="tips">是否必填</div>
|
|
|
+ <el-switch v-model="currentData.required" />
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template v-if="['input','select','textarea','time','date','region','email','phone'].includes(currentData.type)">
|
|
|
<div class="tips">
|
|
|
提示文字
|
|
|
<guide
|
|
|
@@ -371,6 +482,27 @@ export default Vue.extend({
|
|
|
<el-input v-model="currentData.placeholder" placeholder="请输入提示文字"></el-input>
|
|
|
</template>
|
|
|
|
|
|
+ <template v-if="['input','textarea'].includes(currentData.type)">
|
|
|
+ <div class="tips">验证规则</div>
|
|
|
+ <el-input v-model="currentData.pattern" :rows="3" type="textarea" placeholder="规则正则表达式"></el-input>
|
|
|
+ <el-select class="pattern-select" @change="currentData.pattern=$event" placeholder="选择预设规则">
|
|
|
+ <el-option label="不做判断" value="^[\s\S]*$"></el-option>
|
|
|
+ <el-option label="国内手机号" value="^1\d{10}$"></el-option>
|
|
|
+ <el-option label="国内身份证号码" value="^[1-9]\d{5}(19\d{2}|20\d{2})((0[1-9])|(1[0-2]))((0[1-9])|([1-2]\d)|(3[0-1]))\d{3}(\d|X|x)$"></el-option>
|
|
|
+ <el-option label="电子邮箱" value="^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$"></el-option>
|
|
|
+ </el-select>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template v-if="currentData.type==='region'">
|
|
|
+ <div class="tips">
|
|
|
+ 地区范围
|
|
|
+ </div>
|
|
|
+ <el-radio-group size="small" v-model="currentData.range">
|
|
|
+ <el-radio-button :label="2">省/市</el-radio-button>
|
|
|
+ <el-radio-button :label="3">省/市/县</el-radio-button>
|
|
|
+ </el-radio-group>
|
|
|
+ </template>
|
|
|
+
|
|
|
<template v-if="['timeRange','dateRange'].includes(currentData.type)">
|
|
|
<div class="tips">
|
|
|
起始提示文字
|
|
|
@@ -462,12 +594,14 @@ export default Vue.extend({
|
|
|
<guide
|
|
|
video="/static/guide/组件宽度.mp4"
|
|
|
title="组件宽度"
|
|
|
- text="设置所选定组件的宽度,使其占据全部宽度或者只占据一半宽度。"
|
|
|
+ text="设置所选定组件的宽度,有1/3、1/2、2/3、占据全部宽度,总共四种尺寸供选择。"
|
|
|
></guide>
|
|
|
</div>
|
|
|
<el-radio-group size="small" v-model="currentData.width">
|
|
|
- <el-radio-button :label="1">窄</el-radio-button>
|
|
|
- <el-radio-button :label="2">宽</el-radio-button>
|
|
|
+ <el-radio-button :label="2">窄</el-radio-button>
|
|
|
+ <el-radio-button :label="3">中</el-radio-button>
|
|
|
+ <el-radio-button :label="4">宽</el-radio-button>
|
|
|
+ <el-radio-button :label="6">长</el-radio-button>
|
|
|
</el-radio-group>
|
|
|
|
|
|
</div>
|
|
|
@@ -514,6 +648,19 @@ export default Vue.extend({
|
|
|
color: #989898;
|
|
|
margin-bottom: 8px;
|
|
|
}
|
|
|
+ &.email{
|
|
|
+ .code-input{
|
|
|
+ display: flex;
|
|
|
+ grid-gap: 8px;
|
|
|
+ margin-top: 8px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ &.phone{
|
|
|
+ .phone-input{
|
|
|
+ display: flex;
|
|
|
+ grid-gap: 8px;
|
|
|
+ }
|
|
|
+ }
|
|
|
&.select{
|
|
|
.el-select{
|
|
|
width: 100%;
|
|
|
@@ -534,6 +681,11 @@ export default Vue.extend({
|
|
|
width: 100%;
|
|
|
}
|
|
|
}
|
|
|
+ &.region{
|
|
|
+ .el-cascader{
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+ }
|
|
|
&.view{
|
|
|
transition-duration: 300ms;
|
|
|
border-radius: 8px;
|
|
|
@@ -589,6 +741,8 @@ export default Vue.extend({
|
|
|
position: sticky;
|
|
|
left: 0;
|
|
|
top: 0;
|
|
|
+ border-bottom-right-radius: 0;
|
|
|
+ border-bottom-left-radius: 0;
|
|
|
border: 1px solid lightgrey;
|
|
|
height: 100%;
|
|
|
.del{
|
|
|
@@ -683,13 +837,22 @@ export default Vue.extend({
|
|
|
.form-body{
|
|
|
.drag-cont{
|
|
|
display: grid;
|
|
|
- grid-template-columns: 1fr 1fr;
|
|
|
+ grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr;
|
|
|
width: 100%;
|
|
|
min-height: 300px;
|
|
|
align-content: start;
|
|
|
.form-item{
|
|
|
height: fit-content;
|
|
|
}
|
|
|
+ .required{
|
|
|
+ .tips{
|
|
|
+ &::after{
|
|
|
+ margin-left: 4px;
|
|
|
+ content: '*';
|
|
|
+ color: red;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -713,6 +876,10 @@ export default Vue.extend({
|
|
|
margin-bottom: 6px;
|
|
|
margin-top: 12px;
|
|
|
}
|
|
|
+ .pattern-select{
|
|
|
+ margin-top: 6px;
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
.select-list{
|
|
|
width: 100%;
|
|
|
.handel{
|