You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							783 lines
						
					
					
						
							19 KiB
						
					
					
				
			
		
		
	
	
							783 lines
						
					
					
						
							19 KiB
						
					
					
				| <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>
 | |
| 
 |