mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-11-04 20:28:44 +08:00 
			
		
		
		
	流程表单,接入新的 form generator 版本
This commit is contained in:
		@@ -7,42 +7,33 @@
 | 
			
		||||
      <el-scrollbar class="left-scrollbar">
 | 
			
		||||
        <!-- 左边:表单项 -->
 | 
			
		||||
        <div class="components-list">
 | 
			
		||||
          <div class="components-title">
 | 
			
		||||
            <svg-icon icon-class="component" />输入型组件
 | 
			
		||||
          </div>
 | 
			
		||||
          <draggable class="components-draggable" :list="inputComponents" :group="{ name: 'componentsGroup', pull: 'clone', put: false }"
 | 
			
		||||
            :clone="cloneComponent" draggable=".components-item" :sort="false" @end="onEnd">
 | 
			
		||||
            <div v-for="(element, index) in inputComponents" :key="index" class="components-item" @click="addComponent(element)">
 | 
			
		||||
              <div class="components-body">
 | 
			
		||||
                <svg-icon :icon-class="element.tagIcon" />
 | 
			
		||||
                {{ element.label }}
 | 
			
		||||
              </div>
 | 
			
		||||
          <div v-for="(item, listIndex) in leftComponents" :key="listIndex">
 | 
			
		||||
            <div class="components-title">
 | 
			
		||||
              <svg-icon icon-class="component" />
 | 
			
		||||
              {{ item.title }}
 | 
			
		||||
            </div>
 | 
			
		||||
          </draggable>
 | 
			
		||||
          <div class="components-title">
 | 
			
		||||
            <svg-icon icon-class="component" />选择型组件
 | 
			
		||||
          </div>
 | 
			
		||||
          <draggable class="components-draggable" :list="selectComponents" :group="{ name: 'componentsGroup', pull: 'clone', put: false }"
 | 
			
		||||
            :clone="cloneComponent" draggable=".components-item" :sort="false" @end="onEnd">
 | 
			
		||||
            <div v-for="(element, index) in selectComponents" :key="index" class="components-item" @click="addComponent(element)">
 | 
			
		||||
              <div class="components-body">
 | 
			
		||||
                <svg-icon :icon-class="element.tagIcon" />
 | 
			
		||||
                {{ element.label }}
 | 
			
		||||
            <draggable
 | 
			
		||||
              class="components-draggable"
 | 
			
		||||
              :list="item.list"
 | 
			
		||||
              :group="{ name: 'componentsGroup', pull: 'clone', put: false }"
 | 
			
		||||
              :clone="cloneComponent"
 | 
			
		||||
              draggable=".components-item"
 | 
			
		||||
              :sort="false"
 | 
			
		||||
              @end="onEnd"
 | 
			
		||||
            >
 | 
			
		||||
              <div
 | 
			
		||||
                v-for="(element, index) in item.list"
 | 
			
		||||
                :key="index"
 | 
			
		||||
                class="components-item"
 | 
			
		||||
                @click="addComponent(element)"
 | 
			
		||||
              >
 | 
			
		||||
                <div class="components-body">
 | 
			
		||||
                  <svg-icon :icon-class="element.__config__.tagIcon" />
 | 
			
		||||
                  {{ element.__config__.label }}
 | 
			
		||||
                </div>
 | 
			
		||||
              </div>
 | 
			
		||||
            </div>
 | 
			
		||||
          </draggable>
 | 
			
		||||
          <div class="components-title">
 | 
			
		||||
            <svg-icon icon-class="component" />布局型组件
 | 
			
		||||
            </draggable>
 | 
			
		||||
          </div>
 | 
			
		||||
          <draggable class="components-draggable" :list="layoutComponents" :group="{ name: 'componentsGroup', pull: 'clone', put: false }"
 | 
			
		||||
                     :clone="cloneComponent" draggable=".components-item" :sort="false" @end="onEnd">
 | 
			
		||||
            <div v-for="(element, index) in layoutComponents" :key="index" class="components-item" @click="addComponent(element)">
 | 
			
		||||
              <div class="components-body">
 | 
			
		||||
                <svg-icon :icon-class="element.tagIcon" />
 | 
			
		||||
                {{ element.label }}
 | 
			
		||||
              </div>
 | 
			
		||||
            </div>
 | 
			
		||||
          </draggable>
 | 
			
		||||
 | 
			
		||||
          <!-- 左边:动态表单 -->
 | 
			
		||||
          <el-form ref="form" :model="form" :rules="rules" label-width="80px">
 | 
			
		||||
@@ -64,20 +55,47 @@
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <div class="center-board">
 | 
			
		||||
      <!-- 上面:操作按钮 -->
 | 
			
		||||
      <div class="action-bar">
 | 
			
		||||
        <el-button icon="el-icon-check" type="text" @click="save">保存</el-button>
 | 
			
		||||
        <el-button class="delete-btn" icon="el-icon-delete" type="text" @click="empty">清空</el-button>
 | 
			
		||||
        <!--        <el-button icon="el-icon-video-play" type="text" @click="run">-->
 | 
			
		||||
<!--          运行-->
 | 
			
		||||
<!--        </el-button>-->
 | 
			
		||||
        <el-button icon="el-icon-view" type="text" @click="showJson">
 | 
			
		||||
          查看json
 | 
			
		||||
        </el-button>
 | 
			
		||||
<!--        <el-button icon="el-icon-download" type="text" @click="download">-->
 | 
			
		||||
<!--          导出vue文件-->
 | 
			
		||||
<!--        </el-button>-->
 | 
			
		||||
<!--        <el-button class="copy-btn-main" icon="el-icon-document-copy" type="text" @click="copy">-->
 | 
			
		||||
<!--          复制代码-->
 | 
			
		||||
