feat:仪表盘模板导入导出

This commit is contained in:
wangjiahao 2021-04-19 18:20:15 +08:00
parent f4f43a47aa
commit 5405332dc2
11 changed files with 258 additions and 120 deletions

View File

@ -31,9 +31,9 @@ public class PanelTemplateController {
return panelTemplateService.save(request); return panelTemplateService.save(request);
} }
@PostMapping("/deleteCircle/{id}") @PostMapping("/delete/{id}")
public void deleteCircle(@PathVariable String id) { public void delete(@PathVariable String id) {
panelTemplateService.deleteCircle(id); panelTemplateService.delete(id);
} }
@GetMapping("/findOne/{id}") @GetMapping("/findOne/{id}")

View File

@ -69,9 +69,9 @@ public class PanelTemplateService {
} }
public void deleteCircle(String id){ public void delete(String id){
Assert.notNull(id, "id cannot be null"); Assert.notNull(id, "id cannot be null");
extPanelTemplateMapper.deleteCircle(id); panelTemplateMapper.deleteByPrimaryKey(id);
} }

View File

@ -1,13 +1,14 @@
<template> <template>
<div @click="handleClick"> <div @click="handleClick">
<component <component
class="component" :is="config.component"
:is="config.component" class="component"
:style="getStyle(config.style)" :style="getStyle(config.style)"
:propValue="config.propValue" :prop-value="config.propValue"
:element="config" :element="config"
/> :filter="filter"
</div> />
</div>
</template> </template>
<script> <script>
@ -16,26 +17,30 @@ import runAnimation from '@/components/canvas/utils/runAnimation'
import { mixins } from '@/components/canvas/utils/events' import { mixins } from '@/components/canvas/utils/events'
export default { export default {
props: { mixins: [mixins],
config: { props: {
type: Object, config: {
require: true, type: Object,
}, require: true
}, },
mounted() { filter: {
runAnimation(this.$el, this.config.animations) type: Object,
}, require: false
mixins: [mixins], }
methods: { },
getStyle, mounted() {
runAnimation(this.$el, this.config.animations)
},
methods: {
getStyle,
handleClick() { handleClick() {
const events = this.config.events const events = this.config.events
Object.keys(events).forEach(event => { Object.keys(events).forEach(event => {
this[event](events[event]) this[event](events[event])
}) })
}, }
}, }
} }
</script> </script>

View File

