From a29201a248374689bf683bbe0ce489d579483e85 Mon Sep 17 00:00:00 2001
From: 稚屿 <1491182878@qq.com>
Date: 星期三, 09 二月 2022 08:46:54 +0800
Subject: [PATCH] 修正单词拼写错误

---
 ruoyi-ui/src/views/tool/build/index.vue | 1566 +++++++++++++++++++++++++++++-----------------------------
 1 files changed, 783 insertions(+), 783 deletions(-)

diff --git a/ruoyi-ui/src/views/tool/build/index.vue b/ruoyi-ui/src/views/tool/build/index.vue
index e511408..d679422 100644
--- a/ruoyi-ui/src/views/tool/build/index.vue
+++ b/ruoyi-ui/src/views/tool/build/index.vue
@@ -1,783 +1,783 @@
-<template>
-  <div class="container">
-    <div class="left-board">
-      <div class="logo-wrapper">
-        <div class="logo">
-          <img :src="logo" alt="logo"> Form Generator
-        </div>
-      </div>
-      <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>
-          </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 }}
-              </div>
-            </div>
-          </draggable>
-          <div class="components-title">
-            <svg-icon icon-class="component" /> 布局型组件
-          </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>
-        </div>
-      </el-scrollbar>
-    </div>
-
-    <div class="center-board">
-      <div class="action-bar">
-        <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'"
-          >
-            <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>
-            <div v-show="!drawingList.length" class="empty-info">
-              从左侧拖入或点选组件进行表单设计
-            </div>
-          </el-form>
-        </el-row>
-      </el-scrollbar>
-    </div>
-
-    <right-panel
-      :active-data="activeData"
-      :form-conf="formConf"
-      :show-field="!!drawingList.length"
-      @tag-change="tagChange"
-    />
-
-    <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 beautifier from 'js-beautify'
-import ClipboardJS from 'clipboard'
-import render from '@/utils/generator/render'
-import RightPanel from './RightPanel'
-import { inputComponents, selectComponents, layoutComponents, formConf } from '@/utils/generator/config'
-import { beautifierConf, titleCase } from '@/utils/index'
-import { makeUpHtml, vueTemplate, vueScript, cssStyle } from '@/utils/generator/html'
-import { makeUpJs } from '@/utils/generator/js'
-import { makeUpCss } from '@/utils/generator/css'
-import drawingDefalut from '@/utils/generator/drawingDefalut'
-import logo from '@/assets/logo/logo.png'
-import CodeTypeDialog from './CodeTypeDialog'
-import DraggableItem from './DraggableItem'
-
-let oldActiveId
-let tempActiveData
-
-export default {
-  components: {
-    draggable,
-    render,
-    RightPanel,
-    CodeTypeDialog,
-    DraggableItem
-  },
-  data() {
-    return {
-      logo,
-      idGlobal: 100,
-      formConf,
-      inputComponents,
-      selectComponents,
-      layoutComponents,
-      labelWidth: 100,
-      drawingList: drawingDefalut,
-      drawingData: {},
-      activeId: drawingDefalut[0].formId,
-      drawerVisible: false,
-      formData: {},
-      dialogVisible: false,
-      generateConf: null,
-      showFileName: false,
-      activeData: drawingDefalut[0]
-    }
-  },
-  created() {
-    // 防止 firefox 下 拖拽 会新打卡一个选项卡
-    document.body.ondrop = event => {
-      event.preventDefault()
-      event.stopPropagation()
-    }
-  },
-  watch: {
-    // eslint-disable-next-line func-names
-    'activeData.label': function (val, oldVal) {
-      if (
-        this.activeData.placeholder === undefined
-        || !this.activeData.tag
-        || oldActiveId !== this.activeId
-      ) {
-        return
-      }
-      this.activeData.placeholder = this.activeData.placeholder.replace(oldVal, '') + val
-    },
-    activeId: {
-      handler(val) {
-        oldActiveId = val
-      },
-      immediate: true
-    }
-  },
-  mounted() {
-    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('代码复制失败')
-    })
-  },
-  methods: {
-    activeFormItem(element) {
-      this.activeData = element
-      this.activeId = element.formId
-    },
-    onEnd(obj, a) {
-      if (obj.from !== obj.to) {
-        this.activeData = tempActiveData
-        this.activeId = this.idGlobal
-      }
-    },
-    addComponent(item) {
-      const clone = this.cloneComponent(item)
-      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
-      }
-      return tempActiveData
-    },
-    AssembleFormData() {
-      this.formData = {
-        fields: JSON.parse(JSON.stringify(this.drawingList)),
-        ...this.formConf
-      }
-    },
-    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' })
-      this.$download.saveAs(blob, data.fileName)
-    },
-    execCopy(data) {
-      document.getElementById('copyNode').click()
-    },
-    empty() {
-      this.$confirm('确定要清空所有组件吗?', '提示', { type: 'warning' }).then(
-        () => {
-          this.drawingList = []
-        }
-      )
-    },
-    drawingItemCopy(item, parent) {
-      let clone = JSON.parse(JSON.stringify(item))
-      clone = this.createIdAndKey(clone)
-      parent.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)
-      this.$nextTick(() => {
-        const len = this.drawingList.length
-        if (len) {
-          this.activeFormItem(this.drawingList[len - 1])
-        }
-      })
-    },
-    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)
-    },
-    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
-      Object.keys(newTag).forEach(key => {
-        if (this.activeData[key] !== undefined
-          && typeof this.activeData[key] === typeof newTag[key]) {
-          newTag[key] = this.activeData[key]
-        }
-      })
-      this.activeData = newTag
-      this.updateDrawingList(newTag, this.drawingList)
-    },
-    updateDrawingList(newTag, list) {
-      const index = list.findIndex(item => item.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)
-        })
-      }
-    }
-  }
-}
-</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;
-  > img{
-    width: 30px;
-    height: 30px;
-    vertical-align: top;
-  }
-  .github{
-    display: inline-block;
-    vertical-align: sub;
-    margin-left: 15px;
-    > img{
-      height: 22px;
-    }
-  }
-}
-
-.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;
-    }
-  }
-}
-
-</style>
+<template>
+  <div class="container">
+    <div class="left-board">
+      <div class="logo-wrapper">
+        <div class="logo">
+          <img :src="logo" alt="logo"> Form Generator
+        </div>
+      </div>
+      <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>
+          </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 }}
+              </div>
+            </div>
+          </draggable>
+          <div class="components-title">
+            <svg-icon icon-class="component" /> 布局型组件
+          </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>
+        </div>
+      </el-scrollbar>
+    </div>
+
+    <div class="center-board">
+      <div class="action-bar">
+        <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'"
+          >
+            <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>
+            <div v-show="!drawingList.length" class="empty-info">
+              从左侧拖入或点选组件进行表单设计
+            </div>
+          </el-form>
+        </el-row>
+      </el-scrollbar>
+    </div>
+
+    <right-panel
+      :active-data="activeData"
+      :form-conf="formConf"
+      :show-field="!!drawingList.length"
+      @tag-change="tagChange"
+    />
+
+    <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 beautifier from 'js-beautify'
+import ClipboardJS from 'clipboard'
+import render from '@/utils/generator/render'
+import RightPanel from './RightPanel'
+import { inputComponents, selectComponents, layoutComponents, formConf } from '@/utils/generator/config'
+import { beautifierConf, titleCase } from '@/utils/index'
+import { makeUpHtml, vueTemplate, vueScript, cssStyle } from '@/utils/generator/html'
+import { makeUpJs } from '@/utils/generator/js'
+import { makeUpCss } from '@/utils/generator/css'
+import drawingDefault from '@/utils/generator/drawingDefault'
+import logo from '@/assets/logo/logo.png'
+import CodeTypeDialog from './CodeTypeDialog'
+import DraggableItem from './DraggableItem'
+
+let oldActiveId
+let tempActiveData
+
+export default {
+  components: {
+    draggable,
+    render,
+    RightPanel,
+    CodeTypeDialog,
+    DraggableItem
+  },
+  data() {
+    return {
+      logo,
+      idGlobal: 100,
+      formConf,
+      inputComponents,
+      selectComponents,
+      layoutComponents,
+      labelWidth: 100,
+      drawingList: drawingDefault,
+      drawingData: {},
+      activeId: drawingDefault[0].formId,
+      drawerVisible: false,
+      formData: {},
+      dialogVisible: false,
+      generateConf: null,
+      showFileName: false,
+      activeData: drawingDefault[0]
+    }
+  },
+  created() {
+    // 防止 firefox 下 拖拽 会新打卡一个选项卡
+    document.body.ondrop = event => {
+      event.preventDefault()
+      event.stopPropagation()
+    }
+  },
+  watch: {
+    // eslint-disable-next-line func-names
+    'activeData.label': function (val, oldVal) {
+      if (
+        this.activeData.placeholder === undefined
+        || !this.activeData.tag
+        || oldActiveId !== this.activeId
+      ) {
+        return
+      }
+      this.activeData.placeholder = this.activeData.placeholder.replace(oldVal, '') + val
+    },
+    activeId: {
+      handler(val) {
+        oldActiveId = val
+      },
+      immediate: true
+    }
+  },
+  mounted() {
+    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('代码复制失败')
+    })
+  },
+  methods: {
+    activeFormItem(element) {
+      this.activeData = element
+      this.activeId = element.formId
+    },
+    onEnd(obj, a) {
+      if (obj.from !== obj.to) {
+        this.activeData = tempActiveData
+        this.activeId = this.idGlobal
+      }
+    },
+    addComponent(item) {
+      const clone = this.cloneComponent(item)
+      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
+      }
+      return tempActiveData
+    },
+    AssembleFormData() {
+      this.formData = {
+        fields: JSON.parse(JSON.stringify(this.drawingList)),
+        ...this.formConf
+      }
+    },
+    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' })
+      this.$download.saveAs(blob, data.fileName)
+    },
+    execCopy(data) {
+      document.getElementById('copyNode').click()
+    },
+    empty() {
+      this.$confirm('确定要清空所有组件吗?', '提示', { type: 'warning' }).then(
+        () => {
+          this.drawingList = []
+        }
+      )
+    },
+    drawingItemCopy(item, parent) {
+      let clone = JSON.parse(JSON.stringify(item))
+      clone = this.createIdAndKey(clone)
+      parent.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)
+      this.$nextTick(() => {
+        const len = this.drawingList.length
+        if (len) {
+          this.activeFormItem(this.drawingList[len - 1])
+        }
+      })
+    },
+    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)
+    },
+    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
+      Object.keys(newTag).forEach(key => {
+        if (this.activeData[key] !== undefined
+          && typeof this.activeData[key] === typeof newTag[key]) {
+          newTag[key] = this.activeData[key]
+        }
+      })
+      this.activeData = newTag
+      this.updateDrawingList(newTag, this.drawingList)
+    },
+    updateDrawingList(newTag, list) {
+      const index = list.findIndex(item => item.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)
+        })
+      }
+    }
+  }
+}
+</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;
+  > img{
+    width: 30px;
+    height: 30px;
+    vertical-align: top;
+  }
+  .github{
+    display: inline-block;
+    vertical-align: sub;
+    margin-left: 15px;
+    > img{
+      height: 22px;
+    }
+  }
+}
+
+.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;
+    }
+  }
+}
+
+</style>

--
Gitblit v1.9.2