Browse Source

onenet推送

master
lijunjie 2 years ago
parent
commit
b6e3f00ad4
  1. 13
      pom.xml
  2. 9
      ruoyi-admin/pom.xml
  3. 46
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/OnenetRecordController.java
  4. 105
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/device/OnenetReceiveController.java
  5. 2
      ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java
  6. 84
      ruoyi-admin/src/main/java/com/ruoyi/web/domain/po/OnenetReceive.java
  7. 61
      ruoyi-admin/src/main/java/com/ruoyi/web/persist/mapper/OnenetReceiveMapper.java
  8. 69
      ruoyi-admin/src/main/java/com/ruoyi/web/service/IOnenetReceiveService.java
  9. 2
      ruoyi-admin/src/main/java/com/ruoyi/web/service/impl/OnenetEquipServiceImpl.java
  10. 136
      ruoyi-admin/src/main/java/com/ruoyi/web/service/impl/OnenetReceiveServiceImpl.java
  11. 176
      ruoyi-admin/src/main/java/com/ruoyi/web/util/OnenetUtil.java
  12. 83
      ruoyi-admin/src/main/resources/mapper/device/OnenetReceiveMapper.xml
  13. 22
      ruoyi-ui/.env.development
  14. 16
      ruoyi-ui/.env.production
  15. 20
      ruoyi-ui/.env.staging
  16. 180
      ruoyi-ui/package.json
  17. 9
      ruoyi-ui/src/api/device/equips.js
  18. 44
      ruoyi-ui/src/api/device/receive.js
  19. 186
      ruoyi-ui/src/layout/components/Sidebar/Logo.vue
  20. 108
      ruoyi-ui/src/views/device/equips/index.vue
  21. 291
      ruoyi-ui/src/views/device/receive/index.vue
  22. 1972
      ruoyi-ui/src/views/index.vue
  23. 438
      ruoyi-ui/src/views/login.vue
  24. 418
      ruoyi-ui/src/views/register.vue
  25. 273
      ruoyi-ui/vue.config.js

13
pom.xml

@ -10,7 +10,7 @@
<name>ruoyi</name> <name>ruoyi</name>
<url>http://www.ruoyi.vip</url> <url>http://www.ruoyi.vip</url>
<description>若依管理系统</description> <description>传控管理系统</description>
<properties> <properties>
<ruoyi.version>3.8.5</ruoyi.version> <ruoyi.version>3.8.5</ruoyi.version>
@ -194,6 +194,17 @@
<version>${hutool.version}</version> <version>${hutool.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.54</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.10</version>
</dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>

9
ruoyi-admin/pom.xml

@ -66,6 +66,15 @@
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>

46
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/OnenetRecordController.java

@ -0,0 +1,46 @@
package com.ruoyi.web.controller.api;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.web.service.IOnenetReceiveService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* onenet推送
*
* @author lijunjie
* @date 2023-01-16
*/
@Slf4j
@RestController
@Anonymous
@RequestMapping("/api/onenet/record")
public class OnenetRecordController
{
@Autowired
private IOnenetReceiveService onenetReceiveService;
/**
* 查询onenet参数列表
*/
@GetMapping("/receive")
public String receive(@RequestParam("msg") String msg, @RequestParam("nonce") String nonce, @RequestParam("signature") String signature)
{
System.out.println(msg);
System.out.println(nonce);
System.out.println(signature);
return msg;
}
@PostMapping("/receive")
public String receive(@RequestBody String request)
{
System.out.println(request);
boolean res = onenetReceiveService.addOnenetReceive(request);
return "ok";
}
}

105
ruoyi-admin/src/main/java/com/ruoyi/web/controller/device/OnenetReceiveController.java

@ -0,0 +1,105 @@
package com.ruoyi.web.controller.device;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import com.ruoyi.web.domain.po.OnenetReceive;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.web.service.IOnenetReceiveService;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;
/**
* onenet推送记录Controller
*
* @author lijunjie
* @date 2023-02-02
*/
@RestController
@RequestMapping("/device/receive")
public class OnenetReceiveController extends BaseController
{
@Autowired
private IOnenetReceiveService onenetReceiveService;
/**
* 查询onenet推送记录列表
*/
@PreAuthorize("@ss.hasPermi('device:receive:list')")
@GetMapping("/list")
public TableDataInfo list(OnenetReceive onenetReceive)
{
startPage();
List<OnenetReceive> list = onenetReceiveService.selectOnenetReceiveList(onenetReceive);
return getDataTable(list);
}
/**
* 导出onenet推送记录列表
*/
@PreAuthorize("@ss.hasPermi('device:receive:export')")
@Log(title = "onenet推送记录", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, OnenetReceive onenetReceive)
{
List<OnenetReceive> list = onenetReceiveService.selectOnenetReceiveList(onenetReceive);
ExcelUtil<OnenetReceive> util = new ExcelUtil<OnenetReceive>(OnenetReceive.class);
util.exportExcel(response, list, "onenet推送记录数据");
}
/**
* 获取onenet推送记录详细信息
*/
@PreAuthorize("@ss.hasPermi('device:receive:query')")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return success(onenetReceiveService.selectOnenetReceiveById(id));
}
/**
* 新增onenet推送记录
*/
@PreAuthorize("@ss.hasPermi('device:receive:add')")
@Log(title = "onenet推送记录", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody OnenetReceive onenetReceive)
{
return toAjax(onenetReceiveService.insertOnenetReceive(onenetReceive));
}
/**
* 修改onenet推送记录
*/
@PreAuthorize("@ss.hasPermi('device:receive:edit')")
@Log(title = "onenet推送记录", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody OnenetReceive onenetReceive)
{
return toAjax(onenetReceiveService.updateOnenetReceive(onenetReceive));
}
/**
* 删除onenet推送记录
*/
@PreAuthorize("@ss.hasPermi('device:receive:remove')")
@Log(title = "onenet推送记录", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(onenetReceiveService.deleteOnenetReceiveByIds(ids));
}
}

2
ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java

@ -113,7 +113,7 @@ public class SwaggerConfig
// 用ApiInfoBuilder进行定制 // 用ApiInfoBuilder进行定制
return new ApiInfoBuilder() return new ApiInfoBuilder()
// 设置标题 // 设置标题
.title("标题:若依管理系统_接口文档") .title("标题:传控管理系统_接口文档")
// 描述 // 描述
.description("描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...") .description("描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...")
// 作者信息 // 作者信息

84
ruoyi-admin/src/main/java/com/ruoyi/web/domain/po/OnenetReceive.java

@ -0,0 +1,84 @@
package com.ruoyi.web.domain.po;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
/**
* onenet推送记录对象 onenet_receive
*
* @author lijunjie
* @date 2023-02-02
*/
public class OnenetReceive extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** */
private Long id;
/** imei */
@Excel(name = "imei")
private String imei;
/** 推送数据 */
@Excel(name = "推送数据")
private String value;
/** 消息摘要
*/
@Excel(name = "消息摘要")
private String msgSignature;
public void setId(Long id)
{
this.id = id;
}
public Long getId()
{
return id;
}
public void setImei(String imei)
{
this.imei = imei;
}
public String getImei()
{
return imei;
}
public void setValue(String value)
{
this.value = value;
}
public String getValue()
{
return value;
}
public void setMsgSignature(String msgSignature)
{
this.msgSignature = msgSignature;
}
public String getMsgSignature()
{
return msgSignature;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("imei", getImei())
.append("value", getValue())
.append("msgSignature", getMsgSignature())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.toString();
}
}

61
ruoyi-admin/src/main/java/com/ruoyi/web/persist/mapper/OnenetReceiveMapper.java