@ -43,6 +43,7 @@
:style="getComponentStyle(item.style)" :style="getComponentStyle(item.style)"
:prop-value="item.propValue" :prop-value="item.propValue"
:element="item" :element="item"
:filter="filter"
/> />
<!-- <component <!-- <component
:is="item.component" :is="item.component"
@ -84,6 +85,10 @@ export default {
isEdit: { isEdit: {
type: Boolean, type: Boolean,
default: true default: true
},
filter: {
type: Object,
require: false
} }
}, },
data() { data() {

View File

@ -15,6 +15,20 @@ export default {
props: { props: {
element: { element: {
type: Object type: Object
},
filter: {
type: Object,
required: false,
default: function() {
return {
filter: []
}
}
}
},
watch: {
filter(val) {
this.getData(this.element.propValue.viewId)
} }
}, },
data() { data() {
@ -31,7 +45,7 @@ export default {
methods: { methods: {
getData(id) { getData(id) {
if (id) { if (id) {
post('/chart/view/getData/' + id, null).then(response => { post('/chart/view/getData/' + id, this.filter).then(response => {
// echart // echart
this.chart = response.data this.chart = response.data
}) })

View File

@ -20,7 +20,11 @@ export default {
chart: { chart: {
type: Object, type: Object,
required: true required: true
} },
filter: {
type: Object,
required: false
}
}, },
data() { data() {
return { return {

View File

@ -38,7 +38,7 @@
:visible.sync="templateSaveShow" :visible.sync="templateSaveShow"
custom-class="de-dialog" custom-class="de-dialog"
> >
<save-to-template /> <save-to-template :template-info="templateInfo" @closeSaveDialog="closeSaveDialog" />
</el-dialog> </el-dialog>
</el-row> </el-row>
</template> </template>
@ -87,12 +87,16 @@ export default {
this.templateSaveShow = true this.templateSaveShow = true
html2canvas(this.$refs.imageWrapper).then(canvas => { html2canvas(this.$refs.imageWrapper).then(canvas => {
debugger debugger
const snapShot = canvas.toDataURL('image/jpeg', 0.2) // 0.2 const snapshot = canvas.toDataURL('image/jpeg', 0.2) // 0.2
if (snapShot !== '') { if (snapshot !== '') {
this.templateInfo = { this.templateInfo = {
snapShot: snapShot, name: this.$store.state.panel.panelInfo.name,
panelStyle: JSON.stringify(this.canvasStyleData), snapshot: snapshot,
panelData: JSON.stringify(this.componentData), templateStyle: JSON.stringify(this.canvasStyleData),
templateData: JSON.stringify(this.componentData),
templateType: 'self',
level: 1,
pid: null,
dynamicData: '' dynamicData: ''
} }
} }
@ -104,6 +108,8 @@ export default {
const snapShot = canvas.toDataURL('image/jpeg', 0.2) // 0.2 const snapShot = canvas.toDataURL('image/jpeg', 0.2) // 0.2
if (snapShot !== '') { if (snapShot !== '') {
this.templateInfo = { this.templateInfo = {
name: this.$store.state.panel.panelInfo.name,
templateType: 'self',
snapShot: snapShot, snapShot: snapShot,
panelStyle: JSON.stringify(this.canvasStyleData), panelStyle: JSON.stringify(this.canvasStyleData),
panelData: JSON.stringify(this.componentData), panelData: JSON.stringify(this.componentData),
@ -128,6 +134,9 @@ export default {
} }
} }
}) })
},
closeSaveDialog() {
this.templateSaveShow = false
} }
} }

View File

@ -1,7 +1,10 @@
<template> <template>
<el-row> <el-row>
<el-row> <el-row>
<el-input v-model="name" placeholder="名称" /> <el-col span="4">模板名称</el-col>
<el-col span="20">
<el-input v-model="templateInfo.name" clearable size="mini" />
</el-col>
</el-row> </el-row>
<el-row class="de-tab"> <el-row class="de-tab">
<div class="my_table"> <div class="my_table">
@ -15,9 +18,9 @@
> >
<el-table-column :label="columnLabel" :column-key="fieldName" :prop="fieldName" /> <el-table-column :label="columnLabel" :column-key="fieldName" :prop="fieldName" />
<el-table-column align="right"> <el-table-column align="right">
<template slot="header"> <!-- <template slot="header">-->
<el-input v-model="keyWordSearch" size="mini" placeholder="输入关键字搜索" /> <!-- <el-input v-model="keyWordSearch" size="mini" placeholder="输入关键字搜索" />-->
</template> <!-- </template>-->
<template slot-scope="scope"> <template slot-scope="scope">
<el-radio v-model="tableRadio" :label="scope.row"><i /></el-radio> <el-radio v-model="tableRadio" :label="scope.row"><i /></el-radio>
</template> </template>
@ -26,8 +29,8 @@
</div> </div>
</el-row> </el-row>
<el-row class="root-class"> <el-row class="root-class">
<el-button @click="cancel"> </el-button> <el-button @click="cancel()"> </el-button>
<el-button type="primary" @click="save"> </el-button> <el-button type="primary" @click="save()"> </el-button>
</el-row> </el-row>
</el-row> </el-row>
</template> </template>
@ -37,10 +40,15 @@ import { post } from '@/api/panel/panel'
export default { export default {
name: 'SaveToTemplate', name: 'SaveToTemplate',
props: {
templateInfo: {
type: Object,
require: true
}
},
data() { data() {
return { return {
data: [], data: [],
name: '',
fieldName: 'name', fieldName: 'name',
tableRadio: null, tableRadio: null,
keyWordSearch: '', keyWordSearch: '',
@ -53,26 +61,37 @@ export default {
methods: { methods: {
search() { search() {
const param = { const param = {
template_type: 'self', templateType: 'self',
level: '0' level: '0'
} }
post('/template/templateList', param).then(response => { post('/template/templateList', param).then(response => {
this.data = response.data this.data = response.data
}) })
}, },
setCheckNodes() {
this.data.forEach(node => {
const nodeId = node.userId
this.shares.includes(nodeId) && this.$refs.table.toggleRowSelection(node, true)
})
},
clickChange(item) { clickChange(item) {
this.tableRadio = item this.tableRadio = item
this.templateInfo.pid = item.id
}, },
cancel() { cancel() {
this.$refs[this.activeName].cancel() this.$emit('closeSaveDialog')
this.$emit('close-grant', 0) },
save() {
if (!this.templateInfo.pid) {
this.$warning('请选择所属类别')
return false
}
if (!this.templateInfo.name) {
this.$warning('模板名称不能为空')
return false
}
post('/template/save', this.templateInfo).then(response => {
this.$message({
message: '保存成功',
type: 'success',
showClose: true
})
this.$emit('closeSaveDialog')
})
} }
} }

View File

@ -1,18 +1,21 @@
<template xmlns:el-col="http://www.w3.org/1999/html"> <template xmlns:el-col="http://www.w3.org/1999/html">
<el-col> <el-col>
<el-row> <el-row>
<div class="block"> <el-button icon="el-icon-folder-add" type="primary" size="mini" @click="add()">
<el-form> 添加分类
<el-form-item class="form-item"> </el-button>
<el-input </el-row>
v-model="systemTemplateFilterText" <el-row style="margin-top: 5px">
placeholder="输入关键字进行过滤" <el-row>
size="mini" <el-input
clearable v-model="systemTemplateFilterText"
prefix-icon="el-icon-search" placeholder="输入关键字进行过滤"
/> size="mini"
</el-form-item> clearable
</el-form> prefix-icon="el-icon-search"
/>
</el-row>
<el-row style="margin-top: 5px">
<el-tree <el-tree
ref="systemTemplateTree" ref="systemTemplateTree"
:default-expanded-keys="defaultExpandedKeys" :default-expanded-keys="defaultExpandedKeys"
@ -27,7 +30,7 @@
<span> <span>
<span> <span>
<el-button <el-button
icon="el-icon-picture-outline" icon="el-icon-collection"
type="text" type="text"
/> />
</span> </span>
@ -35,22 +38,27 @@
</span> </span>
</span> </span>
</el-tree> </el-tree>
</div> </el-row>
</el-row> </el-row>
</el-col> </el-col>
</template> </template>
<script> <script>
import { get, post } from '@/api/panel/panel'
export default { export default {
name: 'SystemTemplateList', name: 'SystemTemplateList',
components: { }, components: { },
props: {
systemTemplateList: {
type: Array,
default: function() {
return []
}
}
},
data() { data() {
return { return {
systemTemplateFilterText: '', systemTemplateFilterText: '',
defaultExpandedKeys: [], defaultExpandedKeys: [],
systemTemplateList: [],
currentTemplateShowList: [] currentTemplateShowList: []
} }
}, },
@ -62,33 +70,18 @@ export default {
this.$refs.systemTemplateTree.filter(val) this.$refs.systemTemplateTree.filter(val)
} }
}, },
mounted() {
this.getTree()
},
methods: { methods: {
filterNode(value, data) { filterNode(value, data) {
if (!value) return true if (!value) return true
return data.label.indexOf(value) !== -1 return data.label.indexOf(value) !== -1
}, },
getTree() {
const request = {
templateType: 'system',
level: '0'
}
post('/template/templateList', request).then(res => {
this.systemTemplateList = res.data
if (this.systemTemplateList && this.systemTemplateList.length > 0) {
const id = this.systemTemplateList[0].id
// this.currentNodeKey = id
// this.$refs['systemTemplateTree'].setCurrentKey(id)
this.$emit('showCurrentTemplate', id)
}
})
},
nodeClick(data, node) { nodeClick(data, node) {
console.log('nodeClick') console.log('nodeClick')
debugger debugger
this.$emit('showCurrentTemplate', data.id) this.$emit('showCurrentTemplate', data.id)
},
add() {
this.$emit('showTemplateEditDialog', 'new')
} }
} }
} }

View File

@ -1,6 +1,6 @@
<template> <template>
<div class="testcase-template"> <div class="testcase-template">
<div :style="classBackground" class="template-img"> <div class="template-img" :style="classBackground">
<i class="el-icon-error" @click.stop="templateDelete" /> <i class="el-icon-error" @click.stop="templateDelete" />
</div> </div>
<span class="demonstration">{{ template.name }}</span> <span class="demonstration">{{ template.name }}</span>
@ -23,13 +23,23 @@ export default {
classBackground() { classBackground() {
return { return {
background: `url(${this.template.snapshot}) no-repeat`, background: `url(${this.template.snapshot}) no-repeat`,
'background-size': '100%,100%' 'background-size': `100% 100%`
} }
} }
}, },
methods: { methods: {
templateDelete() { templateDelete() {
console.log('templateDelete') this.$alert('是否删除模板:' + this.template.name + '', '', {
confirmButtonText: '确认',
callback: (action) => {
if (action === 'confirm') {
this.$emit('templateDelete', this.template.id)
}
}
})
},
templateEdit() {
this.$emit('templateEdit', this.template)
}, },
handleDelete() { handleDelete() {
console.log('handleDelete') console.log('handleDelete')
@ -57,14 +67,13 @@ export default {
} }
.template-img { .template-img {
height: 150px; height: 130px;
width: 200px; width: 200px;
margin: 0 auto; margin: 0 auto;
box-shadow: 0 0 2px 0 rgba(31,31,31,0.15), 0 1px 2px 0 rgba(31,31,31,0.15); box-shadow: 0 0 2px 0 rgba(31,31,31,0.15), 0 1px 2px 0 rgba(31,31,31,0.15);
border: solid 2px #fff; border: solid 2px #fff;
box-sizing: border-box; box-sizing: border-box;
border-radius: 3px; border-radius: 3px;
background-size: 100%,100%;
} }
.template-img:hover { .template-img:hover {

View File

@ -1,26 +1,38 @@
<template> <template>
<de-container> <de-container>
<de-aside-container> <de-aside-container>
<el-tabs v-model="activeName" @tab-click="handleClick"> <el-tabs v-model="currentTemplateType" @tab-click="handleClick">
<el-tab-pane name="SystemTemplate"> <el-tab-pane name="system">
<span slot="label"><i class="el-icon-document" />系统模板</span> <span slot="label"><i class="el-icon-document" />系统模板</span>
<system-template-list @showCurrentTemplate="showCurrentTemplate" /> <system-template-list :system-template-list="systemTemplateList" @showTemplateEditDialog="showTemplateEditDialog" />
</el-tab-pane> </el-tab-pane>
<el-tab-pane name="UserTemplate"> <el-tab-pane name="self">
<span slot="label"><i class="el-icon-star-off" />用户模板</span> <span slot="label"><i class="el-icon-star-off" />用户模板</span>
开发中... 开发中...
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
</de-aside-container> </de-aside-container>
<de-main-container> <de-main-container>
<!-- <el-card class="el-card-template">-->
<template-item <template-item
v-for="item in currentTemplateShowList" v-for="item in currentTemplateShowList"
:key="item.id" :key="item.id"
:template="item" :template="item"
@templateDelete="templateDelete"
@templateEdit="templateEdit"
/> />
<!-- </el-card>-->
</de-main-container> </de-main-container>
<el-dialog :title="dialogTitle" :visible="editTemplate" :show-close="false" width="30%">
<el-form ref="templateEditForm" :model="templateEditForm" :rules="templateEditFormRules">
<el-form-item label="名称" prop="name">
<el-input v-model="templateEditForm.name" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button size="mini" @click="close()">{{ $t('panel.cancel') }}</el-button>
<el-button type="primary" size="mini" @click="saveTemplateEdit(templateEditForm)">{{ $t('panel.confirm') }}
</el-button>
</div>
</el-dialog>
</de-container> </de-container>
</template> </template>
@ -31,38 +43,106 @@ import DeAsideContainer from '@/components/dataease/DeAsideContainer'
import SystemTemplateList from './component/SystemTemplateList' import SystemTemplateList from './component/SystemTemplateList'
import TemplateItem from './component/TemplateItem' import TemplateItem from './component/TemplateItem'
import { get, post } from '@/api/panel/panel' import { get, post } from '@/api/panel/panel'
import { deepCopy } from '../../../components/canvas/utils/utils'
export default { export default {
name: 'PanelMain', name: 'PanelMain',
components: { DeMainContainer, DeContainer, DeAsideContainer, SystemTemplateList, TemplateItem }, components: { DeMainContainer, DeContainer, DeAsideContainer, SystemTemplateList, TemplateItem },
data() { data() {
return { return {
activeName: 'SystemTemplate',
showShare: false, showShare: false,
currentTemplateShowList: [] currentTemplateShowList: [],
currentPid: '',
currentTemplateType: 'system',
templateEditFormRules: {
name: [
{ required: true, message: this.$t('commons.input_content'), trigger: 'change' }
]
},
templateEditForm: {},
editTemplate: false,
dialogTitle: '',
systemTemplateList: []
} }
}, },
mounted() {
this.getTree()
},
methods: { methods: {
handleClick(tab, event) { handleClick(tab, event) {
//
if (tab.name === 'panels_share') {
this.refreshShare()
}
}, },
refreshShare() { showCurrentTemplate(pid) {
this.showShare = false this.currentPid = pid
this.$nextTick(() => (this.showShare = true)) if (this.currentPid) {
}, post('/template/templateList', { pid: this.currentPid }).then(response => {
get() {
this.showShare = false
this.$nextTick(() => (this.showShare = true))
},
showCurrentTemplate(currentPid) {
if (currentPid) {
post('/template/templateList', { pid: currentPid }).then(response => {
this.currentTemplateShowList = response.data this.currentTemplateShowList = response.data
}) })
} }
},
templateDelete(id) {
if (id) {
post('/template/delete/' + id, null).then(response => {
this.$message({
message: '删除成功',
type: 'success',
showClose: true
})
this.showCurrentTemplate(this.currentPid)
})
}
},
saveTemplate(templateEditForm) {
if (templateEditForm) {
post('/template/save', templateEditForm).then(response => {
this.$message({
message: '删除成功',
type: 'success',
showClose: true
})
this.showCurrentTemplate(this.currentPid)
})
}
},
showTemplateEditDialog(type, templateInfo) {
if (type === 'edit') {
this.dialogTitle = '编辑'
this.templateEditForm = deepCopy(templateInfo)
} else {
this.dialogTitle = '新建'
this.templateEditForm = { name: '', templateType: this.currentTemplateType, level: 0 }
}
this.editTemplate = true
},
templateEdit(templateInfo) {
this.showTemplateEditDialog('edit', templateInfo)
},
saveTemplateEdit(templateEditForm) {
debugger
post('/template/save', templateEditForm).then(response => {
this.$message({
message: '保存成功',
type: 'success',
showClose: true
})
this.editTemplate = false
this.getTree()
})
},
close() {
this.editTemplate = false
},
getTree() {
const request = {
templateType: this.currentTemplateType,
level: '0'
}
post('/template/templateList', request).then(res => {
this.systemTemplateList = res.data
if (this.systemTemplateList && this.systemTemplateList.length > 0) {
this.showCurrentTemplate(this.systemTemplateList[0].id)
}
})
} }
} }
} }