1128 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			1128 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
| <template>
 | ||
|   <div class="form-config">
 | ||
|     <el-scrollbar class="left">
 | ||
|       <div class="left-item" v-for="(component, index) in components" :key="index">
 | ||
|         <div class="left-item__title">
 | ||
|           <h2>{{ component.label }}</h2>
 | ||
|           <span>{{ component.tips }}</span>
 | ||
|         </div>
 | ||
|         <div class="left-item__list">
 | ||
|           <draggable
 | ||
|             class="components-draggable"
 | ||
|             :list="component.children"
 | ||
|             :group="{ name: 'componentsGroup', pull: 'clone', put: false }"
 | ||
|             :sort="false"
 | ||
|             :move="onMove"
 | ||
|             :clone="cloneComponent"
 | ||
|             @end="onEnd">
 | ||
|             <div class="left-item__item" v-for="(item, i) in component.children" :key="i" @click="clone(item)">
 | ||
|               <i class="iconfont" :class="item.icon"></i>
 | ||
|               <span>{{ item.fixedLabel }}</span>
 | ||
|             </div>
 | ||
|           </draggable>
 | ||
|         </div>
 | ||
|       </div>
 | ||
|     </el-scrollbar>
 | ||
|     <el-scrollbar class="middle">
 | ||
|       <div class="middle-content">
 | ||
|         <div class="middle-content__wrapper">
 | ||
|           <el-form label-width="100px" label-position="right">
 | ||
|             <draggable
 | ||
|               class="middle-draggable"
 | ||
|               style="height: 100%;"
 | ||
|               :animation="340"
 | ||
|               scroll
 | ||
|               v-model="targetList"
 | ||
|               element="div"
 | ||
|               @end="onElEnd"
 | ||
|               :sort="true">
 | ||
|               <ai-card
 | ||
|                 :class="[groupIndex === j && isGroup ? 'active' : '']"
 | ||
|                 :data-index="j"
 | ||
|                 @click.native.stop="groupIndex = j, activeIndex = -1, isGroup = true"
 | ||
|                 :title="group.groupName" v-for="(group, j) in targetList"
 | ||
|                 :key="j">
 | ||
|                 <template #content>
 | ||
|                   <draggable
 | ||
|                     class="ai-form"
 | ||
|                     style="height: 100%;"
 | ||
|                     v-model="group.column"
 | ||
|                     :animation="340"
 | ||
|                     scroll
 | ||
|                     @end="onElEnd"
 | ||
|                     element="div"
 | ||
|                     draggable=".components-item"
 | ||
|                     group="componentsGroup"
 | ||
|                     :sort="true">
 | ||
|                     <div
 | ||
|                       class="components-item"
 | ||
|                       v-for="(item, i) in group.column"
 | ||
|                       :style="{width: item.grid * 100 + '%'}"
 | ||
|                       :class="[groupIndex === j && activeIndex === i ? 'active' : '']"
 | ||
|                       @click.stop="groupIndex = j, activeIndex = i, isGroup = false"
 | ||
|                       :key="i">
 | ||
|                       <div class="left-item__item--remove" title="删除字段" v-show="groupIndex === j && activeIndex === i" @click.stop="removeItem(j, i)">
 | ||
|                         <i class="iconfont iconDelete"></i>
 | ||
|                         <span>删除字段</span>
 | ||
|                       </div>
 | ||
|                       <el-form-item style="width: 100%;" :label="item.fieldName" :rules="[{ required: item.mustFill === '1' ? true : false }]">
 | ||
|                         <template v-if="(item.type === 'textarea')">
 | ||
|                           <el-input :disabled="item.disable === '1'" :rows="item.lineNumber" size="small" type="textarea" :placeholder="item.fieldTips" v-model="item.defaultValue"></el-input>
 | ||
|                         </template>
 | ||
|                         <template v-if="item.type === 'radio'">
 | ||
|                           <el-radio-group v-model="item.defaultValue" :disabled="item.disable === '1'">
 | ||
|                             <el-radio :label="field.label" v-for="(field, index) in item.options" :key="index">{{ field.label }}</el-radio>
 | ||
|                           </el-radio-group>
 | ||
|                         </template>
 | ||
|                         <template v-if="item.type === 'number'">
 | ||
|                           <el-input-number v-model="item.defaultValue" :placeholder="item.fieldTips"></el-input-number>
 | ||
|                         </template>
 | ||
|                         <template v-if="item.type === 'rtf'">
 | ||
|                           <ai-editor v-model="item.defaultValue" :placeholder="item.fieldTips" :instance="instance"/>
 | ||
|                         </template>
 | ||
|                         <template v-if="item.type === 'time'">
 | ||
|                           <el-date-picker
 | ||
|                             v-model="item.defaultValue"
 | ||
|                             size="small"
 | ||
|                             :placeholder="item.fieldTips">
 | ||
|                           </el-date-picker>
 | ||
|                         </template>
 | ||
|                         <template v-if="item.type === 'date'">
 | ||
|                           <el-date-picker
 | ||
|                             v-model="item.defaultValue"
 | ||
|                             size="small"
 | ||
|                             :placeholder="item.fieldTips">
 | ||
|                           </el-date-picker>
 | ||
|                         </template>
 | ||
|                         <template v-if="item.type === 'datetime'">
 | ||
|                           <el-date-picker
 | ||
|                             v-model="item.defaultValue"
 | ||
|                             size="small"
 | ||
|                             :placeholder="item.fieldTips">
 | ||
|                           </el-date-picker>
 | ||
|                         </template>
 | ||
|                         <template v-if="item.type === 'onOff'">
 | ||
|                           <el-switch active-value="1" inactive-value="0" v-model="item.defaultValue"></el-switch>
 | ||
