| | |
| | | |
| | | <style> |
| | | #app { |
| | | width: 100%; |
| | | box-sizing: border-box; |
| | | height: 100vh; |
| | | } |
| | | |
| | | #app:before { |
| | | display: table; |
| | | content: " "; |
| | | } |
| | | </style> |
| | |
| | | font-family: "Microsoft Yahei", arial; |
| | | } |
| | | |
| | | body { |
| | | overflow: hidden; |
| | | } |
| | | |
| | | em, |
| | | strong, |
| | | th, |
| | |
| | | border: 0; |
| | | } |
| | | |
| | | * { |
| | | margin: 0; |
| | | padding: 0; |
| | | border: 0; |
| | | font-size: 100%; |
| | | vertical-align: baseline; |
| | | } |
| | | |
| | | .clearfix:after { |
| | | content: "."; |
| | | display: block; |
| | |
| | | |
| | | .clearfix { |
| | | *zoom: 1; |
| | | } |
| | | |
| | | ::-webkit-scrollbar { |
| | | width: 4px; |
| | | height: 4px; |
| | | } |
| | | |
| | | ::-webkit-scrollbar-thumb { |
| | | background-color: #434b55; |
| | | } |
| | | |
| | | /*basic end*/ |
| | |
| | | box-sizing: border-box; |
| | | } |
| | | |
| | | html { |
| | | overflow-y: scroll; |
| | | overflow-x: hidden; |
| | | } |
| | | |
| | | html, |
| | | body { |
| | | margin: 0; |
| | | color: #FFFFFF; |
| | | margin: 0; |
| | | padding: 0; |
| | | height: 100%; |
| | | min-width: 1024px; |
| | | font-size: 12px; |
| | | } |
| | | |
| | | body { |
| | | background: #171b22 !important; |
| | | -webkit-font-smoothing: antialiased; |
| | | } |
| | | |
| | | /* page animate */ |
| | |
| | | export default { |
| | | name: "abeamProChart", |
| | | chart: "", |
| | | chartData: [], |
| | | chartData: {}, |
| | | props: { |
| | | id: { |
| | | require: true, |
| | |
| | | let dataColor = sendData.color; |
| | | let bgColor = sendData.bgColor; |
| | | let yData = sendData.yData; |
| | | let radius = this.$refs.chart.clientHeight / 3 - 7; |
| | | let radius = (this.$refs.chart.clientHeight / 3 - 7) > 0 ? this.$refs.chart.clientHeight / 3 - 7 : 0; |
| | | let data = sendData.data; |
| | | let max = data[0]; |
| | | data.map(item => { |
| | |
| | | normal: { |
| | | show: true, |
| | | position: 'insideRight', |
| | | fontSize: chartFontsize(20), |
| | | fontSize: chartFontsize(18), |
| | | color: '#021750' |
| | | } |
| | | }, |
| | |
| | | export default { |
| | | name: "imgPieChart", |
| | | chart: "", |
| | | chartData: [], |
| | | chartData: {}, |
| | | props: { |
| | | id: { |
| | | require: true, |
| | |
| | | } |
| | | } |
| | | }, |
| | | data: sendData, |
| | | data: sendData.data, |
| | | zlevel: 1 |
| | | }, |
| | | { |
| | |
| | | export default { |
| | | name: "latticeBar", |
| | | chart: "", |
| | | chartData: [], |
| | | chartData: {}, |
| | | props: { |
| | | id: { |
| | | require: true, |
| | |
| | | export default { |
| | | name: "triangleBarChart", |
| | | chart: "", |
| | | chartData: [], |
| | | chartData: {}, |
| | | props: { |
| | | id: { |
| | | require: true, |
New file |
| | |
| | | <template> |
| | | <div class="nav-main"> |
| | | <canvas id="canvas-2761" style="position: absolute; z-index: -1; left: 0px;"></canvas> |
| | | <span class="nav-span"> |
| | | <a class="nav-link nav-active" aria-current="true"> |
| | | <i class="el-icon-cpu nav-icon"></i>我的可视化 |
| | | </a> |
| | | </span> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | var c = Math.min, |
| | | h = Math.sign, |
| | | m = Math.max, |
| | | n = Math.abs, |
| | | j = .85, |
| | | k = 10, |
| | | l = 4; |
| | | var opt = {}; |
| | | var calcAVGSpeed = function (a) { |
| | | var b = (l * j * a + k * (1 - j) * a) / (k * l * 20); |
| | | return b = m(n(b), 2.5) * h(b), b |
| | | } |
| | | var getCurSpeed = function (a, b) { |
| | | var c = n(a) > n(j * b) ? l * opt.avgSpeed : k * opt.avgSpeed; |
| | | return c |
| | | } |
| | | var _calCurve = function (a, b, c, d, e, f) { |
| | | //console.log(a + f,b,c-f,d,c,d); |
| | | e.bezierCurveTo(a + f, b, c - f, d, c, d) |
| | | } |
| | | var _initCanvas = function (canvas, width, height) { |
| | | var devicePixelRatio = window.devicePixelRatio, |
| | | canvasObj = canvas.getContext("2d"); |
| | | canvas.width = width * devicePixelRatio, canvas.height = height * devicePixelRatio, canvas.style.width = |
| | | width + |
| | | "px", canvas.style.height = height + "px", canvasObj.scale(devicePixelRatio, devicePixelRatio) |
| | | } |
| | | var resize = function () { |
| | | //resize发生 |
| | | opt.timer && cancelAnimationFrame(opt.timer); |
| | | _calcTabs(); |
| | | _initCanvas(opt.canvas, opt.width, opt.height), draw(0) |
| | | } |
| | | var _calcTabs = function () { |
| | | var a = document.querySelectorAll(".nav-main .nav-span"), |
| | | b = [], |
| | | c = 0; |
| | | Array.prototype.forEach.call(a, function (a) { |
| | | b.push(c), c += a.offsetWidth |
| | | }), b[0] = -20, b.push(c), opt.tabWidthList = b, opt.tabHeight = a[0].offsetHeight + 0, opt.height = opt |
| | | .tabHeight + |
| | | 20, opt.width = window.innerWidth |
| | | } |
| | | var _toggle = function (navindex) { |
| | | |
| | | "undefined" !== typeof navindex && navindex !== opt.currentIndex && opt.tabWidthList && opt.tabWidthList |
| | | .length && |
| | | (!opt.animating || navindex !== opt.nextIndex) && (opt.animating = true, opt.distance = opt.tabWidthList[ |
| | | navindex] - opt.tabWidthList[opt.currentIndex], opt.avgSpeed = calcAVGSpeed(opt.distance), opt.curDisX = |
| | | 0, |
| | | opt.nextIndex = navindex) |
| | | return false; |
| | | } |
| | | var _createPattern = function (a) { |
| | | var b = 140, |
| | | c = 63, |
| | | d = 1, |
| | | e = document.createElement("canvas"); |
| | | e.width = b, e.height = c, e.style.width = b / d + "px", e.style.height = c / d + "px"; |
| | | var f = e.getContext("2d"); |
| | | //缩放 宽高 100% |
| | | f.scale(d, d); |
| | | f.lineWidth = .4; |
| | | for (var g = 3, h = .8, j = 1; 30 > j; j++) { |
| | | //设置或返回用于笔触的颜色、渐变或模式 |
| | | f.strokeStyle = "RGBA(22, 120, 160, " + h + ")"; |
| | | //开始一条路径 |
| | | f.beginPath(); |
| | | //把路径移动到画布中的指定点,不创建线条 |
| | | f.moveTo(0, j * g); |
| | | //添加一个新点,然后在画布中创建从该点到最后指定点的线条 |
| | | f.lineTo(b, j * g); |
| | | //绘制已定义的路径 |
| | | f.stroke(); |
| | | //创建从当前点回到起始点的路径 |
| | | f.closePath(); |
| | | 10 < j && (h -= .1); |
| | | } |
| | | var i = a.getContext("2d").createPattern(e, "repeat-x"); |
| | | opt.pattern = i, e = null |
| | | } |
| | | var _drawHightlight = function (a) { |
| | | //a = 0 |
| | | var b = opt.canvas.getContext("2d"), |
| | | d = .3; |
| | | //clearRect 在给定的矩形内清除指定的像素,这里清完了 |
| | | b.clearRect(0, 0, 2 * opt.width, 2 * opt.height); |
| | | b.shadowColor = "rgba(0, 193, 220, 1)"; |
| | | b.shadowBlur = 5; |
| | | b.strokeStyle = "#1558d1"; |
| | | b.lineWidth = .8; |
| | | b.fillStyle = "none"; |
| | | _draw(b, false); |
| | | //这里绘制了外围边框线条 |
| | | //return false; |
| | | var e = b.createLinearGradient(0, 0, opt.width, opt.height), |
| | | f = a - d; |
| | | e.addColorStop(c(1, m(0, 0 + f)), "rgba(0,0,0,0)"); |
| | | e.addColorStop(c(1, m(0, 0 + f + .1)), "#8ED6FF"); |
| | | e.addColorStop(c(1, 0 + f + d), "#8ED6FF"); |
| | | e.addColorStop(c(1, 0 + f + d + .1), "rgba(0,0,0,0)"); |
| | | e.addColorStop(1, "rgba(0,0,0,0)"); |
| | | b.lineWidth = 1.5; |
| | | b.strokeStyle = e; |
| | | b.fillStyle = opt.pattern; |
| | | _draw(b, true) |
| | | } |
| | | var draw = function (a) { |
| | | //console.log(a); |
| | | _drawHightlight(a); |
| | | //return false; |
| | | opt.timer = requestAnimationFrame(function () { |
| | | //console.log(a); |
| | | draw((a + .005) % 1.6) |
| | | }) |
| | | } |
| | | |
| | | var _draw = function (canvasObj, trueorfalse) { |
| | | var navindex = opt.currentIndex, |
| | | tableHeight = opt.tabHeight, |
| | | f = 0, |
| | | g = 40, |
| | | i = 20, |
| | | j = .5, |
| | | k = 2.5, |
| | | l = 0; |
| | | if (canvasObj.beginPath(), canvasObj.moveTo(-50, opt.height + 10), canvasObj.lineTo(-50, tableHeight + j), opt |
| | | .animating) { |
| | | var m = getCurSpeed(opt.curDisX, opt.distance); |
| | | l = c(n(opt.distance), n(opt.curDisX + m)) * h(m) |
| | | } |
| | | if (canvasObj.lineTo(f + opt.tabWidthList[navindex] + l - g / 2, tableHeight + j), _calCurve(f + opt |
| | | .tabWidthList[ |
| | | navindex] + l - g / 2, tableHeight + j, f + opt.tabWidthList[navindex] + l + g / 2, k + j, canvasObj, i |
| | | ), opt |
| | | .animating) { |
| | | var o = opt.tabWidthList[opt.nextIndex + 1] - opt.tabWidthList[opt.nextIndex]; |
| | | canvasObj.lineTo(f + opt.tabWidthList[navindex] + o + l - g / 2, k + j), _calCurve(f + opt.tabWidthList[ |
| | | navindex] + o + l - g / 2, k + j, f + opt.tabWidthList[navindex] + o + l + g / 2, tableHeight + j, |
| | | canvasObj, i) |
| | | } else { |
| | | //lineTO添加一个新点 宽度长度 |
| | | canvasObj.lineTo(f + opt.tabWidthList[navindex + 1] + l - g / 2, k + j); |
| | | _calCurve(f + opt.tabWidthList[navindex + 1] + l - g / 2, k + j, f + opt.tabWidthList[navindex + 1] + l + |
| | | g / |
| | | 2, tableHeight + j, canvasObj, i); |
| | | } |
| | | |
| | | canvasObj.lineTo(opt.width + 10, tableHeight + j); |
| | | canvasObj.lineTo(opt.width + 10, opt.height + 10); |
| | | canvasObj.closePath(); |
| | | canvasObj.stroke(); |
| | | trueorfalse && canvasObj.fill(); |
| | | opt.animating && trueorfalse && (opt.curDisX = l, n(l) >= n(opt.distance) && (opt.animating = false, opt |
| | | .currentIndex = opt.nextIndex)) |
| | | } |
| | | export default { |
| | | data() { |
| | | return { |
| | | |
| | | } |
| | | }, |
| | | mounted() { |
| | | opt.currentIndex = 0; |
| | | opt.canvas = document.getElementById('canvas-2761'); |
| | | _toggle(0); |
| | | _calcTabs(); |
| | | _initCanvas(opt.canvas, opt.width, opt.height); |
| | | _createPattern(opt.canvas); |
| | | draw(0); |
| | | window.onresize = function () { |
| | | resize(); |
| | | }; |
| | | }, |
| | | methods: { |
| | | |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .nav-main { |
| | | z-index: 10; |
| | | display: flex; |
| | | width: 100%; |
| | | margin-top: 250px; |
| | | min-width: 1024px; |
| | | user-select: none; |
| | | } |
| | | |
| | | #canvas-2761 { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | |
| | | .nav-main .nav-icon { |
| | | padding-right: 5px; |
| | | font-size: 20px; |
| | | } |
| | | |
| | | /* .nav-main .nav-span .nav-active, |
| | | .nav-main .nav-span .nav-link:hover { |
| | | color: #00baff !important; |
| | | } */ |
| | | |
| | | .nav-main .nav-span .nav-link { |
| | | text-decoration: none !important; |
| | | display: block; |
| | | color: #fff; |
| | | width: auto; |
| | | min-width: 140px; |
| | | line-height: 40px; |
| | | font-size: 18px; |
| | | text-align: left; |
| | | cursor: pointer; |
| | | padding: 5px 52px 5px; |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <div class="pageWarp"> |
| | | <vue-draggable-resizable :w="340" :h="210" :x="0" :y="0" @dragging="onDrag" @resizing="onResize" |
| | | @refLineParams="getRefLineParams" :parent="true" :debug="false" :is-conflict-check="true" :snap="true" |
| | | :snapTolerance="5" style="transition: none; will-change: transform;"> |
| | | <layout-box title="放电和充电电流"> |
| | | <lattice-bar id="latticeBar" ref="latticeBar"></lattice-bar> |
| | | </layout-box> |
| | | </vue-draggable-resizable> |
| | | <vue-draggable-resizable :w="340" :h="210" :x="360" :y="0" @dragging="onDrag" @resizing="onResize" |
| | | @refLineParams="getRefLineParams" :parent="true" :debug="false" :is-conflict-check="true" :snap="true" |
| | | :snapTolerance="5" style="transition: none; will-change: transform;"> |
| | | <layout-box title="整流器"> |
| | | <img-pie-chart id="ImgPieChart" ref="ImgPieChart"></img-pie-chart> |
| | | </layout-box> |
| | | </vue-draggable-resizable> |
| | | <div class="indexWarp"> |
| | | <div class="datav-header" :style="{backgroundColor:isBgColor?'rgb(23, 27, 34)':''}"> |
| | | <div class="logo"> |
| | | <div class="top-tip"></div> |
| | | </div> |
| | | <div class="user"> |
| | | </div> |
| | | </div> |
| | | <div class="nav-banner"> |
| | | <div class="img"></div> |
| | | <div class="bigText">大屏驾驶舱数据可视化</div> |
| | | <div class="subText">数据管理界面</div> |
| | | </div> |
| | | |
| | | <!-- <div class="chartCon"> |
| | | <layout-box title="整流器"> |
| | | <img-pie-chart id="ImgPieChart" ref="ImgPieChart"></img-pie-chart> |
| | | </layout-box> |
| | | </div> |
| | | <div class="chartCon"> |
| | | <layout-box title="电池组"> |
| | | <triangle-bar-chart id="TriangleBarChart" ref="TriangleBarChart"></triangle-bar-chart> |
| | | </layout-box> |
| | | </div> |
| | | <div class="chartCon"> |
| | | <layout-box title="电池状态"> |
| | | <div class="flexCon"> |
| | | <div class="con"> |
| | | <abeam-pro-chart id="AbeamProChart" ref="AbeamProChart"></abeam-pro-chart> |
| | | <streamer-nav class="streamer-nav" :style="{backgroundColor:isBgColor?'rgb(23, 27, 34)':''}"></streamer-nav> |
| | | <div class="nav-shadow"></div> |
| | | <div class="projectList"> |
| | | <div class="project-header"> |
| | | <div class="text">全部应用</div> |
| | | </div> |
| | | <div class="template-list"> |
| | | <div class="template-item --blank"> |
| | | <div class="template-image"> |
| | | <el-button type="primary" @click="dialogFormVisible = true"> + 创建项目</el-button> |
| | | </div> |
| | | <div class="template-info"> |
| | | <div class="emptyCon">空白画板</div> |
| | | </div> |
| | | </div> |
| | | </layout-box> |
| | | <div class="template-item" v-for="(item,i) in 20" :key="i"> |
| | | <div class="template-image"> |
| | | <div class="screen-edit"> |
| | | <el-tooltip class="item" effect="dark" content="查看" placement="top"> |
| | | <i class="preview el-icon-view"></i> |
| | | </el-tooltip> |
| | | <el-tooltip class="item" effect="dark" content="编辑" placement="top"> |
| | | <i class="preview el-icon-edit editview"></i> |
| | | </el-tooltip> |
| | | </div> |
| | | </div> |
| | | <div class="template-info">空白画板</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="chartCon"> |
| | | <layout-box title="电源状态"> |
| | | <div class="chartItem"> |
| | | <pross-pie-chart id="ProssPieChart1" ref="ProssPieChart1"></pross-pie-chart> |
| | | </div> |
| | | <div class="chartItem"> |
| | | <pross-pie-chart id="ProssPieChart2" ref="ProssPieChart2"></pross-pie-chart> |
| | | </div> |
| | | <div class="chartItem"> |
| | | <pross-pie-chart id="ProssPieChart3" ref="ProssPieChart3"></pross-pie-chart> |
| | | </div> |
| | | <div class="chartItem"> |
| | | <pross-pie-chart id="ProssPieChart4" ref="ProssPieChart4"></pross-pie-chart> |
| | | </div> |
| | | </layout-box> |
| | | </div> --> |
| | | <span class="ref-line v-line" v-for="(item,index) in vLine" :key="index" v-show="item.display" |
| | | :style="{ left: item.position, top: item.origin, height: item.lineLength}"></span> |
| | | <span class="ref-line h-line" v-for="(item,index) in hLine" :key="index" v-show="item.display" |
| | | :style="{ top: item.position, left: item.origin, width: item.lineLength}"></span> |
| | | <el-dialog title="创建数据大屏" width="30%" :visible.sync="dialogFormVisible"> |
| | | <el-form ref="form" :model="panelForm" label-width="100px"> |
| | | <el-form-item label="数据大屏名称"> |
| | | <el-input v-model="panelForm.name" autocomplete="off"></el-input> |
| | | </el-form-item> |
| | | </el-form> |
| | | <div slot="footer" class="dialog-footer"> |
| | | <el-button @click="dialogFormVisible = false">取 消</el-button> |
| | | <el-button type="primary" @click="dialogFormVisible = false">确 定</el-button> |
| | | </div> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import VueDraggableResizable from 'vue-draggable-resizable-gorkys' |
| | | import 'vue-draggable-resizable-gorkys/dist/VueDraggableResizable.css' |
| | | import LayoutBox from "@/components/LayoutBox"; |
| | | import latticeBar from '../components/charts/latticeBar.vue' |
| | | import ImgPieChart from '../components/charts/imgPieChart.vue'; |
| | | // import TriangleBarChart from '../components/charts/triangleBarChart.vue'; |
| | | // import AbeamProChart from '../components/charts/abeamProChart.vue'; |
| | | // import ProssPieChart from '../components/charts/prossPieChart.vue'; |
| | | |
| | | import streamerNav from '../components/streamerNav.vue' |
| | | export default { |
| | | components: { |
| | | VueDraggableResizable, |
| | | LayoutBox, |
| | | latticeBar, |
| | | ImgPieChart, |
| | | // TriangleBarChart, |
| | | // AbeamProChart, |
| | | // ProssPieChart, |
| | | streamerNav, |
| | | }, |
| | | data() { |
| | | return { |
| | | width: 0, |
| | | height: 0, |
| | | x: 0, |
| | | y: 0, |
| | | vLine: [], |
| | | hLine: [] |
| | | scrollTop: null, |
| | | isBgColor: false, |
| | | dialogFormVisible: false, |
| | | panelForm: { |
| | | name: '' |
| | | } |
| | | } |
| | | }, |
| | | mounted() { |
| | | this.$refs.latticeBar.setData({ |
| | | xData: ['高告警数量', '告警总数', '告警总数比例', '告警机房总数', '告警机房数比例'], |
| | | series: [{ |
| | | name: '放电', |
| | | data: [120, 220, 150, 80, 70], |
| | | color: '#90ec7d' |
| | | }, { |
| | | name: '充电', |
| | | data: [80, 160, 120, 310, 50], |
| | | color: '#ff6b6b' |
| | | }] |
| | | }); |
| | | this.$refs.latticeBar.resize(); |
| | | |
| | | this.$refs.ImgPieChart.setData([{ |
| | | value: 30, |
| | | name: '整流器交流异常' |
| | | }, |
| | | { |
| | | value: 22, |
| | | name: '整流器过流' |
| | | }, |
| | | { |
| | | value: 120, |
| | | name: '总故障' |
| | | }, |
| | | { |
| | | value: 50, |
| | | name: '整流器欠压' |
| | | }, |
| | | ]); |
| | | this.$refs.ImgPieChart.resize(); |
| | | // this.$refs.TriangleBarChart.setData({ |
| | | // xData: ['熔断', '电压低', '下电', '充电过流'], |
| | | // data: [35, 72, 55, 45] |
| | | // }); |
| | | // this.$refs.AbeamProChart.setData({ |
| | | // yData: ['浮充数量', '放电数量', '充电数量'], |
| | | // color: ['#f58881', '#b4d465', '#ffcb29'], |
| | | // bgColor: ['rgba(245,136,129,0.35)', 'rgba(255,255,255,0.35)', 'rgba(255,203,41,0.35)'], |
| | | // data: [32, 15, 20] |
| | | // }); |
| | | // this.$refs.ProssPieChart1.setData({ |
| | | // title: '交流停电数量', |
| | | // data: 56, |
| | | // color: '#37a9b3' |
| | | // }); |
| | | // this.$refs.ProssPieChart2.setData({ |
| | | // title: '机房告警数', |
| | | // data: 12, |
| | | // color: '#f3535f' |
| | | // }); |
| | | // this.$refs.ProssPieChart3.setData({ |
| | | // title: '直流电压超限数', |
| | | // data: 21, |
| | | // unit: '%', |
| | | // color: '#ff8b00' |
| | | // }); |
| | | // this.$refs.ProssPieChart4.setData({ |
| | | // title: '负载熔断数量', |
| | | // data: 8, |
| | | // color: '#757ffb' |
| | | // }); |
| | | window.addEventListener('scroll', () => { |
| | | this.scrollTop = document.documentElement.scrollTop || document.body.scrollTop; |
| | | if (this.scrollTop > 260) { |
| | | this.isBgColor = true |
| | | } else { |
| | | this.isBgColor = false |
| | | } |
| | | }) |
| | | }, |
| | | methods: { |
| | | onResize: function (x, y, width, height) { |
| | | console.log(width) |
| | | console.log(height) |
| | | this.$refs.latticeBar.resize(); |
| | | this.$refs.ImgPieChart.resize(); |
| | | this.x = x |
| | | this.y = y |
| | | this.width = width |
| | | this.height = height; |
| | | }, |
| | | onDrag: function (x, y) { |
| | | this.x = x |
| | | this.y = y |
| | | }, |
| | | // 辅助线回调事件 |
| | | getRefLineParams(params) { |
| | | const { |
| | | vLine, |
| | | hLine |
| | | } = params |
| | | this.vLine = vLine |
| | | this.hLine = hLine |
| | | } |
| | | } |
| | | methods: {} |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .pageWarp { |
| | | width: 100%; |
| | | height: 100vh; |
| | | background-color: #031D67; |
| | | background-image: url("../assets/images/bg-box.png"); |
| | | } |
| | | |
| | | .chartCon { |
| | | width: 33.33%; |
| | | height: 50%; |
| | | padding: 10px; |
| | | float: left; |
| | | box-sizing: border-box; |
| | | } |
| | | |
| | | .flexCon { |
| | | .indexWarp { |
| | | width: 100%; |
| | | height: 100%; |
| | | background: #171b22 !important; |
| | | -webkit-font-smoothing: antialiased; |
| | | } |
| | | |
| | | .datav-header { |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | } |
| | | |
| | | .flexCon .con { |
| | | position: fixed; |
| | | top: 0; |
| | | justify-content: space-between; |
| | | z-index: 999; |
| | | width: 100%; |
| | | height: 60%; |
| | | height: 38px; |
| | | padding: 0 10px; |
| | | background-image: linear-gradient(0deg, rgba(0, 0, 0, 0) 19%, #171717 100%); |
| | | } |
| | | |
| | | .chartCon .chartItem { |
| | | width: 50%; |
| | | height: 48%; |
| | | float: left; |
| | | margin-bottom: 2%; |
| | | .nav-banner { |
| | | display: flex; |
| | | position: absolute; |
| | | top: 0; |
| | | justify-content: center; |
| | | flex-direction: column; |
| | | background: #171b22; |
| | | height: 360px; |
| | | transition: .5s height cubic-bezier(.65, .05, .36, 1); |
| | | width: 100%; |
| | | } |
| | | |
| | | .nav-banner .img { |
| | | position: absolute; |
| | | width: 100%; |
| | | height: 360px; |
| | | background-image: url('../assets/images/setting-page-bg.png'); |
| | | background-size: cover; |
| | | background-position: center; |
| | | transition: .5s opacity cubic-bezier(.4, 0, 1, 1); |
| | | z-index: 1; |
| | | } |
| | | |
| | | .nav-banner .bigText { |
| | | margin-top: -80px; |
| | | width: 700px; |
| | | font-size: 52px; |
| | | letter-spacing: 8px; |
| | | background-image: -webkit-linear-gradient(left, #a0e5ff, #1bc5f7); |
| | | -webkit-background-clip: text; |
| | | -webkit-text-fill-color: transparent; |
| | | font-weight: bold; |
| | | z-index: 2; |
| | | padding-left: 60px; |
| | | } |
| | | |
| | | .nav-banner .subText { |
| | | font-size: 26px; |
| | | color: #95b4c3; |
| | | letter-spacing: 5px; |
| | | margin-top: 6px; |
| | | z-index: 2; |
| | | padding-left: 60px; |
| | | } |
| | | |
| | | .nav-shadow { |
| | | background: linear-gradient(180deg, transparent, #171b22); |
| | | height: 50px; |
| | | position: relative; |
| | | width: 100%; |
| | | z-index: 1; |
| | | } |
| | | |
| | | .streamer-nav { |
| | | top: 38px; |
| | | left: 0; |
| | | position: sticky; |
| | | } |
| | | |
| | | .projectList { |
| | | padding: 0 30px; |
| | | background: #171b22; |
| | | z-index: 1; |
| | | } |
| | | |
| | | .projectList .project-header { |
| | | position: sticky; |
| | | top: 80px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | border-bottom: 1px solid #434b55; |
| | | padding-bottom: 5px; |
| | | padding-top: 10px; |
| | | height: 56px; |
| | | background: #171b22; |
| | | z-index: 1; |
| | | min-width: 1024px; |
| | | } |
| | | |
| | | .projectList .project-header .text { |
| | | max-width: 200px; |
| | | font-size: 14px; |
| | | color: #2681ff; |
| | | padding: 0 10px; |
| | | border-left: 2px solid #2681ff; |
| | | text-overflow: ellipsis; |
| | | overflow: hidden; |
| | | white-space: nowrap; |
| | | } |
| | | |
| | | .template-list { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | color: #fff; |
| | | font-size: 12px; |
| | | margin: 0 -16px; |
| | | } |
| | | |
| | | .template-item { |
| | | width: 345px; |
| | | height: 230px; |
| | | box-shadow: 0 0 10px -6px #000; |
| | | border: 1px solid #3a4659; |
| | | margin: 16px; |
| | | transition: .2s; |
| | | outline: 1px solid transparent; |
| | | cursor: default; |
| | | position: relative; |
| | | } |
| | | |
| | | .template-list .template-item.--blank, |
| | | .template-list .template-item:hover { |
| | | outline: 1px solid #2681ff; |
| | | } |
| | | |
| | | .template-list .template-image { |
| | | width: 100%; |
| | | height: 183px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | transition: .2s; |
| | | position: relative; |
| | | } |
| | | |
| | | .template-list .template-item.--blank .template-image { |
| | | box-shadow: inset 0 0 46px 0 rgba(136, 215, 255, .29); |
| | | } |
| | | |
| | | .template-list .template-info { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | padding: 10px; |
| | | height: 44px; |
| | | background: #1d262e; |
| | | transition: .2s; |
| | | } |
| | | |
| | | .template-item.--blank .template-info { |
| | | justify-content: center; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .template-item .template-info .emptyCon { |
| | | width: 100%; |
| | | text-align: center; |
| | | } |
| | | |
| | | .template-list .template-item.--blank .template-info { |
| | | border-top: 1px solid var(--datav-main-color); |
| | | } |
| | | |
| | | .template-item .screen-edit { |
| | | position: absolute; |
| | | opacity: 0; |
| | | display: flex; |
| | | width: 100%; |
| | | height: 100%; |
| | | pointer-events: none; |
| | | align-items: center; |
| | | justify-content: center; |
| | | transition: opacity .2s; |
| | | background: rgba(0, 0, 0, .81); |
| | | } |
| | | |
| | | .template-item .screen-edit .preview { |
| | | position: absolute; |
| | | top: 10px; |
| | | right: 55px; |
| | | color: #fff; |
| | | cursor: pointer; |
| | | transition: color .2s; |
| | | padding: 5px; |
| | | font-size: 24px; |
| | | } |
| | | |
| | | .template-item .screen-edit .preview:hover { |
| | | color: #2681ff; |
| | | } |
| | | |
| | | .template-item .screen-edit .editview { |
| | | right: 15px; |
| | | } |
| | | |
| | | .template-item:hover .screen-edit { |
| | | opacity: 1; |
| | | pointer-events: all; |
| | | } |
| | | </style> |
New file |
| | |
| | | <template> |
| | | <div class="pageWarp"> |
| | | <vue-draggable-resizable :w="item.w" :h="item.h" :x="item.x" :y="item.y" @dragging="onDrag" @resizing="onResize" |
| | | @refLineParams="getRefLineParams" :parent="true" :debug="false" :snap="true" :snapTolerance="5" |
| | | style="transition: none; will-change: transform;" @activated="onActived(item)" v-for="(item,i) in layOut.children" |
| | | :key="i"> |
| | | <div @contextmenu.prevent.stop="openMenu(item,$event)" style="width:100%;height:100%;"> |
| | | <layout-box :title="item.name"> |
| | | <div v-if="item.type=='latticeBar'" style="width:100%;height:100%"> |
| | | <lattice-bar :id="'chart'+item.id" :ref="'chart'+item.id"></lattice-bar> |
| | | </div> |
| | | <div v-else-if="item.type=='ImgPieChart'" style="width:100%;height:100%"> |
| | | <img-pie-chart :id="'chart'+item.id" :ref="'chart'+item.id"></img-pie-chart> |
| | | </div> |
| | | <div v-else-if="item.type=='TriangleBarChart'" style="width:100%;height:100%"> |
| | | <triangle-bar-chart :id="'chart'+item.id" :ref="'chart'+item.id"></triangle-bar-chart> |
| | | </div> |
| | | <div v-else-if="item.type=='AbeamProChart'" style="width:100%;height:100%"> |
| | | <div class="flexCon"> |
| | | <div class="con"> |
| | | <abeam-pro-chart :id="'chart'+item.id" :ref="'chart'+item.id"></abeam-pro-chart> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </layout-box> |
| | | </div> |
| | | </vue-draggable-resizable> |
| | | |
| | | <!--<div class="chartCon"> |
| | | <layout-box title="电源状态"> |
| | | <div class="chartItem"> |
| | | <pross-pie-chart id="ProssPieChart1" ref="ProssPieChart1"></pross-pie-chart> |
| | | </div> |
| | | <div class="chartItem"> |
| | | <pross-pie-chart id="ProssPieChart2" ref="ProssPieChart2"></pross-pie-chart> |
| | | </div> |
| | | <div class="chartItem"> |
| | | <pross-pie-chart id="ProssPieChart3" ref="ProssPieChart3"></pross-pie-chart> |
| | | </div> |
| | | <div class="chartItem"> |
| | | <pross-pie-chart id="ProssPieChart4" ref="ProssPieChart4"></pross-pie-chart> |
| | | </div> |
| | | </layout-box> |
| | | </div> --> |
| | | <span class="ref-line v-line" v-for="(item,index) in vLine" :key="'vLine'+index" v-show="item.display" |
| | | :style="{ left: item.position, top: item.origin, height: item.lineLength}"></span> |
| | | <span class="ref-line h-line" v-for="(item,index) in hLine" :key="'hLine'+index" v-show="item.display" |
| | | :style="{ top: item.position, left: item.origin, width: item.lineLength}"></span> |
| | | <ul v-show="rightMenuVisible" :style="{left:contextmenuLeft+'px',top:contextmenuTop+'px'}" class="contextmenu"> |
| | | <li><i class="el-icon-refresh-right"></i> 重新加载</li> |
| | | <li @click="removeModular"><i class="el-icon-delete"></i> 删除</li> |
| | | </ul> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import VueDraggableResizable from 'vue-draggable-resizable-gorkys' |
| | | import 'vue-draggable-resizable-gorkys/dist/VueDraggableResizable.css' |
| | | import LayoutBox from "@/components/LayoutBox"; |
| | | import latticeBar from '../components/charts/latticeBar.vue' |
| | | import ImgPieChart from '../components/charts/imgPieChart.vue'; |
| | | import TriangleBarChart from '../components/charts/triangleBarChart.vue'; |
| | | import AbeamProChart from '../components/charts/abeamProChart.vue'; |
| | | // import ProssPieChart from '../components/charts/prossPieChart.vue'; |
| | | |
| | | export default { |
| | | components: { |
| | | VueDraggableResizable, |
| | | LayoutBox, |
| | | latticeBar, |
| | | ImgPieChart, |
| | | TriangleBarChart, |
| | | AbeamProChart, |
| | | // ProssPieChart, |
| | | }, |
| | | data() { |
| | | return { |
| | | draggableActived: null, |
| | | layOut: { |
| | | name: '', |
| | | id: '', |
| | | children: [{ |
| | | name: '放电和充电电流', |
| | | id: 1, |
| | | w: 340, |
| | | h: 210, |
| | | x: 0, |
| | | y: 0, |
| | | type: 'latticeBar', |
| | | setData: { |
| | | xData: ['高告警数量', '告警总数', '告警总数比例', '告警机房总数', '告警机房数比例'], |
| | | series: [{ |
| | | name: '放电', |
| | | data: [120, 220, 150, 80, 70], |
| | | color: '#90ec7d' |
| | | }, { |
| | | name: '充电', |
| | | data: [80, 160, 120, 310, 50], |
| | | color: '#ff6b6b' |
| | | }] |
| | | } |
| | | }, { |
| | | name: '整流器', |
| | | id: 2, |
| | | w: 340, |
| | | h: 210, |
| | | x: 360, |
| | | y: 0, |
| | | type: 'ImgPieChart', |
| | | setData: { |
| | | data: [{ |
| | | value: 30, |
| | | name: '整流器交流异常' |
| | | }, |
| | | { |
| | | value: 22, |
| | | name: '整流器过流' |
| | | }, |
| | | { |
| | | value: 120, |
| | | name: '总故障' |
| | | }, |
| | | { |
| | | value: 50, |
| | | name: '整流器欠压' |
| | | }, |
| | | ] |
| | | } |
| | | }, { |
| | | name: '电池组', |
| | | id: 3, |
| | | w: 340, |
| | | h: 210, |
| | | x: 720, |
| | | y: 0, |
| | | type: 'TriangleBarChart', |
| | | setData: { |
| | | xData: ['熔断', '电压低', '下电', '充电过流'], |
| | | data: [35, 72, 55, 45] |
| | | } |
| | | }, { |
| | | name: '电池状态', |
| | | id: 4, |
| | | w: 340, |
| | | h: 210, |
| | | x: 1080, |
| | | y: 0, |
| | | type: 'AbeamProChart', |
| | | setData: { |
| | | yData: ['浮充数量', '放电数量', '充电数量'], |
| | | color: ['#f58881', '#b4d465', '#ffcb29'], |
| | | bgColor: ['rgba(245,136,129,0.35)', 'rgba(255,255,255,0.35)', 'rgba(255,203,41,0.35)'], |
| | | data: [32, 15, 20] |
| | | } |
| | | }] |
| | | }, |
| | | vLine: [], |
| | | hLine: [], |
| | | rightMenuVisible: false, |
| | | contextmenuTop: 0, |
| | | contextmenuLeft: 0, |
| | | clickItem: null, |
| | | } |
| | | }, |
| | | watch: { |
| | | rightMenuVisible(value) { |
| | | if (value) { |
| | | document.body.addEventListener('click', this.closeMenu) |
| | | } else { |
| | | document.body.removeEventListener('click', this.closeMenu) |
| | | } |
| | | } |
| | | }, |
| | | mounted() { |
| | | //禁止鼠标右键菜单 |
| | | document.oncontextmenu = function () { |
| | | return false; |
| | | }; |
| | | this.loadLayout(); |
| | | // this.$refs.ProssPieChart1.setData({ |
| | | // title: '交流停电数量', |
| | | // data: 56, |
| | | // color: '#37a9b3' |
| | | // }); |
| | | }, |
| | | methods: { |
| | | // 选中要调整的面板时 |
| | | onActived(panel) { |
| | | this.draggableActived = panel; |
| | | }, |
| | | //面板改变大小时 |
| | | onResize(x, y, width, height) { |
| | | this.layOut.children.filter((card) => { |
| | | if (this.draggableActived.id === card.id) { |
| | | card.w = width; |
| | | card.h = height; |
| | | card.x = x; |
| | | card.y = y; |
| | | let nowChart = `chart${this.draggableActived.id}`; |
| | | this.$refs[nowChart][0].resize(); |
| | | } |
| | | return true; |
| | | }); |
| | | }, |
| | | //面板改变位置时 |
| | | onDrag(x, y) { |
| | | this.layOut.children.filter((card) => { |
| | | if (this.draggableActived.id === card.id) { |
| | | card.x = x; |
| | | card.y = y; |
| | | } |
| | | return true; |
| | | }); |
| | | }, |
| | | // 辅助线回调事件 |
| | | getRefLineParams(params) { |
| | | const { |
| | | vLine, |
| | | hLine |
| | | } = params |
| | | this.vLine = vLine |
| | | this.hLine = hLine |
| | | }, |
| | | //模块右键菜单打开 |
| | | openMenu(clickItem, e) { |
| | | this.clickItem = clickItem; |
| | | const menuMinWidth = 105 |
| | | const offsetLeft = this.$el.getBoundingClientRect().left // container margin left |
| | | const offsetWidth = this.$el.offsetWidth // container width |
| | | const maxLeft = offsetWidth - menuMinWidth // left boundary |
| | | const left = e.clientX - offsetLeft // margin right |
| | | if (left > maxLeft) { |
| | | this.contextmenuLeft = maxLeft |
| | | } else { |
| | | this.contextmenuLeft = left |
| | | } |
| | | this.contextmenuTop = e.clientY - 60 |
| | | this.rightMenuVisible = true |
| | | }, |
| | | //模块右键菜单关闭 |
| | | closeMenu() { |
| | | this.rightMenuVisible = false |
| | | }, |
| | | //删除大屏数据模块 |
| | | removeModular() { |
| | | this.layOut.children.map((item, i) => { |
| | | if (item.name == this.clickItem.name) { |
| | | this.layOut.children.splice(i, 1); |
| | | } |
| | | }) |
| | | }, |
| | | // 加载布局数据 |
| | | loadLayout() { |
| | | this.layOut.children.map((item) => { |
| | | let nowChart = `chart${item.id}`; |
| | | this.$refs[nowChart][0].setData(item.setData); |
| | | this.$refs[nowChart][0].resize(); |
| | | }) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .pageWarp { |
| | | width: 100%; |
| | | height: 100vh; |
| | | background-color: #031D67; |
| | | background-image: url("../assets/images/bg-box.png"); |
| | | } |
| | | |
| | | .chartCon { |
| | | width: 33.33%; |
| | | height: 50%; |
| | | padding: 10px; |
| | | float: left; |
| | | box-sizing: border-box; |
| | | } |
| | | |
| | | .flexCon { |
| | | width: 100%; |
| | | height: 100%; |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | } |
| | | |
| | | .flexCon .con { |
| | | width: 100%; |
| | | height: 60%; |
| | | } |
| | | |
| | | .chartCon .chartItem { |
| | | width: 50%; |
| | | height: 48%; |
| | | float: left; |
| | | margin-bottom: 2%; |
| | | } |
| | | |
| | | .contextmenu { |
| | | margin: 0; |
| | | background: #27343e; |
| | | z-index: 3000; |
| | | position: absolute; |
| | | list-style-type: none; |
| | | padding: 5px 0; |
| | | border-radius: 4px; |
| | | font-size: 12px; |
| | | font-weight: 400; |
| | | color: #bcc9d4; |
| | | box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, 0.3); |
| | | } |
| | | |
| | | .contextmenu li { |
| | | padding: 0 6px; |
| | | line-height: 28px; |
| | | height: 28px; |
| | | border-left: 2px solid transparent; |
| | | cursor: pointer; |
| | | overflow: hidden; |
| | | padding-right: 3em; |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .contextmenu li i { |
| | | margin-right: 8px; |
| | | } |
| | | |
| | | .contextmenu li:hover { |
| | | background-color: #1d262e; |
| | | color: #2681ff; |
| | | border-left: 2px solid #2681ff; |
| | | } |
| | | |
| | | .flexCon { |
| | | width: 100%; |
| | | height: 100%; |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | } |
| | | |
| | | .flexCon .con { |
| | | width: 100%; |
| | | height: 60%; |
| | | } |
| | | </style> |
| | |
| | | path: '/', |
| | | meta: {}, |
| | | component: (resolve) => require(['@/pages/index.vue'], resolve) |
| | | }, { |
| | | path: '/settingPage', |
| | | meta: {}, |
| | | component: (resolve) => require(['@/pages/settingPage.vue'], resolve) |
| | | }, ]; |