From 7e8edd4b59fb22146b90d01ca38f75148f3fd774 Mon Sep 17 00:00:00 2001
From: liding <756868258@qq.com>
Date: 星期一, 20 四月 2026 17:57:18 +0800
Subject: [PATCH] feat(bom): 添加BOM管理功能模块,工序 管理,基础 - 新增CustomerPrivatePoolMapper.xml实现客户私池映射 - 添加SysLoginController支持登录验证和用户信息获取 - 创建TechnologyBomController提供BOM的增删改查接口 - 定义TechnologyBomDto数据传输对象 - 实现TechnologyBomMapper和相关XML映射文件 - 开发TechnologyBomService业务逻辑层 - 添加TechnologyBomStructure结构管理功能 - 集成Excel导入导出BOM数据功能 - 实现BOM结构树形展示和维护功能

---
 src/main/java/com/ruoyi/framework/config/FilterConfig.java                               |   13 
 src/main/resources/mapper/technology/TechnologyOperationParamMapper.xml                  |   20 
 src/main/java/com/ruoyi/technology/controller/TechnologyParamController.java             |   54 +
 src/main/resources/mapper/technology/TechnologyRoutingMapper.xml                         |    5 
 src/main/java/com/ruoyi/project/system/controller/SysLoginController.java                |   29 
 src/main/resources/mapper/basic/CustomerPrivatePoolMapper.xml                            |    4 
 src/main/java/com/ruoyi/technology/bean/dto/TechnologyOperationDto.java                  |   12 
 src/main/java/com/ruoyi/technology/bean/vo/TechnologyParamVo.java                        |    8 
 src/main/java/com/ruoyi/technology/mapper/TechnologyBomStructureMapper.java              |    5 
 src/main/java/com/ruoyi/technology/service/TechnologyOperationParamService.java          |   17 
 src/main/java/com/ruoyi/technology/service/impl/TechnologyParamServiceImpl.java          |  166 +++++
 src/main/java/com/ruoyi/technology/bean/dto/TechnologyBomDto.java                        |   17 
 src/main/java/com/ruoyi/technology/bean/vo/TechnologyBomStructureVo.java                 |   27 +
 src/main/java/com/ruoyi/technology/service/impl/TechnologyBomStructureServiceImpl.java   |  132 ++++
 src/main/java/com/ruoyi/technology/service/impl/TechnologyOperationServiceImpl.java      |   85 ++
 src/main/java/com/ruoyi/technology/controller/TechnologyOperationParamController.java    |   46 +
 src/main/java/com/ruoyi/technology/bean/dto/TechnologyBomStructureDto.java               |   31 +
 src/main/java/com/ruoyi/technology/bean/dto/TechnologyRoutingOperationDto.java           |    2 
 src/main/java/com/ruoyi/technology/bean/vo/TechnologyOperationParamVo.java               |   29 +
 src/main/resources/mapper/technology/TechnologyOperationMapper.xml                       |   16 
 src/main/java/com/ruoyi/technology/mapper/TechnologyBomMapper.java                       |    6 
 src/main/java/com/ruoyi/technology/service/TechnologyBomService.java                     |   30 
 src/main/java/com/ruoyi/technology/controller/TechnologyOperationController.java         |   61 +
 src/main/java/com/ruoyi/technology/bean/dto/TechnologyOperationParamDto.java             |   29 +
 src/main/java/com/ruoyi/technology/service/TechnologyParamService.java                   |   11 
 src/main/java/com/ruoyi/technology/bean/dto/TechnologyRoutingDto.java                    |    2 
 src/main/resources/mapper/technology/TechnologyBomMapper.xml                             |   23 
 src/main/java/com/ruoyi/technology/bean/vo/TechnologyOperationVo.java                    |   12 
 src/main/java/com/ruoyi/technology/bean/vo/TechnologyRoutingOperationVo.java             |    2 
 src/main/java/com/ruoyi/technology/mapper/TechnologyOperationMapper.java                 |    6 
 src/main/java/com/ruoyi/technology/bean/vo/TechnologyBomVo.java                          |   15 
 src/main/java/com/ruoyi/technology/service/TechnologyOperationService.java               |   22 
 src/main/java/com/ruoyi/technology/controller/TechnologyBomStructureController.java      |   35 
 src/main/java/com/ruoyi/technology/mapper/TechnologyOperationParamMapper.java            |    6 
 src/main/java/com/ruoyi/technology/service/impl/TechnologyBomServiceImpl.java            |  383 +++++++++++++
 src/main/java/com/ruoyi/technology/controller/TechnologyBomController.java               |   92 +++
 src/main/java/com/ruoyi/technology/service/TechnologyBomStructureService.java            |   15 
 src/main/java/com/ruoyi/technology/mapper/TechnologyRoutingMapper.java                   |    2 
 src/main/java/com/ruoyi/technology/service/impl/TechnologyOperationParamServiceImpl.java |   71 ++
 src/main/java/com/ruoyi/technology/bean/dto/TechnologyParamDto.java                      |   10 
 src/main/resources/mapper/technology/TechnologyBomStructureMapper.xml                    |   13 
 src/main/java/com/ruoyi/technology/bean/vo/TechnologyRoutingVo.java                      |    2 
 42 files changed, 1,423 insertions(+), 143 deletions(-)

