上传项目设计图,将项目设计图dxf文件转化为geojson文件并将存储信息保存到数据库
This commit is contained in:
		| @ -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; | ||||
|     } | ||||
|  | ||||
| } | ||||
| @ -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 { | ||||
|  | ||||
| @ -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<JSONObject> 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); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -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<BusProjectFileVo> 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<BusProjectFileVo> list = busProjectFileService.queryList(req); | ||||
|         ExcelUtil.exportExcel(list, "项目文件存储", BusProjectFileVo.class, response); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取项目文件存储详细信息 | ||||
|      * | ||||
|      * @param id 主键 | ||||
|      */ | ||||
|     @SaCheckPermission("project:projectFile:query") | ||||
|     @GetMapping("/{id}") | ||||
|     public R<BusProjectFileVo> 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<Void> 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<Void> 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<Long> 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<JSONObject> getJSONFile(@NotNull(message = "主键不能为空") | ||||
|                                      @PathVariable Long id){ | ||||
|         return R.ok(busProjectFileService.getJSONFile(id)); | ||||
|     } | ||||
| } | ||||
| @ -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; | ||||
|  | ||||
| } | ||||
| @ -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; | ||||
|  | ||||
| } | ||||
| @ -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; | ||||
|  | ||||
| } | ||||
| @ -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; | ||||
|  | ||||
| } | ||||
| @ -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; | ||||
|  | ||||
|  | ||||
| } | ||||
| @ -160,6 +160,11 @@ public class BusProjectVo implements Serializable { | ||||
|     @ExcelProperty(value = "安全协议书") | ||||
|     private String securityAgreement; | ||||
|  | ||||
|     /** | ||||
|      * 设计文件id | ||||
|      */ | ||||
|     private Long designId; | ||||
|  | ||||
|     /** | ||||
|      * 显示隐藏(0显示 1隐藏) | ||||
|      */ | ||||
|  | ||||
| @ -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<BusProjectFile, BusProjectFileVo> { | ||||
|  | ||||
| } | ||||
| @ -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<BusProjectFile> { | ||||
|  | ||||
|     /** | ||||
|      * 查询项目文件存储 | ||||
|      * | ||||
|      * @param id 主键 | ||||
|      * @return 项目文件存储 | ||||
|      */ | ||||
|     BusProjectFileVo queryById(Long id); | ||||
|  | ||||
|     /** | ||||
|      * 分页查询项目文件存储列表 | ||||
|      * | ||||
|      * @param req       查询条件 | ||||
|      * @param pageQuery 分页参数 | ||||
|      * @return 项目文件存储分页列表 | ||||
|      */ | ||||
|     TableDataInfo<BusProjectFileVo> queryPageList(ProjectFileQueryReq req, PageQuery pageQuery); | ||||
|  | ||||
|     /** | ||||
|      * 查询符合条件的项目文件存储列表 | ||||
|      * | ||||
|      * @param req 查询条件 | ||||
|      * @return 项目文件存储列表 | ||||
|      */ | ||||
|     List<BusProjectFileVo> queryList(ProjectFileQueryReq req); | ||||
|  | ||||
|     /** | ||||
|      * 修改项目文件存储 | ||||
|      * | ||||
|      * @param req 项目文件存储 | ||||
|      * @return 是否修改成功 | ||||
|      */ | ||||
|     Boolean updateByBo(ProjectFileUpdateReq req); | ||||
|  | ||||
|     /** | ||||
|      * 校验并批量删除项目文件存储信息 | ||||
|      * | ||||
|      * @param ids     待删除的主键集合 | ||||
|      * @param isValid 是否进行有效性校验 | ||||
|      * @return 是否删除成功 | ||||
|      */ | ||||
|     Boolean deleteWithValidByIds(Collection<Long> 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<BusProjectFile> buildQueryWrapper(ProjectFileQueryReq req); | ||||
|  | ||||
|     /** | ||||
|      * 获取项目文件存储分页对象视图 | ||||
|      * | ||||
|      * @param projectFilePage 项目文件存储分页对象 | ||||
|      * @return 项目文件存储分页对象视图 | ||||
|      */ | ||||
|     Page<BusProjectFileVo> getVoPage(Page<BusProjectFile> projectFilePage); | ||||
|  | ||||
| } | ||||
| @ -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<BusProjectFileMapper, BusProjectFile> | ||||
|     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<BusProjectFileVo> queryPageList(ProjectFileQueryReq req, PageQuery pageQuery) { | ||||
|         Page<BusProjectFile> projectFilePage = this.page(pageQuery.build(), this.buildQueryWrapper(req)); | ||||
|         return TableDataInfo.build(this.getVoPage(projectFilePage)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 查询符合条件的项目文件存储列表 | ||||
|      * | ||||
|      * @param req 查询条件 | ||||
|      * @return 项目文件存储列表 | ||||
|      */ | ||||
|     @Override | ||||
|     public List<BusProjectFileVo> queryList(ProjectFileQueryReq req) { | ||||
|         LambdaQueryWrapper<BusProjectFile> 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<Long> 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<BusProjectFile> buildQueryWrapper(ProjectFileQueryReq req) { | ||||
|         LambdaQueryWrapper<BusProjectFile> 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<BusProjectFileVo> getVoPage(Page<BusProjectFile> projectFilePage) { | ||||
|         List<BusProjectFile> projectFileList = projectFilePage.getRecords(); | ||||
|         Page<BusProjectFileVo> projectFileVoPage = new Page<>( | ||||
|             projectFilePage.getCurrent(), | ||||
|             projectFilePage.getSize(), | ||||
|             projectFilePage.getTotal()); | ||||
|         if (CollUtil.isEmpty(projectFileList)) { | ||||
|             return projectFileVoPage; | ||||
|         } | ||||
|         List<BusProjectFileVo> projectFileVoList = projectFileList.stream().map(this::getVo).toList(); | ||||
|         projectFileVoPage.setRecords(projectFileVoList); | ||||
|         return projectFileVoPage; | ||||
|     } | ||||
| } | ||||
| @ -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<BusProjectMapper, BusProj | ||||
|     @Resource | ||||
|     private IBusContractorService contractorService; | ||||
|  | ||||
|     @Lazy | ||||
|     @Resource | ||||
|     private IBusProjectFileService projectFileService; | ||||
|  | ||||
|     /** | ||||
|      * 查询项目 | ||||
|      * | ||||
| @ -206,7 +212,7 @@ public class BusProjectServiceImpl extends ServiceImpl<BusProjectMapper, BusProj | ||||
|             throw new ServiceException("修改项目失败,数据不存在", HttpStatus.NOT_FOUND); | ||||
|         } | ||||
|         // 判断名称是否重复 | ||||
|         if (!req.getProjectName().equals(oldProject.getProjectName())) { | ||||
|         if (req.getProjectName() != null && !req.getProjectName().equals(oldProject.getProjectName())) { | ||||
|             Long count = this.lambdaQuery().eq(BusProject::getProjectName, req.getProjectName()).count(); | ||||
|             if (count > 0) { | ||||
|                 throw new ServiceException("项目名称重复", HttpStatus.BAD_REQUEST); | ||||
| @ -287,6 +293,13 @@ public class BusProjectServiceImpl extends ServiceImpl<BusProjectMapper, BusProj | ||||
|             projectVo.setPlayCardStart(split[0]); | ||||
|             projectVo.setPlayCardEnd(split[1]); | ||||
|         } | ||||
|         // 关联设计id | ||||
|         BusProjectFile projectFile = projectFileService.lambdaQuery() | ||||
|             .eq(BusProjectFile::getProjectId, project.getId()) | ||||
|             .one(); | ||||
|         if (projectFile != null) { | ||||
|             projectVo.setDesignId(projectFile.getId()); | ||||
|         } | ||||
|         return projectVo; | ||||
|     } | ||||
|  | ||||
| @ -351,8 +364,29 @@ public class BusProjectServiceImpl extends ServiceImpl<BusProjectMapper, BusProj | ||||
|         if (CollUtil.isEmpty(projectList)) { | ||||
|             return projectVoPage; | ||||
|         } | ||||
|         // 获取项目文件id | ||||
|         Set<Long> projectIdList = projectList.stream().map(BusProject::getId).collect(Collectors.toSet()); | ||||
|         Map<Long, List<BusProjectFile>> projectFileMap = projectFileService.lambdaQuery() | ||||
|             .in(BusProjectFile::getProjectId, projectIdList).list() | ||||
|             .stream().collect(Collectors.groupingBy(BusProjectFile::getProjectId)); | ||||
|         // 对象列表 => 封装对象列表 | ||||
|         List<BusProjectVo> projectVoList = projectList.stream().map(this::getVo).toList(); | ||||
|         List<BusProjectVo> 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<BusProjectFile> projectFileList = projectFileMap.get(project.getId()); | ||||
|             if (CollUtil.isNotEmpty(projectFileList)) { | ||||
|                 projectVo.setDesignId(projectFileList.get(0).getId()); | ||||
|             } | ||||
|             return projectVo; | ||||
|         }).toList(); | ||||
|         projectVoPage.setRecords(projectVoList); | ||||
|         return projectVoPage; | ||||
|     } | ||||
|  | ||||
| @ -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<BusQualityConstructionLogMapper, BusQualityConstructionLog> | ||||
|     implements IBusQualityConstructionLogService { | ||||
| @ -320,36 +323,48 @@ public class BusQualityConstructionLogServiceImpl extends ServiceImpl<BusQuality | ||||
|         } | ||||
|         Map<String, String> 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); | ||||
|  | ||||
| @ -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<BusQualityInspectionMapper, BusQualityInspection> | ||||
|     implements IBusQualityInspectionService { | ||||
| @ -372,36 +375,48 @@ public class BusQualityInspectionServiceImpl extends ServiceImpl<BusQualityInspe | ||||
|         } | ||||
|         Map<String, String> 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); | ||||
|  | ||||
| @ -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<BusSafetyInspectionMapper, BusSafetyInspection> | ||||
|     implements IBusSafetyInspectionService { | ||||
| @ -334,36 +337,48 @@ public class BusSafetyInspectionServiceImpl extends ServiceImpl<BusSafetyInspect | ||||
|         } | ||||
|         Map<String, String> 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); | ||||
|  | ||||
| @ -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<String> 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<String> buildParameter(String exePath, | ||||
|                                               String inputDXFPath, | ||||
|                                               String outputJSONPath, | ||||
|                                               String sourceEPSG, | ||||
|                                               String targetEPSG) { | ||||
|         // 构造命令行 | ||||
|         return Arrays.asList( | ||||
|             exePath, | ||||
|             inputDXFPath, | ||||
|             outputJSONPath, | ||||
|             sourceEPSG, | ||||
|             targetEPSG | ||||
|         ); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @ -0,0 +1,7 @@ | ||||
| <?xml version="1.0" encoding="UTF-8" ?> | ||||
| <!DOCTYPE mapper | ||||
| PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" | ||||
| "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | ||||
| <mapper namespace="org.dromara.project.mapper.BusProjectFileMapper"> | ||||
|  | ||||
| </mapper> | ||||
		Reference in New Issue
	
	Block a user