Merge remote-tracking branch 'origin/master'

dev
xins 1 year ago
commit 0dde98d704

@ -9,7 +9,7 @@
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>rouyi-modules-mqttBroker</artifactId>
<artifactId>hw-mqtt-broker</artifactId>
<description>
海威物联网平台Broker模块
@ -22,11 +22,10 @@
<dependencies>
<!-- SpringCloud Alibaba Nacos -->
<!--<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- SpringCloud Alibaba Nacos Config -->
<dependency>
@ -47,12 +46,6 @@
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>net.dreamlu</groupId>
<artifactId>mica-redis</artifactId>
<version>2.7.9</version>
</dependency>
<dependency>
<groupId>net.dreamlu</groupId>
<artifactId>mica-logging</artifactId>

@ -0,0 +1,35 @@
package com.hw.mqtt.config;
import com.hw.mqtt.enums.RedisKeys;
import com.hw.mqtt.listener.RedisMessageListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
/**
* @author Wen JY
* @description: TODO
* @date 2023-09-11 15:35:20
* @version: 1.0
*/
@Configuration
public class RedisListenerConfig {
@Bean
RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory,
MessageListenerAdapter msgIngoListenerAdapter) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
// 可以添加多个 messageListener配置不同的交换机
container.addMessageListener(msgIngoListenerAdapter, new PatternTopic(RedisKeys.REDIS_CHANNEL_DOWN.getKey()));
return container;
}
@Bean
MessageListenerAdapter msgIngoListenerAdapter(RedisMessageListener receiver) {
return new MessageListenerAdapter(receiver, "deviceCommand");
}
}

@ -1,225 +0,0 @@
package com.hw.mqtt.domain;
import java.util.HashMap;
import java.util.Objects;
/**
* @author Wen JY
* @description: TODO
* @date 2023-08-17 13:33:31
* @version: 1.0
*/
public class AjaxResult extends HashMap<String, Object>
{
private static final long serialVersionUID = 1L;
/** 状态码 */
public static final String CODE_TAG = "code";
/** 返回内容 */
public static final String MSG_TAG = "msg";
/** 数据对象 */
public static final String DATA_TAG = "data";
/**
*
*/
public enum Type
{
/** 成功 */
SUCCESS(0),
/** 警告 */
WARN(301),
/** 错误 */
ERROR(500);
private final int value;
Type(int value)
{
this.value = value;
}
public int value()
{
return this.value;
}
}
/**
* AjaxResult 使
*/
public AjaxResult()
{
}
/**
* AjaxResult
*
* @param type
* @param msg
*/
public AjaxResult(Type type, String msg)
{
super.put(CODE_TAG, type.value);
super.put(MSG_TAG, msg);
}
/**
* AjaxResult
*
* @param type
* @param msg
* @param data
*/
public AjaxResult(Type type, String msg, Object data)
{
super.put(CODE_TAG, type.value);
super.put(MSG_TAG, msg);
if (isNotNull(data))
{
super.put(DATA_TAG, data);
}
}
/**
*
*
* @return
*/
public static AjaxResult success()
{
return AjaxResult.success("操作成功");
}
/**
*
*
* @return
*/
public static AjaxResult success(Object data)
{
return AjaxResult.success("操作成功", data);
}
/**
*
*
* @param msg
* @return
*/
public static AjaxResult success(String msg)
{
return AjaxResult.success(msg, null);
}
/**
*
*
* @param msg
* @param data
* @return
*/
public static AjaxResult success(String msg, Object data)
{
return new AjaxResult(Type.SUCCESS, msg, data);
}
/**
*
*
* @param msg
* @return
*/
public static AjaxResult warn(String msg)
{
return AjaxResult.warn(msg, null);
}
/**
*
*
* @param msg
* @param data
* @return
*/
public static AjaxResult warn(String msg, Object data)
{
return new AjaxResult(Type.WARN, msg, data);
}
/**
*
*
* @return
*/
public static AjaxResult error()
{
return AjaxResult.error("操作失败");
}
/**
*
*
* @param msg
* @return
*/
public static AjaxResult error(String msg)
{
return AjaxResult.error(msg, null);
}
/**
*
*
* @param msg
* @param data
* @return
*/
public static AjaxResult error(String msg, Object data)
{
return new AjaxResult(Type.ERROR, msg, data);
}
/**
*
*
* @return
*/
public boolean isSuccess()
{
return !isError();
}
/**
*
*
* @return
*/
public boolean isError()
{
return Objects.equals(Type.ERROR.value, this.get(CODE_TAG));
}
/**
* 便
*
* @param key
* @param value
* @return
*/
@Override
public AjaxResult put(String key, Object value)
{
super.put(key, value);
return this;
}
public static boolean isNotNull(Object object)
{
return !isNull(object);
}
public static boolean isNull(Object object)
{
return object == null;
}
}

@ -1,25 +0,0 @@
package com.hw.mqtt.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author WenJY
* @date 20230314 13:46
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ServerNode {
/**
*
*/
private String name;
/**
* ip:port
*/
private String peerHost;
}