diff --git a/src/main/java/com/ruoyi/framework/config/FilterConfig.java b/src/main/java/com/ruoyi/framework/config/FilterConfig.java
index 610807a..66802f8 100644
--- a/src/main/java/com/ruoyi/framework/config/FilterConfig.java
+++ b/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閰嶇疆
diff --git a/src/main/java/com/ruoyi/project/system/controller/SysLoginController.java b/src/main/java/com/ruoyi/project/system/controller/SysLoginController.java
index b165f3e..d998f45 100644
--- a/src/main/java/com/ruoyi/project/system/controller/SysLoginController.java
+++ b/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;
 
 /**
  * 鐧诲綍楠岃瘉
diff --git a/src/main/java/com/ruoyi/technology/bean/dto/TechnologyBomDto.java b/src/main/java/com/ruoyi/technology/bean/dto/TechnologyBomDto.java
new file mode 100644
index 0000000..1488a3d
--- /dev/null
+++ b/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;
+}
diff --git a/src/main/java/com/ruoyi/technology/bean/dto/TechnologyBomStructureDto.java b/src/main/java/com/ruoyi/technology/bean/dto/TechnologyBomStructureDto.java
new file mode 100644
index 0000000..cb2228a
--- /dev/null
+++ b/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;
+}
diff --git a/src/main/java/com/ruoyi/technology/bean/dto/TechnologyOperationDto.java b/src/main/java/com/ruoyi/technology/bean/dto/TechnologyOperationDto.java
new file mode 100644
index 0000000..21305a4
--- /dev/null
+++ b/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 {
+}
diff --git a/src/main/java/com/ruoyi/technology/bean/dto/TechnologyOperationParamDto.java b/src/main/java/com/ruoyi/technology/bean/dto/TechnologyOperationParamDto.java
new file mode 100644
index 0000000..d28ab87
--- /dev/null
+++ b/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;
+}
diff --git a/src/main/java/com/ruoyi/technology/bean/dto/TechnologyParamDto.java b/src/main/java/com/ruoyi/technology/bean/dto/TechnologyParamDto.java
new file mode 100644
index 0000000..2a45544
--- /dev/null
+++ b/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 {
+}
diff --git a/src/main/java/com/ruoyi/technology/bean/dto/TechnologyRoutingDto.java b/src/main/java/com/ruoyi/technology/bean/dto/TechnologyRoutingDto.java
index 35499fd..d960f31 100644
--- a/src/main/java/com/ruoyi/technology/bean/dto/TechnologyRoutingDto.java
+++ b/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 {
diff --git a/src/main/java/com/ruoyi/technology/bean/dto/TechnologyRoutingOperationDto.java b/src/main/java/com/ruoyi/technology/bean/dto/TechnologyRoutingOperationDto.java
index af86ada..c310931 100644
--- a/src/main/java/com/ruoyi/technology/bean/dto/TechnologyRoutingOperationDto.java
+++ b/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 {
diff --git a/src/main/java/com/ruoyi/technology/bean/vo/TechnologyBomStructureVo.java b/src/main/java/com/ruoyi/technology/bean/vo/TechnologyBomStructureVo.java
new file mode 100644
index 0000000..fc6ecbb
--- /dev/null
+++ b/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;
+}
diff --git a/src/main/java/com/ruoyi/technology/bean/vo/TechnologyBomVo.java b/src/main/java/com/ruoyi/technology/bean/vo/TechnologyBomVo.java
new file mode 100644
index 0000000..019bc22
--- /dev/null
+++ b/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;
+}
diff --git a/src/main/java/com/ruoyi/technology/bean/vo/TechnologyOperationParamVo.java b/src/main/java/com/ruoyi/technology/bean/vo/TechnologyOperationParamVo.java
new file mode 100644
index 0000000..2345455
--- /dev/null
+++ b/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;
+}
diff --git a/src/main/java/com/ruoyi/technology/bean/vo/TechnologyOperationVo.java b/src/main/java/com/ruoyi/technology/bean/vo/TechnologyOperationVo.java
new file mode 100644
index 0000000..68a1fab
--- /dev/null
+++ b/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 {
+}
diff --git a/src/main/java/com/ruoyi/technology/bean/vo/TechnologyParamVo.java b/src/main/java/com/ruoyi/technology/bean/vo/TechnologyParamVo.java
new file mode 100644
index 0000000..21e5299
--- /dev/null
+++ b/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 {
+}
diff --git a/src/main/java/com/ruoyi/technology/bean/vo/TechnologyRoutingOperationVo.java b/src/main/java/com/ruoyi/technology/bean/vo/TechnologyRoutingOperationVo.java
index 7090be1..a5d8ef2 100644
--- a/src/main/java/com/ruoyi/technology/bean/vo/TechnologyRoutingOperationVo.java
+++ b/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 {
diff --git a/src/main/java/com/ruoyi/technology/bean/vo/TechnologyRoutingVo.java b/src/main/java/com/ruoyi/technology/bean/vo/TechnologyRoutingVo.java
index b0c1016..34a007d 100644
--- a/src/main/java/com/ruoyi/technology/bean/vo/TechnologyRoutingVo.java
+++ b/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 {
diff --git a/src/main/java/com/ruoyi/technology/controller/TechnologyBomController.java b/src/main/java/com/ruoyi/technology/controller/TechnologyBomController.java
index e7a07e2..10b8b7d 100644
--- a/src/main/java/com/ruoyi/technology/controller/TechnologyBomController.java
+++ b/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瀵煎叆妯℃澘");
+    }
 }
diff --git a/src/main/java/com/ruoyi/technology/controller/TechnologyBomStructureController.java b/src/main/java/com/ruoyi/technology/controller/TechnologyBomStructureController.java
index 9ec14d2..3655e0e 100644
--- a/src/main/java/com/ruoyi/technology/controller/TechnologyBomStructureController.java
+++ b/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("鏂板鎴栦慨鏀笲OM缁撴瀯")
+    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));
+    }
 }
diff --git a/src/main/java/com/ruoyi/technology/controller/TechnologyOperationController.java b/src/main/java/com/ruoyi/technology/controller/TechnologyOperationController.java
index aea5925..367366d 100644
--- a/src/main/java/com/ruoyi/technology/controller/TechnologyOperationController.java
+++ b/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());
+    }
 }
diff --git a/src/main/java/com/ruoyi/technology/controller/TechnologyOperationParamController.java b/src/main/java/com/ruoyi/technology/controller/TechnologyOperationParamController.java
index 44df244..e3552b5 100644
--- a/src/main/java/com/ruoyi/technology/controller/TechnologyOperationParamController.java
+++ b/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));
+    }
 }
diff --git a/src/main/java/com/ruoyi/technology/controller/TechnologyParamController.java b/src/main/java/com/ruoyi/technology/controller/TechnologyParamController.java
index abccfaa..d16d514 100644
--- a/src/main/java/com/ruoyi/technology/controller/TechnologyParamController.java
+++ b/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));
+    }
 }
diff --git a/src/main/java/com/ruoyi/technology/mapper/TechnologyBomMapper.java b/src/main/java/com/ruoyi/technology/mapper/TechnologyBomMapper.java
index 6fe56c3..7ae5509 100644
--- a/src/main/java/com/ruoyi/technology/mapper/TechnologyBomMapper.java
+++ b/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);
 }
diff --git a/src/main/java/com/ruoyi/technology/mapper/TechnologyBomStructureMapper.java b/src/main/java/com/ruoyi/technology/mapper/TechnologyBomStructureMapper.java
index a02706e..29f6cc8 100644
--- a/src/main/java/com/ruoyi/technology/mapper/TechnologyBomStructureMapper.java
+++ b/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);
 }
diff --git a/src/main/java/com/ruoyi/technology/mapper/TechnologyOperationMapper.java b/src/main/java/com/ruoyi/technology/mapper/TechnologyOperationMapper.java
index c493d07..89596b4 100644
--- a/src/main/java/com/ruoyi/technology/mapper/TechnologyOperationMapper.java
+++ b/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);
 }
diff --git a/src/main/java/com/ruoyi/technology/mapper/TechnologyOperationParamMapper.java b/src/main/java/com/ruoyi/technology/mapper/TechnologyOperationParamMapper.java
index 6fab01a..040c52a 100644
--- a/src/main/java/com/ruoyi/technology/mapper/TechnologyOperationParamMapper.java
+++ b/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);
 }
diff --git a/src/main/java/com/ruoyi/technology/mapper/TechnologyRoutingMapper.java b/src/main/java/com/ruoyi/technology/mapper/TechnologyRoutingMapper.java
index 4933162..e688c4f 100644
--- a/src/main/java/com/ruoyi/technology/mapper/TechnologyRoutingMapper.java
+++ b/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);
 }
diff --git a/src/main/java/com/ruoyi/technology/service/TechnologyBomService.java b/src/main/java/com/ruoyi/technology/service/TechnologyBomService.java
index a77caf1..cf4a5af 100644
--- a/src/main/java/com/ruoyi/technology/service/TechnologyBomService.java
+++ b/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);
 }
diff --git a/src/main/java/com/ruoyi/technology/service/TechnologyBomStructureService.java b/src/main/java/com/ruoyi/technology/service/TechnologyBomStructureService.java
index 2ffb69d..47ea67d 100644
--- a/src/main/java/com/ruoyi/technology/service/TechnologyBomStructureService.java
+++ b/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);
 }
diff --git a/src/main/java/com/ruoyi/technology/service/TechnologyOperationParamService.java b/src/main/java/com/ruoyi/technology/service/TechnologyOperationParamService.java
index e93951f..3f217ab 100644
--- a/src/main/java/com/ruoyi/technology/service/TechnologyOperationParamService.java
+++ b/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);
 }
diff --git a/src/main/java/com/ruoyi/technology/service/TechnologyOperationService.java b/src/main/java/com/ruoyi/technology/service/TechnologyOperationService.java
index e6790f1..42ba667 100644
--- a/src/main/java/com/ruoyi/technology/service/TechnologyOperationService.java
+++ b/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();
 }
diff --git a/src/main/java/com/ruoyi/technology/service/TechnologyParamService.java b/src/main/java/com/ruoyi/technology/service/TechnologyParamService.java
index ee5d503..958dab5 100644
--- a/src/main/java/com/ruoyi/technology/service/TechnologyParamService.java
+++ b/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);
 }
diff --git a/src/main/java/com/ruoyi/technology/service/impl/TechnologyBomServiceImpl.java b/src/main/java/com/ruoyi/technology/service/impl/TechnologyBomServiceImpl.java
index 3c6cfca..536df14 100644
--- a/src/main/java/com/ruoyi/technology/service/impl/TechnologyBomServiceImpl.java
+++ b/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");
+        }
+    }
+
+    /**
+     * 鍒濆鍖朆OM鏍硅妭鐐圭粨鏋勩��
+     */
+    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瑙f瀽澶辫触");
+        }
+
+        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); // 鐖惰妭鐐笽D
+            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);
+        }
+    }
 }
