Commit 863ab6f33ae34ab8af47fcdb64e74e75f66d5a95

Authored by YunaiV
1 parent d574a99d

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

yudao-admin-ui/src/components/RADME.md 0 → 100644
  1 +## form-generator
  2 +
  3 +github 地址:https://github.com/JakHuang/form-generator
  4 +
  5 +* generator
  6 +* parser
  7 +* render
  8 +* tinymce
0 9 \ No newline at end of file
... ...
yudao-admin-ui/src/views/bpm/form/formEditor.vue
... ... @@ -7,42 +7,33 @@
7 7 <el-scrollbar class="left-scrollbar">
8 8 <!-- 左边:表单项 -->
9 9 <div class="components-list">
10   - <div class="components-title">
11   - <svg-icon icon-class="component" />输入型组件
12   - </div>
13   - <draggable class="components-draggable" :list="inputComponents" :group="{ name: 'componentsGroup', pull: 'clone', put: false }"
14   - :clone="cloneComponent" draggable=".components-item" :sort="false" @end="onEnd">
15   - <div v-for="(element, index) in inputComponents" :key="index" class="components-item" @click="addComponent(element)">
16   - <div class="components-body">
17   - <svg-icon :icon-class="element.tagIcon" />
18   - {{ element.label }}
19   - </div>
  10 + <div v-for="(item, listIndex) in leftComponents" :key="listIndex">
  11 + <div class="components-title">
  12 + <svg-icon icon-class="component" />
  13 + {{ item.title }}
20 14 </div>
21   - </draggable>
22   - <div class="components-title">
23   - <svg-icon icon-class="component" />选择型组件
24   - </div>
25   - <draggable class="components-draggable" :list="selectComponents" :group="{ name: 'componentsGroup', pull: 'clone', put: false }"
26   - :clone="cloneComponent" draggable=".components-item" :sort="false" @end="onEnd">
27   - <div v-for="(element, index) in selectComponents" :key="index" class="components-item" @click="addComponent(element)">
28   - <div class="components-body">
29   - <svg-icon :icon-class="element.tagIcon" />
30   - {{ element.label }}
  15 + <draggable
  16 + class="components-draggable"
  17 + :list="item.list"
  18 + :group="{ name: 'componentsGroup', pull: 'clone', put: false }"
  19 + :clone="cloneComponent"
  20 + draggable=".components-item"
  21 + :sort="false"
  22 + @end="onEnd"
  23 + >
  24 + <div
  25 + v-for="(element, index) in item.list"
  26 + :key="index"
  27 + class="components-item"
  28 + @click="addComponent(element)"
  29 + >
  30 + <div class="components-body">
  31 + <svg-icon :icon-class="element.__config__.tagIcon" />
  32 + {{ element.__config__.label }}
  33 + </div>
31 34 </div>
32   - </div>
33   - </draggable>
34   - <div class="components-title">
35   - <svg-icon icon-class="component" />布局型组件
  35 + </draggable>
36 36 </div>
37   - <draggable class="components-draggable" :list="layoutComponents" :group="{ name: 'componentsGroup', pull: 'clone', put: false }"
38   - :clone="cloneComponent" draggable=".components-item" :sort="false" @end="onEnd">
39   - <div v-for="(element, index) in layoutComponents" :key="index" class="components-item" @click="addComponent(element)">
40   - <div class="components-body">
41   - <svg-icon :icon-class="element.tagIcon" />
42   - {{ element.label }}
43   - </div>
44   - </div>
45   - </draggable>
46 37  
47 38 <!-- 左边:动态表单 -->
48 39 <el-form ref="form" :model="form" :rules="rules" label-width="80px">
... ... @@ -64,20 +55,47 @@
64 55 </div>
65 56  
66 57 <div class="center-board">
67   - <!-- 上面:操作按钮 -->
68 58 <div class="action-bar">
69 59 <el-button icon="el-icon-check" type="text" @click="save">保存</el-button>
70   - <el-button class="delete-btn" icon="el-icon-delete" type="text" @click="empty">清空</el-button>
  60 + <!-- <el-button icon="el-icon-video-play" type="text" @click="run">-->
  61 +<!-- 运行-->
  62 +<!-- </el-button>-->
  63 + <el-button icon="el-icon-view" type="text" @click="showJson">
  64 + 查看json
  65 + </el-button>
  66 +<!-- <el-button icon="el-icon-download" type="text" @click="download">-->
  67 +<!-- 导出vue文件-->
  68 +<!-- </el-button>-->
  69 +<!-- <el-button class="copy-btn-main" icon="el-icon-document-copy" type="text" @click="copy">-->
  70 +<!-- 复制代码-->
  71 +<!-- </el-button>-->
  72 + <el-button class="delete-btn" icon="el-icon-delete" type="text" @click="empty">
  73 + 清空
  74 + </el-button>
