This commit is contained in:
hzz 2025-03-14 08:37:09 +08:00
parent 56b07ac5ed
commit 58a5614c3a
81 changed files with 2851 additions and 2794 deletions

View File

@ -10,6 +10,6 @@ VITE_APP_BASE_API = '/prod-api'
# 是否在打包时开启压缩,支持 gzip 和 brotli # 是否在打包时开启压缩,支持 gzip 和 brotli
VITE_BUILD_COMPRESS = gzip VITE_BUILD_COMPRESS = gzip
VITE_PUBLIC_BASE_PATH = '/' VITE_PUBLIC_BASE_PATH = '/ras-web'
VITE_APP_WS_API = '' VITE_APP_WS_API = ''

BIN
dist.zip Normal file

Binary file not shown.

View File

@ -0,0 +1 @@

98
src/api/screen/micro.js Normal file
View File

@ -0,0 +1,98 @@
import request from '@/utils/request'
// 查询设备列表
export function listDevice(devId) {
return request({
url: '/mf/device',
method: 'get',
params: { devId }
})
}
// 查询设备能耗排行
export function listElect(type) {
return request({
url: '/mf/elect?type=' + type,
method: 'get',
})
}
// 查询设备用电监测
export function electMonitoring() {
return request({
url: '/mf/electMonitoring',
method: 'get',
})
}
// 查询设备状态
export function deviceStatus() {
return request({
url: '/mf/deviceStatus',
method: 'get',
})
}
// 设备利用率
export function deviceRate() {
return request({
url: '/mf/deviceRate',
method: 'get',
})
}
// 设备保养提醒
export function deviceCheck(devId) {
return request({
url: '/mf/deviceCheck',
method: 'get',
params: { devId }
})
}
//设备报警记录
export function deviceRepair(devId) {
return request({
url: '/mf/deviceRepair',
method: 'get',
params: { devId }
})
}
//单设备运行状态
export function deviceStatusById(devId) {
return request({
url: '/mf/deviceStatusById',
method: 'get',
params: { devId }
})
}
//单设备运行状态
export function deviceStatusChart(devId) {
return request({
url: '/mf/deviceStatusChart',
method: 'get',
params: { devId }
})
}
//单设备运行状态
export function deviceRateChart(devId) {
return request({
url: '/mf/deviceRateChart',
method: 'get',
params: { devId }
})
}
//单设备用电量图表
export function deviceElectChart(devId) {
return request({
url: '/mf/deviceElectChart',
method: 'get',
params: { devId }
})
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

View File

@ -0,0 +1,135 @@
<!--
* @FilePath: \code\gitscreenFront\src\views\Mechanics\components\scrollBoard.vue
* @Author: 王路平
* @文件版本: V1.0.0
* @Date: 2023-06-13 08:33:37
* @Description:
*
* 版权信息 : 2023 by ${RAS}, All Rights Reserved.
-->
<template>
<div class="box">
<ZdScrollBoard ref="devList" @click="dvClick" :config="newConfig" @mouseover="dvMouseover"
@mouseout="dvmouseleave" :style="{
width: '100%',
height: '100%',
}" />
<el-tooltip v-model:visible="visible" :content="tipcontent" effect="light" placement="top" trigger="click"
popper-class="tooltip-class" virtual-triggering :virtual-ref="triggerRef" />
</div>
</template>
<script setup lang='ts'>
import { getCurrentInstance, onMounted, reactive, ref, watch,computed } from "vue";
import ZdScrollBoard from "@/components/ZdScrollBoard/index.vue";
import { useRouter } from "vue-router"
const prop = defineProps({
config: Object,
data: <any>Array
})
let newConfig: any = computed(() => {
return {
...prop.config,
data: prop.data
}
})
const router = useRouter()
const emit: any = defineEmits()
//
let tipcontent = ref(null)
//
let visible = ref(false)
//dom
let triggerRef = ref(null)
let devList = ref(null)
/**
* @函数功能: 鼠标移入组件方法
* @param {*} value
* @出口参数:
* @函数备注:
*/
const dvMouseover = (value) => {
if (value.toElement && value.toElement.innerHTML && value.toElement.className == 'ceil') {
triggerRef.value = value.toElement
tipcontent.value = value.toElement.innerText
visible.value = true
}
};
// watch(
// () => prop.data,
// (val) => {
// devList.value.updateRows(val)
// },
// { deep: true, immediate: false }
// );
/**
* 点击表格事件
*/
const dvClick = (value) => {
if (value.row) {
emit('dvclick', value)
}
}
/**
* @函数功能: 鼠标移出组件方法
* @出口参数:
* @函数备注:
*/
const dvmouseleave = () => {
triggerRef.value = null
tipcontent.value = null
visible.value = false
};
</script>
<style scoped>
.box {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-around;
}
.box-title {
width: 100%;
font-size: 20px;
margin: 5px 0 10px 0;
color: #fff;
text-align: center;
font-weight: bold;
}
.box-body {
width: 100%;
flex: 1;
display: flex;
justify-content: space-around;
align-items: center;
}
:deep(.dv-scroll-board .rows .ceil) {
overflow: auto;
white-space: pre-wrap;
text-overflow: none
}
:deep(.dv-scroll-board .rows .row-item) {
font-size: 16px;
}
</style>
<style>
.el-popper.tooltip-class {
color: #fff !important;
}
</style>

View File

@ -77,16 +77,28 @@ export const constantRoutes = [
hidden: true, hidden: true,
redirect: 'noredirect', redirect: 'noredirect',
children: [ children: [
// {
// path: "/screen/R_D_Environment",
// name: "R_D_Environment",
// component: () => import("../views/screen/R_D_Environment/index.vue"),
// hidden: true
// },
{ {
path: "/screen/R_D_Environment", path: "/screen/R_D_Environment",
name: "R_D_Environment", name: "R_D_Environment",
component: () => import("../views/screen/R_D_Environment/index.vue"), component: () => import("../views/screen/R_D_Environment/index.vue"),
hidden: true hidden: true
}, },
{ {
path: "/screen/R_D_Environment1", path: "microFactory",
name: "R_D_Environment1", name: "MicroFactory",
component: () => import("../views/screen/R_D_Environment1/index.vue"), component: () => import("../views/screen/microFactory/index.vue"),
// meta: { title: '大屏首页', icon: 'dashboard', affix: true }
},
{
path: "devItem_:id",
component: () => import("../views/screen/devItem/index.vue"),
hidden: true hidden: true
}, },
] ]

View File

@ -41,7 +41,7 @@ onMounted(() => {
initModel(); initModel();
viewer.scene.traverse((item: THREE.Object3D) => { viewer.scene.traverse((item: THREE.Object3D) => {
console.log(item, '0000000000'); //console.log(item, '0000000000');
}); });
}); });
@ -58,6 +58,7 @@ const init = () => {
boxHelperWrap = new BoxHelperWrap(viewer); boxHelperWrap = new BoxHelperWrap(viewer);
viewer.emitter.on(Event.dblclick.raycaster, (list: THREE.Intersection[]) => { viewer.emitter.on(Event.dblclick.raycaster, (list: THREE.Intersection[]) => {
onMouseClick(list); onMouseClick(list);
}); });
@ -174,7 +175,6 @@ const initModel = () => {
}; };
const planeAnimate = (texture: any): Animate => { const planeAnimate = (texture: any): Animate => {
// console.log(texture, 'texture');
texture.wrapS = THREE.RepeatWrapping; texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping; texture.wrapT = THREE.RepeatWrapping;
const animateFn = { const animateFn = {
@ -208,7 +208,7 @@ const onMouseClick = (intersects: THREE.Intersection[]) => {
} }
}; };
findClickModel(selectedObject); findClickModel(selectedObject);
console.log(selectedObjectName); //console.log(selectedObjectName);
// if (!selectedObjectName || !selectedObjectName.includes('')) { // if (!selectedObjectName || !selectedObjectName.includes('')) {
// // this.scene.remove(this.label); // // this.scene.remove(this.label);
@ -216,7 +216,7 @@ const onMouseClick = (intersects: THREE.Intersection[]) => {
// } // }
// const selectedModel = viewer.scene.getObjectByName(selectedObjectName); // const selectedModel = viewer.scene.getObjectByName(selectedObjectName);
console.log(selectedObject, 'selectedObject'); //console.log(selectedObject, 'selectedObject');
// //
if (selectedObject.name.includes('zuo')) { if (selectedObject.name.includes('zuo')) {
@ -272,10 +272,9 @@ const onMouseMove = (intersects: THREE.Intersection[]) => {
// }; // };
findClickModel(selectedObject); findClickModel(selectedObject);
console.log(selectedObjectName, '--selectedObjectName---'); // console.log(selectedObjectName,selectedObject, '--selectedObjectName---');
console.log(selectedObject, '------selectedObject---------');
const rack = findParent(selectedObject, checkIsRack); const rack = findParent(selectedObject, checkIsRack);
console.log(rack, '-------rack---------'); // console.log(rack, '-------rack---------');
if (rack) { if (rack) {
boxHelperWrap.attach(rack); boxHelperWrap.attach(rack);

View File

@ -1,202 +0,0 @@
<template>
<div ref="threeContainer"></div>
</template>
<script setup>
import * as THREE from 'three';
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader';
import { MTLLoader } from 'three/examples/jsm/loaders/MTLLoader';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { CSS3DObject, CSS3DRenderer } from 'three/examples/jsm/Addons.js';
import { onMounted, ref } from 'vue';
const threeContainer = ref(null);
let camera, scene, renderer, model, controls, cssRenderer;
let width = 1920;
let height = 1080;
let text = ref('标注1');
const init = () => {
scene = new THREE.Scene();
// scene.background = new THREE.Color(0x100c2a);//0x100c2a
// scene.background.setAlpha(0);
camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 2000);
camera.position.set(40, 300, 200);
renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true
});
renderer.setSize(width, height);
threeContainer.value.appendChild(renderer.domElement);
cssRenderer = initLabelRenderer(threeContainer.value);
const objLoader = new OBJLoader();
let mtlLoader = new MTLLoader();
mtlLoader.load('/src/assets/obj/goats_R&D.mtl', function (materials) {
materials.preload();
objLoader.setMaterials(materials);
objLoader.load('/src/assets/obj/goats_R&D.obj', function (obj) {
var scale = 0.07 / obj.scale.x;
obj.scale.set(scale, scale, scale);
model = obj;
const box = new THREE.Box3().setFromObject(model);
const size = box.getSize(new THREE.Vector3())
// console.log(size,'-----');
obj.position.set(-size.x * 0.5, -size.y * 0.1, -size.z * 0.5);
obj.children.forEach((child) => {
const c = child;
const cm = c.material;
cm.emissive = cm.color;
cm.emissiveMap = cm.map;
});
addMarks(text.value);
scene.add(model);
animate();
});
});
// loader.load(
// '/src/assets/obj/goats_R&D.obj',
// (obj) => {
// var scale = 0.1 / obj.scale.x;
// obj.scale.set(scale, scale, scale);
// model = obj;
// //
// // scene.add(new THREE.AmbientLight(0x404040));
// scene.add(new THREE.DirectionalLight());
// scene.add(model);
// },
// (xhr) => {
// console.log((xhr.loaded / xhr.total * 100) + '% loaded');
// },
// (error) => {
// console.error('An error happened: ', error);
// }
// );
controls = new OrbitControls(camera, cssRenderer.domElement);
controls.enableDamping = true;
animate();
};
//
const initLabelRenderer = boxElement => {
const labelRenderer = new CSS3DRenderer();
labelRenderer.setSize(width, height);
labelRenderer.domElement.style.position = 'absolute';
labelRenderer.domElement.style.top = 0;
boxElement.appendChild(labelRenderer.domElement);
return labelRenderer;
};
function addMarks(text) {
// canvas texture
const offScreenCanvas = document.createElement('canvas');
const offScreenCtx = offScreenCanvas.getContext('2d');
//
offScreenCtx.font = '16px 黑体';
const txt = text;
const textWidth = offScreenCtx.measureText(txt).width;
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
if (ctx !== null) {
// pixelRatio:
canvas.width = (5 + textWidth + 5) * 2;
canvas.height = 18 * 2;
ctx.setTransform(2, 0, 0, 2, 0, 0);
ctx.font = '16px 黑体';
ctx.fillStyle = '#fff'; //
ctx.fillRect(0, 0, 5 + textWidth + 5, 18);
ctx.fillStyle = '#000'; //
ctx.fillText(txt, 5, 16);
}
// texture
const texture = new THREE.CanvasTexture(canvas);
var geometry2 = new THREE.BufferGeometry();
var material = new THREE.LineBasicMaterial({ vertexColors: true });
var color1 = new THREE.Color(0xffffff), color2 = new THREE.Color(0xffffff);
//线
var p3 = new THREE.Vector3(0, 50, 40);
var p4 = new THREE.Vector3(4, 23.5, 10);
const points = [];
points.push(p3);
points.push(p4);
// geometry2.vertices.push(p3);
// geometry2.vertices.push(p4);
// geometry2.colors.push(color1, color2);
geometry2.setFromPoints(points);
//线
var line2 = new THREE.Line(geometry2, material, THREE.LinePieces);
scene.add(line2);
//
/**精灵图 */
// var spriteMaterial2 = new THREE.SpriteMaterial({ map: texture, color: 0xffffff });
// var sprite2 = new THREE.Sprite(spriteMaterial2);
// sprite2.position.set(0, 50, 40);
// sprite2.scale.set(15, 5, 0);
// scene.add(sprite2);
/** CSS3D */
const label = new CSS3DObject(document.createElement('div'));
label.position.set(0, 50, 40);
label.scale.set(0.5, 0.5, 0.5);
label.element.style.backgroundColor = '#fff';
label.element.innerText = text;
scene.add(label);
//
// HTML90Y使
label.rotation.set(-Math.PI / 4,0, 0);
//
var radius = 0.5, segemnt = 16, rings = 16;
var sphereMaterial = new THREE.MeshLambertMaterial({ color: 0x9afc00 });
var sphere101 = new THREE.Mesh(new THREE.SphereGeometry(radius, segemnt, rings), sphereMaterial);
sphere101.position.set(4, 23.5, 10);
scene.add(sphere101);
// var group = new THREE.Object3D();
// group.add(line2);
// group.add(sphere101);
// group.add(sprite2);
// scene.add(group);
}
const animate = () => {
requestAnimationFrame(animate);
renderer.render(scene, camera);
cssRenderer.render(scene, camera);
controls.update();
};
onMounted(() => {
init();
window.addEventListener('resize', onWindowResize);
});
const onWindowResize = () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
};
onMounted(() => {
window.removeEventListener('resize', onWindowResize);
});
</script>
<style>
#threeContainer {
width: 1920px;
height: 1080px;
/* 根据需要调整位置 */
overflow: hidden;
}
</style>

View File

@ -1,147 +0,0 @@
<template>
<v-chart :option="options" theme="dark" style="width: 100%;height: 100%;" />
</template>
<script setup>
import { computed } from 'vue';
const prop = defineProps({
data: {
type: Object,
default: () => {
return {};
}
}
});
const options = computed(() => {
return {
tooltip: {
trigger: 'axis',
backgroundColor: 'rgba(0, 0, 0, 0.8)',
borderColor: '#00c6ff',
borderWidth: 2,
textStyle: {
color: '#fff',
fontSize: 14
},
formatter: function (params) {
let tooltipText = '';
let xAxisValue = params[0].name;
params.forEach((item) => {
tooltipText += `<div style="padding: 2px 0;"><strong>${item.seriesName}:</strong> ${item.value}</div>`;
});
return `${xAxisValue}<br>${tooltipText}`;
},
padding: 10,
extraCssText: 'border-radius: 8px; box-shadow: 0 0 15px rgba(0, 0, 0, 0.5);'
},
backgroundColor: 'transparent',
legend: {
show: true,
data: ['目标产量', '实际产量'],
textStyle: {
color: '#fff',
},
},
xAxis: {
type: 'category',
data: ['102410', '102411', '102412', '102413', '102414', '102415', '102416', '102417'],
axisLabel: {
color: "#ffffff",
interval: 0,
},
axisLine: {
lineStyle: {
color: '#0091ea'
}
},
axisTick: {
show: false,
}
},
yAxis: [
{
type: 'value',
axisTick: {
show: false
}
},
{
type: 'value',
axisTick: {
show: false
}
}
],
series: [
{
name: '目标产量',
data: [150, 105, 110, 80, 120, 100, 140, 180],
yAxisIndex: 0,
type: 'bar',
barCategoryGap: '10%',
showBackground: true,
itemStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 1,
y2: 1,
colorStops: [
{ offset: 0, color: '#5aaef3' },
{ offset: 1, color: '#1e90ff' }
]
},
borderRadius: [60, 60, 60, 60],
stroke: '#00c6ff',
lineWidth: 2
},
label: {
show: true,
position: 'top',
color: '#ffffff'
},
backgroundStyle: {
borderRadius: [60, 60, 60, 60],
}
},
{
name: '实际产量',
yAxisIndex: 1,
data: [106, 90, 25, 80, 35, 100, 140, 172],
type: 'bar',
barCategoryGap: '10%',
showBackground: true,
itemStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 1,
y2: 1,
colorStops: [
{ offset: 0, color: '#f8efd4' },
{ offset: 1, color: '#fbdc7f' }
]
},
borderRadius: [60, 60, 60, 60],
stroke: '#ff6347',
lineWidth: 2
},
label: {
show: true,
position: 'top',
color: '#ffffff'
},
backgroundStyle: {
borderRadius: [60, 60, 60, 60],
}
},
],
}
});
</script>
<style lang="scss" scoped></style>

View File

@ -1,64 +0,0 @@
<template>
<v-chart :option="options" theme="dark" style="width: 100%;height: 100%;" />
</template>
<script setup>
import { computed } from 'vue';
const prop = defineProps({
data: {
type: Object,
default: () => {
return {
date: ['2021-10-01', '2021-10-02', '2021-10-03', '2021-10-04', '2021-10-05', '2021-10-06', '2021-10-07'],
series: [{
type: '温度',
value: [20, 22, 23, 24, 25, 26, 27]
}, {
type: '湿度',
value: [30, 32, 33, 34, 35, 36, 37]
}]
};
}
}
});
const options = computed(() => {
let seriesData = [];
prop.data.series.forEach(res => {
seriesData.push({
name: res.type,
type: 'line',
showSymbol: false,
data: prop.data.date.map((key, value) => [key, res.value[value]]),
smooth: true,
})
})
return {
backgroundColor: 'transparent',
tooltip: {
trigger: 'axis',
},
grid: {
top: "15%",
left: "5%",
right: "5%",
bottom: "5%",
containLabel: true,
},
xAxis: {
type: 'time',
splitLine: {
show: false
}
},
yAxis: {
type: 'value',
},
series: seriesData
};
});
</script>
<style lang="scss" scoped></style>

View File

@ -1,201 +0,0 @@
<template>
<v-chart :option="options" style="width: 100%;height: 100%;" />
</template>
<script setup>
import { computed } from 'vue';
const prop = defineProps({
value: {
type: Object,
default: () => {
return {
Humiture: [{
"devId": "eb98cb70-158f-11ee-b4df-a9653aef169c",
"name": "服装军团",
"temp": "18.2",
"humidity": "32.2",
"status": true
}],
top: { temp: 0, humidity: 0 },
bottom: { temp: 0, humidity: 0 }
};
}
}
});
const options = computed(() => {
//x
let x = [];
//y
let y = { temp: [], humidity: [] };
prop.value.Humiture.forEach((res) => {
x.push(res.name);
y.temp.push(res.temp);
y.humidity.push(res.humidity);
});
return {
tooltip: {
trigger: "axis",
axisPointer: {
type: "shadow",
},
},
legend: {
// bottom: "3%",
top: '6%'
},
grid: {
top: "15%",
left: "3%",
right: "4%",
bottom: "3%",
containLabel: true,
},
color: ["#4992FF", "#7CFFB2", "#FF6E76"],
xAxis: {
type: "category",
data: x,
axisLabel: {
interval: 0
}
},
yAxis: {
name: "温度(°C)/湿度(%RH)",
type: "value",
boundaryGap: [0, 0.01],
axisLabel: {
formatter: "{value}",
},
},
series: [
{
//name: `${''}(°C)(${t('messages.fanwei')}${value.bottom.temp}°C - ${value.top.temp}°C)`,
type: "bar",
data: y.temp,
barWidth: '30%',
itemStyle: {
color: function (params) {
var index_color = params.value;
if (
index_color <= prop.value.bottom.temp ||
index_color >= prop.value.top.temp
) {
return "#FF6E76";
} else {
return "#4992FF";
}
},
},
label: {
formatter: "{c} °C",
show: true,
position: "top",
textStyle: {
color: "rgb(255,255,255,0.9)",
},
},
markLine: {
//
silent: true, //线
symbol: "none", //
data: [
{
name: '温度',
yAxis: prop.value.bottom.temp,
label: {
formatter: `温度下限值: ${prop.value.bottom.temp} °C`,
position: "middle",
},
lineStyle: {
color: "yellow", // 线
},
},
{
name: '温度',
yAxis: prop.value.top.temp,
label: {
formatter: `温度上限值:${prop.value.top.temp} °C`,
position: "middle",
},
lineStyle: {
color: "yellow", // 线
},
},
],
},
},
{
//name: `${t('messages.HumidityRange')}(%RH)(${t('messages.fanwei')}${value.bottom.humidity}%RH - ${value.top.humidity}%RH)`,
name: `湿度(%RH)(范围:${prop.value.bottom.humidity}%RH - ${prop.value.top.humidity}%RH)`,
type: "bar",
data: y.humidity,
barWidth: '30%',
itemStyle: {
color: function (params) {
var index_color = params.value;
if (
index_color <= prop.value.bottom.humidity ||
index_color >= prop.value.top.humidity
) {
return "#FF6E76";
} else {
return "#7CFFB2";
}
},
},
label: {
formatter: "{c} %RH",
show: true,
position: "top",
textStyle: {
color: "rgb(255,255,255,0.9)",
},
},
markLine: {
//
silent: true, //线
symbol: "none", //
data: [
{
name: "湿度",
yAxis: prop.value.bottom.humidity,
label: {
// formatter: `${t('messages.HumidityRange')}${t('messages.TemperatureRange_down')}` + value.bottom.humidity + "%RH",
formatter: `湿度下限值:` + prop.value.bottom.humidity + "%RH",
position: "middle",
},
lineStyle: {
color: "red", // 线
},
},
{
name: "湿度",
yAxis: prop.value.top.humidity,
label: {
// formatter: `${t('messages.HumidityRange')}${t('messages.TemperatureRange_up')}` + value.top.humidity + "%RH",
formatter: `湿度上限值:` + prop.value.top.humidity + "%RH",
position: "middle",
},
lineStyle: {
color: "red", // 线
},
},
],
},
},
{
name: '超标(温湿度未达正常值均为超标)',
type: "bar",
color: '#FF6E76'
}
],
};
});
</script>
<style lang="scss" scoped></style>

