diff --git a/sql/sn_screenshot.sql b/sql/sn_screenshot.sql index c8db844a..a87aba64 100644 --- a/sql/sn_screenshot.sql +++ b/sql/sn_screenshot.sql @@ -16,6 +16,7 @@ CREATE TABLE IF NOT EXISTS `sys_sn_screenshot` `file_sha1` VARCHAR(64) DEFAULT NULL COMMENT '文件Sha1值', `file_sha256` VARCHAR(64) DEFAULT NULL COMMENT '文件Sha256值', `upload_time` DATETIME DEFAULT NULL COMMENT '上传时间', + `camera` TINYINT DEFAULT NULL COMMENT '摄像头类型:0-后置,1-前置,-1-截屏', -- ===================== 通用字段 ===================== `create_time` DATETIME DEFAULT NULL COMMENT '创建时间', diff --git a/src/main/java/com/youlai/boot/client/controller/ClientDeviceOpsController.java b/src/main/java/com/youlai/boot/client/controller/ClientDeviceOpsController.java index 83ffcda1..046a2f90 100644 --- a/src/main/java/com/youlai/boot/client/controller/ClientDeviceOpsController.java +++ b/src/main/java/com/youlai/boot/client/controller/ClientDeviceOpsController.java @@ -147,17 +147,21 @@ public class ClientDeviceOpsController { @PreAuthorize("isAuthenticated()") @PostMapping("/take_photo") public Result takePhoto( - @Parameter(description = "设备序列号") @RequestParam("sn") String sn + @Parameter(description = "设备序列号") @RequestParam("sn") String sn, + @Parameter(description = "摄像头类型(0=后置摄像头,1=前置摄像头)") @RequestParam("camera") int camera ) { + if (camera != 0 && camera != 1) { + return Result.failed("摄像头类型非法,仅支持 0(后置)或 1(前置)"); + } try { checkBound(sn); - boolean result = deviceService.takePhoto(sn); + boolean result = deviceService.takePhoto(sn, camera); return Result.judge(result); } catch (BusinessException be) { return Result.failed(be.getMessage()); } catch (Exception e) { - log.error("remoteCamera error, sn: {}", sn, e); - return Result.failed("设备截图失败: " + e.getMessage()); + log.error("takePhoto error, sn: {}, camera: {}", sn, camera, e); + return Result.failed("远程拍照失败: " + e.getMessage()); } } @@ -436,4 +440,94 @@ public class ClientDeviceOpsController { return Result.failed("停止应用失败: " + e.getMessage()); } } + + @Operation(summary = "文件传输(家属端)") + @PreAuthorize("isAuthenticated()") + @PostMapping("/file_transfer") + public Result fileTransfer( + @Parameter(description = "设备序列号") @RequestParam("sn") String sn + ) { + try { + checkBound(sn); + boolean result = deviceService.fileTransfer(sn); + return Result.judge(result); + } catch (BusinessException be) { + return Result.failed(be.getMessage()); + } catch (Exception e) { + log.error("fileTransfer error, sn: {}", sn, e); + return Result.failed("文件传输指令下发失败: " + e.getMessage()); + } + } + + @Operation(summary = "短信同步(家属端)") + @PreAuthorize("isAuthenticated()") + @PostMapping("/msg_sync") + public Result msgSync( + @Parameter(description = "设备序列号") @RequestParam("sn") String sn + ) { + try { + checkBound(sn); + boolean result = deviceService.msgSync(sn); + return Result.judge(result); + } catch (BusinessException be) { + return Result.failed(be.getMessage()); + } catch (Exception e) { + log.error("msgSync error, sn: {}", sn, e); + return Result.failed("短信同步指令下发失败: " + e.getMessage()); + } + } + + @Operation(summary = "清理(家属端)") + @PreAuthorize("isAuthenticated()") + @PostMapping("/clean") + public Result clean( + @Parameter(description = "设备序列号") @RequestParam("sn") String sn + ) { + try { + checkBound(sn); + boolean result = deviceService.clean(sn); + return Result.judge(result); + } catch (BusinessException be) { + return Result.failed(be.getMessage()); + } catch (Exception e) { + log.error("clean error, sn: {}", sn, e); + return Result.failed("清理指令下发失败: " + e.getMessage()); + } + } + + @Operation(summary = "屏幕镜像(家属端)") + @PreAuthorize("isAuthenticated()") + @PostMapping("/mirror") + public Result mirror( + @Parameter(description = "设备序列号") @RequestParam("sn") String sn + ) { + try { + checkBound(sn); + boolean result = deviceService.mirror(sn); + return Result.judge(result); + } catch (BusinessException be) { + return Result.failed(be.getMessage()); + } catch (Exception e) { + log.error("mirror error, sn: {}", sn, e); + return Result.failed("屏幕镜像指令下发失败: " + e.getMessage()); + } + } + + @Operation(summary = "屏幕锁定(家属端)") + @PreAuthorize("isAuthenticated()") + @PostMapping("/screen_lock") + public Result screenLock( + @Parameter(description = "设备序列号") @RequestParam("sn") String sn + ) { + try { + checkBound(sn); + boolean result = deviceService.screenLock(sn); + return Result.judge(result); + } catch (BusinessException be) { + return Result.failed(be.getMessage()); + } catch (Exception e) { + log.error("screenLock error, sn: {}", sn, e); + return Result.failed("屏幕锁定指令下发失败: " + e.getMessage()); + } + } } diff --git a/src/main/java/com/youlai/boot/device/controller/DeviceOpsController.java b/src/main/java/com/youlai/boot/device/controller/DeviceOpsController.java index 54721d2d..7f6cbbd3 100644 --- a/src/main/java/com/youlai/boot/device/controller/DeviceOpsController.java +++ b/src/main/java/com/youlai/boot/device/controller/DeviceOpsController.java @@ -84,8 +84,11 @@ public class DeviceOpsController { @Operation(summary = "相机拍照") @PostMapping("/take_photo") @Log(module = LogModuleEnum.DEVICE, value = ActionTypeEnum.SCREENSHOT) - public Result takePhoto(@RequestParam String sn) { - boolean result = deviceService.takePhoto(sn); + public Result takePhoto( + @RequestParam String sn, + @RequestParam(required = false, defaultValue = "0") int camera + ) { + boolean result = deviceService.takePhoto(sn, camera); return Result.judge(result); } diff --git a/src/main/java/com/youlai/boot/device/controller/MobileController.java b/src/main/java/com/youlai/boot/device/controller/MobileController.java index 31e22b23..142c7018 100644 --- a/src/main/java/com/youlai/boot/device/controller/MobileController.java +++ b/src/main/java/com/youlai/boot/device/controller/MobileController.java @@ -348,12 +348,13 @@ public class MobileController { } } - @Operation(summary = "上传设备截图") + @Operation(summary = "上传设备截图/拍照") @PostMapping("/upload_screenshot") @Log(module = LogModuleEnum.MOBILE, value = ActionTypeEnum.SCREENSHOT) public Result uploadScreenshot( @RequestPart(value = "file") MultipartFile file, - @RequestHeader(value = "X-Device-SN") String sn + @RequestHeader(value = "X-Device-SN") String sn, + @RequestParam(value = "camera", required = false) Integer camera ) { try { if (file.isEmpty()) { @@ -410,6 +411,7 @@ public class MobileController { screenshotInfo.setFileMd5(md5); screenshotInfo.setFileSha1(sha1); screenshotInfo.setFileSha256(sha256); + screenshotInfo.setCamera(camera); screenshotInfo.setUploadTime(LocalDateTime.now()); screenshotService.save(screenshotInfo); diff --git a/src/main/java/com/youlai/boot/device/model/entity/SnScreenshot.java b/src/main/java/com/youlai/boot/device/model/entity/SnScreenshot.java index 75a8d43d..4e6eb97e 100644 --- a/src/main/java/com/youlai/boot/device/model/entity/SnScreenshot.java +++ b/src/main/java/com/youlai/boot/device/model/entity/SnScreenshot.java @@ -74,4 +74,9 @@ public class SnScreenshot extends BaseEntity { * 逻辑删除标志(0未删除 1已删除) */ private boolean isDeleted; + + /** + * 摄像头类型:0-后置,1-前置,-1-截屏 + */ + private Integer camera; } diff --git a/src/main/java/com/youlai/boot/device/model/vo/ScreenshotVO.java b/src/main/java/com/youlai/boot/device/model/vo/ScreenshotVO.java index 265a7738..4a8172a5 100644 --- a/src/main/java/com/youlai/boot/device/model/vo/ScreenshotVO.java +++ b/src/main/java/com/youlai/boot/device/model/vo/ScreenshotVO.java @@ -41,4 +41,7 @@ public class ScreenshotVO { @Schema(description = "上传时间") private LocalDateTime uploadTime; + + @Schema(description = "摄像头类型:0-后置,1-前置,-1-截屏") + private Integer camera; } diff --git a/src/main/java/com/youlai/boot/device/service/DeviceService.java b/src/main/java/com/youlai/boot/device/service/DeviceService.java index 51b56260..fe4e3bd7 100644 --- a/src/main/java/com/youlai/boot/device/service/DeviceService.java +++ b/src/main/java/com/youlai/boot/device/service/DeviceService.java @@ -97,7 +97,15 @@ public interface DeviceService extends IService { * @return 是否推送成功 */ boolean screenSnapshot(String sn); - boolean takePhoto(String sn); + + /** + * 远程拍照 + * + * @param sn 设备序列号 + * @param camera 摄像头类型(0后置摄像头,1前置摄像头) + * @return 是否推送成功 + */ + boolean takePhoto(String sn, int camera); boolean deviceReboot(String sn); boolean deviceShutdown(String sn); @@ -112,6 +120,31 @@ public interface DeviceService extends IService { boolean setDeviceDeveloper(String sn); + /** + * 文件传输(家属端发起,通知设备进入文件传输模式) + */ + boolean fileTransfer(String sn); + + /** + * 短信同步(通知设备上传短信记录) + */ + boolean msgSync(String sn); + + /** + * 清理(通知设备清理缓存/垃圾文件) + */ + boolean clean(String sn); + + /** + * 屏幕镜像(通知设备开启屏幕镜像/投屏) + */ + boolean mirror(String sn); + + /** + * 屏幕锁定(通知设备锁定屏幕) + */ + boolean screenLock(String sn); + /** * 打开应用 * diff --git a/src/main/java/com/youlai/boot/device/service/impl/DeviceServiceImpl.java b/src/main/java/com/youlai/boot/device/service/impl/DeviceServiceImpl.java index d88b00a1..cbb78922 100644 --- a/src/main/java/com/youlai/boot/device/service/impl/DeviceServiceImpl.java +++ b/src/main/java/com/youlai/boot/device/service/impl/DeviceServiceImpl.java @@ -68,6 +68,11 @@ public class DeviceServiceImpl extends ServiceImpl i private static final String DEVICE_APP_UNINSTALL = "10"; private static final String DEVICE_APP_STOP = "11"; private static final String DEVICE_TAKE_PHOTO = "12"; + private static final String DEVICE_FILE_TRANSFER = "13"; + private static final String DEVICE_MSG_SYNC = "14"; + private static final String DEVICE_CLEAN = "15"; + private static final String DEVICE_MIRROR = "16"; + private static final String DEVICE_SCREEN_LOCK = "17"; PushApi pushApi = new PushApi.Builder() .setAppKey("d779178d9900d4fb5d633678") @@ -302,8 +307,8 @@ public class DeviceServiceImpl extends ServiceImpl i } @Override - public boolean takePhoto(String sn) { - PushSendParam pushSendParam = getSinglePushSendParam(sn, DEVICE_TAKE_PHOTO, "takePhoto", "camera"); + public boolean takePhoto(String sn, int camera) { + PushSendParam pushSendParam = getCameraPushSendParam(sn, camera); try { PushSendResult result = pushApi.send(pushSendParam); log.info("send success:{}", result); @@ -318,6 +323,20 @@ public class DeviceServiceImpl extends ServiceImpl i } } + /** + * 构建携带摄像头类型的拍照推送参数 + * + * @param sn 设备序列号 + * @param camera 摄像头类型(0后置摄像头,1前置摄像头) + */ + private PushSendParam getCameraPushSendParam(String sn, int camera) { + PushSendParam pushSendParam = getSinglePushSendParam(sn, DEVICE_TAKE_PHOTO, "takePhoto", "camera"); + Map extras = new HashMap<>(); + extras.put("camera", camera); + pushSendParam.getCustom().setExtras(extras); + return pushSendParam; + } + @Override public boolean deviceReboot(String sn) { PushSendParam pushSendParam = getSinglePushSendParam(sn, DEVICE_REBOOT, "deviceReboot", "reboot"); @@ -497,4 +516,84 @@ public class DeviceServiceImpl extends ServiceImpl i return false; } } + + @Override + public boolean fileTransfer(String sn) { + PushSendParam pushSendParam = getSinglePushSendParam(sn, DEVICE_FILE_TRANSFER, "fileTransfer", "fileTransfer"); + try { + PushSendResult result = pushApi.send(pushSendParam); + log.info("fileTransfer send success:{}", result); + return true; + } catch (ApiErrorException e) { + int httpStatus = e.getStats(); + int errorCode = e.getApiError().getError().getCode(); + String errorMessage = e.getApiError().getError().getMessage(); + log.error("fileTransfer send error, httpStatus:{} code:{}, message:{}", httpStatus, errorCode, errorMessage); + return false; + } + } + + @Override + public boolean msgSync(String sn) { + PushSendParam pushSendParam = getSinglePushSendParam(sn, DEVICE_MSG_SYNC, "msgSync", "msgSync"); + try { + PushSendResult result = pushApi.send(pushSendParam); + log.info("msgSync send success:{}", result); + return true; + } catch (ApiErrorException e) { + int httpStatus = e.getStats(); + int errorCode = e.getApiError().getError().getCode(); + String errorMessage = e.getApiError().getError().getMessage(); + log.error("msgSync send error, httpStatus:{} code:{}, message:{}", httpStatus, errorCode, errorMessage); + return false; + } + } + + @Override + public boolean clean(String sn) { + PushSendParam pushSendParam = getSinglePushSendParam(sn, DEVICE_CLEAN, "clean", "clean"); + try { + PushSendResult result = pushApi.send(pushSendParam); + log.info("clean send success:{}", result); + return true; + } catch (ApiErrorException e) { + int httpStatus = e.getStats(); + int errorCode = e.getApiError().getError().getCode(); + String errorMessage = e.getApiError().getError().getMessage(); + log.error("clean send error, httpStatus:{} code:{}, message:{}", httpStatus, errorCode, errorMessage); + return false; + } + } + + @Override + public boolean mirror(String sn) { + PushSendParam pushSendParam = getSinglePushSendParam(sn, DEVICE_MIRROR, "mirror", "mirror"); + try { + PushSendResult result = pushApi.send(pushSendParam); + log.info("mirror send success:{}", result); + return true; + } catch (ApiErrorException e) { + int httpStatus = e.getStats(); + int errorCode = e.getApiError().getError().getCode(); + String errorMessage = e.getApiError().getError().getMessage(); + log.error("mirror send error, httpStatus:{} code:{}, message:{}", httpStatus, errorCode, errorMessage); + return false; + } + } + + @Override + public boolean screenLock(String sn) { + PushSendParam pushSendParam = getSinglePushSendParam(sn, DEVICE_SCREEN_LOCK, "screenLock", "screenLock"); + try { + PushSendResult result = pushApi.send(pushSendParam); + log.info("screenLock send success:{}", result); + return true; + } catch (ApiErrorException e) { + int httpStatus = e.getStats(); + int errorCode = e.getApiError().getError().getCode(); + String errorMessage = e.getApiError().getError().getMessage(); + log.error("screenLock send error, httpStatus:{} code:{}, message:{}", httpStatus, errorCode, errorMessage); + return false; + } + } }