<template> 
 | 
  <div class="drag-container"> 
 | 
    <!-- @start="onStart" --> 
 | 
    <div class="drag-left"> 
 | 
      <div class="left-title">组件列表</div> 
 | 
      <draggable 
 | 
        v-model="components" 
 | 
        @end="end1" 
 | 
        class="left-draggable-item" 
 | 
        :group="{ name: 'componentsGroup', pull: 'clone', put: false }" 
 | 
        animation="300" 
 | 
        @start="onStart" 
 | 
        :sort="false" 
 | 
        :move="onMove1" 
 | 
      > 
 | 
        <transition-group> 
 | 
          <div 
 | 
            :class="item.id == 1 ? 'item forbid' : 'item'" 
 | 
            v-for="item in components" 
 | 
            :key="item.id" 
 | 
          > 
 | 
            <i :class="item.icon"></i> {{ item.name }} 
 | 
          </div> 
 | 
        </transition-group> 
 | 
      </draggable> 
 | 
      <div class="example"> 
 | 
        <div @click="example1">示例一<i class="el-icon-arrow-right"></i></div> 
 | 
        <div @click="example2">示例二<i class="el-icon-arrow-right"></i></div> 
 | 
        <div @click="example3">示例三<i class="el-icon-arrow-right"></i></div> 
 | 
      </div> 
 | 
    </div> 
 | 
  
 | 
    <div class="drag-center"> 
 | 
      <div class="center-top"> 
 | 
        <span> 
 | 
          <!-- <i class="el-icon-warning-outline"></i>高效的表单配置 --> 
 | 
        </span> 
 | 
        <el-button type="primary" size="mini" plain @click="save" 
 | 
          ><i class="el-icon-check"> </i>保存</el-button 
 | 
        > 
 | 
        <el-button type="primary" size="mini" plain @click="preview(true)" 
 | 
          ><i class="el-icon-view"> </i>预览</el-button 
 | 
        > 
 | 
        <el-button type="primary" size="mini" plain @click="download" 
 | 
          ><i class="el-icon-view"> </i>下载</el-button 
 | 
        > 
 | 
        <el-button type="primary" @click="clearItems" size="mini" plain 
 | 
          ><i class="el-icon-delete"> </i>清空</el-button 
 | 
        > 
 | 
        <a 
 | 
          style="margin-left: 15px" 
 | 
          href="http://v2.volcore.xyz/document/api" 
 | 
          target="_blank" 
 | 
          >设计器基于框架volform、voltable、volupload、volbox定制开发</a 
 | 
        > 
 | 
      </div> 
 | 
      <div> 
 | 
        <el-alert 
 | 
          title="关于表单设计器" 
 | 
          type="success" 
 | 
          :show-icon="true" 
 | 
          :closable="false" 
 | 
        > 
 | 
          <div> 
 | 
            1、表单设计器基于draggable开发,为本框架自定义页面功能的补充,框架仍以可视化代码生成器为核心 
 | 
          </div> 
 | 
          <div> 
 | 
            2、支持可视化设计1对1、1对多及表单下拉框自动绑定、table自动加载数据(分页、编辑)、自动上传文件、富文本编辑 
 | 
          </div> 
 | 
        </el-alert> 
 | 
      </div> 
 | 
      <el-scrollbar style="flex: 1"> 
 | 
        <div class="tips" key="empty" v-show="!currentComponents.length"> 
 | 
          请将左边组件拖入此容器中 
 | 
        </div> 
 | 
        <el-form label-position="top"> 
 | 
          <draggable 
 | 
            class="draggable-container" 
 | 
            v-model="currentComponents" 
 | 
            @end="end2" 
 | 
            animation="300" 
 | 
            :move="onMove" 
 | 
            group="componentsGroup" 
 | 
          > 
 | 
            <transition-group class="drag-center-item"> 
 | 
              <div 
 | 
                class="item2" 
 | 
                :class="{ actived: index === currentIndex }" 
 | 
                @click="itemClick(item, index)" 
 | 
                :style="{ width: item.width + '%' }" 
 | 
                v-for="(item, index) in currentComponents" 
 | 
                :key="index" 
 | 
              > 
 | 
                <i 
 | 
                  class="el-icon-document-copy" 
 | 
                  @click.stop="copyItem(item)" 
 | 
                ></i> 
 | 
                <i class="el-icon-delete" @click.stop="removeItem(index)"> </i> 
 | 
                <el-form-item 
 | 
                  :required="item.required" 
 | 
                  label-position="top" 
 | 
                  style="width: 100%" 
 | 
                  :label="item.type == 'line' ? '' : item.name" 
 | 
                > 
 | 
                  <el-col> 
 | 
                    <!-- <div></div> --> 
 | 
                    <!-- {{ item.name }} --> 
 | 
                    <el-input 
 | 
                      v-if="item.type == 'text'" 
 | 
                      placeholder="请输入内容" 
 | 
                      v-model="item.value" 
 | 
                      :disabled="item.readonly" 
 | 
                      size="medium" 
 | 
                    ></el-input> 
 | 
                    <el-input 
 | 
                      v-else-if="item.type == 'textarea'" 
 | 
                      type="textarea" 
 | 
                      v-model="item.value" 
 | 
                      :disabled="item.readonly" 
 | 
                      placeholder="请输入内容" 
 | 
                    ></el-input> 
 | 
                    <el-date-picker 
 | 
                      v-else-if="item.type == 'date'" 
 | 
                      align="right" 
 | 
                      v-model="item.value" 
 | 
                      type="date" 
 | 
                      :disabled="item.readonly" 
 | 
                      size="medium" 
 | 
                      placeholder="选择日期" 
 | 
                    > 
 | 
                    </el-date-picker> 
 | 
                    <el-radio-group 
 | 
                      :disabled="item.readonly" 
 | 
                      v-else-if="item.type == 'radio'" 
 | 
                      v-model="item.value" 
 | 
                    > 
 | 
                      <el-radio 
 | 
                        v-for="item in item.data" 
 | 
                        :key="item.key" 
 | 
                        :label="item.value" 
 | 
                        :value="item.key" 
 | 
                      > 
 | 
                      </el-radio> 
 | 
                      <!-- <el-radio :label="1">是</el-radio> 
 | 
                      <el-radio :label="0">否</el-radio> --> 
 | 
                    </el-radio-group> 
 | 
  
 | 
                    <el-checkbox-group 
 | 
                      v-model="item.values" 
 | 
                      :disabled="item.readonly" 
 | 
                      style="width: 100%; display: inline-block" 
 | 
                      v-else-if="item.type == 'checkbox'" 
 | 
                    > 
 | 
                      <el-checkbox 
 | 
                        v-for="item in item.data" 
 | 
                        :key="item.key" 
 | 
                        :label="item.value" 
 | 
                        :value="item.key" 
 | 
                      > 
 | 
                      </el-checkbox> 
 | 
                      <!-- <el-checkbox label="复选框 A"></el-checkbox> 
 | 
                      <el-checkbox label="复选框 B"></el-checkbox> 
 | 
                      <el-checkbox label="复选框 C"></el-checkbox> --> 
 | 
                    </el-checkbox-group> 
 | 
  
 | 
                    <el-select 
 | 
                      style="width: 100%" 
 | 
                      :disabled="item.readonly" 
 | 
                      v-model="item.value" 
 | 
                      size="medium" 
 | 
                      v-else-if="item.type == 'select'" 
 | 
                      placeholder="请选择" 
 | 
                    > 
 | 
                      <el-option 
 | 
                        v-for="item in item.data" 
 | 
                        :key="item.value" 
 | 
                        :label="item.label" 
 | 
                        :value="item.value" 
 | 
                      > 
 | 
                      </el-option> 
 | 
                    </el-select> 
 | 
                    <el-select 
 | 
                      style="width: 100%" 
 | 
                      :disabled="item.readonly" 
 | 
                      v-model="item.values" 
 | 
                      size="medium" 
 | 
                      :multiple="true" 
 | 
                      v-else-if="item.type == 'selectList'" 
 | 
                      placeholder="请选择" 
 | 
                    > 
 | 
                      <el-option 
 | 
                        v-for="item in item.data" 
 | 
                        :key="item.value" 
 | 
                        :label="item.label" 
 | 
                        :value="item.value" 
 | 
                      > 
 | 
                      </el-option> 
 | 
                    </el-select> 
 | 
                    <el-cascader 
 | 
                      :disabled="item.readonly" 
 | 
                      style="width: 100%" 
 | 
                      v-else-if="item.type == 'cascader'" 
 | 
                      v-model="item.values" 
 | 
                      :options="item.data" 
 | 
                      @change="() => {}" 
 | 
                    ></el-cascader> 
 | 
  
 | 
                    <el-switch 
 | 
                      :disabled="item.readonly" 
 | 
                      v-model="item.value" 
 | 
                      style="width: 100%" 
 | 
                      v-else-if="item.type == 'switch'" 
 | 
                      active-color="#13ce66" 
 | 
                      inactive-color="#0e7ef3" 
 | 
                      :active-value="1" 
 | 
                      :inactive-value="0" 
 | 
                    > 
 | 
                    </el-switch> 
 | 
                    <div class="col-line" v-else-if="item.type == 'line'"> 
 | 
                      {{ item.name }} 
 | 
                    </div> 
 | 
  
 | 
                    <vol-upload 
 | 
                      v-else-if=" 
 | 
                        item.type == 'img' || 
 | 
                        item.type == 'excel' || 
 | 
                        item.type == 'file' 
 | 
                      " 
 | 
                      :fileInfo="item.fileInfo" 
 | 
                      :url="item.url" 
 | 
                      :img="item.type == 'img'" 
 | 
                      :excel="item.type == 'excel'" 
 | 
                      :multiple="item.multiple" 
 | 
                      :max-size="item.maxSize" 
 | 
                      :max-file="item.maxFile" 
 | 
                      :autoUpload="item.autoUpload" 
 | 
                    > 
 | 
                    </vol-upload> 
 | 
                    <vol-wang-editor 
 | 
                      v-else-if="item.type == 'editor'" 
 | 
                      :url="item.url" 
 | 
                      v-model="item.value" 
 | 
                      :height="item.height" 
 | 
                    ></vol-wang-editor> 
 | 
  
 | 
                    <vol-table 
 | 
                      v-else-if="item.type == 'table'" 
 | 
                      :url="item.url" 
 | 
                      :load-key="true" 
 | 
                      :index="item.edit" 
 | 
                      :tableData="item.tableData" 
 | 
                      :columns="item.columns" 
 | 
                      :height="item.height" 
 | 
                      :pagination-hide="true" 
 | 
                      :column-index="item.columnIndex" 
 | 
                      :ck="item.ck" 
 | 
                    ></vol-table> 
 | 
                    <el-button 
 | 
                      @click="model = true" 
 | 
                      v-else-if="item.type == 'box'" 
 | 
                      type="primary" 
 | 
                      size="small" 
 | 
                      >{{ item.name }}</el-button 
 | 
                    > 
 | 
                  </el-col> 
 | 
                </el-form-item> 
 | 
              </div> 
 | 
            </transition-group> 
 | 
          </draggable> 
 | 
        </el-form> 
 | 
      </el-scrollbar> 
 | 
    </div> 
 | 
    <div class="drag-right"> 
 | 
      <div class="left-title">组件属性</div> 
 | 
      <div class="attr" v-show="currentIndex != -1"> 
 | 
        <div class="attr-item"> 
 | 
          <div class="text">字段名称</div> 
 | 
          <el-input size="medium" v-model="currentItem.name" /> 
 | 
        </div> 
 | 
        <div class="attr-item"> 
 | 
          <div class="text">字段(唯一字段)</div> 
 | 
          <el-input size="medium" v-model="currentItem.field" /> 
 | 
        </div> 
 | 
        <div class="attr-item" v-show="currentItem.type == 'table'"> 
 | 
          <div class="text">后台返回数据接口地址</div> 
 | 
          <el-input 
 | 
            size="medium" 
 | 
            placeholder="例:api/表名/getPageData" 
 | 
            v-model="currentItem.url" 
 | 
          /> 
 | 
        </div> 
 | 
        <div 
 | 
          class="attr-item" 
 | 
          v-show=" 
 | 
            currentItem.type != 'table' && currentItem.hasOwnProperty('url') 
 | 
          " 
 | 
        > 
 | 
          <div class="text">上传接口地址(后台接口)</div> 
 | 
          <el-input 
 | 
            size="medium" 
 | 
            placeholder="可用框架地址:api/表名/upload" 
 | 
            v-model="currentItem.url" 
 | 
          /> 
 | 
          <div class="text" style="margin-top: 10px">文件大小限制(M)</div> 
 | 
          <el-input size="medium" v-model="currentItem.maxSize" /> 
 | 
          <div class="text" style="margin-top: 10px">是否多文件上传</div> 
 | 
          <el-switch 
 | 
            v-model="currentItem.multiple" 
 | 
            style="width: 100%" 
 | 
            active-color="#13ce66" 
 | 
            inactive-color="rgb(165 165 165)" 
 | 
            :active-value="true" 
 | 
            :inactive-value="false" 
 | 
          > 
 | 
          </el-switch> 
 | 
          <div class="text" style="margin-top: 10px">是否自动上传</div> 
 | 
          <el-switch 
 | 
            v-model="currentItem.autoUpload" 
 | 
            style="width: 100%" 
 | 
            active-color="#13ce66" 
 | 
            inactive-color="rgb(165 165 165)" 
 | 
            :active-value="true" 
 | 
            :inactive-value="false" 
 | 
          > 
 | 
          </el-switch> 
 | 
        </div> 
 | 
        <div class="attr-item" v-show="currentItem.data"> 
 | 
          <div class="text">数据源(下拉框绑定设置中维护)</div> 
 | 
  
 | 
          <!-- dicList --> 
 | 
          <el-select 
 | 
            style="width: 100%" 
 | 
            v-model="currentItem.key" 
 | 
            size="medium" 
 | 
            @change="dicChange" 
 | 
            placeholder="请选择数据源字典" 
 | 
          > 
 | 
            <el-option 
 | 
              v-for="item in dicList" 
 | 
              :key="item.key" 
 | 
              :label="item.value" 
 | 
              :value="item.key" 
 | 
            > 
 | 
            </el-option> 
 | 
          </el-select> 
 | 
        </div> 
 | 
        <div class="attr-item" v-show="currentItem.type != 'table'"> 
 | 
          <div class="text">标签宽度</div> 
 | 
          <el-slider 
 | 
            style="width: 90%" 
 | 
            :min="20" 
 | 
            v-model="colWidth" 
 | 
            :step="10" 
 | 
            show-stops 
 | 
          > 
 | 
          </el-slider> 
 | 
        </div> 
 | 
        <div class="attr-item attr2" v-show="currentItem.type != 'table'"> 
 | 
          <div> 
 | 
            <div class="text">必填</div> 
 | 
            <el-switch 
 | 
              v-model="currentItem.required" 
 | 
              style="width: 100%" 
 | 
              active-color="#13ce66" 
 | 
              inactive-color="rgb(165 165 165)" 
 | 
              :active-value="true" 
 | 
              :inactive-value="false" 
 | 
            > 
 | 
            </el-switch> 
 | 
          </div> 
 | 
  
 | 
          <div> 
 | 
            <!-- active-text="是" 
 | 
              inactive-text="否" --> 
 | 
            <div class="text">只读</div> 
 | 
            <el-switch 
 | 
              v-model="currentItem.readonly" 
 | 
              style="width: 100%" 
 | 
              active-color="#13ce66" 
 | 
              inactive-color="rgb(165 165 165)" 
 | 
              :active-value="true" 
 | 
              :inactive-value="false" 
 | 
            > 
 | 
            </el-switch> 
 | 
          </div> 
 | 
        </div> 
 | 
        <div v-show="currentItem.type == 'table'"> 
 | 
          <div class="attr-item"> 
 | 
            <div class="text">是否使用选项卡(tabs)</div> 
 | 
            <div> 
 | 
              <el-switch 
 | 
                v-model="currentItem.tabs" 
 | 
                style="width: 100%" 
 | 
                active-text="是" 
 | 
                inactive-text="否" 
 | 
                active-color="#13ce66" 
 | 
                inactive-color="rgb(165 165 165)" 
 | 
                :active-value="true" 
 | 
                :inactive-value="false" 
 | 
              > 
 | 
              </el-switch> 
 | 
            </div> 
 | 
          </div> 
 | 
          <div class="attr-item attr2"> 
 | 
            <el-button 
 | 
              style="width: 100%" 
 | 
              @click="openTableModel" 
 | 
              type="primary" 
 | 
              size="medium" 
 | 
              >table配置</el-button 
 | 
            > 
 | 
          </div> 
 | 
        </div> 
 | 
      </div> 
 | 
    </div> 
 | 
  </div> 
 | 
  <vol-box 
 | 
    v-model="model" 
 | 
    :height="300" 
 | 
    :width="550" 
 | 
    :lazy="true" 
 | 
    title="弹出框" 
 | 
  > 
 | 
    <template #content> 
 | 
      <div>弹出框内容</div> 
 | 
    </template> 
 | 
    <template #footer> 
 | 
      <div> 
 | 
        <el-button type="primary" size="mini" @click="model = false" 
 | 
          ><i class="el-icon-close"></i>点击关闭</el-button 
 | 
        > 
 | 
        <el-button size="mini" @click="model = false" 
 | 
          ><i class="el-icon-close"></i>关闭</el-button 
 | 
        > 
 | 
      </div> 
 | 
    </template> 
 | 
  </vol-box> 
 | 
  
 | 
  <vol-box 
 | 
    v-model="previewModel" 
 | 
    :height="600" 
 | 
    :width="1300" 
 | 
    :lazy="true" 
 | 
    :padding="1" 
 | 
    :close="false" 
 | 
    title="预览" 
 | 
  > 
 | 
    <preview style="height:600px" :options="viewFormData"></preview> 
 | 
  </vol-box> 
 | 
  
 | 
  <vol-box 
 | 
    v-model="tableModel" 
 | 
    :height="600" 
 | 
    :width="1300" 
 | 
    :lazy="true" 
 | 
    :padding="0" 
 | 
    :title="currentItem.name" 
 | 
  > 
 | 
    <template #content> 
 | 
      <div style="height:600px" > 
 | 
      <el-alert title="关于table配置" type="info" :closable="false" show-icon> 
 | 
        此处table是对框架voltable基本操作的配置,如果需要事件触发、数据加载等更多功能,请在生成后的代码添加需要的功能,完整配置见文档<a 
 | 
          href="http://v2.volcore.xyz/document/api" 
 | 
          style="color: #1e88e5; margin-left: 9px" 
 | 
          target="_blank" 
 | 
          >voltable</a 
 | 
        > 
 | 
      </el-alert> 
 | 
      <div class="btns"> 
 | 
        <div class="btns-left"> 
 | 
          表格默认功能按钮: 
 | 
          <el-checkbox 
 | 
            v-for="item in currentItem.buttons" 
 | 
            :label="item.name" 
 | 
            :key="item.name" 
 | 
            >{{ item.name }}</el-checkbox 
 | 
          > 
 | 
        </div> 
 | 
        <div class="btns-right"> 
 | 
          <el-button type="primary" size="mini" @click="addRow" 
 | 
            ><i class="el-icon-plus"></i>添加字段</el-button 
 | 
          > 
 | 
          <el-button type="primary" size="mini" @click="delRow" 
 | 
            ><i class="el-icon-delete"></i>删除字段</el-button 
 | 
          > 
 | 
          <el-button type="primary" size="mini" @click="sortRow" 
 | 
            ><i class="el-icon-sort"></i>重新排列</el-button 
 | 
          > 
 | 
        </div> 
 | 
      </div> 
 | 
      <vol-table 
 | 
        :load-key="true" 
 | 
        :tableData="currnetTableData" 
 | 
        :columns="currentTableOption" 
 | 
        :height="448" 
 | 
        ref="table" 
 | 
        :index="true" 
 | 
        :pagination-hide="true" 
 | 
        :column-index="true" 
 | 
        :ck="true" 
 | 
      ></vol-table> 
 | 
    </div> 
 | 
    </template> 
 | 
    <template #footer> 
 | 
      <div style="text-align: center"> 
 | 
        <el-button size="mini" @click="tableModel = false" 
 | 
          ><i class="el-icon-close"></i>关闭</el-button 
 | 
        > 
 | 
        <el-button type="primary" size="mini" @click="saveConfigOptions" 
 | 
          ><i class="el-icon-check"></i>保存</el-button 
 | 
        > 
 | 
      </div> 
 | 
    </template> 
 | 
  </vol-box> 
 | 
