src/main/java/com/ruoyi/framework/config/FilterConfig.java
@@ -1,16 +1,17 @@ package com.ruoyi.framework.config; import java.util.HashMap; import java.util.Map; import javax.servlet.DispatcherType; import com.ruoyi.common.filter.RepeatableFilter; import com.ruoyi.common.filter.XssFilter; import com.ruoyi.common.utils.StringUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.ruoyi.common.filter.RepeatableFilter; import com.ruoyi.common.filter.XssFilter; import com.ruoyi.common.utils.StringUtils; import javax.servlet.DispatcherType; import java.util.HashMap; import java.util.Map; /** * Filteré ç½® src/main/java/com/ruoyi/project/system/controller/SysLoginController.java
@@ -1,18 +1,5 @@ package com.ruoyi.project.system.controller; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; import com.ruoyi.project.system.domain.SysDept; import com.ruoyi.project.system.domain.vo.SysUserDeptVo; import com.ruoyi.project.system.mapper.SysDeptMapper; import com.ruoyi.project.system.service.ISysUserDeptService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.ObjectUtils; import org.springframework.web.bind.annotation.*; import com.ruoyi.common.constant.Constants; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.framework.security.LoginBody; @@ -21,9 +8,25 @@ import com.ruoyi.framework.security.service.SysPermissionService; import com.ruoyi.framework.security.service.TokenService; import com.ruoyi.framework.web.domain.AjaxResult; import com.ruoyi.project.system.domain.SysDept; import com.ruoyi.project.system.domain.SysMenu; import com.ruoyi.project.system.domain.SysUser; import com.ruoyi.project.system.domain.vo.SysUserDeptVo; import com.ruoyi.project.system.mapper.SysDeptMapper; import com.ruoyi.project.system.service.ISysMenuService; import com.ruoyi.project.system.service.ISysUserDeptService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.ObjectUtils; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; /** * ç»å½éªè¯ src/main/java/com/ruoyi/technology/bean/dto/TechnologyBomDto.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,17 @@ package com.ruoyi.technology.bean.dto; import com.ruoyi.technology.pojo.TechnologyBom; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; @EqualsAndHashCode(callSuper = true) @Data public class TechnologyBomDto extends TechnologyBom { @ApiModelProperty("产ååç§°") private String productName; @ApiModelProperty("è§æ ¼åå·") private String productModelName; } src/main/java/com/ruoyi/technology/bean/dto/TechnologyBomStructureDto.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,31 @@ package com.ruoyi.technology.bean.dto; import com.ruoyi.technology.pojo.TechnologyBomStructure; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; import java.util.List; @Data @EqualsAndHashCode(callSuper = true) public class TechnologyBomStructureDto extends TechnologyBomStructure { @ApiModelProperty("å·¥åºåç§°") private String operationName; @ApiModelProperty("产ååç§°") private String productName; @ApiModelProperty("产åID") private Long productId; @ApiModelProperty("è§æ ¼åå·") private String model; private String tempId; private String parentTempId; private List<TechnologyBomStructureDto> children; } src/main/java/com/ruoyi/technology/bean/dto/TechnologyOperationDto.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,12 @@ package com.ruoyi.technology.bean.dto; import com.ruoyi.technology.pojo.TechnologyOperation; import io.swagger.annotations.ApiModel; import lombok.Data; import lombok.EqualsAndHashCode; @EqualsAndHashCode(callSuper = true) @Data @ApiModel(value = "TechnologyOperationDto对象", description = "å·¥åºæ¥è¯¢åæ°") public class TechnologyOperationDto extends TechnologyOperation { } src/main/java/com/ruoyi/technology/bean/dto/TechnologyOperationParamDto.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,29 @@ package com.ruoyi.technology.bean.dto; import com.ruoyi.technology.pojo.TechnologyOperationParam; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; @Data @EqualsAndHashCode(callSuper = true) public class TechnologyOperationParamDto extends TechnologyOperationParam { @ApiModelProperty("åæ°ç¼ç ") private String paramCode; @ApiModelProperty("åæ°åç§°") private String paramName; @ApiModelProperty("åæ°ç±»å") private Byte paramType; @ApiModelProperty("åæ°æ ¼å¼") private String paramFormat; @ApiModelProperty("åä½") private String unit; @ApiModelProperty("æ¯å¦å¿ å¡«") private Byte isRequired; } src/main/java/com/ruoyi/technology/bean/dto/TechnologyParamDto.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,10 @@ package com.ruoyi.technology.bean.dto; import com.ruoyi.technology.pojo.TechnologyParam; import lombok.Data; import lombok.EqualsAndHashCode; @EqualsAndHashCode(callSuper = true) @Data public class TechnologyParamDto extends TechnologyParam { } src/main/java/com/ruoyi/technology/bean/dto/TechnologyRoutingDto.java
@@ -3,7 +3,9 @@ import com.ruoyi.technology.pojo.TechnologyRouting; import io.swagger.annotations.ApiModel; import lombok.Data; import lombok.EqualsAndHashCode; @EqualsAndHashCode(callSuper = true) @Data @ApiModel(value = "TechnologyRoutingDto对象", description = "å·¥èºè·¯çº¿è¡¨") public class TechnologyRoutingDto extends TechnologyRouting { src/main/java/com/ruoyi/technology/bean/dto/TechnologyRoutingOperationDto.java
@@ -3,7 +3,9 @@ import com.ruoyi.technology.pojo.TechnologyRoutingOperation; import io.swagger.annotations.ApiModel; import lombok.Data; import lombok.EqualsAndHashCode; @EqualsAndHashCode(callSuper = true) @Data @ApiModel(value = "TechnologyRoutingOperationDto对象", description = "å·¥èºè·¯çº¿å·¥åºæ¥è¯¢åæ°") public class TechnologyRoutingOperationDto extends TechnologyRoutingOperation { src/main/java/com/ruoyi/technology/bean/vo/TechnologyBomStructureVo.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,27 @@ package com.ruoyi.technology.bean.vo; import com.ruoyi.technology.pojo.TechnologyBomStructure; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; import java.util.List; @Data @EqualsAndHashCode(callSuper = true) public class TechnologyBomStructureVo extends TechnologyBomStructure { @ApiModelProperty("å·¥åºåç§°") private String operationName; @ApiModelProperty("产ååç§°") private String productName; @ApiModelProperty("产åID") private Long productId; @ApiModelProperty("è§æ ¼åå·") private String model; private List<TechnologyBomStructureVo> children; } src/main/java/com/ruoyi/technology/bean/vo/TechnologyBomVo.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,15 @@ package com.ruoyi.technology.bean.vo; import com.ruoyi.technology.pojo.TechnologyBom; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @Data public class TechnologyBomVo extends TechnologyBom { @ApiModelProperty("产ååç§°") private String productName; @ApiModelProperty("è§æ ¼åå·") private String productModelName; } src/main/java/com/ruoyi/technology/bean/vo/TechnologyOperationParamVo.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,29 @@ package com.ruoyi.technology.bean.vo; import com.ruoyi.technology.pojo.TechnologyOperationParam; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; @Data @EqualsAndHashCode(callSuper = true) public class TechnologyOperationParamVo extends TechnologyOperationParam { @ApiModelProperty("åæ°ç¼ç ") private String paramCode; @ApiModelProperty("åæ°åç§°") private String paramName; @ApiModelProperty("åæ°ç±»å") private Byte paramType; @ApiModelProperty("åæ°æ ¼å¼") private String paramFormat; @ApiModelProperty("åä½") private String unit; @ApiModelProperty("æ¯å¦å¿ å¡«") private Byte isRequired; } src/main/java/com/ruoyi/technology/bean/vo/TechnologyOperationVo.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,12 @@ package com.ruoyi.technology.bean.vo; import com.ruoyi.technology.pojo.TechnologyOperation; import io.swagger.annotations.ApiModel; import lombok.Data; import lombok.EqualsAndHashCode; @EqualsAndHashCode(callSuper = true) @Data @ApiModel(value = "TechnologyOperationVo对象", description = "å·¥åºè¿å对象") public class TechnologyOperationVo extends TechnologyOperation { } src/main/java/com/ruoyi/technology/bean/vo/TechnologyParamVo.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,8 @@ package com.ruoyi.technology.bean.vo; import com.ruoyi.technology.pojo.TechnologyParam; import lombok.Data; @Data public class TechnologyParamVo extends TechnologyParam { } src/main/java/com/ruoyi/technology/bean/vo/TechnologyRoutingOperationVo.java
@@ -3,7 +3,9 @@ import com.ruoyi.technology.pojo.TechnologyRoutingOperation; import io.swagger.annotations.ApiModel; import lombok.Data; import lombok.EqualsAndHashCode; @EqualsAndHashCode(callSuper = true) @Data @ApiModel(value = "TechnologyRoutingOperationVo对象", description = "å·¥èºè·¯çº¿å·¥åºè¿å对象") public class TechnologyRoutingOperationVo extends TechnologyRoutingOperation { src/main/java/com/ruoyi/technology/bean/vo/TechnologyRoutingVo.java
@@ -3,7 +3,9 @@ import com.ruoyi.technology.pojo.TechnologyRouting; import io.swagger.annotations.ApiModel; import lombok.Data; import lombok.EqualsAndHashCode; @EqualsAndHashCode(callSuper = true) @Data @ApiModel(value = "TechnologyRoutingVo对象", description = "å·¥èºè·¯çº¿è¡¨") public class TechnologyRoutingVo extends TechnologyRouting { src/main/java/com/ruoyi/technology/controller/TechnologyBomController.java
@@ -1,18 +1,90 @@ package com.ruoyi.technology.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.framework.aspectj.lang.annotation.Log; import com.ruoyi.framework.aspectj.lang.enums.BusinessType; import com.ruoyi.framework.web.domain.R; import com.ruoyi.production.dto.BomImportDto; import com.ruoyi.technology.bean.dto.TechnologyBomDto; import com.ruoyi.technology.bean.vo.TechnologyBomVo; import com.ruoyi.technology.pojo.TechnologyBom; import com.ruoyi.technology.service.TechnologyBomService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; /** * <p> * BOM表 å端æ§å¶å¨ * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-04-20 10:05:55 */ import javax.servlet.http.HttpServletResponse; import java.util.List; @RestController @RequestMapping("/technologyBom") @RequiredArgsConstructor @Api(tags = "åºç¡BOM") public class TechnologyBomController { private final TechnologyBomService technologyBomService; @GetMapping("/listPage") @Log(title = "Technology BOM page", businessType = BusinessType.OTHER) @ApiOperation("BOMå页æ¥è¯¢") public R<IPage<TechnologyBomVo>> listPage(Page<TechnologyBomDto> page, TechnologyBomDto technologyBomDto) { return R.ok(technologyBomService.listPage(page, technologyBomDto)); } @PostMapping("/add") @Log(title = "Add technology BOM", businessType = BusinessType.INSERT) @ApiOperation("æ°å¢BOM") public R add(@RequestBody TechnologyBom technologyBom) { return technologyBomService.add(technologyBom); } @PutMapping("/update") @Log(title = "Update technology BOM", businessType = BusinessType.UPDATE) @ApiOperation("ä¿®æ¹BOM") public R update(@RequestBody TechnologyBom technologyBom) { return technologyBomService.update(technologyBom); } @DeleteMapping("/batchDelete") @Log(title = "Delete technology BOM", businessType = BusinessType.DELETE) @ApiOperation("æ¹éå é¤BOM") public R batchDelete(@RequestBody List<Integer> ids) { return R.ok(technologyBomService.batchDelete(ids)); } @GetMapping("/getByModel") @Log(title = "List BOM by model", businessType = BusinessType.OTHER) @ApiOperation("æ ¹æ®è§æ ¼æ¥è¯¢BOM") public R<List<TechnologyBomVo>> getByModel(Long productModelId) { return R.ok(technologyBomService.listByModel(productModelId)); } @PostMapping("/uploadBom") @PreAuthorize("@ss.hasPermi('product:bom:import')") @Log(title = "æ ¹æ®Excelå¯¼å ¥BOM", businessType = BusinessType.IMPORT) @ApiOperation("æ ¹æ®Excelå¯¼å ¥BOM") public R uploadBom(@RequestParam("file") MultipartFile file) { return technologyBomService.uploadBom(file); } @PostMapping("/exportBom") @PreAuthorize("@ss.hasPermi('product:bom:export')") @ApiOperation("导åºBOMæä»¶") @Log(title = "导åºBOMæä»¶", businessType = BusinessType.EXPORT) public void exportBom(HttpServletResponse response, @RequestParam Integer bomId) { technologyBomService.exportBom(response, bomId); } @GetMapping("/downloadTemplate") @Log(title = "ä¸è½½BOMå¯¼å ¥æ¨¡æ¿", businessType = BusinessType.EXPORT) @ApiOperation("ä¸è½½BOMå¯¼å ¥æ¨¡æ¿") public void importTemplate(HttpServletResponse response) { ExcelUtil<BomImportDto> excelUtil = new ExcelUtil<>(BomImportDto.class); excelUtil.importTemplateExcel(response, "BOMå¯¼å ¥æ¨¡æ¿"); } } src/main/java/com/ruoyi/technology/controller/TechnologyBomStructureController.java
@@ -1,18 +1,33 @@ package com.ruoyi.technology.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.ruoyi.framework.web.domain.R; import com.ruoyi.technology.bean.dto.TechnologyBomStructureDto; import com.ruoyi.technology.bean.vo.TechnologyBomStructureVo; import com.ruoyi.technology.service.TechnologyBomStructureService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; /** * <p> * BOM产åç»æè¡¨ å端æ§å¶å¨ * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-04-20 10:06:17 */ import java.util.List; @RestController @RequestMapping("/technologyBomStructure") @RequiredArgsConstructor @Api(tags = "BOMç»æ") public class TechnologyBomStructureController { private final TechnologyBomStructureService technologyBomStructureService; @PostMapping @ApiOperation("æ°å¢æä¿®æ¹BOMç»æ") public R addOrUpdate(@RequestBody TechnologyBomStructureDto technologyBomStructureDto) { return R.ok(technologyBomStructureService.addTechnologyBomStructure(technologyBomStructureDto)); } @GetMapping("/listByBomId/{bomId}") @ApiOperation("æ ¹æ®BOMæ¥è¯¢ç»ææ ") public R<List<TechnologyBomStructureVo>> listByBomId(@PathVariable("bomId") Long bomId) { return R.ok(technologyBomStructureService.listByBomId(bomId)); } } src/main/java/com/ruoyi/technology/controller/TechnologyOperationController.java
@@ -1,18 +1,59 @@ package com.ruoyi.technology.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.framework.aspectj.lang.annotation.Log; import com.ruoyi.framework.aspectj.lang.enums.BusinessType; import com.ruoyi.framework.web.domain.R; import com.ruoyi.technology.bean.dto.TechnologyOperationDto; import com.ruoyi.technology.bean.vo.TechnologyOperationVo; import com.ruoyi.technology.service.TechnologyOperationService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; /** * <p> * å·¥åºè¡¨ å端æ§å¶å¨ * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-04-20 10:33:03 */ import java.util.List; @RestController @Api(tags = "å·¥åºç®¡ç") @RequestMapping("/technologyOperation") @RequiredArgsConstructor public class TechnologyOperationController { private final TechnologyOperationService technologyOperationService; @GetMapping("/listPage") @Log(title = "Technology operation page", businessType = BusinessType.OTHER) @ApiOperation("å·¥åºå页æ¥è¯¢") public R<IPage<TechnologyOperationVo>> listPage(Page<TechnologyOperationDto> page, TechnologyOperationDto technologyOperationDto) { return R.ok(technologyOperationService.listPage(page, technologyOperationDto)); } @PostMapping @Log(title = "Add technology operation", businessType = BusinessType.INSERT) @ApiOperation("æ°å¢å·¥åº") public R add(@RequestBody TechnologyOperationDto technologyOperationDto) { return technologyOperationService.add(technologyOperationDto); } @PutMapping("/update") @Log(title = "Update technology operation", businessType = BusinessType.UPDATE) @ApiOperation("ä¿®æ¹å·¥åº") public R update(@RequestBody com.ruoyi.technology.pojo.TechnologyOperation technologyOperation) { return R.ok(technologyOperationService.updateById(technologyOperation)); } @DeleteMapping("/batchDelete") @Log(title = "Delete technology operation", businessType = BusinessType.DELETE) @ApiOperation("æ¹éå é¤å·¥åº") public R batchDelete(@RequestBody List<Long> ids) { return R.ok(technologyOperationService.batchDelete(ids)); } @GetMapping("/list") @ApiOperation("æ¥è¯¢å ¨é¨å·¥åº") public R<List<TechnologyOperationVo>> list() { return R.ok(technologyOperationService.listVo()); } } src/main/java/com/ruoyi/technology/controller/TechnologyOperationParamController.java
@@ -1,18 +1,44 @@ package com.ruoyi.technology.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.ruoyi.framework.aspectj.lang.annotation.Log; import com.ruoyi.framework.aspectj.lang.enums.BusinessType; import com.ruoyi.framework.web.domain.AjaxResult; import com.ruoyi.framework.web.domain.R; import com.ruoyi.technology.bean.dto.TechnologyOperationParamDto; import com.ruoyi.technology.bean.vo.TechnologyOperationParamVo; import com.ruoyi.technology.pojo.TechnologyOperationParam; import com.ruoyi.technology.service.TechnologyOperationParamService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; /** * <p> * å·¥åºåæ° å端æ§å¶å¨ * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-04-20 10:05:35 */ import java.util.List; @RestController @RequestMapping("/technologyOperationParam") @Api(tags = "å·¥åºåæ°") @RequiredArgsConstructor public class TechnologyOperationParamController { private final TechnologyOperationParamService technologyOperationParamService; @GetMapping("/list") @ApiOperation("å·¥åºåæ°å表æ¥è¯¢") public R<List<TechnologyOperationParamVo>> list(TechnologyOperationParamDto technologyOperationParamDto) { return R.ok(technologyOperationParamService.listOperationParam(technologyOperationParamDto)); } @PostMapping @ApiOperation("æ°å¢æä¿®æ¹å·¥åºåæ°") public R addOrUpdate(@RequestBody TechnologyOperationParam technologyOperationParam) { return R.ok(technologyOperationParamService.saveTechnologyOperationParam(technologyOperationParam)); } @DeleteMapping("/batchDelete/{id}") @Log(title = "Delete technology operation param", businessType = BusinessType.DELETE) @ApiOperation("å é¤å·¥åºåæ°") public AjaxResult batchDelete(@PathVariable("id") Long id) { return AjaxResult.success(technologyOperationParamService.batchDelete(id)); } } src/main/java/com/ruoyi/technology/controller/TechnologyParamController.java
@@ -1,18 +1,52 @@ package com.ruoyi.technology.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.framework.aspectj.lang.annotation.Log; import com.ruoyi.framework.aspectj.lang.enums.BusinessType; import com.ruoyi.framework.web.domain.R; import com.ruoyi.technology.bean.dto.TechnologyParamDto; import com.ruoyi.technology.bean.vo.TechnologyParamVo; import com.ruoyi.technology.service.TechnologyParamService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; /** * <p> * åºç¡åæ°è¡¨ å端æ§å¶å¨ * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-04-20 09:45:20 */ @RestController @RequestMapping("/technologyParam") @RequiredArgsConstructor @Api(tags = "åºç¡åæ°") public class TechnologyParamController { private final TechnologyParamService technologyParamService; @GetMapping("list") @Log(title = "åºç¡åæ°æ°æ®éå", businessType = BusinessType.OTHER) @ApiOperation("åºç¡åæ°å页æ¥è¯¢") public R<IPage<TechnologyParamVo>> TechnologyParamDtoList(Page<TechnologyParamDto> page, TechnologyParamDto technologyParamDto) { IPage<TechnologyParamVo> paramList = technologyParamService.baseParamList(page, technologyParamDto); return R.ok(paramList); } @PostMapping("/add") @Log(title = "æ°å¢åºç¡åæ°", businessType = BusinessType.INSERT) @ApiOperation("æ°å¢åºç¡åæ°") public R TechnologyParamDtoAdd(@RequestBody TechnologyParamDto TechnologyParamDto) { return R.ok(technologyParamService.addBaseParam(TechnologyParamDto)); } @PutMapping("/edit") @Log(title = "ä¿®æ¹åºç¡åæ°", businessType = BusinessType.UPDATE) @ApiOperation("ä¿®æ¹åºç¡åæ°") public R TechnologyParamDtoEdit(@RequestBody TechnologyParamDto TechnologyParamDto) { return R.ok(technologyParamService.updateBaseParam(TechnologyParamDto)); } @DeleteMapping("/remove/{ids}") @Log(title = "å é¤åºç¡åæ°", businessType = BusinessType.DELETE) @ApiOperation("å é¤åºç¡åæ°") public R TechnologyParamDtoRemove(@PathVariable Long[] ids) { return R.ok(technologyParamService.deleteBaseParamByIds(ids)); } } src/main/java/com/ruoyi/technology/mapper/TechnologyBomMapper.java
@@ -1,8 +1,13 @@ package com.ruoyi.technology.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.technology.bean.dto.TechnologyBomDto; import com.ruoyi.technology.bean.vo.TechnologyBomVo; import com.ruoyi.technology.pojo.TechnologyBom; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; /** * <p> @@ -15,4 +20,5 @@ @Mapper public interface TechnologyBomMapper extends BaseMapper<TechnologyBom> { IPage<TechnologyBomVo> listPage(Page<TechnologyBomDto> page, @Param("c") TechnologyBomDto technologyBomDto); } src/main/java/com/ruoyi/technology/mapper/TechnologyBomStructureMapper.java
@@ -1,8 +1,12 @@ package com.ruoyi.technology.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.ruoyi.technology.bean.vo.TechnologyBomStructureVo; import com.ruoyi.technology.pojo.TechnologyBomStructure; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import java.util.List; /** * <p> @@ -15,4 +19,5 @@ @Mapper public interface TechnologyBomStructureMapper extends BaseMapper<TechnologyBomStructure> { List<TechnologyBomStructureVo> listByBomId(@Param("bomId") Long bomId); } src/main/java/com/ruoyi/technology/mapper/TechnologyOperationMapper.java
@@ -1,8 +1,13 @@ package com.ruoyi.technology.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.technology.bean.dto.TechnologyOperationDto; import com.ruoyi.technology.bean.vo.TechnologyOperationVo; import com.ruoyi.technology.pojo.TechnologyOperation; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; /** * <p> @@ -15,4 +20,5 @@ @Mapper public interface TechnologyOperationMapper extends BaseMapper<TechnologyOperation> { IPage<TechnologyOperationVo> listPage(Page<TechnologyOperationDto> page, @Param("c") TechnologyOperationDto technologyOperationDto); } src/main/java/com/ruoyi/technology/mapper/TechnologyOperationParamMapper.java
@@ -1,8 +1,12 @@ package com.ruoyi.technology.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.ruoyi.technology.bean.vo.TechnologyOperationParamVo; import com.ruoyi.technology.pojo.TechnologyOperationParam; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import java.util.List; /** * <p> @@ -15,4 +19,6 @@ @Mapper public interface TechnologyOperationParamMapper extends BaseMapper<TechnologyOperationParam> { List<TechnologyOperationParamVo> listOperationParam(@Param("technologyOperationId") Long technologyOperationId, @Param("paramId") Long technologyParamId); } src/main/java/com/ruoyi/technology/mapper/TechnologyRoutingMapper.java
@@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.ruoyi.technology.pojo.TechnologyRouting; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; /** * <p> @@ -15,4 +16,5 @@ @Mapper public interface TechnologyRoutingMapper extends BaseMapper<TechnologyRouting> { int updateProductModelByBomId(@Param("productModelId") Long productModelId, @Param("bomId") Long bomId); } src/main/java/com/ruoyi/technology/service/TechnologyBomService.java
@@ -1,16 +1,30 @@ package com.ruoyi.technology.service; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.IService; import com.ruoyi.framework.web.domain.R; import com.ruoyi.technology.bean.dto.TechnologyBomDto; import com.ruoyi.technology.bean.vo.TechnologyBomVo; import com.ruoyi.technology.pojo.TechnologyBom; import org.springframework.web.multipart.MultipartFile; /** * <p> * BOM表 æå¡ç±» * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-04-20 10:05:55 */ import javax.servlet.http.HttpServletResponse; import java.util.List; public interface TechnologyBomService extends IService<TechnologyBom> { IPage<TechnologyBomVo> listPage(Page<TechnologyBomDto> page, TechnologyBomDto technologyBomDto); List<TechnologyBomVo> listByModel(Long productModelId); R add(TechnologyBom technologyBom); R update(TechnologyBom technologyBom); boolean batchDelete(List<Integer> ids); R uploadBom(MultipartFile file); void exportBom(HttpServletResponse response, Integer bomId); } src/main/java/com/ruoyi/technology/service/TechnologyBomStructureService.java
@@ -1,16 +1,15 @@ package com.ruoyi.technology.service; import com.baomidou.mybatisplus.extension.service.IService; import com.ruoyi.technology.bean.dto.TechnologyBomStructureDto; import com.ruoyi.technology.bean.vo.TechnologyBomStructureVo; import com.ruoyi.technology.pojo.TechnologyBomStructure; /** * <p> * BOM产åç»æè¡¨ æå¡ç±» * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-04-20 10:06:17 */ import java.util.List; public interface TechnologyBomStructureService extends IService<TechnologyBomStructure> { Boolean addTechnologyBomStructure(TechnologyBomStructureDto technologyBomStructureDto); List<TechnologyBomStructureVo> listByBomId(Long bomId); } src/main/java/com/ruoyi/technology/service/TechnologyOperationParamService.java
@@ -1,16 +1,17 @@ package com.ruoyi.technology.service; import com.baomidou.mybatisplus.extension.service.IService; import com.ruoyi.technology.bean.dto.TechnologyOperationParamDto; import com.ruoyi.technology.bean.vo.TechnologyOperationParamVo; import com.ruoyi.technology.pojo.TechnologyOperationParam; /** * <p> * å·¥åºåæ° æå¡ç±» * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-04-20 10:05:35 */ import java.util.List; public interface TechnologyOperationParamService extends IService<TechnologyOperationParam> { List<TechnologyOperationParamVo> listOperationParam(TechnologyOperationParamDto technologyOperationParamDto); boolean saveTechnologyOperationParam(TechnologyOperationParam technologyOperationParam); String batchDelete(Long id); } src/main/java/com/ruoyi/technology/service/TechnologyOperationService.java
@@ -1,16 +1,22 @@ package com.ruoyi.technology.service; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.IService; import com.ruoyi.framework.web.domain.R; import com.ruoyi.technology.bean.dto.TechnologyOperationDto; import com.ruoyi.technology.bean.vo.TechnologyOperationVo; import com.ruoyi.technology.pojo.TechnologyOperation; /** * <p> * å·¥åºè¡¨ æå¡ç±» * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-04-20 10:33:03 */ import java.util.List; public interface TechnologyOperationService extends IService<TechnologyOperation> { IPage<TechnologyOperationVo> listPage(Page<TechnologyOperationDto> page, TechnologyOperationDto technologyOperationDto); R add(TechnologyOperationDto technologyOperationDto); String batchDelete(List<Long> ids); List<TechnologyOperationVo> listVo(); } src/main/java/com/ruoyi/technology/service/TechnologyParamService.java
@@ -1,6 +1,10 @@ package com.ruoyi.technology.service; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.IService; import com.ruoyi.technology.bean.dto.TechnologyParamDto; import com.ruoyi.technology.bean.vo.TechnologyParamVo; import com.ruoyi.technology.pojo.TechnologyParam; /** @@ -13,4 +17,11 @@ */ public interface TechnologyParamService extends IService<TechnologyParam> { IPage<TechnologyParamVo> baseParamList(Page<TechnologyParamDto> page, TechnologyParamDto technologyParamDto); int addBaseParam(TechnologyParamDto technologyParamDto); int updateBaseParam(TechnologyParamDto technologyParamDto); int deleteBaseParamByIds(Long[] ids); } src/main/java/com/ruoyi/technology/service/impl/TechnologyBomServiceImpl.java
@@ -1,20 +1,387 @@ package com.ruoyi.technology.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.basic.pojo.Product; import com.ruoyi.basic.pojo.ProductModel; import com.ruoyi.basic.service.IProductModelService; import com.ruoyi.basic.service.IProductService; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.framework.web.domain.R; import com.ruoyi.production.dto.BomImportDto; import com.ruoyi.production.dto.ProductStructureDto; import com.ruoyi.production.pojo.ProductStructure; import com.ruoyi.technology.bean.dto.TechnologyBomDto; import com.ruoyi.technology.bean.vo.TechnologyBomVo; import com.ruoyi.technology.mapper.TechnologyBomMapper; import com.ruoyi.technology.mapper.TechnologyRoutingMapper; import com.ruoyi.technology.pojo.TechnologyBom; import com.ruoyi.technology.pojo.TechnologyBomStructure; import com.ruoyi.technology.pojo.TechnologyRouting; import com.ruoyi.technology.service.TechnologyBomService; import com.ruoyi.technology.service.TechnologyBomStructureService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; /** * <p> * BOM表 æå¡å®ç°ç±» * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-04-20 10:05:55 */ import javax.servlet.http.HttpServletResponse; import java.math.BigDecimal; import java.util.*; import java.util.stream.Collectors; @Service @RequiredArgsConstructor public class TechnologyBomServiceImpl extends ServiceImpl<TechnologyBomMapper, TechnologyBom> implements TechnologyBomService { private final TechnologyBomMapper technologyBomMapper; private final IProductModelService productModelService; private final TechnologyBomStructureService technologyBomStructureService; private final TechnologyRoutingMapper technologyRoutingMapper; private final IProductService productService; /** * å页æ¥è¯¢BOMå表ã */ @Override public IPage<TechnologyBomVo> listPage(Page<TechnologyBomDto> page, TechnologyBomDto technologyBomDto) { return technologyBomMapper.listPage(page, technologyBomDto); } /** * æ ¹æ®è§æ ¼æ¥è¯¢BOM并转æ¢ä¸ºè¿å对象ã */ @Override public List<TechnologyBomVo> listByModel(Long productModelId) { List<TechnologyBom> list = this.list(Wrappers.<TechnologyBom>lambdaQuery() .eq(TechnologyBom::getProductModelId, productModelId)); List<TechnologyBomVo> result = new ArrayList<>(list.size()); for (TechnologyBom item : list) { TechnologyBomVo vo = new TechnologyBomVo(); vo.setId(item.getId()); vo.setProductModelId(item.getProductModelId()); vo.setRemark(item.getRemark()); vo.setVersion(item.getVersion()); vo.setCreateTime(item.getCreateTime()); vo.setUpdateTime(item.getUpdateTime()); vo.setCreateUser(item.getCreateUser()); vo.setUpdateUser(item.getUpdateUser()); vo.setBomNo(item.getBomNo()); vo.setDeptId(item.getDeptId()); result.add(vo); } return result; } /** * æ°å¢BOMå¹¶åå§åæ ¹ç»æèç¹ã */ @Override @Transactional(rollbackFor = Exception.class) public R add(TechnologyBom technologyBom) { validateProductModel(technologyBom.getProductModelId()); boolean saved = technologyBomMapper.insert(technologyBom) > 0; if (!saved) { return R.fail("Add BOM failed"); } technologyBom.setBomNo("BM." + String.format("%05d", technologyBom.getId())); technologyBomMapper.updateById(technologyBom); initRootStructure(technologyBom.getId().longValue(), technologyBom.getProductModelId()); return R.ok(); } /** * ä¿®æ¹BOMï¼è§æ ¼å忶忥巿°å ³èç»æä¸è·¯çº¿æ°æ®ã */ @Override @Transactional(rollbackFor = Exception.class) public R update(TechnologyBom technologyBom) { if (technologyBom.getId() == null) { throw new ServiceException("BOM id is required"); } validateProductModel(technologyBom.getProductModelId()); TechnologyBom oldBom = technologyBomMapper.selectById(technologyBom.getId()); if (oldBom == null) { throw new ServiceException("BOM not found"); } if (oldBom.getProductModelId() != null && !oldBom.getProductModelId().equals(technologyBom.getProductModelId())) { technologyRoutingMapper.updateProductModelByBomId(technologyBom.getProductModelId(), technologyBom.getId().longValue()); technologyBomStructureService.remove(Wrappers.<TechnologyBomStructure>lambdaQuery() .eq(TechnologyBomStructure::getBomId, technologyBom.getId().longValue())); initRootStructure(technologyBom.getId().longValue(), technologyBom.getProductModelId()); } if (technologyBom.getBomNo() == null) { technologyBom.setBomNo(oldBom.getBomNo()); } technologyBomMapper.updateById(technologyBom); return R.ok(); } /** * å é¤BOMåæ ¡éªæ¯å¦å·²è¢«å·¥èºè·¯çº¿å¼ç¨ã */ @Override @Transactional(rollbackFor = Exception.class) public boolean batchDelete(List<Integer> ids) { if (ids == null || ids.isEmpty()) { throw new ServiceException("Select at least one BOM"); } List<TechnologyRouting> list = technologyRoutingMapper.selectList(Wrappers.<TechnologyRouting>lambdaQuery() .in(TechnologyRouting::getBomId, ids)); if (!list.isEmpty()) { throw new ServiceException("BOM is referenced by routing"); } technologyBomStructureService.remove(Wrappers.<TechnologyBomStructure>lambdaQuery() .in(TechnologyBomStructure::getBomId, ids)); return this.removeBatchByIds(ids); } /** * æ ¡éªäº§åè§æ ¼æ¯å¦åå¨ã */ private void validateProductModel(Long productModelId) { if (productModelId == null) { throw new ServiceException("Product model is required"); } ProductModel productModel = productModelService.getById(productModelId); if (productModel == null) { throw new ServiceException("Product model not found"); } } /** * åå§åBOMæ ¹èç¹ç»æã */ private void initRootStructure(Long bomId, Long productModelId) { ProductModel productModel = productModelService.getById(productModelId); TechnologyBomStructure root = new TechnologyBomStructure(); root.setBomId(bomId); root.setParentId(null); root.setProductModelId(productModelId); root.setUnit(productModel.getUnit()); root.setUnitQuantity(BigDecimal.ONE); technologyBomStructureService.save(root); } @Override @Transactional(rollbackFor = Exception.class) public R uploadBom(MultipartFile file) { ExcelUtil<BomImportDto> util = new ExcelUtil<>(BomImportDto.class); List<BomImportDto> list; try { list = util.importExcel(file.getInputStream()); } catch (Exception e) { return R.fail("Excelè§£æå¤±è´¥"); } if (list == null || list.isEmpty()) return R.fail("æ°æ®ä¸ºç©º"); // å¤çå·¥åº list.forEach(dto -> { dto.setParentName(clean(dto.getParentName())); dto.setParentSpec(clean(dto.getParentSpec())); dto.setChildName(clean(dto.getChildName())); dto.setChildSpec(clean(dto.getChildSpec())); }); handleProcess(list); // Map<String, Long> processMap = productProcessService.list().stream() // .collect(Collectors.toMap(ProductProcess::getName, ProductProcess::getId, (k1, k2) -> k1)); // å建 BOM æ°æ® BomImportDto first = list.get(0); ProductModel rootModel = findModel(first.getParentName(), first.getParentSpec()); TechnologyBom bom = new TechnologyBom(); bom.setProductModelId(rootModel.getId()); bom.setVersion("1.0"); technologyBomMapper.insert(bom); bom.setBomNo("BM." + String.format("%05d", bom.getId())); technologyBomMapper.updateById(bom); // è®°å½å·²ç»æå ¥ç»æçèç¹ï¼Key = "åç§°+è§æ ¼", Value = structure_id Map<String, Long> treePathMap = new HashMap<>(); for (int i = 0; i < list.size(); i++) { BomImportDto dto = list.get(i); String parentKey = dto.getParentName() + "|" + dto.getParentSpec(); String childKey = dto.getChildName() + "|" + dto.getChildSpec(); //å¤çæ ¹èç¹,第ä¸è¡ä¸å项为空 if (i == 0 && StringUtils.isBlank(dto.getChildName())) { ProductStructure rootNode = new ProductStructure(); rootNode.setBomId(bom.getId()); rootNode.setParentId(null); // 顶屿²¡æç¶èç¹ rootNode.setProductModelId(rootModel.getId()); rootNode.setUnitQuantity(BigDecimal.ONE); rootNode.setUnit(rootModel.getUnit()); // productStructureService.save(rootNode); treePathMap.put(parentKey, rootNode.getId()); continue; } // å¤çåå±çº§èç¹ // æ¾å°ç¶èç¹å¨æ°æ®åºéç ID Long parentStructureId = treePathMap.get(parentKey); if (parentStructureId == null) { // 妿 Map éæ¾ä¸å°ï¼è¯´æ Excel 顺åºä¹±äºæè æ°æ®æè¯¯ throw new ServiceException("å¯¼å ¥å¤±è´¥: ç¶é¡¹[" + dto.getParentName() + "]å¿ é¡»å¨å ¶å项ä¹åå®ä¹"); } // è·åå项模åä¿¡æ¯ ProductModel childModel = findModel(dto.getChildName(), dto.getChildSpec()); // æå ¥ç»æè¡¨ ProductStructure node = new ProductStructure(); node.setBomId(bom.getId()); node.setParentId(parentStructureId); // ç¶èç¹ID node.setProductModelId(childModel.getId()); node.setUnitQuantity(dto.getUnitQty()); node.setUnit(childModel.getUnit()); // if (processMap.containsKey(dto.getProcess())) { // node.setProcessId(processMap.get(dto.getProcess())); // } // productStructureService.save(node); // æå½åå项记å½å° Map,ä½ä¸ºä»¥åæ´æ·±å±çº§çç¶é¡¹æ¥æ¾ä¾æ® // åä¸ç¶é¡¹ä¸çååå项ä¸éè¦éå¤è®°å½ treePathMap.put(childKey, node.getId()); } return R.ok("BOMå¯¼å ¥æå"); } @Override public void exportBom(HttpServletResponse response, Integer bomId) { if (bomId == null) { return; } // List<ProductStructureDto> treeData = productStructureService.listBybomId(bomId); // if (treeData == null || treeData.isEmpty()) { // return; // } // // // å°æ å½¢ç»ææå¹³å ä½¿ç¨ BFSç®æ³ 导åº,æå±çº§é¡ºåº // List<BomImportDto> exportList = new ArrayList<>(); // // // Map<ID, Node> idMap ç¨äºæ¥æ¾ç¶èç¹ // Map<Long, ProductStructureDto> idMap = new HashMap<>(); // populateMap(treeData, idMap); // // // treeData ç第ä¸ä¸ªæ¯æ ¹èç¹ // for (ProductStructureDto root : treeData) { // // æ·»å æ ¹èç¹ // BomImportDto rootRow = new BomImportDto(); // rootRow.setParentName(root.getProductName()); // rootRow.setParentSpec(root.getModel()); // rootRow.setUnitQty(root.getUnitQuantity()); // rootRow.setRemark(""); // exportList.add(rootRow); // // // BFS éå-éå // Queue<ProductStructureDto> queue = new LinkedList<>(); // if (root.getChildren() != null) { // queue.addAll(root.getChildren()); // } // // while (!queue.isEmpty()) { // ProductStructureDto child = queue.poll(); // // // æ¥æ¾ç¶èç¹ // ProductStructureDto parent = idMap.get(child.getParentId()); // if (parent == null) { // // é¤äºæå¤å±èç¹,å ¶ä»èç¹çç¶ç±»è¯å®æ¯ä¸ä¼ä¸ºç©ºç // continue; // } // // BomImportDto row = new BomImportDto(); // // ç¶ç±»ä¿¡æ¯ // row.setParentName(parent.getProductName()); // row.setParentSpec(parent.getModel()); // // åç±»ä¿¡æ¯ // row.setChildName(child.getProductName()); // row.setChildSpec(child.getModel()); // row.setUnitQty(child.getUnitQuantity()); // row.setProcess(child.getProcessName()); // // exportList.add(row); // // // å°åèç¹çåèç¹å å ¥éå-ä¸ä¸å± // if (child.getChildren() != null && !child.getChildren().isEmpty()) { // queue.addAll(child.getChildren()); // } // } // } ExcelUtil<BomImportDto> util = new ExcelUtil<>(BomImportDto.class); // util.exportExcel(response, exportList, "BOMç»æå¯¼åº"); } private ProductModel findModel(String name, String spec) { Product product = productService.getOne(new LambdaQueryWrapper<Product>() .eq(Product::getProductName, name).last("limit 1")); if (product == null) throw new ServiceException("äº§åæªç»´æ¤ï¼" + name); ProductModel model = productModelService.getOne(new LambdaQueryWrapper<ProductModel>() .eq(ProductModel::getProductId, product.getId()) .eq(ProductModel::getModel, spec).last("limit 1")); if (model == null) throw new ServiceException("è§æ ¼æªç»´æ¤ï¼" + name + "[" + spec + "]"); return model; } private void handleProcess(List<BomImportDto> list) { Set<String> processNames = list.stream() .map(BomImportDto::getProcess) .filter(StringUtils::isNotBlank) .collect(Collectors.toSet()); if (processNames.isEmpty()) { return; } // List<ProductProcess> exists = productProcessService.list( // new LambdaQueryWrapper<ProductProcess>().in(ProductProcess::getName, processNames) // ); // Set<String> existNames = exists.stream() // .map(ProductProcess::getName) // .collect(Collectors.toSet()); // // List<ProductProcess> needSave = processNames.stream() // .filter(n -> !existNames.contains(n)) // .map(n -> { // ProductProcess p = new ProductProcess(); // p.setName(n); // return p; // }) // .collect(Collectors.toList()); // // if (!needSave.isEmpty()) { // productProcessService.saveBatch(needSave); // needSave.forEach(p -> p.setNo("GX" + String.format("%08d", p.getId()))); // productProcessService.updateBatchById(needSave); // } } private String clean(String s) { if (s == null) return null; return s.replaceAll("[\\u00A0\\u3000]", "").trim(); } private void populateMap(List<ProductStructureDto> nodes, Map<Long, ProductStructureDto> map) { if (nodes == null || nodes.isEmpty()) { return; } for (ProductStructureDto node : nodes) { map.put(node.getId(), node); populateMap(node.getChildren(), map); } } } src/main/java/com/ruoyi/technology/service/impl/TechnologyBomStructureServiceImpl.java
@@ -1,20 +1,136 @@ package com.ruoyi.technology.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.technology.bean.dto.TechnologyBomStructureDto; import com.ruoyi.technology.bean.vo.TechnologyBomStructureVo; import com.ruoyi.technology.mapper.TechnologyBomStructureMapper; import com.ruoyi.technology.pojo.TechnologyBomStructure; import com.ruoyi.technology.service.TechnologyBomStructureService; import lombok.RequiredArgsConstructor; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; /** * <p> * BOM产åç»æè¡¨ æå¡å®ç°ç±» * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-04-20 10:06:17 */ import java.util.*; @Service @RequiredArgsConstructor public class TechnologyBomStructureServiceImpl extends ServiceImpl<TechnologyBomStructureMapper, TechnologyBomStructure> implements TechnologyBomStructureService { private final TechnologyBomStructureMapper technologyBomStructureMapper; /** * ä¿åBOMç»ææ ï¼å¤çæ°å¢ãæ´æ°åå é¤èç¹ã */ @Override @Transactional(rollbackFor = Exception.class) public Boolean addTechnologyBomStructure(TechnologyBomStructureDto dto) { Long bomId = dto.getBomId(); List<TechnologyBomStructureDto> flatDtoList = new ArrayList<>(); flattenTree(dto.getChildren(), flatDtoList); List<TechnologyBomStructure> dbList = this.list(new LambdaQueryWrapper<TechnologyBomStructure>() .eq(TechnologyBomStructure::getBomId, bomId)); Set<Long> frontendIds = new HashSet<>(); for (TechnologyBomStructureDto item : flatDtoList) { if (item.getId() != null) { frontendIds.add(item.getId()); } } Set<Long> deleteIds = new HashSet<>(); for (TechnologyBomStructure dbItem : dbList) { if (!frontendIds.contains(dbItem.getId())) { deleteIds.add(dbItem.getId()); } } if (!deleteIds.isEmpty()) { this.removeByIds(deleteIds); } List<TechnologyBomStructure> insertList = new ArrayList<>(); List<TechnologyBomStructure> updateList = new ArrayList<>(); Map<String, TechnologyBomStructure> tempEntityMap = new HashMap<>(); for (TechnologyBomStructureDto item : flatDtoList) { TechnologyBomStructure entity = new TechnologyBomStructure(); BeanUtils.copyProperties(item, entity); entity.setBomId(bomId); if (item.getId() == null) { entity.setParentId(null); insertList.add(entity); tempEntityMap.put(item.getTempId(), entity); } else { updateList.add(entity); } } if (!insertList.isEmpty()) { this.saveBatch(insertList); } List<TechnologyBomStructure> parentFixList = new ArrayList<>(); for (TechnologyBomStructureDto item : flatDtoList) { if (item.getId() == null && item.getParentTempId() != null) { TechnologyBomStructure child = tempEntityMap.get(item.getTempId()); if (child == null) { continue; } TechnologyBomStructure parent = tempEntityMap.get(item.getParentTempId()); Long realParentId = parent != null ? parent.getId() : Long.valueOf(item.getParentTempId()); child.setParentId(realParentId); parentFixList.add(child); } } if (!parentFixList.isEmpty()) { this.updateBatchById(parentFixList); } if (!updateList.isEmpty()) { this.updateBatchById(updateList); } return true; } /** * æ ¹æ®BOMæ¥è¯¢å¹¶ç»è£ ç»ææ ã */ @Override public List<TechnologyBomStructureVo> listByBomId(Long bomId) { List<TechnologyBomStructureVo> list = technologyBomStructureMapper.listByBomId(bomId); Map<Long, TechnologyBomStructureVo> map = new HashMap<>(); for (TechnologyBomStructureVo node : list) { node.setChildren(new ArrayList<>()); map.put(node.getId(), node); } List<TechnologyBomStructureVo> tree = new ArrayList<>(); for (TechnologyBomStructureVo node : list) { Long parentId = node.getParentId(); if (parentId == null || parentId == 0L) { tree.add(node); continue; } TechnologyBomStructureVo parent = map.get(parentId); if (parent != null) { parent.getChildren().add(node); } } return tree; } /** * å°æ å½¢ç»ææå¹³æå表ï¼ä¾¿äºç»ä¸ä¿åã */ private void flattenTree(List<TechnologyBomStructureDto> source, List<TechnologyBomStructureDto> result) { if (source == null) { return; } for (TechnologyBomStructureDto node : source) { result.add(node); flattenTree(node.getChildren(), result); } } } src/main/java/com/ruoyi/technology/service/impl/TechnologyOperationParamServiceImpl.java
@@ -1,20 +1,75 @@ package com.ruoyi.technology.service.impl; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.technology.bean.dto.TechnologyOperationParamDto; import com.ruoyi.technology.bean.vo.TechnologyOperationParamVo; import com.ruoyi.technology.mapper.TechnologyOperationMapper; import com.ruoyi.technology.mapper.TechnologyOperationParamMapper; import com.ruoyi.technology.mapper.TechnologyParamMapper; import com.ruoyi.technology.pojo.TechnologyOperationParam; import com.ruoyi.technology.pojo.TechnologyParam; import com.ruoyi.technology.service.TechnologyOperationParamService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; /** * <p> * å·¥åºåæ° æå¡å®ç°ç±» * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-04-20 10:05:35 */ import java.util.List; @Service @RequiredArgsConstructor public class TechnologyOperationParamServiceImpl extends ServiceImpl<TechnologyOperationParamMapper, TechnologyOperationParam> implements TechnologyOperationParamService { private final TechnologyOperationParamMapper technologyOperationParamMapper; private final TechnologyOperationMapper technologyOperationMapper; private final TechnologyParamMapper technologyParamMapper; /** * æå·¥åºæåæ°æ¡ä»¶æ¥è¯¢å·¥åºåæ°å表ã */ @Override public List<TechnologyOperationParamVo> listOperationParam(TechnologyOperationParamDto technologyOperationParamDto) { Long operationId = technologyOperationParamDto == null ? null : technologyOperationParamDto.getTechnologyOperationId(); Long paramId = technologyOperationParamDto == null ? null : technologyOperationParamDto.getTechnologyParamId(); return technologyOperationParamMapper.listOperationParam(operationId, paramId); } /** * ä¿åå·¥åºåæ°å¹¶æ ¡éªå·¥åºãåæ°åå¯ä¸æ§ã */ @Override public boolean saveTechnologyOperationParam(TechnologyOperationParam technologyOperationParam) { if (technologyOperationParam.getTechnologyOperationId() == null || technologyOperationMapper.selectById(technologyOperationParam.getTechnologyOperationId()) == null) { throw new ServiceException("Operation not found"); } if (technologyOperationParam.getTechnologyParamId() == null) { throw new ServiceException("Param is required"); } TechnologyParam technologyParam = technologyParamMapper.selectById(technologyOperationParam.getTechnologyParamId()); if (technologyParam == null) { throw new ServiceException("Param not found"); } boolean duplicate = technologyOperationParamMapper.selectCount(Wrappers.<TechnologyOperationParam>lambdaQuery() .eq(TechnologyOperationParam::getTechnologyOperationId, technologyOperationParam.getTechnologyOperationId()) .eq(TechnologyOperationParam::getTechnologyParamId, technologyOperationParam.getTechnologyParamId()) .ne(technologyOperationParam.getId() != null, TechnologyOperationParam::getId, technologyOperationParam.getId())) > 0; if (duplicate) { throw new ServiceException("Duplicate param in operation"); } return this.saveOrUpdate(technologyOperationParam); } /** * å é¤å个工åºåæ°ã */ @Override public String batchDelete(Long id) { TechnologyOperationParam deleteItem = technologyOperationParamMapper.selectById(id); if (deleteItem == null) { return "Delete failed"; } technologyOperationParamMapper.deleteById(id); return "Success"; } } src/main/java/com/ruoyi/technology/service/impl/TechnologyOperationServiceImpl.java
@@ -1,20 +1,89 @@ package com.ruoyi.technology.service.impl; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.framework.web.domain.R; import com.ruoyi.technology.bean.dto.TechnologyOperationDto; import com.ruoyi.technology.bean.vo.TechnologyOperationVo; import com.ruoyi.technology.mapper.TechnologyBomStructureMapper; import com.ruoyi.technology.mapper.TechnologyOperationMapper; import com.ruoyi.technology.mapper.TechnologyOperationParamMapper; import com.ruoyi.technology.mapper.TechnologyRoutingOperationMapper; import com.ruoyi.technology.pojo.TechnologyBomStructure; import com.ruoyi.technology.pojo.TechnologyOperation; import com.ruoyi.technology.pojo.TechnologyOperationParam; import com.ruoyi.technology.pojo.TechnologyRoutingOperation; import com.ruoyi.technology.service.TechnologyOperationService; import lombok.RequiredArgsConstructor; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; /** * <p> * å·¥åºè¡¨ æå¡å®ç°ç±» * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-04-20 10:33:03 */ import java.util.List; import java.util.stream.Collectors; @Service @RequiredArgsConstructor public class TechnologyOperationServiceImpl extends ServiceImpl<TechnologyOperationMapper, TechnologyOperation> implements TechnologyOperationService { private final TechnologyOperationMapper technologyOperationMapper; private final TechnologyRoutingOperationMapper technologyRoutingOperationMapper; private final TechnologyBomStructureMapper technologyBomStructureMapper; private final TechnologyOperationParamMapper technologyOperationParamMapper; /** * å页æ¥è¯¢å·¥åºå表ã */ @Override public IPage<TechnologyOperationVo> listPage(Page<TechnologyOperationDto> page, TechnologyOperationDto technologyOperationDto) { return technologyOperationMapper.listPage(page, technologyOperationDto); } /** * æ°å¢å·¥åºå¹¶è¡¥é½å·¥åºç¼ç ã */ @Override public R add(TechnologyOperationDto technologyOperationDto) { TechnologyOperation technologyOperation = new TechnologyOperation(); BeanUtils.copyProperties(technologyOperationDto, technologyOperation); boolean saved = technologyOperationMapper.insert(technologyOperation) > 0; if (saved && ObjectUtils.isNull(technologyOperationDto.getNo())) { technologyOperation.setNo("GX" + String.format("%08d", technologyOperation.getId())); technologyOperationMapper.updateById(technologyOperation); } return R.ok(); } /** * å é¤å·¥åºåæ ¡éªæ¯å¦å·²è¢«BOMç»ææå·¥èºè·¯çº¿å¼ç¨ã */ @Override public String batchDelete(List<Long> ids) { List<TechnologyRoutingOperation> routingOperations = technologyRoutingOperationMapper.selectList( Wrappers.<TechnologyRoutingOperation>lambdaQuery().in(TechnologyRoutingOperation::getTechnologyOperationId, ids)); List<TechnologyBomStructure> bomStructures = technologyBomStructureMapper.selectList( Wrappers.<TechnologyBomStructure>lambdaQuery().in(TechnologyBomStructure::getOperationId, ids)); if (!CollectionUtils.isEmpty(routingOperations) || !CollectionUtils.isEmpty(bomStructures)) { throw new RuntimeException("Operation is referenced and cannot be deleted"); } technologyOperationParamMapper.delete(Wrappers.<TechnologyOperationParam>lambdaQuery() .in(TechnologyOperationParam::getTechnologyOperationId, ids)); technologyOperationMapper.deleteBatchIds(ids); return null; } /** * æ¥è¯¢å ¨é¨å·¥åºå¹¶è½¬æ¢ä¸ºè¿å对象ã */ @Override public List<TechnologyOperationVo> listVo() { return this.list().stream().map(item -> { TechnologyOperationVo vo = new TechnologyOperationVo(); BeanUtils.copyProperties(item, vo); return vo; }).collect(Collectors.toList()); } } src/main/java/com/ruoyi/technology/service/impl/TechnologyParamServiceImpl.java
@@ -1,20 +1,170 @@ package com.ruoyi.technology.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.technology.bean.dto.TechnologyParamDto; import com.ruoyi.technology.bean.vo.TechnologyParamVo; import com.ruoyi.technology.mapper.TechnologyParamMapper; import com.ruoyi.technology.pojo.TechnologyParam; import com.ruoyi.technology.service.TechnologyParamService; import lombok.RequiredArgsConstructor; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; /** * <p> * åºç¡åæ°è¡¨ æå¡å®ç°ç±» * </p> * * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå ¬å¸ * @since 2026-04-20 09:45:20 */ import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @Service @RequiredArgsConstructor public class TechnologyParamServiceImpl extends ServiceImpl<TechnologyParamMapper, TechnologyParam> implements TechnologyParamService { private static final List<Integer> VALID_PARAM_TYPES = Arrays.asList(1, 2, 3, 4); private static final String PARAM_CODE_PREFIX = "PARAM_"; private static final Byte DATE_PARAM_TYPE = (byte) 4; /** * å页æ¥è¯¢åºç¡åæ°å¹¶æ ¼å¼åæ¥æç±»åå±ç¤ºã */ @Override public IPage<TechnologyParamVo> baseParamList(Page<TechnologyParamDto> page, TechnologyParamDto baseParam) { LambdaQueryWrapper<TechnologyParam> queryWrapper = new LambdaQueryWrapper<>(); if (baseParam != null && StringUtils.isNotEmpty(baseParam.getParamName())) { queryWrapper.like(TechnologyParam::getParamName, baseParam.getParamName()); } queryWrapper.orderByDesc(TechnologyParam::getId); Page<TechnologyParam> entityPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal()); Page<TechnologyParam> paramPage = page(entityPage, queryWrapper); Page<TechnologyParamVo> resultPage = new Page<>(paramPage.getCurrent(), paramPage.getSize(), paramPage.getTotal()); List<TechnologyParamVo> records = new ArrayList<>(paramPage.getRecords().size()); for (TechnologyParam item : paramPage.getRecords()) { TechnologyParamVo vo = new TechnologyParamVo(); BeanUtils.copyProperties(item, vo); if (DATE_PARAM_TYPE.equals(item.getParamType()) && StringUtils.isNotEmpty(item.getParamFormat())) { vo.setParamFormat(toDisplayDatePattern(item.getParamFormat())); } records.add(vo); } resultPage.setRecords(records); return resultPage; } /** * æ°å¢åºç¡åæ°å¹¶çæå¯ä¸åæ°ç¼ç ã */ @Override public int addBaseParam(TechnologyParamDto baseParam) { if (baseParam == null) { throw new RuntimeException("æ°å¢åæ°ä¸è½ä¸ºç©º"); } checkBaseParam(baseParam); baseParam.setParamCode(generateParamCode()); baseParam.setCreateUser(SecurityUtils.getUsername()); baseParam.setCreateTime(LocalDateTime.now()); if (baseParam.getIsRequired() == null) { baseParam.setIsRequired((byte) 0); } return baseMapper.insert(baseParam); } /** * ä¿®æ¹åºç¡åæ°å¹¶ä¿çåæåæ°ç¼ç ã */ @Override public int updateBaseParam(TechnologyParamDto baseParam) { if (baseParam == null || baseParam.getId() == null) { throw new RuntimeException("ä¿®æ¹åæ°IDä¸è½ä¸ºç©º"); } checkBaseParam(baseParam); TechnologyParam current = baseMapper.selectById(baseParam.getId()); if (current == null) { throw new RuntimeException("åæ°ä¸åå¨"); } if (StringUtils.isEmpty(baseParam.getParamCode())) { baseParam.setParamCode(current.getParamCode()); } baseParam.setUpdateUser(SecurityUtils.getUsername()); baseParam.setUpdateTime(LocalDateTime.now()); return baseMapper.updateById(baseParam); } /** * åæ°å®ä¹åæ³æ ¡éªã */ private void checkBaseParam(TechnologyParamDto baseParam) { if (StringUtils.isEmpty(baseParam.getParamName())) { throw new RuntimeException("åæ°åç§°ä¸è½ä¸ºç©º"); } if (baseParam.getParamType() == null || !VALID_PARAM_TYPES.contains(Integer.valueOf(baseParam.getParamType()))) { throw new RuntimeException("éæ³åæ°ç±»å"); } if (DATE_PARAM_TYPE.equals(baseParam.getParamType())) { if (StringUtils.isEmpty(baseParam.getParamFormat())) { throw new RuntimeException("æ¥æç±»åå¿ é¡»é ç½®åæ°æ ¼å¼(å¦: yyyy-MM-dd)"); } try { String standardPattern = normalizeDatePattern(baseParam.getParamFormat()); DateTimeFormatter.ofPattern(standardPattern); baseParam.setParamFormat(standardPattern); } catch (Exception e) { throw new RuntimeException("æ¥ææ ¼å¼éæ³: " + baseParam.getParamFormat()); } } else { baseParam.setParamFormat(baseParam.getParamFormat()); } } /** * çæåæ°å¯ä¸ç¼ç ï¼ä¾å·¥èºåæ°åç产订åå¿«ç §å¼ç¨ã */ private String generateParamCode() { LambdaQueryWrapper<TechnologyParam> wrapper = new LambdaQueryWrapper<>(); wrapper.select(TechnologyParam::getParamCode) .likeRight(TechnologyParam::getParamCode, PARAM_CODE_PREFIX) .orderByDesc(TechnologyParam::getParamCode) .last("limit 1"); TechnologyParam last = baseMapper.selectOne(wrapper); int nextNum = 1; if (last != null && StringUtils.isNotEmpty(last.getParamCode())) { try { String numStr = last.getParamCode().replace(PARAM_CODE_PREFIX, ""); nextNum = Integer.parseInt(numStr) + 1; } catch (Exception e) { log.error("è§£æ paramCode å¼å¸¸", e); } } return PARAM_CODE_PREFIX + String.format("%04d", nextNum); } private String normalizeDatePattern(String pattern) { return pattern.trim() .replace('Y', 'y') .replace('D', 'd') .replace('S', 's'); } private String toDisplayDatePattern(String pattern) { return normalizeDatePattern(pattern); } /** * æ¹éå é¤åºç¡åæ°ã */ @Override public int deleteBaseParamByIds(Long[] ids) { if (ids == null || ids.length == 0) { throw new RuntimeException("å é¤IDä¸è½ä¸ºç©º"); } return baseMapper.deleteBatchIds(Arrays.asList(ids)); } } src/main/resources/mapper/basic/CustomerPrivatePoolMapper.xml
@@ -41,8 +41,8 @@ <if test="c.customerType != null"> and c.customer_type = #{c.customerType} </if> <if test="c.boundId != null"> and cpp.boundId = #{c.boundId} <if test="c.bound_id != null"> and cpp.bound_id = #{c.boundId} </if> </where> src/main/resources/mapper/technology/TechnologyBomMapper.xml
@@ -16,4 +16,27 @@ <result column="dept_id" property="deptId" /> </resultMap> <select id="listPage" resultType="com.ruoyi.technology.bean.vo.TechnologyBomVo"> select tb.*, pm.model as productModelName, p.product_name as productName from technology_bom tb left join product_model pm on tb.product_model_id = pm.id left join product p on pm.product_id = p.id <where> <if test="c.productModelName != null and c.productModelName != ''"> and pm.model like concat('%', #{c.productModelName}, '%') </if> <if test="c.productName != null and c.productName != ''"> and p.product_name like concat('%', #{c.productName}, '%') </if> <if test="c.bomNo != null and c.bomNo != ''"> and tb.bom_no like concat('%', #{c.bomNo}, '%') </if> <if test="c.version != null and c.version != ''"> and tb.version = #{c.version} </if> </where> order by tb.id desc </select> </mapper> src/main/resources/mapper/technology/TechnologyBomStructureMapper.xml
@@ -16,4 +16,17 @@ <result column="dept_id" property="deptId" /> </resultMap> <select id="listByBomId" resultType="com.ruoyi.technology.bean.vo.TechnologyBomStructureVo"> select tbs.*, p.product_name as productName, pm.product_id as productId, pm.model, top1.name as operationName from technology_bom_structure tbs left join product_model pm on tbs.product_model_id = pm.id left join product p on pm.product_id = p.id left join technology_operation top1 on tbs.operation_id = top1.id where tbs.bom_id = #{bomId} order by tbs.id </select> </mapper> src/main/resources/mapper/technology/TechnologyOperationMapper.xml
@@ -18,4 +18,20 @@ <result column="dept_id" property="deptId" /> </resultMap> <select id="listPage" resultType="com.ruoyi.technology.bean.vo.TechnologyOperationVo"> select * from technology_operation t <where> <if test="c.name != null and c.name != ''"> and t.name like concat('%', #{c.name}, '%') </if> <if test="c.no != null and c.no != ''"> and t.no like concat('%', #{c.no}, '%') </if> <if test="c.type != null"> and t.type = #{c.type} </if> </where> order by t.id asc </select> </mapper> src/main/resources/mapper/technology/TechnologyOperationParamMapper.xml
@@ -10,4 +10,24 @@ <result column="standard_value" property="standardValue" /> </resultMap> <select id="listOperationParam" resultType="com.ruoyi.technology.bean.vo.TechnologyOperationParamVo"> select top1.*, tp.param_code as paramCode, tp.param_name as paramName, tp.param_type as paramType, tp.param_format as paramFormat, tp.unit, tp.is_required as isRequired from technology_operation_param top1 left join technology_param tp on top1.technology_param_id = tp.id <where> <if test="technologyOperationId != null"> and top1.technology_operation_id = #{technologyOperationId} </if> <if test="paramId != null"> and top1.technology_param_id = #{paramId} </if> </where> order by top1.id asc </select> </mapper> src/main/resources/mapper/technology/TechnologyRoutingMapper.xml
@@ -15,4 +15,9 @@ <result column="dept_id" property="deptId" /> </resultMap> <update id="updateProductModelByBomId"> update technology_routing set product_model_id = #{productModelId} where bom_id = #{bomId} </update> </mapper>