@ -0,0 +1,61 @@
package com.ruoyi.web.persist.mapper;
import java.util.List;
import com.ruoyi.web.domain.po.OnenetReceive;
/**
* onenet推送记录Mapper接口
*
* @author lijunjie
* @date 2023-02-02
*/
public interface OnenetReceiveMapper
{
/**
* 查询onenet推送记录
*
* @param id onenet推送记录主键
* @return onenet推送记录
*/
public OnenetReceive selectOnenetReceiveById(Long id);
/**
* 查询onenet推送记录列表
*
* @param onenetReceive onenet推送记录
* @return onenet推送记录集合
*/
public List<OnenetReceive> selectOnenetReceiveList(OnenetReceive onenetReceive);
/**
* 新增onenet推送记录
*
* @param onenetReceive onenet推送记录
* @return 结果
*/
public int insertOnenetReceive(OnenetReceive onenetReceive);
/**
* 修改onenet推送记录
*
* @param onenetReceive onenet推送记录
* @return 结果
*/
public int updateOnenetReceive(OnenetReceive onenetReceive);
/**
* 删除onenet推送记录
*
* @param id onenet推送记录主键
* @return 结果
*/
public int deleteOnenetReceiveById(Long id);
/**
* 批量删除onenet推送记录
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
public int deleteOnenetReceiveByIds(Long[] ids);
}

69
ruoyi-admin/src/main/java/com/ruoyi/web/service/IOnenetReceiveService.java

@ -0,0 +1,69 @@
package com.ruoyi.web.service;
import java.util.List;
import com.ruoyi.web.domain.po.OnenetReceive;
/**
* onenet推送记录Service接口
*
* @author lijunjie
* @date 2023-02-02
*/
public interface IOnenetReceiveService
{
/**
* 查询onenet推送记录
*
* @param id onenet推送记录主键
* @return onenet推送记录
*/
public OnenetReceive selectOnenetReceiveById(Long id);
/**
* 查询onenet推送记录列表
*
* @param onenetReceive onenet推送记录
* @return onenet推送记录集合
*/
public List<OnenetReceive> selectOnenetReceiveList(OnenetReceive onenetReceive);
/**
* 新增onenet推送记录
*
* @param onenetReceive onenet推送记录
* @return 结果
*/
public boolean addOnenetReceive(String onenetReceive);
/**
* 新增onenet推送记录
*
* @param onenetReceive onenet推送记录
* @return 结果
*/
public int insertOnenetReceive(OnenetReceive onenetReceive);
/**
* 修改onenet推送记录
*
* @param onenetReceive onenet推送记录
* @return 结果
*/
public int updateOnenetReceive(OnenetReceive onenetReceive);
/**
* 批量删除onenet推送记录
*
* @param ids 需要删除的onenet推送记录主键集合
* @return 结果
*/
public int deleteOnenetReceiveByIds(Long[] ids);
/**
* 删除onenet推送记录信息
*
* @param id onenet推送记录主键
* @return 结果
*/
public int deleteOnenetReceiveById(Long id);
}

2
ruoyi-admin/src/main/java/com/ruoyi/web/service/impl/OnenetEquipServiceImpl.java

@ -122,7 +122,7 @@ public class OnenetEquipServiceImpl implements IOnenetEquipService {
uriParams.put("obj_id", InsertDto.getObj_id()); uriParams.put("obj_id", InsertDto.getObj_id());
uriParams.put("obj_inst_id", InsertDto.getObj_inst_id()); uriParams.put("obj_inst_id", InsertDto.getObj_inst_id());
uriParams.put("mode", InsertDto.getMode()); uriParams.put("mode", InsertDto.getMode());
uriParams.put("expired_time", "2023-01-10T09:35:03"); uriParams.put("expired_time", InsertDto.getExpired_time());
uriParams.put("trigger_msg", InsertDto.getTrigger_msg()); uriParams.put("trigger_msg", InsertDto.getTrigger_msg());
String uriParam = HttpUtil.toParams(uriParams); String uriParam = HttpUtil.toParams(uriParams);

136
ruoyi-admin/src/main/java/com/ruoyi/web/service/impl/OnenetReceiveServiceImpl.java

@ -0,0 +1,136 @@
package com.ruoyi.web.service.impl;
import java.util.List;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.web.domain.po.OnenetReceive;
import com.ruoyi.web.persist.mapper.OnenetReceiveMapper;
import com.ruoyi.web.util.OnenetUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.web.service.IOnenetReceiveService;
import javax.annotation.Resource;
/**
* onenet推送记录Service业务层处理
*
* @author lijunjie
* @date 2023-02-02
*/
@Service
public class OnenetReceiveServiceImpl implements IOnenetReceiveService
{
@Resource
private OnenetReceiveMapper onenetReceiveMapper;
/**
* 查询onenet推送记录
*
* @param id onenet推送记录主键
* @return onenet推送记录
*/
@Override
public OnenetReceive selectOnenetReceiveById(Long id)
{
return onenetReceiveMapper.selectOnenetReceiveById(id);
}
/**
* 查询onenet推送记录列表
*
* @param onenetReceive onenet推送记录
* @return onenet推送记录
*/
@Override
public List<OnenetReceive> selectOnenetReceiveList(OnenetReceive onenetReceive)
{
return onenetReceiveMapper.selectOnenetReceiveList(onenetReceive);
}
@Override
public boolean addOnenetReceive(String request) {
OnenetUtil.BodyObj obj = OnenetUtil.resolveBody(request, false);
if (obj == null){
return false;
}
JSONObject jsonObject = JSONObject.parseObject(obj.getMsg().toString());
String imei = jsonObject.getString("imei");
if (StrUtil.hasEmpty(imei)){
return false;
}
OnenetReceive onenetReceive = new OnenetReceive();
onenetReceive.setImei(imei);
onenetReceive.setMsgSignature(obj.getMsgSignature());
List<OnenetReceive> onenetReceives = onenetReceiveMapper.selectOnenetReceiveList(onenetReceive);
if (onenetReceives.size() > 0){
return false;
}
onenetReceive.setValue(obj.getMsg().toString());
onenetReceive.setCreateTime(DateUtils.getNowDate());
int insertOnenetReceive = onenetReceiveMapper.insertOnenetReceive(onenetReceive);
if (insertOnenetReceive > 0){
return true;
}
return false;
}
/**
* 新增onenet推送记录
*
* @param onenetReceive onenet推送记录
* @return 结果
*/
@Override
public int insertOnenetReceive(OnenetReceive onenetReceive)
{
onenetReceive.setCreateTime(DateUtils.getNowDate());
return onenetReceiveMapper.insertOnenetReceive(onenetReceive);
}
/**
* 修改onenet推送记录
*
* @param onenetReceive onenet推送记录
* @return 结果
*/
@Override
public int updateOnenetReceive(OnenetReceive onenetReceive)
{
onenetReceive.setUpdateTime(DateUtils.getNowDate());
return onenetReceiveMapper.updateOnenetReceive(onenetReceive);
}
/**
* 批量删除onenet推送记录
*
* @param ids 需要删除的onenet推送记录主键
* @return 结果
*/
@Override
public int deleteOnenetReceiveByIds(Long[] ids)
{
return onenetReceiveMapper.deleteOnenetReceiveByIds(ids);
}
/**
* 删除onenet推送记录信息
*
* @param id onenet推送记录主键
* @return 结果
*/
@Override
public int deleteOnenetReceiveById(Long id)
{
return onenetReceiveMapper.deleteOnenetReceiveById(id);
}
}

176
ruoyi-admin/src/main/java/com/ruoyi/web/util/OnenetUtil.java

@ -0,0 +1,176 @@
package com.ruoyi.web.util;
import com.alibaba.fastjson2.JSONObject;
import org.apache.tomcat.util.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.*;
/**
* 功能描述: OneNet数据推送接收程序工具类
*
* Created by Roy on 2017/5/17.
*
*/
public class OnenetUtil {
private static Logger logger = LoggerFactory.getLogger(OnenetUtil.class);
private static MessageDigest mdInst;
static {
try {
mdInst = MessageDigest.getInstance("MD5");
Security.addProvider(new BouncyCastleProvider());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
/**
* 功能描述:在OneNet平台配置数据接收地址时平台会发送URL&token验证请求<p>
* 使用此功能函数验证token
* @param msg 请求参数 <msg>的值
* @param nonce 请求参数 <nonce>的值
* @param signature 请求参数 <signature>的值
* @param token OneNet平台配置页面token的值
* @return token检验成功返回truetoken校验失败返回false
*/
public static boolean checkToken(String msg,String nonce,String signature, String token) throws UnsupportedEncodingException {
byte[] paramB = new byte[token.length() + 8 + msg.length()];
System.arraycopy(token.getBytes(), 0, paramB, 0, token.length());
System.arraycopy(nonce.getBytes(), 0, paramB, token.length(), 8);
System.arraycopy(msg.getBytes(), 0, paramB, token.length() + 8, msg.length());
String sig = com.sun.org.apache.xerces.internal.impl.dv.util.Base64.encode(mdInst.digest(paramB));
logger.info("url&token validation: result {}, detail receive:{} calculate:{}", sig.equals(signature.replace(' ','+')),signature,sig);
return sig.equals(signature.replace(' ','+'));
}
/**
* 功能描述: 检查接收数据的信息摘要是否正确<p>
* 方法非线程安全
* @param obj 消息体对象
* @param token OneNet平台配置页面token的值
* @return
*/
public static boolean checkSignature(BodyObj obj, String token) {
//计算接受到的消息的摘要
//token长度 + 8B随机字符串长度 + 消息长度
byte[] signature = new byte[token.length() + 8 + obj.getMsg().toString().length()];
System.arraycopy(token.getBytes(), 0, signature, 0, token.length());
System.arraycopy(obj.getNonce().getBytes(), 0, signature, token.length(), 8);
System.arraycopy(obj.getMsg().toString().getBytes(), 0, signature, token.length() + 8, obj.getMsg().toString().length());
String calSig = Base64.encodeBase64String(mdInst.digest(signature));
logger.info("check signature: result:{} receive sig:{},calculate sig: {}",calSig.equals(obj.getMsgSignature()),obj.getMsgSignature(),calSig);
return calSig.equals(obj.getMsgSignature());
}
/**
* 功能描述 解密消息
* @param obj 消息体对象
* @param encodeKey OneNet平台第三方平台配置页面为用户生成的AES的BASE64编码格式秘钥
* @return
* @throws NoSuchPaddingException
* @throws NoSuchAlgorithmException
* @throws InvalidAlgorithmParameterException
* @throws InvalidKeyException
* @throws BadPaddingException
* @throws IllegalBlockSizeException
*/
public static String decryptMsg(BodyObj obj, String encodeKey) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
byte[] encMsg = Base64.decodeBase64(obj.getMsg().toString());
byte[] aeskey = Base64.decodeBase64(encodeKey + "=");
SecretKey secretKey = new SecretKeySpec(aeskey, 0, 32, "AES");
Cipher cipher = null;
cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(aeskey, 0, 16));
byte[] allmsg = cipher.doFinal(encMsg);
byte[] msgLenBytes = new byte[4];
System.arraycopy(allmsg, 16, msgLenBytes, 0, 4);
int msgLen = getMsgLen(msgLenBytes);
byte[] msg = new byte[msgLen];
System.arraycopy(allmsg, 20, msg, 0, msgLen);
return new String(msg);
}
/**
* 功能描述 解析数据推送请求生成code>BodyObj</code>消息对象
* @param body 数据推送请求body部分
* @param encrypted 表征是否为加密消息
* @return 生成的<code>BodyObj</code>消息对象
*/
public static BodyObj resolveBody(String body, boolean encrypted) {
JSONObject jsonMsg = JSONObject.parseObject(body);
BodyObj obj = new BodyObj();
obj.setNonce(jsonMsg.getString("nonce"));
obj.setMsgSignature(jsonMsg.getString("msg_signature"));
if (encrypted) {
String enc_msg = jsonMsg.getString("enc_msg");
if (enc_msg == null) {
return null;
}
obj.setMsg(jsonMsg.getString("enc_msg"));
} else {
Object msg = jsonMsg.get("msg");
if (msg == null) {
return null;
}
obj.setMsg(jsonMsg.get("msg"));
}
return obj;
}
private static int getMsgLen(byte[] arrays) {
int len = 0;
len += (arrays[0] & 0xFF) << 24;
len += (arrays[1] & 0xFF) << 16;
len += (arrays[2] & 0xFF) << 8;
len += (arrays[3] & 0xFF);
return len;
}
public static class BodyObj {
private Object msg;
private String nonce;
private String msgSignature;
public Object getMsg() {
return msg;
}
public void setMsg(Object msg) {
this.msg = msg;
}
public String getNonce() {
return nonce;
}
public void setNonce(String nonce) {
this.nonce = nonce;
}
public String getMsgSignature() {
return msgSignature;
}
public void setMsgSignature(String msgSignature) {
this.msgSignature = msgSignature;
}
public String toString(){
return "{ \"msg\":"+this.msg+",\"nonce\":"+this.nonce+",\"signature\":"+this.msgSignature+"}";
}
}
}

83
ruoyi-admin/src/main/resources/mapper/device/OnenetReceiveMapper.xml

@ -0,0 +1,83 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.web.persist.mapper.OnenetReceiveMapper">
<resultMap type="OnenetReceive" id="OnenetReceiveResult">
<result property="id" column="id" />
<result property="imei" column="imei" />
<result property="value" column="value" />
<result property="msgSignature" column="msg_signature" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
</resultMap>
<sql id="selectOnenetReceiveVo">
select id, imei, value, msg_signature, create_by, create_time, update_by, update_time from onenet_receive
</sql>
<select id="selectOnenetReceiveList" parameterType="OnenetReceive" resultMap="OnenetReceiveResult">
<include refid="selectOnenetReceiveVo"/>
<where>
<if test="imei != null and imei != ''"> and imei = #{imei}</if>
<if test="value != null and value != ''"> and value = #{value}</if>
<if test="msgSignature != null and msgSignature != ''"> and msg_signature = #{msgSignature}</if>
</where>
order by id desc
</select>
<select id="selectOnenetReceiveById" parameterType="Long" resultMap="OnenetReceiveResult">
<include refid="selectOnenetReceiveVo"/>
where id = #{id}
</select>
<insert id="insertOnenetReceive" parameterType="OnenetReceive" useGeneratedKeys="true" keyProperty="id">
insert into onenet_receive
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="imei != null">imei,</if>
<if test="value != null">value,</if>
<if test="msgSignature != null">msg_signature,</if>
<if test="createBy != null">create_by,</if>
<if test="createTime != null">create_time,</if>
<if test="updateBy != null">update_by,</if>
<if test="updateTime != null">update_time,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="imei != null">#{imei},</if>
<if test="value != null">#{value},</if>
<if test="msgSignature != null">#{msgSignature},</if>
<if test="createBy != null">#{createBy},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateBy != null">#{updateBy},</if>
<if test="updateTime != null">#{updateTime},</if>
</trim>
</insert>
<update id="updateOnenetReceive" parameterType="OnenetReceive">
update onenet_receive
<trim prefix="SET" suffixOverrides=",">
<if test="imei != null">imei = #{imei},</if>
<if test="value != null">value = #{value},</if>
<if test="msgSignature != null">msg_signature = #{msgSignature},</if>
<if test="createBy != null">create_by = #{createBy},</if>
<if test="createTime != null">create_time = #{createTime},</if>
<if test="updateBy != null">update_by = #{updateBy},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
</trim>
where id = #{id}
</update>
<delete id="deleteOnenetReceiveById" parameterType="Long">
delete from onenet_receive where id = #{id}
</delete>
<delete id="deleteOnenetReceiveByIds" parameterType="String">
delete from onenet_receive where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>

22
ruoyi-ui/.env.development

@ -1,11 +1,11 @@
# 页面标题 # 页面标题
VUE_APP_TITLE = 若依管理系统 VUE_APP_TITLE = 传控管理系统
# 开发环境配置 # 开发环境配置
ENV = 'development' ENV = 'development'
# 若依管理系统/开发环境 # 传控管理系统/开发环境
VUE_APP_BASE_API = '/dev-api' VUE_APP_BASE_API = '/dev-api'
# 路由懒加载 # 路由懒加载
VUE_CLI_BABEL_TRANSPILE_MODULES = true VUE_CLI_BABEL_TRANSPILE_MODULES = true

16
ruoyi-ui/.env.production

@ -1,8 +1,8 @@
# 页面标题 # 页面标题
VUE_APP_TITLE = 若依管理系统 VUE_APP_TITLE = 传控管理系统
# 生产环境配置 # 生产环境配置
ENV = 'production' ENV = 'production'
# 若依管理系统/生产环境 # 传控管理系统/生产环境
VUE_APP_BASE_API = '/prod-api' VUE_APP_BASE_API = '/prod-api'

20
ruoyi-ui/.env.staging

@ -1,10 +1,10 @@
# 页面标题 # 页面标题
VUE_APP_TITLE = 若依管理系统 VUE_APP_TITLE = 传控管理系统
NODE_ENV = production NODE_ENV = production
# 测试环境配置 # 测试环境配置
ENV = 'staging' ENV = 'staging'
# 若依管理系统/测试环境 # 传控管理系统/测试环境
VUE_APP_BASE_API = '/stage-api' VUE_APP_BASE_API = '/stage-api'

180
ruoyi-ui/package.json

@ -1,90 +1,90 @@
{ {
"name": "ruoyi", "name": "ruoyi",
"version": "3.8.5", "version": "3.8.5",
"description": "若依管理系统", "description": "传控管理系统",
"author": "若依", "author": "传控",
"license": "MIT", "license": "MIT",
"scripts": { "scripts": {
"dev": "vue-cli-service serve", "dev": "vue-cli-service serve",
"build:prod": "vue-cli-service build", "build:prod": "vue-cli-service build",
"build:stage": "vue-cli-service build --mode staging", "build:stage": "vue-cli-service build --mode staging",
"preview": "node build/index.js --preview", "preview": "node build/index.js --preview",
"lint": "eslint --ext .js,.vue src" "lint": "eslint --ext .js,.vue src"
}, },
"husky": { "husky": {
"hooks": { "hooks": {
"pre-commit": "lint-staged" "pre-commit": "lint-staged"
} }
}, },
"lint-staged": { "lint-staged": {
"src/**/*.{js,vue}": [ "src/**/*.{js,vue}": [
"eslint --fix", "eslint --fix",
"git add" "git add"
] ]
}, },
"keywords": [ "keywords": [
"vue", "vue",
"admin", "admin",
"dashboard", "dashboard",
"element-ui", "element-ui",
"boilerplate", "boilerplate",
"admin-template", "admin-template",
"management-system" "management-system"
], ],
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://gitee.com/y_project/RuoYi-Vue.git" "url": "https://gitee.com/y_project/RuoYi-Vue.git"
}, },
"dependencies": { "dependencies": {
"@riophae/vue-treeselect": "0.4.0", "@riophae/vue-treeselect": "0.4.0",
"axios": "0.24.0", "axios": "0.24.0",
"clipboard": "2.0.8", "clipboard": "2.0.8",
"core-js": "3.25.3", "core-js": "3.25.3",
"echarts": "5.4.0", "echarts": "5.4.0",
"element-ui": "2.15.10", "element-ui": "2.15.10",
"file-saver": "2.0.5", "file-saver": "2.0.5",
"fuse.js": "6.4.3", "fuse.js": "6.4.3",
"highlight.js": "9.18.5", "highlight.js": "9.18.5",
"js-beautify": "1.13.0", "js-beautify": "1.13.0",
"js-cookie": "3.0.1", "js-cookie": "3.0.1",
"jsencrypt": "3.0.0-rc.1", "jsencrypt": "3.0.0-rc.1",
"nprogress": "0.2.0", "nprogress": "0.2.0",
"quill": "1.3.7", "quill": "1.3.7",
"screenfull": "5.0.2", "screenfull": "5.0.2",
"sortablejs": "1.10.2", "sortablejs": "1.10.2",
"vue": "2.6.12", "vue": "2.6.12",
"vue-count-to": "1.0.13", "vue-count-to": "1.0.13",
"vue-cropper": "0.5.5", "vue-cropper": "0.5.5",
"vue-meta": "2.4.0", "vue-meta": "2.4.0",
"vue-router": "3.4.9", "vue-router": "3.4.9",
"vuedraggable": "2.24.3", "vuedraggable": "2.24.3",
"vuex": "3.6.0" "vuex": "3.6.0"
}, },
"devDependencies": { "devDependencies": {
"@vue/cli-plugin-babel": "4.4.6", "@vue/cli-plugin-babel": "4.4.6",
"@vue/cli-plugin-eslint": "4.4.6", "@vue/cli-plugin-eslint": "4.4.6",
"@vue/cli-service": "4.4.6", "@vue/cli-service": "4.4.6",
"babel-eslint": "10.1.0", "babel-eslint": "10.1.0",
"babel-plugin-dynamic-import-node": "2.3.3", "babel-plugin-dynamic-import-node": "2.3.3",
"chalk": "4.1.0", "chalk": "4.1.0",
"compression-webpack-plugin": "5.0.2", "compression-webpack-plugin": "5.0.2",
"connect": "3.6.6", "connect": "3.6.6",
"eslint": "7.15.0", "eslint": "7.15.0",
"eslint-plugin-vue": "7.2.0", "eslint-plugin-vue": "7.2.0",
"lint-staged": "10.5.3", "lint-staged": "10.5.3",
"runjs": "4.4.2", "runjs": "4.4.2",
"sass": "1.32.13", "sass": "1.32.13",
"sass-loader": "10.1.1", "sass-loader": "10.1.1",
"script-ext-html-webpack-plugin": "2.1.5", "script-ext-html-webpack-plugin": "2.1.5",
"svg-sprite-loader": "5.1.1", "svg-sprite-loader": "5.1.1",
"vue-template-compiler": "2.6.12" "vue-template-compiler": "2.6.12"
}, },
"engines": { "engines": {
"node": ">=8.9", "node": ">=8.9",
"npm": ">= 3.0.0" "npm": ">= 3.0.0"
}, },
"browserslist": [ "browserslist": [
"> 1%", "> 1%",
"last 2 versions" "last 2 versions"
] ]
} }

