侧边栏树形结构整合

pull/22/head
Mercutio 2023-04-10 15:57:29 +08:00
parent 2fb47ee9af
commit 4f169ba9ab
6 changed files with 219 additions and 67 deletions

View File

@ -2,9 +2,9 @@
<div id="app"> <div id="app">
<VFormDesigner ref="vfDesignerRef" :designer-config="designerConfig" :global-dsv="globalDsv"> <VFormDesigner ref="vfDesignerRef" :designer-config="designerConfig" :global-dsv="globalDsv">
<template #customToolButtons> <template #customToolButtons>
<el-button type="normal" @click="printFormJson"></el-button> <!-- <el-button type="normal" @click="printFormJson"></el-button> -->
<el-button type="normal" @click="printFormJson"></el-button> <el-button type="normal" @click="insertFormJson"></el-button>
<el-button type="primary" @click="printFormJson"></el-button> <el-button type="primary" @click="printFormJson"></el-button>
</template> </template>
</VFormDesigner> </VFormDesigner>
</div> </div>
@ -52,6 +52,10 @@ export default {
methods: { methods: {
printFormJson() { printFormJson() {
console.log( this.$refs.vfDesignerRef.getFormJson() ) console.log( this.$refs.vfDesignerRef.getFormJson() )
},
insertFormJson() {
let jsonObj = require('./assets/testForm.json')
this.$refs.vfDesignerRef.setFormJson(jsonObj)
} }
} }
} }

1
src/assets/testForm.json Normal file

File diff suppressed because one or more lines are too long

View File

@ -13,15 +13,15 @@
<el-button :type="layoutType === 'H5' ? 'info': ''" @click="changeLayoutType('H5')"> <el-button :type="layoutType === 'H5' ? 'info': ''" @click="changeLayoutType('H5')">
{{i18nt('designer.toolbar.mobileLayout')}}</el-button> {{i18nt('designer.toolbar.mobileLayout')}}</el-button>
</el-button-group> </el-button-group>
<el-button type="" style="margin-left: 20px" :title="i18nt('designer.toolbar.nodeTreeHint')" @click="showNodeTreeDrawer"> <!-- <el-button type="" style="margin-left: 20px" :title="i18nt('designer.toolbar.nodeTreeHint')" @click="showNodeTreeDrawer">
<svg-icon icon-class="node-tree" /></el-button> <svg-icon icon-class="node-tree" /></el-button> -->
</div> </div>
<el-drawer :title="i18nt('designer.toolbar.nodeTreeTitle')" direction="ltr" :visible.sync="showNodeTreeDrawerFlag" :modal="false" :size="280" <!-- <el-drawer :title="i18nt('designer.toolbar.nodeTreeTitle')" direction="ltr" :visible.sync="showNodeTreeDrawerFlag" :modal="false" :size="280"
:destroy-on-close="true" class="node-tree-drawer"> :destroy-on-close="true" class="node-tree-drawer">
<el-tree ref="nodeTree" :data="nodeTreeData" node-key="id" default-expand-all highlight-current class="node-tree" <el-tree ref="nodeTree" :data="nodeTreeData" node-key="id" default-expand-all highlight-current class="node-tree"
icon-class="el-icon-arrow-right" @node-click="onNodeTreeClick"></el-tree> icon-class="el-icon-arrow-right" @node-click="onNodeTreeClick"></el-tree>
</el-drawer> </el-drawer> -->
<div class="right-toolbar"> <div class="right-toolbar">
<div class="right-toolbar-con"> <div class="right-toolbar-con">

View File