</template> 
 | 
  
 | 
<script> 
 | 
import { h, resolveComponent } from "vue"; 
 | 
// import draggable from "vuedraggable"; 
 | 
import { VueDraggableNext } from "vue-draggable-next"; 
 | 
import VolWangEditor from "@/components/editor/VolWangEditor.vue"; 
 | 
import VolUpload from "./../VolUpload"; 
 | 
import VolTable from "./../VolTable"; 
 | 
import VolBox from "./../VolBox"; 
 | 
import VolFormPreview from "./VolFormPreview"; 
 | 
import { components, tableOption } from "./options"; 
 | 
import { options1, options2, options3 } from "./formTemplate"; 
 | 
import downloadForm from "./DownloadForm"; 
 | 
export default { 
 | 
  props: { 
 | 
    userComponents: { 
 | 
      type: Array, 
 | 
      default: () => { 
 | 
        return []; 
 | 
      }, 
 | 
    }, 
 | 
  }, 
 | 
  components: { 
 | 
    draggable: VueDraggableNext, 
 | 
    "vol-upload": VolUpload, 
 | 
    "vol-wang-editor": VolWangEditor, 
 | 
    "vol-table": VolTable, 
 | 
    "vol-box": VolBox, 
 | 
    preview: VolFormPreview, 
 | 
  }, 
 | 
  data() { 
 | 
    return { 
 | 
      options:{}, 
 | 
      options1: options1, 
 | 
      options2: options2, 
 | 
      options3: options3, 
 | 
      colWidth: 100, 
 | 
      currentIndex: -1, 
 | 
      currentItem: {}, 
 | 
      currnetTableData: [], 
 | 
      currentTableOption: tableOption, 
 | 
      //定义要被拖拽对象的数组 
 | 
      components: components, 
 | 
      currentComponents: [], 
 | 
      dicList: [], 
 | 
      model: false, 
 | 
      tableModel: false, 
 | 
      previewModel: false, 
 | 
      viewFormData: { fields: {}, formOptions: [], tables: [] }, 
 | 
    }; 
 | 
  }, 
 | 
  watch: { 
 | 
    colWidth(newVal) { 
 | 
      if (this.currentIndex != -1) { 
 | 
        this.currentComponents[this.currentIndex].width = newVal; 
 | 
      } 
 | 
    }, 
 | 
    userComponents: { 
 | 
      handler(newVal) { 
 | 
        this.currentComponents = newVal; 
 | 
      }, 
 | 
      immediate: true, 
 | 
      deep: true, 
 | 
    }, 
 | 
  }, 
 | 
  created() { 
 | 
    this.currentComponents = this.userComponents; 
 | 
    this.http 
 | 
      .post("api/Sys_Dictionary/GetBuilderDictionary", {}, false) 
 | 
      .then((x) => { 
 | 
        this.dicList = x.map((c) => { 
 | 
          return { key: c, value: c }; 
 | 
        }); 
 | 
      }); 
 | 
  }, 
 | 
  methods: { 
 | 
    getFormOptions(item) { 
 | 
      let _option = {}; 
 | 
      _option.field = item.field; 
 | 
      _option.title = item.name; 
 | 
      _option.type = item.type; 
 | 
      _option.required = item.required; 
 | 
      _option.readonly = item.readonly; 
 | 
      if (item.type == "line") { 
 | 
        _option.title = ""; 
 | 
        let title = item.name; 
 | 
        _option.render = (h) => { 
 | 
          return h( 
 | 
            "div", 
 | 
            { 
 | 
              style: { 
 | 
                "line-height": "25px", 
 | 
                "font-weight": "bold", 
 | 
                "margin-left": "15px", 
 | 
                "border-bottom": "1px solid #dadada", 
 | 
              }, 
 | 
            }, 
 | 
            title 
 | 
            //也可以在这里放一些组件,例如: 
 | 
            // resolveComponent("el-tooltip"), 
 | 
            // { 
 | 
            //   content: "这里是提示的内容", 
 | 
            //   props: { effect: "dark", placement: "top-start" }, 
 | 
            //   style: {}, 
 | 
            // }, 
 | 
            // [h("a", { style: { color: "#2a92ff" } }, "提示信息")] 
 | 
          ); 
 | 
        }; 
 | 
      } 
 | 
      if (item.type == "editor") { 
 | 
        _option.height = item.height; 
 | 
      } 
 | 
      if (item.width == 100) { 
 | 
        _option.colSize = 12; 
 | 
      } else { 
 | 
        _option.colSize = (_option.width * 12) / 100; 
 | 
      } 
 | 
      if (["img", "excel", "file"].indexOf(item.type) != -1) { 
 | 
        _option.maxSize = item.maxSize; 
 | 
        _option.fileInfo = item.fileInfo; 
 | 
        _option.multiple = item.multiple; 
 | 
        _option.autoUpload = item.autoUpload; 
 | 
        _option.maxFile = item.maxFile; 
 | 
      } 
 | 
      if ( 
 | 
        ["img", "excel", "file", "editor", "table"].indexOf(item.type) != -1 
 | 
      ) { 
 | 
        _option.url = item.url; 
 | 
      } 
 | 
      if (item.data) { 
 | 
        _option.data = item.data; 
 | 
        _option.dataKey = item.key; 
 | 
      } 
 | 
      return _option; 
 | 
    }, 
 | 
    getLineFormOptions(index) { 
 | 
      let _index = index; 
 | 
      let endIndex = index; 
 | 
      let width = 0; 
 | 
      let _options = []; 
 | 
      for (index; index < this.filterCurrentComponents().length; index++) { 
 | 
        const item = this.currentComponents[index]; 
 | 
        if (item.width + width <= 100) { 
 | 
          width = item.width + width; 
 | 
          endIndex = index; 
 | 
          _options.push(this.getFormOptions(item)); 
 | 
        } 
 | 
      } 
 | 
      return { options: _options, index: _index, endIndex: endIndex }; 
 | 
    }, 
 | 
    filterCurrentComponents() { 
 | 
      return this.currentComponents.filter((x) => { 
 | 
        return x.type != "table"; 
 | 
      }); 
 | 
    }, 
 | 
    setSpan() {}, 
 | 
    preview(isPre) { 
 | 
      let _fields = {}; 
 | 
      let _formOptions = []; 
 | 
      let endIndex = -1; 
 | 
      this.filterCurrentComponents().forEach((item, index) => { 
 | 
        if (item.hasOwnProperty("values")) { 
 | 
          _fields[item.field] = []; 
 | 
        } else { 
 | 
          _fields[item.field] = null; 
 | 
        } 
 | 
  
 | 
        if (item.width == 100) { 
 | 
          _formOptions.push([this.getFormOptions(item)]); 
 | 
        } else { 
 | 
          if (endIndex == -1) { 
 | 
            let lineOptions = this.getLineFormOptions(index); 
 | 
            endIndex = lineOptions.endIndex; 
 | 
            _formOptions.push(lineOptions.options); 
 | 
            endIndex--; 
 | 
          } else { 
 | 
            endIndex--; 
 | 
          } 
 | 
        } 
 | 
        // _fields[item.field] = null;xc 
 | 
        // let _option = {}; 
 | 
        // _option.field = item.field; 
 | 
        // _option.title = item.name; 
 | 
        // _option.type = item.type; 
 | 
        // _option.required = item.required; 
 | 
        // _option.readonly = item.readonly; 
 | 
        // if (["img", "excel", "file"].indexOf(item.type) != -1) { 
 | 
        //   _option.maxSize = item.maxSize; 
 | 
        //   _option.fileInfo = item.fileInfo; 
 | 
        //   _option.multiple = item.multiple; 
 | 
        //   _option.autoUpload = item.autoUpload; 
 | 
        //   _option.maxFile = item.maxFile; 
 | 
        // } 
 | 
        // if ( 
 | 
        //   ["img", "excel", "file", "editor", "table"].indexOf(item.type) != -1 
 | 
        // ) { 
 | 
        //   _option.url = item.url; 
 | 
        // } 
 | 
        // if (item.data) { 
 | 
        //   _option.data = item.data; 
 | 
        //   _option.dataKey = item.key; 
 | 
        // } 
 | 
        // _formOptions.push(_option); 
 | 
      }); 
 | 
      this.viewFormData.fields = _fields; 
 | 
      // console.log(JSON.stringify(_formOptions)) 
 | 
      this.viewFormData.formOptions = _formOptions; 
 | 
      if (isPre) { 
 | 
        this.previewModel = true; 
 | 
      } 
 | 
      let tableIndex = 0; 
 | 
      let keys = []; 
 | 
      let tables = this.currentComponents 
 | 
        .filter((x) => { 
 | 
          return x.type == "table"; 
 | 
        }) 
 | 
        .map((m) => { 
 | 
          m.pagination = !m.url; 
 | 
          if (m.name == "表格") { 
 | 
            tableIndex++; 
 | 
          } 
 | 
          return { 
 | 
            name: m.name + (m.name == "表格" ? tableIndex : ""), 
 | 
            url: m.url, 
 | 
            tabs: m.tabs, 
 | 
            pagination: m.pagination, 
 | 
            buttons: m.buttons, 
 | 
            columns: m.columns.map((c) => { 
 | 
              let obj = { 
 | 
                title: c.title, 
 | 
                field: c.field, 
 | 
                hidden: !c.show, 
 | 
                width: c.width, 
 | 
                required: c.required, 
 | 
              }; 
 | 
  
 | 
              if (c.dataSource) { 
 | 
                obj.bind = { key: c.dataSource, data: [] }; 
 | 
              } 
 | 
              if (c.dataSource) { 
 | 
                keys.push(c.dataSource); 
 | 
              } 
 | 
              if (c.edit) { 
 | 
                if (!obj.bind) { 
 | 
                  obj.bind = { key: "", data: [] }; 
 | 
                } 
 | 
                obj.edit = { type: c.editType }; 
 | 
              } 
 | 
              return obj; 
 | 
            }), 
 | 
            tableData: [{}, {}, {}], 
 | 
          }; 
 | 
        }); 
 | 
      this.viewFormData.tables = tables.filter((x) => { 
 | 
        return !x.tabs; 
 | 
      }); 
 | 
      this.viewFormData.tabs = tables.filter((x) => { 
 | 
        return x.tabs; 
 | 
      }); 
 | 
      this.getDicKeys(keys); 
 | 
          this.options = this.viewFormData; 
 | 
    }, 
 | 
    getDicKeys(keys) { 
 | 
      if (!keys.length) { 
 | 
        return; 
 | 
      } 
 | 
      debugger 
 | 
      this.http 
 | 
        .post("api/Sys_Dictionary/GetVueDictionary", keys, true) 
 | 
        .then((result) => { 
 | 
          result.forEach((c) => { 
 | 
            this.viewFormData.tables.forEach((t) => { 
 | 
              let _option = t.columns.find((x) => { 
 | 
                return x.bind && x.bind.key == c.dicNo; 
 | 
              }); 
 | 
              if (_option) { 
 | 
                _option.bind.data = c.data; 
 | 
              } 
 | 
            }); 
 | 
            this.viewFormData.tabs.forEach((t) => { 
 | 
              let _option = t.columns.find((x) => { 
 | 
                return x.bind && x.bind.key == c.dicNo; 
 | 
              }); 
 | 
              if (_option) { 
 | 
                _option.bind.data = c.data; 
 | 
              } 
 | 
            }); 
 | 
          }); 
 | 
        }); 
 | 
    }, 
 | 
    save() { 
 | 
      this.preview(false); 
 | 
      this.$emit("save", { 
 | 
        daraggeOptions: this.currentComponents, 
 | 
        formOptions: this.viewFormData, 
 | 
      }); 
 | 
    }, 
 | 
    download() { 
 | 
      this.preview(false); 
 | 
      downloadForm.call(this); 
 | 
    }, 
 | 
    openTableModel() { 
 | 
      let dataSource = this.currentTableOption.find((x) => { 
 | 
        return x.field == "dataSource"; 
 | 
      }); 
 | 
      if (!dataSource.bind.data.length) { 
 | 
        dataSource.bind.data = this.dicList; 
 | 
      } 
 | 
      this.currnetTableData = JSON.parse( 
 | 
        JSON.stringify(this.currentItem.columns) 
 | 
      ); 
 | 
      this.tableModel = true; 
 | 
    }, 
 | 
    addRow() { 
 | 
      this.currnetTableData.push({ field: this.getField() }); 
 | 
    }, 
 | 
    delRow() { 
 | 
      this.$confirm("确认要删除选择的数据吗?", "警告", { 
 | 
        confirmButtonText: "确定", 
 | 
        cancelButtonText: "取消", 
 | 
        type: "warning", 
 | 
        center: true, 
 | 
      }).then(() => { 
 | 
        this.$refs.table.delRow(); 
 | 
      }); 
 | 
    }, 
 | 
    sortRow() { 
 | 
      this.currnetTableData = this.currnetTableData.sort((a, b) => { 
 | 
        return a.orderNo - b.orderNo; 
 | 
      }); //.reverse(); 
 | 
      this.$Message.success("列显示顺序已重新排列,点击预览可查看"); 
 | 
    }, 
 | 
    saveConfigOptions() { 
 | 
      this.currentItem.columns = JSON.parse( 
 | 
        JSON.stringify(this.currnetTableData) 
 | 
      ); 
 | 
      this.tableModel = false; 
 | 
    }, 
 | 
    copyItem(item) { 
 | 
      let itemClone = JSON.parse(JSON.stringify(item)); 
 | 
      itemClone.field = "field" + new Date().valueOf(); 
 | 
      this.currentComponents.push(itemClone); 
 | 
    }, 
 | 
    removeItem(index) { 
 | 
      this.currentComponents.splice(index, 1); 
 | 
      this.colWidth = 100; 
 | 
      this.currentIndex = -1; 
 | 
      this.currentItem = {}; 
 | 
    }, 
 | 
    clearItems() { 
 | 
      this.currentComponents.length = 0; 
 | 
      this.colWidth = 100; 
 | 
      this.currentIndex = -1; 
 | 
      this.currentItem = {}; 
 | 
    }, 
 | 
    itemClick(item, index) { 
 | 
      this.currentIndex = index; 
 | 
      this.colWidth = this.currentComponents[this.currentIndex].width; 
 | 
      this.currentItem = this.currentComponents[this.currentIndex]; 
 | 
    }, 
 | 
    //开始拖拽事件 
 | 
    onStart(e, e1) { 
 | 
      this.drag = true; 
 | 
    }, 
 | 
    getField() { 
 | 
      return "field" + new Date().valueOf(); 
 | 
    }, 
 | 
    //左边往右边拖动时的事件 
 | 
    end1(e) { 
 | 
      if (1 == 1 && e.from !== e.to) { 
 | 
        let obj = JSON.parse(JSON.stringify(this.components[e.oldIndex])); 
 | 
        obj.field = this.getField(); 
 | 
        obj.width = 100; 
 | 
        obj.readonly = false; 
 | 
        obj.required = false; 
 | 
        this.currentComponents.splice(e.newIndex, 1, obj); 
 | 
        this.userComponents.splice(0); 
 | 
        this.userComponents.push(...this.currentComponents); 
 | 
        // this.currentComponents = this.currentComponents.filter((x) => { 
 | 
        //   return x.hasOwnProperty("field"); 
 | 
        // }); 
 | 
        this.colWidth = 100; 
 | 
        this.currentIndex = e.newIndex; //this.currentComponents.length - 1; 
 | 
        this.currentItem = this.currentComponents[this.currentIndex]; 
 | 
      } 
 | 
    }, 
 | 
    //右边往左边拖动时的事件 
 | 
    end2(e) {}, 
 | 
    onMove1(e, originalEvent) { 
 | 
      // this.moveId = e.relatedContext.element.id; 
 | 
      return true; 
 | 
    }, 
 | 
    //move回调方法 
 | 
    onMove(e, originalEvent) { 
 | 
      console.log(JSON.stringify(this.currentComponents)); 
 | 
      return true; 
 | 
    }, 
 | 
    dicChange(key) { 
 | 
      debugger 
 | 
      this.http 
 | 
        .post("api/Sys_Dictionary/GetVueDictionary", [key], true) 
 | 
        .then((result) => { 
 | 
          this.currentItem.data = result[0].data; 
 | 
          if (result[0].data.length) { 
 | 
            if (this.currentItem.type == "select") { 
 | 
              this.currentItem.value = result[0].data[0].value; 
 | 
            } else { 
 | 
              this.currentItem.values = [result[0].data[0].value]; 
 | 
            } 
 | 
          } 
 | 
        }); 
 | 
    }, 
 | 
    example1() { 
 | 
      this.currentComponents = this.options1; 
 | 
    }, 
 | 
    example2() { 
 | 
      this.currentComponents = this.options2; 
 | 
    }, 
 | 
    example3() { 
 | 
      this.currentComponents = this.options3; 
 | 
    }, 
 | 
  }, 
 | 
  computed: { 
 | 
    tabsTable() { 
 | 
      return this.currentComponents.filter((x) => { 
 | 
        return x.type == "table" && x.tabs == true; 
 | 
      }); 
 | 
    }, 
 | 
  }, 
 | 
}; 
 | 
