Browse Source

feat:看板调整;

fuyang
YOU 9 months ago
parent
commit
8e4bad6422
  1. 4
      public/cdn/normal_bg.svg
  2. 0
      src/assets/images/njhl/block_1.png
  3. BIN
      src/assets/images/njhl/block_2.png
  4. 40
      src/service/dragStretchService.ts
  5. 18
      src/service/utilService.ts
  6. 137
      src/views/dashboard/common/model.ts
  7. 2
      src/views/dashboard/common/style.ts
  8. 22
      src/views/dashboard/comp/block.vue
  9. 54
      src/views/dashboard/main.vue

4
public/cdn/normal_bg.svg
File diff suppressed because it is too large
View File

0
src/assets/images/njhl/block.png → src/assets/images/njhl/block_1.png

Before

Width: 484  |  Height: 318  |  Size: 3.6 KiB

After

Width: 484  |  Height: 318  |  Size: 3.6 KiB

BIN
src/assets/images/njhl/block_2.png

After

Width: 895  |  Height: 318  |  Size: 16 KiB

40
src/service/dragStretchService.ts

@ -1,4 +1,4 @@
import { IObject } from "@/types/interface";
import { IObject } from '@/types/interface';
class DragStretchService { class DragStretchService {
target: HTMLElement; target: HTMLElement;
@ -20,7 +20,7 @@ class DragStretchService {
this.sourceX = 0; this.sourceX = 0;
this.sourceY = 0; this.sourceY = 0;
this.distanceY = opt?.distanceY || 0; this.distanceY = opt?.distanceY || 0;
this.scale = opt?.scale || "1";
this.scale = opt?.scale || '1';
this.transform = this.getTransform(); this.transform = this.getTransform();
this.init(); this.init();
} }
@ -29,7 +29,7 @@ class DragStretchService {
return { return {
distanceX: this.distanceX, distanceX: this.distanceX,
distanceY: this.distanceY, distanceY: this.distanceY,
scale: this.scale
scale: this.scale,
}; };
} }
@ -39,10 +39,10 @@ class DragStretchService {
: this.target.currentStyle[property]; : this.target.currentStyle[property];
} }
getTransform() { getTransform() {
let transform = "",
let transform = '',
i = 0; i = 0;
const divStyle = document.createElement("div").style,
transformArr = ["transform", "webkitTransform", "MozTransform", "msTransform", "OTransform"],
const divStyle = document.createElement('div').style,
transformArr = ['transform', 'webkitTransform', 'MozTransform', 'msTransform', 'OTransform'],
len = transformArr.length; len = transformArr.length;
for (; i < len; i++) { for (; i < len; i++) {
@ -57,18 +57,18 @@ class DragStretchService {
let pos = { x: 0, y: 0 }; let pos = { x: 0, y: 0 };
const transformValue = this.getStyle(this.transform); const transformValue = this.getStyle(this.transform);
if (transformValue == "none") {
this.target.style[this.transform] = "translate(0, 0) scale(1)";
if (transformValue == 'none') {
this.target.style[this.transform] = 'translate(0, 0) scale(1)';
} }
const matrixReg = /^matrix\((?:[-\d.]+,\s*){4}([-\d.]+),\s*([-\d.]+)\)$/; const matrixReg = /^matrix\((?:[-\d.]+,\s*){4}([-\d.]+),\s*([-\d.]+)\)$/;
const scaleReg = /\d+(?:\.\d+)?(?=,)/; const scaleReg = /\d+(?:\.\d+)?(?=,)/;
const temp = transformValue.match(matrixReg); const temp = transformValue.match(matrixReg);
const scale = transformValue.match(scaleReg); const scale = transformValue.match(scaleReg);
console.log(scale, "scale");
console.log(scale, 'scale');
pos = { pos = {
x: parseInt(temp[1].trim()), x: parseInt(temp[1].trim()),
y: parseInt(temp[2].trim()), y: parseInt(temp[2].trim()),
scale: parseFloat(scale[0])
scale: parseFloat(scale[0]),
}; };
return pos; return pos;
@ -83,8 +83,8 @@ class DragStretchService {
this.sourceX = pos.x; this.sourceX = pos.x;
this.sourceY = pos.y; this.sourceY = pos.y;
this.scale = pos.scale; this.scale = pos.scale;
document.addEventListener("mousemove", move, false);
document.addEventListener("mouseup", end, false);
document.addEventListener('mousemove', move, false);
document.addEventListener('mouseup', end, false);
}; };
const move = (event: MouseEvent) => { const move = (event: MouseEvent) => {
@ -98,12 +98,12 @@ class DragStretchService {
}; };
const end = () => { const end = () => {
document.removeEventListener("mousemove", move);
document.removeEventListener("mouseup", end);
document.removeEventListener('mousemove', move);
document.removeEventListener('mouseup', end);
// do other things // do other things
}; };
this.target.addEventListener("mousedown", start, false);
this.target.addEventListener('mousedown', start, false);
} }
// 初始化 // 初始化
init() { init() {
@ -121,7 +121,7 @@ class DragStretchService {
const { clientWidth, clientHeight } = parentNode as HTMLElement; const { clientWidth, clientHeight } = parentNode as HTMLElement;
return { return {
clientWidth, clientWidth,
clientHeight
clientHeight,
}; };
} }
return {}; return {};
@ -192,7 +192,7 @@ class DragStretchService {
// } // }
stretch() { stretch() {
this.target.addEventListener("mousewheel", (e: Event) => {
this.target.addEventListener('mousewheel', (e: Event) => {
const ev: IObject = e; const ev: IObject = e;
const up = ev.wheelDelta ? ev.wheelDelta >= 0 : ev.detail <= 0; // 定义一个标志,当滚轮向下滚时,执行一些操作 const up = ev.wheelDelta ? ev.wheelDelta >= 0 : ev.detail <= 0; // 定义一个标志,当滚轮向下滚时,执行一些操作
@ -206,7 +206,7 @@ class DragStretchService {
this.setTransform(); this.setTransform();
} else { } else {
if (+this.scale <= 0.1) { if (+this.scale <= 0.1) {
this.scale = "0.1";
this.scale = '0.1';
} else { } else {
this.scale = (parseFloat(this.scale) - this.options.ratio).toFixed(2); this.scale = (parseFloat(this.scale) - this.options.ratio).toFixed(2);
} }
@ -222,7 +222,7 @@ class DragStretchService {
} }
setTransform() { setTransform() {
console.log(this.scale, "this.scale");
console.log(this.scale, 'this.scale');
//this.target.style.transform = `translate(${this.distanceX}px, ${this.distanceY}px)`; //this.target.style.transform = `translate(${this.distanceX}px, ${this.distanceY}px)`;
this.target.style.transform = `translate(${this.distanceX}px, ${this.distanceY}px) scale(${this.scale})`; this.target.style.transform = `translate(${this.distanceX}px, ${this.distanceY}px) scale(${this.scale})`;
//this.target.style.transformOrigin = "0 0"; //this.target.style.transformOrigin = "0 0";
@ -231,7 +231,7 @@ class DragStretchService {
reset() { reset() {
this.distanceX = 0; this.distanceX = 0;
this.distanceY = 0; this.distanceY = 0;
this.scale = "1";
this.scale = this.options.scale || '1';
this.setTransform(); this.setTransform();
} }
} }

18
src/service/utilService.ts

@ -433,8 +433,6 @@ class UtilService {
return arr; return arr;
} }
findParentElByCondition(element: any, condition: IFunction) { findParentElByCondition(element: any, condition: IFunction) {
let currentElement = element; let currentElement = element;
while (currentElement) { while (currentElement) {
@ -446,6 +444,22 @@ class UtilService {
return null; return null;
} }
hexToRgba(h: string, alpha = 1): string {
// 去除可能存在的 # 符号
let hex = h.replace('#', '');
// 如果是 3 位的十六进制颜色值,扩展为 6 位
if (hex.length === 3) {
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
}
// 解析红、绿、蓝分量
const r = parseInt(hex.substring(0, 2), 16);
const g = parseInt(hex.substring(2, 4), 16);
const b = parseInt(hex.substring(4, 6), 16);
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
}
} }
export default new UtilService(); export default new UtilService();

137
src/views/dashboard/common/model.ts

@ -1,7 +1,7 @@
import dateService from '@/service/dateService'; import dateService from '@/service/dateService';
import utilService from '@/service/utilService'; import utilService from '@/service/utilService';
import { IObject } from '@/types/interface'; import { IObject } from '@/types/interface';
import { smooth } from '@antv/x6/lib/registry/connector/smooth';
import { Legend } from 'highcharts';
import moment from 'moment'; import moment from 'moment';
export const monthEnergyUsageTrend = (data = []): IObject => { export const monthEnergyUsageTrend = (data = []): IObject => {
@ -257,7 +257,7 @@ export const costStatistic = (data = []): IObject => {
}; };
}; };
export const usageRanking = (data = []): IObject => {
export const usageRanking = (data = [], unit?: string): IObject => {
let yAxisData = []; let yAxisData = [];
let seriesData = []; let seriesData = [];
if (utilService.isValidArray(data)) { if (utilService.isValidArray(data)) {
@ -271,6 +271,20 @@ export const usageRanking = (data = []): IObject => {
axisPointer: { axisPointer: {
type: 'shadow', type: 'shadow',
}, },
formatter: (params: Array<IObject>) => {
if (utilService.isValidArray(params)) {
const [first] = params;
const { axisValue } = first;
let str = `<div>${axisValue}</div><div>`;
for (const item of params) {
const { data } = item;
str += `<div style="display: flex;justify-content: space-between;"><span>${item.marker}</span> <span><b>${data}</b> ${unit}</span></div>`;
}
return str + '</div>';
}
return '';
},
}, },
grid: { grid: {
bottom: 35, bottom: 35,
@ -336,7 +350,23 @@ export const elecPayload = (data = []): IObject => {
top: 30, top: 30,
left: 40, left: 40,
}, },
tooltip: { trigger: 'axis' },
tooltip: {
trigger: 'axis',
formatter: (params: Array<IObject>) => {
if (utilService.isValidArray(params)) {
const [first] = params;
const { axisValue } = first;
let str = `<div>${moment().format('YYYY-MM-DD')} ${axisValue}时</div><div>`;
for (const item of params) {
const { seriesName, data } = item;
str += `<div style="display: flex;justify-content: space-between;"><span>${item.marker}电力负荷:</span> <span><b>${data}</b> kWh</span></div>`;
}
return str + '</div>';
}
return '';
},
},
xAxis: { xAxis: {
name: '(时)', name: '(时)',
type: 'category', type: 'category',
@ -376,3 +406,104 @@ export const elecPayload = (data = []): IObject => {
], ],
}; };
}; };
export const energyUsageDistribution = (data = []): IObject => {
const length = 24;
const xAxisData = Array.from({ length }, (x, i) => i);
const seriesData = [];
if (utilService.isValidArray(data)) {
for (const day of xAxisData) {
let val;
for (const item of data) {
if (
typeof item.date === 'string' &&
item.date.includes(`${new dateService().addZero(day)}:00:00`)
) {
val = item.value;
}
}
}
}
const energyMap: Array<IObject> = [
{ key: 'A29hh', name: '电用量', unit: '万kWh', color: '#0084FF' },
{ key: 'E3hh', name: '蒸汽用量', unit: 't', color: '#FFE777' },
{ key: 'B2hh', name: '水用量', unit: 't', color: '#37FFC9' },
{ key: 'C2hh', name: '压缩空气用量', unit: 'Nm³', color: '#19D6FF' },
];
for (const key in data) {
const item = data[key] || [];
if (utilService.isValidArray(item)) {
const [first] = item;
const val = utilService.getTargetItemByKey(energyMap, first.attrKey, 'key');
const color = val.color;
seriesData.push({
name: val.name,
data: item.map((v) => v.val),
type: 'line',
smooth: true,
lineStyle: { width: 1, color },
areaStyle: {
opacity: 0.8,
color: new window.echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ color: utilService.hexToRgba(color, 0.7), offset: 0 },
{ color: utilService.hexToRgba(color, 0.2), offset: 1 },
]),
},
emphasis: {
focus: 'series',
},
showSymbol: false,
connectNulls: true,
});
}
}
const yesterday = moment().subtract(1, 'days').format('YYYY-MM-DD');
return {
grid: {
bottom: 45,
top: 30,
left: 40,
},
tooltip: {
trigger: 'axis',
formatter: (params: Array<IObject>) => {
if (utilService.isValidArray(params)) {
const [first] = params;
const { axisValue } = first;
let str = `<div>${yesterday} ${axisValue}时</div><div>`;
for (const item of params) {
const { seriesName, data } = item;
str += `<div style="display: flex;justify-content: space-between;"><span>${
item.marker
}${seriesName}</span> <span><b>${data}</b> ${
utilService.getTargetItemByKey(energyMap, seriesName, 'name')?.unit || ''
}</span></div>`;
}
return str + '</div>';
}
return '';
},
},
legend: {
right: 15,
textStyle: {
color: '#fff',
},
},
xAxis: {
name: '(时)',
type: 'category',
data: xAxisData,
axisLine: { lineStyle: { color: '#fff' } },
axisLabel: { fontSize: 10 },
},
yAxis: {
type: 'value',
axisLine: { lineStyle: { color: '#fff' }, show: true },
splitLine: { lineStyle: { type: 'dashed', color: 'rgba(255,255,255,0.3)' } },
},
series: seriesData,
};
};

2
src/views/dashboard/common/style.ts

@ -285,5 +285,5 @@ export const init = (state: IObject, target: HTMLElement): void => {
initLine(); initLine();
initCloseToolTip(); initCloseToolTip();
state.dragStretch = new dragStretchService(target);
state.dragStretch = new dragStretchService(target, state.opt);
}; };

22
src/views/dashboard/comp/block.vue

@ -1,5 +1,5 @@
<template> <template>
<div class="block" ref="blockRef">
<div class="block" ref="blockRef" :style="`background: url(${$util.getImg('/src/assets/images/njhl/block_' + sizeType + '.png')}) no-repeat center`">
<div :class="['title']"> <div :class="['title']">
<span>{{ item.title || '' }}</span> <span>{{ item.title || '' }}</span>
@ -15,22 +15,26 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { computed, defineComponent, h, nextTick, onMounted, reactive, toRefs } from 'vue';
import { computed, defineComponent, nextTick, onMounted, reactive, toRefs } from 'vue';
import { IObject } from '@/types/interface'; import { IObject } from '@/types/interface';
import utilService from '@/service/utilService'; import utilService from '@/service/utilService';
export default defineComponent({ export default defineComponent({
name: 'block', name: 'block',
props: { item: { type: Object, default: () => ({}) }, dataForm: { type: Object, default: () => ({}) }, width: { type: String, default: () => '484px' }, height: { type: String, default: () => '318px' } },
props: { item: { type: Object, default: () => ({}) }, dataForm: { type: Object, default: () => ({}) }, sizeType: { type: String, default: () => '1' } },
setup(props) { setup(props) {
const state = reactive({ const state = reactive({
blockRef: null, blockRef: null,
}); });
const block = computed(() => { const block = computed(() => {
return {
w: props.width,
h: props.height,
};
const img = utilService.getImg('/src/assets/images/njhl/block_' + props.sizeType + '.png');
switch (props.sizeType) {
case '2':
return { w: '884px', h: '318px', s: `url('${img}'))` };
default:
return { w: '484px', h: '318px', s: `url('${img}'))` };
}
}); });
return { return {
@ -46,7 +50,7 @@ export default defineComponent({
.block { .block {
width: v-bind('block.w'); width: v-bind('block.w');
height: v-bind('block.h'); height: v-bind('block.h');
background: url('@/assets/images/njhl/block.png') no-repeat center;
// background: v-bind('block.s') no-repeat center;
background-size: 100% 100%; background-size: 100% 100%;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -57,7 +61,7 @@ export default defineComponent({
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
padding: 10px 38px;
padding: 15px 38px 10px 38px;
color: #fff; color: #fff;
> span { > span {

54
src/views/dashboard/main.vue

@ -4,7 +4,7 @@
<div class="boards-container"> <div class="boards-container">
<div class="center" title="使用鼠标左键、滚轮实现拖拽、放大缩小。"></div> <div class="center" title="使用鼠标左键、滚轮实现拖拽、放大缩小。"></div>
<div class="top"> <div class="top">
<div class="title" @click="reset" title="点击此标题将鸟瞰图及管线恢复成初始状态。">{{ $store.state.user.tenantName || '平台看板' }}</div>
<div class="title" @click="reset" title="点击此标题将鸟瞰图恢复成初始状态。">{{ $store.state.user.tenantName || '平台看板' }}</div>
<div class="time" v-if="timeCount && timeCount.ts > 0"> <div class="time" v-if="timeCount && timeCount.ts > 0">
<div class="time-left"> <div class="time-left">
{{ $m(timeCount.ts).format('HH:mm:ss') }} {{ $m(timeCount.ts).format('HH:mm:ss') }}
@ -30,6 +30,11 @@
<component :is="item.comp" :key="index" :item="item" :option="item.option" tip-loop></component> <component :is="item.comp" :key="index" :item="item" :option="item.option" tip-loop></component>
</block> </block>
</div> </div>
<div class="bottom">
<block size-type="2" :item="bottom">
<component :is="bottom.comp" :item="bottom" :option="bottom.option" tip-loop></component>
</block>
</div>
</div> </div>
<tooltip :data="toolTipData" /> <tooltip :data="toolTipData" />
</screen-adapter> </screen-adapter>
@ -46,7 +51,7 @@ import timeCountHooks from '@/hooks/time-count';
import { useFetch } from '@/hooks/fetch'; import { useFetch } from '@/hooks/fetch';
import utilService from '@/service/utilService'; import utilService from '@/service/utilService';
import Chart from '@/components/chart.vue'; import Chart from '@/components/chart.vue';
import { costStatistic, elecPayload, monthEnergyUsageTrend, usageRanking } from './common/model';
import { costStatistic, elecPayload, monthEnergyUsageTrend, usageRanking, energyUsageDistribution } from './common/model';
import { IObject } from '@/types/interface'; import { IObject } from '@/types/interface';
import moment from 'moment'; import moment from 'moment';
import toolHooks from '@/hooks/tool'; import toolHooks from '@/hooks/tool';
@ -68,6 +73,7 @@ export default defineComponent({
const { generateSvg2Dom } = toolHooks(); const { generateSvg2Dom } = toolHooks();
const state = reactive({ const state = reactive({
opt: { scale: 0.8 },
dragStretch: null, dragStretch: null,
toolTipData: {}, toolTipData: {},
timer: null, timer: null,
@ -212,6 +218,11 @@ export default defineComponent({
unit: 'kWh', unit: 'kWh',
}, },
], ],
bottom: {
comp: 'chart',
title: '24小时用能分布情况',
option: energyUsageDistribution(),
},
}) as IObject; }) as IObject;
const changeType = (type: string) => { const changeType = (type: string) => {
@ -242,7 +253,9 @@ export default defineComponent({
}, },
cb: (res: any) => { cb: (res: any) => {
if (utilService.isValidArray(res)) { if (utilService.isValidArray(res)) {
state.right[1].option = usageRanking(res);
const c = state.dataForm.code;
const u = state.dataForm.codeMap[c];
state.right[1].option = usageRanking(res, u);
} }
}, },
}); });
@ -306,6 +319,19 @@ export default defineComponent({
}); });
}; };
//24
useFetch('/board/dayEnergy/trend', {
data: {
//day: '2025-04-01',
day: moment().subtract(1, 'days').format('YYYY-MM-DD'),
},
cb: (res: any) => {
if (utilService.isValidObject(res)) {
state.bottom.option = energyUsageDistribution(res);
}
},
});
changeType(state.dataForm.code); changeType(state.dataForm.code);
fn(); fn();
@ -326,8 +352,8 @@ export default defineComponent({
const getSvg = () => { const getSvg = () => {
const target = document.querySelector('.boards-container .center') as HTMLElement; const target = document.querySelector('.boards-container .center') as HTMLElement;
generateSvg2Dom('/cdn/njhl_bg.svg', target, () => {
target.style.transform = 'scale(1.2)';
generateSvg2Dom('/cdn/normal_bg.svg', target, () => {
target.style.transform = 'scale(0.7)';
nextTick(() => { nextTick(() => {
init(state, target); init(state, target);
@ -475,6 +501,7 @@ export default defineComponent({
> * { > * {
margin: 0 40px; margin: 0 40px;
background: rgba(#000b31, 0.7);
} }
} }
@ -486,8 +513,14 @@ export default defineComponent({
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: space-between; justify-content: space-between;
background: rgba(#000b31, 0.7);
} }
.bottom {
> * {
background-color: rgba(#000b31, 0.7) !important;
}
}
.left { .left {
//left: 0; //left: 0;
left: 16px; left: 16px;
@ -497,6 +530,17 @@ export default defineComponent({
//right: 0; //right: 0;
right: 16px; right: 16px;
} }
.bottom {
position: absolute;
bottom: 20px;
width: 100%;
height: 318px;
left: 0;
> * {
margin: 0 auto;
}
}
} }
} }
} }

Loading…
Cancel
Save