25 changed files with 2976 additions and 1787 deletions
@ -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"; |
||||
|
} |
||||
|
|
||||
|
} |
@ -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)); |
||||
|
} |
||||
|
} |
@ -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(); |
||||
|
} |
||||
|
} |
@ -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); |
||||
|
} |
@ -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); |
||||
|
} |
@ -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); |
||||
|
} |
||||
|
} |
@ -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检验成功返回true;token校验失败返回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+"}"; |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} |
@ -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> |
@ -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 |
||||
|
@ -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' |
||||
|
@ -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' |
||||
|
@ -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" |
||||
] |
] |
||||
} |
} |
||||
|
@ -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' |
||||
|
}) |
||||
|
} |
@ -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> |
||||
|
@ -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> |
File diff suppressed because it is too large
@ -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> |
||||
|
@ -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> |
||||
|
@ -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…
Reference in new issue