</script> 
 | 
<style lang="less" scoped> 
 | 
* { 
 | 
  box-sizing: border-box; 
 | 
} 
 | 
.drag-container { 
 | 
  /* padding: 20px; */ 
 | 
  display: flex; 
 | 
  height: 100%; 
 | 
  position: absolute; 
 | 
  width: 100%; 
 | 
  box-sizing: border-box; 
 | 
} 
 | 
.drag-left { 
 | 
  width: 250px; 
 | 
  display: flex; 
 | 
  border-right: 1px solid #eee; 
 | 
  flex-direction: column; 
 | 
} 
 | 
.left-title { 
 | 
  height: 42px; 
 | 
  text-align: left; 
 | 
  border-right: 1px solid #eee; 
 | 
  padding: 10px 0 10px 11px; 
 | 
  border-bottom: 1px solid #eee; 
 | 
} 
 | 
.drag-center { 
 | 
  display: flex; 
 | 
  flex-direction: column; 
 | 
  flex: 1; 
 | 
} 
 | 
.left-draggable-item { 
 | 
  //   flex: 1; 
 | 
  display: inline-block; 
 | 
  padding: 5px; 
 | 
  //   border-right: 1px solid #eee; 
 | 
} 
 | 
  
 | 
.left-draggable-item .item { 
 | 
  cursor: move; 
 | 
  float: left; 
 | 
  width: 111px; 
 | 
  /* height: 20px; */ 
 | 
  text-align: center; 
 | 
  border: 1px solid #eeeeee; 
 | 
  padding: 2px 13px; 
 | 
  text-align: left; 
 | 
  line-height: 28px; 
 | 
  margin: 4px; 
 | 
  border-radius: 3px; 
 | 
  background: #f0f9eb; 
 | 
  font-size: 13px; 
 | 
} 
 | 
