forked from github/dataease
feat:增加仪表盘设计组件及设计
This commit is contained in:
parent
fec733f262
commit
8b80d8fa72
@ -29,6 +29,7 @@ public class ShiroServiceImpl implements ShiroService {
|
||||
filterChainDefinitionMap.put("/v2/**","anon");
|
||||
filterChainDefinitionMap.put("/v3/**","anon");
|
||||
filterChainDefinitionMap.put("/static/**", "anon");
|
||||
filterChainDefinitionMap.put("/common-files/**", "anon");
|
||||
|
||||
|
||||
// filterChainDefinitionMap.put("/401", "anon");
|
||||
|
@ -0,0 +1,22 @@
|
||||
package io.dataease.controller;
|
||||
|
||||
import io.dataease.service.CommonFilesService;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("common-files")
|
||||
public class CommonFilesController {
|
||||
@Resource
|
||||
private CommonFilesService commonFilesService;
|
||||
|
||||
@GetMapping("/images/{imageId}")
|
||||
public ResponseEntity<byte[]> image(@PathVariable("imageId") String imageId) {
|
||||
return commonFilesService.getImageById(imageId);
|
||||
}
|
||||
}
|
@ -5,7 +5,9 @@ import io.dataease.controller.request.dataset.DataSetGroupRequest;
|
||||
import io.dataease.controller.request.panel.PanelGroupRequest;
|
||||
import io.dataease.dto.dataset.DataSetGroupDTO;
|
||||
import io.dataease.dto.panel.PanelGroupDTO;
|
||||
import io.dataease.service.CommonFilesService;
|
||||
import io.dataease.service.panel.PanelGroupService;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
@ -0,0 +1,33 @@
|
||||
package io.dataease.service;
|
||||
|
||||
import io.dataease.base.domain.FileMetadata;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@Service
|
||||
public class CommonFilesService {
|
||||
|
||||
@Resource
|
||||
private FileService fileService;
|
||||
|
||||
|
||||
public ResponseEntity<byte[]> getImageById(String imageId) {
|
||||
byte[] bytes = null;
|
||||
MediaType contentType = MediaType.parseMediaType("application/octet-stream");
|
||||
FileMetadata fileMetadata = fileService.copyFile(imageId);
|
||||
if (fileMetadata == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
bytes = fileService.loadFileAsBytes(imageId);
|
||||
return ResponseEntity.ok()
|
||||
.contentType(contentType)
|
||||
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileMetadata.getName() + "\"")
|
||||
.body(bytes);
|
||||
}
|
||||
|
||||
}
|
@ -54,6 +54,10 @@ management.endpoints.web.exposure.include=*
|
||||
rsa.private_key=MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEA0vfvyTdGJkdbHkB8mp0f3FE0GYP3AYPaJF7jUd1M0XxFSE2ceK3k2kw20YvQ09NJKk+OMjWQl9WitG9pB6tSCQIDAQABAkA2SimBrWC2/wvauBuYqjCFwLvYiRYqZKThUS3MZlebXJiLB+Ue/gUifAAKIg1avttUZsHBHrop4qfJCwAI0+YRAiEA+W3NK/RaXtnRqmoUUkb59zsZUBLpvZgQPfj1MhyHDz0CIQDYhsAhPJ3mgS64NbUZmGWuuNKp5coY2GIj/zYDMJp6vQIgUueLFXv/eZ1ekgz2Oi67MNCk5jeTF2BurZqNLR3MSmUCIFT3Q6uHMtsB9Eha4u7hS31tj1UWE+D+ADzp59MGnoftAiBeHT7gDMuqeJHPL4b+kC+gzV4FGTfhR9q3tTbklZkD2A==
|
||||
spring.cache.type=ehcache
|
||||
spring.cache.ehcache.config=classpath:/ehcache/ehcache.xml
|
||||
#打印URL路径
|
||||
logging.level.org.springframework.web=trace
|
||||
logging.level.org.springframework.boot.web=trace
|
||||
spring.mvc.log-request-details=true
|
||||
|
||||
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@riophae/vue-treeselect": "0.4.0",
|
||||
"axios": "0.18.1",
|
||||
"axios": "^0.21.1",
|
||||
"echarts": "^5.0.2",
|
||||
"element-ui": "2.13.0",
|
||||
"fit2cloud-ui": "^0.1.12",
|
||||
@ -45,6 +45,8 @@
|
||||
"eslint": "5.15.3",
|
||||
"eslint-plugin-vue": "5.2.2",
|
||||
"html-webpack-plugin": "3.2.0",
|
||||
"less": "^4.1.1",
|
||||
"less-loader": "^8.0.0",
|
||||
"mockjs": "1.0.1-beta3",
|
||||
"runjs": "^4.3.2",
|
||||
"sass": "^1.32.5",
|
||||
|
60
frontend/src/components/vue-drag-resize-rotate/dom.js
Normal file
60
frontend/src/components/vue-drag-resize-rotate/dom.js
Normal file
@ -0,0 +1,60 @@
|
||||
import { isFunction } from './fns'
|
||||
|
||||
// 将选择器与父元素匹配
|
||||
export function matchesSelectorToParentElements (el, selector, baseNode) {
|
||||
let node = el
|
||||
|
||||
const matchesSelectorFunc = [
|
||||
'matches',
|
||||
'webkitMatchesSelector',
|
||||
'mozMatchesSelector',
|
||||
'msMatchesSelector',
|
||||
'oMatchesSelector'
|
||||
].find(func => isFunction(node[func]))
|
||||
|
||||
if (!isFunction(node[matchesSelectorFunc])) return false
|
||||
|
||||
do {
|
||||
if (node[matchesSelectorFunc](selector)) return true
|
||||
if (node === baseNode) return false
|
||||
node = node.parentNode
|
||||
} while (node)
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
export function getComputedSize ($el) {
|
||||
const style = window.getComputedStyle($el)
|
||||
|
||||
return [
|
||||
parseFloat(style.getPropertyValue('width'), 10),
|
||||
parseFloat(style.getPropertyValue('height'), 10)
|
||||
]
|
||||
}
|
||||
// 添加事件
|
||||
export function addEvent (el, event, handler) {
|
||||
if (!el) {
|
||||
return
|
||||
}
|
||||
if (el.attachEvent) {
|
||||
el.attachEvent('on' + event, handler)
|
||||
} else if (el.addEventListener) {
|
||||
el.addEventListener(event, handler, true)
|
||||
} else {
|
||||
el['on' + event] = handler
|
||||
}
|
||||
}
|
||||
|
||||
// 删除事件
|
||||
export function removeEvent (el, event, handler) {
|
||||
if (!el) {
|
||||
return
|
||||
}
|
||||
if (el.detachEvent) {
|
||||
el.detachEvent('on' + event, handler)
|
||||
} else if (el.removeEventListener) {
|
||||
el.removeEventListener(event, handler, true)
|
||||
} else {
|
||||
el['on' + event] = null
|
||||
}
|
||||
}
|
40
frontend/src/components/vue-drag-resize-rotate/fns.js
Normal file
40
frontend/src/components/vue-drag-resize-rotate/fns.js
Normal file
@ -0,0 +1,40 @@
|
||||
export function isFunction (func) {
|
||||
return (typeof func === 'function' || Object.prototype.toString.call(func) === '[object Function]')
|
||||
}
|
||||
|
||||
// 对其栅格
|
||||
export function snapToGrid (grid, pendingX, pendingY, scale = 1) {
|
||||
const x = Math.round((pendingX / scale) / grid[0]) * grid[0]
|
||||
const y = Math.round((pendingY / scale) / grid[1]) * grid[1]
|
||||
return [x, y]
|
||||
}
|
||||
|
||||
// 获取rect模型
|
||||
export function getSize (el) {
|
||||
const rect = el.getBoundingClientRect()
|
||||
|
||||
return [
|
||||
parseInt(rect.width),
|
||||
parseInt(rect.height)
|
||||
]
|
||||
}
|
||||
|
||||
export function computeWidth (parentWidth, left, right) {
|
||||
return parentWidth - left - right
|
||||
}
|
||||
|
||||
export function computeHeight (parentHeight, top, bottom) {
|
||||
return parentHeight - top - bottom
|
||||
}
|
||||
|
||||
export function restrictToBounds (value, min, max) {
|
||||
if (min !== null && value < min) {
|
||||
return min
|
||||
}
|
||||
|
||||
if (max !== null && max < value) {
|
||||
return max
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
1506
frontend/src/components/vue-drag-resize-rotate/index.vue
Normal file
1506
frontend/src/components/vue-drag-resize-rotate/index.vue
Normal file
File diff suppressed because it is too large
Load Diff
60
frontend/src/components/vue-drag-resize/dom.js
Normal file
60
frontend/src/components/vue-drag-resize/dom.js
Normal file
@ -0,0 +1,60 @@
|
||||
import { isFunction } from './fns'
|
||||
|
||||
// 将选择器与父元素匹配
|
||||
export function matchesSelectorToParentElements (el, selector, baseNode) {
|
||||
let node = el
|
||||
|
||||
const matchesSelectorFunc = [
|
||||
'matches',
|
||||
'webkitMatchesSelector',
|
||||
'mozMatchesSelector',
|
||||
'msMatchesSelector',
|
||||
'oMatchesSelector'
|
||||
].find(func => isFunction(node[func]))
|
||||
|
||||
if (!isFunction(node[matchesSelectorFunc])) return false
|
||||
|
||||
do {
|
||||
if (node[matchesSelectorFunc](selector)) return true
|
||||
if (node === baseNode) return false
|
||||
node = node.parentNode
|
||||
} while (node)
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
export function getComputedSize ($el) {
|
||||
const style = window.getComputedStyle($el)
|
||||
|
||||
return [
|
||||
parseFloat(style.getPropertyValue('width'), 10),
|
||||
parseFloat(style.getPropertyValue('height'), 10)
|
||||
]
|
||||
}
|
||||
// 添加事件
|
||||
export function addEvent (el, event, handler) {
|
||||
if (!el) {
|
||||
return
|
||||
}
|
||||
if (el.attachEvent) {
|
||||
el.attachEvent('on' + event, handler)
|
||||
} else if (el.addEventListener) {
|
||||
el.addEventListener(event, handler, true)
|
||||
} else {
|
||||
el['on' + event] = handler
|
||||
}
|
||||
}
|
||||
|
||||
// 删除事件
|
||||
export function removeEvent (el, event, handler) {
|
||||
if (!el) {
|
||||
return
|
||||
}
|
||||
if (el.detachEvent) {
|
||||
el.detachEvent('on' + event, handler)
|
||||
} else if (el.removeEventListener) {
|
||||
el.removeEventListener(event, handler, true)
|
||||
} else {
|
||||
el['on' + event] = null
|
||||
}
|
||||
}
|
40
frontend/src/components/vue-drag-resize/fns.js
Normal file
40
frontend/src/components/vue-drag-resize/fns.js
Normal file
@ -0,0 +1,40 @@
|
||||
export function isFunction (func) {
|
||||
return (typeof func === 'function' || Object.prototype.toString.call(func) === '[object Function]')
|
||||
}
|
||||
|
||||
// 对其栅格
|
||||
export function snapToGrid (grid, pendingX, pendingY, scale = 1) {
|
||||
const x = Math.round((pendingX / scale) / grid[0]) * grid[0]
|
||||
const y = Math.round((pendingY / scale) / grid[1]) * grid[1]
|
||||
return [x, y]
|
||||
}
|
||||
|
||||
// 获取rect模型
|
||||
export function getSize (el) {
|
||||
const rect = el.getBoundingClientRect()
|
||||
|
||||
return [
|
||||
parseInt(rect.width),
|
||||
parseInt(rect.height)
|
||||
]
|
||||
}
|
||||
|
||||
export function computeWidth (parentWidth, left, right) {
|
||||
return parentWidth - left - right
|
||||
}
|
||||
|
||||
export function computeHeight (parentHeight, top, bottom) {
|
||||
return parentHeight - top - bottom
|
||||
}
|
||||
|
||||
export function restrictToBounds (value, min, max) {
|
||||
if (min !== null && value < min) {
|
||||
return min
|
||||
}
|
||||
|
||||
if (max !== null && max < value) {
|
||||
return max
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
1277
frontend/src/components/vue-drag-resize/index.vue
Normal file
1277
frontend/src/components/vue-drag-resize/index.vue
Normal file
File diff suppressed because it is too large
Load Diff
@ -720,7 +720,7 @@ export default {
|
||||
confirm: '确认',
|
||||
cancel: '取消',
|
||||
search: '搜索',
|
||||
back: '返回'
|
||||
|
||||
back: '返回',
|
||||
view: '视图'
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,9 @@ import message from '@/metersphere/common/js/message'
|
||||
import { left2RightDrag, bottom2TopDrag, right2LeftDrag } from '@/metersphere/common/js/directive'
|
||||
import directives from './directive'
|
||||
|
||||
import vdrr from './components/vue-drag-resize-rotate'
|
||||
Vue.component('vdrr', vdrr)
|
||||
|
||||
Vue.prototype.$api = api
|
||||
|
||||
import * as echarts from 'echarts'
|
||||
|
123
frontend/src/styles/vdrr/common.scss
Normal file
123
frontend/src/styles/vdrr/common.scss
Normal file
@ -0,0 +1,123 @@
|
||||
* {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
// 滚动条
|
||||
::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
box-shadow: inset 0 0 5px rgba(0, 0, 0, .5);
|
||||
border-radius: 10px;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
border-radius: 10px;
|
||||
box-shadow: inset 0 0 5px rgba(0, 0, 0, .5);
|
||||
background: #141414;
|
||||
}
|
||||
|
||||
// 文字对齐
|
||||
.text-left {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.text-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.text-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
// 首页
|
||||
#app {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
}
|
||||
|
||||
#menu {
|
||||
width: 275px;
|
||||
min-width: 200px;
|
||||
max-width: 500px;
|
||||
height: 100vh;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
|
||||
.el-menu {
|
||||
border: none;
|
||||
|
||||
.el-submenu__title {
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
.el-menu-item {
|
||||
height: 28px;
|
||||
line-height: 28px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#view {
|
||||
flex: 1;
|
||||
min-width: 500px;
|
||||
padding: 10px 35px 0 35px;
|
||||
height: 100vh;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
|
||||
.drag-bar {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100vh;
|
||||
width: 5px;
|
||||
z-index: 99;
|
||||
border-left: 1px solid #ccc;
|
||||
cursor: ew-resize
|
||||
}
|
||||
|
||||
.view-box {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#toolbar {
|
||||
left: 0;
|
||||
top: 0;
|
||||
height: 24px;
|
||||
padding: 5px;
|
||||
border: 1px solid #999;
|
||||
border-bottom: none;
|
||||
background-color: #CCC;
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
.container {
|
||||
width: 100%;
|
||||
height: 600px;
|
||||
border: 1px solid #000;
|
||||
|
||||
position: relative;
|
||||
box-sizing: border-box
|
||||
}
|
||||
|
||||
.vdr {
|
||||
border: 1px dashed;
|
||||
}
|
||||
|
||||
.vdrr {
|
||||
border: 1px dashed;
|
||||
}
|
147
frontend/src/styles/vdrr/customize.scss
Normal file
147
frontend/src/styles/vdrr/customize.scss
Normal file
@ -0,0 +1,147 @@
|
||||
.pattern-contaienr {
|
||||
border: 1px solid #ccc;
|
||||
width: 576px;
|
||||
height: 324px;
|
||||
}
|
||||
|
||||
.iconPistion {
|
||||
border-width: 2px;
|
||||
border-style: solid;
|
||||
border-color: #409eff;
|
||||
background-color: rgba(128, 128, 128, 0.5);
|
||||
box-sizing: border-box;
|
||||
|
||||
.icon-slot {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.patternContent {
|
||||
display: flex;
|
||||
|
||||
.patternLeft {
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.patternRight {
|
||||
width: 400px;
|
||||
margin: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.icon-slot {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
.status {
|
||||
text-align: left;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.order {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
}
|
||||
|
||||
.activePattern {
|
||||
border-style: solid;
|
||||
border-color: #08de05;
|
||||
}
|
||||
|
||||
|
||||
.drag-handle,
|
||||
.drag-cancel {
|
||||
padding: 6px;
|
||||
margin: 6px;
|
||||
background-color: #CCC;
|
||||
border: 2px solid;
|
||||
}
|
||||
|
||||
.drag-handle:hover {
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
.drag-cancel:hover {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.my-handle-class {
|
||||
position: absolute;
|
||||
border: 1px solid black;
|
||||
border-radius: 50%;
|
||||
height: 14px;
|
||||
width: 14px;
|
||||
font-size: 1em;
|
||||
line-height: 1em;
|
||||
box-sizing: border-box;
|
||||
-webkit-transition: all 300ms linear;
|
||||
-ms-transition: all 300ms linear;
|
||||
transition: all 300ms linear;
|
||||
}
|
||||
|
||||
.my-handle-class-tl {
|
||||
top: -14px;
|
||||
left: -14px;
|
||||
cursor: nw-resize;
|
||||
}
|
||||
|
||||
.my-handle-class-tm {
|
||||
top: -14px;
|
||||
left: 50%;
|
||||
margin-left: -7px;
|
||||
cursor: n-resize;
|
||||
}
|
||||
|
||||
.my-handle-class-tr {
|
||||
top: -14px;
|
||||
right: -14px;
|
||||
cursor: ne-resize;
|
||||
}
|
||||
|
||||
.my-handle-class-ml {
|
||||
top: 50%;
|
||||
margin-top: -7px;
|
||||
left: -14px;
|
||||
cursor: w-resize;
|
||||
}
|
||||
|
||||
.my-handle-class-mr {
|
||||
top: 50%;
|
||||
margin-top: -7px;
|
||||
right: -14px;
|
||||
cursor: e-resize;
|
||||
}
|
||||
|
||||
.my-handle-class-bl {
|
||||
bottom: -14px;
|
||||
left: -14px;
|
||||
cursor: sw-resize;
|
||||
}
|
||||
|
||||
.my-handle-class-bm {
|
||||
bottom: -14px;
|
||||
left: 50%;
|
||||
margin-left: -7px;
|
||||
cursor: s-resize;
|
||||
}
|
||||
|
||||
.my-handle-class-br {
|
||||
bottom: -14px;
|
||||
right: -14px;
|
||||
cursor: se-resize;
|
||||
}
|
||||
|
||||
.my-handle-class-tl:hover,
|
||||
.my-handle-class-tm:hover,
|
||||
.my-handle-class-tr:hover,
|
||||
.my-handle-class-ml:hover,
|
||||
.my-handle-class-mr:hover,
|
||||
.my-handle-class-bl:hover,
|
||||
.my-handle-class-bm:hover,
|
||||
.my-handle-class-br:hover {
|
||||
transform: scale(1.4);
|
||||
}
|
50
frontend/src/styles/vdrr/highlight.scss
Normal file
50
frontend/src/styles/vdrr/highlight.scss
Normal file
@ -0,0 +1,50 @@
|
||||
// 添加行号样式
|
||||
pre.hljs {
|
||||
padding: 8px 2px;
|
||||
border-radius: 5px;
|
||||
position: relative;
|
||||
|
||||
ol {
|
||||
list-style: decimal;
|
||||
margin: 0;
|
||||
margin-left: 40px;
|
||||
padding: 0;
|
||||
|
||||
li {
|
||||
list-style: decimal-leading-zero;
|
||||
position: relative;
|
||||
padding-left: 10px;
|
||||
|
||||
.line-num {
|
||||
position: absolute;
|
||||
left: -40px;
|
||||
top: 0;
|
||||
width: 40px;
|
||||
height: 100%;
|
||||
border-right: 1px solid rgba(0, 0, 0, .66);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
b.name {
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
right: 12px;
|
||||
z-index: 10;
|
||||
color: #999;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
span.hljs-tag,
|
||||
span.hljs-name {
|
||||
color: #eb333c;
|
||||
}
|
||||
|
||||
|
||||
span.hljs-string {
|
||||
color: #b4aa34;
|
||||
|
||||
}
|
247
frontend/src/styles/vdrr/markdown.scss
Normal file
247
frontend/src/styles/vdrr/markdown.scss
Normal file
@ -0,0 +1,247 @@
|
||||
.markdown-render {
|
||||
html {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: "Open Sans", "Clear Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
color: rgb(51, 51, 51);
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #4183C4;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
position: relative;
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
font-weight: bold;
|
||||
line-height: 1.4;
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
h1:hover a.anchor,
|
||||
h2:hover a.anchor,
|
||||
h3:hover a.anchor,
|
||||
h4:hover a.anchor,
|
||||
h5:hover a.anchor,
|
||||
h6:hover a.anchor {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
h1 tt,
|
||||
h1 code {
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
h2 tt,
|
||||
h2 code {
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
h3 tt,
|
||||
h3 code {
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
h4 tt,
|
||||
h4 code {
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
h5 tt,
|
||||
h5 code {
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
h6 tt,
|
||||
h6 code {
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
h1 {
|
||||
padding-bottom: .3em;
|
||||
font-size: 2.0m;
|
||||
line-height: 1.2;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
h2 {
|
||||
padding-bottom: .3em;
|
||||
font-size: 1.66em;
|
||||
line-height: 1.225;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.33em;
|
||||
line-height: 1.43;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 1.11em;
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: .8m;
|
||||
color: #777;
|
||||
}
|
||||
|
||||
p,
|
||||
blockquote,
|
||||
ul,
|
||||
ol,
|
||||
dl,
|
||||
table {
|
||||
margin: 0.8em 0;
|
||||
}
|
||||
|
||||
li>ol,
|
||||
li>ul {
|
||||
margin: 0 0;
|
||||
}
|
||||
|
||||
hr {
|
||||
height: 2px;
|
||||
padding: 0;
|
||||
margin: 16px 0;
|
||||
background-color: #e7e7e7;
|
||||
border: 0 none;
|
||||
overflow: hidden;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
li p.first {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
ul,
|
||||
ol {
|
||||
padding-left: 30px;
|
||||
}
|
||||
|
||||
ul:first-child,
|
||||
ol:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
ul:last-child,
|
||||
ol:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
border-left: 4px solid #dfe2e5;
|
||||
padding: 0 15px;
|
||||
color: #777777;
|
||||
}
|
||||
|
||||
blockquote blockquote {
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
table {
|
||||
padding: 0;
|
||||
word-break: initial;
|
||||
}
|
||||
|
||||
table tr {
|
||||
border-top: 1px solid #dfe2e5;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
table tr:nth-child(2n),
|
||||
thead {
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
|
||||
table tr th {
|
||||
font-weight: bold;
|
||||
border: 1px solid #dfe2e5;
|
||||
border-bottom: 0;
|
||||
margin: 0;
|
||||
padding: 6px 13px;
|
||||
}
|
||||
|
||||
table tr td {
|
||||
border: 1px solid #dfe2e5;
|
||||
margin: 0;
|
||||
padding: 6px 13px;
|
||||
}
|
||||
|
||||
table tr th:first-child,
|
||||
table tr td:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
table tr th:last-child,
|
||||
table tr td:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
tt {
|
||||
border: 1px solid #e7eaed;
|
||||
background-color: #f8f8f8;
|
||||
border-radius: 3px;
|
||||
padding: 0;
|
||||
padding: 2px 4px 0px 4px;
|
||||
font-size: .9em;
|
||||
}
|
||||
|
||||
code {
|
||||
background-color: #f3f4f4;
|
||||
padding: 0 2px 0 2px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
|
||||
@media print {
|
||||
html {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
table,
|
||||
pre {
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
|
||||
pre {
|
||||
word-wrap: break-word;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
pre {
|
||||
padding: 1rem;
|
||||
font-size: 100%;
|
||||
line-height: 1.45;
|
||||
background-color:#f7f7f7;
|
||||
border: 0;
|
||||
border-radius: 3px;
|
||||
color: #777777;
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
border-left-color: rgba(85, 85, 85, 0.12);
|
||||
}
|
||||
|
||||
header,
|
||||
footer {
|
||||
font-family: "Segoe UI", "Arial", sans-serif;
|
||||
}
|
||||
|
||||
}
|
20
frontend/src/views/panel/chart/chart.js
Normal file
20
frontend/src/views/panel/chart/chart.js
Normal file
@ -0,0 +1,20 @@
|
||||
export const BASE_BAR = {
|
||||
title: {
|
||||
text: ''
|
||||
},
|
||||
tooltip: {},
|
||||
legend: {
|
||||
data: []
|
||||
},
|
||||
xAxis: {
|
||||
data: []
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value'
|
||||
},
|
||||
series: []
|
||||
}
|
||||
|
||||
export default {
|
||||
BASE_BAR
|
||||
}
|
@ -37,13 +37,14 @@ import MsAsideContainer from '@/metersphere/common/components/MsAsideContainer'
|
||||
// import Group from './group/Group'
|
||||
import PanelList from './list/PanelList'
|
||||
import PanelView from './list/PanelView'
|
||||
import PanelViewShow from './list/PanelViewShow'
|
||||
|
||||
export default {
|
||||
name: 'Panel',
|
||||
components: { MsMainContainer, MsContainer, MsAsideContainer, PanelList, PanelView },
|
||||
components: { MsMainContainer, MsContainer, MsAsideContainer, PanelList, PanelView ,PanelViewShow},
|
||||
data() {
|
||||
return {
|
||||
component: PanelView,
|
||||
component: PanelViewShow,
|
||||
param: {},
|
||||
activeName: 'PanelList'
|
||||
}
|
||||
@ -56,8 +57,8 @@ export default {
|
||||
console.log(c)
|
||||
this.param = c.param
|
||||
switch (c.name) {
|
||||
case 'PanelView':
|
||||
this.component = PanelView
|
||||
case 'PanelViewShow':
|
||||
this.component = PanelViewShow
|
||||
break
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,7 @@
|
||||
<template xmlns:el-col="http://www.w3.org/1999/html">
|
||||
<el-col>
|
||||
<el-row>
|
||||
<el-row style="height: 100%;overflow-y: hidden;width: 100%;">
|
||||
<span>仪表盘名称:{{panelName}}</span>
|
||||
|
||||
</el-row>
|
||||
</el-col>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
364
frontend/src/views/panel/list/PanelViewShow.vue
Normal file
364
frontend/src/views/panel/list/PanelViewShow.vue
Normal file
@ -0,0 +1,364 @@
|
||||
<template>
|
||||
<el-row style="height: 100%;overflow-y: hidden;width: 100%;">
|
||||
<el-row style="display: flex;height: 100%">
|
||||
<el-col class="view-list">
|
||||
<el-tabs v-model="ViewActiveName">
|
||||
<!--视图展示操作-->
|
||||
<el-tab-pane name="Views" class="view-list-thumbnails-outline">
|
||||
<span slot="label"><i class="el-icon-s-data" />视图</span>
|
||||
<draggable
|
||||
v-model="thumbnails"
|
||||
:options="{group:{name: 'itxst',pull:'clone'},sort: true}"
|
||||
animation="300"
|
||||
:move="onMove"
|
||||
style="height: 100%;overflow:auto"
|
||||
@end="end1"
|
||||
>
|
||||
<transition-group>
|
||||
<img class="view-list-thumbnails" v-for="item in thumbnails" :key="item.name" :src="'/common-files/images/'+item.id" alt=""/>
|
||||
</transition-group>
|
||||
</draggable>
|
||||
</el-tab-pane>
|
||||
|
||||
<!--通用组件操作-->
|
||||
<el-tab-pane name="PublicTools">
|
||||
<span slot="label"><i class="el-icon-s-grid" />组件</span>
|
||||
开发中...
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-col>
|
||||
|
||||
<el-col class="panel-design">
|
||||
<!--TODO 仪表盘设计公共设置区域-->
|
||||
<el-row class="panel-design-head">
|
||||
<span style="float: right;line-height: 40px;">
|
||||
<el-button size="mini">
|
||||
背景图
|
||||
</el-button>
|
||||
<el-button type="primary" size="mini" @click="save">
|
||||
透视
|
||||
</el-button>
|
||||
</span>
|
||||
</el-row>
|
||||
<el-row class="panel-design-show">
|
||||
<div class="Echarts" style="height: 100%;display: flex;margin-top: 10px;">
|
||||
<div id="echart" style="width: 100%;height: 80vh;"/>
|
||||
</div>
|
||||
</el-row>
|
||||
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-row>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { post } from '@/api/dataset/dataset'
|
||||
import draggable from 'vuedraggable'
|
||||
import { BASE_BAR } from '../chart/chart'
|
||||
|
||||
export default {
|
||||
name: 'PanelViewShow',
|
||||
components: { draggable },
|
||||
data() {
|
||||
return {
|
||||
ViewActiveName:'Views',
|
||||
table: {},
|
||||
thumbnails: [
|
||||
{id:'772572ba-8bc1-4125-97a9-5b810466e339',name:'TEST1'},
|
||||
{id:'772572ba-8bc1-4125-97a9-5b810466e339',name:'TEST2'},
|
||||
{id:'772572ba-8bc1-4125-97a9-5b810466e339',name:'TEST3'},
|
||||
{id:'772572ba-8bc1-4125-97a9-5b810466e339',name:'TEST4'}
|
||||
],
|
||||
quota: [],
|
||||
view: {
|
||||
xaxis: [],
|
||||
yaxis: [],
|
||||
show: true,
|
||||
type: 'bar',
|
||||
title: ''
|
||||
},
|
||||
// 定义要被拖拽对象的数组
|
||||
arr1: [
|
||||
{ id: 1, name: 'id' },
|
||||
{ id: 2, name: '名称' },
|
||||
{ id: 3, name: '类型' },
|
||||
{ id: 5, name: '状态' },
|
||||
{ id: 4, name: '指标指标指标' }
|
||||
],
|
||||
arr2: [
|
||||
{ id: 11, name: '容量' }
|
||||
],
|
||||
moveId: -1
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
tableId() {
|
||||
// console.log(this.$store.state.chart.tableId);
|
||||
this.initTableData(this.$store.state.chart.tableId)
|
||||
return this.$store.state.chart.tableId
|
||||
},
|
||||
sceneId() {
|
||||
// console.log(this.$store.state.chart.sceneId);
|
||||
return this.$store.state.chart.sceneId
|
||||
},
|
||||
vId() {
|
||||
// console.log(this.$store.state.chart.viewId);
|
||||
this.getData(this.$store.state.chart.viewId)
|
||||
return this.$store.state.chart.viewId
|
||||
}
|
||||
|
||||
},
|
||||
watch: {},
|
||||
created() {
|
||||
// this.get(this.$store.state.chart.viewId);
|
||||
},
|
||||
mounted() {
|
||||
// this.get(this.$store.state.chart.viewId);
|
||||
this.getData(this.$store.state.chart.viewId)
|
||||
// this.myEcharts();
|
||||
},
|
||||
activated() {
|
||||
},
|
||||
methods: {
|
||||
initTableData(id) {
|
||||
if (id != null) {
|
||||
post('/dataset/table/get/' + id, null).then(response => {
|
||||
this.table = response.data
|
||||
this.initTableField(id)
|
||||
})
|
||||
}
|
||||
},
|
||||
initTableField(id) {
|
||||
post('/dataset/table/getFieldsFromDE', this.table).then(response => {
|
||||
this.thumbnails = response.data.thumbnails
|
||||
this.quota = response.data.quota
|
||||
})
|
||||
},
|
||||
click1(item) {
|
||||
// console.log(item);
|
||||
const c = this.view.xaxis.filter(function(ele) {
|
||||
return ele.id === item.id
|
||||
})
|
||||
// console.log(c);
|
||||
if (c && c.length === 0) {
|
||||
this.view.xaxis.push(item)
|
||||
}
|
||||
},
|
||||
click2(item) {
|
||||
// console.log(item);
|
||||
const c = this.view.yaxis.filter(function(ele) {
|
||||
return ele.id === item.id
|
||||
})
|
||||
// console.log(c);
|
||||
if (c && c.length === 0) {
|
||||
this.view.yaxis.push(item)
|
||||
}
|
||||
},
|
||||
clear1(index) {
|
||||
this.view.xaxis.splice(index, 1)
|
||||
},
|
||||
clear2(index) {
|
||||
this.view.yaxis.splice(index, 1)
|
||||
},
|
||||
get(id) {
|
||||
if (id) {
|
||||
post('/chart/view/get/' + id, null).then(response => {
|
||||
this.view = response.data
|
||||
this.view.xaxis = this.view.xaxis ? JSON.parse(this.view.xaxis) : []
|
||||
this.view.yaxis = this.view.yaxis ? JSON.parse(this.view.yaxis) : []
|
||||
})
|
||||
} else {
|
||||
this.view = {}
|
||||
}
|
||||
},
|
||||
save() {
|
||||
const view = JSON.parse(JSON.stringify(this.view))
|
||||
view.id = this.view.id
|
||||
view.sceneId = this.sceneId
|
||||
view.name = this.table.name
|
||||
view.tableId = this.$store.state.chart.tableId
|
||||
view.xaxis = JSON.stringify(view.xaxis)
|
||||
view.yaxis = JSON.stringify(view.yaxis)
|
||||
post('/chart/view/save', view).then(response => {
|
||||
// this.get(response.data.id);
|
||||
this.getData(response.data.id)
|
||||
this.$store.dispatch('chart/setChartSceneData', null)
|
||||
this.$store.dispatch('chart/setChartSceneData', this.sceneId)
|
||||
})
|
||||
},
|
||||
getData(id) {
|
||||
if (id) {
|
||||
post('/chart/view/getData/' + id, null).then(response => {
|
||||
this.view = response.data
|
||||
this.view.xaxis = this.view.xaxis ? JSON.parse(this.view.xaxis) : []
|
||||
this.view.yaxis = this.view.yaxis ? JSON.parse(this.view.yaxis) : []
|
||||
|
||||
const chart = response.data
|
||||
const chart_option = JSON.parse(JSON.stringify(BASE_BAR))
|
||||
// console.log(chart_option);
|
||||
if (chart.data) {
|
||||
chart_option.title.text = chart.title
|
||||
chart_option.xAxis.data = chart.data.x
|
||||
chart.data.series.forEach(function(y) {
|
||||
chart_option.legend.data.push(y.name)
|
||||
chart_option.series.push(y)
|
||||
})
|
||||
}
|
||||
// console.log(chart_option);
|
||||
this.myEcharts(chart_option)
|
||||
})
|
||||
} else {
|
||||
this.view = {}
|
||||
}
|
||||
},
|
||||
|
||||
// 左边往右边拖动时的事件
|
||||
end1(e) {
|
||||
// console.log(e)
|
||||
// var that = this;
|
||||
// var items = this.arr2.filter(function (m) {
|
||||
// return m.id == that.moveId
|
||||
// })
|
||||
// //如果左边
|
||||
// if (items.length < 2) return;
|
||||
// this.arr2.splice(e.newDraggableIndex, 1)
|
||||
},
|
||||
// 右边往左边拖动时的事件
|
||||
end2(e) {
|
||||
// console.log(e)
|
||||
// var that = this;
|
||||
// var items = this.yAxisData.filter(function (m) {
|
||||
// return m.id == that.moveId
|
||||
// })
|
||||
// //如果左边
|
||||
// if (items.length < 2) return;
|
||||
// this.yAxisData.splice(e.newDraggableIndex, 1)
|
||||
},
|
||||
end3(e) {
|
||||
|
||||
},
|
||||
end4(e) {
|
||||
|
||||
},
|
||||
// move回调方法
|
||||
onMove(e, originalEvent) {
|
||||
console.log(e)
|
||||
// this.moveId = e.relatedContext.element.id;
|
||||
// //不允许停靠
|
||||
// if (e.relatedContext.element.id == 1) return false;
|
||||
// //不允许拖拽
|
||||
// if (e.draggedContext.element.id == 4) return false;
|
||||
// if (e.draggedContext.element.id == 11) return false;
|
||||
return true
|
||||
},
|
||||
|
||||
myEcharts(option) {
|
||||
// 基于准备好的dom,初始化echarts实例
|
||||
var myChart = this.$echarts.init(document.getElementById('echart'))
|
||||
// 指定图表的配置项和数据
|
||||
setTimeout(myChart.setOption(option, true), 500)
|
||||
window.onresize = function() {
|
||||
myChart.resize()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.view-list {
|
||||
height: 100%;
|
||||
width: 20%;
|
||||
min-width: 180px;
|
||||
max-width:220px;
|
||||
border: 1px solid #E6E6E6;
|
||||
border-left: 0 solid;
|
||||
}
|
||||
|
||||
.view-list-thumbnails-outline {
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.view-list-thumbnails {
|
||||
width: 100%;
|
||||
padding: 0px 15px 15px 0px;
|
||||
}
|
||||
|
||||
.panel-design {
|
||||
height: 100%;
|
||||
min-width: 500px;
|
||||
border-top: 1px solid #E6E6E6;
|
||||
}
|
||||
|
||||
.panel-design-head {
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.panel-design-show {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
border-top: 1px solid #E6E6E6;
|
||||
}
|
||||
|
||||
.padding-lr {
|
||||
padding: 0 6px;
|
||||
}
|
||||
|
||||
.itxst {
|
||||
margin: 10px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.col {
|
||||
width: 40%;
|
||||
flex: 1;
|
||||
padding: 10px;
|
||||
border: solid 1px #eee;
|
||||
border-radius: 5px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.col + .col {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.item {
|
||||
padding: 2px 12px;
|
||||
margin: 3px 3px 0 3px;
|
||||
border: solid 1px #eee;
|
||||
background-color: #f1f1f1;
|
||||
text-align: left;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.item + .item {
|
||||
border-top: none;
|
||||
margin-top: 3px;
|
||||
}
|
||||
|
||||
.item:hover {
|
||||
background-color: #fdfdfd;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.item-axis {
|
||||
padding: 2px 12px;
|
||||
margin: 3px 3px 0 3px;
|
||||
border: solid 1px #eee;
|
||||
background-color: #f1f1f1;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.item-axis:hover {
|
||||
background-color: #fdfdfd;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.el-form-item {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: 12px;
|
||||
}
|
||||
</style>
|
@ -14,6 +14,12 @@ module.exports = {
|
||||
// 使用mock-server
|
||||
devServer: {
|
||||
port: port,
|
||||
proxy: {
|
||||
['^(?!/login)']: {
|
||||
target: 'http://localhost:8081/',
|
||||
ws: false,
|
||||
}
|
||||
},
|
||||
open: true,
|
||||
overlay: {
|
||||
warnings: false,
|
||||
|
Loading…
Reference in New Issue
Block a user