1050 lines
		
	
	
		
			31 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			1050 lines
		
	
	
		
			31 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
| <template>
 | ||
|   <div class="detailLayout">
 | ||
|     <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"
 | ||
|                       filter=".components-filter"
 | ||
|                       draggable=".components-item"
 | ||
|                       group="componentsGroup"
 | ||
|                       :sort="true">
 | ||
|                     <div
 | ||
|                         class="components-item"
 | ||
|                         v-for="(item, i) in group.column"
 | ||
|                         :style="{width: item.grid * 100 + '%'}"
 | ||
|                         :class="{
 | ||
|                         'components-filter': item.isInit,
 | ||
|                         'active': groupIndex === j && activeIndex === i
 | ||
|                       }"
 | ||
|                         @click.stop="groupIndex = j, activeIndex = i, isGroup = false"
 | ||
|                         :key="i">
 | ||
|                       <div class="left-item__item--remove" title="删除字段" v-show="!item.isInit && 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' }]">
 | ||
|                         <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 === 'resident')">
 | ||
|                           <el-input :disabled="item.disable === '1'" size="small" placeholder="请选择人员" v-model="item.defaultValue">
 | ||
|                             <template slot="append">选择人员</template>
 | ||
|                           </el-input>
 | ||
|                         </template>
 | ||
|                         <template v-if="(item.type === 'gird')">
 | ||
|                           <el-input :disabled="item.disable === '1'" size="small" placeholder="请选择网格" v-model="item.defaultValue">
 | ||
|                             <template slot="append">选择网格</template>
 | ||
|                           </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'" style="width: 100%;" 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 && !currTarget.isInit">
 | ||
|         <span>删除分组</span>
 | ||
|       </div>
 | ||
|       <template v-if="activeIndex > -1">
 | ||
|         <div class="right-item">
 | ||
|           <div class="right-item__title no-solid">
 | ||
|             <h2>绑定字段</h2>
 | ||
|           </div>
 | ||
|           <div class="right-item__content">
 | ||
|             <ai-select v-model="currTarget.prop" :selectList="propOps" @change="handleAutoFieldName"/>
 | ||
|           </div>
 | ||
|         </div>
 | ||
|       </template>
 | ||
|       <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 options from './config'
 | ||
| 
 | ||
| export default {
 | ||
|   name: 'detailLayout',
 | ||
|   model: {
 | ||
|     prop: 'value',
 | ||
|     event: 'change',
 | ||
|   },
 | ||
|   props: {
 | ||
|     instance: Function,
 | ||
|     dict: Object,
 | ||
|     form: {default: () => ({})},
 | ||
|     value: Array
 | ||
|   },
 | ||
|   components: {draggable},
 | ||
|   data() {
 | ||
|     let {config: components} = options
 | ||
|     return {
 | ||
|       isGroup: false,
 | ||
|       components,
 | ||
|       groupIndex: -1,
 | ||
|       activeIndex: -1,
 | ||
|       currTarget: {},
 | ||
|       targetList: []
 | ||
|     }
 | ||
|   },
 | ||
|   watch: {
 | ||
|     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)
 | ||
|         }
 | ||
|       } else if (this.groupIndex > -1 && this.isGroup) {
 | ||
|         this.currTarget = this.targetList[this.groupIndex]
 | ||
|       } else 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()
 | ||
|             })
 | ||
|           })
 | ||
|         }
 | ||
|       } else if (this.groupIndex > -1 && this.isGroup) {
 | ||
|         this.currTarget = this.targetList[this.groupIndex]
 | ||
|       } else this.currTarget = {}
 | ||
|     },
 | ||
|     targetList: {
 | ||
|       deep: true,
 | ||
|       handler(v) {
 | ||
|         this.$emit('change', v)
 | ||
|       }
 | ||
|     }
 | ||
|   },
 | ||
|   computed: {
 | ||
|     currComponentTitle() {
 | ||
|       return '表单设置'
 | ||
|     },
 | ||
|     propOps: v => v.form.props?.map(e => ({dictValue: e.prop, dictName: e.label})),
 | ||
|   },
 | ||
|   methods: {
 | ||
|     initValue() {
 | ||
|       let unwatch = this.$watch('value', (v) => {
 | ||
|         if (this.targetList.length > 0) unwatch && unwatch()
 | ||
|         else if (!!v) {
 | ||
|           this.targetList = this.$copy(v)
 | ||
|           unwatch && unwatch()
 | ||
|         }
 | ||
|       }, {immediate: true})
 | ||
|     },
 | ||
|     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
 | ||
|     },
 | ||
|     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 {
 | ||
|         if (this.targetList[0]) this.targetList[0]?.column.push(JSON.parse(JSON.stringify(e)))
 | ||
|         else return this.$message.error("请先添加分组!")
 | ||
|       }
 | ||
| 
 | ||
|       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)
 | ||
|         })
 | ||
|       })
 | ||
|       return !(list.indexOf(el.type) > -1 && ['name', 'idNumber', 'phone', 'area'].includes(el.type));
 | ||
|     },
 | ||
|     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))
 | ||
|     },
 | ||
|     handleAutoFieldName(v) {
 | ||
|       this.currTarget.fieldName = this.propOps.find(e => e.dictValue == v)?.dictName || this.currTarget.fieldName
 | ||
|     }
 | ||
|   },
 | ||
|   created() {
 | ||
|     this.initValue()
 | ||
|   }
 | ||
| }
 | ||
| </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;
 | ||
|     }
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| .detailLayout {
 | ||
|   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;
 | ||
|     }
 | ||
|   }
 | ||
| 
 | ||
|   :deep( .ai-card ){
 | ||
|     cursor: move;
 | ||
| 
 | ||
|     &.active {
 | ||
|       background: #f6f7ff;
 | ||
|     }
 | ||
|   }
 | ||
| 
 | ||
|   :deep( .ai-detail__content ){
 | ||
|     height: calc(100% - 52px) !important;
 | ||
|     padding: 0 !important;
 | ||
|     overflow: hidden !important;
 | ||
|   }
 | ||
| 
 | ||
|   .ai-dialog__success {
 | ||
|     :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;
 | ||
|     }
 | ||
|   }
 | ||
| 
 | ||
|   :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);
 | ||
|   }
 | ||
| 
 | ||
|   :deep( .ai-detail__content--wrapper ){
 | ||
|     display: flex;
 | ||
|     max-width: 100% !important;
 | ||
|     height: 100% !important;
 | ||
|     padding: 0 !important;
 | ||
|     background: #F5F6F9;
 | ||
|   }
 | ||
| 
 | ||
|   .middle {
 | ||
|     flex: 1;
 | ||
|     height: 100%;
 | ||
| 
 | ||
|     :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;
 | ||
|       }
 | ||
|     }
 | ||
| 
 | ||
|     :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: hidden;
 | ||
|     background: #FFFFFF;
 | ||
| 
 | ||
|     .el-checkbox {
 | ||
|       display: block;
 | ||
|       margin-bottom: 10px;
 | ||
| 
 | ||
|       &:last-child {
 | ||
|         margin-bottom: 0;
 | ||
|       }
 | ||
|     }
 | ||
| 
 | ||
|     .right-item {
 | ||
|       margin: 20px 0;
 | ||
|       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: 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>
 |