<!--        </el-button>-->
 | 
			
		||||
        <el-button class="delete-btn" icon="el-icon-delete" type="text" @click="empty">
 | 
			
		||||
          清空
 | 
			
		||||
        </el-button>
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      <!-- 中间,表单项 -->
 | 
			
		||||
      <el-scrollbar class="center-scrollbar">
 | 
			
		||||
        <el-row class="center-board-row" :gutter="formConf.gutter">
 | 
			
		||||
          <el-form :size="formConf.size" :label-position="formConf.labelPosition" :disabled="formConf.disabled"
 | 
			
		||||
            :label-width="formConf.labelWidth + 'px'">
 | 
			
		||||
          <el-form
 | 
			
		||||
            :size="formConf.size"
 | 
			
		||||
            :label-position="formConf.labelPosition"
 | 
			
		||||
            :disabled="formConf.disabled"
 | 
			
		||||
            :label-width="formConf.labelWidth + 'px'"
 | 
			
		||||
          >
 | 
			
		||||
            <draggable class="drawing-board" :list="drawingList" :animation="340" group="componentsGroup">
 | 
			
		||||
              <draggable-item v-for="(element, index) in drawingList" :key="element.renderKey" :drawing-list="drawingList"
 | 
			
		||||
                :element="element" :index="index" :active-id="activeId" :form-conf="formConf"
 | 
			
		||||
                @activeItem="activeFormItem" @copyItem="drawingItemCopy" @deleteItem="drawingItemDelete"/>
 | 
			
		||||
              <draggable-item
 | 
			
		||||
                v-for="(item, index) in drawingList"
 | 
			
		||||
                :key="item.renderKey"
 | 
			
		||||
                :drawing-list="drawingList"
 | 
			
		||||
                :current-item="item"
 | 
			
		||||
                :index="index"
 | 
			
		||||
                :active-id="activeId"
 | 
			
		||||
                :form-conf="formConf"
 | 
			
		||||
                @activeItem="activeFormItem"
 | 
			
		||||
                @copyItem="drawingItemCopy"
 | 
			
		||||
                @deleteItem="drawingItemDelete"
 | 
			
		||||
              />
 | 
			
		||||
            </draggable>
 | 
			
		||||
            <div v-show="!drawingList.length" class="empty-info">
 | 
			
		||||
              从左侧拖入或点选组件进行表单设计
 | 
			
		||||
@@ -88,52 +106,128 @@
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <!-- 右边:组件属性/表单属性 -->
 | 
			
		||||
    <right-panel :active-data="activeData" :form-conf="formConf" :show-field="!!drawingList.length" @tag-change="tagChange"/>
 | 
			
		||||
    <right-panel
 | 
			
		||||
      :active-data="activeData"
 | 
			
		||||
      :form-conf="formConf"
 | 
			
		||||
      :show-field="!!drawingList.length"
 | 
			
		||||
      @tag-change="tagChange"
 | 
			
		||||
      @fetch-data="fetchData"
 | 
			
		||||
    />
 | 
			
		||||
 | 
			
		||||
<!--    <form-drawer-->
 | 
			
		||||
<!--      :visible.sync="drawerVisible"-->
 | 
			
		||||
<!--      :form-data="formData"-->
 | 
			
		||||
<!--      size="100%"-->
 | 
			
		||||
<!--      :generate-conf="generateConf"-->
 | 
			
		||||
<!--    />-->
 | 
			
		||||
 | 
			
		||||
    <json-drawer
 | 
			
		||||
      size="60%"
 | 
			
		||||
      :visible.sync="jsonDrawerVisible"
 | 
			
		||||
      :json-str="JSON.stringify(formData)"
 | 
			
		||||
      @refresh="refreshJson"
 | 
			
		||||
    />
 | 
			
		||||
 | 
			
		||||
<!--    <code-type-dialog-->
 | 
			
		||||
<!--      :visible.sync="dialogVisible"-->
 | 
			
		||||
<!--      title="选择生成类型"-->
 | 
			
		||||
<!--      :show-file-name="showFileName"-->
 | 
			
		||||
<!--      @confirm="generate"-->
 | 
			
		||||
<!--    />-->
 | 
			
		||||
 | 
			
		||||
<!--    <input id="copyNode" type="hidden">-->
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import draggable from 'vuedraggable'
 | 
			
		||||
import render from '@/utils/generator/render'
 | 
			
		||||
import { inputComponents, selectComponents, layoutComponents, formConf} from '@/utils/generator/config'
 | 
			
		||||
import drawingDefalut from '@/utils/generator/drawingDefalut'
 | 
			
		||||
// import logo from '@/assets/logo/logo.png'
 | 
			
		||||
import DraggableItem from './../../tool/build/DraggableItem'
 | 
			
		||||
import RightPanel from './../../tool/build/RightPanel'
 | 
			
		||||
import {createForm, getForm, updateForm} from "@/api/bpm/form";
 | 
			
		||||
import { debounce } from 'throttle-debounce'
 | 
			
		||||
import { saveAs } from 'file-saver'
 | 
			
		||||
import ClipboardJS from 'clipboard'
 | 
			
		||||
import render from '@/components/render/render'
 | 
			
		||||
import FormDrawer from '@/views/tool/build/FormDrawer'
 | 
			
		||||
import JsonDrawer from '@/views/tool/build/JsonDrawer'
 | 
			
		||||
import RightPanel from '@/views/tool/build/RightPanel'
 | 
			
		||||
import {
 | 
			
		||||
  inputComponents, selectComponents, layoutComponents, formConf
 | 
			
		||||
} from '@/utils/generator/config'
 | 
			
		||||
import {
 | 
			
		||||
  exportDefault, beautifierConf, isNumberStr, titleCase, deepClone, isObjectObject
 | 
			
		||||
} from '@/utils/index'
 | 
			
		||||
import {
 | 
			
		||||
  makeUpHtml, vueTemplate, vueScript, cssStyle
 | 
			
		||||
} from '@/components/generator/html'
 | 
			
		||||
import { makeUpJs } from '@/components/generator/js'
 | 
			
		||||
import { makeUpCss } from '@/components/generator/css'
 | 
			
		||||
import drawingDefalut from '@/components/generator/drawingDefalut'
 | 
			
		||||
import logo from '@/assets/logo/logo.png'
 | 
			
		||||