71 75 </div>
  76 +
72 77 <!-- 中间,表单项 -->
73 78 <el-scrollbar class="center-scrollbar">
74 79 <el-row class="center-board-row" :gutter="formConf.gutter">
75   - <el-form :size="formConf.size" :label-position="formConf.labelPosition" :disabled="formConf.disabled"
76   - :label-width="formConf.labelWidth + 'px'">
  80 + <el-form
  81 + :size="formConf.size"
  82 + :label-position="formConf.labelPosition"
  83 + :disabled="formConf.disabled"
  84 + :label-width="formConf.labelWidth + 'px'"
  85 + >
77 86 <draggable class="drawing-board" :list="drawingList" :animation="340" group="componentsGroup">
78   - <draggable-item v-for="(element, index) in drawingList" :key="element.renderKey" :drawing-list="drawingList"
79   - :element="element" :index="index" :active-id="activeId" :form-conf="formConf"
80   - @activeItem="activeFormItem" @copyItem="drawingItemCopy" @deleteItem="drawingItemDelete"/>
  87 + <draggable-item
  88 + v-for="(item, index) in drawingList"
  89 + :key="item.renderKey"
  90 + :drawing-list="drawingList"
  91 + :current-item="item"
  92 + :index="index"
  93 + :active-id="activeId"
  94 + :form-conf="formConf"
  95 + @activeItem="activeFormItem"
  96 + @copyItem="drawingItemCopy"
  97 + @deleteItem="drawingItemDelete"
  98 + />
81 99 </draggable>
82 100 <div v-show="!drawingList.length" class="empty-info">
83 101 从左侧拖入或点选组件进行表单设计
... ... @@ -88,52 +106,128 @@
88 106 </div>
89 107  
90 108 <!-- 右边:组件属性/表单属性 -->
91   - <right-panel :active-data="activeData" :form-conf="formConf" :show-field="!!drawingList.length" @tag-change="tagChange"/>
  109 + <right-panel
  110 + :active-data="activeData"
  111 + :form-conf="formConf"
  112 + :show-field="!!drawingList.length"
  113 + @tag-change="tagChange"
  114 + @fetch-data="fetchData"
  115 + />
  116 +
  117 +<!-- <form-drawer-->
  118 +<!-- :visible.sync="drawerVisible"-->
  119 +<!-- :form-data="formData"-->
  120 +<!-- size="100%"-->
  121 +<!-- :generate-conf="generateConf"-->
  122 +<!-- />-->
  123 +
  124 + <json-drawer
  125 + size="60%"
  126 + :visible.sync="jsonDrawerVisible"
  127 + :json-str="JSON.stringify(formData)"
  128 + @refresh="refreshJson"
  129 + />
92 130  
  131 +<!-- <code-type-dialog-->
  132 +<!-- :visible.sync="dialogVisible"-->
  133 +<!-- title="选择生成类型"-->
  134 +<!-- :show-file-name="showFileName"-->
  135 +<!-- @confirm="generate"-->
  136 +<!-- />-->
  137 +
  138 +<!-- <input id="copyNode" type="hidden">-->
93 139 </div>
94 140 </template>
95 141  
96 142 <script>
97 143 import draggable from 'vuedraggable'
98   -import render from '@/utils/generator/render'
99   -import { inputComponents, selectComponents, layoutComponents, formConf} from '@/utils/generator/config'
100   -import drawingDefalut from '@/utils/generator/drawingDefalut'
101   -// import logo from '@/assets/logo/logo.png'
102   -import DraggableItem from './../../tool/build/DraggableItem'
103   -import RightPanel from './../../tool/build/RightPanel'
104   -import {createForm, getForm, updateForm} from "@/api/bpm/form";
  144 +import { debounce } from 'throttle-debounce'
  145 +import { saveAs } from 'file-saver'
  146 +import ClipboardJS from 'clipboard'
  147 +import render from '@/components/render/render'
  148 +import FormDrawer from '@/views/tool/build/FormDrawer'
  149 +import JsonDrawer from '@/views/tool/build/JsonDrawer'
  150 +import RightPanel from '@/views/tool/build/RightPanel'
  151 +import {
  152 + inputComponents, selectComponents, layoutComponents, formConf
  153 +} from '@/utils/generator/config'
  154 +import {
  155 + exportDefault, beautifierConf, isNumberStr, titleCase, deepClone, isObjectObject
  156 +} from '@/utils/index'
  157 +import {
  158 + makeUpHtml, vueTemplate, vueScript, cssStyle
  159 +} from '@/components/generator/html'
  160 +import { makeUpJs } from '@/components/generator/js'
  161 +import { makeUpCss } from '@/components/generator/css'
  162 +import drawingDefalut from '@/components/generator/drawingDefalut'
  163 +import logo from '@/assets/logo/logo.png'
  164 +import CodeTypeDialog from '@/views/tool/build/CodeTypeDialog'
  165 +import DraggableItem from '@/views/tool/build/DraggableItem'
  166 +import {
  167 + getDrawingList, saveDrawingList, getIdGlobal, saveIdGlobal, getFormConf
  168 +} from '@/utils/db'
  169 +import loadBeautifier from '@/utils/loadBeautifier'