@ -17,23 +17,20 @@
package com.hw.mqtt.listener;
import com.alibaba.fastjson2.JSONArray;
import com.hw.mqtt.domain.AjaxResult;
import com.hw.mqtt.enums.RedisKeys;
import net.dreamlu.iot.mqtt.core.server.MqttServerCreator;
import net.dreamlu.iot.mqtt.core.server.event.IMqttConnectStatusListener;
import net.dreamlu.iot.mqtt.spring.server.MqttServerTemplate;
import net.dreamlu.mica.redis.cache.MicaRedisCache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.tio.core.ChannelContext;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@ -50,26 +47,26 @@ public class MqttConnectStatusListener implements IMqttConnectStatusListener, Sm
private static final Logger logger = LoggerFactory.getLogger(MqttConnectStatusListener.class);
private final ApplicationContext context;
private final MicaRedisCache redisCache;
private final StringRedisTemplate redisTemplate;
private MqttServerCreator serverCreator;
private MqttServerTemplate mqttServerTemplate;
public MqttConnectStatusListener(ApplicationContext context, MicaRedisCache redisCache) {
public MqttConnectStatusListener(ApplicationContext context, StringRedisTemplate redisTemplate) {
this.context = context;
this.redisCache = redisCache;
this.redisTemplate = redisTemplate;
}
@Override
public void online(ChannelContext context, String clientId, String username) {
logger.info("Mqtt clientId:{} username:{} online.", clientId, username);
redisCache.sAdd(getRedisKey(), clientId);
redisTemplate.opsForSet().add(getRedisKey(), clientId);
pushConnectStatus(clientId,1);
}
@Override
public void offline(ChannelContext context, String clientId, String username, String reason) {
logger.info("Mqtt clientId:{} username:{} offline reason:{}.", clientId, username, reason);
redisCache.sRem(getRedisKey(), clientId);
redisTemplate.opsForSet().remove(getRedisKey(), clientId);
pushConnectStatus(clientId,2);
}
@ -91,7 +88,7 @@ public class MqttConnectStatusListener implements IMqttConnectStatusListener, Sm
@Override
public void destroy() throws Exception {
// 停机时删除集合
redisCache.del(getRedisKey());
redisTemplate.opsForSet().remove(getRedisKey());
}
/**

@ -0,0 +1,56 @@
package com.hw.mqtt.listener;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.core.utils.StringUtils;
import net.dreamlu.iot.mqtt.spring.server.MqttServerTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import java.nio.charset.StandardCharsets;
/**
* @author Wen JY
* @description: TODO
* @date 2023-09-11 15:28:18
* @version: 1.0
*/
@Component
public class RedisMessageListener {
private static final Logger logger = LoggerFactory.getLogger(RedisMessageListener.class);
@Autowired
private MqttServerTemplate mqttServerTemplate;
/**
*
* @param message
*/
public void deviceCommand(String message){
try {
if(StringUtils.isEmpty(message)){
logger.warn("Redis订阅内容为空");
return;
}
logger.info("Redis订阅内容"+message);
JSONObject jsonObject = JSONObject.parseObject(message);
String topic = jsonObject.get("Topic").toString();
String payload = jsonObject.get("Payload").toString();
boolean publishResult = mqttServerTemplate.publishAll(topic, payload.getBytes(StandardCharsets.UTF_8));
if(publishResult){
logger.info("Topic:"+topic+";Payload:"+payload+";消息发布成功");
}else {
logger.info("Topic:"+topic+";Payload:"+payload+";消息发布失败!!!");
}
}catch (Exception e){
logger.error("设备控制指令下发异常:"+e.getMessage());
}
}
}

@ -1,62 +0,0 @@
/*
* Copyright (c) 2019-2029, Dreamlu (596392912@qq.com & dreamlu.net).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hw.mqtt.service;
import java.util.List;
/**
* mqtt broker
*
* @author L.cm
*/
public interface IMqttBrokerService {
/**
* 线
* @author WenJY
* @date 2023-03-14 13:51
* @return long
*/
long getOnlineClientSize();
/**
* 线
* @author WenJY
* @date 2023-03-14 13:51
* @return java.util.List<java.lang.String>
*/
List<String> getOnlineClients();
/**
*
* @author WenJY
* @date 2023-03-14 13:50
* @param topic
* @param payload
* @return boolean
*/
boolean publish(String topic,String payload);
/**
*
* @author WenJY
* @date 2023-03-18 9:23
* @param clientId
*/
boolean closeClientById(String clientId);
}

@ -1,96 +0,0 @@
/*
* Copyright (c) 2019-2029, Dreamlu (596392912@qq.com & dreamlu.net).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hw.mqtt.service.impl;
import com.hw.mqtt.enums.RedisKeys;
import com.hw.mqtt.service.IMqttBrokerService;
import net.dreamlu.iot.mqtt.spring.server.MqttServerTemplate;
import net.dreamlu.mica.core.utils.StringPool;
import net.dreamlu.mica.redis.cache.MicaRedisCache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
/**
* mqtt broker
*
* @author L.cm
*/
@Service
public class MqttBrokerServiceImpl implements IMqttBrokerService {
private static final Logger logger = LoggerFactory.getLogger(MqttBrokerServiceImpl.class);
@Autowired private MicaRedisCache redisCache;
@Autowired private MqttServerTemplate server;
@Override
public long getOnlineClientSize() {
Set<String> keySet = redisCache.scan(RedisKeys.CONNECT_STATUS.getKey(StringPool.STAR));
if (keySet.isEmpty()) {
return 0L;
}
long result = 0;
for (String redisKey : keySet) {
Long count = redisCache.getSetOps().size(redisKey);
if (count != null) {
result += count;
}
}
return result;
}
@Override
public List<String> getOnlineClients() {
Set<String> keySet = redisCache.scan(RedisKeys.CONNECT_STATUS.getKey(StringPool.STAR));
if (keySet.isEmpty()) {
return Collections.emptyList();
}
List<String> clientList = new ArrayList<>();
for (String redisKey : keySet) {
Set<String> members = redisCache.sMembers(redisKey);
if (members != null && !members.isEmpty()) {
clientList.addAll(members);
}
}
return clientList;
}
@Override
public boolean publish(String topic, String payload) {
boolean result = server.publishAll(topic, payload.getBytes(StandardCharsets.UTF_8));
logger.info("Mqtt publishAll result:{};topic:{};payload:{}", result, topic, payload);
return result;
}
@Override
public boolean closeClientById(String clientId) {
try{
server.close(clientId);
}catch (Exception ex){
return false;
}
return true;
}
}

@ -1,27 +0,0 @@
package com.hw.mqtt.task;
import net.dreamlu.iot.mqtt.core.server.MqttServer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import java.nio.charset.StandardCharsets;
/**
*
* @author WenJY
* @date 2023-03-14 12:16
* @param null
* @return null
*/
@Service
public class PublishAllTask {
@Autowired
private MqttServer mqttServer;
@Scheduled(fixedDelay = 1000)
public void run() {
mqttServer.publishAll("/test/heartbeat", "心跳指令无需处理".getBytes(StandardCharsets.UTF_8));
}
}

@ -1,40 +0,0 @@
/*
* Copyright (c) 2019-2029, Dreamlu (596392912@qq.com & dreamlu.net).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hw.mqtt.util;
import net.dreamlu.mica.core.utils.CharPool;
/**
* redis
*
* @author L.cm
*/
public class RedisUtil {
/**
* redis pattern
*
* @return pattern
*/
public static String getTopicPattern(String topicFilter) {
// mqtt 分享主题 $share/{ShareName}/{filter}
return topicFilter
.replace(CharPool.PLUS, CharPool.STAR)
.replace(CharPool.HASH, CharPool.STAR);
}
}

@ -37,6 +37,7 @@
},
"dependencies": {
"@riophae/vue-treeselect": "0.4.0",
"Vue-i18n": "npm:vue-i18n@^8.26.7",
"axios": "0.24.0",
"clipboard": "2.0.8",
"core-js": "3.25.3",
@ -48,6 +49,8 @@
"js-beautify": "1.13.0",
"js-cookie": "3.0.1",
"jsencrypt": "3.0.0-rc.1",
"less": "^4.2.0",
"less-loader": "5.0.0",
"nprogress": "0.2.0",
"quill": "1.3.7",
"screenfull": "5.0.2",
@ -56,9 +59,9 @@
"vue-count-to": "1.0.13",
"vue-cropper": "0.5.5",
"vue-i18n": "8.26.7",
"Vue-i18n": "npm:vue-i18n@^8.26.7",
"vue-meta": "2.4.0",
"vue-router": "3.4.9",
"vue-seamless-scroll": "^1.1.23",
"vuedraggable": "2.24.3",
"vuex": "3.6.0"
},