import CodeTypeDialog from '@/views/tool/build/CodeTypeDialog'
 | 
			
		||||
import DraggableItem from '@/views/tool/build/DraggableItem'
 | 
			
		||||
import {
 | 
			
		||||
  getDrawingList, saveDrawingList, getIdGlobal, saveIdGlobal, getFormConf
 | 
			
		||||
} from '@/utils/db'
 | 
			
		||||
import loadBeautifier from '@/utils/loadBeautifier'
 | 
			
		||||
import {SysCommonStatusEnum} from "@/utils/constants";
 | 
			
		||||
import {createForm, getForm, updateForm} from "@/api/bpm/form";
 | 
			
		||||
 | 
			
		||||
// const emptyActiveData = { style: {}, autosize: {} }
 | 
			
		||||
let beautifier
 | 
			
		||||
const emptyActiveData = { style: {}, autosize: {} }
 | 
			
		||||
let oldActiveId
 | 
			
		||||
let tempActiveData
 | 
			
		||||
const drawingListInDB = getDrawingList()
 | 
			
		||||
const formConfInDB = getFormConf()
 | 
			
		||||
const idGlobal = getIdGlobal()
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  components: {
 | 
			
		||||
    draggable,
 | 
			
		||||
    render,
 | 
			
		||||
    FormDrawer,
 | 
			
		||||
    JsonDrawer,
 | 
			
		||||
    RightPanel,
 | 
			
		||||
    CodeTypeDialog,
 | 
			
		||||
    DraggableItem
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      // logo,
 | 
			
		||||
      idGlobal: 100, // 自动 ID 生成时,全局递增。例如说 field100
 | 
			
		||||
      formConf, // 表单格式
 | 
			
		||||
      logo,
 | 
			
		||||
      idGlobal,
 | 
			
		||||
      formConf,
 | 
			
		||||
      inputComponents,
 | 
			
		||||
      selectComponents,
 | 
			
		||||
      layoutComponents,
 | 
			
		||||
      labelWidth: 100,
 | 
			
		||||
 | 
			
		||||
      // drawingList: drawingDefalut,
 | 
			
		||||
      drawingData: {}, // 生成后的表单数据
 | 
			
		||||
      activeId: drawingDefalut[0].__config__.formId,
 | 
			
		||||
 | 
			
		||||
      drawingList: [], // 表单项的数组
 | 
			
		||||
      activeId: undefined,
 | 
			
		||||
      activeData: {},
 | 
			
		||||
      // drawerVisible: false,
 | 
			
		||||
      // formData: {},
 | 
			
		||||
      // dialogVisible: false,
 | 
			
		||||
      // showFileName: false,
 | 
			
		||||
      // activeId: undefined,
 | 
			
		||||
      // activeData: {},
 | 
			
		||||
 | 
			
		||||
      drawerVisible: false,
 | 
			
		||||
      formData: {},
 | 
			
		||||
      dialogVisible: false,
 | 
			
		||||
      jsonDrawerVisible: false,
 | 
			
		||||
      generateConf: null,
 | 
			
		||||
      showFileName: false,
 | 
			
		||||
      activeData: drawingDefalut[0], // 右边编辑器激活的表单项
 | 
			
		||||
      saveDrawingListDebounce: debounce(340, saveDrawingList),
 | 
			
		||||
      saveIdGlobalDebounce: debounce(340, saveIdGlobal),
 | 
			
		||||
      leftComponents: [
 | 
			
		||||
        {
 | 
			
		||||
          title: '输入型组件',
 | 
			
		||||
          list: inputComponents
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          title: '选择型组件',
 | 
			
		||||
          list: selectComponents
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          title: '布局型组件',
 | 
			
		||||
          list: layoutComponents
 | 
			
		||||
        }
 | 
			
		||||
      ],
 | 
			
		||||
 | 
			
		||||
      // 表单参数
 | 
			
		||||
      form: {
 | 
			
		||||
@@ -146,12 +240,14 @@ export default {
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  computed: {
 | 
			
		||||
  },
 | 
			
		||||
  watch: {
 | 
			
		||||
    // eslint-disable-next-line func-names
 | 
			
		||||
    'activeData.label': function (val, oldVal) {
 | 
			
		||||
    'activeData.__config__.label': function (val, oldVal) {
 | 
			
		||||
      if (
 | 
			
		||||
        this.activeData.placeholder === undefined
 | 
			
		||||
        || !this.activeData.tag
 | 
			
		||||
        || !this.activeData.__config__.tag
 | 
			
		||||
        || oldActiveId !== this.activeId
 | 
			
		||||
      ) {
 | 
			
		||||
        return
 | 
			
		||||
@@ -163,8 +259,50 @@ export default {
 | 
			
		||||
        oldActiveId = val
 | 
			
		||||
      },
 | 
			
		||||
      immediate: true
 | 
			
		||||
    },
 | 
			
		||||
    drawingList: {
 | 
			
		||||
      handler(val) {
 | 
			
		||||
        this.saveDrawingListDebounce(val)
 | 
			
		||||
        if (val.length === 0) this.idGlobal = 100
 | 
			
		||||
      },
 | 
			
		||||
      deep: true
 | 
			
		||||
    },
 | 
			
		||||
    idGlobal: {
 | 
			
		||||
      handler(val) {
 | 
			
		||||
        this.saveIdGlobalDebounce(val)
 | 
			
		||||
      },
 | 
			
		||||
      immediate: true
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  mounted() {
 | 
			
		||||
    // 【add by 芋道源码】不读缓存
 | 
			
		||||
    // if (Array.isArray(drawingListInDB) && drawingListInDB.length > 0) {
 | 
			
		||||
    //   this.drawingList = drawingListInDB
 | 
			
		||||
    // } else {
 | 
			
		||||
    //   this.drawingList = drawingDefalut
 | 
			
		||||
    // }
 | 
			
		||||
    // this.activeFormItem(this.drawingList[0])
 | 
			
		||||
    // if (formConfInDB) {
 | 
			
		||||
    //   this.formConf = formConfInDB
 | 
			
		||||
    // }
 | 
			
		||||
    loadBeautifier(btf => {
 | 
			
		||||
      beautifier = btf
 | 
			
		||||
    })
 | 
			
		||||
    const clipboard = new ClipboardJS('#copyNode', {
 | 
			
		||||
      text: trigger => {
 | 
			
		||||
        const codeStr = this.generateCode()
 | 
			
		||||
        this.$notify({
 | 
			
		||||
          title: '成功',
 | 
			
		||||
          message: '代码已复制到剪切板,可粘贴。',
 | 
			
		||||
          type: 'success'
 | 
			
		||||
        })
 | 
			
		||||
        return codeStr
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
    clipboard.on('error', e => {
 | 
			
		||||
      this.$message.error('代码复制失败')
 | 
			
		||||
    })
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    // 读取表单配置
 | 
			
		||||
    const formId = this.$route.query && this.$route.query.formId
 | 
			
		||||
@@ -179,49 +317,105 @@ export default {
 | 
			
		||||
        }
 | 
			
		||||
        this.formConf = JSON.parse(data.conf)
 | 
			
		||||
        this.drawingList = this.decodeFields(data.fields)
 | 
			
		||||
        // 设置激活的表单项
 | 
			
		||||
        this.activeData = this.drawingList[0]
 | 
			
		||||
        this.activeId = this.activeData.__config__.formId
 | 
			
		||||
        // 设置 idGlobal,避免重复
 | 
			
		||||
        this.idGlobal += this.drawingList.length
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    activeFormItem(element) {
 | 
			
		||||
      this.activeData = element
 | 
			
		||||
      this.activeId = element.formId
 | 
			
		||||
    setObjectValueReduce(obj, strKeys, data) {
 | 
			
		||||
      const arr = strKeys.split('.')
 | 
			
		||||
      arr.reduce((pre, item, i) => {
 | 
			
		||||
        if (arr.length === i + 1) {
 | 
			
		||||
          pre[item] = data
 | 
			
		||||
        } else if (!isObjectObject(pre[item])) {
 | 
			
		||||
          pre[item] = {}
 | 
			
		||||
        }
 | 
			
		||||
        return pre[item]
 | 
			
		||||
      }, obj)
 | 
			
		||||
    },
 | 
			
		||||
    onEnd(obj, a) {
 | 
			
		||||
    setRespData(component, resp) {
 | 
			
		||||
      const { dataPath, renderKey, dataConsumer } = component.__config__
 | 
			
		||||
      if (!dataPath || !dataConsumer) return
 | 
			
		||||
      const respData = dataPath.split('.').reduce((pre, item) => pre[item], resp)
 | 
			
		||||
 | 
			
		||||
      // 将请求回来的数据,赋值到指定属性。
 | 
			
		||||
      // 以el-tabel为例,根据Element文档,应该将数据赋值给el-tabel的data属性,所以dataConsumer的值应为'data';
 | 
			
		||||
      // 此时赋值代码可写成 component[dataConsumer] = respData;
 | 
			
		||||
      // 但为支持更深层级的赋值(如:dataConsumer的值为'options.data'),使用setObjectValueReduce
 | 
			
		||||
      this.setObjectValueReduce(component, dataConsumer, respData)
 | 
			
		||||
      const i = this.drawingList.findIndex(item => item.__config__.renderKey === renderKey)
 | 
			
		||||
      if (i > -1) this.$set(this.drawingList, i, component)
 | 
			
		||||
    },
 | 
			
		||||
    fetchData(component) {
 | 
			
		||||
      const { dataType, method, url } = component.__config__
 | 
			
		||||
      if (dataType === 'dynamic' && method && url) {
 | 
			
		||||
        this.setLoading(component, true)
 | 
			
		||||
        this.$axios({
 | 
			
		||||
          method,
 | 
			
		||||
          url
 | 
			
		||||
        }).then(resp => {
 | 
			
		||||
          this.setLoading(component, false)
 | 
			
		||||
          this.setRespData(component, resp.data)
 | 
			
		||||
        })
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    setLoading(component, val) {
 | 
			
		||||
      const { directives } = component
 | 
			
		||||
      if (Array.isArray(directives)) {
 | 
			
		||||
        const t = directives.find(d => d.name === 'loading')
 | 
			
		||||
        if (t) t.value = val
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    activeFormItem(currentItem) {
 | 
			
		||||
      this.activeData = currentItem
 | 
			
		||||
      this.activeId = currentItem.__config__.formId
 | 
			
		||||
    },
 | 
			
		||||
    onEnd(obj) {
 | 
			
		||||
      if (obj.from !== obj.to) {
 | 
			
		||||
        this.fetchData(tempActiveData)
 | 
			
		||||
        this.activeData = tempActiveData
 | 
			
		||||
        this.activeId = this.idGlobal
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    addComponent(item) {
 | 
			
		||||
      const clone = this.cloneComponent(item)
 | 
			
		||||
      this.fetchData(clone)
 | 
			
		||||
      this.drawingList.push(clone)
 | 
			
		||||
      this.activeFormItem(clone)
 | 
			
		||||
    },
 | 
			
		||||
    cloneComponent(origin) {
 | 
			
		||||
      const clone = JSON.parse(JSON.stringify(origin))
 | 
			
		||||
      clone.formId = ++this.idGlobal
 | 
			
		||||
      clone.span = formConf.span
 | 
			
		||||
      clone.renderKey = +new Date() // 改变renderKey后可以实现强制更新组件
 | 
			
		||||
      if (!clone.layout) clone.layout = 'colFormItem'
 | 
			
		||||
      if (clone.layout === 'colFormItem') {
 | 
			
		||||
        clone.vModel = `field${this.idGlobal}`
 | 
			
		||||
        clone.placeholder !== undefined && (clone.placeholder += clone.label)
 | 
			
		||||
        tempActiveData = clone
 | 
			
		||||
      } else if (clone.layout === 'rowFormItem') {
 | 
			
		||||
        delete clone.label
 | 
			
		||||
        clone.componentName = `row${this.idGlobal}`
 | 
			
		||||
        clone.gutter = this.formConf.gutter
 | 
			
		||||
        tempActiveData = clone
 | 
			
		||||
      }
 | 
			
		||||
      const clone = deepClone(origin)
 | 
			
		||||
      const config = clone.__config__
 | 
			
		||||
      config.span = this.formConf.span // 生成代码时,会根据span做精简判断
 | 
			
		||||
      this.createIdAndKey(clone)
 | 
			
		||||
      clone.placeholder !== undefined && (clone.placeholder += config.label)
 | 
			
		||||
      tempActiveData = clone
 | 
			
		||||
      return tempActiveData
 | 
			
		||||
    },
 | 
			
		||||
    createIdAndKey(item) {
 | 
			
		||||
      const config = item.__config__
 | 
			
		||||
      config.formId = ++this.idGlobal
 | 
			
		||||
      config.renderKey = `${config.formId}${+new Date()}` // 改变renderKey后可以实现强制更新组件
 | 
			
		||||
      if (config.layout === 'colFormItem') {
 | 
			
		||||
        item.__vModel__ = `field${this.idGlobal}`
 | 
			
		||||
      } else if (config.layout === 'rowFormItem') {
 | 
			
		||||
        config.componentName = `row${this.idGlobal}`
 | 
			
		||||
        !Array.isArray(config.children) && (config.children = [])
 | 
			
		||||
        delete config.label // rowFormItem无需配置label属性
 | 
			
		||||
      }
 | 
			
		||||
      if (Array.isArray(config.children)) {
 | 
			
		||||
        config.children = config.children.map(childItem => this.createIdAndKey(childItem))
 | 
			
		||||
      }
 | 
			
		||||
      return item
 | 
			
		||||
    },
 | 
			
		||||
    // 获得表单数据
 | 
			
		||||
    AssembleFormData() {
 | 
			
		||||
      this.formData = {
 | 
			
		||||
        fields: JSON.parse(JSON.stringify(this.drawingList)),
 | 
			
		||||
        fields: deepClone(this.drawingList),
 | 
			
		||||
        ...this.formConf
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
@@ -272,34 +466,39 @@ export default {
 | 
			
		||||
      })
 | 
			
		||||
      return drawingList
 | 
			
		||||
    },
 | 
			
		||||
    generate(data) {
 | 
			
		||||
      const func = this[`exec${titleCase(this.operationType)}`]
 | 
			
		||||
      this.generateConf = data
 | 
			
		||||
      func && func(data)
 | 
			
		||||
    },
 | 
			
		||||
    execRun(data) {
 | 
			
		||||
      this.AssembleFormData()
 | 
			
		||||
      this.drawerVisible = true
 | 
			
		||||
    },
 | 
			
		||||
    execDownload(data) {
 | 
			
		||||
      const codeStr = this.generateCode()
 | 
			
		||||
      const blob = new Blob([codeStr], { type: 'text/plain;charset=utf-8' })
 | 
			
		||||
      saveAs(blob, data.fileName)
 | 
			
		||||
    },
 | 
			
		||||
    execCopy(data) {
 | 
			
		||||
      document.getElementById('copyNode').click()
 | 
			
		||||
    },
 | 
			
		||||
    empty() {
 | 
			
		||||
      this.$confirm('确定要清空所有组件吗?', '提示', { type: 'warning' }).then(
 | 
			
		||||
        () => {
 | 
			
		||||
          this.drawingList = []
 | 
			
		||||
          this.idGlobal = 100
 | 
			
		||||
        }
 | 
			
		||||
      )
 | 
			
		||||
    },
 | 
			
		||||
    drawingItemCopy(item, parent) {
 | 
			
		||||
      let clone = JSON.parse(JSON.stringify(item))
 | 
			
		||||
    drawingItemCopy(item, list) {
 | 
			
		||||
      let clone = deepClone(item)
 | 
			
		||||
      clone = this.createIdAndKey(clone)
 | 
			
		||||
      parent.push(clone)
 | 
			
		||||
      list.push(clone)
 | 
			
		||||
      this.activeFormItem(clone)
 | 
			
		||||
    },
 | 
			
		||||
    createIdAndKey(item) {
 | 
			
		||||
      item.formId = ++this.idGlobal
 | 
			
		||||
      item.renderKey = +new Date()
 | 
			
		||||
      if (item.layout === 'colFormItem') {
 | 
			
		||||
        item.vModel = `field${this.idGlobal}`
 | 
			
		||||
      } else if (item.layout === 'rowFormItem') {
 | 
			
		||||
        item.componentName = `row${this.idGlobal}`
 | 
			
		||||
      }
 | 
			
		||||
      if (Array.isArray(item.children)) {
 | 
			
		||||
        item.children = item.children.map(childItem => this.createIdAndKey(childItem))
 | 
			
		||||
      }
 | 
			
		||||
      return item
 | 
			
		||||
    },
 | 
			
		||||
    drawingItemDelete(index, parent) {
 | 
			
		||||
      parent.splice(index, 1)
 | 
			
		||||
    drawingItemDelete(index, list) {
 | 
			
		||||
      list.splice(index, 1)
 | 
			
		||||
      this.$nextTick(() => {
 | 
			
		||||
        const len = this.drawingList.length
 | 
			
		||||
        if (len) {
 | 
			
		||||
@@ -307,17 +506,47 @@ export default {
 | 
			
		||||
        }
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
    generateCode() {
 | 
			
		||||
      const { type } = this.generateConf
 | 
			
		||||
      this.AssembleFormData()
 | 
			
		||||
      const script = vueScript(makeUpJs(this.formData, type))
 | 
			
		||||
      const html = vueTemplate(makeUpHtml(this.formData, type))
 | 
			
		||||
      const css = cssStyle(makeUpCss(this.formData))
 | 
			
		||||
      return beautifier.html(html + script + css, beautifierConf.html)
 | 
			
		||||
    },
 | 
			
		||||
    showJson() {
 | 
			
		||||
      this.AssembleFormData()
 | 
			
		||||
      this.jsonDrawerVisible = true
 | 
			
		||||
    },
 | 
			
		||||
    download() {
 | 
			
		||||
      this.dialogVisible = true
 | 
			
		||||
      this.showFileName = true
 | 
			
		||||
      this.operationType = 'download'
 | 
			
		||||
    },
 | 
			
		||||
    run() {
 | 
			
		||||
      this.dialogVisible = true
 | 
			
		||||
      this.showFileName = false
 | 
			
		||||
      this.operationType = 'run'
 | 
			
		||||
    },
 | 
			
		||||
    copy() {
 | 
			
		||||
      this.dialogVisible = true
 | 
			
		||||
      this.showFileName = false
 | 
			
		||||
      this.operationType = 'copy'
 | 
			
		||||
    },
 | 
			
		||||
    tagChange(newTag) {
 | 
			
		||||
      newTag = this.cloneComponent(newTag)
 | 
			
		||||
      newTag.vModel = this.activeData.vModel
 | 
			
		||||
      newTag.formId = this.activeId
 | 
			
		||||
      newTag.span = this.activeData.span
 | 
			
		||||
      delete this.activeData.tag
 | 
			
		||||
      delete this.activeData.tagIcon
 | 
			
		||||
      delete this.activeData.document
 | 
			
		||||
      const config = newTag.__config__
 | 
			
		||||
      newTag.__vModel__ = this.activeData.__vModel__
 | 
			
		||||
      config.formId = this.activeId
 | 
			
		||||
      config.span = this.activeData.__config__.span
 | 
			
		||||
      this.activeData.__config__.tag = config.tag
 | 
			
		||||
      this.activeData.__config__.tagIcon = config.tagIcon
 | 
			
		||||
      this.activeData.__config__.document = config.document
 | 
			
		||||
      if (typeof this.activeData.__config__.defaultValue === typeof config.defaultValue) {
 | 
			
		||||
        config.defaultValue = this.activeData.__config__.defaultValue
 | 
			
		||||
      }
 | 
			
		||||
      Object.keys(newTag).forEach(key => {
 | 
			
		||||
        if (this.activeData[key] !== undefined
 | 
			
		||||
          && typeof this.activeData[key] === typeof newTag[key]) {
 | 
			
		||||
        if (this.activeData[key] !== undefined) {
 | 
			
		||||
          newTag[key] = this.activeData[key]
 | 
			
		||||
        }
 | 
			
		||||
      })
 | 
			
		||||
@@ -325,414 +554,24 @@ export default {
 | 
			
		||||
      this.updateDrawingList(newTag, this.drawingList)
 | 
			
		||||
    },
 | 
			
		||||
    updateDrawingList(newTag, list) {
 | 
			
		||||
      const index = list.findIndex(item => item.formId === this.activeId)
 | 
			
		||||
      const index = list.findIndex(item => item.__config__.formId === this.activeId)
 | 
			
		||||
      if (index > -1) {
 | 
			
		||||
        list.splice(index, 1, newTag)
 | 
			
		||||
      } else {
 | 
			
		||||
        list.forEach(item => {
 | 
			
		||||
          if (Array.isArray(item.children)) this.updateDrawingList(newTag, item.children)
 | 
			
		||||
          if (Array.isArray(item.__config__.children)) this.updateDrawingList(newTag, item.__config__.children)
 | 
			
		||||
        })
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    refreshJson(data) {
 | 
			
		||||
      this.drawingList = deepClone(data.fields)
 | 
			
		||||
      delete data.fields
 | 
			
		||||
      this.formConf = data
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang='scss'>
 | 
			
		||||
body, html{
 | 
			
		||||
  margin: 0;
 | 
			
		||||
  padding: 0;
 | 
			
		||||
  background: #fff;
 | 
			
		||||
  -moz-osx-font-smoothing: grayscale;
 | 
			
		||||
  -webkit-font-smoothing: antialiased;
 | 
			
		||||
  text-rendering: optimizeLegibility;
 | 
			
		||||
  font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
input, textarea{
 | 
			
		||||
  font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.editor-tabs{
 | 
			
		||||
  background: #121315;
 | 
			
		||||
  .el-tabs__header{
 | 
			
		||||
    margin: 0;
 | 
			
		||||
    border-bottom-color: #121315;
 | 
			
		||||
    .el-tabs__nav{
 | 
			
		||||
      border-color: #121315;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  .el-tabs__item{
 | 
			
		||||
    height: 32px;
 | 
			
		||||
    line-height: 32px;
 | 
			
		||||
    color: #888a8e;
 | 
			
		||||
    border-left: 1px solid #121315 !important;
 | 
			
		||||
    background: #363636;
 | 
			
		||||
    margin-right: 5px;
 | 
			
		||||
    user-select: none;
 | 
			
		||||
  }
 | 
			
		||||
  .el-tabs__item.is-active{
 | 
			
		||||
    background: #1e1e1e;
 | 
			
		||||
    border-bottom-color: #1e1e1e!important;
 | 
			
		||||
    color: #fff;
 | 
			
		||||
  }
 | 
			
		||||
  .el-icon-edit{
 | 
			
		||||
    color: #f1fa8c;
 | 
			
		||||
  }
 | 
			
		||||
  .el-icon-document{
 | 
			
		||||
    color: #a95812;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// home
 | 
			
		||||
.right-scrollbar {
 | 
			
		||||
  .el-scrollbar__view {
 | 
			
		||||
    padding: 12px 18px 15px 15px;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
.left-scrollbar .el-scrollbar__wrap {
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
  overflow-x: hidden !important;
 | 
			
		||||
  margin-bottom: 0 !important;
 | 
			
		||||
}
 | 
			
		||||
.center-tabs{
 | 
			
		||||
  .el-tabs__header{
 | 
			
		||||
    margin-bottom: 0!important;
 | 
			
		||||
  }
 | 
			
		||||
  .el-tabs__item{
 | 
			
		||||
    width: 50%;
 | 
			
		||||
    text-align: center;
 | 
			
		||||
  }
 | 
			
		||||
  .el-tabs__nav{
 | 
			
		||||
    width: 100%;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
.reg-item{
 | 
			
		||||
  padding: 12px 6px;
 | 
			
		||||
  background: #f8f8f8;
 | 
			
		||||
  position: relative;
 | 
			
		||||
  border-radius: 4px;
 | 
			
		||||
  .close-btn{
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    right: -6px;
 | 
			
		||||
    top: -6px;
 | 
			
		||||
    display: block;
 | 
			
		||||
    width: 16px;
 | 
			
		||||
    height: 16px;
 | 
			
		||||
    line-height: 16px;
 | 
			
		||||
    background: rgba(0, 0, 0, 0.2);
 | 
			
		||||
    border-radius: 50%;
 | 
			
		||||
    color: #fff;
 | 
			
		||||
    text-align: center;
 | 
			
		||||
    z-index: 1;
 | 
			
		||||
    cursor: pointer;
 | 
			
		||||
    font-size: 12px;
 | 
			
		||||
    &:hover{
 | 
			
		||||
      background: rgba(210, 23, 23, 0.5)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  & + .reg-item{
 | 
			
		||||
    margin-top: 18px;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
.action-bar{
 | 
			
		||||
  & .el-button+.el-button {
 | 
			
		||||
    margin-left: 15px;
 | 
			
		||||
  }
 | 
			
		||||
  & i {
 | 
			
		||||
    font-size: 20px;
 | 
			
		||||
    vertical-align: middle;
 | 
			
		||||
    position: relative;
 | 
			
		||||
    top: -1px;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.custom-tree-node{
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  font-size: 14px;
 | 
			
		||||
  .node-operation{
 | 
			
		||||
    float: right;
 | 
			
		||||
  }
 | 
			
		||||
  i[class*="el-icon"] + i[class*="el-icon"]{
 | 
			
		||||
    margin-left: 6px;
 | 
			
		||||
  }
 | 
			
		||||
  .el-icon-plus{
 | 
			
		||||
    color: #409EFF;
 | 
			
		||||
  }
 | 
			
		||||
  .el-icon-delete{
 | 
			
		||||
    color: #157a0c;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.left-scrollbar .el-scrollbar__view{
 | 
			
		||||
  overflow-x: hidden;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.el-rate{
 | 
			
		||||
  display: inline-block;
 | 
			
		||||
  vertical-align: text-top;
 | 
			
		||||
}
 | 
			
		||||
.el-upload__tip{
 | 
			
		||||
  line-height: 1.2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
$selectedColor: #f6f7ff;
 | 
			
		||||
$lighterBlue: #409EFF;
 | 
			
		||||
 | 
			
		||||
.container {
 | 
			
		||||
  position: relative;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.components-list {
 | 
			
		||||
  padding: 8px;
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  .components-item {
 | 
			
		||||
    display: inline-block;
 | 
			
		||||
    width: 48%;
 | 
			
		||||
    margin: 1%;
 | 
			
		||||
    transition: transform 0ms !important;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
.components-draggable{
 | 
			
		||||
  padding-bottom: 20px;
 | 
			
		||||
}
 | 
			
		||||
.components-title{
 | 
			
		||||
  font-size: 14px;
 | 
			
		||||
  color: #222;
 | 
			
		||||
  margin: 6px 2px;
 | 
			
		||||
  .svg-icon{
 | 
			
		||||
    color: #666;
 | 
			
		||||
    font-size: 18px;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.components-body {
 | 
			
		||||
  padding: 8px 10px;
 | 
			
		||||
  background: $selectedColor;
 | 
			
		||||
  font-size: 12px;
 | 
			
		||||
  cursor: move;
 | 
			
		||||
  border: 1px dashed $selectedColor;
 | 
			
		||||
  border-radius: 3px;
 | 
			
		||||
  .svg-icon{
 | 
			
		||||
    color: #777;
 | 
			
		||||
    font-size: 15px;
 | 
			
		||||
  }
 | 
			
		||||
  &:hover {
 | 
			
		||||
    border: 1px dashed #787be8;
 | 
			
		||||
    color: #787be8;
 | 
			
		||||
    .svg-icon {
 | 
			
		||||
      color: #787be8;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.left-board {
 | 
			
		||||
  width: 260px;
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  left: 0;
 | 
			
		||||
  top: 0;
 | 
			
		||||
  height: 100vh;
 | 
			
		||||
}
 | 
			
		||||
.left-scrollbar{
 | 
			
		||||
  height: calc(100vh - 42px);
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
}
 | 
			
		||||
.center-scrollbar {
 | 
			
		||||
  height: calc(100vh - 42px);
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  border-left: 1px solid #f1e8e8;
 | 
			
		||||
  border-right: 1px solid #f1e8e8;
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
}
 | 
			
		||||
.center-board {
 | 
			
		||||
  height: 100vh;
 | 
			
		||||
  width: auto;
 | 
			
		||||
  margin: 0 350px 0 260px;
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
}
 | 
			
		||||
.empty-info{
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  top: 46%;
 | 
			
		||||
  left: 0;
 | 
			
		||||
  right: 0;
 | 
			
		||||
  text-align: center;
 | 
			
		||||
  font-size: 18px;
 | 
			
		||||
  color: #ccb1ea;
 | 
			
		||||
  letter-spacing: 4px;
 | 
			
		||||
}
 | 
			
		||||
.action-bar{
 | 
			
		||||
  position: relative;
 | 
			
		||||
  height: 42px;
 | 
			
		||||
  text-align: right;
 | 
			
		||||
  padding: 0 15px;
 | 
			
		||||
  box-sizing: border-box;;
 | 
			
		||||
  border: 1px solid #f1e8e8;
 | 
			
		||||
  border-top: none;
 | 
			
		||||
  border-left: none;
 | 
			
		||||
  .delete-btn{
 | 
			
		||||
    color: #F56C6C;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
.logo-wrapper{
 | 
			
		||||
  position: relative;
 | 
			
		||||
  height: 42px;
 | 
			
		||||
  background: #fff;
 | 
			
		||||
  border-bottom: 1px solid #f1e8e8;
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
}
 | 
			
		||||
.logo{
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  left: 12px;
 | 
			
		||||
  top: 6px;
 | 
			
		||||
  line-height: 30px;
 | 
			
		||||
  color: #00afff;
 | 
			
		||||
  font-weight: 600;
 | 
			
		||||
  font-size: 17px;
 | 
			
		||||
  white-space: nowrap;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.center-board-row {
 | 
			
		||||
  padding: 12px 12px 15px 12px;
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
  & > .el-form {
 | 
			
		||||
    // 69 = 12+15+42
 | 
			
		||||
    height: calc(100vh - 69px);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
.drawing-board {
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  position: relative;
 | 
			
		||||
  .components-body {
 | 
			
		||||
    padding: 0;
 | 
			
		||||
    margin: 0;
 | 
			
		||||
    font-size: 0;
 | 
			
		||||
  }
 | 
			
		||||
  .sortable-ghost {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    display: block;
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
    &::before {
 | 
			
		||||
      content: " ";
 | 
			
		||||
      position: absolute;
 | 
			
		||||
      left: 0;
 | 
			
		||||
      right: 0;
 | 
			
		||||
      top: 0;
 | 
			
		||||
      height: 3px;
 | 
			
		||||
      background: rgb(89, 89, 223);
 | 
			
		||||
      z-index: 2;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  .components-item.sortable-ghost {
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    height: 60px;
 | 
			
		||||
    background-color: $selectedColor;
 | 
			
		||||
  }
 | 
			
		||||
  .active-from-item {
 | 
			
		||||
    & > .el-form-item{
 | 
			
		||||
      background: $selectedColor;
 | 
			
		||||
      border-radius: 6px;
 | 
			
		||||
    }
 | 
			
		||||
    & > .drawing-item-copy, & > .drawing-item-delete{
 | 
			
		||||
      display: initial;
 | 
			
		||||
    }
 | 
			
		||||
    & > .component-name{
 | 
			
		||||
      color: $lighterBlue;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  .el-form-item{
 | 
			
		||||
    margin-bottom: 15px;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
.drawing-item{
 | 
			
		||||
  position: relative;
 | 
			
		||||
  cursor: move;
 | 
			
		||||
  &.unfocus-bordered:not(.activeFromItem) > div:first-child  {
 | 
			
		||||
    border: 1px dashed #ccc;
 | 
			
		||||
  }
 | 
			
		||||
  .el-form-item{
 | 
			
		||||
    padding: 12px 10px;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
.drawing-row-item{
 | 
			
		||||
  position: relative;
 | 
			
		||||
  cursor: move;
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
  border: 1px dashed #ccc;
 | 
			
		||||
  border-radius: 3px;
 | 
			
		||||
  padding: 0 2px;
 | 
			
		||||
  margin-bottom: 15px;
 | 
			
		||||
  .drawing-row-item {
 | 
			
		||||
    margin-bottom: 2px;
 | 
			
		||||
  }
 | 
			
		||||
  .el-col{
 | 
			
		||||
    margin-top: 22px;
 | 
			
		||||
  }
 | 
			
		||||
  .el-form-item{
 | 
			
		||||
    margin-bottom: 0;
 | 
			
		||||
  }
 | 
			
		||||
  .drag-wrapper{
 | 
			
		||||
    min-height: 80px;
 | 
			
		||||
  }
 | 
			
		||||
  &.active-from-item{
 | 
			
		||||
    border: 1px dashed $lighterBlue;
 | 
			
		||||
  }
 | 
			
		||||
  .component-name{
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    top: 0;
 | 
			
		||||
    left: 0;
 | 
			
		||||
    font-size: 12px;
 | 
			
		||||
    color: #bbb;
 | 
			
		||||
    display: inline-block;
 | 
			
		||||
    padding: 0 6px;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
.drawing-item, .drawing-row-item{
 | 
			
		||||
  &:hover {
 | 
			
		||||
    & > .el-form-item{
 | 
			
		||||
      background: $selectedColor;
 | 
			
		||||
      border-radius: 6px;
 | 
			
		||||
    }
 | 
			
		||||
    & > .drawing-item-copy, & > .drawing-item-delete{
 | 
			
		||||
      display: initial;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  & > .drawing-item-copy, & > .drawing-item-delete{
 | 
			
		||||
    display: none;
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    top: -10px;
 | 
			
		||||
    width: 22px;
 | 
			
		||||
    height: 22px;
 | 
			
		||||
    line-height: 22px;
 | 
			
		||||
    text-align: center;
 | 
			
		||||
    border-radius: 50%;
 | 
			
		||||
    font-size: 12px;
 | 
			
		||||
    border: 1px solid;
 | 
			
		||||
    cursor: pointer;
 | 
			
		||||
    z-index: 1;
 | 
			
		||||
  }
 | 
			
		||||
  & > .drawing-item-copy{
 | 
			
		||||
    right: 56px;
 | 
			
		||||
    border-color: $lighterBlue;
 | 
			
		||||
    color: $lighterBlue;
 | 
			
		||||
    background: #fff;
 | 
			
		||||
    &:hover{
 | 
			
		||||
      background: $lighterBlue;
 | 
			
		||||
      color: #fff;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  & > .drawing-item-delete{
 | 
			
		||||
    right: 24px;
 | 
			
		||||
    border-color: #F56C6C;
 | 
			
		||||
    color: #F56C6C;
 | 
			
		||||
    background: #fff;
 | 
			
		||||
    &:hover{
 | 
			
		||||
      background: #F56C6C;
 | 
			
		||||
      color: #fff;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@import '@/styles/home';
 | 
			
		||||
</style>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								yudao-admin-ui/src/views/tool/build/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								yudao-admin-ui/src/views/tool/build/README.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
【add by 芋道源码】引自 https://github.com/JakHuang/form-generator/tree/dev/src/views/index 目录
 | 
			
		||||
		Reference in New Issue
	
	Block a user