drone-common/src/main/java/org/sxkj/common/constant/WordOrderConstant.java
@@ -4,7 +4,11 @@ // 订单号前缀 String ORDER_PREFIX = "GD"; // 巡查任务号前缀 String PATROL_TASK_PREFIX = "RW"; // 订单号redisKEY String ORDER_REDIS_KEY = "wordOrderInfo"; // 巡查任务key String PATROL_TASK_KEY = "patrolTaskInfo"; } drone-ops/drone-resource/src/main/java/org/sxkj/resource/controller/AttachController.java
@@ -80,33 +80,6 @@ return R.data(detail); } @GetMapping("/test") public R test(@RequestParam(required = true) Date startTime, @RequestParam(required = true) Date endTime) { CacheUtil.clear(RESOURCE_CACHE); attachClient.processingYesterdayVideo(startTime, endTime); return R.success("成功"); } @GetMapping("/getlotInfoList") public ResponseResult getlotInfoList(@ApiParam Long lotInfoId) { return ResponseResult.success(attachService.getlotInfoList(lotInfoId)); } /** * 分页 附件表 */ @GetMapping("/list") @ApiOperationSupport(order = 2) @ApiOperation(value = "附件分页", notes = "传入attach") public R<IPage<Attach>> list(Attach attach, Query query) { List<String> wayLineJobIds = attach.getWayLineJobIds(); QueryWrapper<Attach> queryWrapper1 = Condition.getQueryWrapper(attach); QueryWrapper<Attach> queryWrapper = queryWrapper1.in(!CollectionUtils.isEmpty(wayLineJobIds), "wayline_job_id", wayLineJobIds); queryWrapper.eq("is_deleted", 0); IPage<Attach> pages = attachService.page(Condition.getPage(query), queryWrapper); return R.data(pages); } /** * 自定义分页 附件表 */ @@ -119,83 +92,6 @@ IPage<AttachVO> pages = attachService.selectAttachPage(Condition.getPage(query), attach); AttachVO.settingNickName(pages.getRecords()); return R.data(pages); } /** * 自定义分页 附件表 */ @PostMapping("/aiImagesPage") @ApiOperationSupport(order = 3) @ApiOperation(value = "自定义分页附件表分页", notes = "ai分页数据") public R<IPage<AttachVO>> aiPage(@RequestBody AttachVO attach, Query query) { String areaCode = HeaderUtils.getAreaCode(); attach.setAreaCode(areaCode); List<Integer> resultTypes = attach.getResultTypes(); String wordOrderType = attach.getWordOrderType(); settingResultType(attach, wordOrderType, resultTypes); if (Objects.nonNull(attach.getAiStatus()) && Objects.nonNull(attach.getResultTypes()) && attach.getResultTypes().contains(Attach.RESULT_TYPE_AI)) { attach.setResultTypes(Arrays.asList(Attach.RESULT_TYPE_AI)); } List<String> aiEventMd5s = attachService.findAiEventMd5s(attach.getEventRecordIds()); attach.setMd5s(aiEventMd5s); if (!CollectionUtils.isEmpty(attach.getEventRecordIds())) { attach.setResultTypes(Arrays.asList(Attach.RESULT_TYPE_AI, Attach.RESULT_TYPE_IMG)); } IPage page = Condition.getPage(query); List<AttachVO> aiAttachImages = attachService.findAiAttachImages(page, attach); AttachVO.settingNickName(aiAttachImages); page.setRecords(aiAttachImages); return R.data(page); } /** * 后台数据中心列表接口 */ @PostMapping("/attachmentsPage") @ApiOperationSupport(order = 4) @ApiOperation(value = "后台数据中心列表接口") public R<IPage<AttachVO>> attachmentsPage(@RequestBody AttachVO attach, Query query) { IPage page = Condition.getPage(query); IPage attachPage = attachService.findAttachImages(page, attach); return R.data(attachPage); } private static void settingResultType(AttachVO attach, String wordOrderType, List<Integer> resultTypes) { if (!StringUtils.isEmpty(wordOrderType) && !CollectionUtils.isEmpty(resultTypes)) { if ("-1".equals(wordOrderType)) { attach.setWordOrderType(null); if (resultTypes.contains(Attach.RESULT_TYPE_IMG)) { resultTypes = Arrays.asList(Attach.RESULT_TYPE_IMG); } } else { if (resultTypes.contains(Attach.RESULT_TYPE_AI)) { resultTypes = Arrays.asList(Attach.RESULT_TYPE_AI); } } attach.setResultTypes(resultTypes); } } /** * 新增 附件表 */ @PostMapping("/save") @ApiOperationSupport(order = 4) @ApiOperation(value = "新增", notes = "传入attach") public R save(@Valid @RequestBody Attach attach) { return R.status(attachService.save(attach)); } /** * 修改 附件表 */ @PostMapping("/update") @ApiOperationSupport(order = 5) @ApiOperation(value = "修改", notes = "传入attach") public R update(@Valid @RequestBody Attach attach) { return R.status(attachService.updateById(attach)); } /** @@ -221,70 +117,161 @@ .in(Attach::getId, Func.toLongList(ids)))); } // @GetMapping("/test") // public R test(@RequestParam(required = true) Date startTime, @RequestParam(required = true) Date endTime) { // CacheUtil.clear(RESOURCE_CACHE); // attachClient.processingYesterdayVideo(startTime, endTime); // return R.success("成功"); // } // @GetMapping("/getlotInfoList") // public ResponseResult getlotInfoList(@ApiParam Long lotInfoId) { // return ResponseResult.success(attachService.getlotInfoList(lotInfoId)); // } /** * 分页 附件表 */ // @GetMapping("/list") // @ApiOperationSupport(order = 2) // @ApiOperation(value = "附件分页", notes = "传入attach") // public R<IPage<Attach>> list(Attach attach, Query query) { // List<String> wayLineJobIds = attach.getWayLineJobIds(); // QueryWrapper<Attach> queryWrapper1 = Condition.getQueryWrapper(attach); // QueryWrapper<Attach> queryWrapper = queryWrapper1.in(!CollectionUtils.isEmpty(wayLineJobIds), "wayline_job_id", wayLineJobIds); // queryWrapper.eq("is_deleted", 0); // IPage<Attach> pages = attachService.page(Condition.getPage(query), queryWrapper); // return R.data(pages); // } /** * 自定义分页 附件表 */ // @PostMapping("/aiImagesPage") // @ApiOperationSupport(order = 3) // @ApiOperation(value = "自定义分页附件表分页", notes = "ai分页数据") // public R<IPage<AttachVO>> aiPage(@RequestBody AttachVO attach, Query query) { // String areaCode = HeaderUtils.getAreaCode(); // attach.setAreaCode(areaCode); // List<Integer> resultTypes = attach.getResultTypes(); // String wordOrderType = attach.getWordOrderType(); // settingResultType(attach, wordOrderType, resultTypes); // if (Objects.nonNull(attach.getAiStatus()) && Objects.nonNull(attach.getResultTypes()) // && attach.getResultTypes().contains(Attach.RESULT_TYPE_AI)) { // attach.setResultTypes(Arrays.asList(Attach.RESULT_TYPE_AI)); // } // List<String> aiEventMd5s = attachService.findAiEventMd5s(attach.getEventRecordIds()); // attach.setMd5s(aiEventMd5s); // if (!CollectionUtils.isEmpty(attach.getEventRecordIds())) { // attach.setResultTypes(Arrays.asList(Attach.RESULT_TYPE_AI, Attach.RESULT_TYPE_IMG)); // } // IPage page = Condition.getPage(query); // List<AttachVO> aiAttachImages = attachService.findAiAttachImages(page, attach); // AttachVO.settingNickName(aiAttachImages); // page.setRecords(aiAttachImages); // return R.data(page); // } /** * 后台数据中心列表接口 */ // @PostMapping("/attachmentsPage") // @ApiOperationSupport(order = 4) // @ApiOperation(value = "后台数据中心列表接口") // public R<IPage<AttachVO>> attachmentsPage(@RequestBody AttachVO attach, Query query) { // IPage page = Condition.getPage(query); // IPage attachPage = attachService.findAttachImages(page, attach); // return R.data(attachPage); // } /** * 新增 附件表 */ // @PostMapping("/save") // @ApiOperationSupport(order = 4) // @ApiOperation(value = "新增", notes = "传入attach") // public R save(@Valid @RequestBody Attach attach) { // return R.status(attachService.save(attach)); // } /** * 修改 附件表 */ // @PostMapping("/update") // @ApiOperationSupport(order = 5) // @ApiOperation(value = "修改", notes = "传入attach") // public R update(@Valid @RequestBody Attach attach) { // return R.status(attachService.updateById(attach)); // } /** * 删除 附件表及对应的附件信息 * * @param ids * @return */ @PostMapping("/removeAttachAndData") @ApiOperationSupport(order = 9) @ApiOperation(value = "删除", notes = "传入ids") @PreAuth(RoleConstant.HAS_ROLE_ADMINISTRATOR) public R removeAttachAndData(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) { return R.status(attachService.removeBatchAndDataByIds(Func.toLongList(ids))); } // @PostMapping("/removeAttachAndData") // @ApiOperationSupport(order = 9) // @ApiOperation(value = "删除", notes = "传入ids") // @PreAuth(RoleConstant.HAS_ROLE_ADMINISTRATOR) // public R removeAttachAndData(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) { // return R.status(attachService.removeBatchAndDataByIds(Func.toLongList(ids))); // } @GetMapping("/deptSize") @ApiOperationSupport(order = 8) @ApiOperation(value = "获取部门文件大小") public R<List<DeptAndSizeVo>> getDeptSize(@RequestParam String startTime, @RequestParam String endTime) { return R.data(attachService.getDeptAllSize(startTime, endTime)); } // @GetMapping("/deptSize") // @ApiOperationSupport(order = 8) // @ApiOperation(value = "获取部门文件大小") // public R<List<DeptAndSizeVo>> getDeptSize(@RequestParam String startTime, @RequestParam String endTime) { // return R.data(attachService.getDeptAllSize(startTime, endTime)); // } /** * 历史正射图片处理 * * @return */ @GetMapping("/hisOrtPicHandler") @ApiOperationSupport(order = 9) @ApiOperation(value = "历史正射图片处理") public R hisOrtPicHandler() { return R.data(attachService.hisOrtPicHandler()); } // @GetMapping("/hisOrtPicHandler") // @ApiOperationSupport(order = 9) // @ApiOperation(value = "历史正射图片处理") // public R hisOrtPicHandler() { // return R.data(attachService.hisOrtPicHandler()); // } /** * 自动更新附件表md5值 * * @return */ @GetMapping("saveMd5") public R saveMd5() { attachService.saveMd5(); return R.success(""); } // @GetMapping("saveMd5") // public R saveMd5() { // attachService.saveMd5(); // return R.success(""); // } @ApiOperation(value = "地图位置上图片数据", notes = "") @PostMapping("/mapAttachs") public ResponseResult<TreeVo> mapEvents(@RequestBody AttachQueryParam dto) { if (Objects.nonNull(dto.getDateEnum())) { TimeRange timeRange = TimeRangeUtils.getTimeRange(dto.getDateEnum()); dto.setStartDate(timeRange.getStartTime()); dto.setEndDate(timeRange.getEndTime()); } if (Objects.nonNull(dto.getStartDate())) { dto.setStartTime(TimeRangeUtils.getEpochMilli(dto.getStartDate())); } if (Objects.nonNull(dto.getEndDate())) { dto.setEndTime(TimeRangeUtils.getEpochMilli(dto.getEndDate())); } String areaCode = HeaderUtils.getHeader(CommonConstant.AREA_CODE).orElse(null); dto.setAreaCode(!StringUtils.isEmpty(dto.getAreaCode()) ? dto.getAreaCode() : areaCode); TreeVo treeVo = attachService.mapAttachEvents(dto); return ResponseResult.success(treeVo); } // @ApiOperation(value = "地图位置上图片数据", notes = "") // @PostMapping("/mapAttachs") // public ResponseResult<TreeVo> mapEvents(@RequestBody AttachQueryParam dto) { // if (Objects.nonNull(dto.getDateEnum())) { // TimeRange timeRange = TimeRangeUtils.getTimeRange(dto.getDateEnum()); // dto.setStartDate(timeRange.getStartTime()); // dto.setEndDate(timeRange.getEndTime()); // } // if (Objects.nonNull(dto.getStartDate())) { // dto.setStartTime(TimeRangeUtils.getEpochMilli(dto.getStartDate())); // } // if (Objects.nonNull(dto.getEndDate())) { // dto.setEndTime(TimeRangeUtils.getEpochMilli(dto.getEndDate())); // } // String areaCode = HeaderUtils.getHeader(CommonConstant.AREA_CODE).orElse(null); // dto.setAreaCode(!StringUtils.isEmpty(dto.getAreaCode()) ? dto.getAreaCode() : areaCode); // TreeVo treeVo = attachService.mapAttachEvents(dto); // return ResponseResult.success(treeVo); // } /** * 图片分析对比 前后图片对比 @@ -292,33 +279,33 @@ * @param id 图片id * @return */ @GetMapping("contrastiveAnalysis") public ResponseResult contrastiveAnalysis(@RequestParam() Long id) { List<AnalysisAttachVo> list = attachService.contrastiveAnalysis(id); return ResponseResult.success(list); } // @GetMapping("contrastiveAnalysis") // public ResponseResult contrastiveAnalysis(@RequestParam() Long id) { // List<AnalysisAttachVo> list = attachService.contrastiveAnalysis(id); // return ResponseResult.success(list); // } @ApiOperation(value = "附件详情", notes = "") @GetMapping("/getAttachInfo") public ResponseResult<AttachInfoVO> getAttachInfo(@ApiParam(value = "附件iD") @RequestParam("id") Long id) throws IOException { return ResponseResult.success(attachService.getAttachInfo(id)); } // @ApiOperation(value = "附件详情", notes = "") // @GetMapping("/getAttachInfo") // public ResponseResult<AttachInfoVO> getAttachInfo(@ApiParam(value = "附件iD") @RequestParam("id") Long id) throws IOException { // return ResponseResult.success(attachService.getAttachInfo(id)); // } @ApiOperation(value = "通过任务id查询附件详情集合", notes = "") @GetMapping("/getAttachInfoByJobId") public ResponseResult<List<AttachInfoVO>> getAttachInfoByJobId(@ApiParam(value = "任务id") @RequestParam("jobId") String jobId) throws IOException { return ResponseResult.success(attachService.getAttachInfoByJobId(jobId)); } // @ApiOperation(value = "通过任务id查询附件详情集合", notes = "") // @GetMapping("/getAttachInfoByJobId") // public ResponseResult<List<AttachInfoVO>> getAttachInfoByJobId(@ApiParam(value = "任务id") @RequestParam("jobId") String jobId) throws IOException { // return ResponseResult.success(attachService.getAttachInfoByJobId(jobId)); // } @ApiLog("修改文件名称") @PostMapping("/updateFileName") public ResponseResult updateFileName(@RequestParam Long id, @RequestParam String nickName) { if (attachService.updateFileName(id, nickName) > 0) { return ResponseResult.success(); } return ResponseResult.error("修改失败"); } // @ApiLog("修改文件名称") // @PostMapping("/updateFileName") // public ResponseResult updateFileName(@RequestParam Long id, @RequestParam String nickName) { // if (attachService.updateFileName(id, nickName) > 0) { // return ResponseResult.success(); // } // return ResponseResult.error("修改失败"); // } /** @@ -326,39 +313,39 @@ * * @return */ @GetMapping("deletedNotExistsUrl") public ResponseResult deletedNotExistsUrl() { attachService.deletedNotExistsUrl(); return ResponseResult.success(); } // @GetMapping("deletedNotExistsUrl") // public ResponseResult deletedNotExistsUrl() { // attachService.deletedNotExistsUrl(); // return ResponseResult.success(); // } @ApiLog("删除图片视频") @DeleteMapping("/deleteMediaFile") public ResponseResult deleteMediaFile(@RequestBody List<Long> ids) { attachService.deleteMediaFile(ids); return ResponseResult.success(); } // @ApiLog("删除图片视频") // @DeleteMapping("/deleteMediaFile") // public ResponseResult deleteMediaFile(@RequestBody List<Long> ids) { // attachService.deleteMediaFile(ids); // return ResponseResult.success(); // } /** * 附件统计 */ @ApiOperation(value = "附件统计", notes = "") @PostMapping("/attachTypeStatistics") public ResponseResult<List<AttachTypeStatisticsVO>> attachTypeStatistics(@RequestBody AttachStatisticsVo attachStatisticsVo) { List<AttachTypeStatisticsVO> result = attachService.attachTypeStatistics(attachStatisticsVo); return ResponseResult.success(result); } // @ApiOperation(value = "附件统计", notes = "") // @PostMapping("/attachTypeStatistics") // public ResponseResult<List<AttachTypeStatisticsVO>> attachTypeStatistics(@RequestBody AttachStatisticsVo attachStatisticsVo) { // List<AttachTypeStatisticsVO> result = attachService.attachTypeStatistics(attachStatisticsVo); // return ResponseResult.success(result); // } /** * 个人中心附件统计 */ @ApiOperation(value = "个人中心附件统计", notes = "") @PostMapping("/getManageAttachTypeStatistics") public ResponseResult<List<LineColumnDateVo>> getManageAttachTypeStatistics(@RequestBody WaylineJobInfoQueryDto dto) { WaylineJobInfoQueryParam param = new WaylineJobInfoQueryParam(dto); param.setFormatTime(ChartDataVo.getTimeFormatByEnum(param.getDateEnum())); List<LineColumnDateVo> result = attachService.getManageAttachTypeStatistics(param); return ResponseResult.success(result); } // @ApiOperation(value = "个人中心附件统计", notes = "") // @PostMapping("/getManageAttachTypeStatistics") // public ResponseResult<List<LineColumnDateVo>> getManageAttachTypeStatistics(@RequestBody WaylineJobInfoQueryDto dto) { // WaylineJobInfoQueryParam param = new WaylineJobInfoQueryParam(dto); // param.setFormatTime(ChartDataVo.getTimeFormatByEnum(param.getDateEnum())); // List<LineColumnDateVo> result = attachService.getManageAttachTypeStatistics(param); // return ResponseResult.success(result); // } } drone-ops/drone-resource/src/main/java/org/sxkj/resource/endpoint/OssEndpoint.java
@@ -1,22 +1,7 @@ /* * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * Neither the name of the dreamlu.net developer nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * Author: Chill 庄骞 (smallchill@163.com) */ package org.sxkj.resource.endpoint; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.AllArgsConstructor; import lombok.SneakyThrows; import org.jetbrains.annotations.NotNull; @@ -28,12 +13,13 @@ import org.springblade.core.tool.constant.RoleConstant; import org.springblade.core.tool.utils.FileUtil; import org.springblade.core.tool.utils.Func; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import org.sxkj.resource.builder.OssBuilder; import org.sxkj.resource.entity.Attach; import org.sxkj.resource.service.IAttachService; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import org.sxkj.resource.util.ImageCompressorUtil; import springfox.documentation.annotations.ApiIgnore; import java.io.IOException; import java.util.HashMap; @@ -48,234 +34,251 @@ @RestController @AllArgsConstructor @RequestMapping("/oss/endpoint") @Api(value = "对象存储端点", tags = "对象存储端点") @Api(value = "对象存储端点", tags = "文件上传接口") public class OssEndpoint { /** * 对象存储构建类 */ private final OssBuilder ossBuilder; /** * 对象存储构建类 */ private final OssBuilder ossBuilder; /** * 附件表服务 */ private final IAttachService attachService; /** * 附件表服务 */ private final IAttachService attachService; /** * 创建存储桶 * * @param bucketName 存储桶名称 * @return Bucket */ @SneakyThrows @PostMapping("/make-bucket") @PreAuth(RoleConstant.HAS_ROLE_ADMIN) public R makeBucket(@RequestParam String bucketName) { ossBuilder.template().makeBucket(bucketName); return R.success("创建成功"); } /** * 创建存储桶 * * @param bucketName 存储桶名称 * @return Bucket */ @SneakyThrows @PostMapping("/make-bucket") @PreAuth(RoleConstant.HAS_ROLE_ADMIN) @ApiIgnore public R makeBucket(@RequestParam String bucketName) { ossBuilder.template().makeBucket(bucketName); return R.success("创建成功"); } /** * 创建存储桶 * * @param bucketName 存储桶名称 * @return R */ @SneakyThrows @PostMapping("/remove-bucket") @PreAuth(RoleConstant.HAS_ROLE_ADMIN) public R removeBucket(@RequestParam String bucketName) { ossBuilder.template().removeBucket(bucketName); return R.success("删除成功"); } /** * 创建存储桶 * * @param bucketName 存储桶名称 * @return R */ @SneakyThrows @PostMapping("/remove-bucket") @PreAuth(RoleConstant.HAS_ROLE_ADMIN) @ApiIgnore public R removeBucket(@RequestParam String bucketName) { ossBuilder.template().removeBucket(bucketName); return R.success("删除成功"); } /** * 拷贝文件 * * @param fileName 存储桶对象名称 * @param destBucketName 目标存储桶名称 * @param destFileName 目标存储桶对象名称 * @return R */ @SneakyThrows @PostMapping("/copy-file") public R copyFile(@RequestParam String fileName, @RequestParam String destBucketName, String destFileName) { ossBuilder.template().copyFile(fileName, destBucketName, destFileName); return R.success("操作成功"); } /** * 拷贝文件 * * @param fileName 存储桶对象名称 * @param destBucketName 目标存储桶名称 * @param destFileName 目标存储桶对象名称 * @return R */ @SneakyThrows @PostMapping("/copy-file") @ApiOperation(value = "拷贝文件", notes = "拷贝文件") public R copyFile(@RequestParam String fileName, @RequestParam String destBucketName, String destFileName) { ossBuilder.template().copyFile(fileName, destBucketName, destFileName); return R.success("操作成功"); } /** * 获取文件信息 * * @param fileName 存储桶对象名称 * @return InputStream */ @SneakyThrows @GetMapping("/stat-file") public R<OssFile> statFile(@RequestParam String fileName) { return R.data(ossBuilder.template().statFile(fileName)); } /** * 获取文件信息 * * @param fileName 存储桶对象名称 * @return InputStream */ @SneakyThrows @GetMapping("/stat-file") @ApiOperation(value = "获取文件信息", notes = "获取文件信息") public R<OssFile> statFile(@RequestParam String fileName) { return R.data(ossBuilder.template().statFile(fileName)); } /** * 获取文件相对路径 * * @param fileName 存储桶对象名称 * @return String */ @SneakyThrows @GetMapping("/file-path") public R<String> filePath(@RequestParam String fileName) { return R.data(ossBuilder.template().filePath(fileName)); } /** * 获取文件相对路径 * * @param fileName 存储桶对象名称 * @return String */ @SneakyThrows @GetMapping("/file-path") @ApiOperation(value = "获取文件相对路径", notes = "获取文件相对路径") public R<String> filePath(@RequestParam String fileName) { return R.data(ossBuilder.template().filePath(fileName)); } /** * 获取文件外链 * * @param fileName 存储桶对象名称 * @return String */ @SneakyThrows @GetMapping("/file-link") public R<String> fileLink(@RequestParam String fileName) { return R.data(ossBuilder.template().fileLink(fileName)); } /** * 获取文件外链 * * @param fileName 存储桶对象名称 * @return String */ @SneakyThrows @GetMapping("/file-link") @ApiOperation(value = "获取文件外链", notes = "获取文件外链") public R<String> fileLink(@RequestParam String fileName) { return R.data(ossBuilder.template().fileLink(fileName)); } /** * 上传文件 * * @param file 文件 * @return ObjectStat */ @SneakyThrows @PostMapping("/put-file") public R<BladeFile> putFile(@RequestParam MultipartFile file) { BladeFile bladeFile = ossBuilder.template().putFile(file.getOriginalFilename(), file.getInputStream()); return R.data(bladeFile); } /** * 上传文件 * * @param file 文件 * @return ObjectStat */ @SneakyThrows @PostMapping("/put-file") @ApiOperation(value = "上传文件", notes = "上传文件") public R<BladeFile> putFile(@RequestParam MultipartFile file) { BladeFile bladeFile = ossBuilder.template().putFile(file.getOriginalFilename(), file.getInputStream()); return R.data(bladeFile); } /** * 上传文件 * * @param fileName 存储桶对象名称 * @param file 文件 * @return ObjectStat */ @SneakyThrows @PostMapping("/put-file-by-name") public R<BladeFile> putFile(@RequestParam String fileName, @RequestParam MultipartFile file) { BladeFile bladeFile = ossBuilder.template().putFile(fileName, file.getInputStream()); return R.data(bladeFile); } /** * 上传文件 * * @param fileName 存储桶对象名称 * @param file 文件 * @return ObjectStat */ @SneakyThrows @PostMapping("/put-file-by-name") @ApiOperation(value = "上传文件", notes = "上传文件-存储桶对象名称") public R<BladeFile> putFile(@RequestParam String fileName, @RequestParam MultipartFile file) { BladeFile bladeFile = ossBuilder.template().putFile(fileName, file.getInputStream()); return R.data(bladeFile); } /** * 上传文件并保存至附件表 * * @param file 文件 * @return ObjectStat */ @SneakyThrows @PostMapping("/put-file-attach") public R<BladeFile> putFileAttach(@RequestParam MultipartFile file) { BladeFile bladeFile = getBladeFile(file); return R.data(bladeFile); } /** * 上传文件并保存至附件表 * * @param file 文件 * @return ObjectStat */ @SneakyThrows @PostMapping("/put-file-attach") @ApiOperation(value = "上传文件并保存至附件表", notes = "上传文件并保存至附件表") public R<BladeFile> putFileAttach(@RequestParam MultipartFile file) { BladeFile bladeFile = getBladeFile(file); return R.data(bladeFile); } /** * 上传文件并保存至附件表 * * @param fileName 存储桶对象名称 * @param file 文件 * @return ObjectStat */ @SneakyThrows @PostMapping("/put-file-attach-by-name") public R<BladeFile> putFileAttach(@RequestParam String fileName, @RequestParam MultipartFile file) { BladeFile bladeFile = ossBuilder.template().putFile(fileName, file.getInputStream()); Long attachId = buildAttach(fileName, file.getSize(), bladeFile); bladeFile.setAttachId(attachId); return R.data(bladeFile); } /** * 上传文件并保存至附件表 * * @param fileName 存储桶对象名称 * @param resultType 结果类型 * @param file 上传文件 * @return BladeFile */ @SneakyThrows @PostMapping("/put-file-attach-by-name") @ApiOperation(value = "上传文件并保存至附件表", notes = "上传文件并保存至附件表-存储桶对象名称") public R<BladeFile> putFileAttach(@RequestParam String fileName, @RequestParam Integer resultType, @RequestParam MultipartFile file) { BladeFile bladeFile = ossBuilder.template().putFile(fileName, file.getInputStream()); Long attachId = buildAttach(fileName, resultType, file.getSize(), bladeFile); bladeFile.setAttachId(attachId); return R.data(bladeFile); } /** * 上传原图和压缩图并保存至附件表 * * @param file 文件 * @return ObjectStat */ @SneakyThrows @PostMapping("/put-file-cop-attach") public R putFileCopAttach(@RequestParam MultipartFile file) { // 上传之前先压缩 MultipartFile compressImage = ImageCompressorUtil.compressImage(file,null); // 上传 BladeFile bladeFile = getBladeFile(file); BladeFile compressFile = getBladeFile(compressImage); // Map<String, Object> map = new HashMap<>(2); map.put("yt",bladeFile); map.put("yst",compressFile); // 返回 return R.data(bladeFile); } /** * 上传原图和压缩图并保存至附件表 * * @param file 文件 * @return ObjectStat */ @SneakyThrows @PostMapping("/put-file-cop-attach") @ApiOperation(value = "上传原图和压缩图并保存至附件表", notes = "上传原图和压缩图并保存至附件表") public R putFileCopAttach(@RequestParam MultipartFile file) { // 上传之前先压缩 MultipartFile compressImage = ImageCompressorUtil.compressImage(file, null); // 上传 BladeFile bladeFile = getBladeFile(file); BladeFile compressFile = getBladeFile(compressImage); // Map<String, Object> map = new HashMap<>(2); map.put("yt", bladeFile); map.put("yst", compressFile); // 返回 return R.data(bladeFile); } @NotNull private BladeFile getBladeFile(@RequestParam MultipartFile file) throws IOException { String fileName = file.getOriginalFilename(); BladeFile bladeFile = ossBuilder.template().putFile(fileName, file.getInputStream()); Long attachId = buildAttach(fileName, file.getSize(), bladeFile); bladeFile.setAttachId(attachId); return bladeFile; } @NotNull private BladeFile getBladeFile(@RequestParam MultipartFile file) throws IOException { String fileName = file.getOriginalFilename(); BladeFile bladeFile = ossBuilder.template().putFile(fileName, file.getInputStream()); Long attachId = buildAttach(fileName, null, file.getSize(), bladeFile); bladeFile.setAttachId(attachId); return bladeFile; } /** * 构建附件表 * * @param fileName 文件名 * @param fileSize 文件大小 * @param bladeFile 对象存储文件 * @return attachId */ private Long buildAttach(String fileName, Long fileSize, BladeFile bladeFile) { String fileExtension = FileUtil.getFileExtension(fileName); Attach attach = new Attach(); attach.setDomainUrl(bladeFile.getDomain()); attach.setLink(bladeFile.getLink()); attach.setName(bladeFile.getName()); attach.setOriginalName(bladeFile.getOriginalName()); attach.setAttachSize(fileSize); attach.setExtension(fileExtension); attachService.save(attach); return attach.getId(); } /** * 构建附件表 * * @param fileName 文件名 * @param fileSize 文件大小 * @param bladeFile 对象存储文件 * @return attachId */ private Long buildAttach(String fileName, Integer resultType, Long fileSize, BladeFile bladeFile) { String fileExtension = FileUtil.getFileExtension(fileName); Attach attach = new Attach(); attach.setDomainUrl(bladeFile.getDomain()); attach.setLink(bladeFile.getLink()); attach.setName(bladeFile.getName()); attach.setResultType(resultType); attach.setOriginalName(bladeFile.getOriginalName()); attach.setAttachSize(fileSize); attach.setExtension(fileExtension); attachService.save(attach); return attach.getId(); } /** * 删除文件 * * @param fileName 存储桶对象名称 * @return R */ @SneakyThrows @PostMapping("/remove-file") @PreAuth(RoleConstant.HAS_ROLE_ADMIN) public R removeFile(@RequestParam String fileName) { ossBuilder.template().removeFile(fileName); return R.success("操作成功"); } /** * 删除文件 * * @param fileName 存储桶对象名称 * @return R */ @SneakyThrows @PostMapping("/remove-file") @PreAuth(RoleConstant.HAS_ROLE_ADMIN) @ApiOperation(value = "删除文件", notes = "删除文件") public R removeFile(@RequestParam String fileName) { ossBuilder.template().removeFile(fileName); return R.success("操作成功"); } /** * 批量删除文件 * * @param fileNames 存储桶对象名称集合 * @return R */ @SneakyThrows @PostMapping("/remove-files") @PreAuth(RoleConstant.HAS_ROLE_ADMIN) public R removeFiles(@RequestParam String fileNames) { ossBuilder.template().removeFiles(Func.toStrList(fileNames)); return R.success("操作成功"); } /** * 批量删除文件 * * @param fileNames 存储桶对象名称集合 * @return R */ @SneakyThrows @PostMapping("/remove-files") @PreAuth(RoleConstant.HAS_ROLE_ADMIN) @ApiOperation(value = "批量删除文件", notes = "批量删除文件") public R removeFiles(@RequestParam String fileNames) { ossBuilder.template().removeFiles(Func.toStrList(fileNames)); return R.success("操作成功"); } } drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/controller/GdWorkOrderFlowController.java
@@ -72,13 +72,13 @@ /** * 流程记录表 分页 */ @GetMapping("/list") @ApiOperationSupport(order = 2) @ApiOperation(value = "分页", notes = "传入gdWorkOrderFlow") public R<IPage<GdWorkOrderFlowVO>> list(@ApiIgnore @RequestParam Map<String, Object> gdWorkOrderFlow, Query query) { IPage<GdWorkOrderFlowEntity> pages = gdWorkOrderFlowService.page(Condition.getPage(query), Condition.getQueryWrapper(gdWorkOrderFlow, GdWorkOrderFlowEntity.class)); return R.data(GdWorkOrderFlowWrapper.build().pageVO(pages)); } // @GetMapping("/list") // @ApiOperationSupport(order = 2) // @ApiOperation(value = "分页", notes = "传入gdWorkOrderFlow") // public R<IPage<GdWorkOrderFlowVO>> list(@ApiIgnore @RequestParam Map<String, Object> gdWorkOrderFlow, Query query) { // IPage<GdWorkOrderFlowEntity> pages = gdWorkOrderFlowService.page(Condition.getPage(query), Condition.getQueryWrapper(gdWorkOrderFlow, GdWorkOrderFlowEntity.class)); // return R.data(GdWorkOrderFlowWrapper.build().pageVO(pages)); // } /** * 流程记录表 自定义分页 @@ -104,32 +104,32 @@ /** * 流程记录表 修改 */ @PostMapping("/update") @ApiOperationSupport(order = 5) @ApiOperation(value = "修改", notes = "传入gdWorkOrderFlow") public R update(@Valid @RequestBody GdWorkOrderFlowEntity gdWorkOrderFlow) { return R.status(gdWorkOrderFlowService.updateById(gdWorkOrderFlow)); } // @PostMapping("/update") // @ApiOperationSupport(order = 5) // @ApiOperation(value = "修改", notes = "传入gdWorkOrderFlow") // public R update(@Valid @RequestBody GdWorkOrderFlowEntity gdWorkOrderFlow) { // return R.status(gdWorkOrderFlowService.updateById(gdWorkOrderFlow)); // } /** * 流程记录表 新增或修改 */ @PostMapping("/submit") @ApiOperationSupport(order = 6) @ApiOperation(value = "新增或修改", notes = "传入gdWorkOrderFlow") public R submit(@Valid @RequestBody GdWorkOrderFlowEntity gdWorkOrderFlow) { return R.status(gdWorkOrderFlowService.saveOrUpdate(gdWorkOrderFlow)); } // @PostMapping("/submit") // @ApiOperationSupport(order = 6) // @ApiOperation(value = "新增或修改", notes = "传入gdWorkOrderFlow") // public R submit(@Valid @RequestBody GdWorkOrderFlowEntity gdWorkOrderFlow) { // return R.status(gdWorkOrderFlowService.saveOrUpdate(gdWorkOrderFlow)); // } /** * 流程记录表 删除 */ @PostMapping("/remove") @ApiOperationSupport(order = 7) @ApiOperation(value = "逻辑删除", notes = "传入ids") public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) { return R.status(gdWorkOrderFlowService.deleteLogic(Func.toLongList(ids))); } // @PostMapping("/remove") // @ApiOperationSupport(order = 7) // @ApiOperation(value = "逻辑删除", notes = "传入ids") // public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) { // return R.status(gdWorkOrderFlowService.deleteLogic(Func.toLongList(ids))); // } /** @@ -138,6 +138,7 @@ @GetMapping("/export-gdWorkOrderFlow") @ApiOperationSupport(order = 9) @ApiOperation(value = "导出数据", notes = "传入gdWorkOrderFlow") @ApiIgnore public void exportGdWorkOrderFlow(@ApiIgnore @RequestParam Map<String, Object> gdWorkOrderFlow, BladeUser bladeUser, HttpServletResponse response) { QueryWrapper<GdWorkOrderFlowEntity> queryWrapper = Condition.getQueryWrapper(gdWorkOrderFlow, GdWorkOrderFlowEntity.class); //if (!AuthUtil.isAdministrator()) { drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/entity/GdPatrolTaskEntity.java
@@ -42,6 +42,12 @@ */ @ApiModelProperty(value = "关联工单任务表ID") private Long workOrderId; /** * 巡查任务编号 */ @ApiModelProperty(value = "巡查任务编号") private String taskNo; /** * 巡查任务名称 */ @@ -50,7 +56,7 @@ /** * 巡查任务类型(巡查类/安检类等) */ @ApiModelProperty(value = "巡查任务类型(巡查类/安检类等)") @ApiModelProperty(value = "巡查任务类型 1.巡查类 2.巡检类 3.安保类 4.文旅类 5.采集数据类 ") private String patrolTaskType; /** * 执行时间 @@ -78,9 +84,9 @@ @ApiModelProperty(value = "任务描述") private String taskDesc; /** * 状态:0草稿、1待签收、2拒绝签收、3待审核 * 状态:0待签收、1拒绝签收、2已撤回、3待审核、4审核驳回、5审核通过、6待验收、7拒绝验收、8验收通过 */ @ApiModelProperty(value = "状态:0草稿、1待签收、2拒绝签收、3待审核") @ApiModelProperty(value = "状态:0待签收、1拒绝签收、2已撤回、3待审核、4审核驳回、5审核通过、6待验收、7拒绝验收、8验收通过") private Byte taskStatus; /** * 区域编码 drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/entity/GdWorkOrderEntity.java
@@ -16,7 +16,9 @@ */ package org.sxkj.gd.workorder.entity; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -41,61 +43,75 @@ * 工单名称 */ @ApiModelProperty(value = "工单名称") @TableField("work_order_name") private String workOrderName; /** * 工单编号(唯一) */ @ApiModelProperty(value = "工单编号(唯一)") @TableField("work_order_code") private String workOrderCode; /** * 工单类型(巡查类/安检类等) */ @ApiModelProperty(value = "工单类型(巡查类/安检类等)") @TableField("work_order_type") private String workOrderType; /** * 设备负载需求(红外、喊话器、探照灯) */ @ApiModelProperty(value = "设备负载需求(红外、喊话器、探照灯)") @TableField("device_load_demand") private String deviceLoadDemand; /** * 推荐设备ID(逗号分隔) */ @ApiModelProperty(value = "推荐设备ID(逗号分隔)") @TableField("recommend_device_ids") private String recommendDeviceIds; /** * 工单状态:0草稿、10发布中_接单中、11发布中_拒绝接单、20响应中_待拆分、21响应中_申请取消、22响应中_申请修改、23响应中_已取消、30执行中_待全部完成、31执行中_协商修改、40完成待验_待全部验收、50验收通过_待结算、60结算完成_已结算 */ @ApiModelProperty(value = "工单状态:0草稿、10发布中_接单中、11发布中_拒绝接单、20响应中_待拆分、21响应中_申请取消、22响应中_申请修改、23响应中_已取消、30执行中_待全部完成、31执行中_协商修改、40完成待验_待全部验收、50验收通过_待结算、60结算完成_已结算") @TableField("work_order_status") private Byte workOrderStatus = 0; /** * 执行时间范围-开始 */ @ApiModelProperty(value = "执行时间范围-开始") @TableField("execute_start_time") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date executeStartTime; /** * 执行时间范围-结束 */ @ApiModelProperty(value = "执行时间范围-结束") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @TableField("execute_end_time") private Date executeEndTime; /** * 服务方(审核人) */ @ApiModelProperty(value = "服务方(审核人)") @TableField("service_party") private String serviceParty; /** * 经纬度面(存储地理面数据) */ @ApiModelProperty(value = "经纬度面(存储地理面数据)") @TableField("geom") private String geom; /** * 备注 */ @ApiModelProperty(value = "备注") @TableField("remark") private String remark; /** * 区域编码 */ @ApiModelProperty(value = "区域编码") @TableField("area_code") private String areaCode; } drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/enums/PatrolTaskTypeEnum.java
New file @@ -0,0 +1,80 @@ package org.sxkj.gd.workorder.enums; import com.baomidou.mybatisplus.annotation.EnumValue; import com.fasterxml.jackson.annotation.JsonValue; import lombok.AllArgsConstructor; import lombok.Getter; /** * 巡查任务类型枚举 * 用于标识巡查任务的不同类型 * * @author BladeX * @date 2026-01-19 */ @Getter @AllArgsConstructor public enum PatrolTaskTypeEnum { /** * 巡查类 */ PATROL_TYPE("1", "巡查类"), /** * 巡检类 */ INSPECTION_TYPE("2", "巡检类"), /** * 安保类 */ SECURITY_TYPE("3", "安保类"), /** * 文旅类 */ CULTURAL_TOURISM_TYPE("4", "文旅类"), /** * 采集数据类 */ DATA_COLLECTION_TYPE("5", "采集数据类"); /** * 枚举值,对应数据库存储值 */ @EnumValue private final String value; /** * 枚举描述,用于展示 */ @JsonValue private final String desc; /** * 根据值获取对应的枚举 * * @param value 枚举值 * @return 对应的枚举,如果未找到则返回null */ public static PatrolTaskTypeEnum getByValue(String value) { for (PatrolTaskTypeEnum type : values()) { if (type.getValue().equals(value)) { return type; } } return null; } /** * 判断值是否为有效的巡查任务类型 * * @param value 待验证的值 * @return 是否有效 */ public static boolean isValidValue(String value) { return getByValue(value) != null; } } drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/mapper/GdManageDeviceMapper.xml
@@ -54,7 +54,7 @@ <select id="selectGdManageDevicePage" resultMap="gdManageDeviceResultMap"> select * from ja_gd_manage_device where is_deleted = 0 select id,device_sn,device_name,nickname,device_payload from ja_gd_manage_device where is_deleted = 0 </select> drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/mapper/GdWorkOrderFlowMapper.xml
@@ -22,7 +22,15 @@ <select id="selectGdWorkOrderFlowPage" resultMap="gdWorkOrderFlowResultMap"> select * from ja_gd_work_order_flow where is_deleted = 0 select * from ja_gd_work_order_flow <where> <if test="param2.type != null and param2.type != ''"> and type = #{param2.type} </if> <if test="param2.workOrderId != null and param2.workOrderId != ''"> and workOrderId = #{param2.workOrderId} </if> </where> </select> drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/mapper/GdWorkOrderMapper.xml
@@ -28,7 +28,28 @@ <select id="selectGdWorkOrderPage" resultMap="gdWorkOrderResultMap"> select * from ja_gd_work_order select id, work_order_name, work_order_code, work_order_type, device_load_demand, recommend_device_ids, work_order_status, execute_start_time, execute_end_time, service_party, ST_AsText(geom) geom, remark, area_code, create_user, create_dept, create_time, update_user, update_time, status, is_deleted from ja_gd_work_order <where> <if test="param2.workOrderStatus != null and param2.workOrderStatus != ''"> and work_order_status like concat(#{param2.workOrderStatus},'%') @@ -48,7 +69,9 @@ <select id="exportGdWorkOrder" resultType="org.sxkj.gd.workorder.excel.GdWorkOrderExcel"> SELECT * SELECT id, work_order_name, work_order_code, work_order_type, device_load_demand, recommend_device_ids, work_order_status, execute_start_time, execute_end_time, service_party, geom, remark, area_code, create_user, create_dept, create_time, update_user, update_time, status, is_deleted FROM ja_gd_work_order ${ew.customSqlSegment} </select> drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/impl/GdPatrolTaskServiceImpl.java
@@ -16,9 +16,12 @@ */ package org.sxkj.gd.workorder.service.impl; import org.apache.commons.lang3.StringUtils; import org.springblade.core.secure.utils.AuthUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; import org.sxkj.common.constant.WordOrderConstant; import org.sxkj.common.utils.OrderNumUtils; import org.sxkj.gd.workorder.entity.GdPatrolTaskEntity; import org.sxkj.gd.workorder.entity.GdWorkOrderFlowEntity; import org.sxkj.gd.workorder.enums.PatrolTaskStatusEnum; @@ -69,6 +72,12 @@ public boolean savePatrolTask(List<GdPatrolTaskEntity> taskEntityList) { // 更新流程节点 for (GdPatrolTaskEntity gdPatrolTaskEntity : taskEntityList) { // 生成巡查任务编号 if (StringUtils.isBlank(gdPatrolTaskEntity.getTaskNo())) { // 使用时间戳生成唯一巡查任务编号 String timestamp = OrderNumUtils.initOrderNum(WordOrderConstant.PATROL_TASK_KEY); gdPatrolTaskEntity.setTaskNo(WordOrderConstant.PATROL_TASK_PREFIX + timestamp); } // 保存巡逻任务 boolean save = save(gdPatrolTaskEntity); if (!save) { @@ -115,7 +124,7 @@ if (PatrolTaskStatusEnum.REJECTED_SIGNING.getValue().equals(auditStatus) && (rejectReason == null || rejectReason.trim().isEmpty())) { throw new RuntimeException("拒绝签收时必须填写拒绝原因"); } // 4. 检查其他需要拒绝原因的状态 if ((PatrolTaskStatusEnum.AUDIT_REJECTED.getValue().equals(auditStatus) || PatrolTaskStatusEnum.REJECTED_ACCEPTANCE.getValue().equals(auditStatus)) && (rejectReason == null || rejectReason.trim().isEmpty())) { throw new RuntimeException("审核驳回或拒绝验收时必须填写拒绝原因"); drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/vo/GdManageDeviceVO.java
@@ -16,9 +16,16 @@ */ package org.sxkj.gd.workorder.vo; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.ApiModelProperty; import org.sxkj.gd.workorder.entity.GdManageDeviceEntity; import lombok.Data; import lombok.EqualsAndHashCode; import java.math.BigDecimal; import java.util.Date; /** * 设备信息 视图实体类 @@ -27,8 +34,35 @@ * @since 2026-01-14 */ @Data @EqualsAndHashCode(callSuper = true) public class GdManageDeviceVO extends GdManageDeviceEntity { public class GdManageDeviceVO { private static final long serialVersionUID = 1L; @ApiModelProperty("主键id") private Integer id; @ApiModelProperty(value = "设备型号") private String deviceName; /** * custom name of the device */ @ApiModelProperty(value = "设备名称") private String nickname; /** * 设备负载(红外,喇叭,闪光灯) */ @ApiModelProperty(value = "设备负载(红外,喇叭,闪光灯)") private String devicePayload; /** * 当前经度 */ @ApiModelProperty(value = "当前经度") private Double longitude; /** * 当前纬度 */ @ApiModelProperty(value = "当前纬度") private Double latitude; } drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/vo/GdWorkOrderFlowVO.java
@@ -16,6 +16,7 @@ */ package org.sxkj.gd.workorder.vo; import io.swagger.annotations.ApiModelProperty; import org.sxkj.gd.workorder.entity.GdWorkOrderFlowEntity; import lombok.Data; import lombok.EqualsAndHashCode; @@ -27,8 +28,18 @@ * @since 2026-01-14 */ @Data @EqualsAndHashCode(callSuper = true) public class GdWorkOrderFlowVO extends GdWorkOrderFlowEntity { public class GdWorkOrderFlowVO { private static final long serialVersionUID = 1L; /** * 关联工单任务表ID/巡查任务ID */ @ApiModelProperty(value = "关联工单任务表ID/巡查任务ID") private Long workOrderId; /** * 类型(0工单任务 1巡查任务) */ @ApiModelProperty(value = "类型(0工单任务 1巡查任务)") private String type; }