|                         </template>
 | ||
|                         <template v-if="['input', 'phone', 'name', 'idNumber'].includes(item.type)">
 | ||
|                           <el-input :disabled="item.disable === '1'" :maxlength="Number(item.maxLength)" size="small" :placeholder="item.fieldTips" v-model="item.defaultValue"></el-input>
 | ||
|                         </template>
 | ||
|                         <template v-if="item.type === 'area'">
 | ||
|                           <ai-area-get
 | ||
|                             :instance="instance"
 | ||
|                             always-show
 | ||
|                           />
 | ||
|                         </template>
 | ||
|                         <template v-if="item.type === 'select'">
 | ||
|                           <el-select :disabled="item.disable === '1'" size="small" :placeholder="item.fieldTips" v-model="item.defaultValue">
 | ||
|                             <el-option
 | ||
|                               v-for="(filed, index) in item.options"
 | ||
|                               :key="index"
 | ||
|                               :label="filed.label"
 | ||
|                               :value="filed.label">
 | ||
|                             </el-option>
 | ||
|                           </el-select>
 | ||
|                         </template>
 | ||
|                         <template v-if="item.type === 'checkbox'" >
 | ||
|                           <el-checkbox-group v-model="item.defaultValue" :disabled="item.disable === '1'">
 | ||
|                             <el-checkbox :label="field.label" v-for="(field, index) in item.options" :key="index">{{ field.label }}</el-checkbox>
 | ||
|                           </el-checkbox-group>
 | ||
|                         </template>
 | ||
|                         <template v-if="item.type === 'upload'">
 | ||
|                           <div class="left-item__item--upload">
 | ||
|                             <i class="iconfont iconAdd"></i>
 | ||
|                             <span>添加附件</span>
 | ||
|                           </div>
 | ||
|                         </template>
 | ||
|                       </el-form-item>
 | ||
|                     </div>
 | ||
|                   </draggable>
 | ||
|                 </template>
 | ||
|               </ai-card>
 | ||
|             </draggable>
 | ||
|           </el-form>
 | ||
|         </div>
 | ||
|       </div>
 | ||
|     </el-scrollbar>
 | ||
|     <el-scrollbar class="right">
 | ||
|       <div class="right-item" v-if="isGroup">
 | ||
|         <div class="right-item__title no-solid">
 | ||
|           <h2>分组名称</h2>
 | ||
|         </div>
 | ||
|         <div class="right-item__content">
 | ||
|           <el-input placeholder="请输入分组名称" :maxlength="32" show-word-limit v-model="currTarget.groupName"></el-input>
 | ||
|         </div>
 | ||
|       </div>
 | ||
|       <div class="layout-right__del" @click="removeGroup" v-if="isGroup && targetList.length > 1">
 | ||
|         <span>删除分组</span>
 | ||
|       </div>
 | ||
|       <div class="right-item" v-if="activeIndex > -1">
 | ||
|         <div class="right-item__title no-solid">
 | ||
|           <h2>标题名称</h2>
 | ||
|         </div>
 | ||
|         <div class="right-item__content">
 | ||
|           <el-input placeholder="标题名称" :maxlength="32" show-word-limit v-model="currTarget.fieldName"></el-input>
 | ||
|         </div>
 | ||
|       </div>
 | ||
|       <div class="right-item" v-if="['select', 'date', 'time', 'input', 'datetime', 'textarea', 'rtf'].includes(currTarget.type)">
 | ||
|         <div class="right-item__title no-solid">
 | ||
|           <h2>占位符</h2>
 | ||
|         </div>
 | ||
|         <div class="right-item__content">
 | ||
|           <el-input placeholder="请输入占位符" :maxlength="32" show-word-limit v-model="currTarget.fieldTips"></el-input>
 | ||
|         </div>
 | ||
|       </div>
 | ||
|       <div class="right-item right-item__select" v-if="['select', 'checkbox', 'radio'].includes(currTarget.type)">
 | ||
|         <div class="right-item__title no-solid">
 | ||
|           <h2>选项设置</h2>
 | ||
|         </div>
 | ||
|         <div class="right-item__select--wrapper">
 | ||
|           <draggable
 | ||
|             v-model="currTarget.options"
 | ||
|             :animation="340"
 | ||
|             group="select"
 | ||
|             handle=".mover"
 | ||
|             :sort="true">
 | ||
|             <div class="select-item" v-for="(item, index) in currTarget.options" :key="index">
 | ||
|               <i class="iconfont iconjdq_led_show mover"></i>
 | ||
|               <el-input placeholder="请输入选项名" :maxlength="30" show-word-limit v-model="item.label"></el-input>
 | ||
|               <i class="iconfont iconDelete" @click="removeOptions(index)"></i>
 | ||
|             </div>
 | ||
|           </draggable>
 | ||
|         </div>
 | ||
|         <el-button type="text" class="add-select" @click="addOptions">添加选项</el-button>
 | ||
|       </div>
 | ||
|       <div class="right-item__group" v-if="activeIndex > -1" key="radio">
 | ||
|         <div class="right-item" v-if="['select', 'radio'].includes(currTarget.type)">
 | ||
|           <div class="right-item__title">
 | ||
|             <h2>默认值</h2>
 | ||
|           </div>
 | ||
|           <div class="right-item__content">
 | ||
|             <el-select placeholder="请选择默认值" style="width: 100%;" clearable v-model="currTarget.defaultValue">
 | ||
|               <el-option
 | ||
|                 v-for="(filed, index) in currTarget.options"
 | ||
|                 :key="index"
 | ||
|                 :label="filed.label"
 | ||
|                 :value="filed.label">
 | ||
|               </el-option>
 | ||
|             </el-select>
 | ||
|           </div>
 | ||
|         </div>
 | ||