// .drag-center-item { 
 | 
//   display: inline-block; 
 | 
//   width: 100%; 
 | 
//   height: calc(100vh - 122px); 
 | 
//   padding: 10px; 
 | 
// } 
 | 
.draggable-container { 
 | 
  display: inline-block; 
 | 
  width: 100%; 
 | 
  height: calc(100vh - 215px); 
 | 
  padding: 10px 0; 
 | 
} 
 | 
  
 | 
.item2 { 
 | 
  position: relative; 
 | 
  cursor: move; 
 | 
  padding: 18px 10px 10px 10px; 
 | 
  text-align: left; 
 | 
  float: left; 
 | 
  margin-bottom: 10px; 
 | 
} 
 | 
.item2 .el-icon-delete, 
 | 
.item2 .el-icon-document-copy { 
 | 
  position: absolute; 
 | 
  right: 10px; 
 | 
  top: 2px; 
 | 
  padding: 5px; 
 | 
  display: none; 
 | 
  color: red; 
 | 
  cursor: pointer; 
 | 
} 
 | 
.item2 .el-icon-document-copy { 
 | 
  right: 35px; 
 | 
} 
 | 
.item2:hover, 
 | 
.actived { 
 | 
  background: #f0f9eb; 
 | 
} 
 | 
.item:hover { 
 | 
  border: 1px dashed #787be8; 
 | 
  color: #787be8; 
 | 
} 
 | 