105 170 import {SysCommonStatusEnum} from "@/utils/constants";
  171 +import {createForm, getForm, updateForm} from "@/api/bpm/form";
106 172  
107   -// const emptyActiveData = { style: {}, autosize: {} }
  173 +let beautifier
  174 +const emptyActiveData = { style: {}, autosize: {} }
108 175 let oldActiveId
109 176 let tempActiveData
  177 +const drawingListInDB = getDrawingList()
  178 +const formConfInDB = getFormConf()
  179 +const idGlobal = getIdGlobal()
110 180  
111 181 export default {
112 182 components: {
113 183 draggable,
114 184 render,
  185 + FormDrawer,
  186 + JsonDrawer,
115 187 RightPanel,
  188 + CodeTypeDialog,
116 189 DraggableItem
117 190 },
118 191 data() {
119 192 return {
120   - // logo,
121   - idGlobal: 100, // 自动 ID 生成时,全局递增。例如说 field100
122   - formConf, // 表单格式
  193 + logo,
  194 + idGlobal,
  195 + formConf,
123 196 inputComponents,
124 197 selectComponents,
125 198 layoutComponents,
126 199 labelWidth: 100,
127   -
  200 + // drawingList: drawingDefalut,
128 201 drawingData: {}, // 生成后的表单数据
  202 + activeId: drawingDefalut[0].__config__.formId,
129 203  
130 204 drawingList: [], // 表单项的数组
131   - activeId: undefined,
132   - activeData: {},
133   - // drawerVisible: false,
134   - // formData: {},
135   - // dialogVisible: false,
136   - // showFileName: false,
  205 + // activeId: undefined,
  206 + // activeData: {},
  207 +
  208 + drawerVisible: false,
  209 + formData: {},
  210 + dialogVisible: false,
  211 + jsonDrawerVisible: false,
  212 + generateConf: null,
  213 + showFileName: false,
  214 + activeData: drawingDefalut[0], // 右边编辑器激活的表单项
  215 + saveDrawingListDebounce: debounce(340, saveDrawingList),
  216 + saveIdGlobalDebounce: debounce(340, saveIdGlobal),
  217 + leftComponents: [
  218 + {
  219 + title: '输入型组件',
  220 + list: inputComponents
  221 + },
  222 + {
  223 + title: '选择型组件',
  224 + list: selectComponents
  225 + },
  226 + {
  227 + title: '布局型组件',
  228 + list: layoutComponents
  229 + }
  230 + ],
137 231  
138 232 // 表单参数
139 233 form: {
... ... @@ -146,12 +240,14 @@ export default {
146 240 }
147 241 }
148 242 },
  243 + computed: {
  244 + },
149 245 watch: {
150 246 // eslint-disable-next-line func-names
151   - 'activeData.label': function (val, oldVal) {
  247 + 'activeData.__config__.label': function (val, oldVal) {
152 248 if (
153 249 this.activeData.placeholder === undefined
154   - || !this.activeData.tag
  250 + || !this.activeData.__config__.tag
155 251 || oldActiveId !== this.activeId
156 252 ) {
157 253 return
... ... @@ -163,8 +259,50 @@ export default {
163 259 oldActiveId = val
164 260 },
165 261 immediate: true
  262 + },
  263 + drawingList: {
  264 + handler(val) {
  265 + this.saveDrawingListDebounce(val)
  266 + if (val.length === 0) this.idGlobal = 100
  267 + },
  268 + deep: true
  269 + },
  270 + idGlobal: {
  271 + handler(val) {
  272 + this.saveIdGlobalDebounce(val)
  273 + },
  274 + immediate: true
166 275 }
167 276 },
  277 + mounted() {
  278 + // 【add by 芋道源码】不读缓存
  279 + // if (Array.isArray(drawingListInDB) && drawingListInDB.length > 0) {
  280 + // this.drawingList = drawingListInDB
  281 + // } else {
  282 + // this.drawingList = drawingDefalut
  283 + // }
  284 + // this.activeFormItem(this.drawingList[0])
  285 + // if (formConfInDB) {
  286 + // this.formConf = formConfInDB
  287 + // }
  288 + loadBeautifier(btf => {
  289 + beautifier = btf
  290 + })
  291 + const clipboard = new ClipboardJS('#copyNode', {
  292 + text: trigger => {
  293 + const codeStr = this.generateCode()
  294 + this.$notify({
  295 + title: '成功',
  296 + message: '代码已复制到剪切板,可粘贴。',
  297 + type: 'success'
  298 + })
  299 + return codeStr
  300 + }
  301 + })
  302 + clipboard.on('error', e => {
  303 + this.$message.error('代码复制失败')
  304 + })
  305 + },
168 306 created() {
169 307 // 读取表单配置
170 308 const formId = this.$route.query && this.$route.query.formId
... ... @@ -179,49 +317,105 @@ export default {
179 317 }
180 318 this.formConf = JSON.parse(data.conf)
181 319 this.drawingList = this.decodeFields(data.fields)
  320 + // 设置激活的表单项
  321 + this.activeData = this.drawingList[0]
  322 + this.activeId = this.activeData.__config__.formId
182 323 // 设置 idGlobal,避免重复
183 324 this.idGlobal += this.drawingList.length
184 325 });
185 326 }
186 327 },
187 328 methods: {
188   - activeFormItem(element) {
189   - this.activeData = element
190   - this.activeId = element.formId
  329 + setObjectValueReduce(obj, strKeys, data) {
  330 + const arr = strKeys.split('.')
  331 + arr.reduce((pre, item, i) => {
  332 + if (arr.length === i + 1) {
  333 + pre[item] = data
  334 + } else if (!isObjectObject(pre[item])) {
  335 + pre[item] = {}
  336 + }
  337 + return pre[item]
  338 + }, obj)
191 339 },
192   - onEnd(obj, a) {
  340 + setRespData(component, resp) {
  341 + const { dataPath, renderKey, dataConsumer } = component.__config__
  342 + if (!dataPath || !dataConsumer) return
  343 + const respData = dataPath.split('.').reduce((pre, item) => pre[item], resp)
  344 +
  345 + // 将请求回来的数据,赋值到指定属性。
  346 + // 以el-tabel为例,根据Element文档,应该将数据赋值给el-tabel的data属性,所以dataConsumer的值应为'data';
  347 + // 此时赋值代码可写成 component[dataConsumer] = respData;
  348 + // 但为支持更深层级的赋值(如:dataConsumer的值为'options.data'),使用setObjectValueReduce
  349 + this.setObjectValueReduce(component, dataConsumer, respData)
  350 + const i = this.drawingList.findIndex(item => item.__config__.renderKey === renderKey)
  351 + if (i > -1) this.$set(this.drawingList, i, component)
  352 + },
  353 + fetchData(component) {
  354 + const { dataType, method, url } = component.__config__
  355 + if (dataType === 'dynamic' && method && url) {
  356 + this.setLoading(component, true)
  357 + this.$axios({
  358 + method,
  359 + url
  360 + }).then(resp => {
  361 + this.setLoading(component, false)
  362 + this.setRespData(component, resp.data)
  363 + })
  364 + }
  365 + },
  366 + setLoading(component, val) {
  367 + const { directives } = component
  368 + if (Array.isArray(directives)) {
  369 + const t = directives.find(d => d.name === 'loading')
  370 + if (t) t.value = val
  371 + }
  372 + },
  373 + activeFormItem(currentItem) {
  374 + this.activeData = currentItem
  375 + this.activeId = currentItem.__config__.formId
  376 + },
  377 + onEnd(obj) {
193 378 if (obj.from !== obj.to) {
  379 + this.fetchData(tempActiveData)
194 380 this.activeData = tempActiveData
195 381 this.activeId = this.idGlobal
196 382 }
197 383 },
198 384 addComponent(item) {
199 385 const clone = this.cloneComponent(item)
  386 + this.fetchData(clone)
200 387 this.drawingList.push(clone)
201 388 this.activeFormItem(clone)
202 389 },
203 390 cloneComponent(origin) {
204   - const clone = JSON.parse(JSON.stringify(origin))
205   - clone.formId = ++this.idGlobal
206   - clone.span = formConf.span
207   - clone.renderKey = +new Date() // 改变renderKey后可以实现强制更新组件
208   - if (!clone.layout) clone.layout = 'colFormItem'
209   - if (clone.layout === 'colFormItem') {
210   - clone.vModel = `field${this.idGlobal}`
211   - clone.placeholder !== undefined && (clone.placeholder += clone.label)
212   - tempActiveData = clone
213   - } else if (clone.layout === 'rowFormItem') {
214   - delete clone.label
215   - clone.componentName = `row${this.idGlobal}`
216   - clone.gutter = this.formConf.gutter
217   - tempActiveData = clone
218   - }
  391 + const clone = deepClone(origin)
  392 + const config = clone.__config__
  393 + config.span = this.formConf.span // 生成代码时,会根据span做精简判断
  394 + this.createIdAndKey(clone)
  395 + clone.placeholder !== undefined && (clone.placeholder += config.label)
  396 + tempActiveData = clone
219 397 return tempActiveData
220 398 },
  399 + createIdAndKey(item) {
  400 + const config = item.__config__
  401 + config.formId = ++this.idGlobal
  402 + config.renderKey = `${config.formId}${+new Date()}` // 改变renderKey后可以实现强制更新组件
  403 + if (config.layout === 'colFormItem') {
  404 + item.__vModel__ = `field${this.idGlobal}`
  405 + } else if (config.layout === 'rowFormItem') {
  406 + config.componentName = `row${this.idGlobal}`
  407 + !Array.isArray(config.children) && (config.children = [])
  408 + delete config.label // rowFormItem无需配置label属性
  409 + }
  410 + if (Array.isArray(config.children)) {
  411 + config.children = config.children.map(childItem => this.createIdAndKey(childItem))
  412 + }
  413 + return item
  414 + },
221 415 // 获得表单数据
222 416 AssembleFormData() {
223 417 this.formData = {
224   - fields: JSON.parse(JSON.stringify(this.drawingList)),
  418 + fields: deepClone(this.drawingList),
225 419 ...this.formConf
226 420 }
227 421 },
... ... @@ -272,34 +466,39 @@ export default {
272 466 })
273 467 return drawingList
274 468 },
  469 + generate(data) {
  470 + const func = this[`exec${titleCase(this.operationType)}`]
  471 + this.generateConf = data
  472 + func && func(data)
  473 + },
  474 + execRun(data) {
  475 + this.AssembleFormData()
  476 + this.drawerVisible = true
  477 + },
  478 + execDownload(data) {
  479 + const codeStr = this.generateCode()
  480 + const blob = new Blob([codeStr], { type: 'text/plain;charset=utf-8' })
  481 + saveAs(blob, data.fileName)
  482 + },
  483 + execCopy(data) {
  484 + document.getElementById('copyNode').click()
  485 + },
275 486 empty() {
276 487 this.$confirm('确定要清空所有组件吗?', '提示', { type: 'warning' }).then(
277 488 () => {
278 489 this.drawingList = []
  490 + this.idGlobal = 100
279 491 }
280 492 )
281 493 },
282   - drawingItemCopy(item, parent) {
283   - let clone = JSON.parse(JSON.stringify(item))
  494 + drawingItemCopy(item, list) {
  495 + let clone = deepClone(item)
284 496 clone = this.createIdAndKey(clone)
285   - parent.push(clone)
  497 + list.push(clone)
286 498 this.activeFormItem(clone)
287 499 },
288   - createIdAndKey(item) {
289   - item.formId = ++this.idGlobal
290   - item.renderKey = +new Date()
291   - if (item.layout === 'colFormItem') {
292   - item.vModel = `field${this.idGlobal}`
293   - } else if (item.layout === 'rowFormItem') {
294   - item.componentName = `row${this.idGlobal}`
295   - }
296   - if (Array.isArray(item.children)) {
297   - item.children = item.children.map(childItem => this.createIdAndKey(childItem))
298   - }
299   - return item
300   - },
301   - drawingItemDelete(index, parent) {
302   - parent.splice(index, 1)
  500 + drawingItemDelete(index, list) {
  501 + list.splice(index, 1)
303 502 this.$nextTick(() => {
304 503 const len = this.drawingList.length
305 504 if (len) {
... ... @@ -307,17 +506,47 @@ export default {
307 506 }
308 507 })
309 508 },
  509 + generateCode() {
  510 + const { type } = this.generateConf
  511 + this.AssembleFormData()
  512 + const script = vueScript(makeUpJs(this.formData, type))
  513 + const html = vueTemplate(makeUpHtml(this.formData, type))
  514 + const css = cssStyle(makeUpCss(this.formData))
  515 + return beautifier.html(html + script + css, beautifierConf.html)
  516 + },
  517 + showJson() {
  518 + this.AssembleFormData()
  519 + this.jsonDrawerVisible = true
  520 + },
  521 + download() {
  522 + this.dialogVisible = true
  523 + this.showFileName = true
  524 + this.operationType = 'download'
  525 + },
  526 + run() {
  527 + this.dialogVisible = true
  528 + this.showFileName = false
  529 + this.operationType = 'run'
  530 + },
  531 + copy() {
  532 + this.dialogVisible = true
  533 + this.showFileName = false
  534 + this.operationType = 'copy'
  535 + },
310 536 tagChange(newTag) {
311 537 newTag = this.cloneComponent(newTag)
312   - newTag.vModel = this.activeData.vModel
313   - newTag.formId = this.activeId
314   - newTag.span = this.activeData.span
315   - delete this.activeData.tag
316   - delete this.activeData.tagIcon
317   - delete this.activeData.document
  538 + const config = newTag.__config__
  539 + newTag.__vModel__ = this.activeData.__vModel__
  540 + config.formId = this.activeId
  541 + config.span = this.activeData.__config__.span
  542 + this.activeData.__config__.tag = config.tag
  543 + this.activeData.__config__.tagIcon = config.tagIcon
  544 + this.activeData.__config__.document = config.document
  545 + if (typeof this.activeData.__config__.defaultValue === typeof config.defaultValue) {
  546 + config.defaultValue = this.activeData.__config__.defaultValue
  547 + }
318 548 Object.keys(newTag).forEach(key => {
319   - if (this.activeData[key] !== undefined
320   - && typeof this.activeData[key] === typeof newTag[key]) {
  549 + if (this.activeData[key] !== undefined) {
321 550 newTag[key] = this.activeData[key]
322 551 }
323 552 })
... ... @@ -325,414 +554,24 @@ export default {
325 554 this.updateDrawingList(newTag, this.drawingList)
326 555 },
327 556 updateDrawingList(newTag, list) {
328   - const index = list.findIndex(item => item.formId === this.activeId)
  557 + const index = list.findIndex(item => item.__config__.formId === this.activeId)
329 558 if (index > -1) {
330 559 list.splice(index, 1, newTag)
331 560 } else {
332 561 list.forEach(item => {
333   - if (Array.isArray(item.children)) this.updateDrawingList(newTag, item.children)
  562 + if (Array.isArray(item.__config__.children)) this.updateDrawingList(newTag, item.__config__.children)
334 563 })
335 564 }
  565 + },
  566 + refreshJson(data) {
  567 + this.drawingList = deepClone(data.fields)
  568 + delete data.fields
  569 + this.formConf = data
336 570 }
337 571 }
338 572 }
339 573 </script>
340 574  
341 575 <style lang='scss'>
342   -body, html{
343   - margin: 0;
344   - padding: 0;
345   - background: #fff;
346   - -moz-osx-font-smoothing: grayscale;
347   - -webkit-font-smoothing: antialiased;
348   - text-rendering: optimizeLegibility;
349   - font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji;
350   -}
351   -
352   -input, textarea{
353   - font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji;
354   -}
355   -
356   -.editor-tabs{
357   - background: #121315;
358   - .el-tabs__header{
359   - margin: 0;
360   - border-bottom-color: #121315;
361   - .el-tabs__nav{
362   - border-color: #121315;
363   - }
364   - }
365   - .el-tabs__item{
366   - height: 32px;
367   - line-height: 32px;
368   - color: #888a8e;
369   - border-left: 1px solid #121315 !important;
370   - background: #363636;
371   - margin-right: 5px;
372   - user-select: none;
373   - }
374   - .el-tabs__item.is-active{
375   - background: #1e1e1e;
376   - border-bottom-color: #1e1e1e!important;
377   - color: #fff;
378   - }
379   - .el-icon-edit{
380   - color: #f1fa8c;
381   - }
382   - .el-icon-document{
383   - color: #a95812;
384   - }
385   -}
386   -
387   -// home
388   -.right-scrollbar {
389   - .el-scrollbar__view {
390   - padding: 12px 18px 15px 15px;
391   - }
392   -}
393   -.left-scrollbar .el-scrollbar__wrap {
394   - box-sizing: border-box;
395   - overflow-x: hidden !important;
396   - margin-bottom: 0 !important;
397   -}
398   -.center-tabs{
399   - .el-tabs__header{
400   - margin-bottom: 0!important;
401   - }
402   - .el-tabs__item{
403   - width: 50%;
404   - text-align: center;
405   - }
406   - .el-tabs__nav{
407   - width: 100%;
408   - }
409   -}
410   -.reg-item{
411   - padding: 12px 6px;
412   - background: #f8f8f8;
413   - position: relative;
414   - border-radius: 4px;
415   - .close-btn{
416   - position: absolute;
417   - right: -6px;
418   - top: -6px;
419   - display: block;
420   - width: 16px;
421   - height: 16px;
422   - line-height: 16px;
423   - background: rgba(0, 0, 0, 0.2);
424   - border-radius: 50%;
425   - color: #fff;
426   - text-align: center;
427   - z-index: 1;
428   - cursor: pointer;
429   - font-size: 12px;
430   - &:hover{
431   - background: rgba(210, 23, 23, 0.5)
432   - }
433   - }
434   - & + .reg-item{
435   - margin-top: 18px;
436   - }
437   -}
438   -.action-bar{
439   - & .el-button+.el-button {
440   - margin-left: 15px;
441   - }
442   - & i {
443   - font-size: 20px;
444   - vertical-align: middle;
445   - position: relative;
446   - top: -1px;
447   - }
448   -}
449   -
450   -.custom-tree-node{
451   - width: 100%;
452   - font-size: 14px;
453   - .node-operation{
454   - float: right;
455   - }
456   - i[class*="el-icon"] + i[class*="el-icon"]{
457   - margin-left: 6px;
458   - }
459   - .el-icon-plus{
460   - color: #409EFF;
461   - }
462   - .el-icon-delete{
463   - color: #157a0c;
464   - }
465   -}
466   -
467   -.left-scrollbar .el-scrollbar__view{
468   - overflow-x: hidden;
469   -}
470   -
471   -.el-rate{
472   - display: inline-block;
473   - vertical-align: text-top;
474   -}
475   -.el-upload__tip{
476   - line-height: 1.2;
477   -}
478   -
479   -$selectedColor: #f6f7ff;
480   -$lighterBlue: #409EFF;
481   -
482   -.container {
483   - position: relative;
484   - width: 100%;
485   - height: 100%;
486   -}
487   -
488   -.components-list {
489   - padding: 8px;
490   - box-sizing: border-box;
491   - height: 100%;
492   - .components-item {
493   - display: inline-block;
494   - width: 48%;
495   - margin: 1%;
496   - transition: transform 0ms !important;
497   - }
498   -}
499   -.components-draggable{
500   - padding-bottom: 20px;
501   -}
502   -.components-title{
503   - font-size: 14px;
504   - color: #222;
505   - margin: 6px 2px;
506   - .svg-icon{
507   - color: #666;
508   - font-size: 18px;
509   - }
510   -}
511   -
512   -.components-body {
513   - padding: 8px 10px;
514   - background: $selectedColor;
515   - font-size: 12px;
516   - cursor: move;
517   - border: 1px dashed $selectedColor;
518   - border-radius: 3px;
519   - .svg-icon{
520   - color: #777;
521   - font-size: 15px;
522   - }
523   - &:hover {
524   - border: 1px dashed #787be8;
525   - color: #787be8;
526   - .svg-icon {
527   - color: #787be8;
528   - }
529   - }
530   -}
531   -
532   -.left-board {
533   - width: 260px;
534   - position: absolute;
535   - left: 0;
536   - top: 0;
537   - height: 100vh;
538   -}
539   -.left-scrollbar{
540   - height: calc(100vh - 42px);
541   - overflow: hidden;
542   -}
543   -.center-scrollbar {
544   - height: calc(100vh - 42px);
545   - overflow: hidden;
546   - border-left: 1px solid #f1e8e8;
547   - border-right: 1px solid #f1e8e8;
548   - box-sizing: border-box;
549   -}
550   -.center-board {
551   - height: 100vh;
552   - width: auto;
553   - margin: 0 350px 0 260px;
554   - box-sizing: border-box;
555   -}
556   -.empty-info{
557   - position: absolute;
558   - top: 46%;
559   - left: 0;
560   - right: 0;
561   - text-align: center;
562   - font-size: 18px;
563   - color: #ccb1ea;
564   - letter-spacing: 4px;
565   -}
566   -.action-bar{
567   - position: relative;
568   - height: 42px;
569   - text-align: right;
570   - padding: 0 15px;
571   - box-sizing: border-box;;
572   - border: 1px solid #f1e8e8;
573   - border-top: none;
574   - border-left: none;
575   - .delete-btn{
576   - color: #F56C6C;
577   - }
578   -}
579   -.logo-wrapper{
580   - position: relative;
581   - height: 42px;
582   - background: #fff;
583   - border-bottom: 1px solid #f1e8e8;
584   - box-sizing: border-box;
585   -}
586   -.logo{
587   - position: absolute;
588   - left: 12px;
589   - top: 6px;
590   - line-height: 30px;
591   - color: #00afff;
592   - font-weight: 600;
593   - font-size: 17px;
594   - white-space: nowrap;
595   -}
596   -
597   -.center-board-row {
598   - padding: 12px 12px 15px 12px;
599   - box-sizing: border-box;
600   - & > .el-form {
601   - // 69 = 12+15+42
602   - height: calc(100vh - 69px);
603   - }
604   -}
605   -.drawing-board {
606   - height: 100%;
607   - position: relative;
608   - .components-body {
609   - padding: 0;
610   - margin: 0;
611   - font-size: 0;
612   - }
613   - .sortable-ghost {
614   - position: relative;
615   - display: block;
616   - overflow: hidden;
617   - &::before {
618   - content: " ";
619   - position: absolute;
620   - left: 0;
621   - right: 0;
622   - top: 0;
623   - height: 3px;
624   - background: rgb(89, 89, 223);
625   - z-index: 2;
626   - }
627   - }
628   - .components-item.sortable-ghost {
629   - width: 100%;
630   - height: 60px;
631   - background-color: $selectedColor;
632   - }
633   - .active-from-item {
634   - & > .el-form-item{
635   - background: $selectedColor;
636   - border-radius: 6px;
637   - }
638   - & > .drawing-item-copy, & > .drawing-item-delete{
639   - display: initial;
640   - }
641   - & > .component-name{
642   - color: $lighterBlue;
643   - }
644   - }
645   - .el-form-item{
646   - margin-bottom: 15px;
647   - }
648   -}
649   -.drawing-item{
650   - position: relative;
651   - cursor: move;
652   - &.unfocus-bordered:not(.activeFromItem) > div:first-child {
653   - border: 1px dashed #ccc;
654   - }
655   - .el-form-item{
656   - padding: 12px 10px;
657   - }
658   -}
659   -.drawing-row-item{
660   - position: relative;
661   - cursor: move;
662   - box-sizing: border-box;
663   - border: 1px dashed #ccc;
664   - border-radius: 3px;
665   - padding: 0 2px;
666   - margin-bottom: 15px;
667   - .drawing-row-item {
668   - margin-bottom: 2px;
669   - }
670   - .el-col{
671   - margin-top: 22px;
672   - }
673   - .el-form-item{
674   - margin-bottom: 0;
675   - }
676   - .drag-wrapper{
677   - min-height: 80px;
678   - }
679   - &.active-from-item{
680   - border: 1px dashed $lighterBlue;
681   - }
682   - .component-name{
683   - position: absolute;
684   - top: 0;
685   - left: 0;
686   - font-size: 12px;
687   - color: #bbb;
688   - display: inline-block;
689   - padding: 0 6px;
690   - }
691   -}
692   -.drawing-item, .drawing-row-item{
693   - &:hover {
694   - & > .el-form-item{
695   - background: $selectedColor;
696   - border-radius: 6px;
697   - }
698   - & > .drawing-item-copy, & > .drawing-item-delete{
699   - display: initial;
700   - }
701   - }
702   - & > .drawing-item-copy, & > .drawing-item-delete{
703   - display: none;
704   - position: absolute;
705   - top: -10px;
706   - width: 22px;
707   - height: 22px;
708   - line-height: 22px;
709   - text-align: center;
710   - border-radius: 50%;
711   - font-size: 12px;
712   - border: 1px solid;
713   - cursor: pointer;
714   - z-index: 1;
715   - }
716   - & > .drawing-item-copy{
717   - right: 56px;
718   - border-color: $lighterBlue;
719   - color: $lighterBlue;
720   - background: #fff;
721   - &:hover{
722   - background: $lighterBlue;
723   - color: #fff;
724   - }
725   - }
726   - & > .drawing-item-delete{
727   - right: 24px;
728   - border-color: #F56C6C;
729   - color: #F56C6C;
730   - background: #fff;
731   - &:hover{
732   - background: #F56C6C;
733   - color: #fff;
734   - }
735   - }
736   -}
737   -
  576 +@import '@/styles/home';
738 577 </style>
... ...
yudao-admin-ui/src/views/tool/build/README.md 0 → 100644
  1 +【add by 芋道源码】引自 https://github.com/JakHuang/form-generator/tree/dev/src/views/index 目录
0 2 \ No newline at end of file
... ...