From 16fc3a4bc23cb9447bd0068b085635b3cc5c4ed6 Mon Sep 17 00:00:00 2001 From: shizhendong Date: Tue, 27 Aug 2024 15:58:41 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20ASW-46=20=E6=96=B0=E5=A2=9E=20device=20?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../device/controller/DeviceController.java | 90 +++++++++++++++ .../asw/module/device/dao/DeviceDao.java | 16 +++ .../asw/module/device/dao/DeviceLogDao.java | 10 ++ .../module/device/entity/DeviceEntity.java | 53 +++++++++ .../module/device/entity/DeviceLogEntity.java | 24 ++++ .../device/service/IDeviceLogService.java | 8 ++ .../module/device/service/IDeviceService.java | 20 ++++ .../service/impl/DeviceLogServiceImpl.java | 15 +++ .../service/impl/DeviceServiceImpl.java | 103 ++++++++++++++++++ .../db/mapper/device/DeviceMapper.xml | 79 ++++++++++++++ .../db/migration/V1.0.01__INIT_TABLES.sql | 47 ++++++++ 11 files changed, 465 insertions(+) create mode 100644 src/main/java/net/geedge/asw/module/device/controller/DeviceController.java create mode 100644 src/main/java/net/geedge/asw/module/device/dao/DeviceDao.java create mode 100644 src/main/java/net/geedge/asw/module/device/dao/DeviceLogDao.java create mode 100644 src/main/java/net/geedge/asw/module/device/entity/DeviceEntity.java create mode 100644 src/main/java/net/geedge/asw/module/device/entity/DeviceLogEntity.java create mode 100644 src/main/java/net/geedge/asw/module/device/service/IDeviceLogService.java create mode 100644 src/main/java/net/geedge/asw/module/device/service/IDeviceService.java create mode 100644 src/main/java/net/geedge/asw/module/device/service/impl/DeviceLogServiceImpl.java create mode 100644 src/main/java/net/geedge/asw/module/device/service/impl/DeviceServiceImpl.java create mode 100644 src/main/resources/db/mapper/device/DeviceMapper.xml diff --git a/src/main/java/net/geedge/asw/module/device/controller/DeviceController.java b/src/main/java/net/geedge/asw/module/device/controller/DeviceController.java new file mode 100644 index 0000000..7942c05 --- /dev/null +++ b/src/main/java/net/geedge/asw/module/device/controller/DeviceController.java @@ -0,0 +1,90 @@ +package net.geedge.asw.module.device.controller; + +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; +import cn.hutool.json.JSONObject; +import cn.hutool.log.Log; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import net.geedge.asw.common.util.R; +import net.geedge.asw.common.util.RCode; +import net.geedge.asw.common.util.T; +import net.geedge.asw.module.device.entity.DeviceEntity; +import net.geedge.asw.module.device.service.IDeviceService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.Map; + +@RestController +@RequestMapping("/api/v1/device") +public class DeviceController { + + private static final Log log = Log.get(); + + + @Autowired + private IDeviceService deviceService; + + @GetMapping("/{id}") + public R detail(@PathVariable("id") String id) { + DeviceEntity entity = deviceService.queryInfo(id); + return R.ok().putData("record", entity); + } + + @GetMapping + public R list(@RequestParam Map params) { + T.VerifyUtil.is(params).notNull() + .and(T.MapUtil.getStr(params, "workspaceId")).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY); + Page page = deviceService.queryList(params); + return R.ok(page); + } + + @PostMapping + public R add(@RequestBody DeviceEntity entity) { + T.VerifyUtil.is(entity).notNull() + .and(entity.getName()).notEmpty(RCode.NAME_CANNOT_EMPTY) + .and(entity.getWorkspaceId()).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY); + + DeviceEntity deviceEntity = deviceService.saveDevice(entity); + return R.ok().putData("id", deviceEntity.getId()); + } + + @DeleteMapping + public R delete(String[] ids) { + T.VerifyUtil.is(ids).notEmpty(); + deviceService.removeDevice(T.ListUtil.of(ids)); + return R.ok(); + } + + @PostMapping("/test") + public R testConnect(@RequestBody DeviceEntity entity) { + T.VerifyUtil.is(entity).notNull() + .and(entity.getParam()).notEmpty(RCode.PARAM_CANNOT_EMPTY); + + JSONObject jsonObject = entity.getParamJSONObject(); + String host = jsonObject.getStr("host"); + String port = jsonObject.getStr("port"); + String token = jsonObject.getStr("token"); + if (T.StrUtil.hasEmpty(host, port, token)) { + return R.error(RCode.PARAM_CANNOT_EMPTY); + } + + try { + HttpRequest request = T.HttpUtil.createGet(String.format("http://%s:%s/api/v1/device/status", host, port)); + request.header("Authorization", token); + HttpResponse response = request.execute(); + log.info("[testConnect] [status: {}]", response.getStatus()); + if (response.getStatus() == 401) { + return R.error(401, "Unauthorized"); + } + if (response.isOk()) { + return R.ok(); + } + } catch (Exception e) { + log.error(e); + return R.error(RCode.ERROR); + } + return R.error(RCode.ERROR); + } + +} \ No newline at end of file diff --git a/src/main/java/net/geedge/asw/module/device/dao/DeviceDao.java b/src/main/java/net/geedge/asw/module/device/dao/DeviceDao.java new file mode 100644 index 0000000..72897da --- /dev/null +++ b/src/main/java/net/geedge/asw/module/device/dao/DeviceDao.java @@ -0,0 +1,16 @@ +package net.geedge.asw.module.device.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import net.geedge.asw.module.device.entity.DeviceEntity; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; +import java.util.Map; + +@Mapper +public interface DeviceDao extends BaseMapper { + + List queryList(Page page, Map params); + +} diff --git a/src/main/java/net/geedge/asw/module/device/dao/DeviceLogDao.java b/src/main/java/net/geedge/asw/module/device/dao/DeviceLogDao.java new file mode 100644 index 0000000..da9ab72 --- /dev/null +++ b/src/main/java/net/geedge/asw/module/device/dao/DeviceLogDao.java @@ -0,0 +1,10 @@ +package net.geedge.asw.module.device.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import net.geedge.asw.module.device.entity.DeviceLogEntity; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface DeviceLogDao extends BaseMapper { + +} diff --git a/src/main/java/net/geedge/asw/module/device/entity/DeviceEntity.java b/src/main/java/net/geedge/asw/module/device/entity/DeviceEntity.java new file mode 100644 index 0000000..e2a9d2e --- /dev/null +++ b/src/main/java/net/geedge/asw/module/device/entity/DeviceEntity.java @@ -0,0 +1,53 @@ +package net.geedge.asw.module.device.entity; + +import cn.hutool.json.JSONObject; +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 com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; +import net.geedge.asw.common.util.T; +import net.geedge.asw.module.sys.entity.SysUserEntity; + +@Data +@TableName("device") +public class DeviceEntity { + + @TableId(type = IdType.ASSIGN_UUID) + private String id; + private String name; + private String location; + private String platform; + private Object param; + private String description; + private Integer status; + + private Long lastHealthCheck; + private Long createTimestamp; + private Long updateTimestamp; + private String createUserId; + private String updateUserId; + + private String workspaceId; + + @TableField(exist = false) + private SysUserEntity createUser; + + @TableField(exist = false) + private SysUserEntity updateUser; + + @TableField(exist = false) + private JSONObject useUser; + + @JsonIgnore + public String getParamStr() { + return null == this.param ? "{}" : T.JSONUtil.toJsonStr(this.param); + } + + @JsonIgnore + public JSONObject getParamJSONObject() { + return null == this.param ? new JSONObject() : T.JSONUtil.parseObj(this.getParamStr()); + } + +} \ No newline at end of file diff --git a/src/main/java/net/geedge/asw/module/device/entity/DeviceLogEntity.java b/src/main/java/net/geedge/asw/module/device/entity/DeviceLogEntity.java new file mode 100644 index 0000000..2c9ec13 --- /dev/null +++ b/src/main/java/net/geedge/asw/module/device/entity/DeviceLogEntity.java @@ -0,0 +1,24 @@ +package net.geedge.asw.module.device.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +@Data +@TableName("device_log") +public class DeviceLogEntity { + + @TableId(type = IdType.ASSIGN_UUID) + private String id; + private String deviceId; + private String userId; + private Integer status; + private String jobId; + + private Long startTimestamp; + private Long endTimestamp; + + private String workspaceId; + +} \ No newline at end of file diff --git a/src/main/java/net/geedge/asw/module/device/service/IDeviceLogService.java b/src/main/java/net/geedge/asw/module/device/service/IDeviceLogService.java new file mode 100644 index 0000000..f910179 --- /dev/null +++ b/src/main/java/net/geedge/asw/module/device/service/IDeviceLogService.java @@ -0,0 +1,8 @@ +package net.geedge.asw.module.device.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import net.geedge.asw.module.device.entity.DeviceLogEntity; + +public interface IDeviceLogService extends IService{ + +} diff --git a/src/main/java/net/geedge/asw/module/device/service/IDeviceService.java b/src/main/java/net/geedge/asw/module/device/service/IDeviceService.java new file mode 100644 index 0000000..4236b3e --- /dev/null +++ b/src/main/java/net/geedge/asw/module/device/service/IDeviceService.java @@ -0,0 +1,20 @@ +package net.geedge.asw.module.device.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import net.geedge.asw.module.device.entity.DeviceEntity; + +import java.util.List; +import java.util.Map; + +public interface IDeviceService extends IService{ + + DeviceEntity queryInfo(String id); + + Page queryList(Map params); + + DeviceEntity saveDevice(DeviceEntity entity); + + void removeDevice(List ids); + +} diff --git a/src/main/java/net/geedge/asw/module/device/service/impl/DeviceLogServiceImpl.java b/src/main/java/net/geedge/asw/module/device/service/impl/DeviceLogServiceImpl.java new file mode 100644 index 0000000..7fd1160 --- /dev/null +++ b/src/main/java/net/geedge/asw/module/device/service/impl/DeviceLogServiceImpl.java @@ -0,0 +1,15 @@ +package net.geedge.asw.module.device.service.impl; + +import cn.hutool.log.Log; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import net.geedge.asw.module.device.dao.DeviceLogDao; +import net.geedge.asw.module.device.entity.DeviceLogEntity; +import net.geedge.asw.module.device.service.IDeviceLogService; +import org.springframework.stereotype.Service; + +@Service +public class DeviceLogServiceImpl extends ServiceImpl implements IDeviceLogService { + + private static final Log log = Log.get(); + +} diff --git a/src/main/java/net/geedge/asw/module/device/service/impl/DeviceServiceImpl.java b/src/main/java/net/geedge/asw/module/device/service/impl/DeviceServiceImpl.java new file mode 100644 index 0000000..e35b1f4 --- /dev/null +++ b/src/main/java/net/geedge/asw/module/device/service/impl/DeviceServiceImpl.java @@ -0,0 +1,103 @@ +package net.geedge.asw.module.device.service.impl; + +import cn.dev33.satoken.stp.StpUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.log.Log; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import net.geedge.asw.common.util.RCode; +import net.geedge.asw.common.util.T; +import net.geedge.asw.module.device.dao.DeviceDao; +import net.geedge.asw.module.device.entity.DeviceEntity; +import net.geedge.asw.module.device.entity.DeviceLogEntity; +import net.geedge.asw.module.device.service.IDeviceLogService; +import net.geedge.asw.module.device.service.IDeviceService; +import net.geedge.asw.module.sys.entity.SysUserEntity; +import net.geedge.asw.module.sys.service.ISysUserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Map; + +@Service +public class DeviceServiceImpl extends ServiceImpl implements IDeviceService { + + private static final Log log = Log.get(); + + @Autowired + private ISysUserService sysUserService; + + @Autowired + private IDeviceLogService deviceLogService; + + @Override + public DeviceEntity queryInfo(String id) { + DeviceEntity device = this.getById(id); + T.VerifyUtil.is(device).notNull(RCode.SYS_RECORD_NOT_FOUND); + + // param + device.setParam(device.getParamJSONObject()); + + SysUserEntity createUser = sysUserService.getById(device.getCreateUserId()); + SysUserEntity updateUser = sysUserService.getById(device.getUpdateUserId()); + device.setCreateUser(createUser); + device.setUpdateUser(updateUser); + + DeviceLogEntity deviceLog = deviceLogService.getOne(new LambdaQueryWrapper().eq(DeviceLogEntity::getDeviceId, device.getId())); + if (null != deviceLog) { + SysUserEntity useUser = sysUserService.getById(deviceLog.getUserId()); + + JSONObject jsonObject = new JSONObject(); + jsonObject.set("id", useUser.getId()); + jsonObject.set("name", useUser.getName()); + jsonObject.set("startTimestamp", deviceLog.getStartTimestamp()); + jsonObject.set("endTimestamp", deviceLog.getEndTimestamp()); + device.setUseUser(jsonObject); + } + return device; + } + + @Override + public Page queryList(Map params) { + Page page = T.PageUtil.getPage(params); + List packageList = this.getBaseMapper().queryList(page, params); + + for (DeviceEntity entity : packageList) { + entity.setParam(entity.getParamJSONObject()); + } + page.setRecords(packageList); + return page; + } + + @Override + public DeviceEntity saveDevice(DeviceEntity entity) { + // param + entity.setParam(entity.getParamStr()); + + // default android + entity.setPlatform(T.StrUtil.emptyToDefault(entity.getPlatform(), "android")); + + entity.setCreateTimestamp(System.currentTimeMillis()); + entity.setUpdateTimestamp(System.currentTimeMillis()); + entity.setCreateUserId(StpUtil.getLoginIdAsString()); + entity.setUpdateUserId(StpUtil.getLoginIdAsString()); + + // save + this.save(entity); + return entity; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void removeDevice(List ids) { + // remove + this.removeBatchByIds(ids); + + // log + deviceLogService.remove(new LambdaQueryWrapper().in(DeviceLogEntity::getDeviceId, ids)); + } + +} \ No newline at end of file diff --git a/src/main/resources/db/mapper/device/DeviceMapper.xml b/src/main/resources/db/mapper/device/DeviceMapper.xml new file mode 100644 index 0000000..a4aec0f --- /dev/null +++ b/src/main/resources/db/mapper/device/DeviceMapper.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/db/migration/V1.0.01__INIT_TABLES.sql b/src/main/resources/db/migration/V1.0.01__INIT_TABLES.sql index 4df4b10..1703503 100644 --- a/src/main/resources/db/migration/V1.0.01__INIT_TABLES.sql +++ b/src/main/resources/db/migration/V1.0.01__INIT_TABLES.sql @@ -456,3 +456,50 @@ CREATE TABLE `workspace_member` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; INSERT INTO `workspace_member` (`workspace_id`, `user_id`, `role_id`, `create_timestamp`, `create_user_id`) VALUES ('1', 'admin', 'admin', 1724291229000, 'admin'); + + +/** + * 新增 device 表 + */ +DROP TABLE IF EXISTS `device`; +CREATE TABLE `device` ( + `id` varchar(64) NOT NULL COMMENT '主键', + `name` varchar(256) NOT NULL DEFAULT '' COMMENT '名称', + `location` varchar(256) NOT NULL DEFAULT '' COMMENT '位置', + `platform` varchar(256) NOT NULL DEFAULT 'android' COMMENT '支持的平台,可选:android', + `param` varchar(1024) NOT NULL DEFAULT '' COMMENT '连接参数', + `description` text NOT NULL DEFAULT '' COMMENT '描述信息', + `status` int(1) NOT NULL DEFAULT 0 COMMENT '状态,0:离线;1:在线', + `last_health_check` bigint(20) NOT NULL DEFAULT -1 COMMENT '最后健康检查时间', + `create_timestamp` bigint(20) NOT NULL COMMENT '创建时间戳', + `update_timestamp` bigint(20) NOT NULL COMMENT '更新时间戳', + `create_user_id` varchar(64) NOT NULL COMMENT '创建人', + `update_user_id` varchar(64) NOT NULL COMMENT '更新人', + `workspace_id` varchar(64) NOT NULL DEFAULT '' COMMENT '工作空间ID', + PRIMARY KEY (`id`) USING BTREE, + KEY `idx_name` (`name`) USING BTREE, + KEY `idx_status` (`status`) USING BTREE, + KEY `idx_workspace_id` (`workspace_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + + +/** + * 新增 device_log 表 + */ +DROP TABLE IF EXISTS `device_log`; +CREATE TABLE `device_log` ( + `id` varchar(64) NOT NULL COMMENT '主键', + `device_id` varchar(64) NOT NULL DEFAULT '' COMMENT '设备id', + `user_id` varchar(64) NOT NULL DEFAULT '' COMMENT '用户id', + `start_timestamp` bigint(20) NOT NULL COMMENT '开始时间', + `end_timestamp` bigint(20) NOT NULL COMMENT '结束时间', + `status` int(1) NOT NULL DEFAULT 1 COMMENT '状态,1:使用中;2:已结束', + `job_id` varchar(64) NOT NULL DEFAULT '' COMMENT '任务id', + `workspace_id` varchar(64) NOT NULL DEFAULT '' COMMENT '工作空间ID', + PRIMARY KEY (`id`) USING BTREE, + KEY `idx_status` (`status`) USING BTREE, + KEY `idx_device_id` (`device_id`) USING BTREE, + KEY `idx_user_id` (`user_id`) USING BTREE, + KEY `idx_job_id` (`job_id`) USING BTREE, + KEY `idx_workspace_id` (`workspace_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;