9
ruoyi-ui/src/api/device/equips.js

@ -26,6 +26,15 @@ export function listEquipDatas(query) {
}) })
} }
// 查询推送记录
export function listReceiveDatas(query) {
return request({
url: '/device/receive/list',
method: 'get',
params: query
})
}
// 查询设备详细 // 查询设备详细
export function getEquips(id) { export function getEquips(id) {
return request({ return request({

44
ruoyi-ui/src/api/device/receive.js

@ -0,0 +1,44 @@
import request from '@/utils/request'
// 查询onenet推送记录列表
export function listReceive(query) {
return request({
url: '/device/receive/list',
method: 'get',
params: query
})
}
// 查询onenet推送记录详细
export function getReceive(id) {
return request({
url: '/device/receive/' + id,
method: 'get'
})
}
// 新增onenet推送记录
export function addReceive(data) {
return request({
url: '/device/receive',
method: 'post',
data: data
})
}
// 修改onenet推送记录
export function updateReceive(data) {
return request({
url: '/device/receive',
method: 'put',
data: data
})
}
// 删除onenet推送记录
export function delReceive(id) {
return request({
url: '/device/receive/' + id,
method: 'delete'
})
}

186
ruoyi-ui/src/layout/components/Sidebar/Logo.vue

@ -1,93 +1,93 @@
<template> <template>
<div class="sidebar-logo-container" :class="{'collapse':collapse}" :style="{ backgroundColor: sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground }"> <div class="sidebar-logo-container" :class="{'collapse':collapse}" :style="{ backgroundColor: sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground }">
<transition name="sidebarLogoFade"> <transition name="sidebarLogoFade">
<router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/"> <router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/">
<img v-if="logo" :src="logo" class="sidebar-logo" /> <img v-if="logo" :src="logo" class="sidebar-logo" />
<h1 v-else class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.logoTitleColor : variables.logoLightTitleColor }">{{ title }} </h1> <h1 v-else class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.logoTitleColor : variables.logoLightTitleColor }">{{ title }} </h1>
</router-link> </router-link>
<router-link v-else key="expand" class="sidebar-logo-link" to="/"> <router-link v-else key="expand" class="sidebar-logo-link" to="/">
<img v-if="logo" :src="logo" class="sidebar-logo" /> <img v-if="logo" :src="logo" class="sidebar-logo" />
<h1 class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.logoTitleColor : variables.logoLightTitleColor }">{{ title }} </h1> <h1 class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.logoTitleColor : variables.logoLightTitleColor }">{{ title }} </h1>
</router-link> </router-link>
</transition> </transition>
</div> </div>
</template> </template>
<script> <script>
import logoImg from '@/assets/logo/logo.png' import logoImg from '@/assets/logo/logo.png'
import variables from '@/assets/styles/variables.scss' import variables from '@/assets/styles/variables.scss'
export default { export default {
name: 'SidebarLogo', name: 'SidebarLogo',
props: { props: {
collapse: { collapse: {
type: Boolean, type: Boolean,
required: true required: true
} }
}, },
computed: { computed: {
variables() { variables() {
return variables; return variables;
}, },
sideTheme() { sideTheme() {
return this.$store.state.settings.sideTheme return this.$store.state.settings.sideTheme
} }
}, },
data() { data() {
return { return {
title: '若依管理系统', title: '传控管理系统',
logo: logoImg logo: logoImg
} }
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.sidebarLogoFade-enter-active { .sidebarLogoFade-enter-active {
transition: opacity 1.5s; transition: opacity 1.5s;
} }
.sidebarLogoFade-enter, .sidebarLogoFade-enter,
.sidebarLogoFade-leave-to { .sidebarLogoFade-leave-to {
opacity: 0; opacity: 0;
} }
.sidebar-logo-container { .sidebar-logo-container {
position: relative; position: relative;
width: 100%; width: 100%;
height: 50px; height: 50px;
line-height: 50px; line-height: 50px;
background: #2b2f3a; background: #2b2f3a;
text-align: center; text-align: center;
overflow: hidden; overflow: hidden;
& .sidebar-logo-link { & .sidebar-logo-link {
height: 100%; height: 100%;
width: 100%; width: 100%;
& .sidebar-logo { & .sidebar-logo {
width: 32px; width: 32px;
height: 32px; height: 32px;
vertical-align: middle; vertical-align: middle;
margin-right: 12px; margin-right: 12px;
} }
& .sidebar-title { & .sidebar-title {
display: inline-block; display: inline-block;
margin: 0; margin: 0;
color: #fff; color: #fff;
font-weight: 600; font-weight: 600;
line-height: 50px; line-height: 50px;
font-size: 14px; font-size: 14px;
font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif; font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif;
vertical-align: middle; vertical-align: middle;
} }
} }
&.collapse { &.collapse {
.sidebar-logo { .sidebar-logo {
margin-right: 0px; margin-right: 0px;
} }
} }
} }
</style> </style>

108
ruoyi-ui/src/views/device/equips/index.vue

@ -32,7 +32,7 @@
<el-table-column label="位置" align="center" prop="location" /> <el-table-column label="位置" align="center" prop="location" />
<el-table-column label="NBIOT设备" align="center" prop="authInfo" /> <el-table-column label="NBIOT设备" align="center" prop="authInfo" />
<el-table-column label="其他信息" align="center" prop="otherInfo" /> <el-table-column label="其他信息" align="center" prop="otherInfo" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width"> <el-table-column label="写设备资源" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button <el-button
size="mini" size="mini"
@ -44,7 +44,7 @@
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width"> <el-table-column label="设备数据点" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button <el-button
size="mini" size="mini"
@ -55,6 +55,18 @@
>设备数据点</el-button> >设备数据点</el-button>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="onenet推送记录" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="getReceiveDatas(scope.row)"
v-hasPermi="['device:equips:edit']"
>onenet推送记录</el-button>
</template>
</el-table-column>
</el-table> </el-table>
<pagination <pagination
@ -77,8 +89,11 @@
<el-form-item label="Obj Inst Id" prop="obj_inst_id" required> <el-form-item label="Obj Inst Id" prop="obj_inst_id" required>
<el-input v-model="form.obj_inst_id" placeholder="" /> <el-input v-model="form.obj_inst_id" placeholder="" />
</el-form-item> </el-form-item>
<el-form-item label="Write的写模式,只能是1或者2" prop="mode" required> <el-form-item label="Write的写模式" prop="mode" required>
<el-input v-model="form.mode" placeholder="" /> <el-radio v-model="form.mode" label="1" border>1</el-radio>
<el-radio v-model="form.mode" label="2" border>2</el-radio>
<!-- <el-input v-model="form.mode" placeholder="" />-->
</el-form-item> </el-form-item>
<el-form-item label="命令过期时间戳,必填且大于Valid Time " prop="expired_time" required> <el-form-item label="命令过期时间戳,必填且大于Valid Time " prop="expired_time" required>
<el-date-picker <el-date-picker
@ -88,7 +103,16 @@
</el-date-picker> </el-date-picker>
</el-form-item> </el-form-item>
<el-form-item label="命令触发的上行消息类型[1,7]" prop="trigger_msg" required> <el-form-item label="命令触发的上行消息类型[1,7]" prop="trigger_msg" required>
<el-input v-model="form.trigger_msg" placeholder="" /> <el-select v-model="form.trigger_msg" placeholder="请选择">
<el-option key="1" label=1 value=1></el-option>
<el-option key="2" label=2 value=2></el-option>
<el-option key="3" label=3 value=3></el-option>
<el-option key="4" label=4 value=4></el-option>
<el-option key="5" label=5 value=5></el-option>
<el-option key="6" label=6 value=6></el-option>
<el-option key="7" label=7 value=7></el-option>
</el-select>
<!-- <el-input v-model="form.trigger_msg" placeholder="" />-->
</el-form-item> </el-form-item>
<el-form-item label="Api-Key" prop="api_key" required> <el-form-item label="Api-Key" prop="api_key" required>
<el-input v-model="form.api_key" placeholder="" /> <el-input v-model="form.api_key" placeholder="" />
@ -201,19 +225,36 @@
</el-table> </el-table>
</el-dialog> </el-dialog>
<!-- onenet推送记录-->
<el-dialog title="onenet推送记录" :visible.sync="receiveDataOpen" width="80%">
<el-table v-loading="loading" :data="receiveDataList">
<el-table-column label="主键" align="center" prop="id" />
<el-table-column label="创建时间" align="center" prop="createTime" />
<el-table-column label="推送数据" align="center" prop="value" />
</el-table>
<pagination
v-show="receiveDataTotal>0"
:total="receiveDataTotal"
:page.sync="receiveDataParam.pageNum"
:limit.sync="receiveDataParam.pageSize"
@pagination="getReceiveDatas()"
/>
</el-dialog>
</div> </div>
</template> </template>
<script> <script>
import { import {
listEquips, listEquips,
getEquips, getEquips,
delEquips, delEquips,
addEquips, addEquips,
updateEquips, updateEquips,
getApiKey, getApiKey,
writeCommand, listEquipDatas writeCommand, listEquipDatas, listReceiveDatas
} from "@/api/device/equips"; } from "@/api/device/equips";
var time = new Date() var time = new Date()
@ -235,13 +276,13 @@ export default {
showSearch: true, showSearch: true,
// //
total: 0, total: 0,
apiKey:null,
//
title: "",
// //
equipsList: [], equipsList: [],
equipDataList: [], equipDataList: [],
equipDataTotal: 0, equipDataTotal: 0,
apiKey:null,
//
title: "",
// //
open: false, open: false,
equipDataOpen:false, equipDataOpen:false,
@ -252,6 +293,16 @@ export default {
obj_id:0, obj_id:0,
equipDataTime:"", equipDataTime:"",
}, },
//onenet
receiveDataOpen:false,
receiveDataParam: {
pageNum: 1,
pageSize: 10,
imei:0,
receiveDataTime:"",
},
receiveDataList: [],
receiveDataTotal: 0,
// //
queryParams: { queryParams: {
pageNum: 1, pageNum: 1,
@ -325,7 +376,6 @@ export default {
}, },
/** 查询设备数据点 */ /** 查询设备数据点 */
getEquipDatas(row) { getEquipDatas(row) {
console.log(row)
this.equipDataOpen = true; this.equipDataOpen = true;
this.title = "查询设备数据点"; this.title = "查询设备数据点";
this.loading = true; this.loading = true;
@ -339,6 +389,23 @@ export default {
this.loading = false; this.loading = false;
}); });
}, },
/** onenet推送记录 */
getReceiveDatas(row) {
console.log(row)
this.receiveDataOpen = true;
this.title = "onenet推送记录";
this.loading = true;
if (row != null){
let authInfo = JSON.parse(row.authInfo)
this.receiveDataParam.imei = Object.keys(authInfo)[0]
}
listReceiveDatas(this.receiveDataParam).then(response => {
this.receiveDataList = response.rows;
this.receiveDataTotal = response.total;
this.loading = false;
});
},
resetEquipData() { resetEquipData() {
this.equipDataParam.equipDataTime = ""; this.equipDataParam.equipDataTime = "";
this.getEquipDatas(); this.getEquipDatas();
@ -355,7 +422,7 @@ export default {
imei:null, imei:null,
obj_id:null, obj_id:null,
obj_inst_id:0, obj_inst_id:0,
mode:1, mode:"1",
expired_time: time, expired_time: time,
trigger_msg:4, trigger_msg:4,
api_key:this.apiKey, api_key:this.apiKey,
@ -429,9 +496,6 @@ export default {
return; return;
} }
} }
this.verifyForm.param4 = this.verifyForm.param4 == 0 ? '01' : '02';
this.verifyForm.param5 = this.verifyForm.param5 == 0 ? '09' : '0B';
this.verifyForm.param8 = this.verifyForm.param8 == 0 ? '00' : '11';
let str = this.verifyForm.param1 + this.verifyForm.param2 + this.verifyForm.param3 + this.verifyForm.param4 + this.verifyForm.param5 + this.verifyForm.param6 + this.verifyForm.param7 + this.verifyForm.param8 + this.verifyForm.param9 + this.verifyForm.param10 let str = this.verifyForm.param1 + this.verifyForm.param2 + this.verifyForm.param3 + this.verifyForm.param4 + this.verifyForm.param5 + this.verifyForm.param6 + this.verifyForm.param7 + this.verifyForm.param8 + this.verifyForm.param9 + this.verifyForm.param10

291
ruoyi-ui/src/views/device/receive/index.vue

@ -0,0 +1,291 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="imei" prop="imei">
<el-input
v-model="queryParams.imei"
placeholder="请输入imei"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="创建时间" prop="createTime">
<el-date-picker clearable
v-model="queryParams.createTime"
type="date"
value-format="yyyy-MM-dd"
placeholder="请选择创建时间">
</el-date-picker>
</el-form-item>
<el-form-item label="更新时间" prop="updateTime">
<el-date-picker clearable
v-model="queryParams.updateTime"
type="date"
value-format="yyyy-MM-dd"
placeholder="请选择更新时间">
</el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
v-hasPermi="['device:receive:add']"
>新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="el-icon-edit"
size="mini"
:disabled="single"
@click="handleUpdate"
v-hasPermi="['device:receive:edit']"
>修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="el-icon-delete"
size="mini"
:disabled="multiple"
@click="handleDelete"
v-hasPermi="['device:receive:remove']"
>删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="el-icon-download"
size="mini"
@click="handleExport"
v-hasPermi="['device:receive:export']"
>导出</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="receiveList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="" align="center" prop="id" />
<el-table-column label="imei" align="center" prop="imei" />
<el-table-column label="推送数据" align="center" prop="value" />
<el-table-column label="消息摘要
" align="center" prop="msgSignature" />
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="更新时间" align="center" prop="updateTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.updateTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
v-hasPermi="['device:receive:edit']"
>修改</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
v-hasPermi="['device:receive:remove']"
>删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<!-- 添加或修改onenet推送记录对话框 -->
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="imei" prop="imei">
<el-input v-model="form.imei" placeholder="请输入imei" />
</el-form-item>
<el-form-item label="推送数据" prop="value">
<el-input v-model="form.value" type="textarea" placeholder="请输入内容" />
</el-form-item>
<el-form-item label="消息摘要
" prop="msgSignature">
<el-input v-model="form.msgSignature" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { listReceive, getReceive, delReceive, addReceive, updateReceive } from "@/api/device/receive";
export default {
name: "Receive",
data() {
return {
//
loading: true,
//
ids: [],
//
single: true,
//
multiple: true,
//
showSearch: true,
//
total: 0,
// onenet
receiveList: [],
//
title: "",
//
open: false,
//
queryParams: {
pageNum: 1,
pageSize: 10,
imei: null,
value: null,
msgSignature: null,
createTime: null,
updateTime: null
},
//
form: {},
//
rules: {
}
};
},
created() {
this.getList();
},
methods: {
/** 查询onenet推送记录列表 */
getList() {
this.loading = true;
listReceive(this.queryParams).then(response => {
this.receiveList = response.rows;
this.total = response.total;
this.loading = false;
});
},
//
cancel() {
this.open = false;
this.reset();
},
//
reset() {
this.form = {
id: null,
imei: null,
value: null,
msgSignature: null,
createBy: null,
createTime: null,
updateBy: null,
updateTime: null
};
this.resetForm("form");
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
//
handleSelectionChange(selection) {
this.ids = selection.map(item => item.id)
this.single = selection.length!==1
this.multiple = !selection.length
},
/** 新增按钮操作 */
handleAdd() {
this.reset();
this.open = true;
this.title = "添加onenet推送记录";
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset();
const id = row.id || this.ids
getReceive(id).then(response => {
this.form = response.data;
this.open = true;
this.title = "修改onenet推送记录";
});
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate(valid => {
if (valid) {
if (this.form.id != null) {
updateReceive(this.form).then(response => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
});
} else {
addReceive(this.form).then(response => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
});
}
}
});
},
/** 删除按钮操作 */
handleDelete(row) {
const ids = row.id || this.ids;
this.$modal.confirm('是否确认删除onenet推送记录编号为"' + ids + '"的数据项?').then(function() {
return delReceive(ids);
}).then(() => {
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
},
/** 导出按钮操作 */
handleExport() {
this.download('device/receive/export', {
...this.queryParams
}, `receive_${new Date().getTime()}.xlsx`)
}
}
};
</script>

1972
ruoyi-ui/src/views/index.vue

File diff suppressed because it is too large

438
ruoyi-ui/src/views/login.vue

@ -1,219 +1,219 @@
<template> <template>
<div class="login"> <div class="login">
<el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form"> <el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form">
<h3 class="title">若依后台管理系统</h3> <h3 class="title">传控后台管理系统</h3>
<el-form-item prop="username"> <el-form-item prop="username">
<el-input <el-input
v-model="loginForm.username" v-model="loginForm.username"
type="text" type="text"
auto-complete="off" auto-complete="off"
placeholder="账号" placeholder="账号"
> >
<svg-icon slot="prefix" icon-class="user" class="el-input__icon input-icon" /> <svg-icon slot="prefix" icon-class="user" class="el-input__icon input-icon" />
</el-input> </el-input>
</el-form-item> </el-form-item>
<el-form-item prop="password"> <el-form-item prop="password">
<el-input <el-input
v-model="loginForm.password" v-model="loginForm.password"
type="password" type="password"
auto-complete="off" auto-complete="off"
placeholder="密码" placeholder="密码"
@keyup.enter.native="handleLogin" @keyup.enter.native="handleLogin"
> >
<svg-icon slot="prefix" icon-class="password" class="el-input__icon input-icon" /> <svg-icon slot="prefix" icon-class="password" class="el-input__icon input-icon" />
</el-input> </el-input>
</el-form-item> </el-form-item>
<el-form-item prop="code" v-if="captchaEnabled"> <el-form-item prop="code" v-if="captchaEnabled">
<el-input <el-input
v-model="loginForm.code" v-model="loginForm.code"
auto-complete="off" auto-complete="off"
placeholder="验证码" placeholder="验证码"
style="width: 63%" style="width: 63%"
@keyup.enter.native="handleLogin" @keyup.enter.native="handleLogin"
> >
<svg-icon slot="prefix" icon-class="validCode" class="el-input__icon input-icon" /> <svg-icon slot="prefix" icon-class="validCode" class="el-input__icon input-icon" />
</el-input> </el-input>
<div class="login-code"> <div class="login-code">
<img :src="codeUrl" @click="getCode" class="login-code-img"/> <img :src="codeUrl" @click="getCode" class="login-code-img"/>
</div> </div>
</el-form-item> </el-form-item>
<el-checkbox v-model="loginForm.rememberMe" style="margin:0px 0px 25px 0px;">记住密码</el-checkbox> <el-checkbox v-model="loginForm.rememberMe" style="margin:0px 0px 25px 0px;">记住密码</el-checkbox>
<el-form-item style="width:100%;"> <el-form-item style="width:100%;">
<el-button <el-button
:loading="loading" :loading="loading"
size="medium" size="medium"
type="primary" type="primary"
style="width:100%;" style="width:100%;"
@click.native.prevent="handleLogin" @click.native.prevent="handleLogin"
> >
<span v-if="!loading"> </span> <span v-if="!loading"> </span>
<span v-else> 中...</span> <span v-else> 中...</span>
</el-button> </el-button>
<div style="float: right;" v-if="register"> <div style="float: right;" v-if="register">
<router-link class="link-type" :to="'/register'">立即注册</router-link> <router-link class="link-type" :to="'/register'">立即注册</router-link>
</div> </div>
</el-form-item> </el-form-item>
</el-form> </el-form>
<!-- 底部 --> <!-- 底部 -->
<div class="el-login-footer"> <div class="el-login-footer">
<span>Copyright © 2018-2022 ruoyi.vip All Rights Reserved.</span> <span>Copyright © 2018-2022 ruoyi.vip All Rights Reserved.</span>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import { getCodeImg } from "@/api/login"; import { getCodeImg } from "@/api/login";
import Cookies from "js-cookie"; import Cookies from "js-cookie";
import { encrypt, decrypt } from '@/utils/jsencrypt' import { encrypt, decrypt } from '@/utils/jsencrypt'
export default { export default {
name: "Login", name: "Login",
data() { data() {
return { return {
codeUrl: "", codeUrl: "",
loginForm: { loginForm: {
username: "admin", username: "admin",
password: "admin123", password: "admin123",
rememberMe: false, rememberMe: false,
code: "", code: "",
uuid: "" uuid: ""
}, },
loginRules: { loginRules: {
username: [ username: [
{ required: true, trigger: "blur", message: "请输入您的账号" } { required: true, trigger: "blur", message: "请输入您的账号" }
], ],
password: [ password: [
{ required: true, trigger: "blur", message: "请输入您的密码" } { required: true, trigger: "blur", message: "请输入您的密码" }
], ],
code: [{ required: true, trigger: "change", message: "请输入验证码" }] code: [{ required: true, trigger: "change", message: "请输入验证码" }]
}, },
loading: false, loading: false,
// //
captchaEnabled: true, captchaEnabled: true,
// //
register: false, register: false,
redirect: undefined redirect: undefined
}; };
}, },
watch: { watch: {
$route: { $route: {
handler: function(route) { handler: function(route) {
this.redirect = route.query && route.query.redirect; this.redirect = route.query && route.query.redirect;
}, },
immediate: true immediate: true
} }
}, },
created() { created() {
this.getCode(); this.getCode();
this.getCookie(); this.getCookie();
}, },
methods: { methods: {
getCode() { getCode() {
getCodeImg().then(res => { getCodeImg().then(res => {
this.captchaEnabled = res.captchaEnabled === undefined ? true : res.captchaEnabled; this.captchaEnabled = res.captchaEnabled === undefined ? true : res.captchaEnabled;
if (this.captchaEnabled) { if (this.captchaEnabled) {
this.codeUrl = "data:image/gif;base64," + res.img; this.codeUrl = "data:image/gif;base64," + res.img;
this.loginForm.uuid = res.uuid; this.loginForm.uuid = res.uuid;
} }
}); });
}, },
getCookie() { getCookie() {
const username = Cookies.get("username"); const username = Cookies.get("username");
const password = Cookies.get("password"); const password = Cookies.get("password");
const rememberMe = Cookies.get('rememberMe') const rememberMe = Cookies.get('rememberMe')
this.loginForm = { this.loginForm = {
username: username === undefined ? this.loginForm.username : username, username: username === undefined ? this.loginForm.username : username,
password: password === undefined ? this.loginForm.password : decrypt(password), password: password === undefined ? this.loginForm.password : decrypt(password),
rememberMe: rememberMe === undefined ? false : Boolean(rememberMe) rememberMe: rememberMe === undefined ? false : Boolean(rememberMe)
}; };
}, },
handleLogin() { handleLogin() {
this.$refs.loginForm.validate(valid => { this.$refs.loginForm.validate(valid => {
if (valid) { if (valid) {
this.loading = true; this.loading = true;
if (this.loginForm.rememberMe) { if (this.loginForm.rememberMe) {
Cookies.set("username", this.loginForm.username, { expires: 30 }); Cookies.set("username", this.loginForm.username, { expires: 30 });
Cookies.set("password", encrypt(this.loginForm.password), { expires: 30 }); Cookies.set("password", encrypt(this.loginForm.password), { expires: 30 });
Cookies.set('rememberMe', this.loginForm.rememberMe, { expires: 30 }); Cookies.set('rememberMe', this.loginForm.rememberMe, { expires: 30 });
} else { } else {
Cookies.remove("username"); Cookies.remove("username");
Cookies.remove("password"); Cookies.remove("password");
Cookies.remove('rememberMe'); Cookies.remove('rememberMe');
} }
this.$store.dispatch("Login", this.loginForm).then(() => { this.$store.dispatch("Login", this.loginForm).then(() => {
this.$router.push({ path: this.redirect || "/" }).catch(()=>{}); this.$router.push({ path: this.redirect || "/" }).catch(()=>{});
}).catch(() => { }).catch(() => {
this.loading = false; this.loading = false;
if (this.captchaEnabled) { if (this.captchaEnabled) {
this.getCode(); this.getCode();
} }
}); });
} }
}); });
} }
} }
}; };
</script> </script>
<style rel="stylesheet/scss" lang="scss"> <style rel="stylesheet/scss" lang="scss">
.login { .login {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
height: 100%; height: 100%;
background-image: url("../assets/images/login-background.jpg"); background-image: url("../assets/images/login-background.jpg");
background-size: cover; background-size: cover;
} }
.title { .title {
margin: 0px auto 30px auto; margin: 0px auto 30px auto;
text-align: center; text-align: center;
color: #707070; color: #707070;
} }
.login-form { .login-form {
border-radius: 6px; border-radius: 6px;
background: #ffffff; background: #ffffff;
width: 400px; width: 400px;
padding: 25px 25px 5px 25px; padding: 25px 25px 5px 25px;
.el-input { .el-input {
height: 38px; height: 38px;
input { input {
height: 38px; height: 38px;
} }
} }
.input-icon { .input-icon {
height: 39px; height: 39px;
width: 14px; width: 14px;
margin-left: 2px; margin-left: 2px;
} }
} }
.login-tip { .login-tip {
font-size: 13px; font-size: 13px;
text-align: center; text-align: center;
color: #bfbfbf; color: #bfbfbf;
} }
.login-code { .login-code {
width: 33%; width: 33%;
height: 38px; height: 38px;
float: right; float: right;
img { img {
cursor: pointer; cursor: pointer;
vertical-align: middle; vertical-align: middle;
} }
} }
.el-login-footer { .el-login-footer {
height: 40px; height: 40px;
line-height: 40px; line-height: 40px;
position: fixed; position: fixed;
bottom: 0; bottom: 0;
width: 100%; width: 100%;
text-align: center; text-align: center;
color: #fff; color: #fff;
font-family: Arial; font-family: Arial;
font-size: 12px; font-size: 12px;
letter-spacing: 1px; letter-spacing: 1px;
} }
.login-code-img { .login-code-img {
height: 38px; height: 38px;
} }
</style> </style>

418
ruoyi-ui/src/views/register.vue

@ -1,209 +1,209 @@
<template> <template>
<div class="register"> <div class="register">
<el-form ref="registerForm" :model="registerForm" :rules="registerRules" class="register-form"> <el-form ref="registerForm" :model="registerForm" :rules="registerRules" class="register-form">
<h3 class="title">若依后台管理系统</h3> <h3 class="title">传控后台管理系统</h3>
<el-form-item prop="username"> <el-form-item prop="username">
<el-input v-model="registerForm.username" type="text" auto-complete="off" placeholder="账号"> <el-input v-model="registerForm.username" type="text" auto-complete="off" placeholder="账号">
<svg-icon slot="prefix" icon-class="user" class="el-input__icon input-icon" /> <svg-icon slot="prefix" icon-class="user" class="el-input__icon input-icon" />
</el-input> </el-input>
</el-form-item> </el-form-item>
<el-form-item prop="password"> <el-form-item prop="password">
<el-input <el-input
v-model="registerForm.password" v-model="registerForm.password"
type="password" type="password"
auto-complete="off" auto-complete="off"
placeholder="密码" placeholder="密码"
@keyup.enter.native="handleRegister" @keyup.enter.native="handleRegister"
> >
<svg-icon slot="prefix" icon-class="password" class="el-input__icon input-icon" /> <svg-icon slot="prefix" icon-class="password" class="el-input__icon input-icon" />
</el-input> </el-input>
</el-form-item> </el-form-item>
<el-form-item prop="confirmPassword"> <el-form-item prop="confirmPassword">
<el-input <el-input
v-model="registerForm.confirmPassword" v-model="registerForm.confirmPassword"
type="password" type="password"
auto-complete="off" auto-complete="off"
placeholder="确认密码" placeholder="确认密码"
@keyup.enter.native="handleRegister" @keyup.enter.native="handleRegister"
> >
<svg-icon slot="prefix" icon-class="password" class="el-input__icon input-icon" /> <svg-icon slot="prefix" icon-class="password" class="el-input__icon input-icon" />
</el-input> </el-input>
</el-form-item> </el-form-item>
<el-form-item prop="code" v-if="captchaEnabled"> <el-form-item prop="code" v-if="captchaEnabled">
<el-input <el-input
v-model="registerForm.code" v-model="registerForm.code"
auto-complete="off" auto-complete="off"
placeholder="验证码" placeholder="验证码"
style="width: 63%" style="width: 63%"
@keyup.enter.native="handleRegister" @keyup.enter.native="handleRegister"
> >
<svg-icon slot="prefix" icon-class="validCode" class="el-input__icon input-icon" /> <svg-icon slot="prefix" icon-class="validCode" class="el-input__icon input-icon" />
</el-input> </el-input>
<div class="register-code"> <div class="register-code">
<img :src="codeUrl" @click="getCode" class="register-code-img"/> <img :src="codeUrl" @click="getCode" class="register-code-img"/>
</div> </div>
</el-form-item> </el-form-item>
<el-form-item style="width:100%;"> <el-form-item style="width:100%;">
<el-button <el-button
:loading="loading" :loading="loading"
size="medium" size="medium"
type="primary" type="primary"
style="width:100%;" style="width:100%;"
@click.native.prevent="handleRegister" @click.native.prevent="handleRegister"
> >
<span v-if="!loading"> </span> <span v-if="!loading"> </span>
<span v-else> 中...</span> <span v-else> 中...</span>
</el-button> </el-button>
<div style="float: right;"> <div style="float: right;">
<router-link class="link-type" :to="'/login'">使用已有账户登录</router-link> <router-link class="link-type" :to="'/login'">使用已有账户登录</router-link>
</div> </div>
</el-form-item> </el-form-item>
</el-form> </el-form>
<!-- 底部 --> <!-- 底部 -->
<div class="el-register-footer"> <div class="el-register-footer">
<span>Copyright © 2018-2022 ruoyi.vip All Rights Reserved.</span> <span>Copyright © 2018-2022 ruoyi.vip All Rights Reserved.</span>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import { getCodeImg, register } from "@/api/login"; import { getCodeImg, register } from "@/api/login";
export default { export default {
name: "Register", name: "Register",
data() { data() {
const equalToPassword = (rule, value, callback) => { const equalToPassword = (rule, value, callback) => {
if (this.registerForm.password !== value) { if (this.registerForm.password !== value) {
callback(new Error("两次输入的密码不一致")); callback(new Error("两次输入的密码不一致"));
} else { } else {
callback(); callback();
} }
}; };
return { return {
codeUrl: "", codeUrl: "",
registerForm: { registerForm: {
username: "", username: "",
password: "", password: "",
confirmPassword: "", confirmPassword: "",
code: "", code: "",
uuid: "" uuid: ""
}, },
registerRules: { registerRules: {
username: [ username: [
{ required: true, trigger: "blur", message: "请输入您的账号" }, { required: true, trigger: "blur", message: "请输入您的账号" },
{ min: 2, max: 20, message: '用户账号长度必须介于 2 和 20 之间', trigger: 'blur' } { min: 2, max: 20, message: '用户账号长度必须介于 2 和 20 之间', trigger: 'blur' }
], ],
password: [ password: [
{ required: true, trigger: "blur", message: "请输入您的密码" }, { required: true, trigger: "blur", message: "请输入您的密码" },
{ min: 5, max: 20, message: '用户密码长度必须介于 5 和 20 之间', trigger: 'blur' } { min: 5, max: 20, message: '用户密码长度必须介于 5 和 20 之间', trigger: 'blur' }
], ],
confirmPassword: [ confirmPassword: [
{ required: true, trigger: "blur", message: "请再次输入您的密码" }, { required: true, trigger: "blur", message: "请再次输入您的密码" },
{ required: true, validator: equalToPassword, trigger: "blur" } { required: true, validator: equalToPassword, trigger: "blur" }
], ],
code: [{ required: true, trigger: "change", message: "请输入验证码" }] code: [{ required: true, trigger: "change", message: "请输入验证码" }]
}, },
loading: false, loading: false,
captchaEnabled: true captchaEnabled: true
}; };
}, },
created() { created() {
this.getCode(); this.getCode();
}, },
methods: { methods: {
getCode() { getCode() {
getCodeImg().then(res => { getCodeImg().then(res => {
this.captchaEnabled = res.captchaEnabled === undefined ? true : res.captchaEnabled; this.captchaEnabled = res.captchaEnabled === undefined ? true : res.captchaEnabled;
if (this.captchaEnabled) { if (this.captchaEnabled) {
this.codeUrl = "data:image/gif;base64," + res.img; this.codeUrl = "data:image/gif;base64," + res.img;
this.registerForm.uuid = res.uuid; this.registerForm.uuid = res.uuid;
} }
}); });
}, },
handleRegister() { handleRegister() {
this.$refs.registerForm.validate(valid => { this.$refs.registerForm.validate(valid => {
if (valid) { if (valid) {
this.loading = true; this.loading = true;
register(this.registerForm).then(res => { register(this.registerForm).then(res => {
const username = this.registerForm.username; const username = this.registerForm.username;
this.$alert("<font color='red'>恭喜你,您的账号 " + username + " 注册成功!</font>", '系统提示', { this.$alert("<font color='red'>恭喜你,您的账号 " + username + " 注册成功!</font>", '系统提示', {
dangerouslyUseHTMLString: true, dangerouslyUseHTMLString: true,
type: 'success' type: 'success'
}).then(() => { }).then(() => {
this.$router.push("/login"); this.$router.push("/login");
}).catch(() => {}); }).catch(() => {});
}).catch(() => { }).catch(() => {
this.loading = false; this.loading = false;
if (this.captchaEnabled) { if (this.captchaEnabled) {
this.getCode(); this.getCode();
} }
}) })
} }
}); });
} }
} }
}; };
</script> </script>
<style rel="stylesheet/scss" lang="scss"> <style rel="stylesheet/scss" lang="scss">
.register { .register {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
height: 100%; height: 100%;
background-image: url("../assets/images/login-background.jpg"); background-image: url("../assets/images/login-background.jpg");
background-size: cover; background-size: cover;
} }
.title { .title {
margin: 0px auto 30px auto; margin: 0px auto 30px auto;
text-align: center; text-align: center;
color: #707070; color: #707070;
} }
.register-form { .register-form {
border-radius: 6px; border-radius: 6px;
background: #ffffff; background: #ffffff;
width: 400px; width: 400px;
padding: 25px 25px 5px 25px; padding: 25px 25px 5px 25px;
.el-input { .el-input {
height: 38px; height: 38px;
input { input {
height: 38px; height: 38px;
} }
} }
.input-icon { .input-icon {
height: 39px; height: 39px;
width: 14px; width: 14px;
margin-left: 2px; margin-left: 2px;
} }
} }
.register-tip { .register-tip {
font-size: 13px; font-size: 13px;
text-align: center; text-align: center;
color: #bfbfbf; color: #bfbfbf;
} }
.register-code { .register-code {
width: 33%; width: 33%;
height: 38px; height: 38px;
float: right; float: right;
img { img {
cursor: pointer; cursor: pointer;
vertical-align: middle; vertical-align: middle;
} }
} }
.el-register-footer { .el-register-footer {
height: 40px; height: 40px;
line-height: 40px; line-height: 40px;
position: fixed; position: fixed;
bottom: 0; bottom: 0;
width: 100%; width: 100%;
text-align: center; text-align: center;
color: #fff; color: #fff;
font-family: Arial; font-family: Arial;
font-size: 12px; font-size: 12px;
letter-spacing: 1px; letter-spacing: 1px;
} }
.register-code-img { .register-code-img {
height: 38px; height: 38px;
} }
</style> </style>

273
ruoyi-ui/vue.config.js

@ -1,136 +1,137 @@
'use strict' 'use strict'
const path = require('path') const path = require('path')
function resolve(dir) { function resolve(dir) {
return path.join(__dirname, dir) return path.join(__dirname, dir)
} }
const CompressionPlugin = require('compression-webpack-plugin') const CompressionPlugin = require('compression-webpack-plugin')
const name = process.env.VUE_APP_TITLE || '若依管理系统' // 网页标题 const name = process.env.VUE_APP_TITLE || '传控管理系统' // 网页标题
const port = process.env.port || process.env.npm_config_port || 80 // 端口 const port = process.env.port || process.env.npm_config_port || 80 // 端口
// vue.config.js 配置说明 // vue.config.js 配置说明
//官方vue.config.js 参考文档 https://cli.vuejs.org/zh/config/#css-loaderoptions //官方vue.config.js 参考文档 https://cli.vuejs.org/zh/config/#css-loaderoptions
// 这里只列一部分,具体配置参考文档 // 这里只列一部分,具体配置参考文档
module.exports = { module.exports = {
// 部署生产环境和开发环境下的URL。 // 部署生产环境和开发环境下的URL。
// 默认情况下,Vue CLI 会假设你的应用是被部署在一个域名的根路径上 // 默认情况下,Vue CLI 会假设你的应用是被部署在一个域名的根路径上
// 例如 https://www.ruoyi.vip/。如果应用被部署在一个子路径上,你就需要用这个选项指定这个子路径。例如,如果你的应用被部署在 https://www.ruoyi.vip/admin/,则设置 baseUrl 为 /admin/。 // 例如 https://www.ruoyi.vip/。如果应用被部署在一个子路径上,你就需要用这个选项指定这个子路径。例如,如果你的应用被部署在 https://www.ruoyi.vip/admin/,则设置 baseUrl 为 /admin/。
publicPath: process.env.NODE_ENV === "production" ? "/" : "/", publicPath: process.env.NODE_ENV === "production" ? "/" : "/",
// 在npm run build 或 yarn build 时 ,生成文件的目录名称(要和baseUrl的生产环境路径一致)(默认dist) // 在npm run build 或 yarn build 时 ,生成文件的目录名称(要和baseUrl的生产环境路径一致)(默认dist)
outputDir: 'dist', outputDir: 'dist',
// 用于放置生成的静态资源 (js、css、img、fonts) 的;(项目打包之后,静态资源会放在这个文件夹下) // 用于放置生成的静态资源 (js、css、img、fonts) 的;(项目打包之后,静态资源会放在这个文件夹下)
assetsDir: 'static', assetsDir: 'static',
// 是否开启eslint保存检测,有效值:ture | false | 'error' // 是否开启eslint保存检测,有效值:ture | false | 'error'
lintOnSave: process.env.NODE_ENV === 'development', lintOnSave: process.env.NODE_ENV === 'development',
// 如果你不需要生产环境的 source map,可以将其设置为 false 以加速生产环境构建。 // 如果你不需要生产环境的 source map,可以将其设置为 false 以加速生产环境构建。
productionSourceMap: false, productionSourceMap: false,
// webpack-dev-server 相关配置 // webpack-dev-server 相关配置
devServer: { devServer: {
host: '0.0.0.0', host: '0.0.0.0',
port: port, port: port,
open: true, open: true,
proxy: { proxy: {
// detail: https://cli.vuejs.org/config/#devserver-proxy // detail: https://cli.vuejs.org/config/#devserver-proxy
[process.env.VUE_APP_BASE_API]: { [process.env.VUE_APP_BASE_API]: {
target: `http://localhost:8080`, // target: `http://81.70.146.184`,
changeOrigin: true, target: `http://localhost:8080`,
pathRewrite: { changeOrigin: true,
['^' + process.env.VUE_APP_BASE_API]: '' pathRewrite: {
} ['^' + process.env.VUE_APP_BASE_API]: ''
} }
}, }
disableHostCheck: true },
}, disableHostCheck: true
css: { },
loaderOptions: { css: {
sass: { loaderOptions: {
sassOptions: { outputStyle: "expanded" } sass: {
} sassOptions: { outputStyle: "expanded" }
} }
}, }
configureWebpack: { },
name: name, configureWebpack: {
resolve: { name: name,
alias: { resolve: {
'@': resolve('src') alias: {
} '@': resolve('src')
}, }
plugins: [ },
// http://doc.ruoyi.vip/ruoyi-vue/other/faq.html#使用gzip解压缩静态文件 plugins: [
new CompressionPlugin({ // http://doc.ruoyi.vip/ruoyi-vue/other/faq.html#使用gzip解压缩静态文件
cache: false, // 不启用文件缓存 new CompressionPlugin({
test: /\.(js|css|html)?$/i, // 压缩文件格式 cache: false, // 不启用文件缓存
filename: '[path].gz[query]', // 压缩后的文件名 test: /\.(js|css|html)?$/i, // 压缩文件格式
algorithm: 'gzip', // 使用gzip压缩 filename: '[path].gz[query]', // 压缩后的文件名
minRatio: 0.8 // 压缩率小于1才会压缩 algorithm: 'gzip', // 使用gzip压缩
}) minRatio: 0.8 // 压缩率小于1才会压缩
], })
}, ],
chainWebpack(config) { },
config.plugins.delete('preload') // TODO: need test chainWebpack(config) {
config.plugins.delete('prefetch') // TODO: need test config.plugins.delete('preload') // TODO: need test
config.plugins.delete('prefetch') // TODO: need test
// set svg-sprite-loader
config.module // set svg-sprite-loader
.rule('svg') config.module
.exclude.add(resolve('src/assets/icons')) .rule('svg')
.end() .exclude.add(resolve('src/assets/icons'))
config.module .end()
.rule('icons') config.module
.test(/\.svg$/) .rule('icons')
.include.add(resolve('src/assets/icons')) .test(/\.svg$/)
.end() .include.add(resolve('src/assets/icons'))
.use('svg-sprite-loader') .end()
.loader('svg-sprite-loader') .use('svg-sprite-loader')
.options({ .loader('svg-sprite-loader')
symbolId: 'icon-[name]' .options({
}) symbolId: 'icon-[name]'
.end() })
.end()
config
.when(process.env.NODE_ENV !== 'development', config
config => { .when(process.env.NODE_ENV !== 'development',
config config => {
.plugin('ScriptExtHtmlWebpackPlugin') config
.after('html') .plugin('ScriptExtHtmlWebpackPlugin')
.use('script-ext-html-webpack-plugin', [{ .after('html')
// `runtime` must same as runtimeChunk name. default is `runtime` .use('script-ext-html-webpack-plugin', [{
inline: /runtime\..*\.js$/ // `runtime` must same as runtimeChunk name. default is `runtime`
}]) inline: /runtime\..*\.js$/
.end() }])
config .end()
.optimization.splitChunks({ config
chunks: 'all', .optimization.splitChunks({
cacheGroups: { chunks: 'all',
libs: { cacheGroups: {
name: 'chunk-libs', libs: {
test: /[\\/]node_modules[\\/]/, name: 'chunk-libs',
priority: 10, test: /[\\/]node_modules[\\/]/,
chunks: 'initial' // only package third parties that are initially dependent priority: 10,
}, chunks: 'initial' // only package third parties that are initially dependent
elementUI: { },
name: 'chunk-elementUI', // split elementUI into a single package elementUI: {
priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app name: 'chunk-elementUI', // split elementUI into a single package
test: /[\\/]node_modules[\\/]_?element-ui(.*)/ // in order to adapt to cnpm priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app
}, test: /[\\/]node_modules[\\/]_?element-ui(.*)/ // in order to adapt to cnpm
commons: { },
name: 'chunk-commons', commons: {
test: resolve('src/components'), // can customize your rules name: 'chunk-commons',
minChunks: 3, // minimum common number test: resolve('src/components'), // can customize your rules
priority: 5, minChunks: 3, // minimum common number
reuseExistingChunk: true priority: 5,
} reuseExistingChunk: true
} }
}) }
config.optimization.runtimeChunk('single'), })
{ config.optimization.runtimeChunk('single'),
from: path.resolve(__dirname, './public/robots.txt'), //防爬虫文件 {
to: './' //到根目录下 from: path.resolve(__dirname, './public/robots.txt'), //防爬虫文件
} to: './' //到根目录下
} }
) }
} )
} }
}

Loading…
Cancel
Save