diff --git a/src/main/java/com/ruoyi/technology/service/impl/TechnologyBomStructureServiceImpl.java b/src/main/java/com/ruoyi/technology/service/impl/TechnologyBomStructureServiceImpl.java
index 8fe52f2..5cb898a 100644
--- a/src/main/java/com/ruoyi/technology/service/impl/TechnologyBomStructureServiceImpl.java
+++ b/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);
+        }
+    }
 }
diff --git a/src/main/java/com/ruoyi/technology/service/impl/TechnologyOperationParamServiceImpl.java b/src/main/java/com/ruoyi/technology/service/impl/TechnologyOperationParamServiceImpl.java
index 122f5cb..107fa22 100644
--- a/src/main/java/com/ruoyi/technology/service/impl/TechnologyOperationParamServiceImpl.java
+++ b/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";
+    }
 }
diff --git a/src/main/java/com/ruoyi/technology/service/impl/TechnologyOperationServiceImpl.java b/src/main/java/com/ruoyi/technology/service/impl/TechnologyOperationServiceImpl.java
index 5294fb8..da9ed8b 100644
--- a/src/main/java/com/ruoyi/technology/service/impl/TechnologyOperationServiceImpl.java
+++ b/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();
+    }
+
+    /**
+     * 鍒犻櫎宸ュ簭鍓嶆牎楠屾槸鍚﹀凡琚獴OM缁撴瀯鎴栧伐鑹鸿矾绾垮紩鐢ㄣ��
+     */
+    @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());
+    }
 }
