diff --git a/RuoYi-Vue-Plus/ruoyi-admin/src/main/resources/application.yml b/RuoYi-Vue-Plus/ruoyi-admin/src/main/resources/application.yml index e68ae3f1..23a925df 100644 --- a/RuoYi-Vue-Plus/ruoyi-admin/src/main/resources/application.yml +++ b/RuoYi-Vue-Plus/ruoyi-admin/src/main/resources/application.yml @@ -76,9 +76,9 @@ spring: servlet: multipart: # 单个文件大小 - max-file-size: 10MB + max-file-size: 100MB # 设置总上传的文件大小 - max-request-size: 20MB + max-request-size: 200MB mvc: # 设置静态资源路径 防止所有请求都去查静态资源 static-path-pattern: /static/** diff --git a/RuoYi-Vue-Plus/ruoyi-admin/src/test/java/org/dromara/test/CmdTest.java b/RuoYi-Vue-Plus/ruoyi-admin/src/test/java/org/dromara/test/CmdTest.java new file mode 100644 index 00000000..6ca218ee --- /dev/null +++ b/RuoYi-Vue-Plus/ruoyi-admin/src/test/java/org/dromara/test/CmdTest.java @@ -0,0 +1,64 @@ +package org.dromara.test; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Arrays; +import java.util.List; + +/** + * @author lcj + * @date 2025/4/23 10:15 + */ +@SpringBootTest +public class CmdTest { + + @Test + public void test() { + // 获取当前项目根目录 + String projectRoot = System.getProperty("user.dir"); + // EXE 和参数 + String exePath = projectRoot + File.separator + "file" + File.separator + "resource" + File.separator + "dxf" + File.separator + "main.exe"; + String inputDXF = "file/resource/dxf/1897160897167638529/桩点图.dxf"; + String outputJSON = "file/resource/dxf/1897160897167638529/output.json"; + String sourceEPSG = "4524"; + String targetEPSG = "4326"; + + // 构造命令行 + List command = Arrays.asList( + exePath, + inputDXF, + outputJSON, + sourceEPSG, + targetEPSG + ); + + ProcessBuilder builder = new ProcessBuilder(command); + builder.redirectErrorStream(true); // 合并标准错误和输出 + + try { + Process process = builder.start(); + + // 读取输出 + BufferedReader reader = new BufferedReader( + new InputStreamReader(process.getInputStream(), "GBK") + ); + String line; + System.out.println("程序输出:"); + while ((line = reader.readLine()) != null) { + System.out.println(line); + } + + int exitCode = process.waitFor(); + System.out.println("程序退出码:" + exitCode); + + reader.close(); + } catch (IOException | InterruptedException e) { + e.printStackTrace(); + } + } +} diff --git a/RuoYi-Vue-Plus/ruoyi-common/pom.xml b/RuoYi-Vue-Plus/ruoyi-common/pom.xml index 2930fd0b..385d7114 100644 --- a/RuoYi-Vue-Plus/ruoyi-common/pom.xml +++ b/RuoYi-Vue-Plus/ruoyi-common/pom.xml @@ -34,6 +34,7 @@ ruoyi-common-tenant ruoyi-common-websocket ruoyi-common-sse + ruoyi-common-mapbox ruoyi-common diff --git a/RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-mapbox/pom.xml b/RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-mapbox/pom.xml new file mode 100644 index 00000000..be0f26fd --- /dev/null +++ b/RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-mapbox/pom.xml @@ -0,0 +1,54 @@ + + + + org.dromara + ruoyi-common + ${revision} + + 4.0.0 + + ruoyi-common-mapbox + + + ruoyi-common-mapbox 地图工具模块 + + + + + com.mapbox.mapboxsdk + mapbox-sdk-geojson + 7.4.0 + + + + com.mapbox.mapboxsdk + mapbox-sdk-services + 7.4.0 + + + + com.mapbox.mapboxsdk + mapbox-sdk-turf + 7.4.0 + + + + com.mapbox.mapboxsdk + mapbox-sdk-core + 7.4.0 + + + + + + mapbox-repo + https://api.mapbox.com/downloads/v2/releases/maven + + false + + + + + diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/constant/DxfFileConstant.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/constant/DxfFileConstant.java new file mode 100644 index 00000000..4a485e70 --- /dev/null +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/constant/DxfFileConstant.java @@ -0,0 +1,24 @@ +package org.dromara.constant; + +import java.io.File; + +/** + * @author lcj + * @date 2025/4/23 11:09 + */ +public interface DxfFileConstant { + + String DXF_BASE_PATH = "file" + File.separator + "resource" + File.separator + "dxf"; + + /** + * WGS 84 + */ + String EPSG4326 = "4326"; + + String EPSG4524 = "4524"; + + static String getDxfProjectPath(Long projectId) { + return DXF_BASE_PATH + File.separator + projectId; + } + +} diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/controller/FacPhotovoltaicPanelPartsController.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/controller/FacPhotovoltaicPanelPartsController.java index 24bbdf32..ba72aba6 100644 --- a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/controller/FacPhotovoltaicPanelPartsController.java +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/facility/controller/FacPhotovoltaicPanelPartsController.java @@ -7,15 +7,18 @@ import org.dromara.common.log.annotation.Log; import org.dromara.common.log.enums.BusinessType; import org.dromara.facility.domain.req.photovoltaicpanelparts.PhotovoltaicPanelPartsCreateReq; import org.dromara.facility.service.IFacPhotovoltaicPanelPartsService; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** + * 设施-光伏板桩点、立柱、支架 + * * @author lcj - * @date 2025/4/21 16:33 + * @date 2025/4/21 */ - +@Validated @RestController @RequestMapping("/facility/photovoltaicPanelPoint/parts") public class FacPhotovoltaicPanelPartsController { diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/controller/BusProjectController.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/controller/BusProjectController.java index eb98ff84..51965a73 100644 --- a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/controller/BusProjectController.java +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/controller/BusProjectController.java @@ -1,8 +1,6 @@ package org.dromara.project.controller; import cn.dev33.satoken.annotation.SaCheckPermission; -import cn.hutool.json.JSONObject; -import cn.hutool.json.JSONUtil; import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; @@ -28,11 +26,6 @@ import org.dromara.project.service.IBusProjectService; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; import java.util.List; /** @@ -128,14 +121,4 @@ public class BusProjectController extends BaseController { return toAjax(projectService.deleteWithValidByIds(List.of(ids), true)); } - @GetMapping("/json") - public R test() throws IOException { - // 1. 指定文件相对于 classpath 的路径 - Path path = Paths.get(System.getProperty("user.dir"), "geo.json"); - - // 2. 把文件内容读成字节数组,再转成字符串 - String json = Files.readString(path, StandardCharsets.UTF_8); - JSONObject json1 = JSONUtil.parseObj(json); - return R.ok(json1); - } } diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/controller/BusProjectFileController.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/controller/BusProjectFileController.java new file mode 100644 index 00000000..da0c0583 --- /dev/null +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/controller/BusProjectFileController.java @@ -0,0 +1,119 @@ +package org.dromara.project.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.json.JSONObject; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.RequiredArgsConstructor; +import org.dromara.common.core.domain.R; +import org.dromara.common.core.validate.EditGroup; +import org.dromara.common.excel.utils.ExcelUtil; +import org.dromara.common.idempotent.annotation.RepeatSubmit; +import org.dromara.common.log.annotation.Log; +import org.dromara.common.log.enums.BusinessType; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.web.core.BaseController; +import org.dromara.project.domain.req.projectfile.ProjectFileQueryReq; +import org.dromara.project.domain.req.projectfile.ProjectFileUpdateReq; +import org.dromara.project.domain.req.projectfile.ProjectFileUploadDxfReq; +import org.dromara.project.domain.vo.BusProjectFileVo; +import org.dromara.project.service.IBusProjectFileService; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; + +/** + * 项目文件存储 + * + * @author lcj + * @date 2025-04-23 + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/project/projectFile") +public class BusProjectFileController extends BaseController { + + private final IBusProjectFileService busProjectFileService; + + /** + * 查询项目文件存储列表 + */ + @SaCheckPermission("project:projectFile:list") + @GetMapping("/list") + public TableDataInfo list(ProjectFileQueryReq req, PageQuery pageQuery) { + return busProjectFileService.queryPageList(req, pageQuery); + } + + /** + * 导出项目文件存储列表 + */ + @SaCheckPermission("project:projectFile:export") + @Log(title = "项目文件存储", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(ProjectFileQueryReq req, HttpServletResponse response) { + List list = busProjectFileService.queryList(req); + ExcelUtil.exportExcel(list, "项目文件存储", BusProjectFileVo.class, response); + } + + /** + * 获取项目文件存储详细信息 + * + * @param id 主键 + */ + @SaCheckPermission("project:projectFile:query") + @GetMapping("/{id}") + public R getInfo(@NotNull(message = "主键不能为空") + @PathVariable Long id) { + return R.ok(busProjectFileService.queryById(id)); + } + + /** + * 修改项目文件存储 + */ + @SaCheckPermission("project:projectFile:edit") + @Log(title = "项目文件存储", businessType = BusinessType.UPDATE) + @RepeatSubmit() + @PutMapping() + public R edit(@Validated(EditGroup.class) @RequestBody ProjectFileUpdateReq req) { + return toAjax(busProjectFileService.updateByBo(req)); + } + + /** + * 删除项目文件存储 + * + * @param ids 主键串 + */ + @SaCheckPermission("project:projectFile:remove") + @Log(title = "项目文件存储", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@NotEmpty(message = "主键不能为空") + @PathVariable Long[] ids) { + return toAjax(busProjectFileService.deleteWithValidByIds(List.of(ids), true)); + } + + /** + * 上传 dxf 文件并解析为 json + */ + @Log(title = "项目文件存储", businessType = BusinessType.IMPORT) + @PostMapping("/upload/dxf") + public R uploadDxf2Json(@RequestParam("file") MultipartFile file, ProjectFileUploadDxfReq req) { + return R.ok(busProjectFileService.uploadDxf2Json(file, req)); + } + + /** + * 获取JSON文件详细信息 + * + * @param id 主键 + */ + @SaCheckPermission("project:projectFile:query") + @GetMapping("/json/{id}") + public R getJSONFile(@NotNull(message = "主键不能为空") + @PathVariable Long id){ + return R.ok(busProjectFileService.getJSONFile(id)); + } +} diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/BusProjectFile.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/BusProjectFile.java new file mode 100644 index 00000000..d3a353ad --- /dev/null +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/BusProjectFile.java @@ -0,0 +1,65 @@ +package org.dromara.project.domain; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.Date; + +/** + * 项目文件存储对象 bus_project_file + * + * @author lcj + * @date 2025-04-23 + */ +@Data +@TableName("bus_project_file") +public class BusProjectFile implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + @TableId(value = "id") + private Long id; + + /** + * 项目id + */ + private Long projectId; + + /** + * 文件类型 + */ + private String fileType; + + /** + * 文件名称 + */ + private String fileName; + + /** + * 文件路径 + */ + private String filePath; + + /** + * 备注 + */ + private String remark; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 更新时间 + */ + private Date updateTime; + +} diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/req/projectfile/ProjectFileQueryReq.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/req/projectfile/ProjectFileQueryReq.java new file mode 100644 index 00000000..60e3f587 --- /dev/null +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/req/projectfile/ProjectFileQueryReq.java @@ -0,0 +1,33 @@ +package org.dromara.project.domain.req.projectfile; + +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; + +/** + * @author lcj + * @date 2025/4/23 14:16 + */ +@Data +public class ProjectFileQueryReq implements Serializable { + + @Serial + private static final long serialVersionUID = 399401709402729491L; + + /** + * 项目id + */ + private Long projectId; + + /** + * 文件类型 + */ + private String fileType; + + /** + * 文件名称 + */ + private String fileName; + +} diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/req/projectfile/ProjectFileUpdateReq.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/req/projectfile/ProjectFileUpdateReq.java new file mode 100644 index 00000000..9f5f5882 --- /dev/null +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/req/projectfile/ProjectFileUpdateReq.java @@ -0,0 +1,43 @@ +package org.dromara.project.domain.req.projectfile; + +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; + +/** + * @author lcj + * @date 2025/4/23 14:18 + */ +@Data +public class ProjectFileUpdateReq implements Serializable { + + @Serial + private static final long serialVersionUID = -5620479296452749930L; + + /** + * 主键 + */ + private Long id; + + /** + * 项目id + */ + private Long projectId; + + /** + * 文件类型 + */ + private String fileType; + + /** + * 文件名称 + */ + private String fileName; + + /** + * 备注 + */ + private String remark; + +} diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/req/projectfile/ProjectFileUploadDxfReq.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/req/projectfile/ProjectFileUploadDxfReq.java new file mode 100644 index 00000000..1d5e6654 --- /dev/null +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/req/projectfile/ProjectFileUploadDxfReq.java @@ -0,0 +1,23 @@ +package org.dromara.project.domain.req.projectfile; + +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; + +/** + * @author lcj + * @date 2025/4/23 11:43 + */ +@Data +public class ProjectFileUploadDxfReq implements Serializable { + + @Serial + private static final long serialVersionUID = -7096688035548954702L; + + /** + * 项目id + */ + private Long projectId; + +} diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/vo/BusProjectFileVo.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/vo/BusProjectFileVo.java new file mode 100644 index 00000000..4f4cb935 --- /dev/null +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/vo/BusProjectFileVo.java @@ -0,0 +1,50 @@ +package org.dromara.project.domain.vo; + +import org.dromara.project.domain.BusProjectFile; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import org.dromara.common.excel.annotation.ExcelDictFormat; +import org.dromara.common.excel.convert.ExcelDictConvert; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.Date; + + + +/** + * 项目文件存储视图对象 bus_project_file + * + * @author lcj + * @date 2025-04-23 + */ +@Data +@ExcelIgnoreUnannotated +@AutoMapper(target = BusProjectFile.class) +public class BusProjectFileVo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 文件类型 + */ + @ExcelProperty(value = "文件类型") + private String fileType; + + /** + * 文件名称 + */ + @ExcelProperty(value = "文件名称") + private String fileName; + + /** + * 文件路径 + */ + @ExcelProperty(value = "文件路径") + private String filePath; + + +} diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/vo/BusProjectVo.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/vo/BusProjectVo.java index b24d7722..ad2f29e7 100644 --- a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/vo/BusProjectVo.java +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/domain/vo/BusProjectVo.java @@ -160,6 +160,11 @@ public class BusProjectVo implements Serializable { @ExcelProperty(value = "安全协议书") private String securityAgreement; + /** + * 设计文件id + */ + private Long designId; + /** * 显示隐藏(0显示 1隐藏) */ diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/mapper/BusProjectFileMapper.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/mapper/BusProjectFileMapper.java new file mode 100644 index 00000000..56aa7bd1 --- /dev/null +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/mapper/BusProjectFileMapper.java @@ -0,0 +1,15 @@ +package org.dromara.project.mapper; + +import org.dromara.project.domain.BusProjectFile; +import org.dromara.project.domain.vo.BusProjectFileVo; +import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; + +/** + * 项目文件存储Mapper接口 + * + * @author lcj + * @date 2025-04-23 + */ +public interface BusProjectFileMapper extends BaseMapperPlus { + +} diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/IBusProjectFileService.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/IBusProjectFileService.java new file mode 100644 index 00000000..969163ad --- /dev/null +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/IBusProjectFileService.java @@ -0,0 +1,110 @@ +package org.dromara.project.service; + +import cn.hutool.json.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.project.domain.BusProjectFile; +import org.dromara.project.domain.req.projectfile.ProjectFileQueryReq; +import org.dromara.project.domain.req.projectfile.ProjectFileUpdateReq; +import org.dromara.project.domain.req.projectfile.ProjectFileUploadDxfReq; +import org.dromara.project.domain.vo.BusProjectFileVo; +import org.springframework.web.multipart.MultipartFile; + +import java.util.Collection; +import java.util.List; + +/** + * 项目文件存储Service接口 + * + * @author lcj + * @date 2025-04-23 + */ +public interface IBusProjectFileService extends IService { + + /** + * 查询项目文件存储 + * + * @param id 主键 + * @return 项目文件存储 + */ + BusProjectFileVo queryById(Long id); + + /** + * 分页查询项目文件存储列表 + * + * @param req 查询条件 + * @param pageQuery 分页参数 + * @return 项目文件存储分页列表 + */ + TableDataInfo queryPageList(ProjectFileQueryReq req, PageQuery pageQuery); + + /** + * 查询符合条件的项目文件存储列表 + * + * @param req 查询条件 + * @return 项目文件存储列表 + */ + List queryList(ProjectFileQueryReq req); + + /** + * 修改项目文件存储 + * + * @param req 项目文件存储 + * @return 是否修改成功 + */ + Boolean updateByBo(ProjectFileUpdateReq req); + + /** + * 校验并批量删除项目文件存储信息 + * + * @param ids 待删除的主键集合 + * @param isValid 是否进行有效性校验 + * @return 是否删除成功 + */ + Boolean deleteWithValidByIds(Collection ids, Boolean isValid); + + /** + * 根据id获取JSON文件 + * + * @param id 主键 + * @return JSON文件 + */ + JSONObject getJSONFile(Long id); + + /** + * 上传dxf文件并转换为json + * + * @param file 文件 + * @param req 请求 + * @return 主键 + */ + Long uploadDxf2Json(MultipartFile file, ProjectFileUploadDxfReq req); + + /** + * 获取项目文件存储视图对象 + * + * @param projectFile 项目文件存储对象 + * @return 项目文件存储视图对象 + */ + BusProjectFileVo getVo(BusProjectFile projectFile); + + /** + * 获取项目文件存储查询条件封装 + * + * @param req 查询条件 + * @return 查询条件封装 + */ + LambdaQueryWrapper buildQueryWrapper(ProjectFileQueryReq req); + + /** + * 获取项目文件存储分页对象视图 + * + * @param projectFilePage 项目文件存储分页对象 + * @return 项目文件存储分页对象视图 + */ + Page getVoPage(Page projectFilePage); + +} diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/impl/BusProjectFileServiceImpl.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/impl/BusProjectFileServiceImpl.java new file mode 100644 index 00000000..1b541409 --- /dev/null +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/impl/BusProjectFileServiceImpl.java @@ -0,0 +1,322 @@ +package org.dromara.project.service.impl; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.util.IdUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.constant.HttpStatus; +import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.utils.ObjectUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.constant.DxfFileConstant; +import org.dromara.project.domain.BusProject; +import org.dromara.project.domain.BusProjectFile; +import org.dromara.project.domain.req.projectfile.ProjectFileQueryReq; +import org.dromara.project.domain.req.projectfile.ProjectFileUpdateReq; +import org.dromara.project.domain.req.projectfile.ProjectFileUploadDxfReq; +import org.dromara.project.domain.vo.BusProjectFileVo; +import org.dromara.project.mapper.BusProjectFileMapper; +import org.dromara.project.service.IBusProjectFileService; +import org.dromara.project.service.IBusProjectService; +import org.dromara.utils.DxfUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Collection; +import java.util.List; +import java.util.Objects; + +/** + * 项目文件存储Service业务层处理 + * + * @author lcj + * @date 2025-04-23 + */ +@Slf4j +@Service +public class BusProjectFileServiceImpl extends ServiceImpl + implements IBusProjectFileService { + + @Resource + private IBusProjectService projectService; + + /** + * 查询项目文件存储 + * + * @param id 主键 + * @return 项目文件存储 + */ + @Override + public BusProjectFileVo queryById(Long id) { + BusProjectFile projectFile = this.getById(id); + if (projectFile == null) { + throw new ServiceException("对应项目文件存储信息不存在", HttpStatus.NOT_FOUND); + } + return this.getVo(projectFile); + } + + /** + * 分页查询项目文件存储列表 + * + * @param req 查询条件 + * @param pageQuery 分页参数 + * @return 项目文件存储分页列表 + */ + @Override + public TableDataInfo queryPageList(ProjectFileQueryReq req, PageQuery pageQuery) { + Page projectFilePage = this.page(pageQuery.build(), this.buildQueryWrapper(req)); + return TableDataInfo.build(this.getVoPage(projectFilePage)); + } + + /** + * 查询符合条件的项目文件存储列表 + * + * @param req 查询条件 + * @return 项目文件存储列表 + */ + @Override + public List queryList(ProjectFileQueryReq req) { + LambdaQueryWrapper lqw = this.buildQueryWrapper(req); + return this.list(lqw).stream().map(this::getVo).toList(); + } + + /** + * 修改项目文件存储 + * + * @param req 项目文件存储 + * @return 是否修改成功 + */ + @Override + public Boolean updateByBo(ProjectFileUpdateReq req) { + // 将实体类和 DTO 进行转换 + BusProjectFile projectFile = new BusProjectFile(); + BeanUtils.copyProperties(req, projectFile); + // 数据校验 + validEntityBeforeSave(projectFile, false); + // 判断是否存在 + BusProjectFile oldProjectFile = this.getById(projectFile.getId()); + if (oldProjectFile == null) { + throw new ServiceException("修改项目文件存储失败,数据不存在", HttpStatus.NOT_FOUND); + } + // 操作数据库 + boolean update = this.updateById(projectFile); + if (!update) { + throw new ServiceException("修改项目文件存储失败,数据库异常", HttpStatus.ERROR); + } + return true; + } + + /** + * 保存前的数据校验 + */ + private void validEntityBeforeSave(BusProjectFile entity, Boolean create) { + // TODO 做一些数据校验,如唯一约束 + Long projectId = entity.getProjectId(); + if (create) { + if (projectId == null) { + throw new ServiceException("项目id不能为空", HttpStatus.BAD_REQUEST); + } + } + if (projectId != null && projectService.getById(projectId) == null) { + throw new ServiceException("对应项目不存在", HttpStatus.NOT_FOUND); + } + } + + /** + * 校验并批量删除项目文件存储信息 + * + * @param ids 待删除的主键集合 + * @param isValid 是否进行有效性校验 + * @return 是否删除成功 + */ + @Override + public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { + if (isValid) { + //TODO 做一些业务上的校验,判断是否需要校验 + } + return baseMapper.deleteByIds(ids) > 0; + } + + /** + * 根据id获取JSON文件 + * + * @param id 主键 + * @return JSON文件 + */ + @Override + public JSONObject getJSONFile(Long id) { + BusProjectFile projectFile = this.getById(id); + if (projectFile == null) { + throw new ServiceException("对应项目文件存储信息不存在", HttpStatus.NOT_FOUND); + } + String filePath = projectFile.getFilePath(); + String suffix = FileUtil.getSuffix(FileUtil.getName(filePath)); + if (!suffix.equals("json")) { + throw new ServiceException("文件格式不正确,只能解析json文件", HttpStatus.BAD_REQUEST); + } + JSONObject jsonObject; + try { + String property = System.getProperty("user.dir"); + Path path = Paths.get(property, filePath); + String jsonStr = Files.readString(path, StandardCharsets.UTF_8); + jsonObject = JSONUtil.parseObj(jsonStr); + } catch (IOException e) { + throw new ServiceException("文件读取失败", HttpStatus.ERROR); + } + return jsonObject; + } + + /** + * 上传dxf文件并转换为json + * + * @param file 文件 + * @param req 请求 + * @return 主键 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Long uploadDxf2Json(MultipartFile file, ProjectFileUploadDxfReq req) { + // 校验文件是否为空 + if (file == null) { + throw new ServiceException("dxf文件不能为空", HttpStatus.BAD_REQUEST); + } + // 校验是否为 dxf 文件 + String fileName = file.getOriginalFilename(); + String suffix = FileUtil.getSuffix(fileName); + if (!Objects.equals(suffix, "dxf")) { + throw new ServiceException("文件格式不正确,只能上传.dxf文件", HttpStatus.BAD_REQUEST); + } + // 校验项目是否存在 + Long projectId = req.getProjectId(); + BusProject project = projectService.getById(projectId); + if (project == null) { + throw new ServiceException("项目信息不存在", HttpStatus.NOT_FOUND); + } + // 获取当前项目根目录 + String projectRoot = System.getProperty("user.dir"); + // 构造保存 DXF 的目录 + String bashPath = DxfFileConstant.getDxfProjectPath(projectId); + String filePath = projectRoot + File.separator + bashPath; + if (!FileUtil.exist(filePath)) { + FileUtil.mkdir(filePath); + } + String inputDXFPath = filePath + File.separator + fileName; + try { + // 保存文件 + File savedFile = new File(inputDXFPath); + file.transferTo(savedFile); + } catch (IOException e) { + throw new ServiceException("dxf 文件保存失败"); + } + // 构造 JSON 输出路径 + String uuid = IdUtil.fastSimpleUUID(); + String outputJSONPath = filePath + File.separator + uuid + ".json"; + // 获取 dxf2json.exe 路径 + String exePath = projectRoot + File.separator + DxfFileConstant.DXF_BASE_PATH + File.separator + "main.exe"; + String sourceEPSG = DxfFileConstant.EPSG4524; + String targetEPSG = DxfFileConstant.EPSG4326; + // 构造命令行参数 + DxfUtils.dxf2json(exePath, inputDXFPath, outputJSONPath, sourceEPSG, targetEPSG); + // 删除之前的数据库记录和文件 + BusProjectFile oldProjectFile = this.lambdaQuery() + .eq(BusProjectFile::getProjectId, projectId) + .one(); + if (oldProjectFile != null) { + boolean result = this.removeById(oldProjectFile); + if (!result) { + throw new ServiceException("删除项目文件存储失败,数据库异常", HttpStatus.ERROR); + } + // 删除之前的文件 + try { + FileUtil.del(oldProjectFile.getFilePath()); + } catch (Exception e) { + log.error("删除项目文件失败", e); + } + } + // 保存项目文件存储 + BusProjectFile projectFile = new BusProjectFile(); + projectFile.setProjectId(projectId); + projectFile.setFileName(FileUtil.getPrefix(fileName) + ".json"); + projectFile.setFilePath(bashPath + File.separator + uuid + ".json"); + boolean save = this.save(projectFile); + if (!save) { + throw new ServiceException("保存项目文件存储失败,数据库异常", HttpStatus.ERROR); + } + return projectFile.getId(); + } + + /** + * 获取项目文件存储视图对象 + * + * @param projectFile 项目文件存储对象 + * @return 项目文件存储视图对象 + */ + @Override + public BusProjectFileVo getVo(BusProjectFile projectFile) { + // 对象转封装类 + BusProjectFileVo projectFileVo = new BusProjectFileVo(); + if (projectFile == null) { + return projectFileVo; + } + BeanUtils.copyProperties(projectFile, projectFileVo); + return projectFileVo; + } + + /** + * 获取项目文件存储查询条件封装 + * + * @param req 查询条件 + * @return 查询条件封装 + */ + @Override + public LambdaQueryWrapper buildQueryWrapper(ProjectFileQueryReq req) { + LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); + if (req == null) { + return lqw; + } + Long projectId = req.getProjectId(); + String fileType = req.getFileType(); + String fileName = req.getFileName(); + lqw.like(StringUtils.isNotBlank(fileName), BusProjectFile::getFileName, fileName); + lqw.eq(ObjectUtils.isNotEmpty(projectId), BusProjectFile::getProjectId, projectId); + lqw.eq(StringUtils.isNotBlank(fileType), BusProjectFile::getFileType, fileType); + return lqw; + } + + /** + * 获取项目文件存储分页对象视图 + * + * @param projectFilePage 项目文件存储分页对象 + * @return 项目文件存储分页对象视图 + */ + @Override + public Page getVoPage(Page projectFilePage) { + List projectFileList = projectFilePage.getRecords(); + Page projectFileVoPage = new Page<>( + projectFilePage.getCurrent(), + projectFilePage.getSize(), + projectFilePage.getTotal()); + if (CollUtil.isEmpty(projectFileList)) { + return projectFileVoPage; + } + List projectFileVoList = projectFileList.stream().map(this::getVo).toList(); + projectFileVoPage.setRecords(projectFileVoList); + return projectFileVoPage; + } +} diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/impl/BusProjectServiceImpl.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/impl/BusProjectServiceImpl.java index 2f619918..d065258c 100644 --- a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/impl/BusProjectServiceImpl.java +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/project/service/impl/BusProjectServiceImpl.java @@ -19,6 +19,7 @@ import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.project.domain.BusContractor; import org.dromara.project.domain.BusProject; +import org.dromara.project.domain.BusProjectFile; import org.dromara.project.domain.BusUserProjectRelevancy; import org.dromara.project.domain.req.project.ProjectCreateReq; import org.dromara.project.domain.req.project.ProjectQueryReq; @@ -27,6 +28,7 @@ import org.dromara.project.domain.resp.project.ProjectContractorListResp; import org.dromara.project.domain.vo.BusProjectVo; import org.dromara.project.mapper.BusProjectMapper; import org.dromara.project.service.IBusContractorService; +import org.dromara.project.service.IBusProjectFileService; import org.dromara.project.service.IBusProjectService; import org.dromara.project.service.IBusUserProjectRelevancyService; import org.springframework.beans.BeanUtils; @@ -55,6 +57,10 @@ public class BusProjectServiceImpl extends ServiceImpl 0) { throw new ServiceException("项目名称重复", HttpStatus.BAD_REQUEST); @@ -287,6 +293,13 @@ public class BusProjectServiceImpl extends ServiceImpl projectIdList = projectList.stream().map(BusProject::getId).collect(Collectors.toSet()); + Map> projectFileMap = projectFileService.lambdaQuery() + .in(BusProjectFile::getProjectId, projectIdList).list() + .stream().collect(Collectors.groupingBy(BusProjectFile::getProjectId)); // 对象列表 => 封装对象列表 - List projectVoList = projectList.stream().map(this::getVo).toList(); + List projectVoList = projectList.stream().map(project -> { + // 对象转封装类 + BusProjectVo projectVo = new BusProjectVo(); + BeanUtils.copyProperties(project, projectVo); + String punchRange = project.getPunchRange(); + if (StringUtils.isNotBlank(punchRange)) { + String[] split = punchRange.split(","); + projectVo.setPlayCardStart(split[0]); + projectVo.setPlayCardEnd(split[1]); + } + // 关联设计id + List projectFileList = projectFileMap.get(project.getId()); + if (CollUtil.isNotEmpty(projectFileList)) { + projectVo.setDesignId(projectFileList.get(0).getId()); + } + return projectVo; + }).toList(); projectVoPage.setRecords(projectVoList); return projectVoPage; } diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/quality/service/impl/BusQualityConstructionLogServiceImpl.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/quality/service/impl/BusQualityConstructionLogServiceImpl.java index d66cb36a..a254d424 100644 --- a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/quality/service/impl/BusQualityConstructionLogServiceImpl.java +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/quality/service/impl/BusQualityConstructionLogServiceImpl.java @@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.xwpf.usermodel.*; import org.dromara.common.core.constant.HttpStatus; @@ -13,6 +14,7 @@ import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.utils.DateUtils; import org.dromara.common.core.utils.ObjectUtils; import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.core.utils.file.FileUtils; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.oss.core.OssClient; @@ -54,6 +56,7 @@ import java.util.zip.ZipOutputStream; * @author lcj * @date 2025-04-16 */ +@Slf4j @Service public class BusQualityConstructionLogServiceImpl extends ServiceImpl implements IBusQualityConstructionLogService { @@ -320,36 +323,48 @@ public class BusQualityConstructionLogServiceImpl extends ServiceImpl replacementMap = getReplacementMap(qualityConstructionLog); Path targetDir = Paths.get(QualityConstant.getQualityConstructionLogFileUrl(qualityConstructionLog)); - try (FileInputStream fis = new FileInputStream(QualityConstant.QUALITY_CONSTRUCTION_LOG_TEMPLATE_PATH); - XWPFDocument document = new XWPFDocument(fis)) { - // 替换段落中的文本 - for (XWPFParagraph paragraph : document.getParagraphs()) { - replaceInParagraph(paragraph, replacementMap, document, qualityConstructionLog); + // 如果存在目录则直接返回,不存在则生成文件并返回 + if (!Files.exists(targetDir)) { + // 清理旧文件 + String baseUrl = QualityConstant.QUALITY_CONSTRUCTION_LOG_FILE_URL + qualityConstructionLog.getId(); + try { + Path dirPath = Paths.get(baseUrl); + FileUtils.deleteDirectory(dirPath); + } catch (IOException e) { + log.error("文件目录:{},清理失败", baseUrl, e); } - // 替换表格中的文本(如果模板中有表格) - for (XWPFTable table : document.getTables()) { - for (XWPFTableRow row : table.getRows()) { - for (XWPFTableCell cell : row.getTableCells()) { - for (XWPFParagraph paragraph : cell.getParagraphs()) { - replaceInParagraph(paragraph, replacementMap, document, qualityConstructionLog); + // 生成文件 + try (FileInputStream fis = new FileInputStream(QualityConstant.QUALITY_CONSTRUCTION_LOG_TEMPLATE_PATH); + XWPFDocument document = new XWPFDocument(fis)) { + // 替换段落中的文本 + for (XWPFParagraph paragraph : document.getParagraphs()) { + replaceInParagraph(paragraph, replacementMap, document, qualityConstructionLog); + } + // 替换表格中的文本(如果模板中有表格) + for (XWPFTable table : document.getTables()) { + for (XWPFTableRow row : table.getRows()) { + for (XWPFTableCell cell : row.getTableCells()) { + for (XWPFParagraph paragraph : cell.getParagraphs()) { + replaceInParagraph(paragraph, replacementMap, document, qualityConstructionLog); + } } } } + // 创建目标目录 + if (!Files.exists(targetDir)) { + Files.createDirectories(targetDir); + } + // 组合目标文件名 + String fileName = QualityConstant.getQualityConstructionLogFileName(qualityConstructionLog); + // 保存修改后的文件 + try (FileOutputStream fos = new FileOutputStream(targetDir.resolve(fileName).toFile())) { + document.write(fos); + } + } catch (IOException | InvalidFormatException e) { + throw new OssException("生成Word文件失败,错误信息: " + e.getMessage()); } - // 创建目标目录 - if (!Files.exists(targetDir)) { - Files.createDirectories(targetDir); - } - // 组合目标文件名 - String fileName = QualityConstant.getQualityConstructionLogFileName(qualityConstructionLog); - // 保存修改后的文件 - try (FileOutputStream fos = new FileOutputStream(targetDir.resolve(fileName).toFile())) { - document.write(fos); - } - } catch (IOException | InvalidFormatException e) { - throw new OssException("生成Word文件失败,错误信息: " + e.getMessage()); } - // 设置响应头 + // 设置响应头,返回ZIP文件 response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE + "; charset=UTF-8"); try (ZipOutputStream zos = new ZipOutputStream(response.getOutputStream())) { DocumentUtils.zipDirectory(targetDir, targetDir, zos); diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/quality/service/impl/BusQualityInspectionServiceImpl.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/quality/service/impl/BusQualityInspectionServiceImpl.java index e563f4d7..8833bae2 100644 --- a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/quality/service/impl/BusQualityInspectionServiceImpl.java +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/quality/service/impl/BusQualityInspectionServiceImpl.java @@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.xwpf.usermodel.*; import org.dromara.common.core.constant.HttpStatus; @@ -13,6 +14,7 @@ import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.utils.DateUtils; import org.dromara.common.core.utils.ObjectUtils; import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.core.utils.file.FileUtils; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.oss.core.OssClient; @@ -58,6 +60,7 @@ import java.util.zip.ZipOutputStream; * @author lcj * @date 2025-04-16 */ +@Slf4j @Service public class BusQualityInspectionServiceImpl extends ServiceImpl implements IBusQualityInspectionService { @@ -372,36 +375,48 @@ public class BusQualityInspectionServiceImpl extends ServiceImpl replacementMap = getReplacementMap(qualityInspection); Path targetDir = Paths.get(QualityConstant.getQualityInspectionFileUrl(qualityInspection)); - try (FileInputStream fis = new FileInputStream(QualityConstant.QUALITY_INSPECTION_TEMPLATE_PATH); - XWPFDocument document = new XWPFDocument(fis)) { - // 替换段落中的文本 - for (XWPFParagraph paragraph : document.getParagraphs()) { - replaceInParagraph(paragraph, replacementMap, document, qualityInspection); + // 如果存在目录则直接返回,不存在则生成文件并返回 + if (!Files.exists(targetDir)) { + // 清理旧文件 + String baseUrl = QualityConstant.QUALITY_INSPECTION_FILE_URL + qualityInspection.getId(); + try { + Path dirPath = Paths.get(baseUrl); + FileUtils.deleteDirectory(dirPath); + } catch (IOException e) { + log.error("文件目录:{},清理失败", baseUrl, e); } - // 替换表格中的文本(如果模板中有表格) - for (XWPFTable table : document.getTables()) { - for (XWPFTableRow row : table.getRows()) { - for (XWPFTableCell cell : row.getTableCells()) { - for (XWPFParagraph paragraph : cell.getParagraphs()) { - replaceInParagraph(paragraph, replacementMap, document, qualityInspection); + // 生成文件 + try (FileInputStream fis = new FileInputStream(QualityConstant.QUALITY_INSPECTION_TEMPLATE_PATH); + XWPFDocument document = new XWPFDocument(fis)) { + // 替换段落中的文本 + for (XWPFParagraph paragraph : document.getParagraphs()) { + replaceInParagraph(paragraph, replacementMap, document, qualityInspection); + } + // 替换表格中的文本(如果模板中有表格) + for (XWPFTable table : document.getTables()) { + for (XWPFTableRow row : table.getRows()) { + for (XWPFTableCell cell : row.getTableCells()) { + for (XWPFParagraph paragraph : cell.getParagraphs()) { + replaceInParagraph(paragraph, replacementMap, document, qualityInspection); + } } } } + // 创建目标目录 + if (!Files.exists(targetDir)) { + Files.createDirectories(targetDir); + } + // 组合目标文件名 + String fileName = QualityConstant.getQualityInspectionFileName(qualityInspection); + // 保存修改后的文件 + try (FileOutputStream fos = new FileOutputStream(targetDir.resolve(fileName).toFile())) { + document.write(fos); + } + } catch (IOException | InvalidFormatException e) { + throw new OssException("生成Word文件失败,错误信息: " + e.getMessage()); } - // 创建目标目录 - if (!Files.exists(targetDir)) { - Files.createDirectories(targetDir); - } - // 组合目标文件名 - String fileName = QualityConstant.getQualityInspectionFileName(qualityInspection); - // 保存修改后的文件 - try (FileOutputStream fos = new FileOutputStream(targetDir.resolve(fileName).toFile())) { - document.write(fos); - } - } catch (IOException | InvalidFormatException e) { - throw new OssException("生成Word文件失败,错误信息: " + e.getMessage()); } - // 设置响应头 + // 设置响应头,返回ZIP文件 response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE + "; charset=UTF-8"); try (ZipOutputStream zos = new ZipOutputStream(response.getOutputStream())) { DocumentUtils.zipDirectory(targetDir, targetDir, zos); diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/service/impl/BusSafetyInspectionServiceImpl.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/service/impl/BusSafetyInspectionServiceImpl.java index 487a39ea..0372e45b 100644 --- a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/service/impl/BusSafetyInspectionServiceImpl.java +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/service/impl/BusSafetyInspectionServiceImpl.java @@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.xwpf.usermodel.*; import org.dromara.common.core.constant.HttpStatus; @@ -14,6 +15,7 @@ import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.utils.DateUtils; import org.dromara.common.core.utils.ObjectUtils; import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.core.utils.file.FileUtils; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.oss.core.OssClient; @@ -59,6 +61,7 @@ import java.util.zip.ZipOutputStream; * @author lcj * @date 2025-03-20 */ +@Slf4j @Service public class BusSafetyInspectionServiceImpl extends ServiceImpl implements IBusSafetyInspectionService { @@ -334,36 +337,48 @@ public class BusSafetyInspectionServiceImpl extends ServiceImpl replacementMap = getReplacementMap(safetyInspection); Path targetDir = Paths.get(SafetyConstant.getSafetyInspectionFileUrl(safetyInspection)); - try (FileInputStream fis = new FileInputStream(SafetyConstant.SAFETY_INSPECTION_TEMPLATE_PATH); - XWPFDocument document = new XWPFDocument(fis)) { - // 替换段落中的文本 - for (XWPFParagraph paragraph : document.getParagraphs()) { - replaceInParagraph(paragraph, replacementMap, document, safetyInspection); + // 如果存在目录则直接返回,不存在则生成文件并返回 + if (!Files.exists(targetDir)) { + // 清理旧文件 + String baseUrl = SafetyConstant.SAFETY_INSPECTION_FILE_URL + safetyInspection.getId(); + try { + Path dirPath = Paths.get(baseUrl); + FileUtils.deleteDirectory(dirPath); + } catch (IOException e) { + log.error("文件目录:{},清理失败", baseUrl, e); } - // 替换表格中的文本(如果模板中有表格) - for (XWPFTable table : document.getTables()) { - for (XWPFTableRow row : table.getRows()) { - for (XWPFTableCell cell : row.getTableCells()) { - for (XWPFParagraph paragraph : cell.getParagraphs()) { - replaceInParagraph(paragraph, replacementMap, document, safetyInspection); + // 生成文件 + try (FileInputStream fis = new FileInputStream(SafetyConstant.SAFETY_INSPECTION_TEMPLATE_PATH); + XWPFDocument document = new XWPFDocument(fis)) { + // 替换段落中的文本 + for (XWPFParagraph paragraph : document.getParagraphs()) { + replaceInParagraph(paragraph, replacementMap, document, safetyInspection); + } + // 替换表格中的文本(如果模板中有表格) + for (XWPFTable table : document.getTables()) { + for (XWPFTableRow row : table.getRows()) { + for (XWPFTableCell cell : row.getTableCells()) { + for (XWPFParagraph paragraph : cell.getParagraphs()) { + replaceInParagraph(paragraph, replacementMap, document, safetyInspection); + } } } } + // 创建目标目录 + if (!Files.exists(targetDir)) { + Files.createDirectories(targetDir); + } + // 组合目标文件名 + String fileName = SafetyConstant.getSafetyInspectionFileName(safetyInspection); + // 保存修改后的文件 + try (FileOutputStream fos = new FileOutputStream(targetDir.resolve(fileName).toFile())) { + document.write(fos); + } + } catch (IOException | InvalidFormatException e) { + throw new OssException("生成Word文件失败,错误信息: " + e.getMessage()); } - // 创建目标目录 - if (!Files.exists(targetDir)) { - Files.createDirectories(targetDir); - } - // 组合目标文件名 - String fileName = SafetyConstant.getSafetyInspectionFileName(safetyInspection); - // 保存修改后的文件 - try (FileOutputStream fos = new FileOutputStream(targetDir.resolve(fileName).toFile())) { - document.write(fos); - } - } catch (IOException | InvalidFormatException e) { - throw new OssException("生成Word文件失败,错误信息: " + e.getMessage()); } - // 设置响应头 + // 设置响应头,返回ZIP文件 response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE + "; charset=UTF-8"); try (ZipOutputStream zos = new ZipOutputStream(response.getOutputStream())) { DocumentUtils.zipDirectory(targetDir, targetDir, zos); diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/utils/DxfUtils.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/utils/DxfUtils.java new file mode 100644 index 00000000..ce9e9c9c --- /dev/null +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/utils/DxfUtils.java @@ -0,0 +1,98 @@ +package org.dromara.utils; + +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.exception.ServiceException; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Arrays; +import java.util.List; + +/** + * @author lcj + * @date 2025/4/23 10:42 + */ +@Slf4j +public class DxfUtils { + + /** + * dxf转json + * + * @param exePath dxf2json.exe路径 + * @param inputDXFPath 输入dxf文件路径 + * @param outputJSONPath 输出json文件路径 + * @param sourceEPSG 源坐标系 + * @param targetEPSG 目标坐标系 + */ + public static void dxf2json(String exePath, String inputDXFPath, String outputJSONPath, String sourceEPSG, String targetEPSG) { + // 判断对应文件是否存在 + File exeFile = new File(exePath); + if (!exeFile.exists()) { + throw new ServiceException("转换程序不存在!"); + } + File inputDXFFile = new File(inputDXFPath); + if (!inputDXFFile.exists()) { + throw new ServiceException("待转换 dxf 文件不存在!"); + } + // 构造命令行参数 + List parameters = buildParameter(exePath, inputDXFPath, outputJSONPath, sourceEPSG, targetEPSG); + // 执行命令行 + ProcessBuilder builder = new ProcessBuilder(parameters); + // 合并标准错误和输出 + builder.redirectErrorStream(true); + try { + Process process = builder.start(); + // 读取输出 + BufferedReader reader = new BufferedReader( + new InputStreamReader(process.getInputStream(), "GBK") + ); + String line; + log.info("dxf 转 json 程序开始执行,程序路径:{},输入 dxf 路径:{},输出 json 文件路径:{},源坐标系:{},模板坐标系:{}", + exePath, inputDXFPath, outputJSONPath, sourceEPSG, targetEPSG); + while ((line = reader.readLine()) != null) { + log.info("dxf 转 json 程序执行中:{}", line); + } + int exitCode = process.waitFor(); + log.info("dxf 转 json 程序执行完毕,程序退出码:{}", exitCode); + reader.close(); + } catch (IOException | InterruptedException e) { + log.error("执行 dxf 转 json 命令行时出错", e); + }finally { + // 删除dxf文件 + if (inputDXFFile.exists()) { + boolean delete = inputDXFFile.delete(); + if (!delete) { + log.error("dxf文件删除失败,路径:{}", inputDXFPath); + } + } + } + } + + /** + * 构造命令行参数 + * + * @param exePath dxf2json.exe路径 + * @param inputDXFPath 输入dxf文件路径 + * @param outputJSONPath 输出json文件路径 + * @param sourceEPSG 源坐标系 + * @param targetEPSG 目标坐标系 + * @return 命令行参数 + */ + public static List buildParameter(String exePath, + String inputDXFPath, + String outputJSONPath, + String sourceEPSG, + String targetEPSG) { + // 构造命令行 + return Arrays.asList( + exePath, + inputDXFPath, + outputJSONPath, + sourceEPSG, + targetEPSG + ); + } + +} diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/resources/mapper/project/BusProjectFileMapper.xml b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/resources/mapper/project/BusProjectFileMapper.xml new file mode 100644 index 00000000..e83c4ac8 --- /dev/null +++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/resources/mapper/project/BusProjectFileMapper.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/RuoYi-Vue-Plus/script/sql/xinnengyuan.sql b/RuoYi-Vue-Plus/script/sql/xinnengyuan.sql index 15d58174..12a53699 100644 --- a/RuoYi-Vue-Plus/script/sql/xinnengyuan.sql +++ b/RuoYi-Vue-Plus/script/sql/xinnengyuan.sql @@ -924,3 +924,18 @@ CREATE TABLE `fac_box_transformer` INDEX `idx_project_id` (`project_id` ASC) USING BTREE, INDEX `idx_matrix_id` (`matrix_id` ASC) USING BTREE ) comment = '设施-箱变' COLLATE = utf8mb4_unicode_ci; + +DROP TABLE IF EXISTS `bus_project_file`; +CREATE TABLE `bus_project_file` +( + `id` bigint not null auto_increment comment '主键id', + `project_id` bigint not null comment '项目id', + `file_type` char(2) null comment '文件类型', + `file_name` varchar(255) null comment '文件名称', + `file_path` varchar(1024) null comment '文件路径', + `create_time` datetime default CURRENT_TIMESTAMP null comment '创建时间', + `update_time` datetime default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '更新时间', + `remark` varchar(512) null comment '备注', + PRIMARY KEY (`id`) USING BTREE, + INDEX `idx_project_id` (`project_id` ASC) USING BTREE comment '项目id' +) comment = '项目文件存储' collate = utf8mb4_unicode_ci;