diff --git a/eladmin-web/package.json b/eladmin-web/package.json
index 91a56b6..b603f94 100644
--- a/eladmin-web/package.json
+++ b/eladmin-web/package.json
@@ -5,7 +5,7 @@
"author": "Zheng Jie",
"license": "Apache-2.0",
"scripts": {
- "dev": "SET NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service serve",
+ "dev": "vue-cli-service serve",
"build:prod": "vue-cli-service build",
"build:stage": "vue-cli-service build --mode staging",
"preview": "node build/index.js --preview",
diff --git a/eladmin-web/src/api/bus/busDevice/busDevice.js b/eladmin-web/src/api/bus/busDevice/busDevice.js
new file mode 100644
index 0000000..6e03560
--- /dev/null
+++ b/eladmin-web/src/api/bus/busDevice/busDevice.js
@@ -0,0 +1,48 @@
+import request from '@/utils/request'
+
+export function add(data) {
+ return request({
+ url: 'api/busDevice',
+ method: 'post',
+ data
+ })
+}
+
+export function del(ids) {
+ return request({
+ url: 'api/busDevice/',
+ method: 'delete',
+ data: ids
+ })
+}
+
+export function edit(data) {
+ return request({
+ url: 'api/busDevice',
+ method: 'put',
+ data
+ })
+}
+
+export function getQrCode(id) {
+ return request({
+ url: 'api/busDevice/getQrCode?id=' + id,
+ method: 'get'
+ })
+}
+
+export function getDeviceTree(pid) {
+ return request({
+ url: 'api/busDevice/getDeviceTree?pid=' + pid,
+ method: 'get'
+ })
+}
+
+export function getChild(id) {
+ return request({
+ url: 'api/busDevice/child?id=' + id,
+ method: 'get'
+ })
+}
+
+export default { add, edit, del, getDeviceTree }
diff --git a/eladmin-web/src/api/bus/busDeviceCommand/busDeviceCommand.js b/eladmin-web/src/api/bus/busDeviceCommand/busDeviceCommand.js
new file mode 100644
index 0000000..b716e4f
--- /dev/null
+++ b/eladmin-web/src/api/bus/busDeviceCommand/busDeviceCommand.js
@@ -0,0 +1,27 @@
+import request from '@/utils/request'
+
+export function add(data) {
+ return request({
+ url: 'api/busDeviceCommand',
+ method: 'post',
+ data
+ })
+}
+
+export function del(ids) {
+ return request({
+ url: 'api/busDeviceCommand/',
+ method: 'delete',
+ data: ids
+ })
+}
+
+export function edit(data) {
+ return request({
+ url: 'api/busDeviceCommand',
+ method: 'put',
+ data
+ })
+}
+
+export default { add, edit, del }
diff --git a/eladmin-web/src/api/bus/busUser/busUser.js b/eladmin-web/src/api/bus/busUser/busUser.js
new file mode 100644
index 0000000..1a01a60
--- /dev/null
+++ b/eladmin-web/src/api/bus/busUser/busUser.js
@@ -0,0 +1,42 @@
+import request from '@/utils/request'
+
+export function add(data) {
+ return request({
+ url: 'api/busUser',
+ method: 'post',
+ data
+ })
+}
+
+export function del(ids) {
+ return request({
+ url: 'api/busUser/',
+ method: 'delete',
+ data: ids
+ })
+}
+
+export function edit(data) {
+ return request({
+ url: 'api/busUser',
+ method: 'put',
+ data
+ })
+}
+
+export function updUserCommands(data) {
+ return request({
+ url: 'api/busUser/updUserCommands',
+ method: 'put',
+ data
+ })
+}
+
+export function get(id) {
+ return request({
+ url: 'api/busUser/' + id,
+ method: 'get'
+ })
+}
+
+export default { add, edit, del, get }
diff --git a/eladmin-web/src/components/Crud/UD.operation.vue b/eladmin-web/src/components/Crud/UD.operation.vue
index 87623e7..eeba427 100644
--- a/eladmin-web/src/components/Crud/UD.operation.vue
+++ b/eladmin-web/src/components/Crud/UD.operation.vue
@@ -1,13 +1,13 @@
diff --git a/eladmin-web/src/components/Echarts/PieChart.vue b/eladmin-web/src/components/Echarts/PieChart.vue
index 8c92337..644f658 100644
--- a/eladmin-web/src/components/Echarts/PieChart.vue
+++ b/eladmin-web/src/components/Echarts/PieChart.vue
@@ -77,7 +77,7 @@ export default {
calculable: true,
series: [
{
- name: '案件类型统计',
+ name: '设备指令统计',
type: 'pie',
roseType: 'radius',
radius: [15, 95],
diff --git a/eladmin-web/src/views/bus/busDevice/index.vue b/eladmin-web/src/views/bus/busDevice/index.vue
new file mode 100644
index 0000000..9bbbdfb
--- /dev/null
+++ b/eladmin-web/src/views/bus/busDevice/index.vue
@@ -0,0 +1,178 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 可以截图保存,有效期只有一小时
+
+
+
+
+
+
+
+
+
+
+
+
+ 在线
+ 离线
+ 故障
+
+
+
+
+ 打印机
+ 摄像头
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/eladmin-web/src/views/bus/busDeviceCommand/index.vue b/eladmin-web/src/views/bus/busDeviceCommand/index.vue
new file mode 100644
index 0000000..a2cb1a5
--- /dev/null
+++ b/eladmin-web/src/views/bus/busDeviceCommand/index.vue
@@ -0,0 +1,133 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 控制
+ 查询
+ 校准
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/eladmin-web/src/views/bus/busUser/index.vue b/eladmin-web/src/views/bus/busUser/index.vue
new file mode 100644
index 0000000..9b57515
--- /dev/null
+++ b/eladmin-web/src/views/bus/busUser/index.vue
@@ -0,0 +1,244 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 用户列表
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 正常
+ 禁止
+
+
+
+
+ 未知
+ 男
+ 女
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 设备分配
+
+ 保存
+
+
+
+
+
+
+
+
+
+
+
diff --git a/eladmin-web/src/views/dashboard/PanelGroup.vue b/eladmin-web/src/views/dashboard/PanelGroup.vue
index 1e955e3..a68670c 100644
--- a/eladmin-web/src/views/dashboard/PanelGroup.vue
+++ b/eladmin-web/src/views/dashboard/PanelGroup.vue
@@ -46,7 +46,7 @@
diff --git a/eladmin/eladmin-common/pom.xml b/eladmin/eladmin-common/pom.xml
index c97dde2..e66aba9 100644
--- a/eladmin/eladmin-common/pom.xml
+++ b/eladmin/eladmin-common/pom.xml
@@ -20,5 +20,22 @@
hutool-all
${hutool.version}
+
+
+
+ org.springframework
+ spring-test
+
+
+ com.google.zxing
+ core
+ 3.4.1
+
+
+ com.google.zxing
+ javase
+ 3.4.1
+
+
\ No newline at end of file
diff --git a/eladmin/eladmin-common/src/main/java/me/zhengjie/utils/CRC32Utils.java b/eladmin/eladmin-common/src/main/java/me/zhengjie/utils/CRC32Utils.java
new file mode 100644
index 0000000..39f0770
--- /dev/null
+++ b/eladmin/eladmin-common/src/main/java/me/zhengjie/utils/CRC32Utils.java
@@ -0,0 +1,28 @@
+package me.zhengjie.utils;
+
+import java.util.zip.CRC32;
+
+public class CRC32Utils {
+
+ public static String getUnsignedCRC32(String input) {
+ CRC32 crc32 = new CRC32();
+ crc32.update(input.getBytes());
+ int value = (int) crc32.getValue();
+ // 将int转换为long以避免潜在的符号扩展问题
+ int unsignedValue = value & 0xFFFFFFFF;
+ String hexString = formatCrcToHex(unsignedValue);
+ return "0x" + hexString; // 0x8abd91cc
+ }
+
+ private static String formatCrcToHex(int crc) {
+ // 方法一:采用String.format
+ String format = String.format("%08x", crc);
+ return format.toUpperCase();
+ }
+
+ public static void main(String[] args) {
+ String text = "{\"Name\":\"4KL200URH300.4K\",\"MachineName\":\"3DPLUS\",\"MachineType\":\"Spade\",\"MainboardID\":\"12345678\",\"ProtocolVersion\":\"V3.0.0\",\"FirmwareVersion\":\"V1.0.0\"}";
+ String crc32Value = getUnsignedCRC32(text);
+ System.out.println("CRC-32 (unsigned): " + crc32Value);
+ }
+}
diff --git a/eladmin/eladmin-common/src/main/java/me/zhengjie/utils/CacheKey.java b/eladmin/eladmin-common/src/main/java/me/zhengjie/utils/CacheKey.java
index e8fb086..0a17a5d 100644
--- a/eladmin/eladmin-common/src/main/java/me/zhengjie/utils/CacheKey.java
+++ b/eladmin/eladmin-common/src/main/java/me/zhengjie/utils/CacheKey.java
@@ -63,4 +63,9 @@ public interface CacheKey {
* 数据字典
*/
String DICT_NAME = "dict::name:";
+
+ /**
+ * 二维码
+ */
+ String QR_CODE = "qrCode:";
}
diff --git a/eladmin/eladmin-common/src/main/java/me/zhengjie/utils/FileUtil.java b/eladmin/eladmin-common/src/main/java/me/zhengjie/utils/FileUtil.java
index 77500d6..d4fa138 100644
--- a/eladmin/eladmin-common/src/main/java/me/zhengjie/utils/FileUtil.java
+++ b/eladmin/eladmin-common/src/main/java/me/zhengjie/utils/FileUtil.java
@@ -75,11 +75,11 @@ public class FileUtil extends cn.hutool.core.io.FileUtil {
*/
private static final DecimalFormat DF = new DecimalFormat("0.00");
- public static final String IMAGE = "图片";
- public static final String TXT = "文档";
- public static final String MUSIC = "音乐";
- public static final String VIDEO = "视频";
- public static final String OTHER = "其他";
+ public static final String IMAGE = "image";
+ public static final String TXT = "txt";
+ public static final String MUSIC = "music";
+ public static final String VIDEO = "video";
+ public static final String OTHER = "others";
/**
diff --git a/eladmin/eladmin-common/src/main/java/me/zhengjie/utils/QrCodeUtil.java b/eladmin/eladmin-common/src/main/java/me/zhengjie/utils/QrCodeUtil.java
new file mode 100644
index 0000000..09a1b3c
--- /dev/null
+++ b/eladmin/eladmin-common/src/main/java/me/zhengjie/utils/QrCodeUtil.java
@@ -0,0 +1,82 @@
+package me.zhengjie.utils;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.mock.web.MockMultipartFile;
+import org.springframework.stereotype.Component;
+import com.google.zxing.BarcodeFormat;
+import com.google.zxing.EncodeHintType;
+import com.google.zxing.MultiFormatWriter;
+import com.google.zxing.WriterException;
+import com.google.zxing.common.BitMatrix;
+import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayOutputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+@Slf4j
+@Component
+public class QrCodeUtil {
+
+ //CODE_WIDTH:二维码宽度,单位像素
+ private static final int CODE_WIDTH = 400;
+ //CODE_HEIGHT:二维码高度,单位像素
+ private static final int CODE_HEIGHT = 400;
+ //FRONT_COLOR:二维码前景色,0x000000 表示黑色
+ private static final int FRONT_COLOR = 0x000000;
+ //BACKGROUND_COLOR:二维码背景色,0xFFFFFF 表示白色
+ //演示用 16 进制表示,和前端页面 CSS 的取色是一样的,注意前后景颜色应该对比明显,如常见的黑白
+ private static final int BACKGROUND_COLOR = 0xFFFFFF;
+ //文件类型
+ private static final String FILE_FORMAT = "png";
+
+ public MultipartFile getQrCode(String content, String orderCode) {
+ try {
+ if (StringUtils.isBlank(content)) { return null; }
+ content = content.trim();
+ // 核心代码-生成二维码
+ BufferedImage image = getBufferedImage(content);
+ MultipartFile multipartFile = toMultipartFile(image, orderCode);
+ return multipartFile;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ private static MultipartFile toMultipartFile(BufferedImage image, String orderCode) throws Exception {
+ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ ImageIO.write(image, FILE_FORMAT, byteArrayOutputStream);
+ byte[] byteArray = byteArrayOutputStream.toByteArray();
+ // 使用MockMultipartFile来创建MultipartFile
+ return new MockMultipartFile(orderCode, orderCode + "." + FILE_FORMAT , "image/png", byteArray);
+ }
+
+ //核心代码-生成二维码
+ private static BufferedImage getBufferedImage(String content) throws WriterException {
+ //com.google.zxing.EncodeHintType:编码提示类型,枚举类型
+ Map hints = new HashMap<>();
+ //EncodeHintType.CHARACTER_SET:设置字符编码类型
+ hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
+ //EncodeHintType.ERROR_CORRECTION:设置误差校正
+ //ErrorCorrectionLevel:误差校正等级,L = ~7% correction、M = ~15% correction、Q = ~25% correction、H = ~30% correction
+ //不设置时,默认为 L 等级,等级不一样,生成的图案不同,但扫描的结果是一样的
+ hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
+ //EncodeHintType.MARGIN:设置二维码边距,单位像素,值越小,二维码离四周越近
+ hints.put(EncodeHintType.MARGIN, 1);
+ MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
+ BitMatrix bitMatrix = multiFormatWriter.encode(content, BarcodeFormat.QR_CODE, CODE_WIDTH, CODE_HEIGHT, hints);
+ BufferedImage bufferedImage = new BufferedImage(CODE_WIDTH, CODE_HEIGHT, BufferedImage.TYPE_INT_BGR);
+ for (int x = 0; x < CODE_WIDTH; x++) {
+ for (int y = 0; y < CODE_HEIGHT; y++) {
+ bufferedImage.setRGB(x, y, bitMatrix.get(x, y) ? FRONT_COLOR : BACKGROUND_COLOR);
+ }
+ }
+ return bufferedImage;
+ }
+
+}
diff --git a/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/front/rest/DeviceController.java b/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/front/rest/DeviceController.java
new file mode 100644
index 0000000..f8178ed
--- /dev/null
+++ b/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/front/rest/DeviceController.java
@@ -0,0 +1,43 @@
+package me.zhengjie.modules.front.rest;
+
+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.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;
+import org.springframework.web.bind.annotation.GetMapping;
+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 {
+
+ @Autowired private BusDeviceService busDeviceService;
+
+ @Log("绑定设备")
+ @ApiOperation(value = "绑定设备")
+ @GetMapping(value = "/binding")
+ public ResponseEntity