From 906bc8adc1e01942ebf38340495d91ada34f2a13 Mon Sep 17 00:00:00 2001 From: "zangch@mesnac.com" Date: Wed, 14 Jan 2026 17:39:28 +0800 Subject: [PATCH] =?UTF-8?q?feat(qms):=20=E6=B7=BB=E5=8A=A0=E8=B4=A8?= =?UTF-8?q?=E6=A3=80=E6=A8=A1=E5=9D=97=E4=B8=8A=E4=BD=8D=E6=9C=BA=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E5=92=8C=E6=A8=A1=E6=9D=BF=E5=8C=B9=E9=85=8D=E7=AD=96?= =?UTF-8?q?=E7=95=A5=EF=BC=8CRemoteCodeRuleService=E6=B7=BB=E5=8A=A0select?= =?UTF-8?q?CodeRuleCodeWithTenant?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增质检模块架构说明文档,包括质检模板匹配策略 - 完善检测类型字典和通用模板规则定义 - 扩展编码规则服务支持租户传递功能 - 实现上位机接口服务层和控制层 - 添加质检任务生成功能和工位名称转编码逻辑 - 实现8级降级匹配策略用于质检模板匹配 - 添加事务管理和异常处理机制 --- .../system/api/RemoteCodeRuleService.java | 10 + ruoyi-modules/hwmom-qms/qc通用模块.md | 58 +++- .../qms/controller/QcHMIController.java | 60 ++++ .../qms/domain/dto/QcInspectionMainTask.java | 61 ++++ .../dromara/qms/service/IQcHMIService.java | 29 ++ .../qms/service/impl/QcHMIServiceImpl.java | 277 ++++++++++++++++++ .../dubbo/RemoteCodeRuleServiceImpl.java | 30 ++ 7 files changed, 524 insertions(+), 1 deletion(-) create mode 100644 ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/controller/QcHMIController.java create mode 100644 ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/dto/QcInspectionMainTask.java create mode 100644 ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/service/IQcHMIService.java create mode 100644 ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/service/impl/QcHMIServiceImpl.java diff --git a/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteCodeRuleService.java b/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteCodeRuleService.java index cbab9e4f..f2ab485b 100644 --- a/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteCodeRuleService.java +++ b/ruoyi-api/ruoyi-api-system/src/main/java/org/dromara/system/api/RemoteCodeRuleService.java @@ -14,4 +14,14 @@ public interface RemoteCodeRuleService { */ String selectCodeRuleCode(String codeRuleCode); + /** + * 通过编码规则编码获取编码(支持Dubbo租户传递) + *

+ * 适用于上位机等无登录场景的跨服务调用 + * + * @param codeRuleCode 编码规则编码 + * @return currentCode + */ + String selectCodeRuleCodeWithTenant(String codeRuleCode); + } diff --git a/ruoyi-modules/hwmom-qms/qc通用模块.md b/ruoyi-modules/hwmom-qms/qc通用模块.md index 472496c5..7b29b516 100644 --- a/ruoyi-modules/hwmom-qms/qc通用模块.md +++ b/ruoyi-modules/hwmom-qms/qc通用模块.md @@ -53,4 +53,60 @@ qc_inspection_main (检验单主表) → [产生不合格] → qc_unqualified_re 1. **模板驱动**: 检验单关联模板,模板包含多个检测项定义 2. **级联继承**: 检验结果从检测项定义继承标准值、上下限等规格参数 3. **主子分离**: 主表记录总体信息(单号、物料、数量),子表记录明细(每个检测项的检测结果) -4. **不合格评审**: 当检验结果不合格时,触发评审流程,生成评审主表及记录子表 \ No newline at end of file +4. **不合格评审**: 当检验结果不合格时,触发评审流程,生成评审主表及记录子表 + +--- + +## 质检模板匹配策略(核心业务规则) + +**生成质检任务时,按以下4级降级优先级自动匹配模板:** + +``` +┌─────────────────────────────────────────────────────────────┐ +│ 质检模板匹配策略 │ +├─────────────────────────────────────────────────────────────┤ +│ │ +│ 第1级:物料 + 工位 + 工序 + 检测类型(精确匹配) │ +│ ↓ 未找到 │ +│ 第2级:物料 + 工位 + 检测类型 │ +│ ↓ 未找到 │ +│ 第3级:物料 + 检测类型 │ +│ ↓ 未找到 │ +│ 第4级:通用模板(仅检测类型 + isDefault=1) │ +│ ↓ 未找到 → 抛出异常:"无可用检测模板" │ +│ │ +└─────────────────────────────────────────────────────────────┘ +``` + +### 匹配条件说明 + +| 优先级 | 匹配条件 | 说明 | 业务场景 | +|-------|---------|------|---------| +| 1 | 物料 + 工位 + 工序 + 检测类型 | 最精确匹配 | 某物料在特定工位/工序有特殊质检要求 | +| 2 | 物料 + 工位 + 检测类型 | 特定工位(不限工序) | 某物料在特定工位的质检要求统一 | +| 3 | 物料 + 检测类型 | 特定物料(不限工位/工序) | 某物料的质检要求在任何工位/工序都一致 | +| 4 | 通用模板(仅检测类型) | 兜底方案 | 该检测类型的默认质检方案 | + +### 检测类型字典 + +| 代码 | 检测类型 | 说明 | +|------|---------|------| +| 0 | 首检 | 生产开始前首批产品的检验 | +| 1 | 专检 | 专职检验员的检验 | +| 2 | 自检 | 操作工自己检验 | +| 3 | 互检 | 相互检验(上下工序互检) | +| 4 | 原材料检 | 原材料入库检验 | +| 5 | 抽检 | 抽样检验 | +| 6 | 成品检 | 成品检验 | +| 7 | 入库检 | 产品入库前的检验 | + +### 通用模板规则 + +**定义**: +- **通用模板**:不绑定具体物料、工序或工位,仅按检测类型适用的默认质检方案 +- **标识字段**:`is_default`(0否/1是) + +**约束规则**: +1. **唯一性**:每种检测类型只能有一个通用模板 +2. **互斥性**:通用模板不能同时绑定物料、工序或工位 +3. **校验方式**:应用层校验(Service层代码校验,非数据库约束) diff --git a/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/controller/QcHMIController.java b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/controller/QcHMIController.java new file mode 100644 index 00000000..1cce9d13 --- /dev/null +++ b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/controller/QcHMIController.java @@ -0,0 +1,60 @@ +package org.dromara.qms.controller; + +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.domain.R; +import org.dromara.qms.domain.dto.QcInspectionMainTask; +import org.dromara.qms.service.IQcHMIService; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * 上位机接口 + *