Binary file not shown.

After

Width:  |  Height:  |  Size: 611 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 993 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 262 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 490 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 611 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 305 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 490 KiB

@ -0,0 +1,35 @@
<template>
<div />
</template>
<script>
import * as echarts from 'echarts';
export default {
expose: ['setData'],
data() {
return {
chart: null,
}
},
mounted() {
},
beforeDestroy() {
if (!this.chart) {
return
}
this.chart.dispose()
this.chart = null
},
methods: {
setData(option) {
this.initChart(option)
},
initChart(option) {
this.chart = echarts.init(this.$el, 'macarons')
this.chart.setOption(option)
}
}
}
</script>

@ -22,7 +22,7 @@ const messages = {
const i18n = new VueI18n({
// 设置语言 选项 en_US | zh_CN
locale: Cookies.get('language') || 'en_US',
locale: Cookies.get('language') || 'zh_CN',
// 设置文本内容
messages
})

@ -1,4 +1,6 @@
import Vue from 'vue'
import less from 'less'
import Cookies from 'js-cookie'
@ -64,6 +66,7 @@ Vue.component('ImagePreview', ImagePreview)
Vue.use(directive)
Vue.use(plugins)
Vue.use(VueMeta)
Vue.use(less)
DictData.install()
/**

@ -87,7 +87,38 @@ export const constantRoutes = [
meta: { title: '个人中心', icon: 'user' }
}
]
}
},
// {
// path: '/board1',
// component: () => import('@/views/board/index'),
// name: 'Index',
// meta: { title: '1', icon: 'dashboard', affix: true }
// },
// {
// path: '/board2',
// component: () => import('@/views/board/equipmentMonitoring'),
// name: 'Index',
// meta: { title: '2', icon: 'dashboard', affix: true }
// },
// {
// path: '/board3',
// component: () => import('@/views/board/GPS'),
// name: 'Index',
// meta: { title: '3', icon: 'dashboard', affix: true }
// },
// {
// path: '/board4',
// component: () => import('@/views/board/senso'),
// name: 'Index',
// meta: { title: '4', icon: 'dashboard', affix: true }
// },
// {
// path: '/board5',
// component: () => import('@/views/board/smartScene'),
// name: 'Index',
// meta: { title: '5', icon: 'dashboard', affix: true }
// },
]
// 动态路由,基于用户权限动态去加载

@ -0,0 +1,655 @@
<template>
<div class="container">
<div class="centerImg"></div>
<div>
<div class="menu menuClick" style="left: 2%">
<span>
监控主页
</span>
</div>
<div class="menu" style="left: 9%">
<el-dropdown trigger="click">
<span class="el-dropdown-link">
智慧场景 <i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>黄金糕</el-dropdown-item>
<el-dropdown-item>狮子头</el-dropdown-item>
<el-dropdown-item>螺蛳粉</el-dropdown-item>
<el-dropdown-item>双皮奶</el-dropdown-item>
<el-dropdown-item>蚵仔煎</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
<div class="menu" style="left: 16%">
<span>
设备监测
</span>
</div>
<div class="menu" style="left: 23%">
<span>
传感器汇总
</span>
</div>
</div>
<Chart ref="chart1" class="chart1"></Chart>
<div class="chart1Right">
<p style="color: #2ff;">电流互感器</p>
<p style="color: #f22;">电压互感器</p>
<p style="color: #f2f;">变压器</p>
<p style="color: #1f1;">电容电抗器</p>
</div>
<div class="chart1Table">
<div style="background-color: #094170">
<div class="scrollTable" style="font-weight: bold;">
名称
</div>
<div class="scrollTable" style="font-weight: bold;">
监控数量
</div>
<div class="scrollTable" style="font-weight: bold;">
报警数量
</div>
</div>
<vue-seamless-scroll
:class-option="chart1TableOption"
:data="chart1Data"
class="case-item"
style="height: 84%;overflow: hidden;"
>
<div
v-for="(item, index) in chart1Data"
:key="index"
>
<div :style='"background-color:" + ((index % 2 === 0)? "#053460":"#032d57") '>
<div
class="scrollTable">
{{ item.name }}
</div>
<div
class="scrollTable">
{{ item.value2 }}
</div>
<div
class="scrollTable">
{{ item.value }}
</div>
</div>
</div>
</vue-seamless-scroll>
</div>
<Chart ref="chart2" class="chart2"></Chart>
<div class="chart2Table">
<div style="background-color: #094170">
<div class="scrollTable" style="font-weight: bold;width: 50%">
名称
</div>
<div class="scrollTable" style="font-weight: bold;width: 50%">
数量
</div>
</div>
<vue-seamless-scroll
:class-option="chart1TableOption"
:data="chart2Data"
class="case-item"
style="height: 84%;overflow: hidden;"
>
<div
v-for="(item, index) in chart2Data"
:key="index"
>
<div :style='"background-color:" + ((index % 2 === 0)? "#053460":"#032d57") '>
<div class="scrollTable" style="width: 50%">
{{ item.name }}
</div>
<div class="scrollTable" style="width: 50%">
{{ item.value }}
</div>
</div>
</div>
</vue-seamless-scroll>
</div>
<div>
<div class="centerInfo">传感器数量</div>
<div class="centerInfo" style="font-weight:bold;top:19.3%;left: 42.5%;font-size: 2vw;">978</div>
<div class="centerInfo" style="left: 56%">监控单元数量</div>
<div class="centerInfo" style="font-weight:bold;top:19.3%;left: 66%;font-size: 2vw;">978</div>
</div>
<div class="inTransit">在运 <span style="color: #00f6ff">{{ inTransitNum }}</span></div>
<Chart ref="chart3" class="chart3"></Chart>
<div class="table1">
<div style="background-color: #094170">
<div class="scrollTable" style="font-weight: bold;width: 25%">
告警编号
</div>
<div class="scrollTable" style="font-weight: bold;width: 25%">
告警类型
</div>
<div class="scrollTable" style="font-weight: bold;width: 25%">
告警位置
</div>
<div class="scrollTable" style="font-weight: bold;width: 25%">
操作
</div>
</div>
<vue-seamless-scroll
:class-option="chart1TableOption"
:data="table1Data"
class="case-item"
style="height: calc(100% - 33px);overflow: hidden;"
>
<div
v-for="(item, index) in table1Data"
:key="index"
>
<div :style='"background-color:" + ((index % 2 === 0)? "#053460":"#032d57") '>
<div class="scrollTable" style="width: 25%">
{{ item.no }}
</div>
<div class="scrollTable" style="width: 25%">
{{ item.type }}
</div>
<div class="scrollTable" style="width: 25%">
{{ item.location }}
</div>
<div class="scrollTable" style="width: 25%">
<el-button size="mini" type="primary">操作</el-button>
</div>
</div>
</div>
</vue-seamless-scroll>
</div>
</div>
</template>
<script>
import Chart from "@/components/Charts/Chart";
import vueSeamlessScroll from "vue-seamless-scroll";
import * as echarts from 'echarts';
export default {
components: {
vueSeamlessScroll,
Chart
},
data() {
return {
chart1Option: {
tooltip: {},
angleAxis: {
max: 100,
clockwise: true,
show: false,
},
radiusAxis: {
type: "category",
show: true,
axisLabel: {
show: false,
},
axisLine: {
show: false,
},
axisTick: {
show: false,
},
},
polar: {
center: ["40%", "50%"],
radius: "100%", //
},
},
chart1Color: ['#2ff', '#f22', '#f2f', '#1f1'],
chart1Data: [
{
value: 12,
value2: 100,
name: '电流互感器',
},
{
value: 23,
value2: 100,
name: '电压互感器',
},
{
value: 34,
value2: 100,
name: '变压器',
},
{
value: 45,
value2: 100,
name: '电容电抗器',
}
],
chart1TableOption: {
step: 0.5, //
limitMoveNum: 3, // this.dataList.length
hoverStop: true, // stop
direction: 1, // 0 1 2 3
openWatch: true, // dom
singleHeight: 0, // (0) direction => 0/1
singleWidth: 0, // (0) direction => 2/3
waitTime: 0,
},
chart2Data: [
{
value: 111,
name: '无源温度传感器',
},
{
value: 111,
name: '有源温度传感器',
},
{
value: 111,
name: '烟雾传感器',
},
{
value: 111,
name: '温湿度传感器',
},
{
value: 111,
name: 'CO传感器',
}
],
chart2Option: {
color: ["#22acfd", "#22fe97", "#f9e728", "#ff922b", "#ed1814"],
legend: {
orient: "vertical",
x: "right",
y: "center",
textStyle: {
color: '#fff'
}
},
tooltip: {
trigger: "item",
formatter: "{b} : ({d}%)",
},
series: [
{
type: "pie",
radius: ["45%", "76%"],
center: ["35%", "50%"],
encode: {
itemName: "group",
value: "占比",
},
labelLine: {
show: false,
},
label: {
show: false,
},
itemStyle: {
opacity: '0.8'
}
},
{
type: "pie",
radius: ["75%", "90%"],
center: ["35%", "50%"],
encode: {
itemName: "group",
value: "占比",
},
labelLine: {
show: false,
},
label: {
show: false,
},
},
],
},
inTransitNum: 1999,
chart3Data: [
{
date: '10-01',
value: '100',
},
{
date: '10-02',
value: '200',
},
{
date: '10-03',
value: '100',
},
{
date: '10-04',
value: '300',
},
{
date: '10-05',
value: '200',
},
],
chart3Option: {
tooltip: {
trigger: "axis",
},
grid: {
top: "middle",
left: "3%",
right: "4%",
bottom: "3%",
height: "80%",
containLabel: true,
},
yAxis: {
type: "value",
splitLine: {
lineStyle: {
type: "dashed",
color: "#ccc3",
},
},
axisLine: {
show: false,
lineStyle: {
color: "#ccc",
},
},
nameTextStyle: {
color: "#999",
},
splitArea: {
show: false,
},
},
},
table1Data: [
{
no: '001',
type: '高温警告',
location: '车间',
},
{
no: '001',
type: '高温警告',
location: '车间',
},
{
no: '001',
type: '高温警告',
location: '车间',
},
{
no: '001',
type: '高温警告',
location: '车间',
},
{
no: '001',
type: '高温警告',
location: '车间',
},
{
no: '001',
type: '高温警告',
location: '车间',
},
{
no: '001',
type: '高温警告',
location: '车间',
},
{
no: '001',
type: '高温警告',
location: '车间',
},
{
no: '001',
type: '高温警告',
location: '车间',
},
{
no: '001',
type: '高温警告',
location: '车间',
},
{
no: '001',
type: '高温警告',
location: '车间',
},
]
}
},
mounted() {
let option1 = {
...this.chart1Option,
series: [
{
type: "bar",
data: this.chart1Data.map((e, i) => {
return {
value: (e.value / e.value2) * 100,
name: e.name,
itemStyle: {
color: this.chart1Color[i]
}
}
}),
showBackground: true,
coordinateSystem: "polar",
roundCap: true,
barWidth: 8,
},
]
}
this.$refs.chart1.setData(option1)
let chart2Num = eval(this.chart2Data.map(e => e.value).join("+"));
let option2 = {
...this.chart2Option,
dataset: {
source: [
["group", "占比"],
...this.chart2Data.map(e => [e.name, (e.value / chart2Num) * 100])
],
}
}
this.$refs.chart2.setData(option2)
let option3 = {
...this.chart3Option,
xAxis: {
boundaryGap: false,
type: "category",
data: this.chart3Data.map(e => e.date),
splitLine: {
show: true,
lineStyle: {
type: "dashed",
color: "#ccc3",
},
},
axisLine: {
lineStyle: {
color: "#999",
},
},
},
series: [
{
name: "",
type: "line",
data: this.chart3Data.map(e => e.value),
color: "#00dae0",
areaStyle: {
normal: {
color: new echarts.graphic.LinearGradient(
0,
0,
0,
1,
[
{
offset: 0,
color: "#00dae033",
},
{
offset: 1,
color: "rgba(0,202,149,0)",
},
],
false
),
shadowColor: "rgba(0,202,149, 0.9)",
shadowBlur: 20,
},
},
},
],
}
this.$refs.chart3.setData(option3)
},
methods: {}
};
</script>
<style scoped>
.container {
background-image: url("~@/assets/board/index/bg.jpg");
background-repeat: no-repeat;
background-size: 100% 100%;
width: 100%;
height: calc(100vh);
position: relative;
}
.centerImg {
background-image: url("~@/assets/board/index/container.png");
background-repeat: no-repeat;
background-size: 100% 100%;
position: absolute;
width: 45vw;
height: 20vw;
top: 60%;
left: 50%;
transform: translate(-50%, -50%);
}
.menu {
background-image: url("~@/assets/board/common/subheadClick1.png");
background-repeat: no-repeat;
background-size: 100% 100%;
position: absolute;
width: 8vw;
height: 1.66vw;
top: 3.8%;
line-height: 1.66vw;
font-size: 0.8vw;
color: #d4d4d4;
text-align: center;
}
.menu .el-dropdown {
font-size: 0.8vw;
color: #d4d4d4;
}
.menuClick {
background-image: url("~@/assets/board/common/subheadClick.png");
color: #f3f3f3;
}
.scrollTable {
color: rgb(185, 186, 192);
margin: auto 0px;
padding: 4px 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
text-align: center;
display: inline-block;
width: 33%;
}
.chart1 {
position: absolute;
width: 20%;
height: 21%;
top: 16%;
left: 3%;
}
.chart1Right {
background-image: url("~@/assets/board/common/bg1.png");
background-repeat: no-repeat;
background-size: 100% 100%;
padding: 0 12px;
position: absolute;
top: 17%;
left: 18%;
}
.chart1Table {
position: absolute;
top: 38%;
left: 2.8%;
width: 21%;
height: 14%;
overflow: hidden;
}
.chart2 {
position: absolute;
width: 20%;
height: 21%;
top: 58.5%;
left: 3%;
}
.chart2Table {
position: absolute;
top: 81%;
left: 2.8%;
width: 21%;
height: 15%;
overflow: hidden;
}
.centerInfo {
position: absolute;
width: 7%;
top: 17.5%;
left: 32.7%;
font-size: 1.4vw;
text-align: center;
transform: translateX(-50%);
color: #01c7fd;
letter-spacing: 4px;
}
.inTransit {
position: absolute;
top: 16%;
left: 87%;
transform: translateX(-50%);
font-size: 1.2vw;
color: rgb(30, 158, 223);
}
.chart3 {
position: absolute;
width: 21%;
height: 22%;
top: 21.5%;
left: 76.1%;
}
.table1 {
position: absolute;
width: 21%;
height: 50%;
top: 45.5%;
left: 76.3%;
}
</style>

@ -0,0 +1,516 @@
<template>
<div class="container">
<div class="centerImg"></div>
<div>
<div class="menu" style="left: 2%">
<span>
监控主页
</span>
</div>
<div class="menu" style="left: 9%">
<el-dropdown trigger="click">
<span class="el-dropdown-link">
智慧场景 <i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>黄金糕</el-dropdown-item>
<el-dropdown-item>狮子头</el-dropdown-item>
<el-dropdown-item>螺蛳粉</el-dropdown-item>
<el-dropdown-item>双皮奶</el-dropdown-item>
<el-dropdown-item>蚵仔煎</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
<div class="menu" style="left: 16%">
<span>
设备监测
</span>
</div>
<div class="menu menuClick " style="left: 23%">
<span>
传感器汇总
</span>
</div>
</div>
<div class="collapse">
<el-collapse v-model="activeName" accordion>
<el-collapse-item name="1">
<template slot="title">
<div class="itemBg">
<div class="icon"></div>
<div class="icon1"></div>
<div class="icon2"></div>
<div class="title"> 大厅-摄像头</div>
<div class="info">
<div class="info1">所属区域</div>
<div class="info2">大厅</div>
</div>
<div class="info" style="left: 70vh;">
<div class="info1">位置:</div>
<div class="info2">深圳</div>
</div>
<div class="info" style="left: 80vh;">
<div class="info1">日期:</div>
<div class="info2">2023-01-01 00:00:00</div>
</div>
</div>
</template>
<div>
<div>
<el-row :gutter="24">
<el-col :span="12">
<el-radio-group v-model="radio">
<el-radio-button label="日统计报表"></el-radio-button>
<el-radio-button label="月统计报表"></el-radio-button>
</el-radio-group>
</el-col>
<el-col :span="12">
<div style="position: absolute; right: 30px;">
<span style="color: #fff;"> 开始时间</span>
<div style="display: inline-block;width: 200px;margin-right: 12px;">
<el-date-picker type="date" placeholder="选择日期" style="width: 100%;"></el-date-picker>
</div>
<el-button type="primary">搜索</el-button>
<el-button>重置</el-button>
<el-button>导出</el-button>
</div>
</el-col>
</el-row>
<el-table :data="tableData" style="width: 100%;margin-top: 12px;"
:header-cell-style="{ textAlign: 'center' }"
:cell-style="{ textAlign: 'center',backgroundColor:'#08406f' }">
<el-table-column prop="date1" label="设备ID">
</el-table-column>
<el-table-column prop="date2" label="传感器编号">
</el-table-column>
<el-table-column prop="date3" label="xx">
</el-table-column>
<el-table-column prop="date4" label="编号">
</el-table-column>
<el-table-column prop="date5" label="xx">
</el-table-column>
<el-table-column prop="date6" label="温度">
</el-table-column>
<el-table-column prop="date7" label="湿度">
</el-table-column>
<el-table-column prop="date8" label="时间">
</el-table-column>
</el-table>
<el-pagination background layout="prev, pager, next" :total="1000">
</el-pagination>
</div>
</div>
</el-collapse-item>
<el-collapse-item name="2">
<template slot="title">
<div class="itemBg">
<div class="icon"></div>
<div class="icon1"></div>
<div class="icon2"></div>
<div class="title"> 大厅-摄像头</div>
<div class="info">
<div class="info1">所属区域</div>
<div class="info2">大厅</div>
</div>
<div class="info" style="left: 70vh;">
<div class="info1">位置:</div>
<div class="info2">深圳</div>
</div>
<div class="info" style="left: 80vh;">
<div class="info1">日期:</div>
<div class="info2">2023-01-01 00:00:00</div>
</div>
</div>
</template>
<div>
<div>
<el-row :gutter="24">
<el-col :span="12">
<el-radio-group v-model="radio">
<el-radio-button label="日统计报表"></el-radio-button>
<el-radio-button label="月统计报表"></el-radio-button>
</el-radio-group>
</el-col>
<el-col :span="12">
<div style="position: absolute; right: 30px;">
<span style="color: #fff;"> 开始时间</span>
<div style="display: inline-block;width: 200px;margin-right: 12px;">
<el-date-picker type="date" placeholder="选择日期" style="width: 100%;"></el-date-picker>
</div>
<el-button type="primary">搜索</el-button>
<el-button>重置</el-button>
<el-button>导出</el-button>
</div>
</el-col>
</el-row>
<el-table :data="tableData" style="width: 100%;margin-top: 12px;"
:header-cell-style="{ textAlign: 'center' }"
:cell-style="{ textAlign: 'center',backgroundColor:'#08406f' }">
<el-table-column prop="date1" label="设备ID">
</el-table-column>
<el-table-column prop="date2" label="传感器编号">
</el-table-column>
<el-table-column prop="date3" label="xx">
</el-table-column>
<el-table-column prop="date4" label="编号">
</el-table-column>
<el-table-column prop="date5" label="xx">
</el-table-column>
<el-table-column prop="date6" label="温度">
</el-table-column>
<el-table-column prop="date7" label="湿度">
</el-table-column>
<el-table-column prop="date8" label="时间">
</el-table-column>
</el-table>
<el-pagination background layout="prev, pager, next" :total="1000">
</el-pagination>
</div>
</div>
</el-collapse-item>
<el-collapse-item name="3">
<template slot="title">
<div class="itemBg">
<div class="icon"></div>
<div class="icon1"></div>
<div class="icon2"></div>
<div class="title"> 大厅-摄像头</div>
<div class="info">
<div class="info1">所属区域</div>
<div class="info2">大厅</div>
</div>
<div class="info" style="left: 70vh;">
<div class="info1">位置:</div>
<div class="info2">深圳</div>
</div>
<div class="info" style="left: 80vh;">
<div class="info1">日期:</div>
<div class="info2">2023-01-01 00:00:00</div>
</div>
</div>
</template>
<div>
<div>
<el-row :gutter="24">
<el-col :span="12">
<el-radio-group v-model="radio">
<el-radio-button label="日统计报表"></el-radio-button>
<el-radio-button label="月统计报表"></el-radio-button>
</el-radio-group>
</el-col>
<el-col :span="12">
<div style="position: absolute; right: 30px;">
<span style="color: #fff;"> 开始时间</span>
<div style="display: inline-block;width: 200px;margin-right: 12px;">
<el-date-picker type="date" placeholder="选择日期" style="width: 100%;"></el-date-picker>
</div>
<el-button type="primary">搜索</el-button>
<el-button>重置</el-button>
<el-button>导出</el-button>
</div>
</el-col>
</el-row>
<el-table :data="tableData" style="width: 100%;margin-top: 12px;"
:header-cell-style="{ textAlign: 'center' }"
:cell-style="{ textAlign: 'center',backgroundColor:'#08406f' }">
<el-table-column prop="date1" label="设备ID">
</el-table-column>
<el-table-column prop="date2" label="传感器编号">
</el-table-column>
<el-table-column prop="date3" label="xx">
</el-table-column>
<el-table-column prop="date4" label="编号">
</el-table-column>
<el-table-column prop="date5" label="xx">
</el-table-column>
<el-table-column prop="date6" label="温度">
</el-table-column>
<el-table-column prop="date7" label="湿度">
</el-table-column>
<el-table-column prop="date8" label="时间">
</el-table-column>
</el-table>
<el-pagination background layout="prev, pager, next" :total="1000">
</el-pagination>
</div>
</div>
</el-collapse-item>
<el-collapse-item name="4">
<template slot="title">
<div class="itemBg">
<div class="icon"></div>
<div class="icon1"></div>
<div class="icon2"></div>
<div class="title"> 大厅-摄像头</div>
<div class="info">
<div class="info1">所属区域</div>
<div class="info2">大厅</div>
</div>
<div class="info" style="left: 70vh;">
<div class="info1">位置:</div>
<div class="info2">深圳</div>
</div>
<div class="info" style="left: 80vh;">
<div class="info1">日期:</div>
<div class="info2">2023-01-01 00:00:00</div>
</div>
</div>
</template>
<div>
<div>
<el-row :gutter="24">
<el-col :span="12">
<el-radio-group v-model="radio">
<el-radio-button label="日统计报表"></el-radio-button>
<el-radio-button label="月统计报表"></el-radio-button>
</el-radio-group>
</el-col>
<el-col :span="12">
<div style="position: absolute; right: 30px;">
<span style="color: #fff;"> 开始时间</span>
<div style="display: inline-block;width: 200px;margin-right: 12px;">
<el-date-picker type="date" placeholder="选择日期" style="width: 100%;"></el-date-picker>
</div>
<el-button type="primary">搜索</el-button>
<el-button>重置</el-button>
<el-button>导出</el-button>
</div>
</el-col>
</el-row>
<el-table :data="tableData" style="width: 100%;margin-top: 12px;"
:header-cell-style="{ textAlign: 'center' }"
:cell-style="{ textAlign: 'center',backgroundColor:'#08406f' }">
<el-table-column prop="date1" label="设备ID">
</el-table-column>
<el-table-column prop="date2" label="传感器编号">
</el-table-column>
<el-table-column prop="date3" label="xx">
</el-table-column>
<el-table-column prop="date4" label="编号">
</el-table-column>
<el-table-column prop="date5" label="xx">
</el-table-column>
<el-table-column prop="date6" label="温度">
</el-table-column>
<el-table-column prop="date7" label="湿度">
</el-table-column>
<el-table-column prop="date8" label="时间">
</el-table-column>
</el-table>
<el-pagination background layout="prev, pager, next" :total="1000">
</el-pagination>
</div>
</div>
</el-collapse-item>
</el-collapse>
</div>
</div>
</template>
<script>
export default {
components: {
},
data() {
return {
radio: '日统计报表',
tableData: [{
date1: '1233454576',
date2: '1233454576',
date3: 'DFHDGHJK',
date4: '12',
date5: 'QSD',
date6: '111',
date7: '222',
date8: new Date().getDate(),
}, {
date1: '1233454576',
date2: '1233454576',
date3: 'DFHDGHJK',
date4: '12',
date5: 'QSD',
date6: '111',
date7: '222',
date8: new Date().getDate(),
}, {
date1: '1233454576',
date2: '1233454576',
date3: 'DFHDGHJK',
date4: '12',
date5: 'QSD',
date6: '111',
date7: '222',
date8: new Date().getDate(),
}, {
date1: '1233454576',
date2: '1233454576',
date3: 'DFHDGHJK',
date4: '12',
date5: 'QSD',
date6: '111',
date7: '222',
date8: new Date().getDate(),
}]
}
},
mounted() {
},
methods: {}
};
</script>
<style lang="less" >
.container {
background-image: url("~@/assets/board/senso/bg.jpg");
background-repeat: no-repeat;
background-size: 100% 100%;
width: 100%;
height: calc(100vh);
position: relative;
}
.menu {
background-image: url("~@/assets/board/common/subheadClick1.png");
background-repeat: no-repeat;
background-size: 100% 100%;
position: absolute;
width: 8vw;
height: 1.66vw;
top: 3.8%;
line-height: 1.66vw;
font-size: 0.8vw;
color: #d4d4d4;
text-align: center;
}
.menu .el-dropdown {
font-size: 0.8vw;
color: #d4d4d4;
}
.menuClick {
background-image: url("~@/assets/board/common/subheadClick.png");
color: #f3f3f3;
}
.collapse {
position: absolute;
top: 9%;
left: 2%;
width: 96%;
height: 87%;
.el-collapse-item__wrap {
background-color: #0000;
border-color: #0000;
}
.el-table {
background-color: #FFF0 !important;
color: #fff;
}
.el-table tr {
background-color: #FFF0 !important;
}
.el-table th.el-table__cell.is-leaf, .el-table td.el-table__cell{
border-color: #0000;
}
.el-table::before, .el-table--group::after, .el-table--border::after{
background-color: #0000;
}
.el-table .el-table__header-wrapper th, .el-table .el-table__fixed-header-wrapper th{
background-color: #0000;
}
}
.collapse .el-collapse-item__header {
background-color: #0000;
border-color: #0000;
height: auto;
}
.collapse .el-collapse {
border-color: #0000;
}
.collapse .el-collapse-item {
// margin-bottom: 2vh;
}
.itemBg {
background-image: url("~@/assets/board/senso/itemBg.png");
background-repeat: no-repeat;
background-size: 100% 100%;
width: 100%;
height: 17vh;
position: relative;
.icon {
background-image: url("~@/assets/board/senso/iconBg.png");
background-repeat: no-repeat;
background-size: 100% 100%;
position: absolute;
top: 2vh;
left: 5vh;
width: 13vh;
height: 13vh;
}
.icon1 {
background-image: url("~@/assets/board/senso/iconBottom.png");
background-repeat: no-repeat;
background-size: 100% 100%;
position: absolute;
top: 2vh;
left: 5vh;
width: 13vh;
height: 13vh;
}
.icon2 {
background-image: url("~@/assets/board/senso/icon.png");
background-repeat: no-repeat;
background-size: 100% 100%;
position: absolute;
top: 50%;
left: 10vh;
width: 2.6vh;
height: 3.3vh;
transform: translateY(-50%);
}
.title {
position: absolute;
left: 25vh;
color: #1fabf3;
line-height: 17vh;
font-size: 2.5vh;
}
.info {
position: absolute;
left: 60vh;
color: #1fabf3;
font-size: 1.5vh;
height: 100%;
white-space: nowrap;
.info1 {
position: absolute;
bottom: 55%;
color: #fffc
}
.info2 {
position: absolute;
top: 55%;
color: #fff
}
}
}
</style>

@ -0,0 +1,537 @@
<template>
<div class="container">
<div>
<div class="menu " style="left: 2%">
<span>
监控主页
</span>
</div>
<div class="menu menuClick" style="left: 9%">
<el-dropdown trigger="click">
<span class="el-dropdown-link">
智慧场景 <i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>黄金糕</el-dropdown-item>
<el-dropdown-item>狮子头</el-dropdown-item>
<el-dropdown-item>螺蛳粉</el-dropdown-item>
<el-dropdown-item>双皮奶</el-dropdown-item>
<el-dropdown-item>蚵仔煎</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
<div class="menu" style="left: 16%">
<span>
设备监测
</span>
</div>
<div class="menu" style="left: 23%">
<span>
传感器汇总
</span>
</div>
</div>
<div class="num1">30</div>
<div class="num2">216</div>
<div class="num3">0</div>
<div class="num4">0</div>
<div class="num5">0</div>
<div class="num6">0</div>
<div class="num7">0</div>
<div class="num8">0</div>
<div class="title1">监控单元</div>
<div class="title2">传感器</div>
<div class="title3">设备高温</div>
<div class="title4">设备振动</div>
<div class="title5">烟雾火情</div>
<div class="title6">环境大风</div>
<div class="title7">柜内温度</div>
<div class="title8">柜内冰浸</div>
<div class="title9">告警信息</div>
<div class="title10">监控单元</div>
<div class="table1">
<div style="background-color: #094170">
<div class="scrollTable" style="font-weight: bold;width: 8%">
告警编号
</div>
<div class="scrollTable" style="font-weight: bold;width: 8%">
告警类型
</div>
<div class="scrollTable" style="font-weight: bold;width: 15%">
告警单元
</div>
<div class="scrollTable" style="font-weight: bold;width: 30%">
告警信息
</div>
<div class="scrollTable" style="font-weight: bold;width: 11%">
告警位置
</div>
<div class="scrollTable" style="font-weight: bold;width: 20%">
告警时间
</div>
<div class="scrollTable" style="font-weight: bold;width: 8%">
处理情况
</div>
</div>
<vue-seamless-scroll :class-option="chart1TableOption" :data="table1Data" class="case-item"
style="height: calc(100% - 33px);overflow: hidden;">
<div v-for="(item, index) in table1Data" :key="index">
<div :style='"background-color:" + ((index % 2 === 0) ? "#053460" : "#032d57")'>
<div class="scrollTable" style="width: 8%">
{{ item.data1 }}
</div>
<div class="scrollTable" style="width: 8%">
{{ item.data2 }}
</div>
<div class="scrollTable" style="width: 15%">
{{ item.data3 }}
</div>
<div class="scrollTable" style="width: 30%">
{{ item.data4 }}
</div>
<div class="scrollTable" style="width: 11%">
{{ item.data5 }}
</div>
<div class="scrollTable" style="width: 20%">
{{ item.data6 }}
</div>
<div class="scrollTable" style="width: 8%">
<span style="color: #67C23A;">已处理</span>
</div>
</div>
</div>
</vue-seamless-scroll>
</div>
<div class="right">
<el-row>
<el-col :span="12">
<div class="item">
<div class="titleBg"></div>
<div class="title">
<span style="margin-right: 28px;"> 变压器 </span>
<el-tag type="success">正常</el-tag>
</div>
<div class="img"></div>
</div>
</el-col>
<el-col :span="12">
<div class="item">
<div class="titleBg"></div>
<div class="title">
<span style="margin-right: 28px;"> 变压器 </span>
<el-tag type="success">正常</el-tag>
</div>
<div class="img"></div>
</div>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<div class="item">
<div class="titleBg"></div>
<div class="title">
<span style="margin-right: 28px;"> 变压器 </span>
<el-tag type="success">正常</el-tag>
</div>
<div class="img"></div>
</div>
</el-col>
<el-col :span="12">
<div class="item">
<div class="titleBg"></div>
<div class="title">
<span style="margin-right: 28px;"> 变压器 </span>
<el-tag type="success">正常</el-tag>
</div>
<div class="img"></div>
</div>
</el-col>
</el-row>
<div class="pagination">
<el-pagination :page-size="20" :pager-count="11" layout="prev, pager, next" :total="1000">
</el-pagination>
</div>
</div>
</div>
</template>
<script>
import vueSeamlessScroll from "vue-seamless-scroll";
export default {
components: {
vueSeamlessScroll,
},
data() {
return {
table1Data: [
{
data1: '001',
data2: '越限',
data3: '123123',
data4: '无线检测 检测值为 21° - 25°',
data5: '设备11233',
data6: '2021.01.01 00:00:00',
},
{
data1: '001',
data2: '越限',
data3: '123123',
data4: '无线检测 检测值为 21° - 25°',
data5: '设备11233',
data6: '2021.01.01 00:00:00',
},
{
data1: '001',
data2: '越限',
data3: '123123',
data4: '无线检测 检测值为 21° - 25°',
data5: '设备11233',
data6: '2021.01.01 00:00:00',
},
{
data1: '001',
data2: '越限',
data3: '123123',
data4: '无线检测 检测值为 21° - 25°',
data5: '设备11233',
data6: '2021.01.01 00:00:00',
},
{
data1: '001',
data2: '越限',
data3: '123123',
data4: '无线检测 检测值为 21° - 25°',
data5: '设备11233',
data6: '2021.01.01 00:00:00',
},
{
data1: '001',
data2: '越限',
data3: '123123',
data4: '无线检测 检测值为 21° - 25°',
data5: '设备11233',
data6: '2021.01.01 00:00:00',
},
{
data1: '001',
data2: '越限',
data3: '123123',
data4: '无线检测 检测值为 21° - 25°',
data5: '设备11233',
data6: '2021.01.01 00:00:00',
},
{
data1: '001',
data2: '越限',
data3: '123123',
data4: '无线检测 检测值为 21° - 25°',
data5: '设备11233',
data6: '2021.01.01 00:00:00',
},
{
data1: '001',
data2: '越限',
data3: '123123',
data4: '无线检测 检测值为 21° - 25°',
data5: '设备11233',
data6: '2021.01.01 00:00:00',
},
{
data1: '001',
data2: '越限',
data3: '123123',
data4: '无线检测 检测值为 21° - 25°',
data5: '设备11233',
data6: '2021.01.01 00:00:00',
},
{
data1: '001',
data2: '越限',
data3: '123123',
data4: '无线检测 检测值为 21° - 25°',
data5: '设备11233',
data6: '2021.01.01 00:00:00',
},
]
}
},
mounted() {
},
methods: {}
};
</script>
<style lang="less" scoped>
.container {
background-image: url("~@/assets/board/standard/bg.jpg");
background-repeat: no-repeat;
background-size: 100% 100%;
width: 100%;
height: calc(100vh);
position: relative;
}
.menu {
background-image: url("~@/assets/board/common/subheadClick1.png");
background-repeat: no-repeat;
background-size: 100% 100%;
position: absolute;
width: 8vw;
height: 1.66vw;
top: 3.8%;
line-height: 1.66vw;
font-size: 0.8vw;
color: #d4d4d4;
text-align: center;
}
.menu .el-dropdown {
font-size: 0.8vw;
color: #d4d4d4;
}
.menuClick {
background-image: url("~@/assets/board/common/subheadClick.png");
color: #f3f3f3;
}
.num1 {
position: absolute;
top: 21%;
left: 18%;
transform: translate(-50%, -50%);
font-size: 3vw;
color: #15d654;
}
.num2 {
position: absolute;
top: 21%;
left: 33%;
transform: translate(-50%, -50%);
font-size: 3vw;
color: #00fff0;
}
.num3 {
position: absolute;
top: 52%;
left: 7.5%;
transform: translate(-50%, -50%);
font-size: 2vw;
color: #d73827;
}
.num4 {
position: absolute;
top: 52%;
left: 15%;
transform: translate(-50%, -50%);
font-size: 2vw;
color: #1ef16d;
}
.num5 {
position: absolute;
top: 52%;
left: 22.5%;
transform: translate(-50%, -50%);
font-size: 2vw;
color: #f2711f;
}
.num6 {
position: absolute;
top: 52%;
left: 30%;
transform: translate(-50%, -50%);
font-size: 2vw;
color: #2a46f9;
}
.num7 {
position: absolute;
top: 52%;
left: 37.5%;
transform: translate(-50%, -50%);
font-size: 2vw;
color: #00a3fd;
}
.num8 {
position: absolute;
top: 52%;
left: 45%;
transform: translate(-50%, -50%);
font-size: 2vw;
color: #eff721;
}
.title1 {
position: absolute;
top: 28%;
left: 18%;
transform: translate(-50%, -50%);
font-size: 2vw;
color: #62bff2;
}
.title2 {
position: absolute;
top: 28%;
left: 33%;
transform: translate(-50%, -50%);
font-size: 2vw;
color: #62bff2;
}
.title3 {
position: absolute;
top: 48%;
left: 7.5%;
transform: translate(-50%, -50%);
font-size: 1vw;
color: #fff;
}
.title4 {
position: absolute;
top: 48%;
left: 15%;
transform: translate(-50%, -50%);
font-size: 1vw;
color: #fff;
}
.title5 {
position: absolute;
top: 48%;
left: 22.5%;
transform: translate(-50%, -50%);
font-size: 1vw;
color: #fff;
}
.title6 {
position: absolute;
top: 48%;
left: 30%;
transform: translate(-50%, -50%);
font-size: 1vw;
color: #fff;
}
.title7 {
position: absolute;
top: 48%;
left: 37.5%;
transform: translate(-50%, -50%);
font-size: 1vw;
color: #fff;
}
.title8 {
position: absolute;
top: 48%;
left: 45%;
transform: translate(-50%, -50%);
font-size: 1vw;
color: #fff;
}
.title9 {
position: absolute;
top: 61%;
left: 26.1%;
transform: translate(-50%, -50%);
font-size: 1vw;
color: #fff;
}
.title10 {
position: absolute;
top: 13%;
left: 74.3%;
transform: translate(-50%, -50%);
font-size: 1vw;
color: #fff;
}
.table1 {
position: absolute;
top: 63%;
left: 3.5%;
width: 45.4%;
height: 32%;
}
.scrollTable {
color: rgb(185, 186, 192);
margin: auto 0px;
padding: 4px 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
text-align: center;
display: inline-block;
}
.right {
position: absolute;
top: 16%;
left: 52%;
width: 44.8%;
height: 80%;
.item {
width: 22vw;
height: 37vh;
position: relative;
border: 1px solid #1ea6ec;
margin-bottom: 12px;
.titleBg {
position: absolute;
top: 0%;
left: 0%;
width: 100%;
height: 10%;
background-color: #063b5a;
}
.title {
position: absolute;
top: 5%;
left: 50%;
transform: translate(-50%, -50%);
color: #fff9f6;
font-size: 0.9vw;
.el-tag.el-tag--success {
vertical-align: top !important;
}
}
.img {
background-image: url("~@/assets/board/standard/device.png");
background-repeat: no-repeat;
background-size: 100% 100%;
position: absolute;
width: 100%;
height: 90%;
top: 10%;
}
}
.pagination{
position: relative;
left: 50%;
transform: translateX(-50%);
display: inline-block;
.el-pagination{
display: inline-block;
}
}
}
</style>
Loading…
Cancel
Save