Browse Source

流程表单,接入新的 form generator 版本

YunaiV 3 years ago
parent
commit
863ab6f33a

+ 8 - 0
yudao-admin-ui/src/components/RADME.md

@@ -0,0 +1,8 @@
+## form-generator
+
+github 地址:https://github.com/JakHuang/form-generator
+
+* generator
+* parser
+* render
+* tinymce

+ 344 - 505
yudao-admin-ui/src/views/bpm/form/formEditor.vue

@@ -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 - 0
yudao-admin-ui/src/views/tool/build/README.md

@@ -0,0 +1 @@
+【add by 芋道源码】引自 https://github.com/JakHuang/form-generator/tree/dev/src/views/index 目录