+ * 提供上位机(HMI)调用质检相关功能的接口 + * + * @author zch + * @date 2026-01-14 + */ +@Validated +@RequiredArgsConstructor +@Slf4j +@RestController +@RequestMapping("/hmi") +public class QcHMIController { + + private final IQcHMIService qcHmiService; + + /** + * 上位机调用生成质检任务 + *

+ * 接口路径: POST /hmi/QcInspectionMainTask + *

+ * 请求参数示例: + *

+     * {
+     *   "MaterialCode": "30109",
+     *   "StationName": "内衬层#01",
+     *   "InspectionQty": "12",
+     *   "InspectionType": "7",
+     *   "ProductionOrder": "20260112100834PL0005",
+     *   "BatchNo": "123",
+     *   "Barcode": "20260114NC001010006"
+     * }
+     * 
+ * + * @param taskDto 上位机传入的任务DTO + * @return 质检单号 + */ + // 上位机接口不登录,不使用@Log注解(LogAspect会尝试获取用户信息导致异常) + @PostMapping("/QcInspectionMainTask") + public R generateInspectionTask(@Valid @RequestBody QcInspectionMainTask taskDto) { + log.info("收到上位机质检任务生成请求,物料编码: {}, 工位名称: {}, 检验类型: {}", + taskDto.getMaterialCode(), taskDto.getStationName(), taskDto.getInspectionType()); + + String inspectionNo = qcHmiService.generateInspectionTask(taskDto); + return R.ok("质检任务生成成功", inspectionNo); + } + +} diff --git a/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/dto/QcInspectionMainTask.java b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/dto/QcInspectionMainTask.java new file mode 100644 index 00000000..9ae96bb7 --- /dev/null +++ b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/domain/dto/QcInspectionMainTask.java @@ -0,0 +1,61 @@ +package org.dromara.qms.domain.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +/** + * 上位机调用接口生成质检任务 + *

+ * 注意:字段使用 @JsonProperty 注解匹配上位机传入的大写开头JSON字段名 + * + * @author zch + * @date 2026-1-13 + */ +@Data +public class QcInspectionMainTask { + + /** + * 物料编码 + */ + @JsonProperty("MaterialCode") + private String materialCode; + + /** + * 工位名称 + */ + @JsonProperty("StationName") + private String stationName; + + /** + * 检验数量 + */ + @JsonProperty("InspectionQty") + private String inspectionQty; + + /** + * 检验类型(0首检 1专检 2自检 3互检 4原材料检 5抽检 6成品检 7入库检) + * 必填,上位机写死传7入库检 + */ + @JsonProperty("InspectionType") + private String inspectionType; + + /** + * 生产订单号(业务来源单号) + * 上位机传的是prod plan info_2的plan_code + */ + @JsonProperty("ProductionOrder") + private String productionOrder; + + /** + * 批次号 + */ + @JsonProperty("BatchNo") + private String batchNo; + + /** + * 条码 + */ + @JsonProperty("Barcode") + private String barcode; + +} diff --git a/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/service/IQcHMIService.java b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/service/IQcHMIService.java new file mode 100644 index 00000000..5804541e --- /dev/null +++ b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/service/IQcHMIService.java @@ -0,0 +1,29 @@ +package org.dromara.qms.service; + +import org.dromara.qms.domain.dto.QcInspectionMainTask; + +/** + * 上位机接口Service接口 + * + * @author zch + * @date 2026-01-14 + */ +public interface IQcHMIService { + + /** + * 上位机调用生成质检任务 + *

+ * 业务流程: + * 1. 参数校验(物料编码、检验类型必填) + * 2. 根据工位名称查询工位编码 + * 3. 匹配质检模板(8级降级匹配策略) + * 4. 生成质检单号 + * 5. 构建并保存质检主表 + * 6. 根据模板生成质检结果子表 + * 7. 返回质检单号 + * + * @param taskDto 上位机传入的任务DTO + * @return 质检单号 + */ + String generateInspectionTask(QcInspectionMainTask taskDto); +} diff --git a/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/service/impl/QcHMIServiceImpl.java b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/service/impl/QcHMIServiceImpl.java new file mode 100644 index 00000000..3edf11de --- /dev/null +++ b/ruoyi-modules/hwmom-qms/src/main/java/org/dromara/qms/service/impl/QcHMIServiceImpl.java @@ -0,0 +1,277 @@ +package org.dromara.qms.service.impl; + +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; + +import cn.dev33.satoken.stp.StpUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.dubbo.config.annotation.DubboReference; +import org.apache.dubbo.rpc.RpcContext; +import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.tenant.helper.TenantHelper; +import org.dromara.system.api.RemoteCodeRuleService; +import org.dromara.qms.domain.bo.QcInspectionMainBo; +import org.dromara.qms.domain.bo.QcInspectionResultBo; +import org.dromara.qms.domain.bo.ProdBaseStationInfoBo; +import org.dromara.qms.domain.bo.ProdBaseProcessInfoBo; +import org.dromara.qms.domain.bo.QcTemplateItemBo; +import org.dromara.qms.domain.dto.QcInspectionMainTask; +import org.dromara.qms.domain.vo.ProdBaseStationInfoVo; +import org.dromara.qms.domain.vo.ProdBaseProcessInfoVo; +import org.dromara.qms.domain.vo.QcInspectionTemplateVo; +import org.dromara.qms.domain.vo.QcTemplateItemVo; +import org.dromara.qms.service.IQcHMIService; +import org.dromara.qms.service.IQcInspectionMainService; +import org.dromara.qms.service.IQcInspectionResultService; +import org.dromara.qms.service.IQcInspectionTemplateService; +import org.dromara.qms.service.IQcTemplateItemService; +import org.dromara.qms.service.IProdBaseStationInfoService; +import org.dromara.qms.service.IProdBaseProcessInfoService; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * 上位机接口Service业务层处理 + * + * @author zch + * @date 2026-01-14 + */ +@Slf4j +@RequiredArgsConstructor +@Service +public class QcHMIServiceImpl implements IQcHMIService { + + private final IQcInspectionMainService qcInspectionMainService; + private final IQcInspectionResultService qcInspectionResultService; + private final IQcInspectionTemplateService qcInspectionTemplateService; + private final IQcTemplateItemService qcTemplateItemService; + private final IProdBaseStationInfoService prodBaseStationInfoService; + private final IProdBaseProcessInfoService prodBaseProcessInfoService; + + /** + * 编码规则服务(Dubbo 引用) + * 用于生成质检单号 + */ + @DubboReference(timeout = 300000) + private final RemoteCodeRuleService remoteCodeRuleService; + + /** + * 上位机默认租户ID + */ + private static final String HMI_DEFAULT_TENANT_ID = "000000"; + + /** + * 上位机默认创建人ID(系统管理员) + */ + private static final Long HMI_DEFAULT_CREATE_BY = 1L; + + /** + * 上位机调用生成质检任务 + *

+ * 业务流程: + * 1. 参数校验(物料编码、检验类型必填) + * 2. 根据工位名称查询工位编码 + * 3. 匹配质检模板(8级降级匹配策略) + * 4. 生成质检单号 + * 5. 构建并保存质检主表 + * 6. 根据模板生成质检结果子表 + * 7. 返回质检单号 + * + * @param taskDto 上位机传入的任务DTO + * @return 质检单号 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public String generateInspectionTask(QcInspectionMainTask taskDto) { + // 【重要】上位机不登录,模拟登录系统管理员,确保认证上下文和租户信息正确传递 + StpUtil.login(HMI_DEFAULT_CREATE_BY, "login"); + // 设置默认租户上下文 + TenantHelper.setDynamic(HMI_DEFAULT_TENANT_ID); + // 【关键】通过Dubbo隐式参数传递租户ID,确保远程服务能获取租户上下文 + RpcContext.getContext().setAttachment("tenantId", HMI_DEFAULT_TENANT_ID); + + try { + return doGenerateInspectionTask(taskDto); + } finally { + // 【清理】清理登录状态和租户上下文,避免线程池复用时的状态污染 + try { + StpUtil.logout(); + } catch (Exception ignored) { + } + try { + TenantHelper.clearDynamic(); + } catch (Exception ignored) { + } + } + } + + /** + * 实际执行生成质检任务的逻辑 + */ + private String doGenerateInspectionTask(QcInspectionMainTask taskDto) { + // 1. 参数校验 + if (StringUtils.isBlank(taskDto.getMaterialCode())) { + throw new ServiceException("物料编码不能为空"); + } + if (StringUtils.isBlank(taskDto.getInspectionType())) { + throw new ServiceException("检验类型不能为空"); + } + + log.info("上位机调用生成质检任务,物料编码: {}, 工位名称: {}, 检验类型: {}", + taskDto.getMaterialCode(), taskDto.getStationName(), taskDto.getInspectionType()); + + // 2. 匹配质检模板(调用已实现的8级降级匹配策略) + // FIXME: QcInspectionMainTask.stationName 是工位名称,需要查询工位编码 + // FIXME: 上位机不传工序信息,工序编码传 null + // TODO: 后期建议上位机直接传递编码,避免跨模块查询 + String materialCode = taskDto.getMaterialCode(); + String stationCode = getStationCodeByName(taskDto.getStationName()); // 根据工位名称查询工位编码 + QcInspectionTemplateVo templateVo = qcInspectionTemplateService.getMatchedTemplate( + materialCode, + stationCode, // 工位编码(通过名称查询) + null, // 工序编码(上位机不传) + taskDto.getInspectionType() + ); + + if (templateVo == null) { + throw new ServiceException("未找到匹配的质检模板,物料编码: " + taskDto.getMaterialCode()); + } + + log.info("质检模板匹配成功,模板ID: {}, 模板名称: {}", templateVo.getTemplateId(), templateVo.getTemplateName()); + + // 3. 生成质检单号(调用编码规则服务,使用支持租户传递的方法) + String inspectionNo = remoteCodeRuleService.selectCodeRuleCodeWithTenant("3"); + if (StringUtils.isBlank(inspectionNo)) { + throw new ServiceException("获取质检单号失败"); + } + + // 4. 构建质检主表BO + QcInspectionMainBo mainBo = buildInspectionMainBo(taskDto, templateVo, inspectionNo); + + // 5. 插入质检主表 + Boolean insertResult = qcInspectionMainService.insertByBo(mainBo); + if (!insertResult) { + throw new ServiceException("质检主表保存失败"); + } + + log.info("质检主表创建成功,质检单号: {}, 质检ID: {}", inspectionNo, mainBo.getInspectionId()); + + // 6. 根据模板生成质检结果子表 + generateInspectionResults(mainBo.getInspectionId(), templateVo.getTemplateId()); + + log.info("质检结果子表生成成功,共{}个检测项", getTemplateItemCount(templateVo.getTemplateId())); + + // 7. 返回质检单号 + return inspectionNo; + } + + /** + * 构建质检主表 BO + */ + private QcInspectionMainBo buildInspectionMainBo(QcInspectionMainTask taskDto, + QcInspectionTemplateVo templateVo, + String inspectionNo) { + QcInspectionMainBo mainBo = new QcInspectionMainBo(); + mainBo.setInspectionNo(inspectionNo); + mainBo.setTemplateId(templateVo.getTemplateId()); + mainBo.setTemplateName(templateVo.getTemplateName()); + mainBo.setInspectionType(templateVo.getTypeId()); + mainBo.setMaterialCode(taskDto.getMaterialCode()); + mainBo.setStationName(taskDto.getStationName()); + mainBo.setInspectionQty(new BigDecimal(taskDto.getInspectionQty())); + mainBo.setProductionOrder(taskDto.getProductionOrder()); + mainBo.setBatchNo(taskDto.getBatchNo()); + mainBo.setBarcode(taskDto.getBarcode()); + mainBo.setStatus("0"); // 未处理 + mainBo.setResult("0"); // 待判定 + + // 上位机不登录,手动设置审计字段 + mainBo.setCreateBy(HMI_DEFAULT_CREATE_BY); + mainBo.setCreateTime(new Date()); + return mainBo; + } + + /** + * 生成质检结果子表 + *

+ * 根据模板中的检测项生成对应的质检结果记录 + */ + private void generateInspectionResults(Long inspectionId, Long templateId) { + QcTemplateItemBo itemBo = new QcTemplateItemBo(); + itemBo.setTemplateId(templateId); + List itemList = qcTemplateItemService.queryList(itemBo); + + for (QcTemplateItemVo item : itemList) { + QcInspectionResultBo resultBo = new QcInspectionResultBo(); + resultBo.setInspectionId(inspectionId); + resultBo.setItemId(item.getItemId()); + resultBo.setDetectResult("2"); // 未判定 + resultBo.setItemCode(item.getItemCode()); + resultBo.setItemName(item.getItemName()); + resultBo.setInspectionPosition(item.getInspectionPosition()); + resultBo.setCategoryName(item.getCategoryName()); + resultBo.setDetectType(item.getDetectType()); + resultBo.setControlType(item.getControlType()); + resultBo.setStandardValue(item.getStandardValue()); + resultBo.setUpperLimit(item.getUpperLimit()); + resultBo.setLowerLimit(item.getLowerLimit()); + resultBo.setSpecName(item.getSpecName()); + resultBo.setSpecUpper(item.getSpecUpper()); + resultBo.setSpecLower(item.getSpecLower()); + resultBo.setDescription(item.getDescription()); + resultBo.setTypeId(item.getInspectionType()); + // 上位机不登录,手动设置审计字段 + resultBo.setCreateBy(HMI_DEFAULT_CREATE_BY); + resultBo.setCreateTime(new Date()); + qcInspectionResultService.insertByBo(resultBo); + } + } + + /** + * 获取模板检测项数量(用于日志) + */ + private int getTemplateItemCount(Long templateId) { + QcTemplateItemBo itemBo = new QcTemplateItemBo(); + itemBo.setTemplateId(templateId); + return qcTemplateItemService.queryList(itemBo).size(); + } + + /** + * 根据工位名称(机台名称)查询工位编码 + * FIXME: 后期需要优化缓存策略,避免每次查询都访问数据库 + * TODO: 考虑在应用启动时缓存工位名称→编码的映射关系 + * + * @param stationName 工位名称(来自上位机 QcInspectionMainTask.stationName) + * @return 工位编码,如果查询不到返回 null + */ + private String getStationCodeByName(String stationName) { + if (StringUtils.isBlank(stationName)) { + return null; + } + ProdBaseStationInfoBo bo = new ProdBaseStationInfoBo(); + bo.setStationName(stationName); + List list = prodBaseStationInfoService.queryList(bo); + return (list != null && !list.isEmpty()) ? list.get(0).getStationCode() : null; + } + + /** + * 根据工序名称查询工序编码 + * FIXME: 后期需要优化缓存策略,避免每次查询都访问数据库 + * TODO: 考虑在应用启动时缓存工序名称→编码的映射关系 + * + * @param processName 工序名称 + * @return 工序编码,如果查询不到返回 null + */ + private String getProcessCodeByName(String processName) { + if (StringUtils.isBlank(processName)) { + return null; + } + ProdBaseProcessInfoBo bo = new ProdBaseProcessInfoBo(); + bo.setProcessName(processName); + List list = prodBaseProcessInfoService.queryList(bo); + return (list != null && !list.isEmpty()) ? list.get(0).getProcessCode() : null; + } +} diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/dubbo/RemoteCodeRuleServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/dubbo/RemoteCodeRuleServiceImpl.java index 35eb56b7..ce9d9eb1 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/dubbo/RemoteCodeRuleServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/dubbo/RemoteCodeRuleServiceImpl.java @@ -2,6 +2,9 @@ package org.dromara.system.dubbo; import lombok.RequiredArgsConstructor; import org.apache.dubbo.config.annotation.DubboService; +import org.apache.dubbo.rpc.RpcContext; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.tenant.helper.TenantHelper; import org.dromara.system.api.RemoteCodeRuleService; import org.dromara.system.domain.bo.SysCodeRuleBo; import org.dromara.system.service.ISysCodeRuleService; @@ -30,4 +33,31 @@ public class RemoteCodeRuleServiceImpl implements RemoteCodeRuleService { bo.setCodeRuleCode(codeRuleCode); return sysCodeRuleService.getRuleGenerateCode(bo); } + + /** + * 通过编码规则编码获取编码(支持Dubbo租户传递) + *

+ * 该方法从Dubbo上下文获取租户ID并设置,确保租户过滤生效 + * 适用于上位机等无登录场景的跨服务调用 + * + * @param codeRuleCode 编码规则编码 + * @return currentCode + */ + @Override + public String selectCodeRuleCodeWithTenant(String codeRuleCode) { + // 从Dubbo上下文获取租户ID并设置,确保租户过滤生效 + String tenantId = RpcContext.getContext().getAttachment("tenantId"); + if (StringUtils.isNotBlank(tenantId)) { + TenantHelper.setDynamic(tenantId); + } + try { + SysCodeRuleBo bo = new SysCodeRuleBo(); + bo.setCodeRuleCode(codeRuleCode); + return sysCodeRuleService.getRuleGenerateCode(bo); + } finally { + if (StringUtils.isNotBlank(tenantId)) { + TenantHelper.clearDynamic(); + } + } + } }