|         <div class="right-item" v-if="['checkbox'].includes(currTarget.type)" key="checkbox">
 | ||
|           <div class="right-item__title">
 | ||
|             <h2>默认值</h2>
 | ||
|           </div>
 | ||
|           <div class="right-item__content">
 | ||
|             <el-select placeholder="请选择默认值" style="width: 100%;" clearable collapse-tags :multiple="true" v-model="currTarget.defaultValue">
 | ||
|               <el-option
 | ||
|                 v-for="(filed, index) in currTarget.options"
 | ||
|                 :key="index"
 | ||
|                 :label="filed.label"
 | ||
|                 :value="filed.label">
 | ||
|               </el-option>
 | ||
|             </el-select>
 | ||
|           </div>
 | ||
|         </div>
 | ||
|         <div class="right-item__group">
 | ||
|           <div class="right-item" v-if="['onOff'].includes(currTarget.type)">
 | ||
|             <div class="right-item__title">
 | ||
|               <h2>默认值</h2>
 | ||
|             </div>
 | ||
|             <div class="right-item__content">
 | ||
|               <el-switch v-model="currTarget.defaultValue" active-value="1" inactive-value="0" active-text="是" inactive-text="否"></el-switch>
 | ||
|             </div>
 | ||
|           </div>
 | ||
|         </div>
 | ||
|         <div class="right-item__group">
 | ||
|           <div class="right-item" v-if="['number'].includes(currTarget.type)">
 | ||
|             <div class="right-item__title">
 | ||
|               <h2>默认值</h2>
 | ||
|             </div>
 | ||
|             <div class="right-item__content">
 | ||
|               <el-input-number style="width: 100%;"  v-model="currTarget.defaultValue" label="默认值"></el-input-number>
 | ||
|             </div>
 | ||
|           </div>
 | ||
|         </div>
 | ||
|         <div class="right-item__group">
 | ||
|           <div class="right-item" v-if="['number'].includes(currTarget.type)">
 | ||
|             <div class="right-item__title">
 | ||
|               <h2>最大值</h2>
 | ||
|             </div>
 | ||
|             <div class="right-item__content">
 | ||
|               <el-input-number style="width: 100%;"  v-model="currTarget.maxValue" label="最大值"></el-input-number>
 | ||
|             </div>
 | ||
|           </div>
 | ||
|         </div>
 | ||
|         <div class="right-item__group">
 | ||
|           <div class="right-item" v-if="['number'].includes(currTarget.type)">
 | ||
|             <div class="right-item__title">
 | ||
|               <h2>最小值</h2>
 | ||
|             </div>
 | ||
|             <div class="right-item__content">
 | ||
|               <el-input-number style="width: 100%;"  v-model="currTarget.minValue" label="最小值"></el-input-number>
 | ||
|             </div>
 | ||
|           </div>
 | ||
|         </div>
 | ||
|         <div class="right-item__group">
 | ||
|           <div class="right-item" v-if="['number'].includes(currTarget.type)">
 | ||
|             <div class="right-item__title">
 | ||
|               <h2>小数精度</h2>
 | ||
|             </div>
 | ||
|             <div class="right-item__content">
 | ||
|               <el-input-number style="width: 100%;" step-strictly :min="0" v-model="currTarget.decimalPlaces" label="小数精度"></el-input-number>
 | ||
|             </div>
 | ||
|           </div>
 | ||
|         </div>
 | ||
|         <div class="right-item" v-if="['input', 'textarea', 'phone'].includes(currTarget.type)">
 | ||
|           <div class="right-item__title">
 | ||
|             <h2>最多输入字符</h2>
 | ||
|           </div>
 | ||
|           <div class="right-item__content">
 | ||
|             <el-input placeholder="字符个数" v-model="currTarget.maxLength">
 | ||
|               <span slot="append">个</span>
 | ||
|             </el-input>
 | ||
|           </div>
 | ||
|         </div>
 | ||
|         <div class="right-item" v-if="['area'].includes(currTarget.type)">
 | ||
|           <div class="right-item__title">
 | ||
|             <h2>默认值</h2>
 | ||
|           </div>
 | ||
|           <div class="right-item__content">
 | ||
|             <ai-area-get v-model="currTarget.defaultValue" :instance="instance" always-show></ai-area-get>
 | ||
|           </div>
 | ||
|         </div>
 | ||
|         <div class="right-item" v-if="currTarget.type === 'upload'">
 | ||
|           <div class="right-item__title">
 | ||
|             <h2>文件大小(MB)</h2>
 | ||
|           </div>
 | ||
|           <div class="right-item__content">
 | ||
|             <el-input-number style="width: 100%;"  v-model="currTarget.fileChoseSize" :min="1" :max="40" label="文件大小"></el-input-number>
 | ||
|           </div>
 | ||
|         </div>
 | ||
|         <div class="right-item" v-if="currTarget.type === 'upload'">
 | ||
|           <div class="right-item__title">
 | ||
|             <h2>最大上传数</h2>
 | ||
|           </div>
 | ||
|           <div class="right-item__content">
 | ||
|             <el-input-number style="width: 100%;" step-strictly v-model="currTarget.fileMaxCount" :min="1" :max="20" label="最大上传数"></el-input-number>
 | ||
|           </div>
 | ||
|         </div>
 | ||
|         <div class="right-item">
 | ||
|           <div class="right-item__title">
 | ||
|             <h2>是否整行显示</h2>
 | ||
|             <el-switch v-model="currTarget.grid" :active-value="1" :inactive-value="0.5"></el-switch>
 | ||
|           </div>
 | ||
|         </div>
 | ||
|         <div class="right-item" v-if="currTarget.type === 'textarea'">
 | ||
|           <div class="right-item__title">
 | ||
