This commit is contained in:
tangzh 2025-06-03 13:52:09 +08:00
parent 439526cba2
commit 47675ad3ac
23 changed files with 364 additions and 91 deletions

View File

@ -58,6 +58,7 @@
<!--表格渲染-->
<el-table ref="table" v-loading="crud.loading" :data="crud.data" size="small" style="width: 100%;" @selection-change="crud.selectionChangeHandler">
<el-table-column type="selection" width="55" />
<el-table-column prop="deviceCode" label="设备码" />
<el-table-column prop="deviceSn" label="设备序列号" />
<el-table-column prop="model" label="型号" />
<el-table-column prop="brand" label="品牌" />
@ -73,7 +74,6 @@
<el-table-column prop="type" label="类型">
<template slot-scope="scope">
<span v-if="scope.row.type==1">打印机</span>
<span v-else>摄像头</span>
</template>
</el-table-column>
<el-table-column prop="createTime" label="创建时间" />
@ -83,7 +83,7 @@
:data="scope.row"
:permission="permission"
/>
<el-button type="success" size="mini" title="设备指令" @click="openCommandData(scope.row.id)"><svg-icon icon-class="chain" /></el-button>
<!-- <el-button type="success" size="mini" title="设备指令" @click="openCommandData(scope.row.id)"><svg-icon icon-class="chain" /></el-button>-->
<el-button type="warning" size="mini" title="生成二维码" @click="createQrCode(scope.row.id)"><svg-icon icon-class="exit-fullscreen" /></el-button>
</template>
</el-table-column>
@ -127,7 +127,6 @@ export default {
},
typeList: [
{ 'label': '打印机', 'value': 1 },
{ 'label': '摄像头', 'value': 2 }
],
rules: {
deviceSn: [

View File

@ -40,9 +40,9 @@
<el-table-column prop="commandName" label="指令名称" />
<el-table-column prop="commandType" label="指令类型" >
<template slot-scope="scope">
<span v-if="scope.row.commandType==1">控制</span>
<span v-else-if="scope.row.commandType==2">查询</span>
<span v-else>校准</span>
<span v-if="scope.row.commandType=='FILE_TRANSFER'">文件传输</span>
<span v-else-if="scope.row.commandType=='PRINT_CONTROL'">打印控制</span>
<span v-else>视频流传输</span>
</template>
</el-table-column>
<el-table-column prop="commandParams" label="指令参数" />
@ -85,9 +85,9 @@ export default {
data() {
return {
commandTypes: [
{ 'label': '控制', 'value': 1 },
{ 'label': '查询', 'value': 2 },
{ 'label': '校准', 'value': 3 }
{ 'label': '文件传输', 'value': 'FILE_TRANSFER' },
{ 'label': '打印控制', 'value': 'PRINT_CONTROL' },
{ 'label': '视频流传输', 'value': 'VIDEO_STREAM' }
],
permission: {
add: ['admin', 'busDeviceCommand:add'],

View File

@ -76,7 +76,6 @@
<span class="role-span">设备分配</span>
</el-tooltip>
<el-button
:disabled="!showButton"
:loading="deviceLoading"
icon="el-icon-check"
@ -98,7 +97,8 @@
show-checkbox
node-key="id"
@check="deviceChange"
/>
>
</el-tree>
</el-card>
</el-col>
</el-row>

View File

@ -0,0 +1,18 @@
package me.zhengjie.modules.front.domain.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class DeviceLogCriteria {
@ApiModelProperty(value = "页码", example = "1")
private Integer page = 1;
@ApiModelProperty(value = "每页数据量", example = "10")
private Integer size = 10;
@ApiModelProperty(value = "设备id")
private Long deviceId;
}

View File

@ -0,0 +1,15 @@
package me.zhengjie.modules.front.domain.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class MyDeviceCriteria {
@ApiModelProperty(value = "页码", example = "1")
private Integer page = 1;
@ApiModelProperty(value = "每页数据量", example = "10")
private Integer size = 10;
}

View File

@ -1,15 +1,13 @@
package me.zhengjie.modules.front.rest;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.annotation.Log;
import me.zhengjie.annotation.rest.AnonymousPostMapping;
import me.zhengjie.modules.front.domain.dto.LoginVo;
import me.zhengjie.modules.front.service.WeChatService;
import me.zhengjie.modules.security.service.dto.JwtUserDto;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.modules.system.domain.BusDevice;
import me.zhengjie.modules.system.service.BusDeviceService;
import me.zhengjie.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
@ -18,22 +16,29 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
@Slf4j
@RestController("DeviceController")
@RequestMapping("api/front/device")
@Api(tags = "微信:设备管理")
public class DeviceController {
public class BusDeviceController {
@Autowired private BusDeviceService busDeviceService;
@Log("获取设备")
@ApiOperation(value = "获取设备")
@GetMapping(value = "/get")
public ResponseEntity<BusDevice> get(@RequestParam String deviceCode) {
BusDevice device = busDeviceService.getByDeviceCode(deviceCode);
if (null == device) { throw new BadRequestException("未查询到设备"); }
return new ResponseEntity<>(device, HttpStatus.OK);
}
@Log("绑定设备")
@ApiOperation(value = "绑定设备")
@GetMapping(value = "/binding")
public ResponseEntity<Object> binding(@RequestParam String code) {
busDeviceService.binding(code);
@GetMapping(value = "/bindingDevice")
public ResponseEntity<Object> bindingDevice(@RequestParam String deviceCode) {
busDeviceService.bindingDevice(deviceCode);
return new ResponseEntity<>("绑定成功", HttpStatus.OK);
}

View File

@ -0,0 +1,73 @@
package me.zhengjie.modules.front.rest;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.annotation.Log;
import me.zhengjie.modules.front.domain.dto.LoginVo;
import me.zhengjie.modules.front.domain.dto.MyDeviceCriteria;
import me.zhengjie.modules.security.service.dto.JwtUserDto;
import me.zhengjie.modules.system.domain.BusDevice;
import me.zhengjie.modules.system.domain.BusUser;
import me.zhengjie.modules.system.domain.dto.BusDeviceQueryCriteria;
import me.zhengjie.modules.system.service.BusDeviceService;
import me.zhengjie.modules.system.service.BusUserService;
import me.zhengjie.utils.PageResult;
import me.zhengjie.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@Slf4j
@RestController("UserController")
@RequestMapping("api/front/user")
@Api(tags = "微信:用户管理")
public class BusUserController {
@Autowired private BusUserService busUserService;
@Autowired private BusDeviceService busDeviceService;
@Log("我的设备")
@GetMapping(value = "myDevice")
@ApiOperation("我的设备")
public ResponseEntity<PageResult<BusDevice>> myDeviceList(MyDeviceCriteria criteria) {
JwtUserDto jwtUser = (JwtUserDto) SecurityUtils.getCurrentUser();
Page<Object> page = new Page<>(criteria.getPage(), criteria.getSize());
return new ResponseEntity<>(busDeviceService.myDeviceList(jwtUser.getUser().getId(), page), HttpStatus.OK);
}
@Log("用户信息")
@ApiOperation("获取用户信息")
@GetMapping(value = "/info")
public ResponseEntity<LoginVo> getLoginInfo() {
JwtUserDto jwtUser = (JwtUserDto) SecurityUtils.getCurrentUser();
LoginVo loginVo = new LoginVo();
loginVo.setType("login");
loginVo.setUid(jwtUser.getUser().getId());
loginVo.setNikeName(jwtUser.getUser().getNickName());
loginVo.setAvatar(jwtUser.getUser().getAvatarPath());
loginVo.setPhone(jwtUser.getUser().getPhone());
return new ResponseEntity<>(loginVo, HttpStatus.OK);
}
@Log("信息修改")
@ApiOperation("修改用户信息")
@PostMapping(value = "/update")
public ResponseEntity<String> updateInfo() {
JwtUserDto jwtUser = (JwtUserDto) SecurityUtils.getCurrentUser();
BusUser upd = new BusUser();
upd.setId(jwtUser.getUser().getId());
upd.setAvatar(jwtUser.getUser().getAvatarPath());
upd.setNickname(jwtUser.getUser().getNickName());
upd.setPhone(jwtUser.getUser().getPhone());
busUserService.updateById(upd);
return new ResponseEntity<>("修改成功", HttpStatus.OK);
}
}

View File

@ -7,8 +7,6 @@ import me.zhengjie.annotation.Log;
import me.zhengjie.annotation.rest.AnonymousPostMapping;
import me.zhengjie.modules.front.domain.dto.LoginVo;
import me.zhengjie.modules.front.service.WeChatService;
import me.zhengjie.modules.security.service.dto.JwtUserDto;
import me.zhengjie.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
@ -35,20 +33,6 @@ public class WeChatController {
LoginVo loginVo = weChatService.authorizeLogin(code, request);
return new ResponseEntity<>(loginVo, HttpStatus.OK);
}
@Log("用户信息")
@ApiOperation("获取用户信息")
@GetMapping(value = "/info")
public ResponseEntity<LoginVo> getLoginInfo() {
JwtUserDto jwtUser = (JwtUserDto) SecurityUtils.getCurrentUser();
LoginVo loginVo = new LoginVo();
loginVo.setType("login");
loginVo.setUid(jwtUser.getUser().getId());
loginVo.setNikeName(jwtUser.getUser().getNickName());
loginVo.setAvatar(jwtUser.getUser().getAvatarPath());
loginVo.setPhone(jwtUser.getUser().getPhone());
return new ResponseEntity<>(loginVo, HttpStatus.OK);
}
}

View File

@ -92,8 +92,7 @@ public class SpringSecurityConfig {
"/**/*.html",
"/**/*.css",
"/**/*.js",
"/webSocket/**",
"/sdcp/**"
"/webSocket/**"
).permitAll()
// swagger 文档
.antMatchers("/swagger-ui.html").permitAll()

View File

@ -0,0 +1,52 @@
/*
* Copyright 2019-2025 Tz
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.zhengjie.modules.system.domain;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.List;
@Data
@TableName("bus_command_log")
public class BusCommandLog implements Serializable {
@TableId(value = "id", type = IdType.AUTO)
@ApiModelProperty(value = "设备唯一标识")
private Long id;
@ApiModelProperty(value = "用户ID外键")
private Long userId;
@ApiModelProperty(value = "设备ID外键")
private Long deviceId;
@ApiModelProperty(value = "指令ID外键")
private Long commandId;
public void copy(BusCommandLog source){
BeanUtil.copyProperties(source,this, CopyOptions.create().setIgnoreNullValue(true));
}
}

View File

@ -48,7 +48,7 @@ public class BusDevice implements Serializable {
@ApiModelProperty(value = "机器序号")
private String deviceCode;
@ApiModelProperty(value = "设备序列号(唯一)")
@ApiModelProperty(value = "设备序列号")
private String deviceSn;
@ApiModelProperty(value = "型号")

View File

@ -39,15 +39,12 @@ public class BusUserCommand implements Serializable {
@ApiModelProperty(value = "操作记录唯一标识")
private Long id;
@NotNull
@ApiModelProperty(value = "用户ID外键")
private Long userId;
@NotNull
@ApiModelProperty(value = "设备ID外键")
private Long deviceId;
@NotNull
@ApiModelProperty(value = "指令ID外键")
private Long commandId;
@ -57,11 +54,9 @@ public class BusUserCommand implements Serializable {
@ApiModelProperty(value = "更新者")
private String updateBy;
@NotNull
@ApiModelProperty(value = "创建时间")
private Timestamp createTime;
@NotNull
@ApiModelProperty(value = "更新时间")
private Timestamp updateTime;

View File

@ -0,0 +1,41 @@
/*
* Copyright 2019-2025 Tz
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package me.zhengjie.modules.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import me.zhengjie.modules.system.domain.BusCommandLog;
import me.zhengjie.modules.system.domain.BusDevice;
import me.zhengjie.modules.system.domain.dto.BusDeviceQueryCriteria;
import me.zhengjie.modules.system.domain.dto.BusTreeVo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* @author tz
* @date 2025-05-20
**/
@Mapper
public interface BusCommandLogMapper extends BaseMapper<BusCommandLog> {
IPage<BusCommandLog> findAll(@Param("criteria") BusDeviceQueryCriteria criteria, Page<Object> page);
List<BusCommandLog> deviceLogList(@Param("deviceId") Long deviceId, Page<Object> page);
}

View File

@ -41,4 +41,6 @@ public interface BusDeviceMapper extends BaseMapper<BusDevice> {
void updateDeviceStatus(@Param("deviceSn") String deviceSn, @Param("status") Integer status, @Param("printStatus") Integer printStatus, @Param("errorStatus") Integer errorStatus, @Param("remark") String remark);
IPage<BusDevice> myDeviceList(@Param("userId") Long userId, Page<Object> page);
}

View File

@ -17,6 +17,7 @@ package me.zhengjie.modules.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import me.zhengjie.modules.system.domain.BusDevice;
import me.zhengjie.modules.system.domain.BusUser;
import me.zhengjie.modules.system.domain.dto.BusTreeVo;
import me.zhengjie.modules.system.domain.dto.BusUserQueryCriteria;
@ -40,4 +41,5 @@ public interface BusUserMapper extends BaseMapper<BusUser> {
List<BusUser> findAll(@Param("criteria") BusUserQueryCriteria criteria);
List<BusTreeVo> getUserCommands(@Param("userId") Long id);
}

View File

@ -18,9 +18,11 @@ package me.zhengjie.modules.system.service;
import java.util.List;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import me.zhengjie.modules.front.domain.dto.DeviceLogCriteria;
import me.zhengjie.modules.security.config.enums.CurrentStatusEnum;
import me.zhengjie.modules.security.config.enums.ErrorStatusEnum;
import me.zhengjie.modules.security.config.enums.PrintInfoStatusEnum;
import me.zhengjie.modules.system.domain.BusCommandLog;
import me.zhengjie.modules.system.domain.BusDevice;
import me.zhengjie.modules.system.domain.Menu;
import me.zhengjie.modules.system.domain.dto.BusDeviceQueryCriteria;
@ -34,13 +36,15 @@ import me.zhengjie.utils.PageResult;
**/
public interface BusDeviceService extends IService<BusDevice> {
List<BusDevice> getByDeviceSns(List<String> deviceSns);
BusDevice getByDeviceSn(String deviceSn);
/**
* 修改设备状态
*/
void updateDeviceStatus(String deviceSn, CurrentStatusEnum e1, PrintInfoStatusEnum e2, ErrorStatusEnum e3, String remarks);
PageResult<BusDevice> myDeviceList(Long userId, Page<Object> page);
/**
* 查询数据分页
* @param criteria 条件
@ -76,10 +80,14 @@ public interface BusDeviceService extends IService<BusDevice> {
String getQrCode(Long id);
void binding(String code);
void bindingDevice(String code);
List<BusTreeVo> getDeviceTree(Long pid);
void updateOrAdd(BusDevice entity);
BusDevice getByDeviceCode(String deviceCode);
PageResult<BusCommandLog> deviceLogList(DeviceLogCriteria criteria, Page<Object> page);
}

View File

@ -19,6 +19,7 @@ import java.util.List;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import me.zhengjie.modules.security.service.dto.JwtUserDto;
import me.zhengjie.modules.system.domain.BusDevice;
import me.zhengjie.modules.system.domain.BusUser;
import me.zhengjie.modules.system.domain.dto.BusTreeVo;
import me.zhengjie.modules.system.domain.dto.BusUserQueryCriteria;

View File

@ -17,36 +17,30 @@ package me.zhengjie.modules.system.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.modules.front.domain.dto.DeviceLogCriteria;
import me.zhengjie.modules.front.service.WeChatService;
import me.zhengjie.modules.security.config.enums.CurrentStatusEnum;
import me.zhengjie.modules.security.config.enums.ErrorStatusEnum;
import me.zhengjie.modules.security.config.enums.PrintInfoStatusEnum;
import me.zhengjie.modules.system.domain.BusDevice;
import me.zhengjie.modules.system.domain.BusDeviceCommand;
import me.zhengjie.modules.security.service.dto.JwtUserDto;
import me.zhengjie.modules.system.domain.*;
import me.zhengjie.modules.system.domain.dto.BusDeviceQueryCriteria;
import me.zhengjie.modules.system.domain.dto.BusTreeVo;
import me.zhengjie.modules.system.mapper.BusCommandMapper;
import me.zhengjie.modules.system.mapper.BusDeviceMapper;
import me.zhengjie.modules.system.mapper.*;
import me.zhengjie.modules.system.service.BusDeviceService;
import lombok.RequiredArgsConstructor;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import me.zhengjie.utils.CacheKey;
import me.zhengjie.utils.RedisUtils;
import me.zhengjie.utils.*;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import me.zhengjie.utils.PageUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import me.zhengjie.utils.PageResult;
/**
* @description 服务实现
* @author tz
@ -58,12 +52,25 @@ public class BusDeviceServiceImpl extends ServiceImpl<BusDeviceMapper, BusDevice
private final BusDeviceMapper busDeviceMapper;
private final BusCommandMapper busCommandMapper;
private final BusUserDeviceMapper userDeviceMapper;
private final BusUserCommandMapper busUserCommandMapper;
private final BusCommandLogMapper busCommandLogMapper;
private final WeChatService weChatService;
private final RedisUtils redisUtils;
@Override
public List<BusDevice> getByDeviceSns(List<String> deviceSns) {
return busDeviceMapper.selectList(new LambdaQueryWrapper<BusDevice>().in(BusDevice::getDeviceSn, deviceSns));
public BusDevice getByDeviceCode(String deviceCode) {
return busDeviceMapper.selectOne(new LambdaQueryWrapper<BusDevice>().in(BusDevice::getDeviceCode, deviceCode));
}
@Override
public PageResult<BusCommandLog> deviceLogList(DeviceLogCriteria criteria, Page<Object> page) {
return PageUtil.toPage(busCommandLogMapper.deviceLogList(criteria.getDeviceId(), page));
}
@Override
public BusDevice getByDeviceSn(String deviceSn) {
return busDeviceMapper.selectOne(new LambdaQueryWrapper<BusDevice>().eq(BusDevice::getDeviceSn, deviceSn));
}
@Async
@ -75,12 +82,14 @@ public class BusDeviceServiceImpl extends ServiceImpl<BusDeviceMapper, BusDevice
@Async
@Override
public void updateOrAdd(BusDevice entity) {
List<BusDevice> devices = getByDeviceSns(new ArrayList<String>() {{ add(entity.getDeviceSn()); }});
if (devices.isEmpty()) {
BusDevice device = getByDeviceSn(entity.getDeviceSn());
if (null == device) {
entity.setDeviceCode((new Random().nextInt(900000) + 100000) + "");
busDeviceMapper.insert(entity);
device = entity;
}
List<BusDeviceCommand> newList = entity.getCommandList();
List<BusDeviceCommand> oldList = busCommandMapper.selectList(new LambdaQueryWrapper<BusDeviceCommand>().eq(BusDeviceCommand::getDeviceId, devices.get(0).getId()));
List<BusDeviceCommand> oldList = busCommandMapper.selectList(new LambdaQueryWrapper<BusDeviceCommand>().eq(BusDeviceCommand::getDeviceId, device.getId()));
if (newList.isEmpty() && !oldList.isEmpty()) {
List<Long> dIds = oldList.stream().map(BusDeviceCommand::getId).collect(Collectors.toList());
busCommandMapper.deleteBatchIds(dIds);
@ -88,7 +97,7 @@ public class BusDeviceServiceImpl extends ServiceImpl<BusDeviceMapper, BusDevice
// 查询第一个列表中 CommandType 在第二个列表中不存在的元素
List<BusDeviceCommand> addList = newList.stream().filter(p1 -> oldList.stream().noneMatch(p2 -> Objects.equals(p1.getCommandType(), p2.getCommandType()))).collect(Collectors.toList());
for (BusDeviceCommand add : addList) {
add.setDeviceId(devices.get(0).getId());
add.setDeviceId(device.getId());
busCommandMapper.insert(add);
}
// 查询第二个列表中 CommandType 在第一个列表中不存在的元素
@ -100,6 +109,11 @@ public class BusDeviceServiceImpl extends ServiceImpl<BusDeviceMapper, BusDevice
}
}
@Override
public PageResult<BusDevice> myDeviceList(Long userId, Page<Object> page) {
return PageUtil.toPage(busDeviceMapper.myDeviceList(userId, page));
}
@Override
public PageResult<BusDevice> queryAll(BusDeviceQueryCriteria criteria, Page<Object> page){
return PageUtil.toPage(busDeviceMapper.findAll(criteria, page));
@ -113,6 +127,12 @@ public class BusDeviceServiceImpl extends ServiceImpl<BusDeviceMapper, BusDevice
@Override
@Transactional(rollbackFor = Exception.class)
public void create(BusDevice resources) {
String deviceSn = resources.getDeviceSn();
BusDevice device = getByDeviceSn(deviceSn);
if (null != device) {
throw new BadRequestException("设备已存在,请勿重复添加");
}
resources.setDeviceCode((new Random().nextInt(900000) + 100000) + "");
busDeviceMapper.insert(resources);
}
@ -132,18 +152,36 @@ public class BusDeviceServiceImpl extends ServiceImpl<BusDeviceMapper, BusDevice
@Override
public String getQrCode(Long id) {
String code = (new Random().nextInt(900000) + 100000) + "";
String qrCode = weChatService.getQrCode(id, code);
redisUtils.set(CacheKey.QR_CODE + code, id, 1, TimeUnit.DAYS);
// String code = (new Random().nextInt(900000) + 100000) + "";
BusDevice device = busDeviceMapper.selectById(id);
String qrCode = weChatService.getQrCode(id, device.getDeviceCode());
// redisUtils.set(CacheKey.QR_CODE + code, id, 1, TimeUnit.DAYS);
return qrCode;
}
@Override
public void binding(String code) {
if (null == redisUtils.get(CacheKey.QR_CODE + code)) {
throw new BadRequestException("二维码已过期,请联系管理员");
public void bindingDevice(String deviceCode) {
BusDevice device = busDeviceMapper.selectOne(new LambdaQueryWrapper<BusDevice>().eq(BusDevice::getDeviceCode, deviceCode));
if (null == device) {
throw new BadRequestException("二维码有误,未查询到设备信息");
}
Long deviceId = Long.parseLong(redisUtils.get(CacheKey.QR_CODE + code).toString());
JwtUserDto jwtUser = (JwtUserDto) SecurityUtils.getCurrentUser();
User user = jwtUser.getUser();
BusUserDevice udEntity = userDeviceMapper.selectOne(new LambdaQueryWrapper<BusUserDevice>()
.eq(BusUserDevice::getDeviceId, device.getId())
.eq(BusUserDevice::getUserId, user.getId())
);
if (null != udEntity) {
throw new BadRequestException("您已绑定过该设备,请勿重复绑定");
}
BusUserDevice addUserDevice = new BusUserDevice();
addUserDevice.setUserId(user.getId());
addUserDevice.setDeviceId(device.getId());
userDeviceMapper.insert(addUserDevice);
List<BusDeviceCommand> commands = busCommandMapper.selectList(new LambdaQueryWrapper<BusDeviceCommand>().eq(BusDeviceCommand::getDeviceId, device.getId()));
if (commands.isEmpty()) { return; }
List<Long> commandIds = commands.stream().map(BusDeviceCommand::getId).collect(Collectors.toList());
busUserCommandMapper.bindingCommand(user.getId(), commandIds);
}
@Override

View File

@ -17,6 +17,7 @@ package me.zhengjie.modules.system.service.impl;
import me.zhengjie.modules.security.service.UserCacheManager;
import me.zhengjie.modules.security.service.dto.JwtUserDto;
import me.zhengjie.modules.system.domain.BusDevice;
import me.zhengjie.modules.system.domain.BusUser;
import me.zhengjie.modules.system.domain.User;
import me.zhengjie.modules.system.domain.dto.BusTreeVo;
@ -45,7 +46,7 @@ import me.zhengjie.utils.PageResult;
@RequiredArgsConstructor
public class BusUserServiceImpl extends ServiceImpl<BusUserMapper, BusUser> implements BusUserService {
private final BusUserMapper busUserMapper;
@Autowired private BusUserMapper busUserMapper;
@Autowired private UserCacheManager userCacheManager;
@Override

View File

@ -16,7 +16,7 @@ import me.zhengjie.modules.system.service.webstocket.res.WebSocketResPrintInfo;
import me.zhengjie.modules.system.service.webstocket.res.WebSocketResStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@ -26,12 +26,13 @@ import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.*;
@ServerEndpoint("/webSocket")
@Slf4j
@Component
@Order(2)
public class WebSocketServer {
@Autowired private BusDeviceService deviceService;
@ -43,6 +44,8 @@ public class WebSocketServer {
private static final ConcurrentHashMap<String, Session> vueClients = new ConcurrentHashMap<>();
// 第三方WebSocket连接
@Value("${thirdParty.socket.init}")
private Boolean thirdPartyInit;
@Value("${thirdParty.socket.url}")
private String thirdPartyWsUrl;
private static Session thirdPartySession;
@ -53,7 +56,8 @@ public class WebSocketServer {
// 初始化连接第三方WebSocket
@PostConstruct
public void initThirdPartyWebSocket() {
if (null == thirdPartyContainer && null == thirdPartySession) { return; }
if (!thirdPartyInit) { return; }
if (null != thirdPartyContainer && null != thirdPartySession) { return; }
try {
thirdPartyContainer = ContainerProvider.getWebSocketContainer();
thirdPartySession = thirdPartyContainer.connectToServer(ThirdPartyClient.class, URI.create(thirdPartyWsUrl));
@ -138,10 +142,21 @@ public class WebSocketServer {
@ClientEndpoint
public static class ThirdPartyClient {
private Timer timer;
private static final long HEARTBEAT_INTERVAL = 30000; // 30秒心跳间隔
@Autowired @Lazy
private WebSocketServer parentService; // 注入父类Bean
public void callParentInitThirdPartyWebSocket() {
parentService.initThirdPartyWebSocket();
}
@OnOpen
public void onOpen(Session session) {
log.info("【第三方客户端】连接成功");
initDevices();
startHeartbeat();
socketMsg(new SocketMsg("已连接", MsgEnum.CONNECT));
}
@ -155,6 +170,13 @@ public class WebSocketServer {
public void onClose(Session session) {
log.info("【第三方客户端】连接断开");
socketMsg(new SocketMsg("连接断开", MsgEnum.DISCONNECT));
try {
thirdPartySession.close();
thirdPartySession = null;
thirdPartyContainer = null;
callParentInitThirdPartyWebSocket();
startHeartbeat();
} catch (Exception e) {}
}
@OnError
@ -163,6 +185,23 @@ public class WebSocketServer {
socketMsg(new SocketMsg("连接异常", MsgEnum.ERROR));
}
private void startHeartbeat() {
timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
messageSendHandle(WebSocketConfig.PING);
}
}, 0, HEARTBEAT_INTERVAL);
}
private void stopHeartbeat() {
if (timer != null) {
timer.cancel();
timer = null;
}
}
// 收到消息解析做响应的处理
private void messageReceiveHandle(String message) {
// 如果是 [心跳] 检测忽略
@ -181,6 +220,7 @@ public class WebSocketServer {
log.info("<<< 设备【{}】在系统未找到,忽略", deviceSn);
return;
}
BusDevice device = myDeviceService.getByDeviceSn(deviceSn);
// request 说明是vue要发送指令给第三方
if (method == MethodEnum.request) {
WebSocketReqDTO requestReq = JSON.parseObject(message, WebSocketReqDTO.class);
@ -189,7 +229,7 @@ public class WebSocketServer {
return;
}
// todo 发送指令给第三方
CapabilitieEnum command = requestReq.getCommand();
// CapabilitieEnum command = requestReq.getCommand();
// messageSendHandle(null);
}
// 其他说明是第三方上推给我们客服端
@ -212,7 +252,7 @@ public class WebSocketServer {
null
);
BusDevice info = new BusDevice();
info.setDeviceSn(deviceSn);
info.setDeviceCode(device.getDeviceCode());
info.setStatus(CurrentStatusEnum.getEnumByNum(status.getCurrentStatus()).getCode());
info.setPrintStatus(PrintInfoStatusEnum.getEnumByNum(printInfo.getStatus()).getCode());
info.setErrorStatus(ErrorStatusEnum.SDCP_PRINT_ERROR_NONE.getCode());
@ -245,7 +285,7 @@ public class WebSocketServer {
null
);
BusDevice info = new BusDevice();
info.setDeviceSn(deviceSn);
info.setDeviceCode(device.getDeviceCode());
info.setStatus(CurrentStatusEnum.getEnumByNum(status.getCurrentStatus()).getCode());
info.setPrintStatus(PrintInfoStatusEnum.getEnumByNum(printInfo.getStatus()).getCode());
info.setErrorStatus(ErrorStatusEnum.SDCP_PRINT_ERROR_NONE.getCode());

View File

@ -110,16 +110,9 @@ weChat:
# socket
thirdParty:
socket:
init: false
url: ws://127.0.0.1:8000/webSocket
# server:
# # 客户端心跳开关
# clientSwitch: false
# # 间隔时间 单位:秒
# interval: 10
# # 最大错误次数
# maxMissCount: 10
# 文件存储路径
file:
mac:

View File

@ -22,14 +22,21 @@
<result column="update_time" property="updateTime"/>
</resultMap>
<select id="myDeviceList" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from bus_device
where EXISTS (select 1 from bus_user_device ud where ud.user_id = #{userId} and ud.device_id = bus_device.id)
</select>
<update id="updateDeviceStatus">
update bus_device set status = #{status}, print_status = #{printStatus}, error_status = #{errorStatus}, remark = #{remark}
<where><if test="deviceSn != null and deviceSn != ''"> device_sn = #{deviceSn} </if></where>
</update>
<select id="getDevice" resultType="me.zhengjie.modules.system.domain.dto.BusTreeVo">
select CONCAT('d', id) id, 0 pid, CONCAT('品牌:', brand, ' | ', '型号:', model) name, CONCAT(location, '[', IF(type=1, '3D打印机', '摄像头'), ']') remark,
(select count(*) from bus_device_command dc where dc.device_id = bus_device.id) subCount
select CONCAT('d', id) id, 0 pid, CONCAT('品牌', brand, ' | ', '型号:', model) name, CONCAT(location, '[', IF(type=1, '3D打印机', '摄像头'), ']') remark
-- , (select count(*) from bus_device_command dc where dc.device_id = bus_device.id) subCount
from bus_device order by id desc
</select>

View File

@ -17,7 +17,7 @@
</resultMap>
<select id="getUserCommands" resultType="me.zhengjie.modules.system.domain.dto.BusTreeVo">
select CONCAT('d', d.id) id, 0 pid, CONCAT('品牌:', d.brand, ' | ', '型号:', d.model) name, CONCAT(d.location, '[', IF(d.type=1, '3D打印机', '摄像头'), ']') remark from bus_user_device ud inner join bus_device d on ud.device_id = d.id where ud.user_id = #{userId}
select CONCAT('d', d.id) id, 0 pid, CONCAT('品牌', d.brand, ' | ', '型号:', d.model) name, CONCAT(d.location, '[', IF(d.type=1, '3D打印机', '摄像头'), ']') remark from bus_user_device ud inner join bus_device d on ud.device_id = d.id where ud.user_id = #{userId}
union all
select CONCAT('c', dc.id) id, CONCAT('d', dc.device_id) pid, dc.command_name name, dc.description remark from bus_user_device_command udc inner join bus_device_command dc on udc.command_id = dc.id where udc.user_id = #{userId}
</select>