@ -1,10 +1,9 @@
<template> <template>
<el-scrollbar class="side-scroll-bar" :style="{height: scrollerHeight}">
<div class="panel-container"> <div class="panel-container">
<el-tabs v-model="firstTab" class="no-bottom-margin indent-left-margin" @tab-click="checkIfTreeTab">
<el-tabs v-model="firstTab" class="no-bottom-margin indent-left-margin">
<el-tab-pane name="componentLib"> <el-tab-pane name="componentLib">
<span slot="label"><i class="el-icon-set-up"></i> {{i18nt('designer.componentLib')}}</span> <span slot="label"><i class="el-icon-set-up"></i> {{i18nt('designer.componentLib')}}</span>
<el-scrollbar class="side-scroll-bar" :style="{height: scrollerHeight}">
<el-collapse v-model="activeNames" class="widget-collapse"> <el-collapse v-model="activeNames" class="widget-collapse">
<el-collapse-item name="1" :title="i18nt('designer.containerTitle')"> <el-collapse-item name="1" :title="i18nt('designer.containerTitle')">
@ -55,12 +54,20 @@
<!-- --> <!-- -->
</el-collapse> </el-collapse>
</el-scrollbar>
</el-tab-pane>
<el-tab-pane name="hierarchy" style="padding: 8px">
<span slot="label"><i class="el-icon-notebook-2"></i> {{i18nt('designer.hierarchy')}}</span>
<el-scrollbar class="side-scroll-bar" :style="{height: scrollerHeight}">
<el-tree ref="nodeTree" :data="nodeTreeData" node-key="id" default-expand-all highlight-current class="node-tree"
icon-class="el-icon-arrow-right" @node-click="onNodeTreeClick"></el-tree>
</el-scrollbar>
</el-tab-pane> </el-tab-pane>
<el-tab-pane v-if="showFormTemplates()" name="formLib" style="padding: 8px"> <el-tab-pane v-if="showFormTemplates()" name="formLib" style="padding: 8px">
<span slot="label"><i class="el-icon-c-scale-to-original"></i> {{i18nt('designer.formLib')}}</span> <span slot="label"><i class="el-icon-c-scale-to-original"></i> {{i18nt('designer.formLib')}}</span>
<el-scrollbar class="side-scroll-bar" :style="{height: scrollerHeight}">
<template v-for="(ft, idx) in formTemplates"> <template v-for="(ft, idx) in formTemplates">
<el-card :key="idx" :bord-style="{ padding: '0' }" shadow="hover" class="ft-card"> <el-card :key="idx" :bord-style="{ padding: '0' }" shadow="hover" class="ft-card">
<el-popover placement="right" trigger="hover"> <el-popover placement="right" trigger="hover">
@ -74,19 +81,17 @@
</div> </div>
</el-card> </el-card>
</template> </template>
</el-tab-pane>
</el-tabs>
</div>
</el-scrollbar> </el-scrollbar>
</el-tab-pane>
</el-tabs>
</div>
</template> </template>
<script> <script>
import Draggable from 'vuedraggable' import Draggable from 'vuedraggable'
import {containers, basicFields, advancedFields, customFields} from "./widgetsConfig" import {containers, basicFields, advancedFields, customFields} from "./widgetsConfig"
import {formTemplates} from './templatesConfig' import {formTemplates} from './templatesConfig'
import {addWindowResizeHandler} from "@/utils/util" import {traverseAllWidgets, addWindowResizeHandler} from "@/utils/util"
import i18n from "@/utils/i18n" import i18n from "@/utils/i18n"
import axios from "axios" import axios from "axios"
import SvgIcon from '@/components/svg-icon' import SvgIcon from '@/components/svg-icon'
@ -121,6 +126,8 @@
activeNames: ['1', '2', '3', '4'], activeNames: ['1', '2', '3', '4'],
nodeTreeData: [],
containers, containers,
basicFields, basicFields,
advancedFields, advancedFields,
@ -145,10 +152,10 @@
mounted() { mounted() {
this.loadWidgets() this.loadWidgets()
this.scrollerHeight = window.innerHeight - 56 + 'px' this.scrollerHeight = window.innerHeight - 56 - 40 + 'px'
addWindowResizeHandler(() => { addWindowResizeHandler(() => {
this.$nextTick(() => { this.$nextTick(() => {
this.scrollerHeight = window.innerHeight - 56 + 'px' this.scrollerHeight = window.innerHeight - 56 - 40 + 'px'
//console.log(this.scrollerHeight) //console.log(this.scrollerHeight)
}) })
}) })
@ -256,8 +263,135 @@
}).catch(error => { }).catch(error => {
console.error(error) console.error(error)
}) })
},
// Tree
buildTreeNodeOfWidget(widget, treeNode) {
let curNode = {
id: widget.id,
label: widget.options.label || widget.type,
//selectable: true,
}
treeNode.push(curNode)
if (widget.category === undefined) {
return
} }
curNode.children = []
if (widget.type === 'grid') {
widget.cols.map(col => {
let colNode = {
id: col.id,
label: col.options.name || widget.type,
children: []
}
curNode.children.push(colNode)
col.widgetList.map(wChild => {
this.buildTreeNodeOfWidget(wChild, colNode.children)
})
})
} else if (widget.type === 'table') {
//TODO:
widget.rows.map(row => {
let rowNode = {
id: row.id,
label: 'table-row',
selectable: false,
children: [],
}
curNode.children.push(rowNode)
row.cols.map(cell => {
if (!!cell.merged) { //
return
}
let rowChildren = rowNode.children
let cellNode = {
id: cell.id,
label: 'table-cell',
children: []
}
rowChildren.push(cellNode)
cell.widgetList.map(wChild => {
this.buildTreeNodeOfWidget(wChild, cellNode.children)
})
})
})
} else if (widget.type === 'tab') {
widget.tabs.map(tab => {
let tabNode = {
id: tab.id,
label: tab.options.name || widget.type,
selectable: false,
children: []
}
curNode.children.push(tabNode)
tab.widgetList.map(wChild => {
this.buildTreeNodeOfWidget(wChild, tabNode.children)
})
})
} else if (widget.type === 'sub-form') {
widget.widgetList.map(wChild => {
this.buildTreeNodeOfWidget(wChild, curNode.children)
})
} else if (widget.category === 'container') { //
widget.widgetList.map(wChild => {
this.buildTreeNodeOfWidget(wChild, curNode.children)
})
}
},
refreshNodeTree() {
this.nodeTreeData.length = 0
this.designer.widgetList.forEach(wItem => {
this.buildTreeNodeOfWidget(wItem, this.nodeTreeData)
})
},
showNodeTreeDrawer() {
this.refreshNodeTree()
// this.showNodeTreeDrawerFlag = true
this.$nextTick(() => {
if (!!this.designer.selectedId) { //
this.$refs.nodeTree.setCurrentKey(this.designer.selectedId)
}
})
},
checkIfTreeTab(tab){
console.log(tab.paneName)
if(tab.paneName == 'hierarchy') {
this.showNodeTreeDrawer()
}
},
onNodeTreeClick(nodeData, node, nodeEl) {
//console.log('test', JSON.stringify(nodeData))
if ((nodeData.selectable !== undefined) && !nodeData.selectable) {
this.$message.info(this.i18nt('designer.hint.currentNodeCannotBeSelected'))
} else {
const selectedId = nodeData.id
const foundW = this.findWidgetById(selectedId)
if (!!foundW) {
this.designer.setSelected(foundW)
}
}
},
findWidgetById(wId) {
let foundW = null
traverseAllWidgets(this.designer.widgetList, (w) => {
if (w.id === wId) {
foundW = w
}
})
return foundW
},
} }
} }
@ -286,7 +420,18 @@
.indent-left-margin { .indent-left-margin {
::v-deep .el-tabs__nav { ::v-deep .el-tabs__nav {
margin-left: 20px; // margin-left: 20px;
margin: 0;
width: 100%;
box-sizing: border-box;
display: flex;
}
::v-deep .el-tabs__item{
// padding: 0 10px;
padding: 0;
width: calc(100% / 3);
display: flex;
justify-content: center;
} }
} }

View File

@ -13,6 +13,7 @@ export default {
designer: { designer: {
componentLib: 'Components', componentLib: 'Components',
formLib: 'Templates', formLib: 'Templates',
hierarchy: 'Hierarchy',
containerTitle: 'Container', containerTitle: 'Container',
dragHandlerHint: 'drag container or field to layout center', dragHandlerHint: 'drag container or field to layout center',
dragAction: 'drag', dragAction: 'drag',

View File

@ -13,6 +13,7 @@ export default {
designer: { designer: {
componentLib: '组件库', componentLib: '组件库',
formLib: '表单模板', formLib: '表单模板',
hierarchy: '大纲',
containerTitle: '容器', containerTitle: '容器',
dragHandlerHint: '鼠标拖拽容器组件或字段组件并放置于表单中', dragHandlerHint: '鼠标拖拽容器组件或字段组件并放置于表单中',
dragAction: '拖动', dragAction: '拖动',