View File

@ -1,52 +0,0 @@
<template>
<div class="item-container">
<div class="box-title" :class="[prop.pos == 'left'?'pos-l':'pos-r']">{{ prop.title }}</div>
<div class="content">
<slot></slot>
</div>
</div>
</template>
<script setup>
const prop = defineProps({
title: {
type: String,
default: '标题'
},
pos: {
type: String,
default: 'left'
}
})
</script>
<style lang="scss" scoped>
.item-container {
width: 100%;
height: 100%;
.box-title {
width: 100%;
height: 41px;
box-sizing: border-box;
padding-left: 25px;
font-size: 20px;
line-height: 40px;
color: #fff;
}
.pos-l {
// background: linear-gradient(to right, #102238 0%, transparent 100%);
background: url('/src/assets/images/box-title-l.png') no-repeat center center / 100% 100%;
}
.pos-r {
// background: linear-gradient(to left, #102238 0%, transparent 100%);
background: url('/src/assets/images/box-title-r.png') no-repeat center center / 100% 100%;
text-align: right;
padding-right: 25px;
}
.content {
width: 100%;
height: calc(100% - 41px);
}
}
</style>

View File

@ -1,62 +0,0 @@
<template>
<v-chart :option="options" theme="dark" style="width: 100%;height: 100%;" />
</template>
<script setup>
import { computed } from 'vue';
const prop = defineProps({
data: {
type: Object,
default: () => {
return {};
}
}
});
const options = computed(() => {
return {
tooltip: {
trigger: "axis",
formatter: function (params) {
let tooltipText = '';
let xAxisValue = params[0].name; // x
params.forEach((item) => {
tooltipText += `${item.marker}${item.seriesName}: ${item.value} kWh<br>`;
});
return `${xAxisValue}<br>${tooltipText}`;
}
},
backgroundColor: 'transparent',
xAxis: {
type: 'category',
data: ['9:00', '10:00', '11:00', '12:00', '13:00', '14:00', '15:00'],
},
yAxis: {
type: 'value',
},
series: [
{
name: "耗电量",
data: [820, 932, 901, 934, 1290, 1330, 1320],
type: 'line',
smooth: true,
areaStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{ offset: 0, color: 'rgba(0, 198, 255, 0.5)' },
{ offset: 1, color: 'rgba(0, 114, 255, 0.01)' }
]
}
},
}
]
};
});
</script>
<style lang="scss" scoped></style>

View File

@ -1,169 +0,0 @@
<template>
<v-chart :option="options" theme="dark" style="width: 100%;height: 100%;" />
</template>
<script setup>
import { computed } from 'vue';
const prop = defineProps({
data: {
type: Object,
default: () => {
return {
pm25: 0,
pm10: 0,
};
}
}
});
const options = computed(() => {
return {
grid: {
//
top: "0px",
left: "0px",
right: "0px",
bottom: "0px",
},
backgroundColor: "transparent",
series: [
{
type: "gauge",
center: ["50%", "90%"],
startAngle: 190,
endAngle: -10,
radius: "50%",
min: 0,
max: 100,
splitNumber: 10,
pointer: {
icon: "path://M12.8,0.7l12,40.1H0.7L12.8,0.7z",
length: "12%",
width: 10,
offsetCenter: [0, "-40%"],
itemStyle: {
color: "inherit",
},
},
axisLine: {
lineStyle: {
width: 8,
color: [
[0.35, "#7CFFB2"],
[0.75, "#FDDD60"],
[1, "#FF6E76"],
],
},
},
axisTick: {
distance: 0,
splitNumber: 5,
lineStyle: {
width: 2,
color: "#999",
},
},
splitLine: {
distance: 5,
length: 8,
lineStyle: {
width: 3,
color: "#999",
},
},
axisLabel: {
distance: 12,
color: "#999",
fontSize: 10,
},
anchor: {
show: false,
},
detail: {
valueAnimation: true,
width: "60%",
lineHeight: 20,
borderRadius: 8,
offsetCenter: [0, "20%"],
fontSize: 15,
fontWeight: "bolder",
formatter: "{value} μg/m3",
color: "inherit",
},
title: {
// show: false,
offsetCenter: [0, "-20%"],
},
data: [
{
value: prop.data.pm25,
name: "PM2.5",
},
],
},
{
type: "gauge",
center: ["50%", "55%"],
startAngle: 200,
endAngle: -20,
min: 0,
max: 200,
axisLine: {
lineStyle: {
width: 10,
color: [
[0.35, "#7CFFB2"],
[0.75, "#FDDD60"],
[1, "#FF6E76"],
],
},
},
pointer: {
itemStyle: {
color: "inherit",
},
},
axisTick: {
distance: -10,
length: 6,
lineStyle: {
color: "#fff",
width: 2,
},
},
splitLine: {
distance: -10,
length: 10,
lineStyle: {
color: "#fff",
width: 4,
},
},
axisLabel: {
color: "inherit",
distance: 20,
fontSize: 10,
},
detail: {
valueAnimation: true,
offsetCenter: [0, "20%"],
fontSize: 20,
formatter: "{value} μg/m3",
color: "inherit",
},
title: {
offsetCenter: [0, "-50%"],
},
data: [
{
value: prop.data.pm10,
name: "PM10",
},
],
},
],
};
});
</script>
<style lang="scss" scoped></style>

View File

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 52 KiB

View File

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

View File

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

View File

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View File

Before

Width:  |  Height:  |  Size: 162 KiB

After

Width:  |  Height:  |  Size: 162 KiB

View File

Before

Width:  |  Height:  |  Size: 162 KiB

After

Width:  |  Height:  |  Size: 162 KiB

View File

Before

Width:  |  Height:  |  Size: 150 KiB

After

Width:  |  Height:  |  Size: 150 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 43 KiB