.item2:hover .el-icon-delete, 
 | 
.item2:hover .el-icon-document-copy { 
 | 
  display: block; 
 | 
} 
 | 
  
 | 
.drag-right { 
 | 
  background: #f7fbff3d; 
 | 
  width: 250px; 
 | 
  border-left: 1px solid #eee; 
 | 
} 
 | 
  
 | 
.center-top { 
 | 
  height: 42px; 
 | 
  line-height: 41px; 
 | 
  background: #f2f5fb; 
 | 
  border-bottom: 1px solid #eee; 
 | 
  text-align: left; 
 | 
  padding: 0 10px; 
 | 
  font-size: 12px; 
 | 
  color: #3391f3; 
 | 
} 
 | 
.center-top span { 
 | 
  margin-right: 10px; 
 | 
} 
 | 
.attr { 
 | 
  padding: 0px 15px 15px 15px; 
 | 
} 
 | 
.attr-item { 
 | 
  text-align: left; 
 | 
  margin-top: 12px; 
 | 
  font-size: 14px; 
 | 
} 
 | 
.attr-item .text { 
 | 
  padding: 0 0 5px 5px; 
 | 
} 
 | 
.attr2 { 
 | 
  display: flex; 
 | 
} 
 | 
.attr2 > div { 
 | 
  flex: 1; 
 | 
} 
 | 