|             <h2>输入框行高</h2>
 | ||
|           </div>
 | ||
|           <div class="right-item__content">
 | ||
|             <el-input-number style="width: 100%;" v-model="currTarget.lineNumber" :min="3" :max="10" label="输入框行高"></el-input-number>
 | ||
|           </div>
 | ||
|         </div>
 | ||
|         <div class="right-item">
 | ||
|           <div class="right-item__title no-solid">
 | ||
|             <div class="right-item__title--left">
 | ||
|               <h2>是否必填</h2>
 | ||
|             </div>
 | ||
|             <el-switch v-model="currTarget.mustFill" active-value="1" inactive-value="0"></el-switch>
 | ||
|           </div>
 | ||
|         </div>
 | ||
|         <div class="right-item" v-if="currTarget.type !== 'rtf'">
 | ||
|           <div class="right-item__title no-solid">
 | ||
|             <div class="right-item__title--left">
 | ||
|               <h2>是否禁用</h2>
 | ||
|             </div>
 | ||
|             <el-switch v-model="currTarget.disable" active-value="1" inactive-value="0"></el-switch>
 | ||
|           </div>
 | ||
|         </div>
 | ||
|       </div>
 | ||
|     </el-scrollbar>
 | ||
|   </div>
 | ||
| </template>
 | ||
| 
 | ||
| <script>
 | ||
|   import draggable from 'vuedraggable'
 | ||
|   import { components } from './config'
 | ||
| 
 | ||