View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -1,533 +1,514 @@
<template> <template>
<div class="container"> <div class="container">
<div class="abs-header" ref="texstref">研发中心环境实时监测系统</div> <div class="header">
<div class="l-box"> <div class="title">研发中心环境实时监测系统</div>
<div class="lbox1">
<ItemVue title="温湿度监测">
<Humiture />
</ItemVue>
</div>
<div class="lbox1">
<ItemVue title="粉尘监测">
<PmVue :data="dustData" />
</ItemVue>
</div>
<div class="lbox1">
<ItemVue title="智能控制系统">
<BarChart />
</ItemVue>
</div>
</div>
<div class="ct-box">
<div class="ct-sensor">
<div class="sensor-item" v-for="item in sensor_list">
<!-- :style="{color:item.status == 'true'?'#469DE9':'gray'}" -->
<component style="width: 75px;height: 75px;margin-top: 10px;" :is="item.component" :value="item.value"
:color="checkCb(item)" :unit="item.unit" /><!-- item.status == 'true'?'#469DE9':'gray' -->
<div style="margin: 10px 0">{{ item.value + item.unit }}</div>
<div>{{ item.name }}</div>
</div> </div>
</div> <div class="ct-box">
<div class="ct-sensor">
<SensorNumLoop :sensorData="item" v-for="(item, index) in sensor_list" :key="index" />
</div>
</div>
<div class="left-content left-right" ref="leftContentRef">
<Lr1 :data="avg_temp_humi.four" />
<Lr2 :deptId="'113'" />
<Lr3 :public_list="noiseDataList.four.public_noise" :office_list="noiseDataList.four.office_noise" />
<Lr4 :data="TVOC_CH2O_floor['4f']" />
</div>
<div class="right-content left-right" ref="rightContentRef">
<Lr1 :data="avg_temp_humi.five" />
<Lr2 :deptId="'114'" />
<Lr3 :public_list="noiseDataList.five.public_noise" :office_list="noiseDataList.five.office_noise" />
<Lr4 :data="TVOC_CH2O_floor['5f']" />
</div>
<div class="bottom-content" ref="bottomContentRef">
</div> <ZdScrollBoard ref="devList" :config="zd_config" class="zd-scroll-board" />
<div class="cb-box"> </div>
<div class="cbox"> <div class="checkboxlist">
<ItemVue title="甲醛监测"> <el-radio-group v-model="radioGroup1" :fill="'#105F88'" size="large">
<LineChart /> <el-radio-button label="四层" value="四层"></el-radio-button>
</ItemVue>
</div>
<div class="cbox">
<ItemVue title="TVOC监测">
<LineChart />
</ItemVue>
</div>
</div>
<div class="r-box">
<div class="rbox-item">
<ItemVue title="公共区域噪音" pos="right">
<LineChart />
</ItemVue>
</div>
<div class="rbox-item">
<ItemVue title="办公室噪音" pos="right">
<ProgeChart :data="noiseDataList" />
</ItemVue>
</div>
<div class="rbox-item">
<ItemVue title="告警信息" pos="right">
<ZdScrollBoard ref="devList" :config="zd_config"
:style="{ width: '100%', height: '260px', 'padding-top': '10px' }" />
</ItemVue>
</div>
</div>
<el-radio-button label="五层" value="五层"></el-radio-button>
<!-- <Sence /> --> </el-radio-group>
</div> </div>
<Sence />
</div>
</template> </template>
<script setup> <script setup>
import { ref, reactive, onMounted } from 'vue'; import { ref, reactive, onMounted, computed, watch } from 'vue';
// import ThreeBG from './component/threeBG.vue';
import Sence from './component/Sence.vue'; import Sence from './component/Sence.vue';
import ItemVue from './component/item.vue'; import Lr1 from './component/Lr1.vue';
import Humiture from './component/humiture_line.vue'; import Lr2 from './component/Lr2.vue';
import PmVue from './component/pm.vue'; import Lr3 from './component/Lr3.vue';
import LineChart from './component/lineChart.vue'; import Lr4 from './component/Lr4.vue';
import BarChart from './component/barChart.vue';
import ProgeChart from './component/proge.vue';
import SvgFenchen from './component/svgFenchen.vue';
import SvgPm25 from './component/svgPm25.vue';
import SvgPm10 from './component/svgPm10.vue';
import SvgJiaquan from './component/svgJiaquan.vue';
import SvgZaosheng from './component/svgZaosheng.vue';
import SvgTVOC from './component/svgTVOC.vue';
import SvgShidu from './component/svgShidu.vue';
import SvgWendu from './component/svgWendu.vue';
import SvgYanwu from './component/svgYanwu.vue';
import ZdScrollBoard from "@/components/ZdScrollBoard/index.vue"; import ZdScrollBoard from "@/components/ZdScrollBoard/index.vue";
import { connectWebsocket, closeWebsocket } from '@/utils/websocket'; import SensorNumLoop from './component/SensorNumLoop.vue';
import { getNoiseData, getTopData, getSensorDateHourByType } from '@/api/screen/R_D_Environment'; import useR_D_EnvironmentStore from '@/store/modules/r_d_environment'
import { connectWebsocket, closeWebsocket} from "@/utils/websocket";
import { getSensorByDept } from '@/api/screen/R_D_Environment';
let noiseDataList = ref([
{ let R_D_EnvironmentStore = useR_D_EnvironmentStore()
"devId": "48a2ec70-a60c-11ef-91f3-abd609c7e488", let deltaY = ref(0)
"devName": "办公区7", let avg_temp_humi = computed(() => {
"label": "noise-7", return R_D_EnvironmentStore.getLayerData
"place": null,
"data": 10,
"status": 0
},
{
"devId": "48a2ec70-a60c-11ef-91f3-abd609c7e489",
"devName": "办公区6",
"label": "noise-6",
"place": null,
"data": 20,
"status": 0
},
{
"devId": "48a2ec70-a60c-11ef-91f3-abd609c7e490",
"devName": "办公区5",
"label": "noise-5",
"place": null,
"data": 22,
"status": 0
},
{
"devId": "48a2ec70-a60c-11ef-91f3-abd609c7e491",
"devName": "办公区4",
"label": "noise-4",
"place": null,
"data": 22,
"status": 0
},
{
"devId": "48a2ec70-a60c-11ef-91f3-abd609c7e491",
"devName": "办公区3",
"label": "noise-3",
"place": null,
"data": 21,
"status": 0
},
{
"devId": "48a2ec70-a60c-11ef-91f3-abd609c7e492",
"devName": "办公区2",
"label": "noise-2",
"place": null,
"data": 24,
"status": 0
},
{
"devId": "48a2ec70-a60c-11ef-91f3-abd609c7e493",
"devName": "办公区1",
"label": "noise-1",
"place": null,
"data": 25,
"status": 0
},
])
let sensor_list = reactive([
{
id: '',
name: '温度',
component: SvgWendu,
value: 20,
unit: '℃',
type: 'AirTemp_Reg',
limit: 40,
status: "true"
},
{
id: '',
name: '湿度',
component: SvgShidu,
value: 20,
unit: '%',
type: 'AirHumi_Reg',
limit: 90,
status: "true"
},
{
id: '',
name: '甲醛',
component: SvgJiaquan,
value: 20,
unit: 'mg/m³',
type: 'CH2O',
limit: 0.08,
status: "true"
},
{
id: '',
name: 'TVOC',
component: SvgTVOC,
value: 20,
unit: 'mg/m³',
type: 'TVOC',
limit: 0.5,
status: "true"
},
{
id: '',
name: 'PM2.5',
component: SvgPm25,
value: 20,
unit: 'mg/m³',
type: 'HIGH_PM25_Reg',
limit: 30,
status: "true"
},
{
id: '',
name: 'PM10',
component: SvgPm10,
value: 20,
unit: 'mg/m³',
type: 'HIGH_PM10_Reg',
limit: 30,
status: "true"
},
{
id: '',
name: '噪音',
component: SvgZaosheng,
value: 20,
unit: 'dB',
type: 'Noise_Reg',
limit: 85,
status: "true"
},
{
id: '',
name: '烟雾',
component: SvgYanwu,
value: 20,
unit: 'mg/m³',
type: 'Smoke_Reg',
limit: 100,
status: "true"
}
])
let dustData = reactive({
pm25: 0,
pm10: 0,
}) })
let texstref = ref(null) let noiseDataList = computed(() => {
let zd_config = ref({ return R_D_EnvironmentStore.getNoiseData
header: ['报警时间', '报警内容', '报警位置'],
rowNum: 4,
data: [
['行1列1', '行1列2', '行1列3'],
['行2列1', '行2列2', '行2列3'],
['行3列1', '行3列2', '行3列3'],
['行4列1', '行4列2', '行4列3'],
['行5列1', '行5列2', '行5列3'],
['行6列1', '行6列2', '行6列3'],
['行7列1', '行7列2', '行7列3'],
['行8列1', '行8列2', '行8列3'],
['行9列1', '行9列2', '行9列3'],
['行10列1', '行10列2', '行10列3']
]
}) })
// let TVOC_CH2O_floor = reactive({
function checkCb(item) { '4f': {
if (item.status === 'false') { ch2o: [],
return 'gray' tvoc: []
} else if (item.value > item.limit) { },
return '#FF0000' '5f': {
} else { ch2o: [],
return '#469DE9' tvoc: []
}
}
//
function getNoiseDataList() {
getNoiseData().then(res => {
if (res.code === 200) {
noiseDataList.value = res.data
} }
}) })
} let sensor_list = computed(() => {
// let sensorData = R_D_EnvironmentStore.sensorData
function getTopDataList() { return [
getTopData(113).then(res => { {
if (res.code === 200) {
res.data.forEach(item => {
let index = sensor_list.findIndex(sensor => sensor.type === item.type)
sensor_list[index].value = item.data
sensor_list[index].id = item.id
sensor_list[index].status = item.status
sensor_list[index].limit = item.limit
if (item.type === 'HIGH_PM25_Reg') {
dustData.pm25 = item.data
} else if (item.type === 'HIGH_PM10_Reg') {
dustData.pm10 = item.data
component: 'SvgWendu',
unit: '℃',
type: 'AirTemp_Reg',
limit: 40,
list: sensorData['temp_humi']?.map(sensor => {
return {
id: sensor.deviceId,
name: sensor.name,
value: sensor.temp,
status: sensor.status
}
})
},
{
component: 'SvgShidu',
unit: '%RH',
type: 'AirHumi_Reg',
limit: 90,
list: sensorData['temp_humi']?.map(sensor => {
return {
id: sensor.deviceId,
name: sensor.name,
value: sensor.humidity,
status: sensor.status
}
})
},
{
component: 'SvgJiaquan',
unit: 'mg/m³',
type: 'CH2O',
limit: 0.08,
list: sensorData['TVOC_CH2O']?.filter(sensor => sensor.type === 'CH2O').map(sensor => {
return {
id: sensor.deviceId,
name: sensor.name,
value: sensor.data,
status: sensor.status
}
})
},
{
component: 'SvgTVOC',
unit: 'mg/m³',
type: 'TVOC',
limit: 0.5,
list: sensorData['TVOC_CH2O']?.filter(sensor => sensor.type === 'TVOC').map(sensor => {
return {
id: sensor.deviceId,
name: sensor.name,
value: sensor.data,
status: sensor.status
}
})
},
{
component: 'SvgPm25',
unit: 'mg/m³',
type: 'HIGH_PM25_Reg',
limit: 30,
list: sensorData['dust']?.filter(sensor => sensor.type === 'HIGH_PM25_Reg').map(sensor => {
return {
id: sensor.deviceId,
name: sensor.name,
value: sensor.data,
status: sensor.status
}
})
},
{
component: 'SvgPm10',
unit: 'mg/m³',
type: 'HIGH_PM10_Reg',
limit: 30,
list: sensorData['dust']?.filter(sensor => sensor.type === 'HIGH_PM10_Reg').map(sensor => {
return {
id: sensor.deviceId,
name: sensor.name,
value: sensor.data,
status: sensor.status
}
})
},
{
component: 'SvgZaosheng',
unit: 'dB',
type: 'Noise_Reg',
limit: 85,
list: sensorData['noise']?.map(sensor => {
return {
id: sensor.deviceId,
name: sensor.name,
value: sensor.data,
status: sensor.status
}
})
},
{
component: 'SvgYanwu',
unit: 'mg/m³',
type: 'Smoke_Reg',
limit: 100,
list: sensorData['Smoke']?.map(sensor => {
return {
id: sensor.deviceId,
name: sensor.name,
value: sensor.data,
status: sensor.status
}
})
} }
]
})
const radioGroup1 = ref('四层')
let zd_config = ref({
header: ['报警时间', '报警内容', '持续时长', '报警设备'],
rowNum: 2,
headerHeight: 50,
headerBGC: 'transparent',
oddRowBGC: 'transparent',
evenRowBGC: 'transparent',
columnWidth: [179, 179, 179, 179],
data: [
['行1列1', '行1列2', '行1列3', '行1列4'],
['行2列1', '行2列2', '行2列3', '行2列4'],
['行3列1', '行3列2', '行3列3', '行3列4'],
['行4列1', '行4列2', '行4列3', '行4列4'],
]
})
function reqSensorByDept() {
getSensorByDept('113,114').then(res => {
if (res.code === 200) {
let sensorData = res.data
let temp_humi = sensorData.temp_humi
let TVOC_CH2O = sensorData.TVOC_CH2O
let temp = []
temp_humi.map(item => {
let index = temp.find(item2 => { return item2.deviceId == item.deviceId })
if (!index) {
if (item.type === 'AirHumi_Reg') {
temp.push({
deviceId: item.deviceId,
humidity: item.data,
name: item.name,
label: item.label,
temp: '',
deptId: item.deptId,
deptName: item.deptName,
status: item.status
})
}) } else if (item.type === 'AirTemp_Reg') {
} temp.push({
}) deviceId: item.deviceId,
humidity: '',
name: item.name,
label: item.label,
temp: item.data,
deptId: item.deptId,
deptName: item.deptName,
status: item.status
})
}
} else {
if (item.type === 'AirHumi_Reg') {
index.humidity = item.data
} else if (item.type === 'AirTemp_Reg') {
index.temp = item.data
}
}
})
let now = +new Date()
TVOC_CH2O.map(item => {
if (item.deptId == '113') {
if (item.type === 'CH2O') {
TVOC_CH2O_floor['4f'].ch2o.push([now,item.data])
} else if (item.type === 'TVOC') {
TVOC_CH2O_floor['4f'].tvoc.push([now,item.data])
}
} else if(item.deptId == '114') {
if (item.type === 'CH2O') {
TVOC_CH2O_floor['5f'].ch2o.push([now,item.data])
} else if (item.type === 'TVOC') {
TVOC_CH2O_floor['5f'].tvoc.push([now,item.data])
}
}
})
sensorData.temp_humi = temp
R_D_EnvironmentStore.sensorData = sensorData
// noiseDataList.value = res.data
// public_noise.value = noiseDataList.value.find(item => item.devName === '')
// office_noise.value = noiseDataList.value.filter(item => item.devName !== '')
}
})
} }
//
function getSensorData(type) {
let query = {
type,
deptId: '100'
}
getSensorDateHourByType(query)
}
//socket //socket
function getWebsocket(val) { function getWebsocket(val) {
try { try {
let data = JSON.parse(val); let data = JSON.parse(val);
if (data.type == "HUMI_TEMP") { if (data.type == "HUMI_TEMP") {
let obj = data.msg; let obj = data.msg;
if (obj.hasOwnProperty('temp')) { if (obj.hasOwnProperty('temp')) {
let index = sensor_list.findIndex(sensor => sensor.type === 'AirTemp_Reg' && sensor.id === obj.temp.devId) let index = sensor_list.findIndex(sensor => sensor.type === 'AirTemp_Reg' && sensor.id === obj.temp.devId)
if (index !== -1) { if (index !== -1) {
sensor_list[index].value = obj.temp.value sensor_list[index].value = obj.temp.value
sensor_list[index].status = "true" sensor_list[index].status = "true"
}
}
if (obj.hasOwnProperty('humi')) {
let index = sensor_list.findIndex(sensor => sensor.type === 'AirHumi_Reg' && sensor.id === obj.humi.devId)
if (index !== -1) {
sensor_list[index].value = obj.humi.value
sensor_list[index].status = "true"
}
}
} }
if (data.type == "TVOC_CH2O") {
let obj = data.msg;
if (obj.hasOwnProperty('CH2O')) {
let index = sensor_list.findIndex(sensor => sensor.type === 'CH2O' && sensor.id === obj.CH2O.devId)
if (index !== -1) {
sensor_list[index].value = obj.CH2O.value
sensor_list[index].status = "true"
}
} }
if (obj.hasOwnProperty('humi')) { if (obj.hasOwnProperty('TVOC')) {
let index = sensor_list.findIndex(sensor => sensor.type === 'AirHumi_Reg' && sensor.id === obj.humi.devId) let index = sensor_list.findIndex(sensor => sensor.type === 'TVOC' && sensor.id === obj.TVOC.devId)
if (index !== -1) { if (index !== -1) {
sensor_list[index].value = obj.humi.value sensor_list[index].value = obj.TVOC.value
sensor_list[index].status = "true" sensor_list[index].status = "true"
}
}
} }
//
if (data.type == "dust") {
let obj = data.msg;
}
let index_pm25 = sensor_list.findIndex(sensor => sensor.type === 'HIGH_PM25_Reg' && sensor.id === obj.devId)
let index_pm10 = sensor_list.findIndex(sensor => sensor.type === 'HIGH_PM10_Reg' && sensor.id === obj.devId)
if (index_pm25 !== -1) {
sensor_list[index_pm25].value = obj.pm25
sensor_list[index_pm25].status = "true"
dustData.pm25 = obj.pm25
}
if (index_pm10 !== -1) {
sensor_list[index_pm10].value = obj.pm10
sensor_list[index_pm10].status = "true"
dustData.pm10 = obj.pm10
}
}
//
if (data.type === "NOISE") {
let obj = data.msg;
let list_index = noiseDataList.value.findIndex(item => item.devId === obj.noise.devId)
if (list_index !== -1) {
noiseDataList.value[list_index].data = obj.noise.value
} else {
let index = sensor_list.findIndex(sensor => sensor.type === 'Noise_Reg' && sensor.id === obj.noise.devId)
if (index !== -1) {
sensor_list[index].value = obj.noise.value
sensor_list[index].status = "true"
}
}
}
} catch (err) {
console.log(err);
} }
if (data.type == "TVOC_CH2O") {
let obj = data.msg;
if (obj.hasOwnProperty('CH2O')) {
let index = sensor_list.findIndex(sensor => sensor.type === 'CH2O' && sensor.id === obj.CH2O.devId)
if (index !== -1) {
sensor_list[index].value = obj.CH2O.value
sensor_list[index].status = "true"
}
}
if (obj.hasOwnProperty('TVOC')) {
let index = sensor_list.findIndex(sensor => sensor.type === 'TVOC' && sensor.id === obj.TVOC.devId)
if (index !== -1) {
sensor_list[index].value = obj.TVOC.value
sensor_list[index].status = "true"
}
}
}
//
if (data.type == "dust") {
let obj = data.msg;
let index_pm25 = sensor_list.findIndex(sensor => sensor.type === 'HIGH_PM25_Reg' && sensor.id === obj.devId)
let index_pm10 = sensor_list.findIndex(sensor => sensor.type === 'HIGH_PM10_Reg' && sensor.id === obj.devId)
if (index_pm25 !== -1) {
sensor_list[index_pm25].value = obj.pm25
sensor_list[index_pm25].status = "true"
dustData.pm25 = obj.pm25
}
if (index_pm10 !== -1) {
sensor_list[index_pm10].value = obj.pm10
sensor_list[index_pm10].status = "true"
dustData.pm10 = obj.pm10
}
}
//
if (data.type === "NOISE") {
let obj = data.msg;
let list_index = noiseDataList.value.findIndex(item => item.devId === obj.noise.devId)
if (list_index !== -1) {
noiseDataList.value[list_index].data = obj.noise.value
} else {
let index = sensor_list.findIndex(sensor => sensor.type === 'Noise_Reg' && sensor.id === obj.noise.devId)
if (index !== -1) {
sensor_list[index].value = obj.noise.value
sensor_list[index].status = "true"
}
}
}
} catch (err) {
console.log(err);
}
} }
function errWebsocket(val) { function errWebsocket(val) {
// console.log(val); // console.log(val);
} }
let deltaY = ref(0)
onMounted(() => { onMounted(() => {
getNoiseDataList() reqSensorByDept()
getTopDataList() window.addEventListener('wheel', function (event) {
deltaY.value += event.deltaY
if (deltaY.value <= -500 && deltaY.value >= -1000) {
this.document.querySelector('.ct-box').style.transform = 'translateY(-200%) translateX(-50%)'
this.document.querySelector('.left-content').style.transform = 'translateX(-100%)'
this.document.querySelector('.right-content').style.transform = 'translateX(100%)'
this.document.querySelector('.bottom-content').style.transform = 'translateY(100%)'
}
if (deltaY.value > -500 && deltaY.value < 0) {
this.document.querySelector('.ct-box').style.transform = 'translateY(0) translateX(-50%)'
this.document.querySelector('.left-content').style.transform = 'translateX(0)'
this.document.querySelector('.right-content').style.transform = 'translateX(0)'
this.document.querySelector('.bottom-content').style.transform = 'translateY(0)'
// }
// window.addEventListener('wheel', function (event) {
// deltaY.value += event.deltaY
// console.log(event.deltaY,deltaY.value,'event.deltaY');
// if (deltaY.value <= -500 &&deltaY.value >= -1000) {
// texstref.value.style.display = 'none'
// }
// if (deltaY.value > -500 && deltaY.value < 0) {
// texstref.value.style.display = 'block'
// } // if (deltaY.value >= 0) {
// }, { passive: false }); // deltaY.value = 0
// }
connectWebsocket(null, null, getWebsocket, errWebsocket); }, { passive: false });
connectWebsocket('','',getWebsocket, errWebsocket)
}); });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.container { .container {
width: 1920px; width: 1920px;
height: 1080px; height: 1080px;
position: relative; position: relative;
display: flex; // display: flex;
justify-content: center; // justify-content: center;
align-items: center;
// background-image: url('/src/assets/images/gif-bg.gif');
background-repeat: no-repeat;
/* 如果你不想让背景平铺 */
background-size: cover;
/* 或者其他你需要的大小设置 */
background-position: center;
.abs-header {
width: 100%;
height: 80px;
position: absolute;
top: 28px;
left: 0;
right: 0;
text-align: center;
font-size: 36px;
font-weight: 700;
color: #00c6ff;
}
.l-box {
position: absolute;
top: 100px;
left: 0px;
width: 410px;
height: 980px;
z-index: 2;
background: linear-gradient(to left, transparent 0%, rgba(15, 32, 54, 0.8) 50%, #102238 100%);
// background: url('/src/assets/images/preview-left.png') center center / 100% 100% no-repeat;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center; align-items: center;
// background-image: url('/src/assets/images/gif-bg.gif');
background-repeat: no-repeat;
/* 如果你不想让背景平铺 */
background-size: cover;
/* 或者其他你需要的大小设置 */
background-position: center;
.lbox1 { .header {
width: 100%; position: absolute;
height: 316px; left: 0;
top: 0;
width: 100%;
height: 72px;
background-image: url('./image/u796.png');
z-index: 2;
.title {
width: 100%;
height: 72px;
font-size: 36px;
color: #2affff;
text-align: center;
line-height: 60px;
font-weight: 700;
}
} }
}
.ct-box { .ct-box {
position: absolute; position: absolute;
top: 100px; top: 100px;
left: 445px; left: 50%;
width: 1026px; transform: translateX(-50%);
height: 180px; width: 825px;
display: flex; height: 180px;
z-index: 2; display: flex;
justify-content: space-between; z-index: 2;
justify-content: space-between;
transition: transform 1s;
.ct-sensor { .ct-sensor {
width: 100%; width: 100%;
height: 100%; height: 100%;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
.sensor-item { }
width: 146px; }
height: 100%;
.left-content {
position: absolute;
top: 0;
left: 0;
width: 557px;
height: 1080px;
box-sizing: border-box;
padding-top: 72px;
background-image: url('./image/u801.png'), url('./image/u797.png');
background-position: center, 0% 78%;
background-repeat: no-repeat, no-repeat;
padding-left: 30px;
transition: transform 1s;
}
.left-right {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; justify-content: space-between;
font-size: 14px; padding-bottom: 30px;
color: #fff;
}
.right-content {
position: absolute;
top: 0;
right: 0;
width: 557px;
height: 1080px;
box-sizing: border-box;
padding-top: 72px;
background-image: url('./image/u800.png'), url('./image/u798.png');
background-position: center, 100% 78%;
background-repeat: no-repeat, no-repeat;
padding-right: 30px;
transition: transform 1s;
align-items: flex-end;
}
.bottom-content {
position: absolute;
bottom: 0;
left: 0;
width: 1920px;
height: 184px;
background-image: url('./image/u799.png'), url('./image/u802.png');
background-position: bottom, 50% 100%;
background-repeat: no-repeat, no-repeat;
transition: transform 1s;
.zd-scroll-board {
width: 716px;
height: 120px, ;
position: absolute;
top: 28px;
left: 50%;
transform: translateX(-50%);
.sensor-icon {
width: 75px;
height: 75px;
} }
}
} }
} }
.cb-box { .checkboxlist {
position: absolute; position: absolute;
bottom: 0px; top: 2px;
left: 435px; right: 60px;
width: 1046px; z-index: 999;
height: 316px;
display: flex;
z-index: 2;
justify-content: space-between;
background: linear-gradient(to bottom, transparent 0%, rgba(15, 32, 54, 0.8) 50%, #102238 100%);
// background: url('/src/assets/images/preview-bottom.png') center center / 100% 100% no-repeat;
.cbox {
width: 48%;
height: 100%;
:deep(.el-checkbox-button__inner) {
font-size: 18px;
} }
}
.r-box {
position: absolute;
top: 100px;
right: 0px;
width: 420px;
height: 980px;
z-index: 2;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
background: linear-gradient(to right, transparent 0%, rgba(15, 32, 54, 0.8) 50%, #102238 100%);
.rbox-item {
width: 100%;
height: 316px;
}
}
} }
</style> </style>

View File

@ -1,61 +0,0 @@
<template>
<div
class="popover"
:style="{
'top': props.top + 'px',
'left': props.left + 'px',
'display': isShow ? 'inline-block' : 'none'
}"
>
<div class="popover-title">
{{ dataRef.name }}
</div>
<div class="popover-content">
{{ 'content' }}
</div>
</div>
</template>
<script lang="ts" setup name="Popover">
import { ref } from 'vue';
type PropsTypes = {
top: number;
left: number;
};
const props = withDefaults(defineProps<PropsTypes>(), {
top: 0,
left: 0,
});
const isShow = ref(false);
const dataRef = ref<any>({});
const setShow = (visible: boolean, data?: any) => {
isShow.value = visible;
if (data) dataRef.value = data;
};
defineExpose({
setShow,
});
</script>
<style scoped>
.popover {
position: absolute;
background-color: rgb(29 78 216 / 0.6);
/* background-image: url('/src/assets/images/preview-bottom.png'); */
border-radius: 5px;
font-size: 0.2rem;
color: #fff;
font-size: 30px;
}
.popover-title {
padding: 12px;
border-bottom: 1px solid #fff;
}
.popover-content {
padding: 24px;
}
</style>

View File

@ -1,385 +0,0 @@
<template>
<div id="three"></div>
<Popover ref="popoverRef" :top="popoverTop" :left="popoverLeft" :data="popoverData"></Popover>
</template>
<script lang="ts" setup name="Sence">
/* eslint-disable */
import { ref, onMounted, type Ref } from 'vue';
import Viewer, { type Animate } from '@/modules/Viewer';
import Floors from '@/modules/Floors';
import ModelLoader from '@/modules/ModelLoder';
import * as THREE from 'three';
import gsap from 'gsap';
import Event from '@/modules/Viewer/Events';
import BoxHelperWrap from '@/modules/BoxHelperWrap';
import { checkNameIncludes, findParent } from '@/utils/threejs';
import Popover from './Popover/index.vue';
let viewer: Viewer;
let modelLoader: ModelLoader;
let boxHelperWrap: BoxHelperWrap;
const popoverRef: Ref = ref(null);
const popoverTop = ref(0);
const popoverLeft = ref(0);
const popoverData = ref<any>({});
let office: any = null;
let oldOffice: any = null;
let dataCenter: any = null;
let oldDataCenter: any = null;
let modelSelect = ['zuo0', 'zuo1', 'zuo2', 'zuo3', 'zuo4', 'zuo5'];
let modelSelectName = '';
let modelMoveName = '';
let isModelSelectName = false;
onMounted(() => {
init();
initModel();
viewer.scene.traverse((item: THREE.Object3D) => {
//console.log(item, '0000000000');
});
});
const init = () => {
viewer = new Viewer('three',{width: 1920, height: 1080});
// viewer.addAxis();
// viewer.addStats();
viewer.initRaycaster();
modelLoader = new ModelLoader(viewer);
// const floors = new Floors(viewer);
// floors.addGird();
boxHelperWrap = new BoxHelperWrap(viewer);
viewer.emitter.on(Event.dblclick.raycaster, (list: THREE.Intersection[]) => {
console.log(list, 'list');
onMouseClick(list);
});
viewer.emitter.on(Event.mousemove.raycaster, (list: THREE.Intersection[]) => {
onMouseMove(list);
});
};
const initModel = () => {
// modelLoader.loadModelToScene('/models/zuo.glb', baseModel => {
// console.log(baseModel, '1111111');
// baseModel.setScalc(0.01);
// const model = baseModel.gltf.scene;
// office = baseModel;
// office.object.rotation.y = Math.PI;
// office.object.position.set(2, 0, 0);
// // model.position.set(80, 2, 90);
// office.object.children.forEach((item: any) => {
// item.name = item.name.replace('zuo', '');
// if (item.name === 'ding') {
// item.name = 6;
// }
// item.name--;
// });
// office.object.children.sort((a: { name: number; }, b: { name: number; }) => a.name - b.name).forEach((v: { name: string; }) => {
// v.name = 'zuo' + v.name;
// });
// model.name = '';
// baseModel.openCastShadow();
// oldOffice = model.clone();
// const list: THREE.Object3D<THREE.Event>[] = [];
// model.traverse(item => {
// list.push(item);
// });
// viewer.setRaycasterObjects(list);
// });
modelLoader.loadModelToScene('/models/plane.glb', baseModel => {
const model = baseModel.gltf.scene;
model.scale.set(0.01 * 3, 0.01 * 3, 0.01 * 3)
model.name = 'plane';
baseModel.openCastShadow();
const texture = (baseModel.object.children[0] as any).material.map;
// console.log(baseModel,baseModel.object.children[0], 'texture-------2222');
const fnOnj = planeAnimate(texture);
viewer.addAnimate(fnOnj);
});
let objUrl = {
mtlUrl: '/obj/goats_R&D.mtl',
objUrl: '/obj/goats_R&D.obj',
}
modelLoader.ladObjModelToScene(objUrl, baseModel => {
var scale = 0.07 / baseModel.scale.x;
baseModel.scale.set(scale, scale, scale);
const box = new THREE.Box3().setFromObject(baseModel);
const size = box.getSize(new THREE.Vector3())
// // console.log(size,'-----');
baseModel.position.set(-size.x * 0.5, -size.y * 0.1+2, -size.z * 0.5);
// baseModel.children.forEach((child) => {
// const c = child;
// const cm = c.material;
// cm.emissive = cm.color;
// cm.emissiveMap = cm.map;
// });
baseModel.name = '再登研发中心';
dataCenter = baseModel;
oldDataCenter = baseModel.clone();
const rackList: any[] = [];
baseModel.traverse(item => {
if (checkIsRack(item)) {
rackList.push(item);
}
});
// console.log(baseModel,rackList, 'rackList------111');
viewer.setRaycasterObjects(rackList);
});
// modelLoader.loadModelToScene('/models/datacenter.glb', baseModel => {
// console.log(baseModel, '1111111');
// baseModel.setScalc(0.2);
// // baseModel.object.rotation.y = Math.PI / 2;
// const model = baseModel.gltf.scene;
// model.position.set(0, 0, 0);
// model.name = '';
// baseModel.openCastShadow();
// dataCenter = baseModel;
// oldDataCenter = model.clone();
// const rackList: any[] = [];
// model.traverse(item => {
// if (checkIsRack(item)) {
// rackList.push(item);
// }
// });
// // console.log(rackList, 'rackList------');
// viewer.setRaycasterObjects(rackList);
// });
};
const planeAnimate = (texture: any): Animate => {
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
const animateFn = {
fun: () => {
const count = texture.repeat.y;
if (count <= 10) {
texture.repeat.x += 0.01;
texture.repeat.y += 0.02;
} else {
texture.repeat.x = 0;
texture.repeat.y = 0;
}
},
content: viewer,
};
return animateFn;
}
const onMouseClick = (intersects: THREE.Intersection[]) => {
if (!intersects.length) return;
const selectedObject = intersects[0].object;
let selectedObjectName = '';
const findClickModel = (object: any) => {
console.log(object, 'object');
if (object.type === 'Group') {
selectedObjectName = object.name;
}
if (object.parent && object.type !== 'Scene') {
findClickModel(object.parent);
}
};
findClickModel(selectedObject);
console.log(selectedObjectName);
// if (!selectedObjectName || !selectedObjectName.includes('')) {
// // this.scene.remove(this.label);
// return;
// }
// const selectedModel = viewer.scene.getObjectByName(selectedObjectName);
console.log(selectedObject, 'selectedObject');
//
if (selectedObject.name.includes('zuo')) {
selectOffice(selectedObject.parent);
}
//
if (!selectedObject.name.includes('zuo')) {
if (!isModelSelectName && oldOffice) {
let oldmodel = oldOffice.getObjectByName(modelMoveName);
office.object.getObjectByName(modelMoveName).traverse(function (child: { isMesh: any; material: any; name: any; }) {
if (child.isMesh) {
child.material = oldmodel.getObjectByName(child.name).material;
}
});
}
}
};
function checkIsRack(obj: any): boolean {
return checkNameIncludes(obj, 'Door');
}
const onMouseMove = (intersects: THREE.Intersection[]) => {
if (!intersects.length) {
popoverRef.value.setShow(false);
boxHelperWrap.setVisible(false);
return;
}
const selectedObject = intersects[0].object || {};
let selectedObjectName = '';
const findClickModel = (object: any) => {
if (object.name.includes('Door')) {
selectedObjectName = object.name;
return;
}
if (object.parent) {
findClickModel(object.parent);
}
};
// const findClickModel = (object: any) => {
// if (object.name.includes('zuo')) {
// selectedObjectName = object.name;
// return;
// }
// if (object.parent) {
// findClickModel(object.parent);
// }
// };
findClickModel(selectedObject);
// console.log(selectedObjectName,selectedObject, '--selectedObjectName---');
const rack = findParent(selectedObject, checkIsRack);
// console.log(rack, '-------rack---------');
if (rack) {
boxHelperWrap.attach(rack);
updateRackInfo(rack.name);
}
// if (!selectedObjectName || !selectedObjectName.includes('')) {
// //
// // viewer.scene.children[viewer.scene.children.findIndex(o => o.name === '')] = office.object = oldOffice.clone();
// return;
// }
modelSelect.forEach((item: any) => {
if (item === selectedObject.parent?.name) {
modelMoveName = item;
if (modelSelectName === modelMoveName) return;
office.object.getObjectByName(item).traverse(function (child: { isMesh: any; material: THREE.MeshPhongMaterial; }) {
if (child.isMesh) {
child.material = new THREE.MeshPhongMaterial({
side: THREE.DoubleSide,
transparent: true,
depthTest: false,
depthWrite: true, // 穿
color: 'yellow',
opacity: 0.3,
});
}
});
} else {
if (!isModelSelectName && oldOffice) {
let oldmodel = oldOffice.getObjectByName(item);
office.object.getObjectByName(item).traverse(function (child: { isMesh: any; material: any; name: any; }) {
if (child.isMesh) {
child.material = oldmodel.getObjectByName(child.name).material;
}
});
}
}
});
};
const updateRackInfo = (name: string) => {
if (name) {
popoverRef.value.setShow(true, { name });
const event = viewer.mouseEvent as MouseEvent;
popoverTop.value = event.y + 10;
popoverLeft.value = event.x + 10;
} else {
popoverRef.value.setShow(false);
}
};
const selectOffice = (model: any) => {
modelSelectName = model.name;
let oldmodel = oldOffice.getObjectByName(modelSelectName);
let modelSelectIndex = modelSelect.findIndex(v => v === modelSelectName);
office.object.children.forEach((child: any, index: number) => {
child.children.forEach((Mesh: any) => {
if (child.name === modelSelectName) {
child.children.forEach((Mesh: { material: any; name: any; }) => {
Mesh.material = oldmodel.getObjectByName(Mesh.name).material;
});
} else {
// Mesh.material = new THREE.MeshPhongMaterial({
// color: new THREE.Color('#123ca8'),
// transparent: true,
// opacity: 0.5,
// emissiveMap: Mesh.material.map,
// });
}
});
if (!model.userData.position && index > modelSelectIndex) {
gsap.to(child.position, {
y: !child.userData.position ? child.position.y + 60 : child.position.y,
duration: 2,
ease: "power1.inOut",
onComplete: () => {
child.userData.position = true;
},
});
}
if (model.userData.position && index <= modelSelectIndex) {
if (child.userData.position) {
gsap.to(child.position, {
y: oldOffice.getObjectByName(child.name).position.y,
duration: 2,
ease: "power1.inOut",
onComplete: () => {
child.userData.position = false;
},
});
}
}
});
};
</script>
<style scoped>
#three {
height: 100%;
width: 100%;
}
</style>

View File

@ -1,121 +0,0 @@
<template>
<v-chart :option="options" theme="dark" style="width: 100%;height: 100%;" />
</template>
<script setup>
import { computed } from 'vue';
const prop = defineProps({
data: {
type: Object,
default: () => {
return [
{
"devId": "48a2ec70-a60c-11ef-91f3-abd609c7e488",
"devName": "噪声监测7",
"label": "noise-7",
"place": null,
"data": 0,
"status": 0
}]
}
}
});
const bodyMax = 150;
const options = computed(() => {
let xData = []
let seriesData = []
prop.data.forEach((item) => {
xData.push(item.devName);
seriesData.push(item.data);
});
const labelSetting = {
show: true,
position: 'top',
offset: [0, -20],
formatter: function (param) {
return xData[param.dataIndex] + '\r\n' + seriesData[param.dataIndex] + 'dB';
},
fontSize: 14,
fontFamily: 'Arial',
color: '#33FFFF'
};
return {
tooltip: {
},
backgroundColor: 'transparent',
xAxis: {
data: xData,
axisTick: { show: false },
axisLine: { show: false },
axisLabel: { show: false }
},
yAxis: {
show: false,
max: bodyMax,
offset: 20,
splitLine: { show: false },
},
grid: {
top: 'center',
height: 230,
left: 0,
right: 0
},
markLine: {
z: -100
},
series: [
{
name: 'typeA',
type: 'pictorialBar',
symbolClip: true,
symbolBoundingData: bodyMax,
symbolRepeat: true, //
symbolSize: [25, 6], //
itemStyle: {
color: '#33FFFF'
},
data: seriesData.map((item) => {
let dataobj = {
value: item
}
if (item > 100) {
dataobj.itemStyle = {
color: '#FF0000'
}
}
return dataobj
}),
z: 10
},
{
name: 'full',
type: 'pictorialBar',
symbolBoundingData: bodyMax,
label: labelSetting,
animationDuration: 0,
symbolRepeat: true, //
symbolSize: [25, 6], //
itemStyle: {
color: '#ccc'
},
data: prop.data.map(item => {
return {
value: 100,
}
})
}
]
}
})
</script>
<style lang="scss" scoped></style>

View File

@ -1,37 +0,0 @@
<template>
<svg t="1730769272802" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
p-id="1039" width="256" height="256" :fill="prop.color">
<path
d="M378.105721 356.776833a62.282417 62.282417 0 0 0-0.01338-63.076668 62.287282 62.287282 0 0 0-55.100101-30.706985c-33.842635 0.76506-60.877578 28.426402-60.867847 62.273902 0.00973 33.852366 27.053187 61.499113 60.895823 62.245928a62.275119 62.275119 0 0 0 55.085505-30.736177zM751.756435 356.776833a62.27147 62.27147 0 0 0-55.114696-93.783653c-33.842635 0.76506-60.877578 28.426402-60.867848 62.273902 0.00973 33.852366 27.058053 61.499113 60.900688 62.245928a62.275119 62.275119 0 0 0 55.081856-30.736177zM540.953941 325.271948c0-17.199853-13.940139-31.139992-31.138776-31.139993-17.194987 0-31.135127 13.940139-31.135127 31.139993 0 17.193771 13.940139 31.133911 31.135127 31.13391 17.198636 0 31.138776-13.940139 31.138776-31.13391zM323.020216 761.162508a62.279984 62.279984 0 0 0 55.085505-30.731312 62.282417 62.282417 0 0 0-0.01338-63.076667 62.267821 62.267821 0 0 0-55.100101-30.706986c-33.842635 0.76506-60.877578 28.421537-60.867847 62.273903 0.00973 33.848717 27.053187 61.495464 60.895823 62.241062zM696.675795 761.162508a62.27147 62.27147 0 0 0 55.066045-93.807979 62.267821 62.267821 0 0 0-55.100101-30.706986c-33.842635 0.76506-60.877578 28.421537-60.867848 62.273903 0.00973 33.848717 27.058053 61.495464 60.901904 62.241062zM478.680038 698.922662c0 17.194987 13.940139 31.135127 31.135127 31.135127 17.198636 0 31.138776-13.940139 31.138776-31.135127 0-17.201069-13.940139-31.141208-31.138776-31.141208-17.194987 0-31.135127 13.940139-31.135127 31.141208zM665.502963 512.093656c0 17.199853 13.945005 31.139992 31.139992 31.139992 17.199853 0 31.139992-13.940139 31.139992-31.139992 0-17.193771-13.940139-31.133911-31.139992-31.133911-17.196204 0-31.139992 13.940139-31.139992 31.133911zM291.852248 512.093656c0 17.199853 13.940139 31.139992 31.139992 31.139992 17.194987 0 31.135127-13.940139 31.135127-31.139992 0-17.193771-13.940139-31.133911-31.135127-31.133911-17.199853 0-31.139992 13.940139-31.139992 31.133911zM448.952183 512.093656c0.003649 33.852366 27.053187 61.495464 60.895822 62.245928a62.27147 62.27147 0 0 0 55.08064-30.736177 62.273903 62.273903 0 0 0-55.11348-93.78487c-33.838986 0.766276-60.872713 28.422754-60.862982 62.275119z"
p-id="1040"></path>
<path
d="M970.857819 318.763468c-25.181285-59.281778-61.204765-112.580522-107.052389-158.434228-45.863436-45.863436-99.171911-81.883267-158.441526-107.059687a491.752072 491.752072 0 0 0-193.366677-39.291708c-83.403656 0-171.837974 23.574538-249.031147 66.383817-12.851541 7.89629-13.060747 22.976113-9.240314 33.865745 4.075858 5.958707 9.962803 9.099222 17.056328 9.099222 4.884705 0 9.996859-1.525254 14.800071-4.404261l0.437872-0.261507 0.451252-0.246911c72.839996-38.846538 148.71712-58.544693 225.534452-58.544694 249.379012 0 452.256024 202.881878 452.256024 452.253591 0 249.377795-202.877012 452.259673-452.256024 452.259673-249.376579 0-452.253591-202.881878-452.253591-452.259673 0-76.807602 19.694506-152.694457 58.534963-225.516207l0.246911-0.460982 0.266372-0.441521c7.265025-12.110808 1.772165-26.726-7.739387-33.862096-2.365725-1.7673-5.702066-2.038537-7.47423-2.038537-8.798793 0-18.591312 5.578002-23.351953 13.289413-42.808063 77.198038-66.383817 165.632356-66.383818 249.02993a491.870054 491.870054 0 0 0 39.292924 193.370327c25.18615 59.280562 61.195035 112.575657 107.058471 158.437876 45.858571 45.859787 99.163397 81.873537 158.434228 107.056039a491.843295 491.843295 0 0 0 193.36911 39.292924 491.928437 491.928437 0 0 0 193.359379-39.283194c59.273264-25.18615 112.57809-61.196251 158.441526-107.059687 45.858571-45.858571 81.871104-99.16218 107.052389-158.435444 26.07649-61.365319 39.292924-126.433087 39.292925-193.367894s-13.216434-131.995277-39.294141-193.370326z"
p-id="1041" class="border"></path>
</svg>
</template>
<script setup>
import { ref, onMounted } from 'vue';
const prop = defineProps({
color: '#469DE9'
});
</script>
<style lang="scss" scoped>
/** .border设置循环旋转动画效果 */
.border {
animation: rotate 3s linear infinite;
transform-origin: center;
}
@keyframes rotate {
0% {
transform: rotate(0deg) ;
}
100% {
transform: rotate(360deg);
}
}
</style>

View File

@ -1,36 +0,0 @@
<template>
<svg t="1730777236728" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
p-id="1648" width="256" height="256" :fill="prop.color">
<path
d="M512 22.26087A488.136348 488.136348 0 0 0 165.709913 165.709913 488.136348 488.136348 0 0 0 22.26087 512a488.136348 488.136348 0 0 0 143.449043 346.290087A488.136348 488.136348 0 0 0 512 1001.73913a488.136348 488.136348 0 0 0 346.290087-143.449043A488.136348 488.136348 0 0 0 1001.73913 512a488.136348 488.136348 0 0 0-143.449043-346.290087A488.136348 488.136348 0 0 0 512 22.26087m0-22.26087c282.779826 0 512 229.220174 512 512S794.779826 1024 512 1024 0 794.779826 0 512 229.220174 0 512 0z"
p-id="1649"></path>
<path
d="M748.477217 625.775304a57.677913 57.677913 0 0 0-35.328 12.198957l-73.928347-42.674087a130.715826 130.715826 0 0 0-80.339479-165.954783v-69.565217a84.057043 84.057043 0 1 0-87.485217-5.075478v74.551652a130.715826 130.715826 0 0 0-80.339478 165.954782l-73.928348 42.674087a57.566609 57.566609 0 1 0 18.18713 23.04l68.140522-39.379478a131.027478 131.027478 0 0 0 223.187478 0l68.140522 39.379478a57.655652 57.655652 0 0 0-4.786087 23.04 58.301217 58.301217 0 1 0 58.434783-58.212174z m-247.874782-258.226087a80.740174 80.740174 0 0 0 29.184 1.424696v53.648696a124.14887 124.14887 0 0 0-29.117218 0v-55.073392z m14.558608 287.47687a102.066087 102.066087 0 1 1 102.110609-102.021565 102.066087 102.066087 0 0 1-102.110609 101.954782z"
p-id="1650" class="border"></path>
</svg>
</template>
<script setup>
import { ref, onMounted } from 'vue';
const prop = defineProps({
color: '#469DE9'
});
</script>
<style lang="scss" scoped>
/** .border设置循环旋转动画效果 */
.border {
animation: rotate 3s linear infinite;
transform-origin: center;
}
@keyframes rotate {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>

View File

@ -1,36 +0,0 @@
<template>
<svg t="1731979776030" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
p-id="15886" width="256" height="256" :fill="prop.color">
<path
d="M507.44 955.95a438.912 438.912 0 0 1-172.62-35.08c-52.91-22.48-100.5-54.63-141.43-95.57-40.94-40.94-73.09-88.52-95.57-141.44a439.09 439.09 0 0 1-35.08-172.62c0-74.45 21.05-153.39 59.26-222.31 4.25-6.88 12.99-11.86 20.85-11.86 1.58 0 4.56 0.24 6.67 1.82 8.49 6.37 13.39 19.42 6.91 30.23l-0.24 0.39-0.22 0.41c-34.67 65.01-52.25 132.75-52.25 201.32 0 222.62 181.11 403.73 403.73 403.73s403.73-181.11 403.73-403.73c0-222.61-181.11-403.73-403.73-403.73-68.57 0-136.31 17.58-201.33 52.26l-0.4 0.22-0.39 0.23c-4.29 2.57-8.85 3.93-13.21 3.93-6.33 0-11.59-2.8-15.23-8.12-3.41-9.72-3.22-23.18 8.25-30.23C354.05 87.58 433 66.54 507.45 66.54a438.912 438.912 0 0 1 172.62 35.08c52.91 22.48 100.5 54.63 141.44 95.57 40.93 40.93 73.09 88.51 95.57 141.43 23.28 54.79 35.08 112.87 35.08 172.62s-11.8 117.84-35.08 172.62c-22.48 52.91-54.63 100.5-95.57 141.43-40.94 40.94-88.53 73.09-141.44 95.57a438.83 438.83 0 0 1-172.63 35.09z m0 0"
p-id="15887" class="border"></path>
<path
d="M327.36 460.82c0 22.16 18.05 40.64 39.71 40.64s39.73-18.57 39.73-40.64c3.62-25.85-18.05-40.61-39.73-40.61s-39.71 18.44-39.71 40.61z m377.59-94.43c-14.46 0-25.3 11.09-25.3 22.16 3.62 11.07 14.46 22.16 25.3 22.16 14.43 0 25.27-11.09 25.27-22.16s-10.84-22.16-25.27-22.16z m-110.23 18.29c21.68 0 39.73-18.56 39.73-40.61s-18.06-40.61-39.73-40.61c-21.67 0-39.73 18.57-39.73 40.61-3.6 22.09 14.46 40.54 39.73 40.54v0.07zM429.23 395.7c18.08 0 36.11-14.78 36.11-33.23 0-18.45-14.43-33.21-36.11-33.21-18.06 0-36.11 14.76-36.11 33.23s14.46 33.21 36.11 33.21z m178.99 95.33c0 18.57 14.46 33.23 36.11 33.23 18.05 0 36.11-14.78 36.11-33.23 0-18.45-14.43-33.23-36.11-33.23-17.96 0-36.11 14.76-36.11 33.23z m-89.64-3.02c18.05 0 28.89-14.87 28.89-29.54s-14.43-29.43-28.89-29.43c-18.05 0-28.89 14.64-28.89 29.43 0 14.78 14.45 29.54 28.89 29.54z m178.2 63.15c-3.88 0-7.77 0-9.7 2-77.74 55.51-147.71 15.85-149.66 13.92-145.76-91.25-242.9 5.85-242.9 5.85a10.313 10.313 0 0 0-3.88 7.94c0.47 2.98 1.81 5.75 3.88 7.96 3.9 5.96 11.6 3.97 17.5 0 1.95-3.97 81.62-81.22 209.9-1.97 1.95 1.97 33.05 19.82 77.74 19.82 29.15 0 66.07-7.91 102.99-33.7a14.953 14.953 0 0 0 1.95-17.85 10.057 10.057 0 0 0-7.82-3.97z m-383.26-185a29.21 29.21 0 0 0 20.56-8.77c5.42-5.54 8.41-13 8.33-20.75 0.19-16.14-12.73-29.39-28.87-29.59a29.227 29.227 0 0 0-28.89 29.54 29.22 29.22 0 0 0 8.3 20.77 29.22 29.22 0 0 0 20.57 8.8z m57.14 267.22h-32.77v95.15h22.49v-31.52h10.91c19.7 0 36.9-9.98 36.9-32.65 0.04-23.55-16.95-30.98-37.53-30.98z m-0.49 45.58h-9.79v-27.52h9.17c10.79 0 16.8 3.34 16.8 12.93 0 9.58-5.27 14.59-16.18 14.59z m103.92-4.48c-1.76 5.5-3.27 11.6-5.15 17.41h-0.63c-1.76-5.87-3.27-11.91-5.15-17.41l-14.81-41.1h-24.23v95.15h20.08v-32.61c-0.39-11.05-1.35-22.07-2.88-33.02h0.51l7.52 22.79 12.67 34.81h12.3l12.56-34.81 7.77-22.79h0.51a320.218 320.218 0 0 0-2.88 33.02v32.72h20.38V633.5h-24.27l-14.3 40.98z m101.23-41.1h-16.45a62.13 62.13 0 0 1-23.21 8.59v14.09h17.2v54.14h-19.82v18.45H592V710.2h-16.69v-76.82z m62.66-1.79c-19.68 0-33 16.13-33 48.9 0 32.77 13.32 49.94 33 49.94s33.14-17.15 33.14-49.94c-0.01-32.79-13.42-48.9-33.14-48.9z m0 81.23c-6.64 0-11.9-6.15-11.9-32.28 0-26.13 5.27-31.35 11.9-31.35 6.64 0 12.07 5.38 12.07 31.35 0 25.97-5.41 32.23-12.07 32.23v0.05z m0 0"
p-id="15888"></path>
</svg>
</template>
<script setup>
import { ref, onMounted } from 'vue';
const prop = defineProps({
color: '#469DE9'
});
</script>
<style lang="scss" scoped>
/** .border设置循环旋转动画效果 */
.border {
animation: rotate 3s linear infinite;
transform-origin: center;
}
@keyframes rotate {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>

View File

@ -1,36 +0,0 @@
<template>
<svg t="1731979377696" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
p-id="4643" width="256" height="256" :fill="prop.color">
<path
d="M510.24 954.86a438.195 438.195 0 0 1-172.33-35.02c-52.82-22.44-100.33-54.54-141.2-95.41-40.87-40.87-72.97-88.37-95.41-141.2A438.195 438.195 0 0 1 66.28 510.9c0-74.33 21.01-153.14 59.16-221.94 4.24-6.87 12.97-11.84 20.81-11.84 1.58 0 4.55 0.24 6.66 1.82 8.48 6.36 13.37 19.39 6.9 30.18l-0.24 0.39-0.22 0.41c-34.62 64.9-52.17 132.53-52.17 200.98 0 222.25 180.81 403.06 403.06 403.06S913.3 733.15 913.3 510.9c0-222.24-180.81-403.06-403.06-403.06-68.46 0-136.08 17.56-201 52.18l-0.4 0.22-0.39 0.23c-4.28 2.57-8.84 3.93-13.19 3.93-6.32 0-11.57-2.8-15.2-8.11-3.4-9.71-3.22-23.14 8.24-30.18 68.8-38.15 147.61-59.16 221.94-59.16a438.16 438.16 0 0 1 172.33 35.02c52.82 22.44 100.33 54.54 141.2 95.41 40.86 40.87 72.97 88.37 95.41 141.2 23.24 54.7 35.02 112.68 35.02 172.33s-11.78 117.64-35.02 172.33c-22.44 52.82-54.54 100.33-95.41 141.2-40.87 40.87-88.38 72.97-141.2 95.41a438.362 438.362 0 0 1-172.33 35.01z m0 0"
p-id="4644" class="border"></path>
<path
d="M314.61 465.3c0 22.12 18.02 40.53 39.63 40.53 21.61 0 39.66-18.51 39.66-40.53 3.61-25.8-18.02-40.54-39.66-40.54-21.64 0.01-39.63 18.33-39.63 40.54z m376.86-94.32c-14.41-0.09-25.13 10.93-25.13 22.03 3.61 11.05 14.41 22.1 25.22 22.1 14.43 0 25.25-11.05 25.25-22.1s-10.91-22.12-25.34-22.12v0.09z m-110 18.25c21.63 0 39.66-18.53 39.66-40.54 0-22-18.02-40.54-39.66-40.54-21.63 0-39.63 18.53-39.63 40.54-3.61 22.01 14.41 40.44 39.63 40.44v0.1z m-165.15 11.05c18.02 0 36.04-14.73 36.04-33.17s-14.43-33.26-36.04-33.26c-18.02 0-36.04 14.75-36.04 33.17 0 18.41 14.41 33.17 36.04 33.17v0.09z m178.63 95.13c0 18.53 14.43 33.17 36.04 33.17 18.02 0 36.04-14.75 36.04-33.17 0-18.41-14.41-33.17-36.04-33.17-17.92-0.04-36.04 14.64-36.04 33.17z m-89.48-3.03c18.02 0 28.84-14.73 28.84-29.49 0-14.76-14.41-29.46-28.84-29.46-18.02 0-28.84 14.73-28.84 29.46s14.43 29.44 28.84 29.44v0.05z m177.87 63.05c-3.87 0-7.76 0-9.68 1.97-77.6 55.41-147.46 15.84-149.38 13.9-145.49-91.12-242.45 5.84-242.45 5.84a10.358 10.358 0 0 0-3.87 7.92c0.47 2.97 1.81 5.73 3.87 7.92 3.89 5.93 11.58 3.96 17.46 0 1.95-3.96 81.46-81.07 209.51-1.97 1.95 1.97 32.98 19.78 77.6 19.78 29.09 0 65.95-7.92 102.82-33.65a14.92 14.92 0 0 0 1.92-17.79 9.92 9.92 0 0 0-7.8-3.96v0.04zM300.8 370.73c16.1-0.18 29.01-13.37 28.84-29.46a29.16 29.16 0 0 0-28.82-29.53c-16.1 0.19-29.01 13.38-28.84 29.49a29.1 29.1 0 0 0 8.29 20.73c5.41 5.52 12.8 8.68 20.53 8.77z m27.15 266.72h-32.68v94.97h22.42v-31.45h10.89c19.66 0 36.83-9.98 36.83-32.59-0.01-23.52-16.91-30.93-37.46-30.93z m-0.51 45.59h-9.75v-27.57h9.15c10.77 0 16.77 3.31 16.77 12.9s-5.26 14.67-16.17 14.67z m103.75-4.64c-1.76 5.49-3.27 11.58-5.14 17.37h-0.6c-1.74-5.88-3.24-11.88-5.12-17.37l-14.78-41.02h-24.11v94.97h19.92v-32.41c-0.39-11.04-1.35-22.05-2.87-32.98h0.51l7.5 22.75 12.65 34.75h12.28l12.53-34.75 7.76-22.75h0.51a316.917 316.917 0 0 0-2.87 32.98v32.57h20.4v-94.97h-24.3l-14.27 40.86z m86.91 36.23c14.29-14.69 28.05-32.71 28.05-49.06 0-18.16-12.51-29.9-30.55-29.9-13.27 0-21.8 4.84-30.95 14.69l12.16 12.28c4.38-4.86 9.26-9.27 15.77-9.27 7.39 0 12.16 4.63 12.16 13.44 0 13.9-15.66 31.04-38.96 52.65v13.02h64.65v-19.16h-17.19c-5.07 0.13-10.13 0.57-15.14 1.31z m60.75-8.57c-5.8-0.36-11.23 2.86-13.69 8.12a14.157 14.157 0 0 0 2.52 15.72 14.158 14.158 0 0 0 15.55 3.42c5.39-2.16 8.92-7.39 8.9-13.21 0.18-3.66-1.15-7.24-3.68-9.9a13.39 13.39 0 0 0-9.7-4.16h0.1z m62.27-35.51c-3.31-0.06-6.6 0.59-9.64 1.92l1.37-16.21h33.19v-18.9h-52.35l-2.32 47.02 9.75 6.51c5.54-3.57 8.04-4.63 13.16-4.63 8.04 0 13.66 5.12 13.66 14.69s-5.63 14.82-14.66 14.82c-7.39 0-13.9-3.96-19.16-9.06l-10.33 14.43a44.022 44.022 0 0 0 32.57 13.18c17.9 0 33.7-12.39 33.7-33.75 0-20.57-13.29-30.02-29.07-30.02h0.13z m0 0"
p-id="4645"></path>
</svg>
</template>
<script setup>
import { ref, onMounted } from 'vue';
const prop = defineProps({
color: '#469DE9'
});
</script>
<style lang="scss" scoped>
/** .border设置循环旋转动画效果 */
.border {
animation: rotate 3s linear infinite;
transform-origin: center;
}
@keyframes rotate {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>

View File

@ -1,36 +0,0 @@
<template>
<svg t="1730777853051" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
p-id="2254" id="mx_n_1730777853052" width="256" height="256" :fill="prop.color">
<path
d="M511.952979 1023.896979a505.462446 505.462446 0 0 1-198.72418-40.381232c-60.914463-25.881164-115.693372-62.891387-162.824501-110.022515-47.131128-47.131128-84.141351-101.902162-110.022514-162.8245a505.462446 505.462446 0 0 1-40.381233-198.72418c0-85.708713 24.227164-176.592083 68.223569-255.928957 4.891115-7.923448 14.956887-13.657316 23.998754-13.657316 1.8194 0 5.245543 0.275667 7.679287 2.095067 9.774353 7.332734 15.421582 22.352631 7.954953 34.797013l-0.275667 0.456819-0.252038 0.472571C67.412872 355.019318 47.17106 433.009363 47.17106 511.944552c0 256.283385 208.498533 464.781919 464.781919 464.781918s464.781919-208.498533 464.781919-464.781918-208.498533-464.781919-464.781919-464.781919c-78.943064 0-156.925233 20.241811-231.780554 60.166224l-0.464696 0.252039-0.448943 0.26779c-4.938372 2.961448-10.191791 4.52881-15.208925 4.52881-7.293353 0-13.342268-3.229238-17.532401-9.349039-3.922343-11.192068-3.709686-26.692412 9.498686-34.804889 79.328998-43.996404 170.212368-68.223568 255.928957-68.223568a505.430941 505.430941 0 0 1 198.72418 40.381232c60.906587 25.873288 115.693372 62.891387 162.824501 110.022515 47.123252 47.123252 84.141351 101.902162 110.022515 162.824501 26.794802 63.072539 40.381232 129.933526 40.381232 198.72418s-13.58643 135.659517-40.381232 198.72418c-25.881164 60.914463-62.891387 115.693372-110.022515 162.824501-47.131128 47.131128-101.910038 84.141351-162.824501 110.022514a505.525456 505.525456 0 0 1-198.716304 40.373356z"
p-id="2255" class="border"></path>
<path
d="M716.088103 531.012811c-23.57344-52.345167-57.480443-102.288095-93.364371-155.160967-25.014783-36.852699-50.872319-74.949835-73.587254-114.74823l-0.181153-0.322923-38.506698-78.344474a1190.187004 1190.187004 0 0 0-16.587259 32.930355c-7.758048 15.783887-15.783887 32.111232-24.227164 46.855462-23.124497 40.538756-47.942376 79.116341-71.949007 116.425858-30.945555 48.076271-62.930768 97.79079-91.820637 152.514566-28.094374 69.444378-21.454745 144.449347 18.257012 205.867886 41.641423 64.411492 113.488039 104.438295 187.508483 104.438295 1.252314 0 2.496753-0.015752 3.756944-0.039381 75.761083-1.236562 145.024309-41.239737 185.255893-107.005934 38.490946-62.930768 44.256318-138.975394 15.445211-203.410513z m-41.594166 166.19551c-30.709269 58.323196-95.538199 103.595543-157.933386 106.060791h-0.716733c-65.269996-1.559486-126.877564-41.869832-160.90271-100.137895-34.607984-59.284091-34.214175-131.359117-6.395468-188.296103 25.314079-49.493985 83.897189-140.542756 130.122555-203.953971a37.293765 37.293765 0 0 1 61.158625 0.669476c21.375983 30.638384 49.470357 71.61033 66.994882 99.94099 19.462068 31.47326 37.845099 61.198006 50.9117 81.16415l0.3308 0.535581c40.341851 69.365616 49.186814 141.818699 16.429735 204.016981zM501.745435 594.298007c-63.994053 35.198698-126.475878 15.07503-159.390481-1.016029-1.590991 36.56128 7.529639 74.524521 27.133479 108.1086 31.796184 54.463862 85.015608 86.535713 146.032461 88.000685l0.669476-0.007876c50.4155-1.992676 99.232133-29.716869 130.098926-72.413702a416.099181 416.099181 0 0 0 20.604116-37.333147c14.051125-34.584356 16.603011-71.964759 7.742296-109.778353-36.33287-8.616553-101.847028-14.633963-172.890273 24.439822z"
p-id="2256"></path>
</svg>
</template>
<script setup>
import { ref, onMounted } from 'vue';
const prop = defineProps({
color: '#469DE9'
});
</script>
<style lang="scss" scoped>
/** .border设置循环旋转动画效果 */
.border {
animation: rotate 3s linear infinite;
transform-origin: center;
}
@keyframes rotate {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>

View File

@ -1,36 +0,0 @@
<template>
<svg t="1730777586016" class="icon" viewBox="0 0 1152 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
p-id="1965" width="256" height="256" :fill="prop.color">
<path
d="M160 512c0-32-19.2-61.44-48.64-74.24l-10.24-3.84 1.28-11.52c17.92-96 64-183.04 133.12-252.16 90.88-90.88 211.2-140.8 340.48-140.8 176.64 0 337.92 96 422.4 250.88 3.84 6.4 12.8 8.96 19.2 5.12 6.4-3.84 8.96-12.8 5.12-19.2C934.4 102.4 762.88 0 576 0c-69.12 0-135.68 14.08-198.4 39.68-61.44 25.6-115.2 62.72-162.56 110.08-47.36 47.36-83.2 102.4-108.8 162.56-15.36 35.84-25.6 72.96-32 110.08l-1.28 8.96-8.96 2.56c-38.4 7.68-64 40.96-64 78.08 0 43.52 35.84 79.36 79.36 79.36 44.8 0 80.64-35.84 80.64-79.36z m912.64-79.36c-43.52 0-79.36 35.84-79.36 79.36 0 32 19.2 61.44 48.64 74.24l10.24 3.84-2.56 11.52c-17.92 96-64 183.04-133.12 252.16-90.88 90.88-211.2 140.8-340.48 140.8-176.64 0-337.92-96-422.4-250.88-2.56-5.12-7.68-7.68-12.8-7.68-2.56 0-5.12 0-6.4 1.28-3.84 1.28-6.4 5.12-6.4 8.96-1.28 3.84-1.28 7.68 1.28 11.52C217.6 921.6 389.12 1024 576 1024c69.12 0 135.68-14.08 198.4-39.68 61.44-25.6 115.2-62.72 162.56-110.08 47.36-47.36 83.2-102.4 108.8-162.56 15.36-35.84 25.6-72.96 32-110.08l1.28-8.96 8.96-2.56c38.4-7.68 64-40.96 64-78.08 0-43.52-35.84-79.36-79.36-79.36z"
p-id="1966" class="border"></path>
<path
d="M266.24 423.68h-69.12v-21.76h162.56v21.76h-69.12V627.2h-25.6V423.68zM382.72 401.92H409.6l38.4 124.16c7.68 26.88 12.8 47.36 21.76 74.24h1.28c8.96-26.88 14.08-47.36 23.04-74.24l37.12-124.16h25.6L483.84 627.2h-29.44l-71.68-225.28zM569.6 514.56c0-71.68 39.68-115.2 94.72-115.2 56.32 0 94.72 43.52 94.72 115.2s-39.68 117.76-94.72 117.76c-55.04-1.28-94.72-46.08-94.72-117.76z m163.84 0c0-57.6-26.88-93.44-69.12-93.44-40.96 0-69.12 35.84-69.12 93.44s26.88 94.72 69.12 94.72c42.24 0 69.12-37.12 69.12-94.72zM794.88 514.56c0-71.68 42.24-116.48 98.56-116.48 26.88 0 48.64 12.8 61.44 26.88l-14.08 16.64c-11.52-12.8-26.88-21.76-46.08-21.76-43.52 0-72.96 35.84-72.96 93.44s28.16 94.72 71.68 94.72c21.76 0 38.4-8.96 53.76-25.6l14.08 15.36c-17.92 20.48-39.68 32-69.12 32-56.32 1.28-97.28-42.24-97.28-115.2z"
p-id="1967"></path>
</svg>
</template>
<script setup>
import { ref, onMounted } from 'vue';
const prop = defineProps({
color: '#469DE9'
});
</script>
<style lang="scss" scoped>
/** .border设置循环旋转动画效果 */
.border {
animation: rotate 3s linear infinite;
transform-origin: center;
}
@keyframes rotate {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>

View File

@ -1,36 +0,0 @@
<template>
<svg t="1730777903037" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
p-id="2469" width="256" height="256" :fill="prop.color">
<path
d="M511.2 959.1c-59.7 0.1-118.7-11.9-173.6-35.3-53.2-22.6-101.1-54.9-142.3-96.1-41.2-41.2-73.5-89-96.1-142.3a441 441 0 0 1-35.3-173.6c0-74.9 21.2-154.3 59.6-223.6 4.3-6.9 13.1-11.9 21-11.9 1.6 0 4.6 0.2 6.7 1.8 8.5 6.4 13.5 19.5 6.9 30.4l-0.2 0.4-0.2 0.4c-34.9 65.4-52.6 133.5-52.6 202.5 0 223.9 182.2 406.1 406.1 406.1 223.9 0 406.1-182.2 406.1-406.1 0-223.9-182.2-406.1-406.1-406.1-69 0-137.1 17.7-202.5 52.6l-0.4 0.2-0.4 0.2c-4.3 2.6-8.9 4-13.3 4-6.4 0-11.7-2.8-15.3-8.2-3.4-9.8-3.2-23.3 8.3-30.4 69.3-38.4 148.7-59.6 223.6-59.6 59.7-0.1 118.7 11.9 173.6 35.3 53.2 22.6 101.1 54.9 142.3 96.1 41.2 41.2 73.5 89 96.1 142.3 23.4 55.1 35.3 113.5 35.3 173.6s-11.9 118.5-35.3 173.6c-22.6 53.2-54.9 101.1-96.1 142.3-41.2 41.2-89 73.5-142.3 96.1a441 441 0 0 1-173.6 35.3z m0 0"
p-id="2470" class="border"></path>
<path
d="M531.5 583.1l-6-2.7V352.8c0-9.5-12-17.6-26.2-17.6s-26.2 8-26.2 17.6v227.7l-6.1 2.7c-28.8 12.9-47.5 41.9-47.5 73.8 0 44.5 35.8 80.7 79.7 80.7 43.9 0 79.7-36.2 79.7-80.7 0.1-31.9-18.5-61-47.4-73.9z m81.7-48.4l-3.2-3.1V286.8c0-24-12.3-47.2-33.8-63.6-20.7-15.9-48-24.6-76.9-24.6-28.9 0-56.2 8.7-76.9 24.6-21.5 16.5-33.8 39.7-33.8 63.6v244.9l-3.2 3.1c-33.1 31.6-52.1 76.2-52.1 122.3 0 44.9 17.3 87.1 48.6 118.9 31.4 31.8 73 49.2 117.4 49.2 44.3 0 86-17.5 117.4-49.2 31.4-31.8 48.6-74 48.6-118.9 0-46.2-19-90.8-52.1-122.4z m-113.9 263c-76.6 0-138.9-63.1-138.9-140.7 0-42.1 18.3-81.6 50.4-108.4l4.9-4.1V286.8c0-16.5 9.6-32.6 26.3-44.1 15.7-10.8 36.1-16.8 57.4-16.8 21.3 0 41.7 5.9 57.4 16.8 16.7 11.5 26.3 27.5 26.3 44.1v257.7l4.9 4.1c32 26.9 50.4 66.4 50.4 108.4-0.2 77.5-62.5 140.7-139.1 140.7zM642 304.5h36.4c5.9 0 10.6-3.9 10.6-8.7 0-4.8-4.8-8.7-10.6-8.7H642c-5.9 0-10.6 3.9-10.6 8.7 0 4.8 4.8 8.7 10.6 8.7z m36.4 20.6H642c-5.9 0-10.6 3.9-10.6 8.7 0 4.8 4.8 8.7 10.6 8.7h36.4c5.9 0 10.6-3.9 10.6-8.7 0-4.9-4.7-8.7-10.6-8.7z m0 37.9H642c-5.9 0-10.6 3.9-10.6 8.7 0 4.8 4.8 8.7 10.6 8.7h36.4c5.9 0 10.6-3.9 10.6-8.7 0-4.8-4.7-8.7-10.6-8.7z m0 37.9H642c-5.9 0-10.6 3.9-10.6 8.7 0 4.8 4.8 8.7 10.6 8.7h36.4c5.9 0 10.6-3.9 10.6-8.7 0-4.8-4.7-8.7-10.6-8.7z m0 38H642c-5.9 0-10.6 3.9-10.6 8.7s4.8 8.7 10.6 8.7h36.4c5.9 0 10.6-3.9 10.6-8.7 0-4.9-4.7-8.7-10.6-8.7z m0 37.9H642c-5.9 0-10.6 3.9-10.6 8.7 0 4.8 4.8 8.7 10.6 8.7h36.4c5.9 0 10.6-3.9 10.6-8.7 0-4.8-4.7-8.7-10.6-8.7z m0 0"
p-id="2471"></path>
</svg>
</template>
<script setup>
import { ref, onMounted } from 'vue';
const prop = defineProps({
color: '#469DE9'
});
</script>
<style lang="scss" scoped>
/** .border设置循环旋转动画效果 */
.border {
animation: rotate 3s linear infinite;
transform-origin: center;
}
@keyframes rotate {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>

View File

@ -1,34 +0,0 @@
<template>
<svg t="1730776964174" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
p-id="7087" width="256" height="256" :fill="prop.color">
<path
d="M631.466667 230.4l-17.066667-8.533333 17.066667-38.4 17.066666 8.533333c76.8 38.4 140.8 98.133333 179.2 174.933333l8.533334 17.066667-38.4 21.333333-8.533334-17.066666c-34.133333-68.266667-89.6-123.733333-157.866666-157.866667z m17.066666 601.6l-17.066666 8.533333-17.066667-38.4 17.066667-8.533333c68.266667-34.133333 123.733333-89.6 162.133333-157.866667l8.533333-17.066666 38.4 21.333333-8.533333 17.066667c-42.666667 76.8-106.666667 136.533333-183.466667 174.933333zM674.133333 170.666667l-17.066666-8.533334 17.066666-38.4 17.066667 8.533334c85.333333 42.666667 157.866667 110.933333 200.533333 196.266666l8.533334 17.066667-38.4 21.333333-8.533334-17.066666c-38.4-81.066667-102.4-140.8-179.2-179.2z m192 490.666666l38.4 21.333334-8.533333 17.066666c-42.666667 85.333333-115.2 153.6-200.533333 196.266667l-17.066667 8.533333-17.066667-38.4 17.066667-8.533333c76.8-38.4 140.8-98.133333 183.466667-174.933333l4.266666-21.333334zM392.533333 793.6l17.066667 8.533333-17.066667 38.4-17.066666-8.533333c-76.8-38.4-140.8-98.133333-179.2-174.933333l-12.8-17.066667 38.4-21.333333 8.533333 17.066666c38.4 68.266667 93.866667 123.733333 162.133333 157.866667z m0-610.133333l17.066667 38.4-17.066667 8.533333c-68.266667 34.133333-123.733333 89.6-162.133333 157.866667l-8.533333 17.066666-38.4-17.066666 8.533333-17.066667c42.666667-81.066667 106.666667-140.8 183.466667-179.2l17.066666-8.533333zM157.866667 366.933333l-38.4-21.333333 8.533333-17.066667c42.666667-85.333333 115.2-153.6 200.533333-196.266666l17.066667-8.533334 17.066667 38.4-12.8 8.533334c-76.8 38.4-145.066667 98.133333-183.466667 174.933333l-8.533333 21.333333z m192 490.666667l17.066666 8.533333-17.066666 38.4-17.066667-8.533333c-85.333333-42.666667-157.866667-110.933333-200.533333-196.266667l-8.533334-17.066666 38.4-21.333334 8.533334 17.066667c38.4 76.8 102.4 140.8 179.2 179.2zM512 981.333333C251.733333 981.333333 42.666667 772.266667 42.666667 512S251.733333 42.666667 512 42.666667s469.333333 213.333333 469.333333 469.333333-213.333333 469.333333-469.333333 469.333333z m0-981.333333C230.4 0 0 230.4 0 512s230.4 512 512 512 512-230.4 512-512S793.6 0 512 0z m426.666667 512c0 25.6-17.066667 42.666667-42.666667 42.666667s-42.666667-17.066667-42.666667-42.666667 17.066667-42.666667 42.666667-42.666667 42.666667 21.333333 42.666667 42.666667z m-426.666667 85.333333c-46.933333 0-85.333333-38.4-85.333333-85.333333s38.4-85.333333 85.333333-85.333333 85.333333 38.4 85.333333 85.333333-38.4 85.333333-85.333333 85.333333z m0-213.333333c-72.533333 0-128 59.733333-128 128s59.733333 128 128 128 128-59.733333 128-128-59.733333-128-128-128z m0 298.666667c-93.866667 0-170.666667-76.8-170.666667-170.666667s76.8-170.666667 170.666667-170.666667 170.666667 76.8 170.666667 170.666667-76.8 170.666667-170.666667 170.666667z m0-384c-119.466667 0-213.333333 93.866667-213.333333 213.333333s93.866667 213.333333 213.333333 213.333333 213.333333-93.866667 213.333333-213.333333-98.133333-213.333333-213.333333-213.333333z"
p-id="7088" class="border"></path>
</svg>
</template>
<script setup>
import { ref, onMounted } from 'vue';
const prop = defineProps({
color: '#469DE9'
});
</script>
<style lang="scss" scoped>
/** .border设置循环旋转动画效果 */
.border {
animation: rotate 3s linear infinite;
transform-origin: center;
}
@keyframes rotate {
0% {
transform: rotate(0deg) ;
}
100% {
transform: rotate(360deg);
}
}
</style>

View File

@ -1,39 +0,0 @@
<template>
<svg t="1730777460223" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
p-id="1806" width="256" height="256" :fill="prop.color">
<path
d="M204.8 869.171l29.491-29.491a431.923 431.923 0 0 1-33.382-31.54l-29.082 29.492q15.975 16.589 32.973 31.54z"
p-id="1807"></path>
<path
d="M512 40.96a471.04 471.04 0 0 0-367.206 765.952l29.286-28.672a430.08 430.08 0 1 1 92.16 87.04l-28.672 29.491A471.04 471.04 0 1 0 512 40.96z"
p-id="1808" class="border"></path>
<path
d="M522.24 634.88v-40.96a81.92 81.92 0 0 0 0-163.84v-40.96a122.88 122.88 0 0 1 0 245.76z m-40.96-350.003a20.48 20.48 0 0 0-4.096 0 86.835 86.835 0 0 0-67.584 24.78l-63.488 63.489H276.48a40.96 40.96 0 0 0-40.96 40.96v204.8a40.96 40.96 0 0 0 40.96 40.96h77.005l55.296 55.296a81.92 81.92 0 0 0 67.379 22.118 20.48 20.48 0 0 0 5.12 0 20.48 20.48 0 0 0 20.48-20.48V305.357a20.48 20.48 0 0 0-20.48-20.48zM460.8 697.549a40.96 40.96 0 0 1-23.142-11.264l-66.15-66.15H358.4v-1.23h-81.92v-204.8h27.648l-1.229 1.23h57.959l76.595-76.596A40.96 40.96 0 0 1 460.8 327.68v369.869z m266.24-201.933H768a20.48 20.48 0 0 1 0 40.96h-40.96a20.48 20.48 0 0 1 0-40.96z m-80.691-153.6l29.491-29.082a20.48 20.48 0 0 1 28.877 28.877l-28.877 29.082a20.48 20.48 0 0 1-28.877-28.877z m36.25 311.091l28.876 28.877a20.48 20.48 0 1 1-28.877 28.877l-28.876-28.877a20.48 20.48 0 1 1 28.876-28.877z"
p-id="1809"></path>
</svg>
</template>
<script setup>
import { ref, onMounted } from 'vue';
const prop = defineProps({
color: '#469DE9'
});
</script>
<style lang="scss" scoped>
/** .border设置循环旋转动画效果 */
.border {
animation: rotate 3s linear infinite;
transform-origin: center;
}
@keyframes rotate {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>

View File

@ -1,514 +0,0 @@
<template>
<div class="container">
<div class="header">
<div class="title">研发中心环境实时监测系统</div>
</div>
<div class="ct-box">
<div class="ct-sensor">
<SensorNumLoop :sensorData="item" v-for="(item, index) in sensor_list" :key="index" />
</div>
</div>
<div class="left-content left-right" ref="leftContentRef">
<Lr1 :data="avg_temp_humi.four" />
<Lr2 :deptId="'113'" />
<Lr3 :public_list="noiseDataList.four.public_noise" :office_list="noiseDataList.four.office_noise" />
<Lr4 :data="TVOC_CH2O['4f']" />
</div>
<div class="right-content left-right" ref="rightContentRef">
<Lr1 :data="avg_temp_humi.five" />
<Lr2 :deptId="'114'" />
<Lr3 :public_list="noiseDataList.five.public_noise" :office_list="noiseDataList.five.office_noise" />
<Lr4 :data="TVOC_CH2O['5f']" />
</div>
<div class="bottom-content" ref="bottomContentRef">
<ZdScrollBoard ref="devList" :config="zd_config" class="zd-scroll-board" />
</div>
<div class="checkboxlist">
<el-radio-group v-model="radioGroup1" :fill="'#105F88'" size="large">
<el-radio-button label="四层" value="四层"></el-radio-button>
<el-radio-button label="五层" value="五层"></el-radio-button>
</el-radio-group>
</div>
<!-- <Sence /> -->
</div>
</template>
<script setup>
import { ref, reactive, onMounted, computed, watch } from 'vue';
import Sence from './component/Sence.vue';
import Lr1 from './component/Lr1.vue';
import Lr2 from './component/Lr2.vue';
import Lr3 from './component/Lr3.vue';
import Lr4 from './component/Lr4.vue';
import ZdScrollBoard from "@/components/ZdScrollBoard/index.vue";
import SensorNumLoop from './component/SensorNumLoop.vue';
import useR_D_EnvironmentStore from '@/store/modules/r_d_environment'
import { connectWebsocket, closeWebsocket} from "@/utils/websocket";
import { getSensorByDept } from '@/api/screen/R_D_Environment';
let R_D_EnvironmentStore = useR_D_EnvironmentStore()
let deltaY = ref(0)
let avg_temp_humi = computed(() => {
return R_D_EnvironmentStore.getLayerData
})
let noiseDataList = computed(() => {
return R_D_EnvironmentStore.getNoiseData
})
let TVOC_CH2O = reactive({
'4f': {
ch2o: [],
tvoc: []
},
'5f': {
ch2o: [],
tvoc: []
}
})
let sensor_list = computed(() => {
let sensorData = R_D_EnvironmentStore.sensorData
return [
{
component: 'SvgWendu',
unit: '℃',
type: 'AirTemp_Reg',
limit: 40,
list: sensorData['temp_humi']?.map(sensor => {
return {
id: sensor.deviceId,
name: sensor.name,
value: sensor.temp,
status: sensor.status
}
})
},
{
component: 'SvgShidu',
unit: '%RH',
type: 'AirHumi_Reg',
limit: 90,
list: sensorData['temp_humi']?.map(sensor => {
return {
id: sensor.deviceId,
name: sensor.name,
value: sensor.humidity,
status: sensor.status
}
})
},
{
component: 'SvgJiaquan',
unit: 'mg/m³',
type: 'CH2O',
limit: 0.08,
list: sensorData['TVOC_CH2O']?.filter(sensor => sensor.type === 'CH2O').map(sensor => {
return {
id: sensor.deviceId,
name: sensor.name,
value: sensor.data,
status: sensor.status
}
})
},
{
component: 'SvgTVOC',
unit: 'mg/m³',
type: 'TVOC',
limit: 0.5,
list: sensorData['TVOC_CH2O']?.filter(sensor => sensor.type === 'TVOC').map(sensor => {
return {
id: sensor.deviceId,
name: sensor.name,
value: sensor.data,
status: sensor.status
}
})
},
{
component: 'SvgPm25',
unit: 'mg/m³',
type: 'HIGH_PM25_Reg',
limit: 30,
list: sensorData['dust']?.filter(sensor => sensor.type === 'HIGH_PM25_Reg').map(sensor => {
return {
id: sensor.deviceId,
name: sensor.name,
value: sensor.data,
status: sensor.status
}
})
},
{
component: 'SvgPm10',
unit: 'mg/m³',
type: 'HIGH_PM10_Reg',
limit: 30,
list: sensorData['dust']?.filter(sensor => sensor.type === 'HIGH_PM10_Reg').map(sensor => {
return {
id: sensor.deviceId,
name: sensor.name,
value: sensor.data,
status: sensor.status
}
})
},
{
component: 'SvgZaosheng',
unit: 'dB',
type: 'Noise_Reg',
limit: 85,
list: sensorData['noise']?.map(sensor => {
return {
id: sensor.deviceId,
name: sensor.name,
value: sensor.data,
status: sensor.status
}
})
},
{
component: 'SvgYanwu',
unit: 'mg/m³',
type: 'Smoke_Reg',
limit: 100,
list: sensorData['Smoke']?.map(sensor => {
return {
id: sensor.deviceId,
name: sensor.name,
value: sensor.data,
status: sensor.status
}
})
}
]
})
const radioGroup1 = ref('四层')
let zd_config = ref({
header: ['报警时间', '报警内容', '持续时长', '报警设备'],
rowNum: 2,
headerHeight: 50,
headerBGC: 'transparent',
oddRowBGC: 'transparent',
evenRowBGC: 'transparent',
columnWidth: [179, 179, 179, 179],
data: [
['行1列1', '行1列2', '行1列3', '行1列4'],
['行2列1', '行2列2', '行2列3', '行2列4'],
['行3列1', '行3列2', '行3列3', '行3列4'],
['行4列1', '行4列2', '行4列3', '行4列4'],
]
})
function reqSensorByDept() {
getSensorByDept('113,114').then(res => {
if (res.code === 200) {
let sensorData = res.data
let temp_humi = sensorData.temp_humi
let TVOC_CH2O = sensorData.TVOC_CH2O
let temp = []
temp_humi.map(item => {
let index = temp.find(item2 => { return item2.deviceId == item.deviceId })
if (!index) {
if (item.type === 'AirHumi_Reg') {
temp.push({
deviceId: item.deviceId,
humidity: item.data,
name: item.name,
label: item.label,
temp: '',
deptId: item.deptId,
deptName: item.deptName,
status: item.status
})
} else if (item.type === 'AirTemp_Reg') {
temp.push({
deviceId: item.deviceId,
humidity: '',
name: item.name,
label: item.label,
temp: item.data,
deptId: item.deptId,
deptName: item.deptName,
status: item.status
})
}
} else {
if (item.type === 'AirHumi_Reg') {
index.humidity = item.data
} else if (item.type === 'AirTemp_Reg') {
index.temp = item.data
}
}
})
let now = +new Date()
TVOC_CH2O.map(item => {
if (item.deptId == '113') {
if (item.type === 'CH2O') {
TVOC_CH2O['4f'].ch2o.push([now,item.data])
} else if (item.type === 'TVOC') {
TVOC_CH2O['4f'].tvoc.push([now,item.data])
}
} else if(item.deptId == '114') {
if (item.type === 'CH2O') {
TVOC_CH2O['5f'].ch2o.push([now,item.data])
} else if (item.type === 'TVOC') {
TVOC_CH2O['5f'].tvoc.push([now,item.data])
}
}
})
sensorData.temp_humi = temp
R_D_EnvironmentStore.sensorData = sensorData
// noiseDataList.value = res.data
// public_noise.value = noiseDataList.value.find(item => item.devName === '')
// office_noise.value = noiseDataList.value.filter(item => item.devName !== '')
}
})
}
//socket
function getWebsocket(val) {
try {
let data = JSON.parse(val);
if (data.type == "HUMI_TEMP") {
let obj = data.msg;
if (obj.hasOwnProperty('temp')) {
let index = sensor_list.findIndex(sensor => sensor.type === 'AirTemp_Reg' && sensor.id === obj.temp.devId)
if (index !== -1) {
sensor_list[index].value = obj.temp.value
sensor_list[index].status = "true"
}
}
if (obj.hasOwnProperty('humi')) {
let index = sensor_list.findIndex(sensor => sensor.type === 'AirHumi_Reg' && sensor.id === obj.humi.devId)
if (index !== -1) {
sensor_list[index].value = obj.humi.value
sensor_list[index].status = "true"
}
}
}
if (data.type == "TVOC_CH2O") {
let obj = data.msg;
if (obj.hasOwnProperty('CH2O')) {
let index = sensor_list.findIndex(sensor => sensor.type === 'CH2O' && sensor.id === obj.CH2O.devId)
if (index !== -1) {
sensor_list[index].value = obj.CH2O.value
sensor_list[index].status = "true"
}
}
if (obj.hasOwnProperty('TVOC')) {
let index = sensor_list.findIndex(sensor => sensor.type === 'TVOC' && sensor.id === obj.TVOC.devId)
if (index !== -1) {
sensor_list[index].value = obj.TVOC.value
sensor_list[index].status = "true"
}
}
}
//
if (data.type == "dust") {
let obj = data.msg;
let index_pm25 = sensor_list.findIndex(sensor => sensor.type === 'HIGH_PM25_Reg' && sensor.id === obj.devId)
let index_pm10 = sensor_list.findIndex(sensor => sensor.type === 'HIGH_PM10_Reg' && sensor.id === obj.devId)
if (index_pm25 !== -1) {
sensor_list[index_pm25].value = obj.pm25
sensor_list[index_pm25].status = "true"
dustData.pm25 = obj.pm25
}
if (index_pm10 !== -1) {
sensor_list[index_pm10].value = obj.pm10
sensor_list[index_pm10].status = "true"
dustData.pm10 = obj.pm10
}
}
//
if (data.type === "NOISE") {
let obj = data.msg;
let list_index = noiseDataList.value.findIndex(item => item.devId === obj.noise.devId)
if (list_index !== -1) {
noiseDataList.value[list_index].data = obj.noise.value
} else {
let index = sensor_list.findIndex(sensor => sensor.type === 'Noise_Reg' && sensor.id === obj.noise.devId)
if (index !== -1) {
sensor_list[index].value = obj.noise.value
sensor_list[index].status = "true"
}
}
}
} catch (err) {
console.log(err);
}
}
function errWebsocket(val) {
// console.log(val);
}
onMounted(() => {
reqSensorByDept()
window.addEventListener('wheel', function (event) {
deltaY.value += event.deltaY
if (deltaY.value <= -500 && deltaY.value >= -1000) {
this.document.querySelector('.ct-box').style.transform = 'translateY(-200%) translateX(-50%)'
this.document.querySelector('.left-content').style.transform = 'translateX(-100%)'
this.document.querySelector('.right-content').style.transform = 'translateX(100%)'
this.document.querySelector('.bottom-content').style.transform = 'translateY(100%)'
}
if (deltaY.value > -500 && deltaY.value < 0) {
this.document.querySelector('.ct-box').style.transform = 'translateY(0) translateX(-50%)'
this.document.querySelector('.left-content').style.transform = 'translateX(0)'
this.document.querySelector('.right-content').style.transform = 'translateX(0)'
this.document.querySelector('.bottom-content').style.transform = 'translateY(0)'
}
// if (deltaY.value >= 0) {
// deltaY.value = 0
// }
}, { passive: false });
//connectWebsocket('','',getWebsocket, errWebsocket)
});
</script>
<style lang="scss" scoped>
.container {
width: 1920px;
height: 1080px;
position: relative;
// display: flex;
// justify-content: center;
align-items: center;
// background-image: url('/src/assets/images/gif-bg.gif');
background-repeat: no-repeat;
/* 如果你不想让背景平铺 */
background-size: cover;
/* 或者其他你需要的大小设置 */
background-position: center;
.header {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 72px;
background-image: url('./image/u796.png');
z-index: 2;
.title {
width: 100%;
height: 72px;
font-size: 36px;
color: #2affff;
text-align: center;
line-height: 60px;
font-weight: 700;
}
}
.ct-box {
position: absolute;
top: 100px;
left: 50%;
transform: translateX(-50%);
width: 825px;
height: 180px;
display: flex;
z-index: 2;
justify-content: space-between;
transition: transform 1s;
.ct-sensor {
width: 100%;
height: 100%;
display: flex;
justify-content: space-between;
align-items: center;
}
}
.left-content {
position: absolute;
top: 0;
left: 0;
width: 557px;
height: 1080px;
box-sizing: border-box;
padding-top: 72px;
background-image: url('./image/u801.png'), url('./image/u797.png');
background-position: center, 0% 78%;
background-repeat: no-repeat, no-repeat;
padding-left: 30px;
transition: transform 1s;
}
.left-right {
display: flex;
flex-direction: column;
justify-content: space-between;
padding-bottom: 30px;
}
.right-content {
position: absolute;
top: 0;
right: 0;
width: 557px;
height: 1080px;
box-sizing: border-box;
padding-top: 72px;
background-image: url('./image/u800.png'), url('./image/u798.png');
background-position: center, 100% 78%;
background-repeat: no-repeat, no-repeat;
padding-right: 30px;
transition: transform 1s;
align-items: flex-end;
}
.bottom-content {
position: absolute;
bottom: 0;
left: 0;
width: 1920px;
height: 184px;
background-image: url('./image/u799.png'), url('./image/u802.png');
background-position: bottom, 50% 100%;
background-repeat: no-repeat, no-repeat;
transition: transform 1s;
.zd-scroll-board {
width: 716px;
height: 120px, ;
position: absolute;
top: 28px;
left: 50%;
transform: translateX(-50%);
}
}
}
.checkboxlist {
position: absolute;
top: 2px;
right: 60px;
z-index: 999;
:deep(.el-checkbox-button__inner) {
font-size: 18px;
}
}
</style>

View File

@ -0,0 +1,65 @@
<template>
<div class="progress-container">
<div class="text-label">
<div class="label-left">{{ prop.mdoelValue1.date }}</div>
<div class="label-right"><i class="value">{{ prop.mdoelValue1.rate }}</i> %</div>
</div>
<div class="progress">
<el-progress :percentage="percentage" stroke-width="8" :color="checkCb(prop.mdoelValue1)" :show-text="false"/>
</div>
</div>
</template>
<script setup>
import { ref,computed } from 'vue';
const prop = defineProps({
mdoelValue1:{
type: Object,
default: () => {
return {
date: '',
rate: 10,
}
}
}
})
const percentage = computed(() => {
console.log(prop.mdoelValue1.data);
return prop.mdoelValue1.rate > 100 ? 100 : prop.mdoelValue1.rate;
})
//
function checkCb(item) {
if (item.data > 85) {
return '#FF0000'
} else {
return '#469DE9'
}
}
</script>
<style lang="scss" scoped>
.progress-container {
width: 100%;
height: 40px;
box-sizing: border-box;
.text-label {
width: 100%;
height: 30px;
display: flex;
justify-content: space-between;
align-items: center;
font-size: 14px;
color: #2affff;
box-sizing: border-box;
.label-right {
.value {
color: #fff;
}
}
}
}
</style>

View File

@ -0,0 +1,42 @@
<template>
<div class="item-container">
<div class="box-title" >{{ prop.title }}</div>
<div class="content">
<slot></slot>
</div>
</div>
</template>
<script setup>
const prop = defineProps({
title: {
type: String,
default: '标题'
}
})
</script>
<style lang="scss" scoped>
.item-container {
position: relative;
width: 100%;
height: 100%;
.box-title {
width: 100%;
height: 53px;
background: url('../image/u17.png') no-repeat;
background-size: auto 100%;
box-sizing: border-box;
padding-left: 32px;
font-size: 20px;
line-height: 53px;
color: #fff;
}
.content {
width: 100%;
height: calc(100% - 53px);
}
}
</style>

View File

@ -0,0 +1,108 @@
<template>
<v-chart :option="options" theme="dark" style="width: 100%;height: 100%;" />
</template>
<script setup>
import { computed } from 'vue';
const prop = defineProps({
data: {
type: Object,
default: () => {
return {
xAxis: [],
series: []
};
}
}
});
const options = computed(() => {
return {
tooltip: {
trigger: 'axis',
backgroundColor: 'rgba(0, 0, 0, 0.8)',
borderColor: '#00c6ff',
borderWidth: 2,
textStyle: {
color: '#fff',
fontSize: 14
},
formatter: function (params) {
let tooltipText = '';
let xAxisValue = params[0].name;
params.forEach((item) => {
tooltipText += `<div style="padding: 2px 0;"><strong>${item.seriesName}:</strong> ${item.value}%</div>`;
});
return `${xAxisValue}<br>${tooltipText}`;
},
padding: 10,
extraCssText: 'border-radius: 8px; box-shadow: 0 0 15px rgba(0, 0, 0, 0.5);'
},
backgroundColor: 'transparent',
// legend: {
// data: ['', ''],
// right: 'left',
// textStyle: {
// color: '#ffff'
// }
// },
grid: {
left: '10%',
},
xAxis: {
type: 'category',
data: prop.data.xAxis,
axisLabel: {
color: "#ffffff",
},
},
yAxis: {
type: 'value',
max: 100,
splitLine: {
show: true,
lineStyle: {
type: 'dashed',
color: '#3c3a4a85',
}
},
axisLabel: {
color: "#ffffff",
formatter: function (value) {
return `${value} %`;
}
},
},
series: [{
name: '利用率',
data: prop.data.series,
type: 'line',
smooth: true,
itemStyle: {
color: 'rgb(150 ,162 ,116)',
},
lineStyle: {
width: 2,
},
areaStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0,
color: 'rgb(150 ,162 ,116 ,0.6)'
}, {
offset: 1,
color: 'rgb(150 ,162 ,116 ,0.2)'
}]
}
}
}]
}
});
</script>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,70 @@
<template>
<v-chart :option="options" theme="dark" style="width: 100%;height: 100%;" />
</template>
<script setup>
import { computed, ref } from 'vue';
const prop = defineProps({
data: {
type: Object,
default: () => {
return {
xAxis: [],
series: []
};
}
}
});
const options = computed(() => {
return {
tooltip: {
trigger: 'axis',
axisPointer: {
// Use axis to trigger tooltip
type: 'shadow' // 'shadow' as default; can also be 'line' or 'shadow'
}
},
legend: {},
backgroundColor: 'transparent',
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'category',
data: prop.data.xAxis,
},
yAxis: {
name: 'min',
type: 'value',
axisLabel: {
color: '#fff',
},
splitLine: {
show: false
}
},
series: prop.data.series.map((item, index) => {
return {
name: item.name,
type: 'bar',
stack: 'total',
barWidth: '30%',
label: {
show: true
},
emphasis: {
focus: 'series'
},
data: item.data
};
})
}
});
</script>
<style lang="scss" scoped></style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 942 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 642 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 584 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 611 B

View File

@ -0,0 +1,500 @@
<template>
<div class="container">
<div class="header">
<div class="title">微工厂设备详情</div>
<svg-icon icon-class="back" class="back_icon" @click="handleBack"/>
</div>
<div class="content">
<div class="left-plane">
<div class="lt-plane">
<div class="ltl-plane">
<Card class="ltl-item1" title="设备详情">
<div class="ltl-content">
<div class="ltl-box">
<div class="ltl-item-box">
<div class="label">名称</div>
<div class="value">{{ deviceInfo.name }}</div>
</div>
</div>
<div class="ltl-box">
<div class="ltl-item-box">
<div class="label">编号</div>
<div class="value">{{ deviceInfo.code }}</div>
</div>
</div>
<div class="ltl-box">
<div class="ltl-item-box">
<div class="label">负责人</div>
<div class="value">{{ deviceInfo.director }}</div>
</div>
</div>
<div class="ltl-box">
<div class="ltl-item-box">
<div class="label">所在位置</div>
<div class="value">{{ deviceInfo.deviceLocation }}</div>
</div>
</div>
</div>
</Card>
<Card class="ltl-item2" title="设备利用率">
<div style="width: 100%;height: 100%;display: flex;flex-direction: column;justify-content: space-around;align-items: center;">
<Progress :mdoelValue1="item" v-for="item in deviceRateChartData"></Progress>
</div>
</Card>
</div>
<div class="ltr-plane">
<div class="tip-type">
<div class="tip-type-item">
<svg-icon icon-class="run" class="el-input__icon" style="width: 26px;height: 26px;" />
<div class="tip-type-item-text">工作</div>
</div>
<div class="tip-type-item">
<svg-icon icon-class="wait" class="el-input__icon" style="width: 26px;height: 26px;" />
<div class="tip-type-item-text">待机</div>
</div>
<div class="tip-type-item">
<svg-icon icon-class="stop" class="el-input__icon" style="width: 26px;height: 26px;" />
<div class="tip-type-item-text">停机</div>
</div>
<div class="tip-type-item">
<svg-icon icon-class="repair" class="el-input__icon"
style="width: 26px;height: 26px;" />
<div class="tip-type-item-text">维修</div>
</div>
<div class="tip-type-item">
<svg-icon icon-class="alarm" class="el-input__icon" style="width: 26px;height: 26px;" />
<div class="tip-type-item-text">故障</div>
</div>
</div>
<div class="c-item c-top">
<div class="item-box">当前状态
<svg-icon v-if="devStatus.state == 0" icon-class="stop"
class="el-input__icon input-icon" />
<svg-icon v-else-if="devStatus.state == 1" icon-class="wait"
class="el-input__icon input-icon" />
<svg-icon v-else-if="devStatus.state == 2" icon-class="run"
class="el-input__icon input-icon" />
<svg-icon v-else-if="devStatus.state == 4" icon-class="alarm"
class="el-input__icon input-icon" />
</div>
<div class="item-box">运行时长{{ devStatus.runTime }}min</div>
</div>
<div class="c-item c-center">
<div class="item-box">停机时长{{ devStatus.stopTime }}min</div>
<el-image :src="baseUrl + deviceInfo.file"
style="height: 100%;position: relative;top: -30px;" />
<div class="item-box">工作时长{{ devStatus.workTime }}min</div>
</div>
<div class="c-item c-bottom">
<div class="item-box">故障时长{{ devStatus.faultTime }}min</div>
<div class="item-box">待机时长{{ devStatus.waitTime }}min</div>
</div>
</div>
</div>
<Card class="lb-plane" title="设备状态分析">
<StackBarChart :data="deviceStatusChartData"></StackBarChart>
</Card>
</div>
<div class="right-plane">
<Card class="right-item1" title="设备维修记录">
<el-table :data="repairData" v-if="repairData.length > 0" v-tableAutoScroll="{ delay: 15 }"
header-row-class-name="table_header" style="width: 100%;height: 100%;">
<el-table-column prop="devCode" label="编码" width="90" />
<el-table-column prop="name" label="设备名称" />
<el-table-column prop="subject" label="报警内容" />
<el-table-column prop="person" label="负责人" />
<el-table-column prop="time" label="报警时间" />
</el-table>
<el-empty v-else description="暂无记录" />
</Card>
<Card class="right-item2" title="设备保养记录">
<el-table :data="remindData" v-if="remindData.length > 0" v-tableAutoScroll="{ delay: 15 }"
header-row-class-name="table_header" style="width: 100%;height: 100%;">
<el-table-column prop="devCode" label="编码" width="90" />
<el-table-column prop="name" label="设备名称" />
<el-table-column prop="subject" label="保养内容" />
<el-table-column prop="person" label="负责人" />
<el-table-column prop="time" label="保养时间" />
</el-table>
<el-empty v-else description="暂无记录" />
</Card>
<Card class="right-item3" title="设备用电量分析">
<LineChart :data="deviceElectChartData"></LineChart>
</Card>
</div>
</div>
</div>
</template>
<script setup>
import 'element-plus/theme-chalk/dark/css-vars.css'
import { onMounted, ref } from 'vue';
import Card from './component/card.vue';
import StackBarChart from './component/stackBarChart.vue';
import Progress from './component/Progress.vue';
import LineChart from './component/lineChart.vue';
import { useRoute,useRouter } from 'vue-router';
import { connectWebsocket, closeWebsocket} from "@/utils/websocket";
import { listDevice, deviceCheck, deviceRepair, deviceStatusById, deviceStatusChart,deviceRateChart,deviceElectChart } from '@/api/screen/micro'
const route = useRoute();
const router = useRouter();
let id = ref(0)
const baseUrl = import.meta.env.VITE_APP_BASE_API;
let deviceInfo = ref({})
//
function getListDevice() {
listDevice(id.value).then(res => {
deviceInfo.value = res.data
})
}
let remindData = ref([])
//
const getDeviceCheck = async () => {
const res = await deviceCheck(id.value);
remindData.value = res.data;
}
let repairData = ref([])
//
const getDeviceRepair = async () => {
const res = await deviceRepair(id.value);
repairData.value = res.data;
}
let devStatus = ref({
"deviceCode": null,
"onlineTime": null,
"realTime": null,
"deviceId": null,
"workTime": null,
"runTime": null,
"waitTime": null,
"stopTime": null,
"faultTime": null,
"ts": null,
"state": null,
})
//
const getDeviceStatus = async () => {
const res = await deviceStatusById(id.value);
devStatus.value = res.data;
}
let deviceStatusChartData = reactive({
xAxis: [],
series: []
})
//
const getDeviceStatusChart = async () => {
const res = await deviceStatusChart(id.value);
deviceStatusChartData.xAxis = res.data.dates;
deviceStatusChartData.series.push({
name: '工作',
data: res.data.work
})
deviceStatusChartData.series.push({
name: '待机',
data: res.data.wait
})
deviceStatusChartData.series.push({
name: '停机',
data: res.data.stop
})
deviceStatusChartData.series.push({
name: '故障',
data: res.data.fault
})
}
//
let deviceRateChartData = ref([])
const getDeviceRateChart = async () => {
const res = await deviceRateChart(id.value);
deviceRateChartData.value = res.data;
}
//
let deviceElectChartData = reactive({
xAxis: [],
series: []
})
function getdeviceElectChart() {
deviceElectChart(id.value).then(res => {
deviceElectChartData.xAxis = res.data.dates;
deviceElectChartData.series = res.data.elects;
})
}
//
function handleBack() {
router.go(-1);
}
//socket
function getWebsocket(val) {
try {
let data = JSON.parse(val);
if (data.type == "status" && data.msg.id == id.value) {
let obj = data.msg;
devStatus.state = obj.status;
}
} catch (err) {
console.log(err);
}
}
function errWebsocket(val) {
// headerref.value.HeadererrWebsocket(val)
// console.log(val);
}
onMounted(() => {
id.value = route.params.id;
getDeviceCheck();
getDeviceRepair();
getListDevice()
getDeviceStatus()
getDeviceStatusChart()
getDeviceRateChart()
getdeviceElectChart()
connectWebsocket('','',getWebsocket, errWebsocket)
});
onUnmounted(() => {
closeWebsocket()
})
</script>
<style lang="scss" scoped>
::v-deep(.table_header th) {
background-color: transparent !important;
color: #21dadb;
text-align: center;
}
.back_icon {
position: absolute;
top: 40px;
left: 20px;
width: 60px;
height: 60px;
color: #f9f8f4;
cursor: pointer;
}
.container {
width: 1920px;
height: 1080px;
position: relative;
// display: flex;
// justify-content: center;
align-items: center;
background-image: url('/src/assets/images/screen-bg.png');
background-repeat: no-repeat;
/* 如果你不想让背景平铺 */
background-size: cover;
/* 或者其他你需要的大小设置 */
background-position: center;
.header {
position: relative;
width: 100%;
height: 89px;
background-image: url('/src/assets/images/screen-header-bg1.png');
background-size: 100% 100%;
.title {
width: 100%;
height: 89px;
font-size: 36px;
color: #f9f8f4;
text-align: center;
line-height: 89px;
font-weight: 700;
}
}
.content {
width: 100%;
height: 975px;
display: flex;
justify-content: space-around;
align-items: center;
box-sizing: border-box;
padding: 20px 0;
.right-plane {
width: 488px;
height: 100%;
.right-item1 {
width: 100%;
height: 280px;
}
.right-item2 {
width: 100%;
height: 280px;
margin: 10px 0;
}
.right-item3 {
width: 100%;
height: 395px;
}
}
.left-plane {
width: 1400px;
height: 100%;
.lt-plane {
width: 100%;
height: 635px;
display: flex;
justify-content: space-between;
align-items: center;
.ltl-plane {
width: 488px;
height: 100%;
.ltl-item1 {
width: 100%;
height: 260px;
.ltl-content {
width: 100%;
height: 100%;
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
.ltl-box {
width: 48%;
height: 50%;
display: flex;
justify-content: flex-start;
align-items: center;
box-sizing: border-box;
.ltl-item-box {
height: 60px;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
background-color: rgba(2, 48, 87, 0.5);
border: #2A80B8 2px solid;
padding: 0 10px;
color: #f9f8f4;
font-size: 20px;
font-weight: 500;
text-align: center;
.label {
width: 50%;
text-wrap: nowrap;
text-align: left;
}
}
}
}
}
.ltl-item2 {
width: 100%;
height: 360px;
margin-top: 15px;
}
}
.ltr-plane {
position: relative;
width: 892px;
height: 100%;
background: url('./image/center-bg.png') no-repeat;
background-size: 38% auto;
background-position: 50% 70%;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
.tip-type {
position: absolute;
top: -15px;
left: 50%;
transform: translateX(-50%);
width: 260px;
height: 50px;
display: flex;
justify-content: space-between;
align-items: center;
font-size: 14px;
font-weight: 700;
.tip-type-item {
width: 33%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
}
}
.c-top,
.c-bottom {
width: 70%;
height: 150px;
}
.c-center {
width: 85%;
flex: 1;
}
.c-item {
display: flex;
justify-content: space-between;
align-items: center;
.item-box {
background-color: rgba(2, 48, 87, 0.5);
border: #2A80B8 2px solid;
padding: 15px;
color: #f9f8f4;
font-size: 22px;
font-weight: 500;
text-align: center;
}
}
}
}
.lb-plane {
width: 100%;
height: 340px;
}
}
}
}
</style>

View File

@ -0,0 +1,101 @@
<template>
<v-chart :option="options" theme="dark" style="width: 100%;height: 100%;" />
</template>
<script setup>
import { computed } from 'vue';
import * as echarts from 'echarts';
const prop = defineProps({
data: {
type: Object,
default: () => {
return {
name: [],
value: []
};
}
}
});
const options = computed(() => {
return {
tooltip: {
trigger: 'axis'
},
backgroundColor: 'transparent',
legend: {
data: ['目标产量', '实际产量'],
textStyle: {
color: "#FFF",
fontSize: 10
},
},
toolbox: {
show: true,
},
calculable: true,
xAxis: [{
type: 'category',
data: ['W01', 'W02', 'W03', 'w04', 'W05', 'W06', 'W07', 'W08'],
axisLabel: {
color: '#fff'
},
},],
yAxis: [{
type: 'value',
axisLabel: {
color: '#fff'
},
splitLine: {
show: false,
},
}],
series: [{
name: '目标产量',
type: 'bar',
data: [20, 15, 30, 25, 18, 35, 20, 15],
barWidth: '20%',
itemStyle: {
borderRadius: [2, 2, 0, 0],
color:
{
type: 'linear',
x: 0,
y: 1,
x2: 0,
y2: 0,
colorStops: [{
offset: 0, color: 'rgba(84,194,238,0.1)' // 0%
}, {
offset: 1, color: 'rgb(84,194,238)' // 100%
}],
global: false // false
}
}
}, {
name: '实际产量',
type: 'bar',
data: [9, 15, 28, 15, 15, 25, 20, 10],
barWidth: '20%',
itemStyle: {
borderRadius: [2, 2, 0, 0],
color: {
type: 'linear',
x: 0,
y: 1,
x2: 0,
y2: 0,
colorStops: [{
offset: 0, color: 'rgba(181,202,159,0.1)' // 0%
}, {
offset: 1, color: 'rgb(181,202,159)' // 100%
}],
global: false // false
}
}
}]
}
});
</script>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,42 @@
<template>
<div class="item-container">
<div class="box-title" >{{ prop.title }}</div>
<div class="content">
<slot></slot>
</div>
</div>
</template>
<script setup>
const prop = defineProps({
title: {
type: String,
default: '标题'
}
})
</script>
<style lang="scss" scoped>
.item-container {
position: relative;
width: 100%;
height: 100%;
.box-title {
width: 100%;
height: 53px;
background: url('../image/u17.png') no-repeat;
background-size: auto 100%;
box-sizing: border-box;
padding-left: 32px;
font-size: 20px;
line-height: 53px;
color: #fff;
}
.content {
width: 100%;
height: calc(100% - 53px);
}
}
</style>

View File

@ -0,0 +1,42 @@
<template>
<div class="item-container">
<div class="box-title" >{{ prop.title }}</div>
<div class="content">
<slot></slot>
</div>
</div>
</template>
<script setup>
const prop = defineProps({
title: {
type: String,
default: '标题'
}
})
</script>
<style lang="scss" scoped>
.item-container {
width: 100%;
height: 100%;
.box-title {
width: 100%;
height: 53px;
background: url('../image/u36.png') no-repeat;
background-size: 100% 100%;
box-sizing: border-box;
padding-left: 32px;
font-size: 20px;
line-height: 53px;
text-align: center;
color: #fff;
}
.content {
width: 100%;
height: calc(100% - 53px);
}
}
</style>

View File

@ -0,0 +1,32 @@
<template>
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" version="1.1" width="20px" height="20px">
<g transform="matrix(1 0 0 1 -436 -253 )">
<path d="M 6.15 6.22 C 7.15 5.24325581395349 8.57 4.69627906976744 10 4.69627906976744 C 11.43 4.69627906976744 12.86 5.25302325581395 13.86 6.22976744186046 C 14.86 7.20651162790698 15.43 8.46651162790698 15.43 9.85348837209303 C 15.43 11.2404651162791 14.86 12.5004651162791 13.86 13.4772093023256 C 11.72 15.5674418604651 8.29 15.5674418604651 6.15 13.6139534883721 C 5.15 12.6372093023256 4.58 11.2404651162791 4.58 9.84372093023256 C 4.58 8.44697674418605 5.15 7.19674418604651 6.15 6.22 Z M 11.43 1.2093023255814 L 11.29 1.2093023255814 C 14.43 1.6293023255814 17 3.71953488372093 18.29 6.51302325581395 C 18.58 7.20651162790698 18.86 7.90976744186047 19 8.60325581395349 L 20 8.60325581395349 C 19.43 4.27627906976744 15.86 0.789302325581395 11.43 0.232558139534884 L 11.43 1.2093023255814 Z M 0 8.60325581395349 L 1 8.60325581395349 C 1.14 7.90976744186047 1.29 7.20651162790698 1.57 6.51302325581395 C 2.86 3.71953488372093 5.57 1.6293023255814 8.57 1.2093023255814 L 8.57 0.232558139534884 C 4.14 0.789302325581395 0.57 4.27627906976744 0 8.60325581395349 Z M 20 11.26 L 19 11.26 C 18.86 11.953488372093 18.71 12.6567441860465 18.43 13.3502325581395 C 17.14 16.1437209302326 14.57 18.2339534883721 11.43 18.6539534883721 L 11.43 19.6306976744186 C 15.86 19.0739534883721 19.43 15.586976744186 20 11.26 Z M 8.57 19.6306976744186 L 8.57 18.6539534883721 C 5.43 18.2339534883721 2.86 16.1437209302326 1.57 13.3502325581395 C 1.28 12.6567441860465 1.14 11.953488372093 1 11.26 L 0 11.26 C 0.57 15.586976744186 4.14 19.0739534883721 8.57 19.6306976744186 Z " fill-rule="nonzero" :fill="color" stroke="none" transform="matrix(1 0 0 1 436 253 )"/>
</g>
</svg>
</template>
<script setup>
import { ref, onMounted } from 'vue';
const prop = defineProps({
color: '#aaef8a'
});
</script>
<style lang="scss" scoped>
/** .border设置循环旋转动画效果 */
// .border {
// animation: rotate 3s linear infinite;
// transform-origin: center;
// }
// @keyframes rotate {
// 0% {
// transform: rotate(0deg);
// }
// 100% {
// transform: rotate(360deg);
// }
// }
</style>

View File

@ -0,0 +1,108 @@
<template>
<v-chart :option="options" theme="dark" style="width: 100%;height: 100%;" />
</template>
<script setup>
import { computed } from 'vue';
const prop = defineProps({
data: {
type: Object,
default: () => {
return {
xAxis: [],
series: []
};
}
}
});
const options = computed(() => {
return {
tooltip: {
trigger: 'axis',
backgroundColor: 'rgba(0, 0, 0, 0.8)',
borderColor: '#00c6ff',
borderWidth: 2,
textStyle: {
color: '#fff',
fontSize: 14
},
formatter: function (params) {
let tooltipText = '';
let xAxisValue = params[0].name;
params.forEach((item) => {
tooltipText += `<div style="padding: 2px 0;"><strong>${item.seriesName}:</strong> ${item.value}%</div>`;
});
return `${xAxisValue}<br>${tooltipText}`;
},
padding: 10,
extraCssText: 'border-radius: 8px; box-shadow: 0 0 15px rgba(0, 0, 0, 0.5);'
},
backgroundColor: 'transparent',
// legend: {
// data: ['', ''],
// right: 'left',
// textStyle: {
// color: '#ffff'
// }
// },
grid: {
left: '10%',
},
xAxis: {
type: 'category',
data: prop.data.xAxis,
axisLabel: {
color: "#ffffff",
},
},
yAxis: {
type: 'value',
max: 100,
splitLine: {
show: true,
lineStyle: {
type: 'dashed',
color: '#3c3a4a85',
}
},
axisLabel: {
color: "#ffffff",
formatter: function (value) {
return `${value} %`;
}
},
},
series: [{
name: '利用率',
data: prop.data.series,
type: 'line',
smooth: true,
itemStyle: {
color: 'rgb(150 ,162 ,116)',
},
lineStyle: {
width: 2,
},
areaStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0,
color: 'rgb(150 ,162 ,116 ,0.6)'
}, {
offset: 1,
color: 'rgb(150 ,162 ,116 ,0.2)'
}]
}
}
}]
}
});
</script>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,84 @@
<template>
<v-chart :option="options" theme="dark" style="width: 100%;height: 100%;" />
</template>
<script setup>
import { computed, ref } from 'vue';
const prop = defineProps({
data: {
type: Number,
default: 0,
}
});
const options = computed(() => {
return {
tooltip: {
formatter: "{a} <br/>{c} {b}",
},
backgroundColor: 'transparent',
series: [{
name: "耗电量",
type: "gauge",
z: 3,
min: 0,
max: 380,
radius: "85%",
axisLine: {
lineStyle: {
width: 12,
color: [[0.9, "#00b2b9"], [1, "#e60007"], ],
},
},
pointer: {
itemStyle: {
color: "auto",
},
},
axisTick: {
distance: 1,
length: 5,
splitNumber: 5,
lineStyle: {
color: "#464646"
},
},
splitLine: {
distance: -3,
length: 12,
lineStyle: {
color: "auto",
},
},
axisLabel: {
color: "#fbffff",
distance: 10,
fontSize: 14,
fontWeight: "bolder",
},
title: {
offsetCenter: ["0", "30%"],
textStyle: {
fontWeight: "bolder",
fontSize: 14,
color: "#fbffff",
},
},
detail: {
formatter: "{value}\n kW·h",
color: "inherit",
fontSize: 14,
textStyle: {
fontWeight: "bolder",
},
},
data: [{
value: prop.data,
}],
}, ],
}
});
</script>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,56 @@
<template>
<v-chart :option="options" theme="dark" style="width: 100%;height: 100%;" />
</template>
<script setup>
import { computed, ref } from 'vue';
const prop = defineProps({
data: {
type: Number,
default: 84.3
}
});
const options = computed(() => {
return {
backgroundColor: 'transparent',
series: [{
type: 'gauge',
startAngle: 90,
endAngle: -270,
pointer: { show: false },
progress: {
show: true,
overlap: false,
roundCap: true,
clip: false,
itemStyle: {
color: '#58D9F9'
}
},
axisLine: {
lineStyle: {
width: 20
}
},
splitLine: { show: false },
axisTick: { show: false },
axisLabel: { show: false },
data: [{
value: prop.data,
// name: '',
title: { offsetCenter: ['0%', '0%'] },
detail: {
offsetCenter: ['0%', '0%'], formatter: function (value) {
return value.toFixed(1) + '%';
}
},
}]
}]
}
});
</script>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,154 @@
<template>
<!-- <v-chart class="chart" :option="option" theme="dark" style="width: 100%;height: 100%;" /> -->
<div ref="test1" style="width: 100%;height: 100%;"></div>
<div class="fullmask" v-show="isFull">
<div ref="fullScreen" v-bind:class="{ show: isFull, hide: !isFull }"></div>
</div>
</template>
<script setup lang='ts'>
import { ref, computed, getCurrentInstance, watch, nextTick } from "vue"
//
const prop = defineProps({
data: {
default: () => {
return [
{ name: '支柱试验台', value: 120 },
]
},
type: Object
},
})
let isFull = ref(false)
const { proxy } = getCurrentInstance() as any
const test1 = ref(null)
const fullScreen = ref(null)
let charts = ref(null)
watch(() => prop.data, () => {
drawChart('test1')
}, { immediate: false, deep: true })
function drawChart(elementId) {
let element = elementId == 'fullScreen' ? fullScreen.value : test1.value;
charts.value = proxy.$echarts.init(element, 'dark');
let sortBarChartData = prop.data.sort((a, b) => b.value - a.value)
if (elementId == 'test1') {
sortBarChartData = sortBarChartData.slice(0, 6)
}
let yAxisData = sortBarChartData.map(item => item.name)
let seriesData = sortBarChartData.map(item => item.value)
var option = {
// title: {
// text: 'Referer of a Website',
// subtext: 'Fake Data',
// left: 'center'
// },
backgroundColor: 'transparent',
// tooltip: {
// trigger: 'item'
// },
tooltip: {
},
toolbox: {
show: true,
right: "10%",
feature: {
myTool1: {
show: true,
title: isFull.value == true ? '取消全屏' : '全屏',
icon:
'path://M641.750109 384.100028l205.227128-204.519-0.704035 115.89966c-0.282433 9.611915 7.489578 18.09103 17.101493 17.808598l12.297071 0c9.611915-0.283456 17.667382-5.936199 17.808598-15.689331l0.565888-172.57752c0-0.14224 0.282433-9.187243 0.282433-9.187243 0.14224-4.804423-0.99056-9.187243-4.100388-12.297071-3.109828-3.109828-7.347339-5.086855-12.297071-4.946662l-8.763594 0.14224c-0.141216 0-0.278339 0-0.420579 0.14224L697.581696 98.166787c-9.611915 0.283456-17.667382 8.200776-17.808598 17.950837l0 12.297071c1.416256 11.44875 10.458189 18.092054 20.070104 17.808598l112.789832 0.283456-204.66124 203.814965c-9.329483 9.329483-9.329483 24.449855 0 33.778314 9.329483 9.470699 24.452925 9.470699 33.782408 0L641.750109 384.100028zM383.095141 576.889893 177.726797 780.705881l0.707105-115.338888c0.283456-9.607822-7.492648-18.086937-17.104563-17.808598l-13.001105 0c-9.611915 0.283456-17.667382 5.937223-17.808598 15.690354l-0.565888 172.718737c0 0.14224-0.282433 9.187243-0.282433 9.187243-0.14224 4.808516 0.99056 9.187243 4.096295 12.297071 3.109828 3.109828 7.351432 5.086855 12.297071 4.946662l8.762571-0.14224c0.14224 0 0.283456 0 0.425695-0.14224l171.873486 0.708128c9.607822-0.283456 17.667382-8.196683 17.808598-17.950837L344.93503 832.575226c-1.415232-11.44875-10.461259-18.092054-20.074198-17.808598L212.069977 814.483172 416.59 610.671277c9.329483-9.329483 9.329483-24.453948 0-33.782408C407.40685 567.41817 392.424624 567.41817 383.095141 576.889893L383.095141 576.889893zM894.047276 835.967486l-0.424672-172.718737c-0.283456-9.612938-8.200776-15.406898-17.809621-15.690354l-12.296047 0c-9.612938-0.278339-17.243733 8.200776-17.105586 17.808598l0.708128 115.903753L641.750109 576.889893c-9.329483-9.329483-24.452925-9.329483-33.782408 0-9.325389 9.328459-9.325389 24.452925 0 33.782408L812.490795 814.483172l-112.789832 0.283456c-9.611915-0.283456-18.515702 6.502088-20.073174 17.808598l0 12.297071c0.282433 9.611915 8.200776 17.667382 17.808598 17.950837l171.166381-0.708128c0.141216 0 0.282433 0.14224 0.424672 0.14224l8.763594 0.14224c4.803399 0.141216 9.187243-1.694595 12.296047-4.946662 3.109828-3.109828 4.238534-7.488555 4.097318-12.297071 0 0-0.14224-9.046027-0.14224-9.187243L894.047276 835.968509zM212.216309 146.506748l112.789832-0.283456c9.607822 0.283456 18.512632-6.502088 20.070104-17.808598L345.076246 116.116601c-0.283456-9.611915-8.196683-17.667382-17.808598-17.950837l-172.011632 0.708128c-0.14224 0-0.283456-0.14224-0.425695-0.14224l-8.761548-0.14224c-4.808516-0.141216-9.187243 1.694595-12.297071 4.946662-3.109828 3.109828-4.242627 7.488555-4.096295 12.297071 0 0 0.282433 9.046027 0.282433 9.187243l0.420579 172.718737c0.14224 9.608845 8.200776 15.406898 17.808598 15.686261l13.005198 0c9.611915 0.282433 17.242709-8.196683 17.10047-17.808598l-0.564865-115.334795 205.231221 203.958228c9.324366 9.329483 24.448832 9.329483 33.777291 0 9.329483-9.329483 9.329483-24.452925 0-33.782408L212.216309 146.506748 212.216309 146.506748zM212.216309 146.506748',
onclick: function () {
if (!isFull.value) {
elementId = 'fullScreen';
}
setTimeout(() => {
nextTick(() => {
drawChart(elementId);
});
}, 10);
isFull.value = !isFull.value;
}
}
}
},
grid: {
left: '25%',
top: '10%',
},
xAxis: {
type: 'value',
},
yAxis: {
type: 'category',
data: yAxisData,
inverse: true,
axisLabel: {
color: '#fff',
fontSize: 13,
}
},
series: [
{
data: seriesData,
type: 'bar',
realtimeSort: true,
itemStyle: {
color: (params) => {
let colorList = ['#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de', '#3ba272', '#fc8452', '#9a60b4', '#ea7ccc'];
return colorList[params.dataIndex % colorList.length]
}
},
label: {
show: true,
position: 'right',
valueAnimation: true
}
}
]
};
charts.value.setOption(option);
}
</script>
<style lang="scss" scoped>
.fullmask {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 998;
background-color: rgba(0, 0, 0, 0.8);
}
.show {
position: fixed !important;
top: 50%;
left: 50%;
width: 65%;
height: 95%;
z-index: 999;
transform: translate(-50%, -50%);
background-color: rgba(18, 27, 38, 0.9137254901960784);
filter: alpha(opacity=10);
}
.hide {
display: none;
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 642 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 584 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 994 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 611 B

View File

@ -0,0 +1,731 @@
<template>
<div class="container">
<div class="header">
<div class="title">{{ skinName }}</div>
</div>
<div class="content">
<div class="left-panel">
<CardVue class="left-container-1" title="设备列表">
<!-- <scrollBoard ref="DvScrollBoard" :data="scrollBoardConfig_data" :config="scrollBoardConfig">
</scrollBoard> -->
<el-table :data="devList"
v-tableAutoScroll="{delay:15}"
header-row-class-name="table_header"
style="width: 100%;height: 100%;"
@row-click="handlePush2item"
>
<el-table-column prop="code" label="编码" width="90"/>
<el-table-column prop="name" label="设备名称" />
<el-table-column prop="runTime" label="运行时长" >
<template #default="{row}">
<div>{{ row.runTime }}min</div>
</template>
</el-table-column>
<el-table-column prop="rate" label="设备利用率" >
<template #default="{row}">
<div>{{ row.rate }}%</div>
</template>
</el-table-column>
<el-table-column prop="state" label="状态" >
<template #default="{row}">
<div style="width:100%;height:100%;display:flex;justify-content: space-around;align-items: center;">
<svg-icon v-if="row.state == 0" icon-class="stop" class="el-input__icon input-icon" />
<svg-icon v-else-if="row.state == 1" icon-class="wait" class="el-input__icon input-icon" />
<svg-icon v-else-if="row.state == 2" icon-class="run" class="el-input__icon input-icon" />
<svg-icon v-else-if="row.state == 4" icon-class="alarm" class="el-input__icon input-icon" />
</div>
</template>
</el-table-column>
</el-table>
<div class="left-tip-type">
<div class="left-tip-type-item">
<svg-icon icon-class="run" class="el-input__icon" style="width: 26px;height: 26px;" />
<div class="left-tip-type-item-text">工作</div>
</div>
<div class="left-tip-type-item">
<svg-icon icon-class="wait" class="el-input__icon" style="width: 26px;height: 26px;" />
<div class="left-tip-type-item-text">待机</div>
</div>
<div class="left-tip-type-item">
<svg-icon icon-class="stop" class="el-input__icon" style="width: 26px;height: 26px;" />
<div class="left-tip-type-item-text">停机</div>
</div>
<div class="left-tip-type-item">
<svg-icon icon-class="repair" class="el-input__icon" style="width: 26px;height: 26px;" />
<div class="left-tip-type-item-text">维修</div>
</div>
<div class="left-tip-type-item">
<svg-icon icon-class="alarm" class="el-input__icon" style="width: 26px;height: 26px;" />
<div class="left-tip-type-item-text">故障</div>
</div>
</div>
</CardVue>
<CardVue class="left-container" title="单设备耗电量排行">
<SortBarChart :data="sortBarChartData" fill="#169BD5" />
<div class="radio-ab-lb">
<el-radio-group v-model="radio_bar" @change="handleChangeBar" size="small">
<el-radio-button label="d">当天</el-radio-button>
<el-radio-button label="all">累计</el-radio-button>
</el-radio-group>
</div>
</CardVue>
</div>
<div class="center-panel">
<div class="dev-type-overview">
<div class="status-item" v-for="item in devStatus.devTypes" :key="item.type">
<div class="value">
<div class="on-text">{{ item.work }}</div>
<div class="all-text">{{ item.total }}</div>
</div>
<div class="label">{{ item.name }}</div>
</div>
<div class="status-flag">
<div class="yuan green"></div>
<div class="flag-text">工作数量</div>
<div class="yuan blue"></div>
<div class="flag-text">设备总数</div>
</div>
</div>
<div class="status-overview">
<div class="status-item">
<div class="item-label item-label-1">工作数量</div>
<div class="item-label item-label-2">停机数量</div>
<div class="item-label item-label-3">待机数量</div>
<div class="item-label item-label-4">设备总数</div>
</div>
<div class="status-center">
<div class="status-center-item">
<div class="item-value item-label-1">{{ devStatus.work }}</div>
<div class="item-value item-label-2">{{ devStatus.stop }}</div>
<div class="item-value item-label-3">{{ devStatus.wait }}</div>
<div class="item-value item-label-4">{{ devStatus.total }}</div>
</div>
</div>
<div class="centerChart">
<div class="ring-chart">
<RingChart :data="devStatus.work/devStatus.total * 100" />
</div>
</div>
</div>
<CenterCard title="用电监测" class="power-monitoring">
<div class="power-item-wrapper">
<div class="power-item" v-for="item in powerMonitoring" :key="item.label">
<div class="item-label">{{ item.label }}</div>
<div class="power-chart">
<PowerMonitoring :data="item.value" />
</div>
</div>
</div>
</CenterCard>
</div>
<div class="right-panel">
<CardVue class="left-container" title="设备利用率">
<LineChart :data="rateData" />
</CardVue>
<CardVue class="left-container" title="设备提醒">
<el-table :data="remindData" v-if="remindData.length > 0" v-tableAutoScroll="{delay:15}" header-row-class-name="table_header" style="width: 100%;height: 100%;">
<el-table-column prop="devCode" label="编码" width="90"/>
<el-table-column prop="name" label="设备名称" />
<el-table-column prop="subject" label="保养内容" />
<el-table-column prop="person" label="负责人" />
<el-table-column prop="time" label="保养时间" />
</el-table>
<el-empty v-else description="暂无记录" />
<!-- <div class="radio-ab-lb">
<el-radio-group v-model="radio_repair" @change="handleChangeRepair" size="small">
<el-radio-button label="b">保养</el-radio-button>
<el-radio-button label="w">维修</el-radio-button>
</el-radio-group>
</div> -->
</CardVue>
<CardVue class="left-container" title="设备报警">
<el-table :data="repairData" v-if="repairData.length > 0" v-tableAutoScroll="{delay:15}" header-row-class-name="table_header" style="width: 100%;height: 100%;">
<el-table-column prop="devCode" label="编码" width="90"/>
<el-table-column prop="name" label="设备名称" />
<el-table-column prop="subject" label="报警内容" />
<el-table-column prop="person" label="负责人" />
<el-table-column prop="time" label="报警时间" />
</el-table>
<el-empty v-else description="暂无记录" />
</CardVue>
</div>
</div>
<div class="footer"></div>
</div>
</template>
<script setup>
import { ref, reactive, onMounted, onUnmounted,getCurrentInstance } from 'vue'
import { useRouter } from 'vue-router'
import CardVue from './component/card.vue'
import CenterCard from './component/centerCard.vue'
import BarChart from './component/barChart.vue'
import LineChart from './component/lineChart.vue'
import RingChart from './component/ringChart.vue'
import PowerMonitoring from './component/powerMonitoring.vue'
import SortBarChart from './component/sortBarChart.vue'
import scrollBoard from "@/components/ZdScrollBoard/scrollBoard.vue";
import u83 from './image/u83.png'
import u156 from './image/u156.png'
import u157 from './image/u157.png'
import u158 from './image/u158.png'
import 'element-plus/theme-chalk/dark/css-vars.css'
import { getConfigKey } from "@/api/system/config";
import { connectWebsocket, closeWebsocket} from "@/utils/websocket";
import { listDevice, listElect, electMonitoring, deviceStatus, deviceRate,deviceCheck,deviceRepair } from '@/api/screen/micro'
let {proxy} = getCurrentInstance()
let router = useRouter()
let radio_bar = ref('d')
let radio_repair = ref('b')
let skinName = ref('');
let devStatus = reactive({
"wait": 0,
"total": 0,
"stop": 0,
"rate": 0,
"work": 0,
"devTypes": []
})
let devList = ref([])
function getConfigKeyFun(key) {
getConfigKey(key).then(res => {
skinName.value = res.msg
})
}
function status2Img(status) {
let html = `<div style="width:100%;height:100%;display:flex;justify-content: space-around;align-items: center;">`
switch (status) {
case 0:
html += `<img src="${u157}" width="32" height="32">`
break
case 1:
html += `<img src="${u156}" width="32" height="32">`
break
case 2:
html += `<img src="${u83}" width="32" height="32">`
break
case 4:
html += `<img src="${u158}" width="32" height="32">`
break
default:
html += `<img src="${u157}" width="32" height="32">`
break
}
html += '</div>'
return html
}
//
function getListDevice() {
listDevice().then(res => {
devList.value = res.data
})
}
let timer = new Date().getTime();
//
function throttle(func, wait) {
let lastTime = 0;
return function(...args) {
const now = Date.now();
if (now - lastTime >= wait) {
lastTime = now;
func.apply(this, args);
}
};
}
let sortBarChartData = ref([])
//
function getlistElect() {
listElect(radio_bar.value).then(res => {
sortBarChartData.value = res.data.map(item => {
return {
name: item.name,
value: item.electricity
}
})
})
}
//
function handleChangeBar() {
getlistElect()
}
function handleChangeRepair() {
if (radio_repair.value == 'b') {
getdeviceCheck()
} else {
getdeviceRepair()
}
}
let powerMonitoring = ref([
{ label: '当天耗电量', value: 8 },
{ label: '本周耗电量', value: 60 },
{ label: '本月耗电量', value: 288 }
])
//
function getelectMonitoring() {
electMonitoring().then(res => {
powerMonitoring.value = [
{ label: '当天耗电量', value: res.data.day },
{ label: '本周耗电量', value: res.data.week },
{ label: '本月耗电量', value: res.data.month }
]
})
}
let remindData = ref([])
//
function getdeviceCheck() {
deviceCheck().then(res => {
remindData.value = res.data
})
}
let repairData = ref([])
//
function getdeviceRepair() {
deviceRepair().then(res => {
repairData.value = res.data
})
}
//
function getdeviceStatus() {
deviceStatus().then(res => {
devStatus.wait = res.data.wait
devStatus.total = res.data.total
devStatus.stop = res.data.stop
devStatus.rate = res.data.rate
devStatus.work = res.data.work
devStatus.devTypes = res.data.devTypes
})
}
let rateData = ref()
//
function getdeviceRate() {
deviceRate().then(res => {
rateData.value = {
xAxis: res.data.dates,
series: res.data.rate
}
})
}
function handlePush2item(row) {
router.push({
path: '/screen/devItem_' + row.id,
})
}
//socket
function getWebsocket(val) {
try {
let data = JSON.parse(val);
if (data.type == "status") {
let obj = data.msg;
let flag = false;
let thatTime = new Date().getTime();
devList.value.forEach(item => {
if (item.id == obj.id) {
item.state = obj.status
// item.runTime = obj.runTime
flag = true
}
})
if (flag && thatTime - timer > 10000) {
timer = thatTime;
getdeviceStatus()
}
}
} catch (err) {
console.log(err);
}
}
function errWebsocket(val) {
// console.log(val);
}
onMounted(() => {
getListDevice()
getlistElect()
getelectMonitoring()
getdeviceStatus()
getdeviceRate()
getdeviceCheck()
getdeviceRepair()
getConfigKeyFun('screen.microFactory.title')
connectWebsocket('','',getWebsocket, errWebsocket)
})
onUnmounted(() => {
closeWebsocket()
})
</script>
<style lang="scss" scoped>
::v-deep(.table_header th) {
background-color: transparent !important;
color: #21dadb;
text-align: center;
}
.input-icon {
width: 32px;
height: 32px;
}
.container {
width: 1920px;
height: 1080px;
position: relative;
// display: flex;
// justify-content: center;
align-items: center;
background-image: url('/src/assets/images/screen-bg.png');
background-repeat: no-repeat;
/* 如果你不想让背景平铺 */
background-size: cover;
/* 或者其他你需要的大小设置 */
background-position: center;
.header {
width: 100%;
height: 89px;
background-image: url('/src/assets/images/screen-header-bg1.png');
background-size: 100% 100%;
.title {
width: 100%;
height: 89px;
font-size: 36px;
color: #f9f8f4;
text-align: center;
line-height: 89px;
font-weight: 700;
}
}
.content {
width: 100%;
height: 975px;
display: flex;
justify-content: space-around;
align-items: center;
box-sizing: border-box;
padding: 20px 0;
.left-panel,
.right-panel {
width: 488px;
height: 100%;
background-color: rgba(242, 242, 242, 0.0274509803921569);
.left-container {
width: 100%;
height: 320px;
}
.left-container-1 {
width: 100%;
height: 640px;
}
.radio-ab-lb {
position: absolute;
top: 23px;
right: 10px;
}
.left-tip-type {
position: absolute;
top: 0;
right: 0;
width: 200px;
height: 50px;
display: flex;
justify-content: space-between;
align-items: center;
font-size: 14px;
font-weight: 700;
.left-tip-type-item {
width: 33%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
}
}
}
.center-panel {
width: 900px;
height: 100%;
// background-color: rgba(242, 242, 242, 0.0274509803921569);
.dev-type-overview {
width: 100%;
height: 80px;
position: relative;
display: flex;
justify-content: space-around;
margin: 30px 0;
.status-item {
width: 120px;
height: 80px;
text-align: center;
color: #f9f8f4;
.value {
width: 100%;
height: 56px;
color: #21dadb;
font-weight: 700;
font-size: 20px;
position: relative;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
&::after {
content: "";
width: 1px;
height: 54px;
border: #f9f8f4 solid 1px;
position: absolute;
transform: rotate(30deg);
top: 0px;
left: 61px;
}
.on-text {
width: 24px;
height: 24px;
position: absolute;
top: 0;
left: 35px;
color: #7CFFB2;
text-align: center;
line-height: 24px;
}
.all-text {
width: 24px;
height: 24px;
position: absolute;
bottom: 0;
left: 60px;
color: #21dadb;
text-align: center;
line-height: 24px;
}
}
.label {
width: 100%;
height: 24px;
font-size: 18px;
font-weight: 700;
line-height: 24px;
}
}
.status-flag {
position: absolute;
width: 100%;
height: 50px;
top: -53px;
left: 15px;
display: flex;
flex-direction: row;
align-items: center;
.yuan {
width: 24px;
height: 24px;
border-radius: 50%;
}
.green {
background-color: #7CFFB2;
}
.blue {
background-color: #21dadb;
}
.flag-text {
color: #f9f8f4;
font-size: 18px;
font-weight: 700;
margin: 0 15px;
}
}
}
.status-overview {
position: relative;
width: 100%;
height: 400px;
background: url('./image/u16.png') no-repeat;
background-size: 100% 100%;
box-sizing: border-box;
padding: 22px;
color: #f9f8f4;
display: flex;
justify-content: center;
align-items: center;
.status-item {
position: relative;
width: 85%;
height: 80%;
.item-label {
position: absolute;
width: 167px;
height: 47px;
text-align: center;
background: url('./image/u19.png') no-repeat;
background-size: 100% 100%;
line-height: 47px;
}
}
.item-label-1 {
top: 0;
left: 0;
}
.item-label-2 {
top: 0;
right: 0;
}
.item-label-3 {
bottom: 0;
left: 0;
}
.item-label-4 {
bottom: 0;
right: 0;
}
.status-center {
position: absolute;
width: calc(85% - 370px);
height: calc(80% - 47px - 47px - 30px);
.item-value {
position: absolute;
width: 60px;
height: 60px;
background: url('./image/u107.png') no-repeat;
background-size: 100% 100%;
line-height: 60px;
text-align: center;
}
}
.centerChart {
position: absolute;
width: 300px;
height: 300px;
background: url('./image/u57.png') no-repeat;
background-size: 100% 100%;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
display: flex;
align-items: center;
justify-content: center;
.ring-chart {
width: 220px;
height: 220px;
}
}
}
.power-monitoring {
width: 100%;
height: 350px;
margin-top: 60px;
.power-item-wrapper {
width: 100%;
height: 100%;
display: flex;
justify-content: space-around;
align-items: center;
.power-item {
width: 280px;
height: 100%;
.item-label {
width: 100%;
height: 47px;
background: url('./image/u19.png') no-repeat;
background-size: 167px 47px;
background-position: center;
text-align: center;
line-height: 47px;
color: #f9f8f4;
font-size: 18px;
font-weight: 700;
margin: 6px 0;
}
.power-chart {
width: 247px;
height: 247px;
}
}
}
}
}
}
.footer {
width: 100%;
height: 16px;
background: url('./image/u26.png') no-repeat;
background-size: 100% 100%;
}
}
</style>

View File

@ -10,7 +10,7 @@ export default defineConfig(({ mode, command }) => {
// 部署生产环境和开发环境下的URL。 // 部署生产环境和开发环境下的URL。
// 默认情况下vite 会假设你的应用是被部署在一个域名的根路径上 // 默认情况下vite 会假设你的应用是被部署在一个域名的根路径上
// 例如 https://www.ruoyi.vip/。如果应用被部署在一个子路径上,你就需要用这个选项指定这个子路径。例如,如果你的应用被部署在 https://www.ruoyi.vip/admin/,则设置 baseUrl 为 /admin/。 // 例如 https://www.ruoyi.vip/。如果应用被部署在一个子路径上,你就需要用这个选项指定这个子路径。例如,如果你的应用被部署在 https://www.ruoyi.vip/admin/,则设置 baseUrl 为 /admin/。
base: VITE_APP_ENV === 'production' ? '/' : '/', base: VITE_APP_ENV === 'production' ? '/ras-web/' : '/',
plugins: createVitePlugins(env, command === 'build'), plugins: createVitePlugins(env, command === 'build'),
resolve: { resolve: {
// https://cn.vitejs.dev/config/#resolve-alias // https://cn.vitejs.dev/config/#resolve-alias
@ -31,8 +31,8 @@ export default defineConfig(({ mode, command }) => {
proxy: { proxy: {
// https://cn.vitejs.dev/config/#server-proxy // https://cn.vitejs.dev/config/#server-proxy
'/dev-api': { '/dev-api': {
target: 'http://192.168.10.97:9015', // target: 'http://192.168.10.65:9015',
// target: 'http://8.141.87.86:9015', target: 'http://8.141.87.86:9015',
// target: 'http://192.168.110.90:10393/mock/5ce74738-f63f-4d21-af85-b1d132c6f6fd', // target: 'http://192.168.110.90:10393/mock/5ce74738-f63f-4d21-af85-b1d132c6f6fd',
changeOrigin: true, changeOrigin: true,
rewrite: (p) => p.replace(/^\/dev-api/, '') rewrite: (p) => p.replace(/^\/dev-api/, '')