.tips { 
 | 
  position: absolute; 
 | 
  font-size: 26px; 
 | 
  letter-spacing: 6px; 
 | 
  left: 0px; 
 | 
  right: 0px; 
 | 
  top: 150px; 
 | 
  width: 500px; 
 | 
  margin: auto; 
 | 
  color: #c5c5c5; 
 | 
} 
 | 
.col-line { 
 | 
  line-height: 25px; 
 | 
  font-weight: bold; 
 | 
  border-bottom: 1px solid rgb(218 218 218); 
 | 
} 
 | 
.drag-container ::v-deep(.el-col) { 
 | 
  width: 100%; 
 | 
} 
 | 
.drag-center ::v-deep(.el-form-item__label) { 
 | 
  line-height: 0 !important; 
 | 
} 
 | 
.drag-center ::v-deep(.el-scrollbar__wrap) { 
 | 
  overflow-x: hidden; 
 | 
} 
 | 
.drag-center ::v-deep(.el-form-item) { 
 | 
  margin-bottom: 10px; 
 | 
} 
 | 
.drag-center ::v-deep(.el-date-editor) { 
 | 
  width: 100%; 
 | 
} 
 | 
.drag-center ::v-deep(.el-checkbox) { 
 | 
  margin-right: 15px; 
 | 
} 
 | 
