diff --git a/fys-admin/src/main/java/com/fuyuanshen/app/controller/AppDeviceShareController.java b/fys-admin/src/main/java/com/fuyuanshen/app/controller/AppDeviceShareController.java index 613bb7ea..388c84f7 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/app/controller/AppDeviceShareController.java +++ b/fys-admin/src/main/java/com/fuyuanshen/app/controller/AppDeviceShareController.java @@ -5,6 +5,7 @@ import cn.hutool.core.util.RandomUtil; import com.fuyuanshen.app.domain.bo.AppDeviceShareBo; import com.fuyuanshen.app.domain.vo.AppDeviceShareDetailVo; import com.fuyuanshen.app.domain.vo.AppDeviceShareVo; +import com.fuyuanshen.app.service.AppDeviceShareService; import com.fuyuanshen.app.service.IAppDeviceShareService; import com.fuyuanshen.common.core.constant.Constants; import com.fuyuanshen.common.core.domain.R; @@ -45,7 +46,7 @@ public class AppDeviceShareController extends BaseController { private final IAppDeviceShareService deviceShareService; - private final DeviceShareService appDeviceShareService; + private final AppDeviceShareService appDeviceShareService; /** * 分享管理列表 diff --git a/fys-admin/src/main/java/com/fuyuanshen/app/controller/device/AppDeviceHBYController.java b/fys-admin/src/main/java/com/fuyuanshen/app/controller/device/AppDeviceHBYController.java new file mode 100644 index 00000000..01883072 --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/app/controller/device/AppDeviceHBYController.java @@ -0,0 +1,119 @@ +package com.fuyuanshen.app.controller.device; + +import com.fuyuanshen.app.domain.bo.AppPersonnelInfoBo; +import com.fuyuanshen.app.domain.dto.AppDeviceLogoUploadDto; +import com.fuyuanshen.app.domain.dto.DeviceInstructDto; +import com.fuyuanshen.app.domain.vo.AppDeviceDetailVo; +import com.fuyuanshen.common.core.domain.R; +import com.fuyuanshen.common.core.validate.AddGroup; +import com.fuyuanshen.common.ratelimiter.annotation.FunctionAccessAnnotation; +import com.fuyuanshen.common.ratelimiter.annotation.FunctionAccessBatcAnnotation; +import com.fuyuanshen.common.web.core.BaseController; +import com.fuyuanshen.equipment.domain.dto.AppDeviceSendMsgBo; +import com.fuyuanshen.web.service.device.DeviceBJQBizService; +import jakarta.validation.constraints.NotNull; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +/** + * HBY210设备控制类 + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/app/hby/device") +public class AppDeviceHBYController extends BaseController { + + private final DeviceBJQBizService appDeviceService; + + /** + * 获取设备详细信息 + * + * @param id 主键 + */ + @GetMapping("/{id}") + public R getInfo(@NotNull(message = "主键不能为空") + @PathVariable Long id) { + return R.ok(appDeviceService.getInfo(id)); + } + + /** + * 人员信息登记 + */ + @PostMapping(value = "/registerPersonInfo") +// @FunctionAccessAnnotation("registerPersonInfo") + public R registerPersonInfo(@Validated(AddGroup.class) @RequestBody AppPersonnelInfoBo bo) { + return toAjax(appDeviceService.registerPersonInfo(bo)); + } + + /** + * 发送信息 + */ + @PostMapping(value = "/sendMessage") + @FunctionAccessBatcAnnotation(value = "sendMessage", timeOut = 30, batchMaxTimeOut = 40) + public R sendMessage(@RequestBody AppDeviceSendMsgBo bo) { + return toAjax(appDeviceService.sendMessage(bo)); + } + + /** + * 发送报警信息 + */ + @PostMapping(value = "/sendAlarmMessage") + @FunctionAccessBatcAnnotation(value = "sendAlarmMessage", timeOut = 5, batchMaxTimeOut = 10) + public R sendAlarmMessage(@RequestBody AppDeviceSendMsgBo bo) { + return toAjax(appDeviceService.sendAlarmMessage(bo)); + } + + /** + * 上传设备logo图片 + */ + @PostMapping("/uploadLogo") + @FunctionAccessAnnotation("uploadLogo") + public R upload(@Validated @ModelAttribute AppDeviceLogoUploadDto bo) { + + MultipartFile file = bo.getFile(); + if(file.getSize()>1024*1024*2){ + return R.warn("图片不能大于2M"); + } + appDeviceService.uploadDeviceLogo(bo); + + return R.ok(); + } + + /** + * 灯光模式 + * 0(关灯),1(强光模式),2(弱光模式), 3(爆闪模式), 4(泛光模式) + */ +// @FunctionAccessAnnotation("lightModeSettings") + @PostMapping("/lightModeSettings") + public R lightModeSettings(@RequestBody DeviceInstructDto params) { + // params 转 JSONObject + appDeviceService.lightModeSettings(params); + return R.ok(); + } + + /** + * 灯光亮度设置 + * + */ +// @FunctionAccessAnnotation("lightBrightnessSettings") + @PostMapping("/lightBrightnessSettings") + public R lightBrightnessSettings(@RequestBody DeviceInstructDto params) { + appDeviceService.lightBrightnessSettings(params); + return R.ok(); + } + + /** + * 激光模式设置 + * + */ + @PostMapping("/laserModeSettings") +// @FunctionAccessAnnotation("laserModeSettings") + public R laserModeSettings(@RequestBody DeviceInstructDto params) { + appDeviceService.laserModeSettings(params); + return R.ok(); + } + +} diff --git a/fys-admin/src/main/java/com/fuyuanshen/app/controller/device/AppDeviceXinghanController.java b/fys-admin/src/main/java/com/fuyuanshen/app/controller/device/AppDeviceXinghanController.java index 85fb39a0..15d9df5d 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/app/controller/device/AppDeviceXinghanController.java +++ b/fys-admin/src/main/java/com/fuyuanshen/app/controller/device/AppDeviceXinghanController.java @@ -5,6 +5,7 @@ import com.fuyuanshen.app.domain.dto.AppDeviceLogoUploadDto; import com.fuyuanshen.app.domain.dto.DeviceInstructDto; import com.fuyuanshen.common.core.domain.R; import com.fuyuanshen.common.core.validate.AddGroup; +import com.fuyuanshen.common.log.annotation.Log; import com.fuyuanshen.common.ratelimiter.annotation.FunctionAccessAnnotation; import com.fuyuanshen.common.ratelimiter.annotation.FunctionAccessBatcAnnotation; import com.fuyuanshen.common.web.core.BaseController; @@ -29,6 +30,7 @@ public class AppDeviceXinghanController extends BaseController { /** * 人员信息登记 */ + @Log(title = "xinghan指令-人员信息登记") @PostMapping(value = "/registerPersonInfo") // @FunctionAccessAnnotation("registerPersonInfo") public R registerPersonInfo(@Validated(AddGroup.class) @RequestBody AppPersonnelInfoBo bo) { @@ -38,6 +40,7 @@ public class AppDeviceXinghanController extends BaseController { /** * 发送紧急通知 */ + @Log(title = "xinghan指令-发送紧急通知") @PostMapping(value = "/sendAlarmMessage") @FunctionAccessBatcAnnotation(value = "sendAlarmMessage", timeOut = 5, batchMaxTimeOut = 10) public R sendAlarmMessage(@RequestBody AppDeviceSendMsgBo bo) { @@ -47,6 +50,7 @@ public class AppDeviceXinghanController extends BaseController { /** * 上传设备logo图片 */ + @Log(title = "xinghan指令-上传设备logo图片") @PostMapping("/uploadLogo") @FunctionAccessAnnotation("uploadLogo") public R upload(@Validated @ModelAttribute AppDeviceLogoUploadDto bo) { @@ -64,6 +68,7 @@ public class AppDeviceXinghanController extends BaseController { * 静电预警档位 * 3,2,1,0,分别表示高档/中档/低挡/关闭 */ + @Log(title = "xinghan指令-静电预警档位") @PostMapping("/DetectGradeSettings") public R DetectGradeSettings(@RequestBody DeviceInstructDto params) { // params 转 JSONObject @@ -75,6 +80,7 @@ public class AppDeviceXinghanController extends BaseController { * 照明档位 * 照明档位,2,1,0,分别表示弱光/强光/关闭 */ + @Log(title = "xinghan指令-照明档位") @PostMapping("/LightGradeSettings") public R LightGradeSettings(@RequestBody DeviceInstructDto params) { // params 转 JSONObject @@ -83,9 +89,10 @@ public class AppDeviceXinghanController extends BaseController { } /** - * SOS档位 + * SOS档位s * SOS档位,2,1,0, 分别表示红蓝模式/爆闪模式/关闭 */ + @Log(title = "xinghan指令-SOS档位s") @PostMapping("/SOSGradeSettings") public R SOSGradeSettings(@RequestBody DeviceInstructDto params) { // params 转 JSONObject @@ -97,6 +104,7 @@ public class AppDeviceXinghanController extends BaseController { * 静止报警状态 * 静止报警状态,0-未静止报警,1-正在静止报警。 */ + @Log(title = "xinghan指令-静止报警状态") @PostMapping("/ShakeBitSettings") public R ShakeBitSettings(@RequestBody DeviceInstructDto params) { // params 转 JSONObject diff --git a/fys-admin/src/main/java/com/fuyuanshen/app/domain/dto/AppFileDto.java b/fys-admin/src/main/java/com/fuyuanshen/app/domain/dto/AppFileDto.java index 1a5361ce..a9dc8e5c 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/app/domain/dto/AppFileDto.java +++ b/fys-admin/src/main/java/com/fuyuanshen/app/domain/dto/AppFileDto.java @@ -18,4 +18,9 @@ public class AppFileDto { */ private MultipartFile[] files; + /** + * 多设备id + */ + private Long[] deviceIds; + } diff --git a/fys-admin/src/main/java/com/fuyuanshen/app/service/AppDeviceShareService.java b/fys-admin/src/main/java/com/fuyuanshen/app/service/AppDeviceShareService.java new file mode 100644 index 00000000..44d1ba42 --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/app/service/AppDeviceShareService.java @@ -0,0 +1,262 @@ +package com.fuyuanshen.app.service; + +import com.alibaba.fastjson2.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.fuyuanshen.app.domain.AppDeviceShare; +import com.fuyuanshen.app.domain.AppPersonnelInfo; +import com.fuyuanshen.app.domain.bo.AppDeviceShareBo; +import com.fuyuanshen.app.domain.vo.AppDeviceShareDetailVo; +import com.fuyuanshen.app.domain.vo.AppDeviceShareVo; +import com.fuyuanshen.app.domain.vo.AppPersonnelInfoVo; +import com.fuyuanshen.app.mapper.AppDeviceShareMapper; +import com.fuyuanshen.app.mapper.AppPersonnelInfoMapper; +import com.fuyuanshen.common.core.constant.GlobalConstants; +import com.fuyuanshen.common.core.exception.ServiceException; +import com.fuyuanshen.common.core.utils.StringUtils; +import com.fuyuanshen.common.mybatis.core.page.PageQuery; +import com.fuyuanshen.common.mybatis.core.page.TableDataInfo; +import com.fuyuanshen.common.redis.utils.RedisUtils; +import com.fuyuanshen.common.satoken.utils.AppLoginHelper; +import com.fuyuanshen.equipment.domain.Device; +import com.fuyuanshen.equipment.domain.DeviceType; +import com.fuyuanshen.equipment.mapper.DeviceMapper; +import com.fuyuanshen.equipment.mapper.DeviceTypeMapper; +import com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +import static com.fuyuanshen.common.core.constant.GlobalConstants.GLOBAL_REDIS_KEY; +import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.*; + + +@RequiredArgsConstructor +@Slf4j +@Service +public class AppDeviceShareService { + + private final AppDeviceShareMapper appDeviceShareMapper; + + private final DeviceMapper deviceMapper; + + private final DeviceTypeMapper deviceTypeMapper; + + private final AppPersonnelInfoMapper appPersonnelInfoMapper; + + public TableDataInfo queryPageList(AppDeviceShareBo bo, PageQuery pageQuery) { + Long userId = AppLoginHelper.getUserId(); + bo.setCreateBy(userId); + Page page = new Page<>(pageQuery.getPageNum(), pageQuery.getPageSize()); + Page result = appDeviceShareMapper.selectAppDeviceShareList(bo, page); + List records = result.getRecords(); + records.forEach(AppDeviceShareService::buildDeviceStatus); + return TableDataInfo.build(result); + } + + public TableDataInfo queryWebPageList(AppDeviceShareBo bo, PageQuery pageQuery) { +// Long userId = AppLoginHelper.getUserId(); +// bo.setCreateBy(userId); + Page page = new Page<>(pageQuery.getPageNum(), pageQuery.getPageSize()); + Page result = appDeviceShareMapper.selectWebDeviceShareList(bo, page); + List records = result.getRecords(); + records.forEach(AppDeviceShareService::buildDeviceStatus); + return TableDataInfo.build(result); + } + + private static void buildDeviceStatus(AppDeviceShareVo item) { + // 设备在线状态 + String onlineStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + item.getDeviceImei() + DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX); + if (StringUtils.isNotBlank(onlineStatus)) { + + item.setOnlineStatus(1); + } else { + item.setOnlineStatus(0); + } + String deviceStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + item.getDeviceImei() + DEVICE_STATUS_KEY_PREFIX); + // 获取电量 + if (StringUtils.isNotBlank(deviceStatus)) { + JSONObject jsonObject = JSONObject.parseObject(deviceStatus); + item.setBattery(jsonObject.getString("batteryPercentage")); + } else { + item.setBattery("0"); + } + + String location = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + item.getDeviceImei() + DEVICE_LOCATION_KEY_PREFIX); + if (StringUtils.isNotBlank(location)) { + JSONObject jsonObject = JSONObject.parseObject(location); + item.setLatitude(jsonObject.getString("latitude")); + item.setLongitude(jsonObject.getString("longitude")); + } + + String alarmStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + item.getDeviceImei() + DEVICE_ALARM_KEY_PREFIX); + if (StringUtils.isNotBlank(alarmStatus)) { + item.setAlarmStatus(alarmStatus); + } + } + + public AppDeviceShareDetailVo getInfo(Long id) { + + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(AppDeviceShare::getId, id); + List appDeviceShareVos = appDeviceShareMapper.selectVoList(queryWrapper); + if (appDeviceShareVos == null || appDeviceShareVos.isEmpty()) { + return null; + } + + AppDeviceShareVo shareVo = appDeviceShareVos.get(0); + AppDeviceShareDetailVo shareDetailVo = new AppDeviceShareDetailVo(); + shareDetailVo.setId(shareVo.getId()); + shareDetailVo.setDeviceId(shareVo.getDeviceId()); + shareDetailVo.setPhonenumber(shareVo.getPhonenumber()); + shareDetailVo.setPermission(shareVo.getPermission()); + + Device device = deviceMapper.selectById(shareVo.getDeviceId()); + shareDetailVo.setDeviceName(device.getDeviceName()); + shareDetailVo.setDeviceImei(device.getDeviceImei()); + shareDetailVo.setDeviceMac(device.getDeviceMac()); + + DeviceType deviceType = deviceTypeMapper.selectById(device.getDeviceType()); + if (deviceType != null) { + shareDetailVo.setCommunicationMode(Integer.valueOf(deviceType.getCommunicationMode())); + } + shareDetailVo.setDevicePic(device.getDevicePic()); + shareDetailVo.setTypeName(deviceType.getTypeName()); + shareDetailVo.setBluetoothName(device.getBluetoothName()); + shareDetailVo.setDeviceStatus(device.getDeviceStatus()); + shareDetailVo.setSendMsg(device.getSendMsg()); + + LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); + qw.eq(AppPersonnelInfo::getDeviceId, device.getId()); + List appPersonnelInfoVos = appPersonnelInfoMapper.selectVoList(qw); + if (appPersonnelInfoVos != null && !appPersonnelInfoVos.isEmpty()) { + shareDetailVo.setPersonnelInfo(appPersonnelInfoVos.get(0)); + } + // 设备在线状态 + String onlineStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + device.getDeviceImei() + DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX); + if (StringUtils.isNotBlank(onlineStatus)) { + shareDetailVo.setOnlineStatus(1); + } else { + shareDetailVo.setOnlineStatus(0); + } + String deviceStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + device.getDeviceImei() + DeviceRedisKeyConstants.DEVICE_STATUS_KEY_PREFIX); + // 获取电量 + if (StringUtils.isNotBlank(deviceStatus)) { + JSONObject jsonObject = JSONObject.parseObject(deviceStatus); + shareDetailVo.setMainLightMode(jsonObject.getString("mainLightMode")); + shareDetailVo.setLaserLightMode(jsonObject.getString("laserLightMode")); + shareDetailVo.setBatteryPercentage(jsonObject.getString("batteryPercentage")); + shareDetailVo.setChargeState(jsonObject.getString("chargeState")); + shareDetailVo.setBatteryRemainingTime(jsonObject.getString("batteryRemainingTime")); + } else { + shareDetailVo.setBatteryPercentage("0"); + } + + // 获取经度纬度 + String locationKey = GlobalConstants.GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + device.getDeviceImei() + DeviceRedisKeyConstants.DEVICE_LOCATION_KEY_PREFIX; + String locationInfo = RedisUtils.getCacheObject(locationKey); + if (StringUtils.isNotBlank(locationInfo)) { + JSONObject jsonObject = JSONObject.parseObject(locationInfo); + shareDetailVo.setLongitude(jsonObject.get("longitude").toString()); + shareDetailVo.setLatitude(jsonObject.get("latitude").toString()); + shareDetailVo.setAddress((String) jsonObject.get("address")); + } + + + String alarmStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + device.getDeviceImei() + DEVICE_ALARM_KEY_PREFIX); + if (StringUtils.isNotBlank(alarmStatus)) { + shareDetailVo.setAlarmStatus(alarmStatus); + } + + String lightBrightness = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + device.getDeviceImei() + DEVICE_LIGHT_BRIGHTNESS_KEY_PREFIX); + if (StringUtils.isNotBlank(lightBrightness)) { + shareDetailVo.setLightBrightness(lightBrightness); + } + + return shareDetailVo; + } + + /** + * 校验短信验证码 + */ + private boolean validateSmsCode(String tenantId, String phonenumber, String smsCode) { + String code = RedisUtils.getCacheObject(GlobalConstants.DEVICE_SHARE_CODES_KEY + phonenumber); + if (StringUtils.isBlank(code)) { + throw new ServiceException("验证码失效"); + } + return code.equals(smsCode); + } + + public int deviceShare(AppDeviceShareBo bo) { + boolean flag = validateSmsCode(AppLoginHelper.getTenantId(), bo.getPhonenumber(), bo.getSmsCode()); + if (!flag) { + throw new ServiceException("验证码错误"); + } + + Device device = deviceMapper.selectById(bo.getDeviceId()); + if (device == null) { + throw new ServiceException("设备不存在"); + } + Long userId = AppLoginHelper.getUserId(); + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + lqw.eq(AppDeviceShare::getDeviceId, bo.getDeviceId()); + lqw.eq(AppDeviceShare::getPhonenumber, bo.getPhonenumber()); + Long count = appDeviceShareMapper.selectCount(lqw); + if (count > 0) { + + UpdateWrapper uw = new UpdateWrapper<>(); + uw.eq("device_id", bo.getDeviceId()); + uw.eq("phonenumber", bo.getPhonenumber()); + uw.set("permission", bo.getPermission()); + uw.set("update_by", userId); + uw.set("update_time", new Date()); + + return appDeviceShareMapper.update(uw); + } else { + AppDeviceShare appDeviceShare = new AppDeviceShare(); + appDeviceShare.setDeviceId(bo.getDeviceId()); + appDeviceShare.setPhonenumber(bo.getPhonenumber()); + appDeviceShare.setPermission(bo.getPermission()); + appDeviceShare.setCreateBy(userId); + return appDeviceShareMapper.insert(appDeviceShare); + } + } + + public int remove(Long[] ids) { + return appDeviceShareMapper.deleteByIds(Arrays.asList(ids)); + } + + public TableDataInfo otherDeviceShareList(AppDeviceShareBo bo, PageQuery pageQuery) { + String username = AppLoginHelper.getUsername(); + bo.setPhonenumber(username); + Page page = new Page<>(pageQuery.getPageNum(), pageQuery.getPageSize()); + IPage result = appDeviceShareMapper.otherDeviceShareList(bo, page); + List records = result.getRecords(); + + records.forEach(AppDeviceShareService::buildDeviceStatus); + return TableDataInfo.build(result); + } + + + /** + * 查询设备分享列表(web) + * + * @param bo + * @param pageQuery + * @return + */ + public TableDataInfo queryWebList(AppDeviceShareBo bo, PageQuery pageQuery) { + Page page = new Page<>(pageQuery.getPageNum(), pageQuery.getPageSize()); + Page result = appDeviceShareMapper.selectWebDeviceShareList(bo, page); + List records = result.getRecords(); + records.forEach(AppDeviceShareService::buildDeviceStatus); + return TableDataInfo.build(result); + } + +} diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/listener/RedisKeyExpirationListener.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/listener/RedisKeyExpirationListener.java index 86e669a0..b3f64ecd 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/listener/RedisKeyExpirationListener.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/listener/RedisKeyExpirationListener.java @@ -1,23 +1,44 @@ package com.fuyuanshen.global.mqtt.listener; +import cn.hutool.core.thread.ThreadUtil; +import com.baomidou.lock.LockInfo; +import com.baomidou.lock.LockTemplate; +import com.baomidou.lock.executor.RedissonLockExecutor; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.fuyuanshen.common.core.constant.GlobalConstants; import com.fuyuanshen.common.redis.utils.RedisUtils; +import com.fuyuanshen.equipment.domain.Device; +import com.fuyuanshen.equipment.mapper.DeviceMapper; import com.fuyuanshen.global.mqtt.listener.domain.FunctionAccessStatus; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.data.redis.connection.Message; import org.springframework.data.redis.connection.MessageListener; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.stereotype.Component; import java.time.Duration; -import java.util.HashMap; -import java.util.Map; import static com.fuyuanshen.common.core.constant.GlobalConstants.FUNCTION_ACCESS_KEY; import static com.fuyuanshen.common.core.constant.GlobalConstants.FUNCTION_ACCESS_TIMEOUT_KEY; +import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_KEY_PREFIX; +import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX; @Component @Slf4j public class RedisKeyExpirationListener implements MessageListener { + @Autowired + @Qualifier("threadPoolTaskExecutor") + private ThreadPoolTaskExecutor threadPoolTaskExecutor; + + @Autowired + private DeviceMapper deviceMapper; + + @Autowired + private LockTemplate lockTemplate; + @Override public void onMessage(Message message, byte[] pattern) { String expiredKey = new String(message.getBody()); @@ -26,8 +47,44 @@ public class RedisKeyExpirationListener implements MessageListener { String element = expiredKey.substring(FUNCTION_ACCESS_KEY.length()); handleFunctionAccessExpired(element); } - } + if(expiredKey.endsWith(DEVICE_ONLINE_STATUS_KEY_PREFIX)) { +// threadPoolTaskExecutor.execute(() -> { +// log.info("设备离线:{}", expiredKey); +// String element = expiredKey.substring(GlobalConstants.GLOBAL_REDIS_KEY.length() + DEVICE_KEY_PREFIX.length(), expiredKey.length() - DEVICE_ONLINE_STATUS_KEY_PREFIX.length()); +// UpdateWrapper deviceUpdateWrapper = new UpdateWrapper<>(); +// deviceUpdateWrapper.eq("device_imei", element); +// deviceUpdateWrapper.set("online_status", 0); +// deviceMapper.update(deviceUpdateWrapper); +// }); + threadPoolTaskExecutor.execute(() -> { + log.info("设备离线:{}", expiredKey); + String element = expiredKey.substring(GlobalConstants.GLOBAL_REDIS_KEY.length() + DEVICE_KEY_PREFIX.length(), expiredKey.length() - DEVICE_ONLINE_STATUS_KEY_PREFIX.length()); + + // 构造设备锁键 + String deviceLockKey = GlobalConstants.GLOBAL_REDIS_KEY + ":device_lock:" + element; + + // 尝试获取Redis锁 + LockInfo lockInfo = lockTemplate.lock(deviceLockKey, 30000L, 5000L, RedissonLockExecutor.class); // 30秒过期 + + if (lockInfo != null) { + try { + UpdateWrapper deviceUpdateWrapper = new UpdateWrapper<>(); + deviceUpdateWrapper.eq("device_imei", element); + deviceUpdateWrapper.set("online_status", 0); + deviceMapper.update(deviceUpdateWrapper); + } finally { + //释放锁 + lockTemplate.releaseLock(lockInfo); + } + } else { + log.warn("无法获取设备锁,跳过设备离线处理: {}", element); + } + }); + } + + + } /** * 访问key过期事件 * @param element 批次ID diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq/BjqLocationDataRule.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq/BjqLocationDataRule.java index 0c3bda1f..69637bfd 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq/BjqLocationDataRule.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq/BjqLocationDataRule.java @@ -117,28 +117,28 @@ public class BjqLocationDataRule implements MqttMessageRule { if(StringUtils.isBlank(latitude) || StringUtils.isBlank(longitude)){ return; } - String[] latArr = latitude.split("\\."); - String[] lonArr = longitude.split("\\."); - // 将位置信息存储到Redis中 +// String[] latArr = latitude.split("\\."); +// String[] lonArr = longitude.split("\\."); +// // 将位置信息存储到Redis中 String redisKey = GlobalConstants.GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX+ deviceImei + DEVICE_LOCATION_KEY_PREFIX; - String redisObj = RedisUtils.getCacheObject(redisKey); - JSONObject jsonOBj = JSONObject.parseObject(redisObj); - if(jsonOBj != null){ - String str1 = latArr[0] +"."+ latArr[1].substring(0,4); - String str2 = lonArr[0] +"."+ lonArr[1].substring(0,4); - - String cacheLatitude = jsonOBj.getString("wgs84_latitude"); - String cacheLongitude = jsonOBj.getString("wgs84_longitude"); - String[] latArr1 = cacheLatitude.split("\\."); - String[] lonArr1 = cacheLongitude.split("\\."); - - String cacheStr1 = latArr1[0] +"."+ latArr1[1].substring(0,4); - String cacheStr2 = lonArr1[0] +"."+ lonArr1[1].substring(0,4); - if(str1.equals(cacheStr1) && str2.equals(cacheStr2)){ - log.info("位置信息未发生变化: device={}, lat={}, lon={}", deviceImei, latitude, longitude); - return; - } - } +// String redisObj = RedisUtils.getCacheObject(redisKey); +// JSONObject jsonOBj = JSONObject.parseObject(redisObj); +// if(jsonOBj != null){ +// String str1 = latArr[0] +"."+ latArr[1].substring(0,4); +// String str2 = lonArr[0] +"."+ lonArr[1].substring(0,4); +// +// String cacheLatitude = jsonOBj.getString("wgs84_latitude"); +// String cacheLongitude = jsonOBj.getString("wgs84_longitude"); +// String[] latArr1 = cacheLatitude.split("\\."); +// String[] lonArr1 = cacheLongitude.split("\\."); +// +// String cacheStr1 = latArr1[0] +"."+ latArr1[1].substring(0,4); +// String cacheStr2 = lonArr1[0] +"."+ lonArr1[1].substring(0,4); +// if(str1.equals(cacheStr1) && str2.equals(cacheStr2)){ +// log.info("位置信息未发生变化: device={}, lat={}, lon={}", deviceImei, latitude, longitude); +// return; +// } +// } // 构造位置信息对象 Map locationInfo = new LinkedHashMap<>(); diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/xinghan/XinghanBootLogoRule.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/xinghan/XinghanBootLogoRule.java index 9109b942..2b92071f 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/xinghan/XinghanBootLogoRule.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/xinghan/XinghanBootLogoRule.java @@ -54,7 +54,7 @@ public class XinghanBootLogoRule implements MqttMessageRule { @Override public void execute(MqttRuleContext ctx) { - final String functionAccessKey = FUNCTION_ACCESS_KEY + ctx.getDeviceImei(); + final String functionAccessKey = FUNCTION_ACCESS_KEY + "LOGO:" + ctx.getDeviceImei(); try { MqttXinghanLogoJson payload = objectMapper.convertValue( ctx.getPayloadDict(), MqttXinghanLogoJson.class); diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/xinghan/XinghanDeviceDataRule.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/xinghan/XinghanDeviceDataRule.java index 23f92be0..cf4fbd03 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/xinghan/XinghanDeviceDataRule.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/xinghan/XinghanDeviceDataRule.java @@ -60,7 +60,7 @@ public class XinghanDeviceDataRule implements MqttMessageRule { @Override public void execute(MqttRuleContext context) { - String functionAccess = FUNCTION_ACCESS_KEY + context.getDeviceImei(); + String functionAccess = FUNCTION_ACCESS_KEY + "DATA:" + context.getDeviceImei(); try { // Latitude, longitude //主灯档位,激光灯档位,电量百分比,充电状态,电池剩余续航时间 diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/xinghan/XinghanSendAlarmMessageRule.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/xinghan/XinghanSendAlarmMessageRule.java index 49f82c97..3a4b368e 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/xinghan/XinghanSendAlarmMessageRule.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/xinghan/XinghanSendAlarmMessageRule.java @@ -48,7 +48,7 @@ public class XinghanSendAlarmMessageRule implements MqttMessageRule { @Override public void execute(MqttRuleContext ctx) { - String functionAccess = FUNCTION_ACCESS_KEY + ctx.getDeviceImei(); + String functionAccess = FUNCTION_ACCESS_KEY + "ALARM:" + ctx.getDeviceImei(); try { XinghanSendAlarmMessageRule.MqttXinghanAlarmMsgJson payload = objectMapper.convertValue( ctx.getPayloadDict(), XinghanSendAlarmMessageRule.MqttXinghanAlarmMsgJson.class); diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/xinghan/XinghanSendMsgRule.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/xinghan/XinghanSendMsgRule.java index 6568b57c..d68d18e3 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/xinghan/XinghanSendMsgRule.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/xinghan/XinghanSendMsgRule.java @@ -47,7 +47,7 @@ public class XinghanSendMsgRule implements MqttMessageRule { @Override public void execute(MqttRuleContext ctx) { - String functionAccess = FUNCTION_ACCESS_KEY + ctx.getDeviceImei(); + String functionAccess = FUNCTION_ACCESS_KEY + "MSG:" + ctx.getDeviceImei(); try { XinghanSendMsgRule.MqttXinghanMsgJson payload = objectMapper.convertValue( ctx.getPayloadDict(), XinghanSendMsgRule.MqttXinghanMsgJson.class); diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/queue/MqttMessageQueueConstants.java b/fys-admin/src/main/java/com/fuyuanshen/global/queue/MqttMessageQueueConstants.java index b4eb34d2..392e06bc 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/global/queue/MqttMessageQueueConstants.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/queue/MqttMessageQueueConstants.java @@ -1,6 +1,8 @@ package com.fuyuanshen.global.queue; +import com.fuyuanshen.common.core.constant.GlobalConstants; + public class MqttMessageQueueConstants { - public static final String MQTT_MESSAGE_QUEUE_KEY = "mqtt:message:queue"; - public static final String MQTT_MESSAGE_DEDUP_KEY = "mqtt:message:dedup"; + public static final String MQTT_MESSAGE_QUEUE_KEY = GlobalConstants.GLOBAL_REDIS_KEY + "mqtt:message:queue"; + public static final String MQTT_MESSAGE_DEDUP_KEY = GlobalConstants.GLOBAL_REDIS_KEY + "mqtt:message:dedup"; } diff --git a/fys-admin/src/main/java/com/fuyuanshen/web/controller/device/DeviceChargeDischargeController.java b/fys-admin/src/main/java/com/fuyuanshen/web/controller/device/DeviceChargeDischargeController.java index c8cc77c4..c43890fd 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/web/controller/device/DeviceChargeDischargeController.java +++ b/fys-admin/src/main/java/com/fuyuanshen/web/controller/device/DeviceChargeDischargeController.java @@ -39,7 +39,7 @@ public class DeviceChargeDischargeController extends BaseController { /** * 查询设备充放电记录列表 */ - @SaCheckPermission("equipment:chargeDischarge:list") + // @SaCheckPermission("equipment:chargeDischarge:list") @GetMapping("/list") public TableDataInfo list(DeviceChargeDischargeBo bo, PageQuery pageQuery) { return deviceChargeDischargeService.queryPageList(bo, pageQuery); @@ -48,7 +48,7 @@ public class DeviceChargeDischargeController extends BaseController { /** * 设备充放电记录列表 */ - @SaCheckPermission("equipment:chargeDischarge:export") + // @SaCheckPermission("equipment:chargeDischarge:export") @Log(title = "设备充放电记录", businessType = BusinessType.EXPORT) @PostMapping("/export") public void export(DeviceChargeDischargeBo bo, HttpServletResponse response) { @@ -61,7 +61,7 @@ public class DeviceChargeDischargeController extends BaseController { * * @param id 主键 */ - @SaCheckPermission("equipment:chargeDischarge:query") + // @SaCheckPermission("equipment:chargeDischarge:query") @GetMapping("/{id}") public R getInfo(@NotNull(message = "主键不能为空") @PathVariable Long id) { @@ -71,7 +71,7 @@ public class DeviceChargeDischargeController extends BaseController { /** * 新增设备充放电记录 */ - @SaCheckPermission("equipment:chargeDischarge:add") + // @SaCheckPermission("equipment:chargeDischarge:add") @Log(title = "设备充放电记录", businessType = BusinessType.INSERT) @RepeatSubmit() @PostMapping() @@ -82,7 +82,7 @@ public class DeviceChargeDischargeController extends BaseController { /** * 修改设备充放电记录 */ - @SaCheckPermission("equipment:chargeDischarge:edit") + // @SaCheckPermission("equipment:chargeDischarge:edit") @Log(title = "设备充放电记录", businessType = BusinessType.UPDATE) @RepeatSubmit() @PutMapping() @@ -95,11 +95,13 @@ public class DeviceChargeDischargeController extends BaseController { * * @param ids 主键串 */ - @SaCheckPermission("equipment:chargeDischarge:remove") + // @SaCheckPermission("equipment:chargeDischarge:remove") @Log(title = "设备充放电记录", businessType = BusinessType.DELETE) @DeleteMapping("/{ids}") public R remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) { return toAjax(deviceChargeDischargeService.deleteWithValidByIds(List.of(ids), true)); } + + } diff --git a/fys-admin/src/main/java/com/fuyuanshen/web/controller/device/DeviceDebugController.java b/fys-admin/src/main/java/com/fuyuanshen/web/controller/device/DeviceDebugController.java new file mode 100644 index 00000000..d098e8c6 --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/web/controller/device/DeviceDebugController.java @@ -0,0 +1,160 @@ +package com.fuyuanshen.web.controller.device; + +import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; +import com.fuyuanshen.app.domain.bo.AppOperationVideoBo; +import com.fuyuanshen.app.domain.dto.AppDeviceLogoUploadDto; +import com.fuyuanshen.app.domain.dto.AppFileDto; +import com.fuyuanshen.common.core.domain.R; +import com.fuyuanshen.common.core.exception.ServiceException; +import com.fuyuanshen.common.log.annotation.Log; +import com.fuyuanshen.common.log.enums.BusinessType; +import com.fuyuanshen.common.mybatis.core.page.PageQuery; +import com.fuyuanshen.common.mybatis.core.page.TableDataInfo; +import com.fuyuanshen.common.ratelimiter.annotation.FunctionAccessAnnotation; +import com.fuyuanshen.common.web.core.BaseController; +import com.fuyuanshen.equipment.domain.query.DeviceQueryCriteria; +import com.fuyuanshen.equipment.domain.vo.AppDeviceVo; +import com.fuyuanshen.equipment.domain.vo.WebDeviceVo; +import com.fuyuanshen.web.domain.Dto.DeviceDebugEditDto; +import com.fuyuanshen.web.domain.Dto.DeviceDebugLogoUploadDto; +import com.fuyuanshen.web.domain.vo.DeviceInfoVo; +import com.fuyuanshen.web.service.device.DeviceBizService; +import com.fuyuanshen.web.service.device.DeviceDebugService; +import com.fuyuanshen.web.service.device.DeviceXinghanBizService; +import io.swagger.v3.oas.annotations.Operation; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * 联调中心 + * + * @author Lion Li + * @date 2025-08-28 + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("api/device/debug") +public class DeviceDebugController extends BaseController { + + private final DeviceBizService appDeviceService; + private final DeviceXinghanBizService deviceXinghanBizService; + private final DeviceDebugService deviceDebugService; + + /** + * 查询设备列表 + */ + @GetMapping("/list") + public TableDataInfo list(DeviceQueryCriteria bo, PageQuery pageQuery) { + return appDeviceService.queryWebDeviceList(bo, pageQuery); + } + + /** + * 上传文件 + */ + @Log(title = "批量上传文件") + @PostMapping("/addFile") + public R uploadFile(@Validated @ModelAttribute AppFileDto bo) throws IOException { + return toAjax(deviceDebugService.addFileHash(bo)); + } + + /** + * 操作视频添加 + */ + @Log(title = "批量添加操作视频") + @PostMapping("/addVideo") + public R addOperationVideo(@RequestBody AppOperationVideoBo bo) { + return toAjax(deviceDebugService.addVideoList(bo)); + } + + /** + * 上传设备logo图片 + */ + @Log(title = "批量上传设备logo图片") + @PostMapping("/addLogo") + @FunctionAccessAnnotation("uploadLogo") + public R uploadLogo670(@Validated @ModelAttribute DeviceDebugLogoUploadDto bo) { + + MultipartFile file = bo.getFile(); + if(file.getSize()>1024*1024*2){ + return R.warn("图片不能大于2M"); + } + deviceXinghanBizService.uploadDeviceLogoBatch(bo); + return R.ok(); + } + + /** + * 设备详情 + */ + @Operation(summary = "设备详情") + @GetMapping(value = "/detail/{id}") + public R getDeviceInfo(@PathVariable Long id) { + return R.ok(deviceDebugService.getDeviceInfo(id)); + } + + /** + * 修改设备联调信息 + */ + @Log(title = "修改设备联调信息") + @PostMapping("/editDebug") + public R editDeviceDebug(@Validated @ModelAttribute DeviceDebugEditDto bo) throws Exception { + // 1. 基础参数必填校验 + validateDeviceDebugEdit(bo); + + // 修改上传设备说明 + if (bo.getExplanationFiles() != null) { + AppFileDto appFileDto = new AppFileDto(); + appFileDto.setDeviceIds(new Long[]{ bo.getDeviceId() }); + appFileDto.setFileType(1L); + appFileDto.setFiles(bo.getExplanationFiles()); + deviceDebugService.addFileHash(appFileDto); + } + // 修改上传设备参数 + if (bo.getParameterFiles() != null) { + AppFileDto appFileDto = new AppFileDto(); + appFileDto.setDeviceIds(new Long[]{ bo.getDeviceId() }); + appFileDto.setFileType(2L); + appFileDto.setFiles(bo.getParameterFiles()); + deviceDebugService.addFileHash(appFileDto); + } + // 修改操作视频 + if (bo.getVideoUrl().isEmpty()) { + AppOperationVideoBo appOperationVideoBo = new AppOperationVideoBo(); + appOperationVideoBo.setDeviceIds(new Long[]{ bo.getDeviceId() }); + appOperationVideoBo.setVideoUrl(bo.getVideoUrl()); + deviceDebugService.addVideoList(appOperationVideoBo); + } + // 修改设备logo 每个型号设备走不同协议无法共用同一个上传 +// if(bo.getLogoFile() != null){ +// MultipartFile file = bo.getLogoFile(); +// if(file.getSize()>1024*1024*2){ +// return R.warn("图片不能大于2M"); +// } +// AppDeviceLogoUploadDto bo1 = new AppDeviceLogoUploadDto(); +// bo1.setDeviceId(bo.getDeviceId()); +// bo1.setDeviceImei(bo.getDeviceImei()); +// bo1.setFile(file); +// deviceXinghanBizService.uploadDeviceLogo(bo1); +// } + + return R.ok(); + } + + /* ------------------ 私有复用 ------------------ */ + + private void validateDeviceDebugEdit(DeviceDebugEditDto bo) { + if (bo.getDeviceId() == null || bo.getDeviceId() == 0L) { + throw new ServiceException("请选择设备"); + } +// if (bo.getDeviceImei().isEmpty()) { +// throw new ServiceException("设备 IMEI 不能为空"); +// } + } + +} diff --git a/fys-admin/src/main/java/com/fuyuanshen/web/controller/device/DeviceShareController.java b/fys-admin/src/main/java/com/fuyuanshen/web/controller/device/DeviceShareController.java index e623e9d6..ce2cc2be 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/web/controller/device/DeviceShareController.java +++ b/fys-admin/src/main/java/com/fuyuanshen/web/controller/device/DeviceShareController.java @@ -1,18 +1,32 @@ package com.fuyuanshen.web.controller.device; +import cn.dev33.satoken.annotation.SaIgnore; +import cn.hutool.core.util.RandomUtil; import com.fuyuanshen.app.domain.bo.AppDeviceShareBo; import com.fuyuanshen.app.domain.vo.AppDeviceShareVo; +import com.fuyuanshen.common.core.constant.Constants; +import com.fuyuanshen.common.core.domain.R; +import com.fuyuanshen.common.core.validate.AddGroup; +import com.fuyuanshen.common.idempotent.annotation.RepeatSubmit; import com.fuyuanshen.common.mybatis.core.page.PageQuery; import com.fuyuanshen.common.mybatis.core.page.TableDataInfo; +import com.fuyuanshen.common.ratelimiter.annotation.RateLimiter; +import com.fuyuanshen.common.redis.utils.RedisUtils; import com.fuyuanshen.common.web.core.BaseController; -import com.fuyuanshen.equipment.domain.bo.DeviceAlarmBo; -import com.fuyuanshen.equipment.domain.vo.DeviceAlarmVo; import com.fuyuanshen.web.service.DeviceShareService; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotEmpty; import lombok.RequiredArgsConstructor; +import org.dromara.sms4j.api.SmsBlend; +import org.dromara.sms4j.api.entity.SmsResponse; +import org.dromara.sms4j.core.factory.SmsFactory; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; + +import java.time.Duration; +import java.util.LinkedHashMap; + +import static com.fuyuanshen.common.core.constant.GlobalConstants.DEVICE_SHARE_CODES_KEY; /** * 设备分享管理 @@ -26,18 +40,66 @@ import org.springframework.web.bind.annotation.RestController; @RequestMapping("api/equipment/share") public class DeviceShareController extends BaseController { - private final DeviceShareService appDeviceShareService; + private final DeviceShareService deviceShareService; /** - *查询设备分享列表(web) + * 分享管理列表 */ - // @SaCheckPermission("equipment:alarm:list") - @GetMapping("/list") + @GetMapping("/deviceShareList") public TableDataInfo list(AppDeviceShareBo bo, PageQuery pageQuery) { - return appDeviceShareService.queryWebList(bo, pageQuery); + return deviceShareService.queryWebPageList(bo, pageQuery); } + /** + * 新增设备分享 + */ + @RepeatSubmit() + @PostMapping("/deviceShare") + public R deviceShare(@Validated(AddGroup.class) @RequestBody AppDeviceShareBo bo) { + return toAjax(deviceShareService.deviceShare(bo)); + } + /** + * 权限管理 + */ + @RepeatSubmit() + @PostMapping("/permission") + public R permission(@Validated(AddGroup.class) @RequestBody AppDeviceShareBo bo) { + return toAjax(deviceShareService.deviceShare(bo)); + } + + /** + * 移除分享用户 + * + * @param ids 主键串 + */ + @DeleteMapping("/{ids}") + public R remove(@NotEmpty(message = "主键不能为空") + @PathVariable Long[] ids) { + return toAjax(deviceShareService.remove(ids)); + } + + /** + * 短信验证码 + * + * @param phonenumber 用户手机号 + */ + @SaIgnore + @RateLimiter(key = "#phonenumber", time = 60, count = 1) + @GetMapping("/sms/code") + public R smsCode(@NotBlank(message = "{user.phonenumber.not.blank}") String phonenumber) { + String key = DEVICE_SHARE_CODES_KEY + phonenumber; + String code = RandomUtil.randomNumbers(4); + RedisUtils.setCacheObject(key, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION)); + LinkedHashMap map = new LinkedHashMap<>(1); + map.put("code", code); + SmsBlend smsBlend = SmsFactory.getSmsBlend("config1"); + SmsResponse smsResponse = smsBlend.sendMessage(phonenumber, map); + if (!smsResponse.isSuccess()) { + return R.fail(smsResponse.getData().toString()); + } + return R.ok(); + } } diff --git a/fys-admin/src/main/java/com/fuyuanshen/web/controller/device/DeviceXinghanController.java b/fys-admin/src/main/java/com/fuyuanshen/web/controller/device/DeviceXinghanController.java new file mode 100644 index 00000000..8600c788 --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/web/controller/device/DeviceXinghanController.java @@ -0,0 +1,106 @@ +package com.fuyuanshen.web.controller.device; + +import com.fuyuanshen.app.domain.bo.AppPersonnelInfoBo; +import com.fuyuanshen.app.domain.dto.AppDeviceLogoUploadDto; +import com.fuyuanshen.app.domain.dto.DeviceInstructDto; +import com.fuyuanshen.common.core.domain.R; +import com.fuyuanshen.common.core.validate.AddGroup; +import com.fuyuanshen.common.ratelimiter.annotation.FunctionAccessAnnotation; +import com.fuyuanshen.common.ratelimiter.annotation.FunctionAccessBatcAnnotation; +import com.fuyuanshen.common.web.core.BaseController; +import com.fuyuanshen.equipment.domain.dto.AppDeviceSendMsgBo; +import com.fuyuanshen.web.service.device.DeviceXinghanBizService; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +/** + * 设备控制类 HBY670 + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/api/xinghan/device") +public class DeviceXinghanController extends BaseController { + + private final DeviceXinghanBizService deviceXinghanBizService; + + /** + * 人员信息登记 + */ + @PostMapping(value = "/registerPersonInfo") +// @FunctionAccessAnnotation("registerPersonInfo") + public R registerPersonInfo(@Validated(AddGroup.class) @RequestBody AppPersonnelInfoBo bo) { + return toAjax(deviceXinghanBizService.registerPersonInfo(bo)); + } + + /** + * 发送紧急通知 + */ + @PostMapping(value = "/sendAlarmMessage") + @FunctionAccessBatcAnnotation(value = "sendAlarmMessage", timeOut = 5, batchMaxTimeOut = 10) + public R sendAlarmMessage(@RequestBody AppDeviceSendMsgBo bo) { + return toAjax(deviceXinghanBizService.sendAlarmMessage(bo)); + } + + /** + * 上传设备logo图片 + */ + @PostMapping("/uploadLogo") + @FunctionAccessAnnotation("uploadLogo") + public R upload(@Validated @ModelAttribute AppDeviceLogoUploadDto bo) { + + MultipartFile file = bo.getFile(); + if(file.getSize()>1024*1024*2){ + return R.warn("图片不能大于2M"); + } + deviceXinghanBizService.uploadDeviceLogo(bo); + + return R.ok(); + } + + /** + * 静电预警档位 + * 3,2,1,0,分别表示高档/中档/低挡/关闭 + */ + @PostMapping("/DetectGradeSettings") + public R DetectGradeSettings(@RequestBody DeviceInstructDto params) { + // params 转 JSONObject + deviceXinghanBizService.upDetectGradeSettings(params); + return R.ok(); + } + + /** + * 照明档位 + * 照明档位,2,1,0,分别表示弱光/强光/关闭 + */ + @PostMapping("/LightGradeSettings") + public R LightGradeSettings(@RequestBody DeviceInstructDto params) { + // params 转 JSONObject + deviceXinghanBizService.upLightGradeSettings(params); + return R.ok(); + } + + /** + * SOS档位 + * SOS档位,2,1,0, 分别表示红蓝模式/爆闪模式/关闭 + */ + @PostMapping("/SOSGradeSettings") + public R SOSGradeSettings(@RequestBody DeviceInstructDto params) { + // params 转 JSONObject + deviceXinghanBizService.upSOSGradeSettings(params); + return R.ok(); + } + + /** + * 静止报警状态 + * 静止报警状态,0-未静止报警,1-正在静止报警。 + */ + @PostMapping("/ShakeBitSettings") + public R ShakeBitSettings(@RequestBody DeviceInstructDto params) { + // params 转 JSONObject + deviceXinghanBizService.upShakeBitSettings(params); + return R.ok(); + } +} diff --git a/fys-admin/src/main/java/com/fuyuanshen/web/controller/device/HomePageController.java b/fys-admin/src/main/java/com/fuyuanshen/web/controller/device/HomePageController.java index b8786bf7..8052c39f 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/web/controller/device/HomePageController.java +++ b/fys-admin/src/main/java/com/fuyuanshen/web/controller/device/HomePageController.java @@ -1,17 +1,16 @@ package com.fuyuanshen.web.controller.device; import com.fuyuanshen.common.core.domain.R; +import com.fuyuanshen.equipment.domain.vo.AlarmInformationVo; import com.fuyuanshen.equipment.domain.vo.DataOverviewVo; +import com.fuyuanshen.equipment.domain.vo.EquipmentClassificationVo; import com.fuyuanshen.equipment.service.DeviceService; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import java.util.Arrays; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; +import java.util.*; /** * 首页数据 @@ -39,29 +38,38 @@ public class HomePageController { } - - - // 获取设备使用数据 - @GetMapping("/{deviceId}") - public Map getUsageData( - @PathVariable String deviceId, - @RequestParam String range) { - - Map response = new HashMap<>(); - - if ("halfYear".equals(range)) { - response.put("months", Arrays.asList("1月", "2月", "3月", "4月", "5月", "6月")); - response.put("data", Arrays.asList(45, 52, 38, 60, 56, 48)); - } else if ("oneYear".equals(range)) { - response.put("months", Arrays.asList("7月", "8月", "9月", "10月", "11月", "12月", - "1月", "2月", "3月", "4月", "5月", "6月")); - response.put("data", Arrays.asList(42, 38, 45, 48, 52, 55, 45, 52, 38, 60, 56, 48)); - } - - response.put("deviceId", deviceId); - response.put("range", range); - response.put("lastUpdate", new Date()); - - return response; + /** + * 获取 设备分类 + * DataOverview + */ + @GetMapping("/getEquipmentClassification") + public R getEquipmentClassification() { + return R.ok(deviceService.getEquipmentClassification()); } + + + /** + * 获取 报警信息 + * DataOverview + */ + @GetMapping("/getAlarmInformation") + public R getAlarmInformation() { + return R.ok(deviceService.getAlarmInformation()); + } + + + /** + * 获取设备使用数据 + * + * @param deviceTypeId 设备ID (可选) + * @param range 时间范围 1:半年 2:一年 + * @return 每月使用数据列表 + */ + @GetMapping("/getEquipmentUsageData/{range}") + public R>> getEquipmentUsageData(@PathVariable Integer range, + @RequestParam(required = false) Long deviceTypeId) { + return R.ok(deviceService.getEquipmentUsageData(deviceTypeId, range)); + } + + } diff --git a/fys-admin/src/main/java/com/fuyuanshen/web/controller/device/WEBDeviceController.java b/fys-admin/src/main/java/com/fuyuanshen/web/controller/device/WEBDeviceController.java index c9580591..aa1fc9f4 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/web/controller/device/WEBDeviceController.java +++ b/fys-admin/src/main/java/com/fuyuanshen/web/controller/device/WEBDeviceController.java @@ -3,6 +3,8 @@ package com.fuyuanshen.web.controller.device; import com.fuyuanshen.app.domain.AppPersonnelInfoRecords; import com.fuyuanshen.common.core.domain.R; +import com.fuyuanshen.common.mybatis.core.page.PageQuery; +import com.fuyuanshen.common.mybatis.core.page.TableDataInfo; import com.fuyuanshen.common.web.core.BaseController; import com.fuyuanshen.equipment.domain.DeviceLog; import com.fuyuanshen.equipment.domain.vo.DeviceAlarmVo; @@ -65,7 +67,7 @@ public class WEBDeviceController extends BaseController { * @param deviceId * @return */ - @Operation(summary = "设备详情") + @Operation(summary = "设备用户详情") @GetMapping(value = "/getDeviceUser/{deviceId}") public R> getDeviceUser(@PathVariable Long deviceId) { List device = deviceService.getDeviceUser(deviceId); @@ -77,13 +79,18 @@ public class WEBDeviceController extends BaseController { * 设备操作记录 * * @param deviceId + * @param startTime 开始时间 + * @param endTime 结束时间 * @return */ @Operation(summary = "设备操作记录") @GetMapping(value = "/getOperationRecord/{deviceId}") - public R> getOperationRecord(@PathVariable Long deviceId) { - List device = deviceService.getOperationRecord(deviceId); - return R.ok(device); + public TableDataInfo getOperationRecord(@PathVariable Long deviceId, + @RequestParam(required = false) String startTime, + @RequestParam(required = false) String endTime, + PageQuery pageQuery) { + TableDataInfo device = deviceService.getOperationRecord(deviceId, startTime, endTime,pageQuery); + return device; } @@ -91,13 +98,17 @@ public class WEBDeviceController extends BaseController { * 设备告警记录 * * @param deviceId + * @param startTime 开始时间 + * @param endTime 结束时间 * @return */ @Operation(summary = "设备告警记录") @GetMapping(value = "/getAlarmRecord/{deviceId}") - public R> getAlarmRecord(@PathVariable Long deviceId) { - List device = deviceService.getAlarmRecord(deviceId); - return R.ok(device); + public TableDataInfo getAlarmRecord(@PathVariable Long deviceId, + @RequestParam(required = false) String startTime, + @RequestParam(required = false) String endTime, + PageQuery pageQuery) { + return deviceService.getAlarmRecord(deviceId, startTime, endTime, pageQuery); } diff --git a/fys-admin/src/main/java/com/fuyuanshen/web/domain/Dto/DeviceDebugEditDto.java b/fys-admin/src/main/java/com/fuyuanshen/web/domain/Dto/DeviceDebugEditDto.java new file mode 100644 index 00000000..9eb34174 --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/web/domain/Dto/DeviceDebugEditDto.java @@ -0,0 +1,34 @@ +package com.fuyuanshen.web.domain.Dto; + +import lombok.Data; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; + +@Data +public class DeviceDebugEditDto { + /** + * 设备主键列表 + */ + private Long deviceId; + /** + * 设备 IMEI + */ + //private String deviceImei; + /** + * 上传 logo 图片 + */ + //private MultipartFile LogoFile; // 同一张图 + /** + * 参数文件 + */ + private MultipartFile[] parameterFiles; + /** + * 说明文件 + */ + private MultipartFile[] explanationFiles; + /** + * 视频链接 + */ + private String videoUrl; +} diff --git a/fys-admin/src/main/java/com/fuyuanshen/web/domain/Dto/DeviceDebugLogoUploadDto.java b/fys-admin/src/main/java/com/fuyuanshen/web/domain/Dto/DeviceDebugLogoUploadDto.java new file mode 100644 index 00000000..5f4ebecf --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/web/domain/Dto/DeviceDebugLogoUploadDto.java @@ -0,0 +1,18 @@ +package com.fuyuanshen.web.domain.Dto; + +import lombok.Data; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; + +@Data +public class DeviceDebugLogoUploadDto { + /** + * 设备主键列表 + */ + private List deviceIds; // 设备主键列表 + /** + * 上传 图片 + */ + private MultipartFile file; // 同一张图 +} diff --git a/fys-admin/src/main/java/com/fuyuanshen/web/domain/vo/DeviceInfoVo.java b/fys-admin/src/main/java/com/fuyuanshen/web/domain/vo/DeviceInfoVo.java new file mode 100644 index 00000000..e0c637b5 --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/web/domain/vo/DeviceInfoVo.java @@ -0,0 +1,27 @@ +package com.fuyuanshen.web.domain.vo; + +import com.fuyuanshen.app.domain.vo.AppBusinessFileVo; +import com.fuyuanshen.app.domain.vo.AppFileVo; +import com.fuyuanshen.app.domain.vo.AppOperationVideoVo; +import com.fuyuanshen.equipment.domain.Device; +import com.fuyuanshen.equipment.domain.vo.AppDeviceVo; +import lombok.Data; + +import java.util.List; + +/** + * 设备信息 视图对象 + * + * @author Michelle.Chung + */ +@Data +public class DeviceInfoVo { + /** + * 设备业务文件 + */ + private List appBusinessFileVoList; + /** + * 设备操作视频 + */ + private List appOperationVideoVoList; +} diff --git a/fys-admin/src/main/java/com/fuyuanshen/web/service/DeviceShareService.java b/fys-admin/src/main/java/com/fuyuanshen/web/service/DeviceShareService.java index 9e493b14..42204bb7 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/web/service/DeviceShareService.java +++ b/fys-admin/src/main/java/com/fuyuanshen/web/service/DeviceShareService.java @@ -2,15 +2,18 @@ package com.fuyuanshen.web.service; import com.alibaba.fastjson2.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.fuyuanshen.app.domain.AppDeviceBindRecord; import com.fuyuanshen.app.domain.AppDeviceShare; import com.fuyuanshen.app.domain.AppPersonnelInfo; import com.fuyuanshen.app.domain.bo.AppDeviceShareBo; import com.fuyuanshen.app.domain.vo.AppDeviceShareDetailVo; import com.fuyuanshen.app.domain.vo.AppDeviceShareVo; import com.fuyuanshen.app.domain.vo.AppPersonnelInfoVo; +import com.fuyuanshen.app.mapper.AppDeviceBindRecordMapper; import com.fuyuanshen.app.mapper.AppDeviceShareMapper; import com.fuyuanshen.app.mapper.AppPersonnelInfoMapper; import com.fuyuanshen.common.core.constant.GlobalConstants; @@ -50,6 +53,8 @@ public class DeviceShareService { private final AppPersonnelInfoMapper appPersonnelInfoMapper; + private final AppDeviceBindRecordMapper appDeviceBindRecordMapper; + public TableDataInfo queryPageList(AppDeviceShareBo bo, PageQuery pageQuery) { Long userId = AppLoginHelper.getUserId(); bo.setCreateBy(userId); @@ -60,6 +65,16 @@ public class DeviceShareService { return TableDataInfo.build(result); } + public TableDataInfo queryWebPageList(AppDeviceShareBo bo, PageQuery pageQuery) { +// Long userId = AppLoginHelper.getUserId(); +// bo.setCreateBy(userId); + Page page = new Page<>(pageQuery.getPageNum(), pageQuery.getPageSize()); + Page result = appDeviceShareMapper.selectWebDeviceShareList(bo, page); + List records = result.getRecords(); + records.forEach(DeviceShareService::buildDeviceStatus); + return TableDataInfo.build(result); + } + private static void buildDeviceStatus(AppDeviceShareVo item) { // 设备在线状态 String onlineStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + item.getDeviceImei() + DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX); @@ -175,7 +190,7 @@ public class DeviceShareService { /** * 校验短信验证码 */ - private boolean validateSmsCode(String tenantId, String phonenumber, String smsCode) { + private boolean validateSmsCode(String phonenumber, String smsCode) { String code = RedisUtils.getCacheObject(GlobalConstants.DEVICE_SHARE_CODES_KEY + phonenumber); if (StringUtils.isBlank(code)) { throw new ServiceException("验证码失效"); @@ -184,16 +199,21 @@ public class DeviceShareService { } public int deviceShare(AppDeviceShareBo bo) { - boolean flag = validateSmsCode(AppLoginHelper.getTenantId(), bo.getPhonenumber(), bo.getSmsCode()); - if (!flag) { - throw new ServiceException("验证码错误"); - } - Device device = deviceMapper.selectById(bo.getDeviceId()); if (device == null) { throw new ServiceException("设备不存在"); } - Long userId = AppLoginHelper.getUserId(); + + boolean flag = validateSmsCode( bo.getPhonenumber(), bo.getSmsCode()); + if (!flag) { + throw new ServiceException("验证码错误"); + } + + LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); + qw.eq(AppDeviceBindRecord::getDeviceId, bo.getDeviceId()); + AppDeviceBindRecord bindRecord = appDeviceBindRecordMapper.selectOne(qw); + Long userId = bindRecord.getBindingUserId(); + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); lqw.eq(AppDeviceShare::getDeviceId, bo.getDeviceId()); lqw.eq(AppDeviceShare::getPhonenumber, bo.getPhonenumber()); diff --git a/fys-admin/src/main/java/com/fuyuanshen/web/service/WEBDeviceService.java b/fys-admin/src/main/java/com/fuyuanshen/web/service/WEBDeviceService.java index 7066a519..121982ff 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/web/service/WEBDeviceService.java +++ b/fys-admin/src/main/java/com/fuyuanshen/web/service/WEBDeviceService.java @@ -53,16 +53,21 @@ public interface WEBDeviceService extends IService { * 设备操作记录 * * @param deviceId + * @param startTime 开始时间 + * @param endTime 结束时间 * @return */ - List getOperationRecord(Long deviceId); + TableDataInfo getOperationRecord(Long deviceId, String startTime, String endTime, PageQuery pageQuery); /** * 设备告警记录 * * @param deviceId + * @param startTime 开始时间 + * @param endTime 结束时间 * @return */ - List getAlarmRecord(Long deviceId); + TableDataInfo getAlarmRecord(Long deviceId, String startTime, String endTime, PageQuery pageQuery); + } diff --git a/fys-admin/src/main/java/com/fuyuanshen/web/service/device/DeviceBJQBizService.java b/fys-admin/src/main/java/com/fuyuanshen/web/service/device/DeviceBJQBizService.java index 17c8d8ae..c62d89c3 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/web/service/device/DeviceBJQBizService.java +++ b/fys-admin/src/main/java/com/fuyuanshen/web/service/device/DeviceBJQBizService.java @@ -100,7 +100,6 @@ public class DeviceBJQBizService { UpdateWrapper updateWrapper = new UpdateWrapper<>(); updateWrapper.eq("id", deviceId) - .eq("binding_user_id", AppLoginHelper.getUserId()) .set("send_msg", bo.getSendMsg()); deviceMapper.update(updateWrapper); @@ -538,6 +537,6 @@ public class DeviceBJQBizService { private boolean getDeviceStatus(String deviceImei) { String deviceOnlineStatusRedisKey = GlobalConstants.GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX+ deviceImei + DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX ; - return StringUtils.isBlank(deviceOnlineStatusRedisKey); + return RedisUtils.getCacheObject(deviceOnlineStatusRedisKey) == null; } } diff --git a/fys-admin/src/main/java/com/fuyuanshen/web/service/device/DeviceDebugService.java b/fys-admin/src/main/java/com/fuyuanshen/web/service/device/DeviceDebugService.java new file mode 100644 index 00000000..2f2e6b85 --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/web/service/device/DeviceDebugService.java @@ -0,0 +1,150 @@ +package com.fuyuanshen.web.service.device; + +import cn.hutool.core.collection.CollUtil; +import com.fuyuanshen.app.domain.AppBusinessFile; +import com.fuyuanshen.app.domain.AppOperationVideo; +import com.fuyuanshen.app.domain.bo.AppBusinessFileBo; +import com.fuyuanshen.app.domain.bo.AppOperationVideoBo; +import com.fuyuanshen.app.domain.dto.AppFileDto; +import com.fuyuanshen.app.service.IAppBusinessFileService; +import com.fuyuanshen.app.service.IAppOperationVideoService; +import com.fuyuanshen.common.core.exception.ServiceException; +import com.fuyuanshen.common.satoken.utils.AppLoginHelper; +import com.fuyuanshen.equipment.mapper.DeviceMapper; +import com.fuyuanshen.equipment.service.DeviceService; +import com.fuyuanshen.system.domain.vo.SysOssVo; +import com.fuyuanshen.system.service.ISysOssService; +import com.fuyuanshen.web.domain.vo.DeviceInfoVo; +import com.fuyuanshen.web.util.FileHashUtil; +import io.swagger.v3.oas.annotations.Operation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * 设备调试服务 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class DeviceDebugService { + private final ISysOssService sysOssService; + + private final IAppBusinessFileService appBusinessFileService; + private final IAppOperationVideoService appOperationVideoService; + private final DeviceService deviceService; + + /** + * 文件上传并添加文件信息哈希去重 + * @param bo + * @return + * @throws IOException + */ + @Transactional(rollbackFor = Exception.class) + public Boolean addFileHash(AppFileDto bo) throws IOException { + MultipartFile[] files = bo.getFiles(); + if (files == null || files.length == 0) { + throw new ServiceException("请选择要上传的文件"); + } + if (files.length > 5) { + throw new ServiceException("最多只能上传5个文件"); + } + if (bo.getDeviceIds() == null || bo.getDeviceIds().length == 0) { + throw new ServiceException("请选择你要上传的设备"); + } + + Map hash2OssId = new LinkedHashMap<>(files.length); + for (MultipartFile file : files) { + // 1. 计算文件哈希 + String hash = FileHashUtil.hash(file); + + // 2. 先根据 hash 查库(秒传) + SysOssVo exist = sysOssService.selectByHash(hash); + Long ossId; + if (exist != null) { + // 2.1 已存在,直接复用 + ossId = exist.getOssId(); + hash2OssId.putIfAbsent(hash, ossId); + } else { + // 2.2 不存在,真正上传 + SysOssVo upload = sysOssService.upload(file); + if (upload == null) { + return false; + } + ossId = upload.getOssId(); + hash2OssId.putIfAbsent(hash, ossId); + // 2.3 把 hash 写回记录(供下次去重) + sysOssService.updateHashById(ossId, hash); + } + } + // 4. 组装业务中间表 + List bizList = new ArrayList<>(bo.getDeviceIds().length * hash2OssId.size()); + Long userId = AppLoginHelper.getUserId(); + for (Long deviceId : bo.getDeviceIds()) { + for (Long ossId : hash2OssId.values()) { + // 3. 关联业务表 + AppBusinessFile appFile = new AppBusinessFile(); + appFile.setFileId(ossId); + appFile.setBusinessId(deviceId); + appFile.setFileType(bo.getFileType()); + appFile.setCreateBy(userId); + bizList.add(appFile); + } + } + if (CollUtil.isEmpty(bizList)) { // 空集合直接返回 + throw new ServiceException("请选择要上传的文件"); + } + return appBusinessFileService.insertBatch(bizList); + } + + public Boolean addVideoList(AppOperationVideoBo bo){ + if (bo.getVideoUrl().isEmpty()) { + throw new ServiceException("请输入视频地址"); + } + if (bo.getDeviceIds() == null || bo.getDeviceIds().length == 0) { + throw new ServiceException("请选择你要上传的设备"); + } + List bizList = new ArrayList<>(bo.getDeviceIds().length); + for (Long deviceId : bo.getDeviceIds()) { + + AppOperationVideo appVideo = new AppOperationVideo(); + appVideo.setVideoName(bo.getVideoName()); + appVideo.setDeviceId(deviceId); + appVideo.setVideoUrl(bo.getVideoUrl()); + bizList.add(appVideo); + } + if (CollUtil.isEmpty(bizList)) { // 空集合直接返回 + throw new ServiceException("请选择要上传的视频"); + } + return appOperationVideoService.insertBatch(bizList); + } + + /** + * 设备详情 + * @param deviceId + * @return + */ + public DeviceInfoVo getDeviceInfo(Long deviceId) { + if(deviceId == null || deviceId <= 0L) { + throw new ServiceException("请选择设备"); + } + DeviceInfoVo vo = new DeviceInfoVo(); + var device = deviceService.getById(deviceId); + AppBusinessFileBo fileBo = new AppBusinessFileBo(); + fileBo.setBusinessId(deviceId); + AppOperationVideoBo videoBo = new AppOperationVideoBo(); + videoBo.setDeviceId(deviceId); + vo.setAppBusinessFileVoList(appBusinessFileService.queryAppFileList(fileBo)); + vo.setAppOperationVideoVoList(appOperationVideoService.queryList(videoBo)); + return vo; + } +} diff --git a/fys-admin/src/main/java/com/fuyuanshen/web/service/device/DeviceXinghanBizService.java b/fys-admin/src/main/java/com/fuyuanshen/web/service/device/DeviceXinghanBizService.java index 29b8374b..8370ed9d 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/web/service/device/DeviceXinghanBizService.java +++ b/fys-admin/src/main/java/com/fuyuanshen/web/service/device/DeviceXinghanBizService.java @@ -3,6 +3,7 @@ package com.fuyuanshen.web.service.device; import com.alibaba.fastjson2.JSON; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.fuyuanshen.app.domain.AppPersonnelInfo; import com.fuyuanshen.app.domain.bo.AppPersonnelInfoBo; import com.fuyuanshen.app.domain.dto.AppDeviceLogoUploadDto; @@ -27,13 +28,17 @@ import com.fuyuanshen.equipment.mapper.DeviceTypeMapper; import com.fuyuanshen.global.mqtt.config.MqttGateway; import com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants; import com.fuyuanshen.global.mqtt.constants.MqttConstants; +import com.fuyuanshen.web.domain.Dto.DeviceDebugLogoUploadDto; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; +import java.io.IOException; import java.time.Duration; import java.util.*; +import java.util.stream.Collectors; import static com.fuyuanshen.common.core.constant.GlobalConstants.GLOBAL_REDIS_KEY; import static com.fuyuanshen.common.core.utils.Bitmap80x12Generator.buildArr; @@ -142,6 +147,67 @@ public class DeviceXinghanBizService { } } + /** + * 批量上传设备logo + */ + @Transactional(rollbackFor = Exception.class) + public void uploadDeviceLogoBatch(DeviceDebugLogoUploadDto batchDto) { + if (CollectionUtils.isEmpty(batchDto.getDeviceIds())) { + throw new ServiceException("设备列表为空"); + } + + // 1. 一次性把设备查出来(N -> 1) + QueryWrapper query = new QueryWrapper<>(); + query.in("id", batchDto.getDeviceIds()); + List devices = deviceMapper.selectList(query); + if (devices.size() != batchDto.getDeviceIds().size()) { + throw new ServiceException("部分设备不存在"); + } + + // 2. 图片只转换一次(160*80 固定尺寸) + byte[] largeData; + try { + largeData = ImageToCArrayConverter.convertImageToCArray( + batchDto.getFile().getInputStream(), 160, 80, 25600); + } catch (IOException e) { + throw new ServiceException("图片解析失败"); + } + int[] picArray = convertHexToDecimal(largeData); + + // 3. 过滤离线设备 & 组装指令 + List onlineDevices = devices.stream() + .filter(d -> !isDeviceOffline(d.getDeviceImei())) + .toList(); + onlineDevices.forEach(d -> { + String redisKey = GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + d.getDeviceImei() + DEVICE_BOOT_LOGO_KEY_PREFIX; + + // 如果 Redis 里已存在,直接跳过 + if (RedisUtils.getCacheObject(redisKey) != null) { + return; // 跳过本次循环 + } + + RedisUtils.setCacheObject( + redisKey, + Arrays.toString(picArray), + Duration.ofSeconds(5 * 60L)); + // 3.2 MQTT 下发 + Map payload = + Collections.singletonMap("ins_PicTrans", Collections.singletonList(0)); + String topic = MqttConstants.GLOBAL_PUB_KEY + d.getDeviceImei(); + String json = JsonUtils.toJsonString(payload); + + try { + mqttGateway.sendMsgToMqtt(topic, 1, json); + } catch (Exception e) { + log.error("上传开机画面失败, topic={}, payload={}", topic, json, e); + throw new ServiceException("上传LOGO失败:" + e.getMessage()); + } + + recordDeviceLog(d.getId(), d.getDeviceName(), "上传开机画面", "上传开机画面", AppLoginHelper.getUserId()); + + }); + } + /** * 人员登记 * @param bo @@ -330,10 +396,10 @@ public class DeviceXinghanBizService { AppLoginHelper.getUserId()); } - private boolean isDeviceOffline(String imei) { - // 原方法名语义相反,这里取反,使含义更清晰 - return getDeviceStatus(imei); - } +// private boolean isDeviceOffline(String imei) { +// // 原方法名语义相反,这里取反,使含义更清晰 +// return getDeviceStatus(imei); +// } /** * 记录设备操作日志 @@ -359,9 +425,9 @@ public class DeviceXinghanBizService { } } - private boolean getDeviceStatus(String deviceImei) { + private boolean isDeviceOffline(String deviceImei) { String deviceOnlineStatusRedisKey = GlobalConstants.GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX+ deviceImei + DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX ; - return StringUtils.isBlank(deviceOnlineStatusRedisKey); + return RedisUtils.getCacheObject(deviceOnlineStatusRedisKey)==null; } } diff --git a/fys-admin/src/main/java/com/fuyuanshen/web/service/impl/WEBDeviceServiceImpl.java b/fys-admin/src/main/java/com/fuyuanshen/web/service/impl/WEBDeviceServiceImpl.java index cc927804..6e7d5a16 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/web/service/impl/WEBDeviceServiceImpl.java +++ b/fys-admin/src/main/java/com/fuyuanshen/web/service/impl/WEBDeviceServiceImpl.java @@ -1,16 +1,20 @@ package com.fuyuanshen.web.service.impl; import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.fuyuanshen.app.domain.AppDeviceBindRecord; import com.fuyuanshen.app.domain.AppDeviceShare; import com.fuyuanshen.app.domain.AppPersonnelInfoRecords; -import com.fuyuanshen.app.domain.vo.AppDeviceShareVo; import com.fuyuanshen.app.mapper.AppDeviceBindRecordMapper; import com.fuyuanshen.app.mapper.AppDeviceShareMapper; import com.fuyuanshen.app.mapper.AppPersonnelInfoRecordsMapper; +import com.fuyuanshen.common.mybatis.core.page.PageQuery; +import com.fuyuanshen.common.mybatis.core.page.TableDataInfo; import com.fuyuanshen.equipment.domain.Device; import com.fuyuanshen.equipment.domain.DeviceAlarm; import com.fuyuanshen.equipment.domain.DeviceAssignments; @@ -23,7 +27,6 @@ import com.fuyuanshen.equipment.mapper.DeviceAssignmentsMapper; import com.fuyuanshen.equipment.mapper.DeviceLogMapper; import com.fuyuanshen.equipment.mapper.DeviceMapper; import com.fuyuanshen.web.service.WEBDeviceService; -import com.fuyuanshen.web.service.device.DeviceBizService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -129,11 +132,19 @@ public class WEBDeviceServiceImpl extends ServiceImpl impl * @return */ @Override - public List getOperationRecord(Long deviceId) { - List logList = deviceLogMapper.selectList( - new QueryWrapper().eq("device_id", deviceId) - .orderByDesc("create_time")); - return logList; + public TableDataInfo getOperationRecord(Long deviceId, String startTime, String endTime, PageQuery pageQuery) { + Page page = pageQuery.build(); + QueryWrapper queryWrapper = new QueryWrapper().eq("device_id", deviceId); + + if (StrUtil.isNotEmpty(startTime)) { + queryWrapper.ge("create_time", startTime); + } + if (StrUtil.isNotEmpty(endTime)) { + queryWrapper.le("create_time", endTime); + } + queryWrapper.orderByDesc("create_time"); + IPage logList = deviceLogMapper.selectPage(page, queryWrapper); + return TableDataInfo.build(logList); } @@ -144,13 +155,23 @@ public class WEBDeviceServiceImpl extends ServiceImpl impl * @return */ @Override - public List getAlarmRecord(Long deviceId) { - List alarmList = deviceAlarmMapper.selectList( - new QueryWrapper().eq("device_id", deviceId) - .orderByDesc("create_time")); - List deviceAlarmVoList = BeanUtil.copyToList(alarmList, DeviceAlarmVo.class); - return deviceAlarmVoList; + public TableDataInfo getAlarmRecord(Long deviceId, String startTime, String endTime, PageQuery pageQuery) { + Page page = pageQuery.build(); + QueryWrapper queryWrapper = new QueryWrapper().eq("device_id", deviceId); + + if (StrUtil.isNotEmpty(startTime)) { + queryWrapper.ge("start_time", startTime); + } + if (StrUtil.isNotEmpty(endTime)) { + queryWrapper.le("start_time", endTime); + } + queryWrapper.orderByDesc("start_time"); + IPage alarmPage = deviceAlarmMapper.selectPage(page, queryWrapper); + + // List deviceAlarmVoList = BeanUtil.copyToList(alarmPage.getRecords(), DeviceAlarmVo.class); + return TableDataInfo.build(alarmPage); } - } + + diff --git a/fys-admin/src/main/java/com/fuyuanshen/web/util/FileHashUtil.java b/fys-admin/src/main/java/com/fuyuanshen/web/util/FileHashUtil.java new file mode 100644 index 00000000..f81c9169 --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/web/util/FileHashUtil.java @@ -0,0 +1,28 @@ +package com.fuyuanshen.web.util; + +import org.apache.commons.codec.digest.DigestUtils; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.io.InputStream; +import java.security.MessageDigest; +import java.util.HexFormat; + +/** + * 文件哈希工具类 + */ +public class FileHashUtil { + private static final String ALGORITHM = "SHA-256"; + + public static String hash(MultipartFile file) throws IOException { + MessageDigest digest = DigestUtils.getDigest(ALGORITHM); + try (InputStream in = file.getInputStream()) { + byte[] buf = new byte[8192]; + int len; + while ((len = in.read(buf)) != -1) { + digest.update(buf, 0, len); + } + } + return HexFormat.of().formatHex(digest.digest()); + } +} diff --git a/fys-common/fys-common-encrypt/src/main/java/com/fuyuanshen/common/encrypt/utils/EncryptUtilsTest.java b/fys-common/fys-common-encrypt/src/main/java/com/fuyuanshen/common/encrypt/utils/EncryptUtilsTest.java index 08b352ac..05e035d2 100644 --- a/fys-common/fys-common-encrypt/src/main/java/com/fuyuanshen/common/encrypt/utils/EncryptUtilsTest.java +++ b/fys-common/fys-common-encrypt/src/main/java/com/fuyuanshen/common/encrypt/utils/EncryptUtilsTest.java @@ -39,8 +39,8 @@ public class EncryptUtilsTest { loginBody.setClientId("e5cd7e4891bf95d1d19206ce24a7b32e"); loginBody.setGrantType("password"); loginBody.setTenantId("894078"); - loginBody.setCode("9"); - loginBody.setUuid("d5be31eac1244cee851a9903f358bc6a"); + loginBody.setCode("0"); + loginBody.setUuid("1d6615668c7f410da77c4e002c601073"); // loginBody.setUsername("admin"); // loginBody.setPassword("admin123"); loginBody.setUsername("dyf"); diff --git a/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/domain/bo/AppOperationVideoBo.java b/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/domain/bo/AppOperationVideoBo.java index 7abd0f68..d15765fe 100644 --- a/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/domain/bo/AppOperationVideoBo.java +++ b/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/domain/bo/AppOperationVideoBo.java @@ -45,5 +45,10 @@ public class AppOperationVideoBo extends BaseEntity { */ private String remark; + /** + * 多设备id + */ + private Long[] deviceIds; + } diff --git a/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/domain/vo/AppFileVo.java b/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/domain/vo/AppFileVo.java index ab8839f0..fdad1f1a 100644 --- a/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/domain/vo/AppFileVo.java +++ b/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/domain/vo/AppFileVo.java @@ -19,6 +19,10 @@ public class AppFileVo { * 文件名称 */ private String fileName; + /** + * 文件类型(1:操作说明,2:产品参数) + */ + private Long fileType; /** * 文件url */ diff --git a/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/service/IAppBusinessFileService.java b/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/service/IAppBusinessFileService.java index c99eb10f..a3676723 100644 --- a/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/service/IAppBusinessFileService.java +++ b/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/service/IAppBusinessFileService.java @@ -1,5 +1,6 @@ package com.fuyuanshen.app.service; +import com.fuyuanshen.app.domain.AppBusinessFile; import com.fuyuanshen.app.domain.vo.AppBusinessFileVo; import com.fuyuanshen.app.domain.bo.AppBusinessFileBo; import com.fuyuanshen.app.domain.vo.AppFileVo; @@ -50,6 +51,14 @@ public interface IAppBusinessFileService { */ Boolean insertByBo(AppBusinessFileBo bo); + /** + * 批量新增app业务文件 + * + * @param bo 批量新增app业务文件 + * @return 是否新增成功 + */ + Boolean insertBatch(Collection bo); + /** * 修改app业务文件 * diff --git a/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/service/IAppOperationVideoService.java b/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/service/IAppOperationVideoService.java index 54fcf444..ed38f869 100644 --- a/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/service/IAppOperationVideoService.java +++ b/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/service/IAppOperationVideoService.java @@ -1,5 +1,7 @@ package com.fuyuanshen.app.service; +import com.fuyuanshen.app.domain.AppBusinessFile; +import com.fuyuanshen.app.domain.AppOperationVideo; import com.fuyuanshen.app.domain.vo.AppOperationVideoVo; import com.fuyuanshen.app.domain.bo.AppOperationVideoBo; import com.fuyuanshen.common.mybatis.core.page.TableDataInfo; @@ -49,6 +51,14 @@ public interface IAppOperationVideoService { */ Boolean insertByBo(AppOperationVideoBo bo); + /** + * 批量新增操作视频 + * + * @param bo 批量新增操作视频 + * @return 是否新增成功 + */ + Boolean insertBatch(Collection bo); + /** * 修改操作视频 * diff --git a/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/service/impl/AppBusinessFileServiceImpl.java b/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/service/impl/AppBusinessFileServiceImpl.java index 4b643b4c..73d96a11 100644 --- a/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/service/impl/AppBusinessFileServiceImpl.java +++ b/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/service/impl/AppBusinessFileServiceImpl.java @@ -1,5 +1,6 @@ package com.fuyuanshen.app.service.impl; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.fuyuanshen.app.domain.vo.AppFileVo; import com.fuyuanshen.common.core.utils.MapstructUtils; import com.fuyuanshen.common.core.utils.StringUtils; @@ -100,6 +101,20 @@ public class AppBusinessFileServiceImpl implements IAppBusinessFileService { return flag; } + @Override + public Boolean insertBatch(Collection bo) { + // 1. 去重后的 businessId 集合 + List businessIds = bo.stream() + .map(AppBusinessFile::getBusinessId) + .distinct() + .toList(); + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.in("business_id", businessIds); + queryWrapper.eq("file_type", bo.stream().findFirst().orElseThrow().getFileType()); + baseMapper.delete(queryWrapper); + return baseMapper.insertBatch(bo); + } + /** * 修改app业务文件 * diff --git a/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/service/impl/AppOperationVideoServiceImpl.java b/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/service/impl/AppOperationVideoServiceImpl.java index 8141548a..32f8781e 100644 --- a/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/service/impl/AppOperationVideoServiceImpl.java +++ b/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/service/impl/AppOperationVideoServiceImpl.java @@ -1,5 +1,7 @@ package com.fuyuanshen.app.service.impl; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.fuyuanshen.app.domain.AppBusinessFile; import com.fuyuanshen.common.core.utils.MapstructUtils; import com.fuyuanshen.common.core.utils.StringUtils; import com.fuyuanshen.common.mybatis.core.page.TableDataInfo; @@ -97,6 +99,19 @@ public class AppOperationVideoServiceImpl implements IAppOperationVideoService { return flag; } + @Override + public Boolean insertBatch(Collection bo) { + // 1. 去重后的 businessId 集合 + List deviceIds = bo.stream() + .map(AppOperationVideo::getDeviceId) + .distinct() + .toList(); + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.in("device_id", deviceIds); + baseMapper.delete(queryWrapper); + return baseMapper.insertBatch(bo); + } + /** * 修改操作视频 * diff --git a/fys-modules/fys-app/src/main/resources/mapper/app/AppBusinessFileMapper.xml b/fys-modules/fys-app/src/main/resources/mapper/app/AppBusinessFileMapper.xml index 71cb53d4..2b0a9a93 100644 --- a/fys-modules/fys-app/src/main/resources/mapper/app/AppBusinessFileMapper.xml +++ b/fys-modules/fys-app/src/main/resources/mapper/app/AppBusinessFileMapper.xml @@ -5,7 +5,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" - select * + select d.device_name, + d.device_mac, + d.device_sn, + d.device_imei, + d.device_pic, + dt.type_name, + dt.communication_mode, + d.bluetooth_name, + dt.app_model_dictionary detailPageUrl, + c.binding_time, + ad.*,u.user_name otherPhonenumber from app_device_share ad + left join device d on ad.device_id = d.id + left join app_user u on ad.create_by = u.user_id + inner join device_type dt on d.device_type = dt.id + inner join app_device_bind_record c on d.id = c.device_id and ad.device_id = #{bo.deviceId} - and ad.share_user = #{bo.shareUser} + and u.user_name = #{bo.shareUser} - - and d.create_time between #{bo.shareStartTime} and #{bo.shareEndTime} + + and ad.create_time between #{bo.shareStartTime} and #{bo.shareEndTime} diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/controller/DeviceController.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/controller/DeviceController.java index 229c2da3..030452a1 100644 --- a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/controller/DeviceController.java +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/controller/DeviceController.java @@ -126,26 +126,26 @@ public class DeviceController extends BaseController { // @Log("分配客户") - @Operation(summary = "分配客户") - @PutMapping(value = "/assignCustomer") - public R assignCustomer(@Validated @RequestBody CustomerVo customerVo) { - deviceService.assignCustomer(customerVo); - return R.ok(); - } + // @Operation(summary = "分配客户") + // @PutMapping(value = "/assignCustomer") + // public R assignCustomer(@Validated @RequestBody CustomerVo customerVo) { + // deviceService.assignCustomer(customerVo); + // return R.ok(); + // } // @Log("撤回设备") - @Operation(summary = "撤回分配设备") - @PostMapping(value = "/withdraw") - public R withdrawDevice(@RequestBody List ids) { - try { - deviceService.withdrawDevice(ids); - } catch (Exception e) { - log.error("updateDevice error: " + e.getMessage()); - return R.fail(e.getMessage()); - } - return R.ok(); - } + // @Operation(summary = "撤回分配设备") + // @PostMapping(value = "/withdraw") + // public R withdrawDevice(@RequestBody List ids) { + // try { + // deviceService.withdrawDevice(ids); + // } catch (Exception e) { + // log.error("updateDevice error: " + e.getMessage()); + // return R.fail(e.getMessage()); + // } + // return R.ok(); + // } // // /** diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/Device.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/Device.java index 2c9a452e..778ab9db 100644 --- a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/Device.java +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/Device.java @@ -162,7 +162,7 @@ public class Device extends TenantEntity { private Date productionDate; /** - * 在线状态(0离线,1在线) + * 在线状态(0离线,1在线,2异常) */ private Integer onlineStatus; } diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/DeviceAlarm.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/DeviceAlarm.java index f83e1611..720ee9bc 100644 --- a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/DeviceAlarm.java +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/DeviceAlarm.java @@ -4,7 +4,9 @@ import com.fuyuanshen.common.tenant.core.TenantEntity; import com.baomidou.mybatisplus.annotation.*; import lombok.Data; import lombok.EqualsAndHashCode; + import java.util.Date; + import com.fasterxml.jackson.annotation.JsonFormat; import java.io.Serial; @@ -36,8 +38,10 @@ public class DeviceAlarm extends TenantEntity { /** * 报警事项 + * 0-强制报警,1-撞击闯入,2-手动报警,3-电子围栏告警,4-强制告警 + * device_action */ - private String deviceAction; + private Integer deviceAction; /** * 设备名称 @@ -61,7 +65,6 @@ public class DeviceAlarm extends TenantEntity { /** * 经度 - */ private Long longitude; @@ -88,10 +91,11 @@ public class DeviceAlarm extends TenantEntity { /** * 报警持续时间 */ - private Long durationTime; + private String durationTime; /** * 0已处理,1未处理 + * treatment_state */ private Long treatmentState; diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/DeviceType.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/DeviceType.java index a8e46186..ef3e3691 100644 --- a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/DeviceType.java +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/DeviceType.java @@ -59,7 +59,7 @@ public class DeviceType extends TenantEntity { @Schema(title = "联网方式", example = "0:无;1:4G;2:WIFI") private String networkWay; - @Schema(title = "通讯方式", example = "0:4G;1:蓝牙") + @Schema(title = "通讯方式", example = "0:4G;1:蓝牙,2 4G&蓝牙") private String communicationMode; /** diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/form/DeviceTypeForm.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/form/DeviceTypeForm.java index d5e1df70..93197f47 100644 --- a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/form/DeviceTypeForm.java +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/form/DeviceTypeForm.java @@ -35,4 +35,18 @@ public class DeviceTypeForm { @Schema(title = "型号字典用于APP页面跳转") private String modelDictionary; + /** + * 型号字典用于APP页面跳转 + * app_model_dictionary + */ + @Schema(title = "型号字典用于APP页面跳转") + private String appModelDictionary; + + /** + * 型号字典用于PC页面跳转 + * pc_model_dictionary + */ + @Schema(title = "型号字典用于PC页面跳转") + private String pcModelDictionary; + } diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/query/DeviceQueryCriteria.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/query/DeviceQueryCriteria.java index 233230ee..1ec9137f 100644 --- a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/query/DeviceQueryCriteria.java +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/query/DeviceQueryCriteria.java @@ -83,6 +83,7 @@ public class DeviceQueryCriteria extends BaseEntity { /** * 通讯方式 0:4G;1:蓝牙 + * communication_mode */ private Integer communicationMode; @@ -113,4 +114,10 @@ public class DeviceQueryCriteria extends BaseEntity { private String content; + /** + * 设备在线状态 + * 0:离线;1:在线 + */ + private Integer onlineStatus; + } diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/AlarmInformationVo.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/AlarmInformationVo.java index 09e73b6d..58216893 100644 --- a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/AlarmInformationVo.java +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/AlarmInformationVo.java @@ -21,6 +21,18 @@ public class AlarmInformationVo { */ private Integer processingAlarm = 0; + + /** + * 今日报警总数 + */ + private Integer alarmsTotalToday = 0; + + /** + * 今日总处理报警 + */ + private Integer processingAlarmToday = 0; + + /** * 强制报警 */ diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/EquipmentClassificationVo.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/EquipmentClassificationVo.java index d84f59ad..2ebecdc1 100644 --- a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/EquipmentClassificationVo.java +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/EquipmentClassificationVo.java @@ -26,4 +26,24 @@ public class EquipmentClassificationVo { */ private Integer devices4GAndBluetooth = 0; + /** + * 设备总数 + */ + private Integer total; + + + /** + * 计算设备总数 + * + * @return 设备总数 + */ + public Integer getTotal() { + if (total == null) { + total = (equipment4G == null ? 0 : equipment4G) + + (deviceBluetooth == null ? 0 : deviceBluetooth) + + (devices4GAndBluetooth == null ? 0 : devices4GAndBluetooth); + } + return total; + } + } diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/mapper/DeviceMapper.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/mapper/DeviceMapper.java index 1a38350a..5d772caa 100644 --- a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/mapper/DeviceMapper.java +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/mapper/DeviceMapper.java @@ -6,13 +6,12 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.fuyuanshen.equipment.domain.Device; import com.fuyuanshen.equipment.domain.dto.InstructionRecordDto; import com.fuyuanshen.equipment.domain.query.DeviceQueryCriteria; -import com.fuyuanshen.equipment.domain.vo.AppDeviceVo; -import com.fuyuanshen.equipment.domain.vo.LocationHistoryVo; -import com.fuyuanshen.equipment.domain.vo.WebDeviceVo; +import com.fuyuanshen.equipment.domain.vo.*; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import java.util.List; +import java.util.Map; /** * @Description: @@ -72,7 +71,42 @@ public interface DeviceMapper extends BaseMapper { AppDeviceVo getDeviceInfo(@Param("deviceMac") String deviceMac); - Page queryWebDeviceList(Page build,@Param("criteria") DeviceQueryCriteria criteria); + Page queryWebDeviceList(Page build, @Param("criteria") DeviceQueryCriteria criteria); Page getLocationHistory(Page build, @Param("bo") InstructionRecordDto criteria); + + /** + * 获取数据总览 + * + * @return + */ + DataOverviewVo getDataOverview(); + + /** + * 获取设备分类 + * + * @return + */ + EquipmentClassificationVo getEquipmentClassification(); + + /** + * 获取告警信息 + * + * @return + */ + AlarmInformationVo getAlarmInformation(); + + /** + * 获取设备使用数据 + * + * @param deviceTypeId 设备ID + * @param range 时间范围 1:半年 2:一年 + * @return 每月使用数据列表 + */ + List> getEquipmentUsageData(@Param("deviceTypeId") Long deviceTypeId, @Param("range") Integer range); + + // 在DeviceMapper.java中添加方法 + int getUsageDataForMonth(@Param("deviceId") Long deviceId, + @Param("year") int year, + @Param("month") int month); } diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/DeviceService.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/DeviceService.java index d2216b64..bae56010 100644 --- a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/DeviceService.java +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/DeviceService.java @@ -9,12 +9,11 @@ import com.fuyuanshen.equipment.domain.Device; import com.fuyuanshen.equipment.domain.dto.AppDeviceBo; import com.fuyuanshen.equipment.domain.form.DeviceForm; import com.fuyuanshen.equipment.domain.query.DeviceQueryCriteria; -import com.fuyuanshen.equipment.domain.vo.AppDeviceVo; -import com.fuyuanshen.equipment.domain.vo.CustomerVo; -import com.fuyuanshen.equipment.domain.vo.DataOverviewVo; +import com.fuyuanshen.equipment.domain.vo.*; import java.io.IOException; import java.util.List; +import java.util.Map; /** * @Description: @@ -122,4 +121,27 @@ public interface DeviceService extends IService { * @return */ DataOverviewVo getDataOverview(); + + /** + * 获取设备分类 + * + * @return + */ + EquipmentClassificationVo getEquipmentClassification(); + + /** + * 获取告警信息 + * + * @return + */ + AlarmInformationVo getAlarmInformation(); + + /** + * 获取设备使用数据 + * + * @param deviceTypeId + * @param range + * @return + */ + List> getEquipmentUsageData(Long deviceTypeId, Integer range); } diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/impl/DeviceLogServiceImpl.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/impl/DeviceLogServiceImpl.java index 16ca6d3d..f6e2c6ae 100644 --- a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/impl/DeviceLogServiceImpl.java +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/impl/DeviceLogServiceImpl.java @@ -53,6 +53,7 @@ public class DeviceLogServiceImpl implements IDeviceLogService { return baseMapper.selectVoById(id); } + /** * 分页查询设备日志列表 * @@ -62,13 +63,12 @@ public class DeviceLogServiceImpl implements IDeviceLogService { */ @Override public TableDataInfo queryPageList(DeviceLogBo bo, PageQuery pageQuery) { - - LambdaQueryWrapper lqw = buildQueryWrapper(bo); Page result = baseMapper.selectVoPage(pageQuery.build(), lqw); return TableDataInfo.build(result); } + /** * 查询符合条件的设备日志列表 * @@ -83,13 +83,17 @@ public class DeviceLogServiceImpl implements IDeviceLogService { private LambdaQueryWrapper buildQueryWrapper(DeviceLogBo bo) { - Long userId = LoginHelper.getUserId(); - List assignments = deviceAssignmentsMapper.selectList(new QueryWrapper().eq("assignee_id", userId)); - List deviceIds = assignments.stream().map(DeviceAssignments::getDeviceId).collect(Collectors.toList()); - if (deviceIds.isEmpty()) { - deviceIds.add(-1L); + // 管理员 + String username = LoginHelper.getUsername(); + if (!username.equals("admin")) { + Long userId = LoginHelper.getUserId(); + List assignments = deviceAssignmentsMapper.selectList(new QueryWrapper().eq("assignee_id", userId)); + List deviceIds = assignments.stream().map(DeviceAssignments::getDeviceId).collect(Collectors.toList()); + if (deviceIds.isEmpty()) { + deviceIds.add(-1L); + } + bo.setDeviceIds(deviceIds); } - bo.setDeviceIds(deviceIds); Map params = bo.getParams(); LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); @@ -99,6 +103,7 @@ public class DeviceLogServiceImpl implements IDeviceLogService { lqw.eq(StringUtils.isNotBlank(bo.getDataSource()), DeviceLog::getDataSource, bo.getDataSource()); lqw.like(StringUtils.isNotBlank(bo.getContent()), DeviceLog::getContent, bo.getContent()); lqw.in(CollectionUtil.isNotEmpty(bo.getDeviceIds()), DeviceLog::getDeviceId, bo.getDeviceIds()); + lqw.orderByDesc(DeviceLog::getCreateTime); return lqw; } diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/impl/DeviceServiceImpl.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/impl/DeviceServiceImpl.java index 2de40b42..5646e991 100644 --- a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/impl/DeviceServiceImpl.java +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/impl/DeviceServiceImpl.java @@ -28,9 +28,7 @@ import com.fuyuanshen.equipment.domain.form.DeviceForm; import com.fuyuanshen.equipment.domain.query.DeviceAssignmentQuery; import com.fuyuanshen.equipment.domain.query.DeviceQueryCriteria; import com.fuyuanshen.equipment.domain.query.DeviceTypeQueryCriteria; -import com.fuyuanshen.equipment.domain.vo.AppDeviceVo; -import com.fuyuanshen.equipment.domain.vo.CustomerVo; -import com.fuyuanshen.equipment.domain.vo.DataOverviewVo; +import com.fuyuanshen.equipment.domain.vo.*; import com.fuyuanshen.equipment.enums.BindingStatusEnum; import com.fuyuanshen.equipment.enums.CommunicationModeEnum; import com.fuyuanshen.equipment.enums.DeviceActiveStatusEnum; @@ -53,11 +51,9 @@ import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.io.IOException; import java.sql.Timestamp; +import java.time.LocalDate; import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.Objects; +import java.util.*; /** * @Description: @@ -596,8 +592,6 @@ public class DeviceServiceImpl extends ServiceImpl impleme } - - /** * 查询设备MAC号 * @@ -623,7 +617,47 @@ public class DeviceServiceImpl extends ServiceImpl impleme */ @Override public DataOverviewVo getDataOverview() { - return null; + DataOverviewVo dataOverviewVo = deviceMapper.getDataOverview(); + return dataOverviewVo; + } + + + /** + * 获取设备分类 + * + * @return + */ + @Override + public EquipmentClassificationVo getEquipmentClassification() { + EquipmentClassificationVo equipmentClassification = deviceMapper.getEquipmentClassification(); + equipmentClassification.getTotal(); + return equipmentClassification; + } + + + /** + * 获取告警信息 + * + * @return + */ + @Override + public AlarmInformationVo getAlarmInformation() { + AlarmInformationVo alarmInformation = deviceMapper.getAlarmInformation(); + return alarmInformation; + } + + /** + * 获取设备使用数据 + * + * @param deviceTypeId 设备ID + * @param range 时间范围 1:半年 2:一年 + * @return 每月使用数据列表 + */ + @Override + public List> getEquipmentUsageData(Long deviceTypeId, Integer range) { + List> equipmentUsageData = deviceMapper.getEquipmentUsageData(deviceTypeId, range); + return equipmentUsageData; + } } diff --git a/fys-modules/fys-equipment/src/main/resources/mapper/equipment/DeviceMapper.xml b/fys-modules/fys-equipment/src/main/resources/mapper/equipment/DeviceMapper.xml index 20b385cc..f70aeca7 100644 --- a/fys-modules/fys-equipment/src/main/resources/mapper/equipment/DeviceMapper.xml +++ b/fys-modules/fys-equipment/src/main/resources/mapper/equipment/DeviceMapper.xml @@ -74,6 +74,9 @@ and d.group_id = #{criteria.groupId} + + and t.communication_mode = #{criteria.communicationMode} + and da.create_time between #{criteria.params.beginTime} and #{criteria.params.endTime} @@ -278,9 +281,13 @@ and d.group_id = #{criteria.groupId} + + and d.online_status = #{criteria.onlineStatus} + + ORDER BY d.create_time DESC + + + + + + + + + + + + + + \ No newline at end of file diff --git a/fys-modules/fys-equipment/src/main/resources/mapper/equipment/DeviceRepairRecordsMapper.xml b/fys-modules/fys-equipment/src/main/resources/mapper/equipment/DeviceRepairRecordsMapper.xml index 7e83e5c7..65e4d8d8 100644 --- a/fys-modules/fys-equipment/src/main/resources/mapper/equipment/DeviceRepairRecordsMapper.xml +++ b/fys-modules/fys-equipment/src/main/resources/mapper/equipment/DeviceRepairRecordsMapper.xml @@ -27,7 +27,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" and dr.device_id = #{criteria.deviceId} - and dr.repairPart like concat('%', TRIM(#{criteria.repairPart}), '%') + and dr.repair_part like concat('%', TRIM(#{criteria.repairPart}), '%') diff --git a/fys-modules/fys-generator/src/main/resources/vm/java/controller.java.vm b/fys-modules/fys-generator/src/main/resources/vm/java/controller.java.vm index 9f9c8185..6b836491 100644 --- a/fys-modules/fys-generator/src/main/resources/vm/java/controller.java.vm +++ b/fys-modules/fys-generator/src/main/resources/vm/java/controller.java.vm @@ -56,7 +56,7 @@ public class ${ClassName}Controller extends BaseController { #end /** - * 导出${functionName}列表 + * ${functionName}列表 */ @SaCheckPermission("${permissionPrefix}:export") @Log(title = "${functionName}", businessType = BusinessType.EXPORT) diff --git a/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/domain/SysOss.java b/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/domain/SysOss.java index b3604361..6d187f57 100644 --- a/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/domain/SysOss.java +++ b/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/domain/SysOss.java @@ -51,5 +51,9 @@ public class SysOss extends TenantEntity { * 服务商 */ private String service; + /** + * 内容哈希 + */ + private String fileHash; } diff --git a/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/domain/bo/SysOssBo.java b/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/domain/bo/SysOssBo.java index 5ca51bac..c6234d8e 100644 --- a/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/domain/bo/SysOssBo.java +++ b/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/domain/bo/SysOssBo.java @@ -50,5 +50,9 @@ public class SysOssBo extends BaseEntity { * 服务商 */ private String service; + /** + * 内容哈希 + */ + private String fileHash; } diff --git a/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/domain/vo/SysOssVo.java b/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/domain/vo/SysOssVo.java index 2e612a46..b63a0c21 100644 --- a/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/domain/vo/SysOssVo.java +++ b/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/domain/vo/SysOssVo.java @@ -72,6 +72,10 @@ public class SysOssVo implements Serializable { * 服务商 */ private String service; + /** + * 内容哈希 + */ + private String fileHash; } diff --git a/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/mapper/SysOssMapper.java b/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/mapper/SysOssMapper.java index f08ecd38..efe59709 100644 --- a/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/mapper/SysOssMapper.java +++ b/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/mapper/SysOssMapper.java @@ -1,9 +1,16 @@ package com.fuyuanshen.system.mapper; +import com.baomidou.mybatisplus.core.toolkit.Constants; +import com.fuyuanshen.common.mybatis.annotation.DataColumn; +import com.fuyuanshen.common.mybatis.annotation.DataPermission; import com.fuyuanshen.common.mybatis.core.mapper.BaseMapperPlus; import com.fuyuanshen.system.domain.SysOss; +import com.fuyuanshen.system.domain.SysUser; import com.fuyuanshen.system.domain.vo.SysOssVo; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.io.Serializable; /** * 文件上传 数据层 @@ -12,4 +19,20 @@ import org.apache.ibatis.annotations.Mapper; */ @Mapper public interface SysOssMapper extends BaseMapperPlus { + + /** + * 用内容哈希查询文件 + * + * @param fileHash 内容哈希 + * @return 文件信息 + */ + SysOssVo selectByHash(String fileHash); + + /** + * 根据主键更新内容哈希 + * + * @param ossId 主键 + * @return 结果 + */ + int updateHashById(long ossId,String fileHash); } diff --git a/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/service/ISysOssService.java b/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/service/ISysOssService.java index fe0d4660..32a0a3e0 100644 --- a/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/service/ISysOssService.java +++ b/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/service/ISysOssService.java @@ -44,6 +44,22 @@ public interface ISysOssService { */ SysOssVo getById(Long ossId); + /** + * 根据文件 hash 值从缓存或数据库中获取 SysOssVo 对象 + * + * @param fileHash 文件 hash 值 + * @return 匹配的 SysOssVo 列表 + */ + SysOssVo selectByHash(String fileHash); + + /** + * 更新文件 hash 值 + * + * @param ossId OSS对象ID + * @param fileHash 文件 hash 值 + */ + int updateHashById(long ossId,String fileHash); + /** * 上传 MultipartFile 到对象存储服务,并保存文件信息到数据库 * diff --git a/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/service/impl/SysOssServiceImpl.java b/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/service/impl/SysOssServiceImpl.java index a46dfe12..80f1e6bf 100644 --- a/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/service/impl/SysOssServiceImpl.java +++ b/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/service/impl/SysOssServiceImpl.java @@ -162,6 +162,16 @@ public class SysOssServiceImpl implements ISysOssService, OssService { return baseMapper.selectVoById(ossId); } + @Override + public SysOssVo selectByHash(String fileHash) { + return baseMapper.selectByHash(fileHash); + } + + @Override + public int updateHashById(long ossId, String fileHash) { + return baseMapper.updateHashById(ossId,fileHash); + } + /** * 文件下载方法,支持一次性下载完整文件 diff --git a/fys-modules/fys-system/src/main/resources/mapper/system/SysOssMapper.xml b/fys-modules/fys-system/src/main/resources/mapper/system/SysOssMapper.xml index 16ad66b9..d230569c 100644 --- a/fys-modules/fys-system/src/main/resources/mapper/system/SysOssMapper.xml +++ b/fys-modules/fys-system/src/main/resources/mapper/system/SysOssMapper.xml @@ -2,4 +2,11 @@ + + + + UPDATE sys_oss SET file_hash = #{fileHash} WHERE oss_id = #{ossId} +