|   export default {
 | ||
|     name: 'formLayout',
 | ||
| 
 | ||
|     model: {
 | ||
|       prop: 'value',
 | ||
|       event: 'change',
 | ||
|     },
 | ||
| 
 | ||
|     props: {
 | ||
|       instance: Function,
 | ||
|       dict: Object,
 | ||
|       params: Object,
 | ||
|       type: String,
 | ||
|       areaId: String,
 | ||
|       value: Array
 | ||
|     },
 | ||
| 
 | ||
|     components: {
 | ||
|       draggable
 | ||
|     },
 | ||
| 
 | ||
|     data () {
 | ||
|       return {
 | ||
|         isGroup: false,
 | ||
|         components: components,
 | ||
|         targetList: [{
 | ||
|           type: 'group',
 | ||
|           fieldName: '卡片',
 | ||
|           fixedLabel: '卡片',
 | ||
|           icon: 'iconpic',
 | ||
|           groupName: '基础信息',
 | ||
|           column: []
 | ||
|         }],
 | ||
|         groupIndex: -1,
 | ||
|         activeIndex: -1,
 | ||
|         currTarget: {}
 | ||
|       }
 | ||
|     },
 | ||
| 
 | ||
|     watch: {
 | ||
|       value (v) {
 | ||
|         if (v) {
 | ||
|           let arr = JSON.parse(JSON.stringify(v))
 | ||
|           let groups = this.unique(arr.map(v => v.groupName))
 | ||
|           this.targetList = groups.map(groupName => {
 | ||
|             const column = arr.filter(v => v.groupName === groupName).map(item => {
 | ||
|               if (['select', 'checkbox', 'radio'].includes(item.type)) {
 | ||
|                 item.options = item.selectValues.split('`').map(v => {
 | ||
|                   return {
 | ||
|                     label: v,
 | ||
|                     value: ''
 | ||
|                   }
 | ||
|                 })
 | ||
|               }
 | ||
| 
 | ||
|               if (item.type === 'checkbox' && item.defaultValue) {
 | ||
|                 item.defaultValue = item.defaultValue.split('`')
 | ||
|               }
 | ||
| 
 | ||
|               if (item.grid) {
 | ||
|                 item.grid = Number(item.grid)
 | ||
|               }
 | ||
| 
 | ||
|               return item
 | ||
|             })
 | ||
| 
 | ||
|             return {
 | ||
|               type: 'group',
 | ||
|               fieldName: '卡片',
 | ||
|               fixedLabel: '卡片',
 | ||
|               icon: 'iconpic',
 | ||
|               groupName,
 | ||
|               column: column
 | ||
|             }
 | ||
|           })
 | ||
|         }
 | ||
|       },
 | ||
| 
 | ||
|       activeIndex () {
 | ||
|         if (this.activeIndex > -1 && this.groupIndex > -1 && !this.isGroup) {
 | ||
|           const filed = this.targetList[this.groupIndex].column[this.activeIndex]
 | ||
|           this.currTarget = filed
 | ||
| 
 | ||
|           if (filed.type === 'checkbox' && !filed.defaultValue.length) {
 | ||
|             setTimeout(() => {
 | ||
|               this.$set(this.currTarget, 'defaultValue', [2])
 | ||
|               this.$forceUpdate()
 | ||
|               this.$set(this.currTarget, 'defaultValue', [])
 | ||
|             }, 100)
 | ||
|           }
 | ||
| 
 | ||
|           return
 | ||
|         }
 | ||
| 
 | ||
|         if (this.groupIndex > -1 && this.isGroup) {
 | ||
|           this.currTarget = this.targetList[this.groupIndex]
 | ||
|           return 
 | ||
|         }
 | ||
| 
 | ||
|         this.currTarget = {}
 | ||
|       },
 | ||
| 
 | ||
|       groupIndex () {
 | ||
|         if (this.activeIndex > -1 && this.groupIndex > -1 && !this.isGroup) {
 | ||
|           const filed = this.targetList[this.groupIndex].column[this.activeIndex]
 | ||
|           this.currTarget = filed
 | ||
|           this.$set(this.currTarget, 'defaultValue', filed.defaultValue)
 | ||
| 
 | ||
|           if (filed.type === 'checkbox' && !filed.defaultValue.length) {
 | ||
|             this.$nextTick(() => {
 | ||
|               this.$set(this.currTarget, 'defaultValue', [])
 | ||
| 
 | ||
|               this.$nextTick(() => {
 | ||
|                 this.$forceUpdate()
 | ||
|               })
 | ||
|             })
 | ||
|           }
 | ||
| 
 | ||
|           return
 | ||
|         }
 | ||
| 
 | ||
|         if (this.groupIndex > -1 && this.isGroup) {
 | ||
|           this.currTarget = this.targetList[this.groupIndex]
 | ||
|           return 
 | ||
|         }
 | ||
| 
 | ||
|         this.currTarget = {}
 | ||
|       }
 | ||
|     },
 | ||
| 
 | ||
|     computed: {
 | ||
|       currComponentTitle () {
 | ||
|         return '表单设置'
 | ||
|       }
 | ||
|     },
 | ||
| 
 | ||
|     mounted () {
 | ||
|     },
 | ||
| 
 | ||
|     methods: {
 | ||
|       removeItem (j, i) {
 | ||
|         this.groupIndex = -1
 | ||
|         this.activeIndex = -1
 | ||
|         this.targetList[j].column.splice(i, 1)
 | ||
|       },
 | ||
| 
 | ||
|       removeGroup () {
 | ||
|         if (this.targetList.length === 1) {
 | ||
|           return this.$message.error('分组不能小于1')
 | ||
|         }
 | ||
| 
 | ||
|         this.targetList.splice(this.groupIndex, 1)
 | ||
|         this.groupIndex = 0
 | ||
|         this.isGroup = true
 | ||
|         this.activeIndex = -1
 | ||
|       },
 | ||
| 
 | ||
|       unique (arr) {
 | ||
|         return arr.filter((item, index) => {
 | ||
|           return arr.indexOf(item, 0) === index
 | ||
|         })
 | ||
|       },
 | ||
| 
 | ||
|       onConfirm () {
 | ||
|         let result = []
 | ||
|         this.targetList.forEach((group, i) => {
 | ||
|           group.column.forEach((item, index) => {
 | ||
|             result.push({
 | ||
|               ...item,
 | ||
|               groupIndex: i,
 | ||
|               groupName: group.groupName,
 | ||
|               fieldDbName: this.isUnique(item.type) ? item.type : `${item.type}${i}${index}`,
 | ||
|               defaultValue: item.type === 'checkbox' && item.defaultValue ? item.defaultValue.join('`') : item.defaultValue,
 | ||
|               selectValues: item.options ? item.options.map(v => v.label).join('`') : ''
 | ||
|             })
 | ||
|           })
 | ||
|         })
 | ||
| 
 | ||
|         this.$emit('change', result)
 | ||
| 
 | ||
|         return result
 | ||
|       },
 | ||
| 
 | ||
|       isUnique (type) {
 | ||
|         const list = this.components[0].children.map(v => v.type)
 | ||
| 
 | ||
|         return list.indexOf(type) > -1
 | ||
|       },
 | ||
| 
 | ||
|       addOptions () {
 | ||
|         const len = this.targetList[this.groupIndex].column[this.activeIndex].options.length
 | ||
|         let label = `选项${len + 1}`
 | ||
| 
 | ||
|         const index= this.targetList[this.groupIndex].column[this.activeIndex].options.findIndex(v => label === v.label)
 | ||
|         if (index > -1) {
 | ||
|           label = `新选项${len + 1}`
 | ||
|         }
 | ||
| 
 | ||
|         this.targetList[this.groupIndex].column[this.activeIndex].options.push({
 | ||
|           label: label,
 | ||
|           value: ''
 | ||
|         })
 | ||
|       },
 | ||
| 
 | ||
|       removeOptions (index) {
 | ||
|         const len = this.targetList[this.groupIndex].column[this.activeIndex].options.length
 | ||
| 
 | ||
|         if (len === 2) {
 | ||
|           return this.$message.error('选项不能少于2个')
 | ||
|         }
 | ||
|         this.targetList[this.groupIndex].column[this.activeIndex].options.splice(index, 1)
 | ||
|       },
 | ||
| 
 | ||
|       onEnd (e) {
 | ||
|         const el = e.to.parentElement.parentElement
 | ||
|         this.isGroup = false
 | ||
|         this.activeIndex = e.newIndex
 | ||
|         this.groupIndex = Number(el.getAttribute('data-index'))
 | ||
|       },
 | ||
| 
 | ||
|       onElEnd (e) {
 | ||
|         if (this.isGroup) {
 | ||
|           this.groupIndex = e.newIndex
 | ||
|         } else {
 | ||
|           this.activeIndex = e.newIndex
 | ||
|         }
 | ||
|       },
 | ||
| 
 | ||
|       clone (e) {
 | ||
|         if (e.type === 'group') {
 | ||
|           this.targetList.push(JSON.parse(JSON.stringify(e)))
 | ||
| 
 | ||
|           this.$nextTick(() => {
 | ||
|             this.isGroup = true
 | ||
|             this.groupIndex = this.targetList.length - 1
 | ||
|             this.activeIndex = -1
 | ||
|           })
 | ||
| 
 | ||
|           return
 | ||
|         }
 | ||
| 
 | ||
|         const list = []
 | ||
|         this.targetList.map(v => {
 | ||
|           v.column.forEach(item => {
 | ||
|             list.push(item.type)
 | ||
|           })
 | ||
|         })
 | ||
| 
 | ||
|         if (list.indexOf(e.type) > -1 && ['name', 'idNumber', 'phone', 'area'].includes(e.type)) {
 | ||
|           return this.$message.error('信息组件不能重复添加')
 | ||
|         }
 | ||
| 
 | ||
|         if (this.isGroup) {
 | ||
|           this.targetList[this.groupIndex].column.push(JSON.parse(JSON.stringify(e)))
 | ||
|         } else {
 | ||
|           this.targetList[0].column.push(JSON.parse(JSON.stringify(e)))
 | ||
|         }
 | ||
| 
 | ||
|         this.$nextTick(() => {
 | ||
|           this.groupIndex = this.isGroup ? this.groupIndex : 0
 | ||
|           this.activeIndex = this.targetList[0].column.length - 1
 | ||
|         })
 | ||
|       },
 | ||
| 
 | ||
|       onMove (e) {
 | ||
|         const el = e.draggedContext.element
 | ||
|         if (el.type === 'group') {
 | ||
|           return false
 | ||
|         }
 | ||
| 
 | ||
|         const list = []
 | ||
|         this.targetList.map(v => {
 | ||
|           v.column.forEach(item => {
 | ||
|             list.push(item.type)
 | ||
|           })
 | ||
|         })
 | ||
| 
 | ||
|         if (list.indexOf(el.type) > -1 && ['name', 'idNumber', 'phone', 'area'].includes(el.type)) {
 | ||
|           
 | ||
|           return false
 | ||
|         }
 | ||
| 
 | ||
|         return true
 | ||
|       },
 | ||
| 
 | ||
|       cloneComponent (e) {
 | ||
|         if (e.type === 'group') {
 | ||
|           this.targetList.push(JSON.parse(JSON.stringify(e)))
 | ||
| 
 | ||
|           return
 | ||
|         }
 | ||
|         const list = []
 | ||
|         this.targetList.map(v => {
 | ||
|           v.column.forEach(item => {
 | ||
|             list.push(item.type)
 | ||
|           })
 | ||
|         })
 | ||
| 
 | ||
|         if (list.indexOf(e.type) > -1 && ['name', 'idNumber', 'phone', 'area'].includes(e.type)) {
 | ||
|           this.$message.error('信息组件不能重复添加')
 | ||
|         }
 | ||
| 
 | ||
| 
 | ||
|         return JSON.parse(JSON.stringify(e))
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
| </script>
 | ||
| 
 | ||
| <style lang="scss" scoped>
 | ||
|   .layout-right__del {
 | ||
|     position: absolute;
 | ||
|     bottom: 100px;
 | ||
|     left: 0;
 | ||
|     z-index: 11;
 | ||
|     width: 100%;
 | ||
|     padding: 0 16px;
 | ||
| 
 | ||
|     span {
 | ||
|       display: block;
 | ||
|       width: 100%;
 | ||
|       height: 40px;
 | ||
|       line-height: 40px;
 | ||
|       text-align: center;
 | ||
|       border-radius: 6px;
 | ||
|       color: #F46;
 | ||
|       cursor: pointer;
 | ||
|       border: 1px solid #F46;
 | ||
| 
 | ||
|       &:hover {
 | ||
|         opacity: 0.7;
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
|   .form-config {
 | ||
|     display: flex;
 | ||
| 
 | ||
|     .ai-form .el-form-item {
 | ||
|       margin-bottom: 0;
 | ||
|     }
 | ||
| 
 | ||
|     .right-item__maintitle {
 | ||
|       height: 62px;
 | ||
|       line-height: 62px;
 | ||
|       margin-bottom: 20px;
 | ||
|       border-bottom: 1px solid #EEEEEE;
 | ||
|       color: #222222;
 | ||
| 
 | ||
|       h2 {
 | ||
|         font-size: 14px;
 | ||
|       }
 | ||
|     }
 | ||
| 
 | ||
|     ::v-deep .ai-card {
 | ||
|       cursor: move;
 | ||
| 
 | ||
|       &.active {
 | ||
|         background: #f6f7ff;
 | ||
|       }
 | ||
|     }
 | ||
| 
 | ||
|     ::v-deep .ai-detail__content {
 | ||
|       height: calc(100% - 52px)!important;
 | ||
|       padding: 0!important;
 | ||
|       overflow: hidden!important;
 | ||
|     }
 | ||
| 
 | ||
|     .ai-dialog__success {
 | ||
|       ::v-deep .ai-dialog__content {
 | ||
|         max-height: initial!important;
 | ||
|       }
 | ||
|     }
 | ||
| 
 | ||
|     .middle-draggable {
 | ||
|       // display: flex;
 | ||
|       // justify-content: space-between;
 | ||
|       // flex-wrap: wrap;
 | ||
|       .left-item__item {
 | ||
|         width: 50%;
 | ||
|         min-height: 73px;
 | ||
|       }
 | ||
| 
 | ||
|       .el-date-editor.el-input {
 | ||
|         width: 100%;
 | ||
|       }
 | ||
| 
 | ||
|       & > span {
 | ||
|         display: block;
 | ||
|         width: 100%;
 | ||
|         height: 100%;
 | ||
|         min-height: 600px;
 | ||
|         padding-bottom: 20px;
 | ||
|       }
 | ||
| 
 | ||
|       .components-item {
 | ||
|         position: relative;
 | ||
|         margin-bottom: 16px;
 | ||
|         padding: 16px 16px;
 | ||
|         cursor: move;
 | ||
| 
 | ||
|         &::after {
 | ||
|           position: absolute;
 | ||
|           left: 0;
 | ||
|           top: 0;
 | ||
|           z-index: 1111;
 | ||
|           width: 100%;
 | ||
|           height: 100%;
 | ||
|           content: ' ';
 | ||
|         }
 | ||
| 
 | ||
|         .left-item__item--remove {
 | ||
|           display: flex;
 | ||
|           position: absolute;
 | ||
|           align-items: center;
 | ||
|           justify-content: center;
 | ||
|           right: 4px;
 | ||
|           top: 4px;
 | ||
|           z-index: 1113;
 | ||
|           width: 84px;
 | ||
|           height: 28px;
 | ||
|           background: #FF4466;
 | ||
|           border-radius: 2px;
 | ||
|           cursor: pointer;
 | ||
|           color: #fff;
 | ||
|           font-size: 12px;
 | ||
| 
 | ||
|           i {
 | ||
|             margin-right: 6px;
 | ||
|             font-size: 12px;
 | ||
| 
 | ||
|             &:hover {
 | ||
|               color: #fff;
 | ||
|             }
 | ||
|           }
 | ||
| 
 | ||
|           &:hover {
 | ||
|             opacity: 0.8;
 | ||
|           }
 | ||
|         }
 | ||
| 
 | ||
|         &:hover {
 | ||
|           background: #f6f7ff;
 | ||
|         }
 | ||
| 
 | ||
|         &.active {
 | ||
|           background: #f6f7ff;
 | ||
|         }
 | ||
| 
 | ||
|         .left-item__item--upload {
 | ||
|           display: flex;
 | ||
|           align-items: center;
 | ||
|           justify-content: center;
 | ||
|           flex-direction: column;
 | ||
|           width: 120px;
 | ||
|           height: 120px;
 | ||
|           line-height: 1;
 | ||
|           border-radius: 6px;
 | ||
|           border: 1px dashed #bbb;
 | ||
| 
 | ||
|           i {
 | ||
|             font-size: 24px;
 | ||
|             color: #8899bb;
 | ||
|           }
 | ||
| 
 | ||
|           span {
 | ||
|             margin-top: 10px;
 | ||
|             font-size: 12px;
 | ||
|             color: #555;
 | ||
|           }
 | ||
|         }
 | ||
| 
 | ||
|         .text-item {
 | ||
|           input {
 | ||
|             display: block;
 | ||
|             width: 100%;
 | ||
|             height: 40px;
 | ||
|             border: none;
 | ||
|             border-bottom: 1px solid #ddd;
 | ||
| 
 | ||
|             &:focus {
 | ||
|               outline: none;
 | ||
|             }
 | ||
| 
 | ||
|             &:disabled {
 | ||
|               background: #fff;
 | ||
|             }
 | ||
|           }
 | ||
|         }
 | ||
| 
 | ||
|         .textarea-item {
 | ||
|           textarea {
 | ||
|             width: 100%;
 | ||
|             height: 120px;
 | ||
|             resize: none;
 | ||
|             border: 1px solid #ddd;
 | ||
|             padding: 10px;
 | ||
| 
 | ||
|             &:focus {
 | ||
|               outline: none;
 | ||
|             }
 | ||
| 
 | ||
|             &:disabled {
 | ||
|               background: #fff;
 | ||
|             }
 | ||
|           }
 | ||
|         }
 | ||
| 
 | ||
|         .radio-item {
 | ||
|           display: flex;
 | ||
|           align-items: center;
 | ||
|           margin-bottom: 10px;
 | ||
| 
 | ||
|           &:last-child {
 | ||
|             margin-bottom: 0;
 | ||
|           }
 | ||
| 
 | ||
|           label {
 | ||
|             margin-left: 10px;
 | ||
|           }
 | ||
| 
 | ||
|           img {
 | ||
|             margin-left: 10px;
 | ||
|           }
 | ||
|         }
 | ||
|       }
 | ||
| 
 | ||
|       .left-item__item--title {
 | ||
|         display: flex;
 | ||
|         align-items: center;
 | ||
|         margin-bottom: 10px;
 | ||
| 
 | ||
|         i {
 | ||
|           margin-right: 5px;
 | ||
|           color: #E22120;
 | ||
|         }
 | ||
| 
 | ||
|         h2 {
 | ||
|           color: #333333;
 | ||
|           font-size: 15px;
 | ||
|         }
 | ||
|       }
 | ||
|     }
 | ||
| 
 | ||
|     .middle-content {
 | ||
|       width: 96%;
 | ||
|       margin: 0 auto;
 | ||
|       padding: 0px 0 1px;
 | ||
| 
 | ||
|       .middle-content__wrapper {
 | ||
|         // min-height: 800px;
 | ||
|         // background: #fff;
 | ||
| 
 | ||
|         & > div {
 | ||
|           &.active {
 | ||
|             background: #f6f7ff;
 | ||
|           }
 | ||
|         }
 | ||
| 
 | ||
|         .radio-item {
 | ||
|           img {
 | ||
|             width: 40px;
 | ||
|             height: 40px;
 | ||
|           }
 | ||
|         }
 | ||
|       }
 | ||
|     }
 | ||
| 
 | ||
|     div {
 | ||
|       box-sizing: border-box;
 | ||
|     }
 | ||
| 
 | ||
|     .right-item__select--wrapper {
 | ||
|       .select-item {
 | ||
|         display: flex;
 | ||
|         align-items: center;
 | ||
|       }
 | ||
|     }
 | ||
| 
 | ||
|     ::v-deep .ai-detail__title {
 | ||
|       margin: 0!important;
 | ||
|       margin-bottom: 4px!important;
 | ||
|       padding: 0 20px;
 | ||
|       box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.08);
 | ||
|     }
 | ||
| 
 | ||
|     ::v-deep .ai-detail__content--wrapper {
 | ||
|       display: flex;
 | ||
|       max-width: 100%!important;
 | ||
|       height: 100%!important;
 | ||
|       padding: 0!important;
 | ||
|       background: #F5F6F9;
 | ||
|     }
 | ||
| 
 | ||
|     .middle {
 | ||
|       flex: 1;
 | ||
|       height: 100%;
 | ||
| 
 | ||
|       ::v-deep .el-scrollbar__view {
 | ||
|         height: 100%;
 | ||
|       }
 | ||
|     }
 | ||
| 
 | ||
|     .add-select {
 | ||
|       height: auto;
 | ||
|       line-height: 1;
 | ||
|       margin: 10px 0 0 26px;
 | ||
|       padding: 0;
 | ||
|     }
 | ||
| 
 | ||
|     .right-item__select--wrapper {
 | ||
|       .select-item {
 | ||
|         margin-bottom: 10px;
 | ||
| 
 | ||
|         &:last-child {
 | ||
|           margin-bottom: 0;
 | ||
|         }
 | ||
| 
 | ||
|         i {
 | ||
|           margin-right: 8px;
 | ||
|           color: #8c9dbd;
 | ||
|         }
 | ||
| 
 | ||
|         .mover {
 | ||
|           cursor: move;
 | ||
|         }
 | ||
| 
 | ||
|         .iconDelete {
 | ||
|           cursor: pointer;
 | ||
|           margin-left: 10px;
 | ||
|         }
 | ||
|       }
 | ||
| 
 | ||
|       ::v-deep .el-upload-list__item {
 | ||
|         width: 40px!important;
 | ||
|         height: 40px!important;
 | ||
|         object-fit: cover;
 | ||
|       }
 | ||
| 
 | ||
|       .config-item__select {
 | ||
|         display: flex;
 | ||
|         align-items: center;
 | ||
|         justify-content: center;
 | ||
|         width: 40px;
 | ||
|         height: 40px;
 | ||
|         border: 1px solid #D0D4DC;
 | ||
| 
 | ||
|         &:hover {
 | ||
|           opacity: 0.7;
 | ||
|         }
 | ||
| 
 | ||
|         i {
 | ||
|           font-size: 18px;
 | ||
|         }
 | ||
|       }
 | ||
|     }
 | ||
| 
 | ||
|     .right {
 | ||
|       width: 320px;
 | ||
|       height: 100%;
 | ||
|       overflow-y: auto;
 | ||
|       overflow: hidden;
 | ||
|       background: #FFFFFF;
 | ||
| 
 | ||
|       .el-checkbox {
 | ||
|         display: block;
 | ||
|         margin-bottom: 10px;
 | ||
| 
 | ||
|         &:last-child {
 | ||
|           margin-bottom: 0;
 | ||
|         }
 | ||
|       }
 | ||
| 
 | ||
|       .right-item {
 | ||
|         margin-top: 20px;
 | ||
|         padding: 0 20px;
 | ||
| 
 | ||
|         .right-item__tips {
 | ||
|           margin-top: 10px;
 | ||
|           color: #888888;
 | ||
|           font-size: 12px;
 | ||
|         }
 | ||
|       }
 | ||
| 
 | ||
|       .right-item__title {
 | ||
|         display: flex;
 | ||
|         align-items: center;
 | ||
|         justify-content: space-between;
 | ||
|         margin-bottom: 10px;
 | ||
| 
 | ||
|         .right-item__title--left {
 | ||
|           display: flex;
 | ||
|           align-items: center;
 | ||
| 
 | ||
|           i {
 | ||
|             color: #888888;
 | ||
|             font-size: 12px;
 | ||
|             font-style: normal;
 | ||
|           }
 | ||
|         }
 | ||
| 
 | ||
|         h2 {
 | ||
|           color: #222222;
 | ||
|           font-size: 14px;
 | ||
|         }
 | ||
|       }
 | ||
|     }
 | ||
| 
 | ||
|     .left {
 | ||
|       width: 280px;
 | ||
|       height: 100%;
 | ||
|       overflow-y: auto;
 | ||
|       overflow: hidden;
 | ||
|       background: #FFFFFF;
 | ||
| 
 | ||
|       .left-item {
 | ||
|         padding: 0 20px;
 | ||
| 
 | ||
|         &:last-child {
 | ||
|           padding-bottom: 20px;
 | ||
|         }
 | ||
| 
 | ||
|         .left-item__title {
 | ||
|           display: flex;
 | ||
|           align-items: baseline;
 | ||
|           margin-bottom: 20px;
 | ||
| 
 | ||
|           h2 {
 | ||
|             color: #222222;
 | ||
|             font-size: 14px;
 | ||
|             font-weight: 700;
 | ||
|           }
 | ||
| 
 | ||
|           span {
 | ||
|             color: #888888;
 | ||
|             font-size: 12px;
 | ||
|           }
 | ||
|         }
 | ||
|       }
 | ||
| 
 | ||
|       .left-item {
 | ||
|         margin-top: 20px;
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
| 
 | ||
|   .left-item__item {
 | ||
|     display: flex;
 | ||
|     align-items: center;
 | ||
|     height: 40px;
 | ||
|     margin-bottom: 10px;
 | ||
|     width: 100%;
 | ||
|     padding: 0 13px;
 | ||
|     background: #FFFFFF;
 | ||
|     border-radius: 2px;
 | ||
|     color: #222222;
 | ||
|     font-size: 12px;
 | ||
|     border: 1px solid #E4E8EF;
 | ||
|     cursor: move;
 | ||
| 
 | ||
|     &:hover {
 | ||
|       border: 1px dashed #2367ff;
 | ||
|       color: #2367ff;
 | ||
| 
 | ||
|       i {
 | ||
|         color: #2367ff;
 | ||
|       }
 | ||
|     }
 | ||
| 
 | ||
|     i {
 | ||
|       margin-right: 13px;
 | ||
|       font-size: 14px;
 | ||
|       color: #8899BB;
 | ||
|     }
 | ||
| 
 | ||
|     &:last-child {
 | ||
|       margin-bottom: 0px;
 | ||
|     }
 | ||
|   }
 | ||
| </style>
 |