.drag-center ::v-deep(.el-checkbox__label) { 
 | 
  padding-left: 5px; 
 | 
} 
 | 
.drag-center ::v-deep(.hello > div) { 
 | 
  z-index: 500 !important; 
 | 
} 
 | 
.drag-center ::v-deep(th), 
 | 
.drag-center ::v-deep(td) { 
 | 
  padding: 6px 0; 
 | 
} 
 | 
.example { 
 | 
  margin-top: 8px; 
 | 
  > div { 
 | 
    cursor: pointer; 
 | 
    padding: 14px 20px; 
 | 
    border-top: 1px solid #eee; 
 | 
    font-size: 13px; 
 | 
    color: #646465; 
 | 
    position: relative; 
 | 
  } 
 | 
  > div:hover { 
 | 
    background: rgb(231, 231, 231); 
 | 
  } 
 | 
  i { 
 | 
    position: absolute; 
 | 
    right: 20px; 
 | 
  } 
 | 
} 
 | 
.btns { 
 | 
  padding: 8px 0; 
 | 
  display: flex; 
 | 
  > div { 
 | 
    flex: 1; 
 | 
  } 
 | 
  .btns-left { 
 | 
    padding-top: 8px; 
 | 
    color: black; 
 | 
    font-weight: bold; 
 | 
  } 
 | 
  .btns-right { 
 | 
    text-align: right; 
 | 
  } 
 | 
} 
 | 
</style> 
 |