diff --git a/src/main/java/com/ruoyi/technology/service/impl/TechnologyParamServiceImpl.java b/src/main/java/com/ruoyi/technology/service/impl/TechnologyParamServiceImpl.java
index 1afea09..a3e8f5e 100644
--- a/src/main/java/com/ruoyi/technology/service/impl/TechnologyParamServiceImpl.java
+++ b/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("瑙f瀽 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));
+    }
 }
diff --git a/src/main/resources/mapper/basic/CustomerPrivatePoolMapper.xml b/src/main/resources/mapper/basic/CustomerPrivatePoolMapper.xml
index c35006c..ded48d8 100644
--- a/src/main/resources/mapper/basic/CustomerPrivatePoolMapper.xml
+++ b/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>
diff --git a/src/main/resources/mapper/technology/TechnologyBomMapper.xml b/src/main/resources/mapper/technology/TechnologyBomMapper.xml
index 619a04a..267b1f5 100644
--- a/src/main/resources/mapper/technology/TechnologyBomMapper.xml
+++ b/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>
diff --git a/src/main/resources/mapper/technology/TechnologyBomStructureMapper.xml b/src/main/resources/mapper/technology/TechnologyBomStructureMapper.xml
index b06ad50..2030715 100644
--- a/src/main/resources/mapper/technology/TechnologyBomStructureMapper.xml
+++ b/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>
diff --git a/src/main/resources/mapper/technology/TechnologyOperationMapper.xml b/src/main/resources/mapper/technology/TechnologyOperationMapper.xml
index 2039849..f6adc74 100644
--- a/src/main/resources/mapper/technology/TechnologyOperationMapper.xml
+++ b/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>
diff --git a/src/main/resources/mapper/technology/TechnologyOperationParamMapper.xml b/src/main/resources/mapper/technology/TechnologyOperationParamMapper.xml
index 149f9d8..e1ccb2a 100644
--- a/src/main/resources/mapper/technology/TechnologyOperationParamMapper.xml
+++ b/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>
diff --git a/src/main/resources/mapper/technology/TechnologyRoutingMapper.xml b/src/main/resources/mapper/technology/TechnologyRoutingMapper.xml
index 4578210..fcf2890 100644
--- a/src/main/resources/mapper/technology/TechnologyRoutingMapper.xml
+++ b/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>

--
Gitblit v1.9.3