Commit 595f6442 authored by 赵啸非's avatar 赵啸非

添加设备导入导出功能

parent 3b316c4d
<template>
<div class="page">
<LayoutTable :data="tableData" :config="tableConfig">
<el-button
slot="table-head-left2"
style="margin-left: 10px"
icon="el-icon-tickets"
size="mini"
@click="handleImport"
>导入</el-button>
<el-button
slot="table-head-left2"
style="margin-left: 10px"
icon="el-icon-tickets"
size="mini"
@click="doExport"
:disabled="isExport"
>导出</el-button>
<el-tag slot="table-body-head" style="margin: 5px" type="success"
>当前在线设备总计:{{ tableData.onlineCount }}</el-tag
>
......@@ -20,7 +35,52 @@
>
</LayoutTable>
<!-- 设备导入对话框 -->
<el-dialog
:title="upload.title"
:visible.sync="upload.open"
width="400px"
append-to-body
>
<el-upload
ref="upload"
:limit="1"
accept=".xlsx, .xls"
:headers="upload.headers"
:action="upload.url + '?updateSupport=' + upload.updateSupport"
:disabled="upload.isUploading"
:on-progress="handleFileUploadProgress"
:on-success="handleFileSuccess"
:auto-upload="false"
drag
>
<i class="el-icon-upload"></i>
<div class="el-upload__text">
将文件拖到此处,或
<em>点击上传</em>
</div>
<div class="el-upload__tip" slot="tip">
<el-checkbox
v-model="upload.updateSupport"
/>是否更新已经存在的数据
<el-link type="primary" style="font-size: 14px" @click="downloadTemplate"
>下载模板</el-link
>
</div>
<div class="el-upload__tip" style="color: red" slot="tip">
提示:仅允许导入“xls”或“xlsx”格式文件!
</div>
</el-upload>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitFileForm">确 定</el-button>
<el-button @click="upload.open = false">取 消</el-button>
</div>
</el-dialog>
<dialog-show ref="dialogform" @ok="getData" />
<dialog-show ref="dialogform" @ok="getData" />
</div>
</template>
......@@ -34,6 +94,46 @@ export default {
mixins: [table],
created() {},
methods: {
/** 导入 */
handleImport() {
this.upload.title = "设备导入";
this.upload.open = true;
},
/** 下载模板操作 */
downloadTemplate() {
this.isExport = true;
this.$download("/device/downloadTemplate", {}, { type: "excel" })
.then(() => (this.isExport = false))
.catch((error) => {
this.isExport = false;
this.$message.error(error.message);
});
},
/** 文件上传中处理 */
handleFileUploadProgress(event, file, fileList) {
this.upload.isUploading = true;
},
/** 文件上传成功处理 */
handleFileSuccess(response, file, fileList) {
this.upload.open = false;
this.upload.isUploading = false;
this.$refs.upload.clearFiles();
this.$alert(response.msg, "导入结果", { dangerouslyUseHTMLString: true });
this.getData();
},
/** 提交上传文件 */
submitFileForm() {
this.$refs.upload.submit();
},
/** 导出Excel */
doExport() {
this.isExport = true;
this.$download("/device/exportExcel", {
}, { type: "excel" }).then(() => this.isExport = false).catch(error => {
this.isExport = false;
this.$message.error(error.message);
});
},
/** 重写新增方法 */
toAdd(row) {
this.$refs.dialogform.add(row);
......@@ -93,6 +193,20 @@ export default {
},
data() {
return {
// 用户导入参数
upload: {
// 是否显示弹出层(设备导入)
open: false,
// 弹出层标题(设备导入)
title: "导入设备数据",
// 是否禁用上传
isUploading: false,
// 是否更新已经存在的数据
updateSupport: 0,
// 上传的地址
url: "/m/device/importData",
},
isExport: false,
config: {
getsocketData: null,
search: [
......
......@@ -34,6 +34,10 @@ public class DeviceQueueAuthInfo implements Serializable {
* 交换机名称
*/
private String exchangeName;
/**
* 队列消息持久化时间
*/
private String messageTtl;
/**
* 设备上行topic队列
*/
......@@ -42,6 +46,10 @@ public class DeviceQueueAuthInfo implements Serializable {
* 设备下行topic队列
*/
private String downTopicFilter;
/**
* 首页
*/
private String homeUrl;
......
package com.mortals.xhx.busiz.security;
import cn.hutool.core.util.IdUtil;
import com.mortals.framework.service.ICacheService;
import com.mortals.framework.util.StringUtils;
import com.mortals.xhx.common.key.Constant;
import com.mortals.xhx.module.device.model.DeviceEntity;
import io.jsonwebtoken.Claims;
import lombok.extern.apachecommons.CommonsLog;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
/**
* token验证处理
*
* @author zxfei
*/
@Component
@CommonsLog
public class DeviceTokenService {
// 令牌自定义标识
@Value("${token.header}")
private String header;
// 令牌秘钥
@Value("${token.secret}")
private String secret;
// 令牌有效期(默认60分钟)
@Value("${token.expireTime}")
private int expireTime;
protected static final long MILLIS_SECOND = 1000;
protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND;
private static final Long MILLIS_MINUTE_TEN = 20 * 60 * 1000L;
@Autowired
private ICacheService cacheService;
/**
* 获取设备信息
*
* @return 设备信息
*/
public DeviceEntity getLoginDevice(HttpServletRequest request) {
// 获取请求携带的令牌
String token = getToken(request);
if (StringUtils.isNotEmpty(token)) {
try {
Claims claims = parseToken(token);
String uuid = (String) claims.get(Constant.LOGIN_DEVICE_KEY);
String deviceKey = getTokenKey(uuid);
DeviceEntity device = cacheService.get(deviceKey, DeviceEntity.class);
return device;
} catch (Exception e) {
log.error("解析jwt token异常!",e);
return null;
}
}
return null;
}
/**
* 设置设备信息
*/
public void setDevice(DeviceEntity device) {
if (StringUtils.isNotNull(device) && StringUtils.isNotEmpty(device.getToken())) {
refreshToken(device);
}
}
/**
* 删除用户身份信息
*/
public void delDevice(String token) {
if (StringUtils.isNotEmpty(token)) {
String deviceKey = getTokenKey(token);
cacheService.del(deviceKey);
}
}
/**
* 创建令牌
*
* @param device 设备信息
* @return 令牌
*/
public String createToken(DeviceEntity device) {
String token = IdUtil.fastSimpleUUID();
device.setToken(token);
refreshToken(device);
Map<String, Object> claims = new HashMap<>();
claims.put(Constant.LOGIN_DEVICE_KEY, token);
return createToken(claims);
}
/**
* 验证令牌有效期,相差不足20分钟,自动刷新缓存
*
* @param device
* @return 令牌
*/
public void verifyToken(DeviceEntity device) {
long expireTime = device.getExpireTime();
long currentTime = System.currentTimeMillis();
if (expireTime - currentTime <= MILLIS_MINUTE_TEN) {
refreshToken(device);
}
}
/**
* 刷新令牌有效期
*
* @param device 信息
*/
public void refreshToken(DeviceEntity device) {
device.setLoginTime(System.currentTimeMillis());
device.setExpireTime(device.getLoginTime() + expireTime * MILLIS_MINUTE);
// 根据uuid将device缓存
String deviceKey = getTokenKey(device.getToken());
//设置有效时间 单位秒
cacheService.setnx(deviceKey, device, expireTime * MILLIS_MINUTE * MILLIS_SECOND);
}
/**
* 从数据声明生成令牌
*
* @param claims 数据声明
* @return 令牌
*/
private String createToken(Map<String, Object> claims) {
String token = Jwts.builder()
.setClaims(claims)
.signWith(SignatureAlgorithm.HS512, secret).compact();
return token;
}
/**
* 从令牌中获取数据声明
*
* @param token 令牌
* @return 数据声明
*/
private Claims parseToken(String token) {
return Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(token)
.getBody();
}
/**
* 从令牌中获取设备编号
*
* @param token 令牌
* @return 用户名
*/
public String getDeviceNumFromToken(String token) {
Claims claims = parseToken(token);
return claims.getSubject();
}
/**
* 获取请求token
*
* @param request
* @return token
*/
private String getToken(HttpServletRequest request) {
String token = request.getHeader(header);
if (StringUtils.isNotEmpty(token) && token.startsWith(Constant.TOKEN_PREFIX)) {
token = token.replace(Constant.TOKEN_PREFIX, "");
}
return token;
}
private String getTokenKey(String uuid) {
return Constant.LOGIN_TOKEN_KEY + uuid;
}
}
//package com.mortals.xhx.busiz.security;
//
//import cn.hutool.core.util.IdUtil;
//import com.mortals.framework.service.ICacheService;
//import com.mortals.framework.util.StringUtils;
//import com.mortals.xhx.common.key.Constant;
//import com.mortals.xhx.module.device.model.DeviceEntity;
//import io.jsonwebtoken.Claims;
//import lombok.extern.apachecommons.CommonsLog;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.beans.factory.annotation.Value;
//import org.springframework.stereotype.Component;
//
//import javax.servlet.http.HttpServletRequest;
//import java.util.HashMap;
//import java.util.Map;
//
//import io.jsonwebtoken.Jwts;
//import io.jsonwebtoken.SignatureAlgorithm;
//
///**
// * token验证处理
// *
// * @author zxfei
// */
//@Component
//@CommonsLog
//public class DeviceTokenService {
// // 令牌自定义标识
// @Value("${token.header}")
// private String header;
//
// // 令牌秘钥
// @Value("${token.secret}")
// private String secret;
//
// // 令牌有效期(默认60分钟)
// @Value("${token.expireTime}")
// private int expireTime;
//
// protected static final long MILLIS_SECOND = 1000;
//
// protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND;
//
// private static final Long MILLIS_MINUTE_TEN = 20 * 60 * 1000L;
//
// @Autowired
// private ICacheService cacheService;
//
// /**
// * 获取设备信息
// *
// * @return 设备信息
// */
// public DeviceEntity getLoginDevice(HttpServletRequest request) {
// // 获取请求携带的令牌
// String token = getToken(request);
// if (StringUtils.isNotEmpty(token)) {
// try {
// Claims claims = parseToken(token);
// String uuid = (String) claims.get(Constant.LOGIN_DEVICE_KEY);
// String deviceKey = getTokenKey(uuid);
// DeviceEntity device = cacheService.get(deviceKey, DeviceEntity.class);
// return device;
// } catch (Exception e) {
// log.error("解析jwt token异常!",e);
// return null;
// }
// }
// return null;
// }
//
// /**
// * 设置设备信息
// */
// public void setDevice(DeviceEntity device) {
// if (StringUtils.isNotNull(device) && StringUtils.isNotEmpty(device.getToken())) {
// refreshToken(device);
// }
// }
//
// /**
// * 删除用户身份信息
// */
// public void delDevice(String token) {
// if (StringUtils.isNotEmpty(token)) {
// String deviceKey = getTokenKey(token);
// cacheService.del(deviceKey);
// }
// }
//
// /**
// * 创建令牌
// *
// * @param device 设备信息
// * @return 令牌
// */
// public String createToken(DeviceEntity device) {
// String token = IdUtil.fastSimpleUUID();
// device.setToken(token);
// refreshToken(device);
// Map<String, Object> claims = new HashMap<>();
// claims.put(Constant.LOGIN_DEVICE_KEY, token);
// return createToken(claims);
// }
//
// /**
// * 验证令牌有效期,相差不足20分钟,自动刷新缓存
// *
// * @param device
// * @return 令牌
// */
// public void verifyToken(DeviceEntity device) {
// long expireTime = device.getExpireTime();
// long currentTime = System.currentTimeMillis();
// if (expireTime - currentTime <= MILLIS_MINUTE_TEN) {
// refreshToken(device);
// }
// }
//
// /**
// * 刷新令牌有效期
// *
// * @param device 信息
// */
// public void refreshToken(DeviceEntity device) {
// device.setLoginTime(System.currentTimeMillis());
// device.setExpireTime(device.getLoginTime() + expireTime * MILLIS_MINUTE);
// // 根据uuid将device缓存
// String deviceKey = getTokenKey(device.getToken());
// //设置有效时间 单位秒
// cacheService.setnx(deviceKey, device, expireTime * MILLIS_MINUTE * MILLIS_SECOND);
// }
//
//
// /**
// * 从数据声明生成令牌
// *
// * @param claims 数据声明
// * @return 令牌
// */
// private String createToken(Map<String, Object> claims) {
// String token = Jwts.builder()
// .setClaims(claims)
// .signWith(SignatureAlgorithm.HS512, secret).compact();
// return token;
// }
//
// /**
// * 从令牌中获取数据声明
// *
// * @param token 令牌
// * @return 数据声明
// */
// private Claims parseToken(String token) {
// return Jwts.parser()
// .setSigningKey(secret)
// .parseClaimsJws(token)
// .getBody();
// }
//
// /**
// * 从令牌中获取设备编号
// *
// * @param token 令牌
// * @return 用户名
// */
// public String getDeviceNumFromToken(String token) {
// Claims claims = parseToken(token);
// return claims.getSubject();
// }
//
// /**
// * 获取请求token
// *
// * @param request
// * @return token
// */
// private String getToken(HttpServletRequest request) {
// String token = request.getHeader(header);
// if (StringUtils.isNotEmpty(token) && token.startsWith(Constant.TOKEN_PREFIX)) {
// token = token.replace(Constant.TOKEN_PREFIX, "");
// }
// return token;
// }
//
// private String getTokenKey(String uuid) {
// return Constant.LOGIN_TOKEN_KEY + uuid;
// }
//}
package com.mortals.xhx.busiz.security.filter;
import com.mortals.framework.util.StringUtils;
import com.mortals.xhx.busiz.security.SecurityUtils;
import com.mortals.xhx.busiz.security.DeviceTokenService;
import com.mortals.xhx.module.device.model.DeviceEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* token过滤器 验证token有效性
*
* @author ruoyi
*/
//@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
@Autowired
private DeviceTokenService deviceTokenService;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
DeviceEntity device = deviceTokenService.getLoginDevice(request);
if (StringUtils.isNotNull(device) && StringUtils.isNull(SecurityUtils.getAuthentication())) {
deviceTokenService.verifyToken(device);
}
chain.doFilter(request, response);
}
}
//package com.mortals.xhx.busiz.security.filter;
//
//import com.mortals.framework.util.StringUtils;
//import com.mortals.xhx.busiz.security.SecurityUtils;
//import com.mortals.xhx.busiz.security.DeviceTokenService;
//import com.mortals.xhx.module.device.model.DeviceEntity;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.web.filter.OncePerRequestFilter;
//
//import javax.servlet.FilterChain;
//import javax.servlet.ServletException;
//import javax.servlet.http.HttpServletRequest;
//import javax.servlet.http.HttpServletResponse;
//import java.io.IOException;
//
///**
// * token过滤器 验证token有效性
// *
// * @author ruoyi
// */
////@Component
//public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
// @Autowired
// private DeviceTokenService deviceTokenService;
//
// @Override
// protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
// throws ServletException, IOException {
// DeviceEntity device = deviceTokenService.getLoginDevice(request);
// if (StringUtils.isNotNull(device) && StringUtils.isNull(SecurityUtils.getAuthentication())) {
// deviceTokenService.verifyToken(device);
// }
// chain.doFilter(request, response);
// }
//}
......@@ -29,6 +29,7 @@ import com.mortals.xhx.module.product.model.ProductQuery;
import com.mortals.xhx.module.product.service.ProductService;
import com.mortals.xhx.queue.TbQueueMsgHeaders;
import com.mortals.xhx.queue.TopicPartitionInfo;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -70,6 +71,8 @@ public class DeviceApiController {
private int port;
@Value("${queue.rabbitmq.username:}")
private String username;
@Value("${queue.rabbitmq.queue-properties.x-message-ttl:86400000}")
private String messageTtl;
@Value("${token.secret}")
private String secret;
......@@ -91,7 +94,6 @@ public class DeviceApiController {
if (deviceEntity.getActive() != ActiveEnum.已激活.getValue()) {
throw new AppException("当前设备未激活,请在后台配置后再激活!");
}
if (deviceEntity.getStatus() != StatusEnum.启用.getValue()) {
throw new AppException("当前设备未启用,请在后台启用当前设备!");
}
......@@ -101,6 +103,7 @@ public class DeviceApiController {
authInfo.setPort(port);
authInfo.setUsername(username);
authInfo.setPassword(password);
authInfo.setMessageTtl(messageTtl);
authInfo.setVirtualHost(virtualHost);
PlatformEntity platformEntity = platformService.get(deviceEntity.getPlatformId());
if (ObjectUtils.isEmpty(platformEntity)) {
......@@ -114,6 +117,7 @@ public class DeviceApiController {
authInfo.setExchangeName(platformEntity.getPlatformSn() + Constant.EXCHANGE_SPLIT + productEntity.getProductCode());
authInfo.setUploadTopicFilter(Constant.UPLOAD_TOPIC + deviceEntity.getDeviceCode());
authInfo.setDownTopicFilter(Constant.DOWN_TOPIC + deviceEntity.getDeviceCode());
authInfo.setHomeUrl(platformEntity.getHomeUrl());
String content = AESUtil.encryptForApp(JSON.toJSONString(authInfo), secret);
deviceResp.setContent(content);
deviceEntity.setOnlineTime(new Date());
......
......@@ -106,6 +106,8 @@ host|String|ip|-
port|String|端口|-
virtualHost|String|虚拟机|-
exchangeName|String|交换机名称|-
messageTtl|String|队列消息超时时间,毫秒|-
homeUrl|String|首页|-
**响应消息样例:**
```
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment