|
@@ -1,12 +1,9 @@
|
|
|
<script lang="ts">
|
|
<script lang="ts">
|
|
|
import Vue from 'vue'
|
|
import Vue from 'vue'
|
|
|
|
|
+import { saveForm, getFormInfo } from '@/api/form'
|
|
|
import guide from '@/views/guide/index'
|
|
import guide from '@/views/guide/index'
|
|
|
import draggable from 'vuedraggable'
|
|
import draggable from 'vuedraggable'
|
|
|
import countryCode from '@/lib/countryCode.json'
|
|
import countryCode from '@/lib/countryCode.json'
|
|
|
-import {
|
|
|
|
|
- pcTextArr,
|
|
|
|
|
- pcaTextArr
|
|
|
|
|
-} from "element-china-area-data"
|
|
|
|
|
|
|
|
|
|
export default Vue.extend({
|
|
export default Vue.extend({
|
|
|
name: 'Edit',
|
|
name: 'Edit',
|
|
@@ -18,169 +15,238 @@ export default Vue.extend({
|
|
|
return {
|
|
return {
|
|
|
compList: [
|
|
compList: [
|
|
|
{
|
|
{
|
|
|
- type: 'tips',
|
|
|
|
|
- label: '将我拖拽至右边试试吧',
|
|
|
|
|
- width: 6,
|
|
|
|
|
|
|
+ type: 'input',
|
|
|
|
|
+ name: 'first_name',
|
|
|
|
|
+ label: '请在下方输入名字',
|
|
|
|
|
+ value: '',
|
|
|
|
|
+ width: 1,
|
|
|
|
|
+ placeholder: '请输入名字',
|
|
|
required: false
|
|
required: false
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
type: 'input',
|
|
type: 'input',
|
|
|
- label: '请在下方输入内容',
|
|
|
|
|
|
|
+ name: 'last_name',
|
|
|
|
|
+ label: '请在下方输入姓氏',
|
|
|
value: '',
|
|
value: '',
|
|
|
- width: 6,
|
|
|
|
|
- placeholder: '请输入',
|
|
|
|
|
- pattern: '^[\\s\\S]*$',
|
|
|
|
|
|
|
+ width: 1,
|
|
|
|
|
+ placeholder: '请输入姓氏',
|
|
|
|
|
+ required: false
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ type: 'select',
|
|
|
|
|
+ name: 'id_type',
|
|
|
|
|
+ label: '请在下方选择证件类型',
|
|
|
|
|
+ value: '',
|
|
|
|
|
+ width: 1,
|
|
|
|
|
+ options: [
|
|
|
|
|
+ { label: '身份证', value: 'id' },
|
|
|
|
|
+ { label: '护照', value: 'passport' },
|
|
|
|
|
+ ],
|
|
|
|
|
+ placeholder: '请选择',
|
|
|
|
|
+ required: false
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ type: 'input',
|
|
|
|
|
+ name: 'id_number',
|
|
|
|
|
+ label: '请在下方输入证件号码',
|
|
|
|
|
+ value: '',
|
|
|
|
|
+ width: 1,
|
|
|
|
|
+ placeholder: '请输入证件号码',
|
|
|
required: false
|
|
required: false
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
type: 'phone',
|
|
type: 'phone',
|
|
|
|
|
+ name: 'mobile',
|
|
|
label: '请在下方输入手机号码',
|
|
label: '请在下方输入手机号码',
|
|
|
value: '',
|
|
value: '',
|
|
|
country: 'CN',
|
|
country: 'CN',
|
|
|
- width: 6,
|
|
|
|
|
|
|
+ width: 1,
|
|
|
placeholder: '请输入手机号',
|
|
placeholder: '请输入手机号',
|
|
|
required: false
|
|
required: false
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
type: 'email',
|
|
type: 'email',
|
|
|
|
|
+ name: 'email',
|
|
|
label: '请在下方输入邮箱',
|
|
label: '请在下方输入邮箱',
|
|
|
value: '',
|
|
value: '',
|
|
|
- width: 6,
|
|
|
|
|
|
|
+ width: 1,
|
|
|
placeholder: '请输入邮箱',
|
|
placeholder: '请输入邮箱',
|
|
|
codePlaceholder: '请输入验证码',
|
|
codePlaceholder: '请输入验证码',
|
|
|
required: false
|
|
required: false
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
- type: 'select',
|
|
|
|
|
- label: '请在下方选择内容',
|
|
|
|
|
|
|
+ type: 'input',
|
|
|
|
|
+ name: 'company',
|
|
|
|
|
+ label: '请在下方输入公司名称',
|
|
|
value: '',
|
|
value: '',
|
|
|
width: 6,
|
|
width: 6,
|
|
|
- options: [
|
|
|
|
|
- { label: '东坡肉', value: '东坡肉' },
|
|
|
|
|
- { label: '酱肘子', value: '酱肘子' },
|
|
|
|
|
- { label: '白切鸡', value: '白切鸡' }
|
|
|
|
|
- ],
|
|
|
|
|
- placeholder: '请选择',
|
|
|
|
|
|
|
+ placeholder: '请输入公司名称',
|
|
|
required: false
|
|
required: false
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
- type: 'checkbox',
|
|
|
|
|
- label: '请选择一至多项内容',
|
|
|
|
|
|
|
+ type: 'input',
|
|
|
|
|
+ name: 'department',
|
|
|
|
|
+ label: '请在下方输入部门名称',
|
|
|
value: '',
|
|
value: '',
|
|
|
- width: 6,
|
|
|
|
|
- options: [
|
|
|
|
|
- { label: '东坡肉', value: '东坡肉' },
|
|
|
|
|
- { label: '酱肘子', value: '酱肘子' },
|
|
|
|
|
- { label: '白切鸡', value: '白切鸡' }
|
|
|
|
|
- ],
|
|
|
|
|
|
|
+ width: 1,
|
|
|
|
|
+ placeholder: '请输入部门名称',
|
|
|
required: false
|
|
required: false
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
- type: 'radio',
|
|
|
|
|
- label: '请选择一项内容',
|
|
|
|
|
|
|
+ type: 'select',
|
|
|
|
|
+ name: 'position',
|
|
|
|
|
+ label: '请在下方选择职位',
|
|
|
value: '',
|
|
value: '',
|
|
|
- width: 6,
|
|
|
|
|
|
|
+ width: 1,
|
|
|
options: [
|
|
options: [
|
|
|
- { label: '东坡肉', value: '东坡肉' },
|
|
|
|
|
- { label: '酱肘子', value: '酱肘子' },
|
|
|
|
|
- { label: '白切鸡', value: '白切鸡' }
|
|
|
|
|
|
|
+ { label: '职位', value: '职位' }
|
|
|
],
|
|
],
|
|
|
|
|
+ placeholder: '请选择',
|
|
|
required: false
|
|
required: false
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
- type: 'number',
|
|
|
|
|
- label: '请在下方输入数字',
|
|
|
|
|
- max: 10,
|
|
|
|
|
- min: 0,
|
|
|
|
|
- step: 1,
|
|
|
|
|
- value: 0,
|
|
|
|
|
- width: 6,
|
|
|
|
|
- required: false
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- type: 'slider',
|
|
|
|
|
- label: '请在下方滑动',
|
|
|
|
|
- max: 10,
|
|
|
|
|
- min: 0,
|
|
|
|
|
- step: 1,
|
|
|
|
|
- value: 0,
|
|
|
|
|
- width: 6,
|
|
|
|
|
- required: false
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- type: 'textarea',
|
|
|
|
|
- label: '请在下方输入内容',
|
|
|
|
|
|
|
+ type: 'select',
|
|
|
|
|
+ name: 'country',
|
|
|
|
|
+ label: '请在下方选择国家',
|
|
|
value: '',
|
|
value: '',
|
|
|
- maxRows: 4,
|
|
|
|
|
- minRows: 2,
|
|
|
|
|
- width: 6,
|
|
|
|
|
- placeholder: '请输入',
|
|
|
|
|
- required: false,
|
|
|
|
|
- pattern: '^[\\s\\S]*$'
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- type: 'region',
|
|
|
|
|
- label: '请在下方选择位置',
|
|
|
|
|
- range: 2,
|
|
|
|
|
- width: 6,
|
|
|
|
|
- value: [],
|
|
|
|
|
- placeholder: '请选择所在区域',
|
|
|
|
|
|
|
+ width: 1,
|
|
|
|
|
+ options: [
|
|
|
|
|
+ { label: '国家', value: '国家' }
|
|
|
|
|
+ ],
|
|
|
|
|
+ placeholder: '请选择',
|
|
|
required: false
|
|
required: false
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
- type: 'time',
|
|
|
|
|
- label: '请在下方选择时间',
|
|
|
|
|
|
|
+ type: 'select',
|
|
|
|
|
+ name: 'province',
|
|
|
|
|
+ label: '请在下方选择省份',
|
|
|
value: '',
|
|
value: '',
|
|
|
- width: 6,
|
|
|
|
|
- placeholder: '请选择时间',
|
|
|
|
|
|
|
+ width: 1,
|
|
|
|
|
+ options: [
|
|
|
|
|
+ { label: '省份', value: '省份' }
|
|
|
|
|
+ ],
|
|
|
|
|
+ placeholder: '请选择',
|
|
|
required: false
|
|
required: false
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
- type: 'timeRange',
|
|
|
|
|
- label: '请在下方选择时间范围',
|
|
|
|
|
|
|
+ type: 'select',
|
|
|
|
|
+ name: 'city',
|
|
|
|
|
+ label: '请在下方选择市',
|
|
|
value: '',
|
|
value: '',
|
|
|
- width: 6,
|
|
|
|
|
- rangeSeparator: '至',
|
|
|
|
|
- placeholder: '开始时间',
|
|
|
|
|
- endPlaceholder: '结束时间',
|
|
|
|
|
|
|
+ width: 1,
|
|
|
|
|
+ options: [
|
|
|
|
|
+ { label: '市', value: '市' }
|
|
|
|
|
+ ],
|
|
|
|
|
+ placeholder: '请选择',
|
|
|
required: false
|
|
required: false
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
- type: 'date',
|
|
|
|
|
- label: '请在下方选择日期',
|
|
|
|
|
|
|
+ type: 'input',
|
|
|
|
|
+ name: 'address',
|
|
|
|
|
+ label: '请在下方输入地址',
|
|
|
value: '',
|
|
value: '',
|
|
|
- width: 6,
|
|
|
|
|
- placeholder: '请选择日期',
|
|
|
|
|
|
|
+ width: 1,
|
|
|
|
|
+ placeholder: '请输入地址',
|
|
|
required: false
|
|
required: false
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
|
- type: 'dateRange',
|
|
|
|
|
- label: '请在下方选择日期范围',
|
|
|
|
|
|
|
+ type: 'select',
|
|
|
|
|
+ name: 'industry',
|
|
|
|
|
+ label: '请在下方选择行业',
|
|
|
value: '',
|
|
value: '',
|
|
|
- width: 6,
|
|
|
|
|
- rangeSeparator: '至',
|
|
|
|
|
- placeholder: '开始日期',
|
|
|
|
|
- endPlaceholder: '结束日期',
|
|
|
|
|
|
|
+ width: 1,
|
|
|
|
|
+ options: [
|
|
|
|
|
+ { label: '行业', value: '行业' }
|
|
|
|
|
+ ],
|
|
|
|
|
+ placeholder: '请选择',
|
|
|
required: false
|
|
required: false
|
|
|
- }
|
|
|
|
|
|
|
+ },
|
|
|
],
|
|
],
|
|
|
formData: [],
|
|
formData: [],
|
|
|
trashData: [],
|
|
trashData: [],
|
|
|
formInfo: {
|
|
formInfo: {
|
|
|
name: '未命名表单',
|
|
name: '未命名表单',
|
|
|
- desc: '从右侧拖动组件到表单区域'
|
|
|
|
|
|
|
+ desc: '从右侧拖动组件到表单区域',
|
|
|
|
|
+ id: ''
|
|
|
},
|
|
},
|
|
|
isDrag: false,
|
|
isDrag: false,
|
|
|
currentKey: '',
|
|
currentKey: '',
|
|
|
currentData: {},
|
|
currentData: {},
|
|
|
hoverKey: '',
|
|
hoverKey: '',
|
|
|
selectInput: '',
|
|
selectInput: '',
|
|
|
- pcTextArr,
|
|
|
|
|
- pcaTextArr,
|
|
|
|
|
- countryCode
|
|
|
|
|
|
|
+ countryCode,
|
|
|
|
|
+ loading: false
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
|
|
+ mounted() {
|
|
|
|
|
+ this.init()
|
|
|
|
|
+ },
|
|
|
methods: {
|
|
methods: {
|
|
|
|
|
+ init() {
|
|
|
|
|
+ function getType(name) {
|
|
|
|
|
+ if(['first_name','last_name','id_number','company','department','address'].includes(name)) {
|
|
|
|
|
+ return 'input'
|
|
|
|
|
+ }
|
|
|
|
|
+ if(['id_type','position','province','city','industry'].includes(name)) {
|
|
|
|
|
+ return 'select'
|
|
|
|
|
+ }
|
|
|
|
|
+ if(['mobile'].includes(name)) {
|
|
|
|
|
+ return 'phone'
|
|
|
|
|
+ }
|
|
|
|
|
+ if(['email'].includes(name)) {
|
|
|
|
|
+ return 'email'
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if (this.$route.params.id) {
|
|
|
|
|
+ this.loading = true
|
|
|
|
|
+ this.formInfo.id = this.$route.params.id
|
|
|
|
|
+ getFormInfo(this.formInfo.id).then(res => {
|
|
|
|
|
+ this.loading = false
|
|
|
|
|
+ this.formInfo.name = res.data.template_name
|
|
|
|
|
+ this.formInfo.desc = res.data.description
|
|
|
|
|
+ res.data.fields.forEach(item => {
|
|
|
|
|
+ console.log(item)
|
|
|
|
|
+ this.formData.push({
|
|
|
|
|
+ key: item.id,
|
|
|
|
|
+ type: getType(item.field_name),
|
|
|
|
|
+ name: item.field_name,
|
|
|
|
|
+ label: item.field_label,
|
|
|
|
|
+ value: '',
|
|
|
|
|
+ width: 1,
|
|
|
|
|
+ placeholder: '请输入',
|
|
|
|
|
+ required: item.is_required
|
|
|
|
|
+ })
|
|
|
|
|
+ })
|
|
|
|
|
+ console.log(res)
|
|
|
|
|
+ }).catch(err => {
|
|
|
|
|
+ this.loading = false
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ save() {
|
|
|
|
|
+ if (this.loading) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ this.loading = true
|
|
|
|
|
+ const saveData = []
|
|
|
|
|
+ this.formData.forEach(item => {
|
|
|
|
|
+ saveData.push({
|
|
|
|
|
+ field_name: item.name,
|
|
|
|
|
+ field_label: item.label,
|
|
|
|
|
+ is_required: item.required,
|
|
|
|
|
+ })
|
|
|
|
|
+ })
|
|
|
|
|
+ saveForm(this.formInfo.id, this.formInfo.name, this.formInfo.desc, saveData).then(res => {
|
|
|
|
|
+ this.loading = false
|
|
|
|
|
+ this.$message.success('保存成功')
|
|
|
|
|
+ this.$router.push('/preRegister/list')
|
|
|
|
|
+ console.log(res)
|
|
|
|
|
+ }).catch(err => {
|
|
|
|
|
+ this.loading = false
|
|
|
|
|
+ this.$message.error('保存失败')
|
|
|
|
|
+ console.log(err)
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
choseComp(element) {
|
|
choseComp(element) {
|
|
|
this.currentKey = element.key
|
|
this.currentKey = element.key
|
|
|
this.currentData = element
|
|
this.currentData = element
|
|
@@ -192,7 +258,7 @@ export default Vue.extend({
|
|
|
type: 'warning',
|
|
type: 'warning',
|
|
|
callback: action => {
|
|
callback: action => {
|
|
|
if (action === 'confirm') {
|
|
if (action === 'confirm') {
|
|
|
- let index = this.getIndexByKey(element.key)
|
|
|
|
|
|
|
+ const index = this.getIndexByKey(element.key)
|
|
|
this.formData.splice(index, 1)
|
|
this.formData.splice(index, 1)
|
|
|
this.currentKey = ''
|
|
this.currentKey = ''
|
|
|
}
|
|
}
|
|
@@ -215,9 +281,9 @@ export default Vue.extend({
|
|
|
newItem.key = newItem.type + new Date().getTime()
|
|
newItem.key = newItem.type + new Date().getTime()
|
|
|
return newItem
|
|
return newItem
|
|
|
},
|
|
},
|
|
|
- removeTrash(element){
|
|
|
|
|
- let index = this.getIndexByKey(element.key)
|
|
|
|
|
- this.trashData.splice(index,1)
|
|
|
|
|
|
|
+ removeTrash(element) {
|
|
|
|
|
+ const index = this.getIndexByKey(element.key)
|
|
|
|
|
+ this.trashData.splice(index, 1)
|
|
|
},
|
|
},
|
|
|
hover(element) {
|
|
hover(element) {
|
|
|
if (this.isDrag) return
|
|
if (this.isDrag) return
|
|
@@ -243,7 +309,7 @@ export default Vue.extend({
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|
|
|
<template>
|
|
<template>
|
|
|
- <div class="main-box">
|
|
|
|
|
|
|
+ <div v-loading="loading" class="main-box">
|
|
|
<div class="comp-lib">
|
|
<div class="comp-lib">
|
|
|
<div class="title">
|
|
<div class="title">
|
|
|
组件库
|
|
组件库
|
|
@@ -251,10 +317,7 @@ export default Vue.extend({
|
|
|
<div class="list">
|
|
<div class="list">
|
|
|
<draggable v-model="compList" :options="{sort:false}" :group="{name:'form',put:false,pull:'clone'}" :clone="cloneItem" class="drag-list">
|
|
<draggable v-model="compList" :options="{sort:false}" :group="{name:'form',put:false,pull:'clone'}" :clone="cloneItem" class="drag-list">
|
|
|
<transition-group class="drag-cont">
|
|
<transition-group class="drag-cont">
|
|
|
- <div v-for="(element) in compList" :key="element.type">
|
|
|
|
|
- <div v-if="element.type==='tips'" :class="[element.type,'form-item']">
|
|
|
|
|
- <div class="tips">{{ element.label }}</div>
|
|
|
|
|
- </div>
|
|
|
|
|
|
|
+ <div v-for="(element) in compList" :key="element.name">
|
|
|
<div v-if="element.type==='input'" :class="[element.type,'form-item']">
|
|
<div v-if="element.type==='input'" :class="[element.type,'form-item']">
|
|
|
<div class="tips">{{ element.label }}</div>
|
|
<div class="tips">{{ element.label }}</div>
|
|
|
<el-input :value="element.value" :placeholder="element.placeholder" />
|
|
<el-input :value="element.value" :placeholder="element.placeholder" />
|
|
@@ -284,55 +347,6 @@ export default Vue.extend({
|
|
|
<el-option v-for="item in element.options" :key="item.value" :label="item.label" :value="item.value" />
|
|
<el-option v-for="item in element.options" :key="item.value" :label="item.label" :value="item.value" />
|
|
|
</el-select>
|
|
</el-select>
|
|
|
</div>
|
|
</div>
|
|
|
- <div v-if="element.type==='checkbox'" :class="[element.type,'form-item']">
|
|
|
|
|
- <div class="tips">{{ element.label }}</div>
|
|
|
|
|
- <el-checkbox-group :value="element.value">
|
|
|
|
|
- <el-checkbox v-for="item in element.options" :key="item.value" :label="item.label" />
|
|
|
|
|
- </el-checkbox-group>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div v-if="element.type==='radio'" :class="[element.type,'form-item']">
|
|
|
|
|
- <div class="tips">{{ element.label }}</div>
|
|
|
|
|
- <el-radio-group :value="element.value">
|
|
|
|
|
- <el-radio v-for="item in element.options" :key="item.value" :label="item.label" />
|
|
|
|
|
- </el-radio-group>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div v-if="element.type==='number'" :class="[element.type,'form-item']">
|
|
|
|
|
- <div class="tips">{{ element.label }}</div>
|
|
|
|
|
- <el-input-number :value="element.value" :max="element.max" :min="element.min" :step="element.step" prefix-icon="el-icon-user" :placeholder="element.placeholder" />
|
|
|
|
|
- </div>
|
|
|
|
|
- <div v-if="element.type==='slider'" :class="[element.type,'form-item']">
|
|
|
|
|
- <div class="tips">{{ element.label }}</div>
|
|
|
|
|
- <el-slider :value="element.value" :max="element.max" :min="element.min" :step="element.step" prefix-icon="el-icon-user" :placeholder="element.placeholder" />
|
|
|
|
|
- </div>
|
|
|
|
|
- <div v-if="element.type==='textarea'" :class="[element.type,'form-item']">
|
|
|
|
|
- <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" />
|
|
|
|
|
- </div>
|
|
|
|
|
- <div v-if="element.type==='timeRange'" :class="[element.type,'form-item']">
|
|
|
|
|
- <div class="tips">{{ element.label }}</div>
|
|
|
|
|
- <el-time-picker is-range :value="element.value" :start-placeholder="element.placeholder" :end-placeholder="element.endPlaceholder" :range-separator="element.rangeSeparator" />
|
|
|
|
|
- </div>
|
|
|
|
|
- <div v-if="element.type==='date'" :class="[element.type,'form-item']">
|
|
|
|
|
- <div class="tips">{{ element.label }}</div>
|
|
|
|
|
- <el-date-picker :value="element.value" :placeholder="element.placeholder" />
|
|
|
|
|
- </div>
|
|
|
|
|
- <div v-if="element.type==='dateRange'" :class="[element.type,'form-item']">
|
|
|
|
|
- <div class="tips">{{ element.label }}</div>
|
|
|
|
|
- <el-date-picker :value="element.value" type="daterange" :start-placeholder="element.placeholder" :end-placeholder="element.endPlaceholder" :range-separator="element.rangeSeparator" />
|
|
|
|
|
- </div>
|
|
|
|
|
</div>
|
|
</div>
|
|
|
</transition-group>
|
|
</transition-group>
|
|
|
</draggable>
|
|
</draggable>
|
|
@@ -348,9 +362,6 @@ export default Vue.extend({
|
|
|
<draggable v-model="formData" :group="{name:'form'}" :options="{sort:true,animation:300}" class="form-body" @start="handleStart" @end="handleEnd">
|
|
<draggable v-model="formData" :group="{name:'form'}" :options="{sort:true,animation:300}" class="form-body" @start="handleStart" @end="handleEnd">
|
|
|
<transition-group class="drag-cont">
|
|
<transition-group class="drag-cont">
|
|
|
<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-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>
|
|
|
|
|
<div v-if="element.type==='input'" :class="[element.type,'form-item','view',{'active':element.key===hoverKey||element.key===currentKey}]">
|
|
<div v-if="element.type==='input'" :class="[element.type,'form-item','view',{'active':element.key===hoverKey||element.key===currentKey}]">
|
|
|
<div class="tips">{{ element.label }}</div>
|
|
<div class="tips">{{ element.label }}</div>
|
|
|
<el-input :value="element.value" :placeholder="element.placeholder" />
|
|
<el-input :value="element.value" :placeholder="element.placeholder" />
|
|
@@ -380,55 +391,6 @@ export default Vue.extend({
|
|
|
<el-option v-for="item in element.options" :key="item.value" :label="item.label" :value="item.value" />
|
|
<el-option v-for="item in element.options" :key="item.value" :label="item.label" :value="item.value" />
|
|
|
</el-select>
|
|
</el-select>
|
|
|
</div>
|
|
</div>
|
|
|
- <div v-if="element.type==='checkbox'" :class="[element.type,'form-item','view',{'active':element.key===hoverKey||element.key===currentKey}]">
|
|
|
|
|
- <div class="tips">{{ element.label }}</div>
|
|
|
|
|
- <el-checkbox-group :value="element.value">
|
|
|
|
|
- <el-checkbox v-for="item in element.options" :key="item.value" :label="item.label" />
|
|
|
|
|
- </el-checkbox-group>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div v-if="element.type==='radio'" :class="[element.type,'form-item','view',{'active':element.key===hoverKey||element.key===currentKey}]">
|
|
|
|
|
- <div class="tips">{{ element.label }}</div>
|
|
|
|
|
- <el-radio-group :value="element.value">
|
|
|
|
|
- <el-radio v-for="item in element.options" :key="item.value" :label="item.label" />
|
|
|
|
|
- </el-radio-group>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div v-if="element.type==='number'" :class="[element.type,'form-item','view',{'active':element.key===hoverKey||element.key===currentKey}]">
|
|
|
|
|
- <div class="tips">{{ element.label }}</div>
|
|
|
|
|
- <el-input-number :value="element.value" :max="element.max" :min="element.min" :step="element.step" prefix-icon="el-icon-user" :placeholder="element.placeholder" />
|
|
|
|
|
- </div>
|
|
|
|
|
- <div v-if="element.type==='slider'" :class="[element.type,'form-item','view',{'active':element.key===hoverKey||element.key===currentKey}]">
|
|
|
|
|
- <div class="tips">{{ element.label }}</div>
|
|
|
|
|
- <el-slider :value="element.value" :max="element.max" :min="element.min" :step="element.step" prefix-icon="el-icon-user" :placeholder="element.placeholder" />
|
|
|
|
|
- </div>
|
|
|
|
|
- <div v-if="element.type==='textarea'" :class="[element.type,'form-item','view',{'active':element.key===hoverKey||element.key===currentKey}]">
|
|
|
|
|
- <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" />
|
|
|
|
|
- </div>
|
|
|
|
|
- <div v-if="element.type==='timeRange'" :class="[element.type,'view','form-item',{'active':element.key===hoverKey||element.key===currentKey}]">
|
|
|
|
|
- <div class="tips">{{ element.label }}</div>
|
|
|
|
|
- <el-time-picker is-range :value="element.value" :start-placeholder="element.placeholder" :end-placeholder="element.endPlaceholder" :range-separator="element.rangeSeparator" />
|
|
|
|
|
- </div>
|
|
|
|
|
- <div v-if="element.type==='date'" :class="[element.type,'form-item','view',{'active':element.key===hoverKey||element.key===currentKey}]">
|
|
|
|
|
- <div class="tips">{{ element.label }}</div>
|
|
|
|
|
- <el-date-picker :value="element.value" :placeholder="element.placeholder" />
|
|
|
|
|
- </div>
|
|
|
|
|
- <div v-if="element.type==='dateRange'" :class="[element.type,'form-item','view',{'active':element.key===hoverKey||element.key===currentKey}]">
|
|
|
|
|
- <div class="tips">{{ element.label }}</div>
|
|
|
|
|
- <el-date-picker :value="element.value" type="daterange" :start-placeholder="element.placeholder" :end-placeholder="element.endPlaceholder" :range-separator="element.rangeSeparator" />
|
|
|
|
|
- </div>
|
|
|
|
|
</div>
|
|
</div>
|
|
|
</transition-group>
|
|
</transition-group>
|
|
|
</draggable>
|
|
</draggable>
|
|
@@ -438,18 +400,18 @@ export default Vue.extend({
|
|
|
<div class="comp-edit">
|
|
<div class="comp-edit">
|
|
|
<template v-if="getIndexByKey(currentKey) === -1">
|
|
<template v-if="getIndexByKey(currentKey) === -1">
|
|
|
<div class="button">
|
|
<div class="button">
|
|
|
- <el-button type="primary">保存表单</el-button>
|
|
|
|
|
|
|
+ <el-button type="primary" @click="save">保存表单</el-button>
|
|
|
</div>
|
|
</div>
|
|
|
<div class="title">表单设定</div>
|
|
<div class="title">表单设定</div>
|
|
|
<div class="body">
|
|
<div class="body">
|
|
|
<div class="tips">表单名称</div>
|
|
<div class="tips">表单名称</div>
|
|
|
<el-input v-model="formInfo.name" placeholder="请输入表单名称" />
|
|
<el-input v-model="formInfo.name" placeholder="请输入表单名称" />
|
|
|
<div class="tips">表单介绍</div>
|
|
<div class="tips">表单介绍</div>
|
|
|
- <el-input type="textarea" v-model="formInfo.desc" placeholder="请输入表单介绍" />
|
|
|
|
|
|
|
+ <el-input v-model="formInfo.desc" type="textarea" placeholder="请输入表单介绍" />
|
|
|
</div>
|
|
</div>
|
|
|
</template>
|
|
</template>
|
|
|
<template v-else>
|
|
<template v-else>
|
|
|
- <div></div>
|
|
|
|
|
|
|
+ <div />
|
|
|
<div class="title">
|
|
<div class="title">
|
|
|
<span class="el-icon-arrow-left icon" @click="currentKey=''" />
|
|
<span class="el-icon-arrow-left icon" @click="currentKey=''" />
|
|
|
组件设定
|
|
组件设定
|
|
@@ -462,152 +424,18 @@ export default Vue.extend({
|
|
|
video="/static/guide/表单项介绍.jpg"
|
|
video="/static/guide/表单项介绍.jpg"
|
|
|
title="表单项介绍"
|
|
title="表单项介绍"
|
|
|
text="展示在输入框上方的大段文本,用于介绍和提示该处应输入的内容。"
|
|
text="展示在输入框上方的大段文本,用于介绍和提示该处应输入的内容。"
|
|
|
- ></guide>
|
|
|
|
|
|
|
+ />
|
|
|
</div>
|
|
</div>
|
|
|
- <el-input v-model="currentData.label" type="textarea" placeholder="请输入表单项介绍"></el-input>
|
|
|
|
|
|
|
+ <el-input v-model="currentData.label" type="textarea" placeholder="请输入表单项介绍" />
|
|
|
|
|
|
|
|
<template>
|
|
<template>
|
|
|
<div class="tips">是否必填</div>
|
|
<div class="tips">是否必填</div>
|
|
|
<el-switch v-model="currentData.required" />
|
|
<el-switch v-model="currentData.required" />
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
- <template v-if="['input','select','textarea','time','date','region','email','phone'].includes(currentData.type)">
|
|
|
|
|
- <div class="tips">
|
|
|
|
|
- 提示文字
|
|
|
|
|
- <guide
|
|
|
|
|
- video="/static/guide/提示文字.jpg"
|
|
|
|
|
- title="提示文字"
|
|
|
|
|
- text="用户输入内容前,展示在输入框中的简短文本,用于提示该处应输入的内容。"
|
|
|
|
|
- ></guide>
|
|
|
|
|
- </div>
|
|
|
|
|
- <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">
|
|
|
|
|
- 起始提示文字
|
|
|
|
|
- <guide
|
|
|
|
|
- video="/static/guide/起始提示文字.jpg"
|
|
|
|
|
- title="起始提示文字"
|
|
|
|
|
- text="时间与日期类型组件输入内容前,显示在开始时间输入框中,用于提示的文字内容"
|
|
|
|
|
- ></guide>
|
|
|
|
|
- </div>
|
|
|
|
|
- <el-input v-model="currentData.placeholder" placeholder="请输入起始提示文字"></el-input>
|
|
|
|
|
- <div class="tips">
|
|
|
|
|
- 结束提示文字
|
|
|
|
|
- <guide
|
|
|
|
|
- video="/static/guide/结束提示文字.jpg"
|
|
|
|
|
- title="结束提示文字"
|
|
|
|
|
- text="时间与日期类型组件输入内容前,显示在结束时间输入框中,用于提示的文字内容"
|
|
|
|
|
- ></guide>
|
|
|
|
|
- </div>
|
|
|
|
|
- <el-input v-model="currentData.endPlaceholder" placeholder="请输入结束提示文字"></el-input>
|
|
|
|
|
- <div class="tips">
|
|
|
|
|
- 范围分隔符
|
|
|
|
|
- <guide
|
|
|
|
|
- video="/static/guide/范围分隔符.jpg"
|
|
|
|
|
- title="范围分隔符"
|
|
|
|
|
- text="时间与日期类型组件中,开始与结束提示文字中间的分隔文字。"
|
|
|
|
|
- ></guide>
|
|
|
|
|
- </div>
|
|
|
|
|
- <el-input v-model="currentData.rangeSeparator" placeholder="请输入范围分隔符"></el-input>
|
|
|
|
|
- </template>
|
|
|
|
|
-
|
|
|
|
|
- <template v-if="['select','radio','checkbox'].includes(currentData.type)">
|
|
|
|
|
- <div class="tips">
|
|
|
|
|
- 选项设定
|
|
|
|
|
- <guide
|
|
|
|
|
- video="/static/guide/选项设定.mp4"
|
|
|
|
|
- title="选项设定"
|
|
|
|
|
- text="在单选、多选、选择器组件中,编辑可供用户选择的选择项目。"
|
|
|
|
|
- ></guide>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="select-list">
|
|
|
|
|
- <div class="item">
|
|
|
|
|
- <draggable :options="{sort:true,animation:300}" v-model="currentData.options">
|
|
|
|
|
- <transition-group class="select-inner">
|
|
|
|
|
- <el-input v-for="(item,index) in currentData.options" :key="item.value" :value="item.label" disabled>
|
|
|
|
|
- <div slot="prefix" class="handel">⠿</div>
|
|
|
|
|
- <el-button type="danger" @click="removeSelectItem(index)" slot="append" icon="el-icon-delete"></el-button>
|
|
|
|
|
- </el-input>
|
|
|
|
|
- </transition-group>
|
|
|
|
|
- </draggable>
|
|
|
|
|
- <el-input v-model="selectInput" @keyup.enter.native="addSelectItem" placeholder="请输入选项">
|
|
|
|
|
- <el-button @click="addSelectItem" slot="append" icon="el-icon-plus"></el-button>
|
|
|
|
|
- </el-input>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </template>
|
|
|
|
|
-
|
|
|
|
|
- <template v-if="['number','slider'].includes(currentData.type)">
|
|
|
|
|
- <div class="tips">
|
|
|
|
|
- 最小值
|
|
|
|
|
- <guide
|
|
|
|
|
- video="/static/guide/最小值.jpg"
|
|
|
|
|
- title="最小值"
|
|
|
|
|
- text="数字输入类型的组件中,限制可以输入的最小数字。"
|
|
|
|
|
- ></guide>
|
|
|
|
|
- </div>
|
|
|
|
|
- <el-input v-model="currentData.min" @change="currentData.value=$event-0"/>
|
|
|
|
|
- <div class="tips">
|
|
|
|
|
- 最大值
|
|
|
|
|
- <guide
|
|
|
|
|
- video="/static/guide/最大值.jpg"
|
|
|
|
|
- title="最大值"
|
|
|
|
|
- text="数字输入类型的组件中,限制可以输入的最大数字。"
|
|
|
|
|
- ></guide>
|
|
|
|
|
- </div>
|
|
|
|
|
- <el-input v-model="currentData.max"/>
|
|
|
|
|
- <div class="tips">
|
|
|
|
|
- 步进值
|
|
|
|
|
- <guide
|
|
|
|
|
- video="/static/guide/步进值.mp4"
|
|
|
|
|
- title="步进值"
|
|
|
|
|
- text="数字输入类型的组件中,限制输入的数字为多少的倍数。"
|
|
|
|
|
- ></guide>
|
|
|
|
|
- </div>
|
|
|
|
|
- <el-input v-model="currentData.step"/>
|
|
|
|
|
- </template>
|
|
|
|
|
-
|
|
|
|
|
- <div class="tips">
|
|
|
|
|
- 组件宽度
|
|
|
|
|
- <guide
|
|
|
|
|
- video="/static/guide/组件宽度.mp4"
|
|
|
|
|
- title="组件宽度"
|
|
|
|
|
- text="设置所选定组件的宽度,有1/3、1/2、2/3、占据全部宽度,总共四种尺寸供选择。"
|
|
|
|
|
- ></guide>
|
|
|
|
|
- </div>
|
|
|
|
|
- <el-radio-group size="small" v-model="currentData.width">
|
|
|
|
|
- <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>
|
|
</div>
|
|
|
<div class="button">
|
|
<div class="button">
|
|
|
- <el-button @click="removeComp(currentData)" type="danger">删除组件</el-button>
|
|
|
|
|
|
|
+ <el-button type="danger" @click="removeComp(currentData)">删除组件</el-button>
|
|
|
</div>
|
|
</div>
|
|
|
</template>
|
|
</template>
|
|
|
</div>
|
|
</div>
|
|
@@ -616,8 +444,8 @@ export default Vue.extend({
|
|
|
<draggable v-model="trashData" :group="{name:'form'}" :options="{sort:false,animation:300}" :class="['trash-cont',trashData.length?'':'hide']">
|
|
<draggable v-model="trashData" :group="{name:'form'}" :options="{sort:false,animation:300}" :class="['trash-cont',trashData.length?'':'hide']">
|
|
|
<transition-group class="drag-cont">
|
|
<transition-group class="drag-cont">
|
|
|
<div v-for="element in trashData" :key="element.key" class="form-item view">
|
|
<div v-for="element in trashData" :key="element.key" class="form-item view">
|
|
|
- <div class="tips">{{element.label}}</div>
|
|
|
|
|
- <div @click="removeTrash(element)" class="del el-icon-delete"></div>
|
|
|
|
|
|
|
+ <div class="tips">{{ element.label }}</div>
|
|
|
|
|
+ <div class="del el-icon-delete" @click="removeTrash(element)" />
|
|
|
</div>
|
|
</div>
|
|
|
</transition-group>
|
|
</transition-group>
|
|
|
</draggable>
|
|
</draggable>
|
|
@@ -838,7 +666,7 @@ export default Vue.extend({
|
|
|
.form-body{
|
|
.form-body{
|
|
|
.drag-cont{
|
|
.drag-cont{
|
|
|
display: grid;
|
|
display: grid;
|
|
|
- grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr;
|
|
|
|
|
|
|
+ grid-template-columns: 1fr;
|
|
|
width: 100%;
|
|
width: 100%;
|
|
|
min-height: 300px;
|
|
min-height: 300px;
|
|
|
align-content: start;
|
|
align-content: start;
|