配合示方生成混炼示方优化

This commit is contained in:
2026-07-30 17:40:31 +08:00
parent 5c27bacd11
commit dea9b7a58c
15 changed files with 541 additions and 107 deletions

View File

@@ -1361,3 +1361,32 @@ jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/MesXslMixingSpec.data.ts
-- author:jiangxh---date:20260730--for: <20><><EFBFBD><EFBFBD><EFBFBD>ϡ<EFBFBD><CFA1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD>/<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>أ<EFBFBD><D8A3><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EBBDBA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB> --- -- author:jiangxh---date:20260730--for: <20><><EFBFBD><EFBFBD><EFBFBD>ϡ<EFBFBD><CFA1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD>/<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>أ<EFBFBD><D8A3><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EBBDBA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB> ---
jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/mes/material/controller/MesMaterialController.java jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/mes/material/controller/MesMaterialController.java
jeecgboot-vue3/src/views/mes/material/MesMaterial.data.ts jeecgboot-vue3/src/views/mes/material/MesMaterial.data.ts
-- author:jiangxh---date:20260730--for: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD>ɡ<EFBFBD><C9A1><EFBFBD><EFBFBD><EFBFBD>ƴ<EFBFBD><EFBFBD>ţ<EFBFBD><C5A3><EFBFBD>ϸ<EFBFBD><CFB8><EFBFBD>ϲ<EFBFBD>ƴ<EFBFBD><EFBFBD><E6B1BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̶<EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD> ---
jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslFormulaSpecServiceImpl.java
-- author:jiangxh---date:20260730--for: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD>ɡ<EFBFBD>ͬһ<CDAC><D2BB><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>Σ<EFBFBD><CEA3><EFBFBD><EFBFBD><EFBFBD>ɾ<EFBFBD><C9BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ---
jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslFormulaSpecServiceImpl.java
-- author:jiangxh---date:20260730--for: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE>ɾ<EFBFBD><C9BE><EFBFBD><EFBFBD>ͣ<EFBFBD><CDA3>ͬ<EFBFBD><CDAC>ɾ<EFBFBD><C9BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ ---
jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslMixingSpecServiceImpl.java
-- author:jiangxh---date:20260730--for: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD>ɡ<EFBFBD>ĸ<EFBFBD><C4B8><EFBFBD><EFBFBD>;NP FOR<4F><52>һ<EFBFBD>ι<EFBFBD><CEB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>;ȡ<CDBE><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ---
jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslFormulaSpecServiceImpl.java
-- author:jiangxh---date:20260730--for: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD>𽺼<EFBFBD><F0BDBABC><EFBFBD><EFBFBD>ϼ<EFBFBD><CFBC><EFBFBD>ϸ<EFBFBD>ۼ<EFBFBD><DBBC>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD>λС<CEBB><D0A1> ---
jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslMixingSpecServiceImpl.java
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/MesXslMixingSpec.data.ts
-- author:jiangxh---date:20260730--for: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD>𽺼<EFBFBD><F0BDBABC><EFBFBD><EFBFBD>ϼ<EFBFBD><CFBC><EFBFBD>ϸ<EFBFBD><CFB8><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD>λС<CEBB><D0A1> ---
jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslMixingSpecServiceImpl.java
jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslFormulaSpecServiceImpl.java
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/MesXslMixingSpec.data.ts
-- author:jiangxh---date:20260730--for: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>PS<50><53><EFBFBD><EFBFBD><EFBFBD>ɷ<EFBFBD><C9B7><EFBFBD><EFBFBD><EFBFBD>׼<EFBFBD><D7BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>/<2F><><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD>(recognition_pass) ---
jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslMixerPsCompileService.java
jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslMixerPsCompileServiceImpl.java
jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslMixingSpecServiceImpl.java
jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslMixingSpecService.java
jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/approval/integration/engine/executor/RegistryStageSyncExecutor.java
jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/approval/integration/engine/executor/RegistryStageRevertExecutor.java

View File

@@ -9,6 +9,7 @@ import org.jeecg.modules.xslmes.approval.integration.entity.MesXslBizDocRegistry
import org.jeecg.modules.xslmes.approval.integration.entity.MesXslIntegrationAction; import org.jeecg.modules.xslmes.approval.integration.entity.MesXslIntegrationAction;
import org.jeecg.modules.xslmes.approval.integration.service.IApprovalTraceSyncService; import org.jeecg.modules.xslmes.approval.integration.service.IApprovalTraceSyncService;
import org.jeecg.modules.xslmes.approval.integration.service.IMesXslBizDocRegistryService; import org.jeecg.modules.xslmes.approval.integration.service.IMesXslBizDocRegistryService;
import org.jeecg.modules.xslmes.service.IMesXslMixerPsCompileService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@@ -26,6 +27,12 @@ public class RegistryStageRevertExecutor implements IIntegrationActionExecutor {
private IApprovalTraceSyncService approvalTraceSyncService; private IApprovalTraceSyncService approvalTraceSyncService;
@Autowired @Autowired
private JdbcTemplate jdbcTemplate; private JdbcTemplate jdbcTemplate;
//update-begin---author:jiangxh ---date:20260730 for【密炼PS】集成方案批准后联动示方正式发布-----------
@Autowired
private IMesXslMixerPsCompileService mesXslMixerPsCompileService;
private static final String BIZ_TABLE_MIXER_PS = "mes_xsl_mixer_ps_compile";
//update-end---author:jiangxh ---date:20260730 for【密炼PS】集成方案批准后联动示方正式发布-----------
@Override @Override
public String supportActionType() { public String supportActionType() {
return "REGISTRY_STAGE_REVERT"; return "REGISTRY_STAGE_REVERT";
@@ -57,6 +64,16 @@ public class RegistryStageRevertExecutor implements IIntegrationActionExecutor {
RegistryStageFieldHelper.assertIdentifier(statusField); RegistryStageFieldHelper.assertIdentifier(statusField);
RegistryStageFieldHelper.assertIdentifier(bizTable); RegistryStageFieldHelper.assertIdentifier(bizTable);
//update-begin---author:jiangxh ---date:20260730 for【密炼PS】集成方案批准后联动示方正式发布-----------
String previousStatus = null;
if (BIZ_TABLE_MIXER_PS.equals(bizTable)) {
Object current = jdbcTemplate.queryForObject(
"SELECT `" + statusField + "` FROM `" + bizTable + "` WHERE id = ?",
Object.class, bizId);
previousStatus = current == null ? null : String.valueOf(current).trim();
}
//update-end---author:jiangxh ---date:20260730 for【密炼PS】集成方案批准后联动示方正式发布-----------
//update-begin---author:GHT ---date:20260609 for【审批注册中心】回退只重置业务表状态操作人/时间由痕迹表承载----------- //update-begin---author:GHT ---date:20260609 for【审批注册中心】回退只重置业务表状态操作人/时间由痕迹表承载-----------
int affected = jdbcTemplate.update( int affected = jdbcTemplate.update(
"UPDATE `" + bizTable + "` SET `" + statusField + "`=? WHERE id=?", "UPDATE `" + bizTable + "` SET `" + statusField + "`=? WHERE id=?",
@@ -67,6 +84,11 @@ public class RegistryStageRevertExecutor implements IIntegrationActionExecutor {
} }
approvalTraceSyncService.revertToStage(bizTable, bizId, targetStage); approvalTraceSyncService.revertToStage(bizTable, bizId, targetStage);
//update-begin---author:jiangxh ---date:20260730 for【密炼PS】集成方案批准后联动示方正式发布-----------
if (BIZ_TABLE_MIXER_PS.equals(bizTable)) {
mesXslMixerPsCompileService.cascadeRelatedAfterStageRevert(bizId, previousStatus, targetStage);
}
//update-end---author:jiangxh ---date:20260730 for【密炼PS】集成方案批准后联动示方正式发布-----------
log.info("[集成引擎][REGISTRY_STAGE_REVERT] table={} id={} targetStage={}", bizTable, bizId, targetStage); log.info("[集成引擎][REGISTRY_STAGE_REVERT] table={} id={} targetStage={}", bizTable, bizId, targetStage);
return "环节回退成功: " + targetStage; return "环节回退成功: " + targetStage;
} }

View File

@@ -13,6 +13,7 @@ import org.jeecg.modules.xslmes.approval.integration.entity.MesXslIntegrationAct
import org.jeecg.modules.xslmes.approval.integration.entity.MesXslIntegrationPlan; import org.jeecg.modules.xslmes.approval.integration.entity.MesXslIntegrationPlan;
import org.jeecg.modules.xslmes.approval.integration.service.IApprovalTraceSyncService; import org.jeecg.modules.xslmes.approval.integration.service.IApprovalTraceSyncService;
import org.jeecg.modules.xslmes.approval.integration.service.IMesXslBizDocRegistryService; import org.jeecg.modules.xslmes.approval.integration.service.IMesXslBizDocRegistryService;
import org.jeecg.modules.xslmes.service.IMesXslMixerPsCompileService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@@ -30,6 +31,12 @@ public class RegistryStageSyncExecutor implements IIntegrationActionExecutor {
private IApprovalTraceSyncService approvalTraceSyncService; private IApprovalTraceSyncService approvalTraceSyncService;
@Autowired @Autowired
private JdbcTemplate jdbcTemplate; private JdbcTemplate jdbcTemplate;
//update-begin---author:jiangxh ---date:20260730 for【密炼PS】集成方案批准后联动示方正式发布-----------
@Autowired
private IMesXslMixerPsCompileService mesXslMixerPsCompileService;
//update-end---author:jiangxh ---date:20260730 for【密炼PS】集成方案批准后联动示方正式发布-----------
private static final String BIZ_TABLE_MIXER_PS = "mes_xsl_mixer_ps_compile";
@Override @Override
public String supportActionType() { public String supportActionType() {
@@ -96,6 +103,11 @@ public class RegistryStageSyncExecutor implements IIntegrationActionExecutor {
} }
approvalTraceSyncService.syncStage(bizTable, bizId, stage, operator, now); approvalTraceSyncService.syncStage(bizTable, bizId, stage, operator, now);
//update-begin---author:jiangxh ---date:20260730 for【密炼PS】集成方案批准后联动示方正式发布-----------
if (BIZ_TABLE_MIXER_PS.equals(bizTable)) {
mesXslMixerPsCompileService.cascadeRelatedAfterStageSync(bizId, statusAfter, operator, now);
}
//update-end---author:jiangxh ---date:20260730 for【密炼PS】集成方案批准后联动示方正式发布-----------
log.info("[集成引擎][REGISTRY_STAGE_SYNC] table={} id={} stage={} statusAfter={} operator={}", log.info("[集成引擎][REGISTRY_STAGE_SYNC] table={} id={} stage={} statusAfter={} operator={}",
bizTable, bizId, stage, statusAfter, operator); bizTable, bizId, stage, statusAfter, operator);
return "环节同步成功: " + ApprovalStageResolver.stageLabel(stage) + " → 状态=" + statusAfter; return "环节同步成功: " + ApprovalStageResolver.stageLabel(stage) + " → 状态=" + statusAfter;

View File

@@ -34,4 +34,20 @@ public interface IMesXslMixerPsCompileService extends IService<MesXslMixerPsComp
*/ */
String withdrawBatch(String ids, String operatorName); String withdrawBatch(String ids, String operatorName);
//update-end---author:GHT ---date:2026-05-29 for【QH-MES审批流设计】密炼PS拒绝/撤回逆向回退----------- //update-end---author:GHT ---date:2026-05-29 for【QH-MES审批流设计】密炼PS拒绝/撤回逆向回退-----------
//update-begin---author:jiangxh ---date:20260730 for【密炼PS】集成方案批准后联动示方正式发布-----------
/**
* 集成方案 REGISTRY_STAGE_SYNC 更新密炼PS状态后联动配合示方/混炼示方(发行编号=PS编码及原材料检验标准。
* 批准(approve)时示方状态写入 recognition_pass承认审批通过-即正式发布)。
*/
void cascadeRelatedAfterStageSync(String psId, String targetStatus, String operatorName, java.util.Date operatorTime);
/**
* 集成方案 REGISTRY_STAGE_REVERT 回退密炼PS状态后联动回退配合示方/混炼示方及原材料检验标准。
*
* @param previousStatus 回退前密炼PS状态
* @param targetStatus 回退后目标状态
*/
void cascadeRelatedAfterStageRevert(String psId, String previousStatus, String targetStatus);
//update-end---author:jiangxh ---date:20260730 for【密炼PS】集成方案批准后联动示方正式发布-----------
} }

View File

@@ -41,7 +41,8 @@ public interface IMesXslMixingSpecService extends IService<MesXslMixingSpec> {
//update-begin---author:cursor ---date:20260526 for【XSLMES-20260526-A61】混炼示方密炼PS审批联动同步审批人----------- //update-begin---author:cursor ---date:20260526 for【XSLMES-20260526-A61】混炼示方密炼PS审批联动同步审批人-----------
/** /**
* 密炼PS校对/审核/批准后按发行编号PS编码同步关联混炼示方审批人 * 密炼PS校对/审核/批准后按发行编号PS编码同步关联混炼示方状态与审批人
* 批准时状态为 recognition_pass承认审批通过-即正式发布)。
* *
* @param ps 已更新后的密炼PS编制单 * @param ps 已更新后的密炼PS编制单
* @param mixerPsTargetStatus 密炼PS目标状态proofread / audit / approve * @param mixerPsTargetStatus 密炼PS目标状态proofread / audit / approve
@@ -50,7 +51,7 @@ public interface IMesXslMixingSpecService extends IService<MesXslMixingSpec> {
//update-begin---author:GHT ---date:2026-05-29 for【QH-MES审批流设计】密炼PS拒绝/撤回联动回退混炼示方----------- //update-begin---author:GHT ---date:2026-05-29 for【QH-MES审批流设计】密炼PS拒绝/撤回联动回退混炼示方-----------
/** /**
* 密炼PS拒绝/撤回时按发行编号PS编码清空关联混炼示方高于目标状态的审批人痕迹。 * 密炼PS拒绝/撤回时按发行编号PS编码关联混炼示方回退到目标状态,并清空高于目标状态的审批人痕迹。
* *
* @param ps 已回退后的密炼PS编制单 * @param ps 已回退后的密炼PS编制单
* @param mixerPsTargetStatus 密炼PS回退后的目标状态compile / proofread / audit * @param mixerPsTargetStatus 密炼PS回退后的目标状态compile / proofread / audit

View File

@@ -565,6 +565,9 @@ public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecM
throw new IllegalArgumentException("请先维护混合段数"); throw new IllegalArgumentException("请先维护混合段数");
} }
String rubberName = resolveRubberName(main); String rubberName = resolveRubberName(main);
//update-begin---author:jiangxh ---date:20260730 for【混炼示方生成】规格拼版本号明细胶料不拼-----------
String formulaCodeSuffix = resolveFormulaCodeSuffix(main);
//update-end---author:jiangxh ---date:20260730 for【混炼示方生成】规格拼版本号明细胶料不拼-----------
boolean hasQ = hasStepQ(main.getLineList()); boolean hasQ = hasStepQ(main.getLineList());
List<MesXslFormulaMixingGeneratePreviewItemVO> items = new ArrayList<>(); List<MesXslFormulaMixingGeneratePreviewItemVO> items = new ArrayList<>();
int aIndex = 0; int aIndex = 0;
@@ -575,20 +578,23 @@ public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecM
item.setStageIndex(i); item.setStageIndex(i);
if (isQSegment) { if (isQSegment) {
item.setStepType("Q"); item.setStepType("Q");
//update-begin---author:jiangxh ---date:20260730 for【混炼示方生成】B/F匹配编号不拼版本后缀----------- //update-begin---author:jiangxh ---date:20260730 for【混炼示方生成】规格=B/F+胶料名+版本号-----------
item.setSpecCode(buildBfRubberSpecCode("F", rubberName)); item.setSpecCode(appendFormulaCodeSuffix(buildBfRubberSpecCode("F", rubberName), formulaCodeSuffix));
//update-end---author:jiangxh ---date:20260730 for【混炼示方生成】B/F匹配编号不拼版本后缀----------- //update-end---author:jiangxh ---date:20260730 for【混炼示方生成】规格=B/F+胶料名+版本号-----------
item.setASegmentIndex(null); item.setASegmentIndex(null);
} else { } else {
aIndex++; aIndex++;
item.setStepType("A"); item.setStepType("A");
item.setASegmentIndex(aIndex); item.setASegmentIndex(aIndex);
//update-begin---author:jiangxh ---date:20260730 for【混炼示方生成】B/F匹配编号不拼版本后缀----------- //update-begin---author:jiangxh ---date:20260730 for【混炼示方生成】规格=B/F+胶料名+版本号-----------
item.setSpecCode(buildBfRubberSpecCode("B" + aIndex, rubberName)); item.setSpecCode(appendFormulaCodeSuffix(buildBfRubberSpecCode("B" + aIndex, rubberName), formulaCodeSuffix));
//update-end---author:jiangxh ---date:20260730 for【混炼示方生成】B/F匹配编号不拼版本后缀----------- //update-end---author:jiangxh ---date:20260730 for【混炼示方生成】规格=B/F+胶料名+版本号-----------
} }
items.add(item); items.add(item);
} }
//update-begin---author:jiangxh ---date:20260730 for【混炼示方生成】同一配合示方仅允许生成一次-----------
assertMixingSpecsNotYetGeneratedByPreview(items);
//update-end---author:jiangxh ---date:20260730 for【混炼示方生成】同一配合示方仅允许生成一次-----------
//update-begin---author:jiangxh ---date:20260730 for【混炼示方生成】列表点生成混炼示方时即匹配胶料列表----------- //update-begin---author:jiangxh ---date:20260730 for【混炼示方生成】列表点生成混炼示方时即匹配胶料列表-----------
// 点击「生成混炼示方」打开预览时即校验拼接示方编号是否已在胶料列表维护 // 点击「生成混炼示方」打开预览时即校验拼接示方编号是否已在胶料列表维护
assertRequiredRubberMaterialsExist(toGenerateRowsFromPreviewItems(items), main, main.getLineList()); assertRequiredRubberMaterialsExist(toGenerateRowsFromPreviewItems(items), main, main.getLineList());
@@ -630,6 +636,9 @@ public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecM
int created = 0; int created = 0;
int totalStages = normalizeMixingStages(formula.getMixingStages()); int totalStages = normalizeMixingStages(formula.getMixingStages());
Date today = Date.from(LocalDate.now().atStartOfDay(ZoneId.systemDefault()).toInstant()); Date today = Date.from(LocalDate.now().atStartOfDay(ZoneId.systemDefault()).toInstant());
//update-begin---author:jiangxh ---date:20260730 for【混炼示方生成】同一配合示方仅允许生成一次-----------
assertMixingSpecsNotYetGeneratedByRows(request.getRows());
//update-end---author:jiangxh ---date:20260730 for【混炼示方生成】同一配合示方仅允许生成一次-----------
//update-begin---author:jiangxh ---date:20260729 for【混炼示方生成】B/F胶料改为胶料列表匹配不存在则提示先维护----------- //update-begin---author:jiangxh ---date:20260729 for【混炼示方生成】B/F胶料改为胶料列表匹配不存在则提示先维护-----------
Map<String, String> categoryIdCache = new HashMap<>(); Map<String, String> categoryIdCache = new HashMap<>();
assertRequiredRubberMaterialsExist(request.getRows(), formula, lines); assertRequiredRubberMaterialsExist(request.getRows(), formula, lines);
@@ -659,7 +668,9 @@ public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecM
} }
MesXslMixingSpec mixing = new MesXslMixingSpec(); MesXslMixingSpec mixing = new MesXslMixingSpec();
mixing.setSpecName(row.getSpecCode()); mixing.setSpecName(row.getSpecCode());
mixing.setPurpose(formula.getPurpose()); //update-begin---author:jiangxh ---date:20260730 for【混炼示方生成】母炼用途NP FOR下一段终炼用途取胶料类别-----------
mixing.setPurpose(resolveGeneratedMixingPurpose(row, request.getRows(), formula, categoryNameCache));
//update-end---author:jiangxh ---date:20260730 for【混炼示方生成】母炼用途NP FOR下一段终炼用途取胶料类别-----------
mixing.setIssueNumber(formula.getIssueNumber()); mixing.setIssueNumber(formula.getIssueNumber());
mixing.setMachineId(machine.getMachineId()); mixing.setMachineId(machine.getMachineId());
mixing.setMachineName(machine.getMachineName()); mixing.setMachineName(machine.getMachineName());
@@ -704,6 +715,70 @@ public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecM
return created; return created;
} }
//update-begin---author:jiangxh ---date:20260730 for【混炼示方生成】母炼/终炼用途拼接规则-----------
/**
* 生成混炼示方用途:
* - 母炼B段NP FOR + 下一段规格(含版本号),如 NP FOR B2XC001SA01
* - 终炼F段胶料类别名称如 注射胶
*/
private String resolveGeneratedMixingPurpose(
MesXslFormulaMixingGenerateRowVO row,
List<MesXslFormulaMixingGenerateRowVO> allRows,
MesXslFormulaSpec formula,
Map<String, String> categoryNameCache) {
if (row == null) {
return "";
}
boolean isFinalStage = "Q".equalsIgnoreCase(resolveMixingMaterialStep(row));
if (isFinalStage) {
return resolveFinalMixingPurpose(formula, categoryNameCache);
}
String nextSpecCode = findNextStageSpecCode(row, allRows);
if (StringUtils.isNotBlank(nextSpecCode)) {
return "NP FOR " + nextSpecCode.trim();
}
// 无下一段时回退为终炼用途规则
return resolveFinalMixingPurpose(formula, categoryNameCache);
}
/** 终炼用途:取所选胶料的类别名(如注射胶);类别为空时回退配合示方用途 */
private String resolveFinalMixingPurpose(MesXslFormulaSpec formula, Map<String, String> categoryNameCache) {
String categoryId = resolveGeneratedRubberCategoryId(formula);
String categoryName = resolveCategoryName(categoryId, categoryNameCache);
if (StringUtils.isNotBlank(categoryName)) {
return categoryName.trim();
}
if (formula != null && StringUtils.isNotBlank(formula.getPurpose())) {
return formula.getPurpose().trim();
}
return "";
}
/** 按混合段序号找下一段规格编号 */
private String findNextStageSpecCode(
MesXslFormulaMixingGenerateRowVO current,
List<MesXslFormulaMixingGenerateRowVO> allRows) {
if (current == null || current.getStageIndex() == null || CollectionUtils.isEmpty(allRows)) {
return null;
}
int currentStage = current.getStageIndex();
MesXslFormulaMixingGenerateRowVO next = null;
for (MesXslFormulaMixingGenerateRowVO row : allRows) {
if (row == null || row.getStageIndex() == null || StringUtils.isBlank(row.getSpecCode())) {
continue;
}
int stage = row.getStageIndex();
if (stage <= currentStage) {
continue;
}
if (next == null || stage < next.getStageIndex()) {
next = row;
}
}
return next != null ? next.getSpecCode().trim() : null;
}
//update-end---author:jiangxh ---date:20260730 for【混炼示方生成】母炼/终炼用途拼接规则-----------
//update-begin---author:cursor ---date:20260525 for【XSLMES-20260525-A44】生成混炼示方时按设备有效体积计算填充体积----------- //update-begin---author:cursor ---date:20260525 for【XSLMES-20260525-A44】生成混炼示方时按设备有效体积计算填充体积-----------
/** 配合示方整体比重(终炼胶比重)= TOTAL PHR ÷ 全部明细体积合计 */ /** 配合示方整体比重(终炼胶比重)= TOTAL PHR ÷ 全部明细体积合计 */
private BigDecimal resolveCompoundSpecificGravity(MesXslFormulaSpec formula, List<MesXslFormulaSpecLine> lines) { private BigDecimal resolveCompoundSpecificGravity(MesXslFormulaSpec formula, List<MesXslFormulaSpecLine> lines) {
@@ -804,6 +879,53 @@ public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecM
//update-end---author:cursor ---date:20260525 for【XSLMES-20260525-A44】生成混炼示方时按设备有效体积计算填充体积----------- //update-end---author:cursor ---date:20260525 for【XSLMES-20260525-A44】生成混炼示方时按设备有效体积计算填充体积-----------
//update-begin---author:cursor ---date:20260601 for【XSLMES-20260601-A62】生成混炼示方改为同步B/F段胶至胶料信息----------- //update-begin---author:cursor ---date:20260601 for【XSLMES-20260601-A62】生成混炼示方改为同步B/F段胶至胶料信息-----------
//update-begin---author:jiangxh ---date:20260730 for【混炼示方生成】同一配合示方仅允许生成一次-----------
/** 预览项:若对应规格混炼示方已存在则禁止再次生成 */
private void assertMixingSpecsNotYetGeneratedByPreview(
List<MesXslFormulaMixingGeneratePreviewItemVO> items) {
if (CollectionUtils.isEmpty(items)) {
return;
}
LinkedHashSet<String> specNames = new LinkedHashSet<>();
for (MesXslFormulaMixingGeneratePreviewItemVO item : items) {
if (item != null && StringUtils.isNotBlank(item.getSpecCode())) {
specNames.add(item.getSpecCode().trim());
}
}
assertMixingSpecNamesNotExist(specNames);
}
/** 确认行:若对应规格混炼示方已存在则禁止再次生成 */
private void assertMixingSpecsNotYetGeneratedByRows(List<MesXslFormulaMixingGenerateRowVO> rows) {
if (CollectionUtils.isEmpty(rows)) {
return;
}
LinkedHashSet<String> specNames = new LinkedHashSet<>();
for (MesXslFormulaMixingGenerateRowVO row : rows) {
if (row != null && StringUtils.isNotBlank(row.getSpecCode())) {
specNames.add(row.getSpecCode().trim());
}
}
assertMixingSpecNamesNotExist(specNames);
}
/** 若已存在同规格混炼示方,则禁止再次生成 */
private void assertMixingSpecNamesNotExist(Collection<String> specNames) {
if (CollectionUtils.isEmpty(specNames)) {
return;
}
long count = mesXslMixingSpecService.count(
new LambdaQueryWrapper<MesXslMixingSpec>()
.in(MesXslMixingSpec::getSpecName, specNames)
.and(w -> w.eq(MesXslMixingSpec::getDelFlag, CommonConstant.DEL_FLAG_0)
.or()
.isNull(MesXslMixingSpec::getDelFlag)));
if (count > 0) {
throw new IllegalArgumentException("该配合示方已生成过混炼示方,请先删除对应混炼示方后再重新生成");
}
}
//update-end---author:jiangxh ---date:20260730 for【混炼示方生成】同一配合示方仅允许生成一次-----------
//update-begin---author:jiangxh ---date:20260729 for【混炼示方生成】B/F胶料改为胶料列表匹配不存在则提示先维护----------- //update-begin---author:jiangxh ---date:20260729 for【混炼示方生成】B/F胶料改为胶料列表匹配不存在则提示先维护-----------
//update-begin---author:jiangxh ---date:20260730 for【混炼示方生成】预览项转生成行供胶料匹配校验----------- //update-begin---author:jiangxh ---date:20260730 for【混炼示方生成】预览项转生成行供胶料匹配校验-----------
/** 预览行转为生成行结构,供胶料匹配校验复用 */ /** 预览行转为生成行结构,供胶料匹配校验复用 */
@@ -829,7 +951,7 @@ public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecM
//update-end---author:jiangxh ---date:20260730 for【混炼示方生成】预览项转生成行供胶料匹配校验----------- //update-end---author:jiangxh ---date:20260730 for【混炼示方生成】预览项转生成行供胶料匹配校验-----------
/** /**
* 生成前校验:按 B段序号/F + 胶料名 拼出的示方编号,必须已在胶料信息中存在;不再自动新建 * 生成前校验:按 B段序号/F + 胶料名(不含版本号)匹配胶料信息;规格上的 SA01 等不参与匹配
* 在列表点击「生成混炼示方」预览时即调用,确认生成时再次校验。 * 在列表点击「生成混炼示方」预览时即调用,确认生成时再次校验。
*/ */
private void assertRequiredRubberMaterialsExist( private void assertRequiredRubberMaterialsExist(
@@ -842,25 +964,28 @@ public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecM
LinkedHashSet<String> requiredCodes = new LinkedHashSet<>(); LinkedHashSet<String> requiredCodes = new LinkedHashSet<>();
String rubberName = resolveRubberName(formula); String rubberName = resolveRubberName(formula);
for (MesXslFormulaMixingGenerateRowVO row : rows) { for (MesXslFormulaMixingGenerateRowVO row : rows) {
if (row == null || StringUtils.isBlank(row.getSpecCode())) { if (row == null) {
continue; continue;
} }
requiredCodes.add(row.getSpecCode().trim());
String stepFilter = resolveMixingMaterialStep(row); String stepFilter = resolveMixingMaterialStep(row);
int mixingColumn = resolveMixingColumn(row, formula); int mixingColumn = resolveMixingColumn(row, formula);
//update-begin---author:jiangxh ---date:20260730 for【混炼示方生成】胶料匹配用不含版本号的B/F名-----------
if ("Q".equalsIgnoreCase(stepFilter)) { if ("Q".equalsIgnoreCase(stepFilter)) {
if (StringUtils.isNotBlank(rubberName)) {
requiredCodes.add(buildBfRubberSpecCode("F", rubberName));
}
int lastBSegment = resolveLastBSegmentIndex(formula, lines); int lastBSegment = resolveLastBSegmentIndex(formula, lines);
if (lastBSegment > 0 && StringUtils.isNotBlank(rubberName)) { if (lastBSegment > 0 && StringUtils.isNotBlank(rubberName)) {
//update-begin---author:jiangxh ---date:20260730 for【混炼示方生成】母胶匹配不拼版本后缀-----------
requiredCodes.add(buildBfRubberSpecCode("B" + lastBSegment, rubberName)); requiredCodes.add(buildBfRubberSpecCode("B" + lastBSegment, rubberName));
//update-end---author:jiangxh ---date:20260730 for【混炼示方生成】母胶匹配不拼版本后缀-----------
} }
} else if (mixingColumn > 1 && StringUtils.isNotBlank(rubberName)) { } else if (StringUtils.isNotBlank(rubberName)) {
//update-begin---author:jiangxh ---date:20260730 for【混炼示方生成】母胶匹配不拼版本后缀----------- requiredCodes.add(buildBfRubberSpecCode("B" + mixingColumn, rubberName));
if (mixingColumn > 1) {
requiredCodes.add(buildBfRubberSpecCode("B" + (mixingColumn - 1), rubberName)); requiredCodes.add(buildBfRubberSpecCode("B" + (mixingColumn - 1), rubberName));
//update-end---author:jiangxh ---date:20260730 for【混炼示方生成】母胶匹配不拼版本后缀-----------
} }
} }
//update-end---author:jiangxh ---date:20260730 for【混炼示方生成】胶料匹配用不含版本号的B/F名-----------
}
List<String> missing = new ArrayList<>(); List<String> missing = new ArrayList<>();
for (String code : requiredCodes) { for (String code : requiredCodes) {
if (StringUtils.isBlank(code)) { if (StringUtils.isBlank(code)) {
@@ -1022,9 +1147,8 @@ public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecM
/** /**
* 配合示方胶料代号/示方编号中,胶料名称之后的后缀原样截取(如 SA01、SB01 等)。 * 配合示方胶料代号/示方编号中,胶料名称之后的后缀原样截取(如 SA01、SB01 等)。
* @deprecated 生成混炼示方匹配胶料已改为仅 B/F+胶料名,不再拼接版本后缀 * 用于混炼示方「规格」拼接;明细胶料匹配不使用此后缀
*/ */
@Deprecated
private String resolveFormulaCodeSuffix(MesXslFormulaSpec main) { private String resolveFormulaCodeSuffix(MesXslFormulaSpec main) {
if (main == null) { if (main == null) {
return ""; return "";
@@ -1051,10 +1175,7 @@ public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecM
return ""; return "";
} }
/** /** 混炼示方规格编号追加版本后缀(如 SA01 */
* @deprecated 生成混炼示方匹配胶料已改为仅 B/F+胶料名,请使用 {@link #buildBfRubberSpecCode(String, String)}
*/
@Deprecated
private String appendFormulaCodeSuffix(String baseSpecCode, String formulaCodeSuffix) { private String appendFormulaCodeSuffix(String baseSpecCode, String formulaCodeSuffix) {
if (StringUtils.isBlank(baseSpecCode)) { if (StringUtils.isBlank(baseSpecCode)) {
return baseSpecCode; return baseSpecCode;
@@ -1065,15 +1186,15 @@ public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecM
return baseSpecCode + formulaCodeSuffix; return baseSpecCode + formulaCodeSuffix;
} }
//update-begin---author:jiangxh ---date:20260730 for【混炼示方生成】B/F匹配编号仅前缀+胶料名----------- //update-begin---author:jiangxh ---date:20260730 for【混炼示方生成】明细胶料匹配编号仅前缀+胶料名-----------
/** /**
* 生成/匹配用示方编号仅「B{n}/F + 胶料名」,不拼接 SA01 等版本号。 * 明细胶料匹配用编号仅「B{n}/F + 胶料名」,不拼接 SA01 等版本号。
* 例:胶料 XC001 三段 → B1XC001、B2XC001、FXC001 * 例:胶料 XC001 → B1XC001、B2XC001、FXC001(规格另拼版本号)
*/ */
private String buildBfRubberSpecCode(String phasePrefix, String rubberName) { private String buildBfRubberSpecCode(String phasePrefix, String rubberName) {
return StringUtils.defaultString(phasePrefix) + StringUtils.defaultString(rubberName).trim(); return StringUtils.defaultString(phasePrefix) + StringUtils.defaultString(rubberName).trim();
} }
//update-end---author:jiangxh ---date:20260730 for【混炼示方生成】B/F匹配编号仅前缀+胶料名----------- //update-end---author:jiangxh ---date:20260730 for【混炼示方生成】明细胶料匹配编号仅前缀+胶料名-----------
private boolean hasStepQ(List<MesXslFormulaSpecLine> lines) { private boolean hasStepQ(List<MesXslFormulaSpecLine> lines) {
if (CollectionUtils.isEmpty(lines)) { if (CollectionUtils.isEmpty(lines)) {
@@ -1263,7 +1384,9 @@ public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecM
ensureMotherRubberMaterialSynced(motherSpecCode, formula, categoryIdCache); ensureMotherRubberMaterialSynced(motherSpecCode, formula, categoryIdCache);
MesXslMixingSpecMaterial material = new MesXslMixingSpecMaterial(); MesXslMixingSpecMaterial material = new MesXslMixingSpecMaterial();
material.setSortNo(sortNo); material.setSortNo(sortNo);
material.setUnitWeight(unitWeight); //update-begin---author:jiangxh ---date:20260730 for【混炼示方】单重列保留三位小数-----------
material.setUnitWeight(unitWeight == null ? null : unitWeight.setScale(3, RoundingMode.HALF_UP));
//update-end---author:jiangxh ---date:20260730 for【混炼示方】单重列保留三位小数-----------
MesMaterial rubber = findRubberMaterialByCodeOrName(motherSpecCode.trim()); MesMaterial rubber = findRubberMaterialByCodeOrName(motherSpecCode.trim());
if (rubber != null) { if (rubber != null) {
fillMixingMaterialFromRubberMaterial(material, rubber, categoryNameCache, kindLookup); fillMixingMaterialFromRubberMaterial(material, rubber, categoryNameCache, kindLookup);
@@ -1343,20 +1466,13 @@ public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecM
material.setMaterialMajor(null); material.setMaterialMajor(null);
material.setMaterialMinor(categoryName); material.setMaterialMinor(categoryName);
material.setMixerMaterialId(rubber.getId()); material.setMixerMaterialId(rubber.getId());
//update-begin---author:jiangxh ---date:20260729 for【混炼示方生成】母胶行种类按配置解析,未命中则带入胶料兜底种类----------- //update-begin---author:jiangxh ---date:20260730 for【混炼示方生成】明细胶料种类固定为「胶料」-----------
String kind = mesXslMixerMaterialKindCfgService.resolveMixingMaterialKind( // 明细母胶/终胶种类固定「胶料」,不取注射胶、胎面胶等类别名
kindLookup, rubber.getCategoryId(), null, categoryName); material.setMaterialKind(resolveRubberMaterialKindName(kindLookup));
if (StringUtils.isBlank(kind) && kindLookup != null && StringUtils.isNotBlank(kindLookup.getRubberKindName())) { //update-end---author:jiangxh ---date:20260730 for【混炼示方生成】明细胶料种类固定为「胶料」-----------
kind = kindLookup.getRubberKindName().trim();
}
if (StringUtils.isBlank(kind)) {
kind = "胶料";
}
material.setMaterialKind(kind);
//update-end---author:jiangxh ---date:20260729 for【混炼示方生成】母胶行种类按配置解析未命中则带入胶料兜底种类-----------
} }
/** 未查到胶料信息时,按配合示方胶料类别从配置表解析种类 */ /** 未查到胶料信息时,按配合示方胶料类别回填小类展示,种类仍固定为「胶料」 */
private void fillMotherRubberCategoryFallback( private void fillMotherRubberCategoryFallback(
MesXslMixingSpecMaterial material, MesXslMixingSpecMaterial material,
MesXslFormulaSpec formula, MesXslFormulaSpec formula,
@@ -1366,17 +1482,17 @@ public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecM
String categoryName = resolveCategoryName(categoryId, categoryNameCache); String categoryName = resolveCategoryName(categoryId, categoryNameCache);
material.setMaterialMajor(null); material.setMaterialMajor(null);
material.setMaterialMinor(categoryName); material.setMaterialMinor(categoryName);
//update-begin---author:jiangxh ---date:20260729 for【混炼示方生成】母胶兜底种类带入胶料种类----------- //update-begin---author:jiangxh ---date:20260730 for【混炼示方生成】明细胶料种类固定为「胶料」-----------
String kind = mesXslMixerMaterialKindCfgService.resolveMixingMaterialKind( material.setMaterialKind(resolveRubberMaterialKindName(kindLookup));
kindLookup, categoryId, null, categoryName); //update-end---author:jiangxh ---date:20260730 for【混炼示方生成】明细胶料种类固定为「胶料」-----------
if (StringUtils.isBlank(kind) && kindLookup != null && StringUtils.isNotBlank(kindLookup.getRubberKindName())) {
kind = kindLookup.getRubberKindName().trim();
} }
if (StringUtils.isBlank(kind)) {
kind = "胶料"; /** 明细胶料种类:优先取种类配置中的胶料种类名,默认「胶料」 */
private String resolveRubberMaterialKindName(MesXslMixerMaterialKindLookupVO kindLookup) {
if (kindLookup != null && StringUtils.isNotBlank(kindLookup.getRubberKindName())) {
return kindLookup.getRubberKindName().trim();
} }
material.setMaterialKind(kind); return "胶料";
//update-end---author:jiangxh ---date:20260729 for【混炼示方生成】母胶兜底种类带入胶料种类-----------
} }
//update-end---author:cursor ---date:20260601 for【XSLMES-20260601-A62】母胶明细行按胶料信息回填----------- //update-end---author:cursor ---date:20260601 for【XSLMES-20260601-A62】母胶明细行按胶料信息回填-----------
//update-end---author:cursor ---date:20260525 for【XSLMES-20260525-A54】母炼胶明细行绑定已同步密炼物料主数据----------- //update-end---author:cursor ---date:20260525 for【XSLMES-20260525-A54】母炼胶明细行绑定已同步密炼物料主数据-----------
@@ -1462,7 +1578,9 @@ public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecM
material.setMixerMaterialName(line.getMixerMaterialName()); material.setMixerMaterialName(line.getMixerMaterialName());
material.setMixerMaterialDesc( material.setMixerMaterialDesc(
StringUtils.isNotBlank(line.getMaterialDesc()) ? line.getMaterialDesc() : line.getMixerMaterialName()); StringUtils.isNotBlank(line.getMaterialDesc()) ? line.getMaterialDesc() : line.getMixerMaterialName());
material.setUnitWeight(unitWeight); //update-begin---author:jiangxh ---date:20260730 for【混炼示方】单重列保留三位小数-----------
material.setUnitWeight(unitWeight == null ? null : unitWeight.setScale(3, RoundingMode.HALF_UP));
//update-end---author:jiangxh ---date:20260730 for【混炼示方】单重列保留三位小数-----------
fillMaterialCategory(material, line.getMixerMaterialId(), line, mixerCache, categoryNameCache, kindLookup); fillMaterialCategory(material, line.getMixerMaterialId(), line, mixerCache, categoryNameCache, kindLookup);
return material; return material;
} }

View File

@@ -207,4 +207,44 @@ public class MesXslMixerPsCompileServiceImpl extends ServiceImpl<MesXslMixerPsCo
} }
} }
//update-end---author:GHT ---date:2026-05-29 for【QH-MES审批流设计】密炼PS拒绝/撤回逆向回退----------- //update-end---author:GHT ---date:2026-05-29 for【QH-MES审批流设计】密炼PS拒绝/撤回逆向回退-----------
//update-begin---author:jiangxh ---date:20260730 for【密炼PS】集成方案批准后联动示方正式发布-----------
@Override
public void cascadeRelatedAfterStageSync(String psId, String targetStatus, String operatorName, Date operatorTime) {
if (oConvertUtils.isEmpty(psId) || oConvertUtils.isEmpty(targetStatus)) {
return;
}
MesXslMixerPsCompile entity = getById(psId.trim());
if (entity == null || oConvertUtils.isEmpty(entity.getPsCode())) {
return;
}
Date now = operatorTime != null ? operatorTime : new Date();
// 操作人/时间以审批上下文为准写入关联示方(源单痕迹由注册中心双写)
fillWorkflowInfo(entity, targetStatus, operatorName, now);
mesXslFormulaSpecService.syncFromMixerPsWorkflow(entity, targetStatus);
mesXslMixingSpecService.syncFromMixerPsWorkflow(entity, targetStatus);
if ("approve".equals(targetStatus)
&& XslMesBizConstants.PS_TYPE_RAW_INSPECT_STD.equals(entity.getPsType())) {
mesXslRubberQuickTestStdService.markAuditApprovedByPsCompileIds(Collections.singletonList(entity.getId()));
}
}
@Override
public void cascadeRelatedAfterStageRevert(String psId, String previousStatus, String targetStatus) {
if (oConvertUtils.isEmpty(psId) || oConvertUtils.isEmpty(targetStatus)) {
return;
}
MesXslMixerPsCompile entity = getById(psId.trim());
if (entity == null || oConvertUtils.isEmpty(entity.getPsCode())) {
return;
}
entity.setStatus(targetStatus);
mesXslFormulaSpecService.revertFromMixerPsWorkflow(entity, targetStatus);
mesXslMixingSpecService.revertFromMixerPsWorkflow(entity, targetStatus);
if ("approve".equals(previousStatus)
&& XslMesBizConstants.PS_TYPE_RAW_INSPECT_STD.equals(entity.getPsType())) {
mesXslRubberQuickTestStdService.markAuditDraftByPsCompileIds(Collections.singletonList(entity.getId()));
}
}
//update-end---author:jiangxh ---date:20260730 for【密炼PS】集成方案批准后联动示方正式发布-----------
} }

View File

@@ -189,15 +189,18 @@ public class MesXslMixingSpecServiceImpl extends ServiceImpl<MesXslMixingSpecMap
//update-end---author:cursor ---date:20260526 for【配方日志查询】混炼示方删除落库修改日志----------- //update-end---author:cursor ---date:20260526 for【配方日志查询】混炼示方删除落库修改日志-----------
clearChildrenBatch(ids); clearChildrenBatch(ids);
this.removeByIds(ids); this.removeByIds(ids);
Set<String> specNames = new LinkedHashSet<>(); //update-begin---author:jiangxh ---date:20260730 for【混炼示方删除】停用同步删除胶料信息-----------
for (MesXslMixingSpec main : mains) { // 胶料改为手工维护并从列表匹配,删除混炼示方时不再同步删除胶料信息
if (main != null && StringUtils.isNotBlank(main.getSpecName())) { // Set<String> specNames = new LinkedHashSet<>();
specNames.add(main.getSpecName().trim()); // for (MesXslMixingSpec main : mains) {
} // if (main != null && StringUtils.isNotBlank(main.getSpecName())) {
} // specNames.add(main.getSpecName().trim());
for (String specName : specNames) { // }
syncDeleteGeneratedRubberMixerMaterial(specName); // }
} // for (String specName : specNames) {
// syncDeleteGeneratedRubberMixerMaterial(specName);
// }
//update-end---author:jiangxh ---date:20260730 for【混炼示方删除】停用同步删除胶料信息-----------
//update-end---author:cursor ---date:20260525 for【XSLMES-20260525-A56】混炼示方批量删除性能优化----------- //update-end---author:cursor ---date:20260525 for【XSLMES-20260525-A56】混炼示方批量删除性能优化-----------
} }
@@ -421,6 +424,13 @@ public class MesXslMixingSpecServiceImpl extends ServiceImpl<MesXslMixingSpecMap
if (CollectionUtils.isEmpty(materialList)) { if (CollectionUtils.isEmpty(materialList)) {
return; return;
} }
//update-begin---author:jiangxh ---date:20260730 for【混炼示方】单重列保留三位小数-----------
for (MesXslMixingSpecMaterial row : materialList) {
if (row != null && row.getUnitWeight() != null) {
row.setUnitWeight(row.getUnitWeight().setScale(3, java.math.RoundingMode.HALF_UP));
}
}
//update-end---author:jiangxh ---date:20260730 for【混炼示方】单重列保留三位小数-----------
//update-begin---author:cursor ---date:20260525 for【XSLMES-20260525-A41】橡胶及配合剂明细累计按种类分组合计----------- //update-begin---author:cursor ---date:20260525 for【XSLMES-20260525-A41】橡胶及配合剂明细累计按种类分组合计-----------
fillMaterialAccumWeight(materialList); fillMaterialAccumWeight(materialList);
//update-end---author:cursor ---date:20260525 for【XSLMES-20260525-A41】橡胶及配合剂明细累计按种类分组合计----------- //update-end---author:cursor ---date:20260525 for【XSLMES-20260525-A41】橡胶及配合剂明细累计按种类分组合计-----------
@@ -653,7 +663,12 @@ public class MesXslMixingSpecServiceImpl extends ServiceImpl<MesXslMixingSpecMap
} }
for (int rowIndex = index; rowIndex < groupEnd; rowIndex++) { for (int rowIndex = index; rowIndex < groupEnd; rowIndex++) {
if (rowIndex == groupEnd - 1) { if (rowIndex == groupEnd - 1) {
materials.get(rowIndex).setAccumWeight(sum.compareTo(BigDecimal.ZERO) != 0 ? sum : null); //update-begin---author:jiangxh ---date:20260730 for【混炼示方】累计列保留三位小数-----------
materials.get(rowIndex).setAccumWeight(
sum.compareTo(BigDecimal.ZERO) != 0
? sum.setScale(3, java.math.RoundingMode.HALF_UP)
: null);
//update-end---author:jiangxh ---date:20260730 for【混炼示方】累计列保留三位小数-----------
} else { } else {
materials.get(rowIndex).setAccumWeight(null); materials.get(rowIndex).setAccumWeight(null);
} }
@@ -757,11 +772,16 @@ public class MesXslMixingSpecServiceImpl extends ServiceImpl<MesXslMixingSpecMap
//update-end---author:GHT ---date:2026-06-10 for【混炼示方】TCU是否附加为否时清空重量----------- //update-end---author:GHT ---date:2026-06-10 for【混炼示方】TCU是否附加为否时清空重量-----------
//update-begin---author:cursor ---date:20260601 for【XSLMES-20260601-A62】删除混炼示方时同步删除自动生成的B/F段胶料信息----------- //update-begin---author:cursor ---date:20260601 for【XSLMES-20260601-A62】删除混炼示方时同步删除自动生成的B/F段胶料信息-----------
//update-begin---author:jiangxh ---date:20260730 for【混炼示方删除】停用同步删除胶料信息方法保留备查-----------
/** /**
* 删除混炼示方后,若该 B/F 段胶示方编号已无其它混炼示方、未被其它示方明细引用、且未被配合示方选作胶料代号, * 删除混炼示方后同步删除胶料信息 —— 已停用。
* 则同步删除生成时写入的「胶料信息」(mes_material)。仅处理 F 段或 B+数字 形态的自动生成编号,避免误删人工维护胶料 * 原逻辑:若 B/F 段胶示方编号已无其它混炼示方引用,则删除 mes_material
* 现胶料改为手工维护匹配,删除混炼示方不再动胶料信息。
*/ */
@SuppressWarnings("unused")
private void syncDeleteGeneratedRubberMixerMaterial(String specName) { private void syncDeleteGeneratedRubberMixerMaterial(String specName) {
// 已停用:不再同步删除胶料
/*
if (StringUtils.isBlank(specName)) { if (StringUtils.isBlank(specName)) {
return; return;
} }
@@ -800,7 +820,9 @@ public class MesXslMixingSpecServiceImpl extends ServiceImpl<MesXslMixingSpecMap
} }
mesMaterialService.removeById(material.getId()); mesMaterialService.removeById(material.getId());
log.info("[混炼示方删除] 同步删除胶料信息 id={}, code={}", material.getId(), specCode); log.info("[混炼示方删除] 同步删除胶料信息 id={}, code={}", material.getId(), specCode);
*/
} }
//update-end---author:jiangxh ---date:20260730 for【混炼示方删除】停用同步删除胶料信息方法保留备查-----------
/** 判断是否为生成混炼示方时自动同步的 B/F 段胶示方编号true=F段false=B段null=非自动生成胶料编号 */ /** 判断是否为生成混炼示方时自动同步的 B/F 段胶示方编号true=F段false=B段null=非自动生成胶料编号 */
private Boolean resolveGeneratedRubberSegment(String specCode) { private Boolean resolveGeneratedRubberSegment(String specCode) {
@@ -859,16 +881,25 @@ public class MesXslMixingSpecServiceImpl extends ServiceImpl<MesXslMixingSpecMap
wrapper.eq(MesXslMixingSpec::getIssueNumber, ps.getPsCode()); wrapper.eq(MesXslMixingSpec::getIssueNumber, ps.getPsCode());
switch (mixerPsTargetStatus) { switch (mixerPsTargetStatus) {
case "proofread": case "proofread":
wrapper.set(MesXslMixingSpec::getProofreadBy, ps.getProofreadBy()) //update-begin---author:jiangxh ---date:20260730 for【混炼示方】密炼PS联动同步正式发布状态-----------
wrapper.set(MesXslMixingSpec::getStatus, "submit")
.set(MesXslMixingSpec::getProofreadBy, ps.getProofreadBy())
.set(MesXslMixingSpec::getProofreadTime, ps.getProofreadTime()); .set(MesXslMixingSpec::getProofreadTime, ps.getProofreadTime());
//update-end---author:jiangxh ---date:20260730 for【混炼示方】密炼PS联动同步正式发布状态-----------
break; break;
case "audit": case "audit":
wrapper.set(MesXslMixingSpec::getAuditBy, ps.getAuditBy()) //update-begin---author:jiangxh ---date:20260730 for【混炼示方】密炼PS联动同步正式发布状态-----------
wrapper.set(MesXslMixingSpec::getStatus, "review_pass")
.set(MesXslMixingSpec::getAuditBy, ps.getAuditBy())
.set(MesXslMixingSpec::getAuditTime, ps.getAuditTime()); .set(MesXslMixingSpec::getAuditTime, ps.getAuditTime());
//update-end---author:jiangxh ---date:20260730 for【混炼示方】密炼PS联动同步正式发布状态-----------
break; break;
case "approve": case "approve":
wrapper.set(MesXslMixingSpec::getApproveBy, ps.getApproveBy()) //update-begin---author:jiangxh ---date:20260730 for【混炼示方】密炼PS联动同步正式发布状态-----------
wrapper.set(MesXslMixingSpec::getStatus, "recognition_pass")
.set(MesXslMixingSpec::getApproveBy, ps.getApproveBy())
.set(MesXslMixingSpec::getApproveTime, ps.getApproveTime()); .set(MesXslMixingSpec::getApproveTime, ps.getApproveTime());
//update-end---author:jiangxh ---date:20260730 for【混炼示方】密炼PS联动同步正式发布状态-----------
break; break;
default: default:
return; return;
@@ -888,19 +919,28 @@ public class MesXslMixingSpecServiceImpl extends ServiceImpl<MesXslMixingSpecMap
wrapper.eq(MesXslMixingSpec::getIssueNumber, ps.getPsCode()); wrapper.eq(MesXslMixingSpec::getIssueNumber, ps.getPsCode());
switch (mixerPsTargetStatus) { switch (mixerPsTargetStatus) {
case "compile": case "compile":
// 回退到编制:清空 校对/审核/批准 三组痕迹 //update-begin---author:jiangxh ---date:20260730 for【混炼示方】密炼PS联动同步正式发布状态-----------
wrapper.set(MesXslMixingSpec::getProofreadBy, null).set(MesXslMixingSpec::getProofreadTime, null) // 回退到编制:状态回 compile清空 校对/审核/批准 三组痕迹
wrapper.set(MesXslMixingSpec::getStatus, "compile")
.set(MesXslMixingSpec::getProofreadBy, null).set(MesXslMixingSpec::getProofreadTime, null)
.set(MesXslMixingSpec::getAuditBy, null).set(MesXslMixingSpec::getAuditTime, null) .set(MesXslMixingSpec::getAuditBy, null).set(MesXslMixingSpec::getAuditTime, null)
.set(MesXslMixingSpec::getApproveBy, null).set(MesXslMixingSpec::getApproveTime, null); .set(MesXslMixingSpec::getApproveBy, null).set(MesXslMixingSpec::getApproveTime, null);
//update-end---author:jiangxh ---date:20260730 for【混炼示方】密炼PS联动同步正式发布状态-----------
break; break;
case "proofread": case "proofread":
// 回退到校对:清空 审核/批准 痕迹(保留校对) //update-begin---author:jiangxh ---date:20260730 for【混炼示方】密炼PS联动同步正式发布状态-----------
wrapper.set(MesXslMixingSpec::getAuditBy, null).set(MesXslMixingSpec::getAuditTime, null) // 回退到校对:状态回 submit清空 审核/批准 痕迹(保留校对)
wrapper.set(MesXslMixingSpec::getStatus, "submit")
.set(MesXslMixingSpec::getAuditBy, null).set(MesXslMixingSpec::getAuditTime, null)
.set(MesXslMixingSpec::getApproveBy, null).set(MesXslMixingSpec::getApproveTime, null); .set(MesXslMixingSpec::getApproveBy, null).set(MesXslMixingSpec::getApproveTime, null);
//update-end---author:jiangxh ---date:20260730 for【混炼示方】密炼PS联动同步正式发布状态-----------
break; break;
case "audit": case "audit":
// 回退到审核:清空 批准 痕迹(保留校对/审核) //update-begin---author:jiangxh ---date:20260730 for【混炼示方】密炼PS联动同步正式发布状态-----------
wrapper.set(MesXslMixingSpec::getApproveBy, null).set(MesXslMixingSpec::getApproveTime, null); // 回退到审核:状态回 review_pass清空 批准 痕迹(保留校对/审核)
wrapper.set(MesXslMixingSpec::getStatus, "review_pass")
.set(MesXslMixingSpec::getApproveBy, null).set(MesXslMixingSpec::getApproveTime, null);
//update-end---author:jiangxh ---date:20260730 for【混炼示方】密炼PS联动同步正式发布状态-----------
break; break;
default: default:
return; return;

View File

@@ -134,7 +134,11 @@ export const materialColumns: JVxeColumn[] = [
minWidth: MIXING_MATERIAL_MIN_COLUMN_WIDTH, minWidth: MIXING_MATERIAL_MIN_COLUMN_WIDTH,
}, },
{ title: '密炼物料描述', key: 'mixerMaterialDesc', type: JVxeTypes.input, width: 220, minWidth: MIXING_MATERIAL_MIN_COLUMN_WIDTH }, { title: '密炼物料描述', key: 'mixerMaterialDesc', type: JVxeTypes.input, width: 220, minWidth: MIXING_MATERIAL_MIN_COLUMN_WIDTH },
{ title: '单重', key: 'unitWeight', type: JVxeTypes.inputNumber, width: 72, minWidth: MIXING_MATERIAL_MIN_COLUMN_WIDTH, align: 'center' }, { title: '单重', key: 'unitWeight', type: JVxeTypes.inputNumber, width: 72, minWidth: MIXING_MATERIAL_MIN_COLUMN_WIDTH, align: 'center',
//update-begin---author:jiangxh ---date:20260730 for【混炼示方】单重列保留三位小数-----------
props: { precision: 3 },
//update-end---author:jiangxh ---date:20260730 for【混炼示方】单重列保留三位小数-----------
},
//update-begin---author:cursor ---date:20260525 for【XSLMES-20260525-A41】累计列按种类分组合计只读展示----------- //update-begin---author:cursor ---date:20260525 for【XSLMES-20260525-A41】累计列按种类分组合计只读展示-----------
{ {
title: '累计', title: '累计',
@@ -144,6 +148,9 @@ export const materialColumns: JVxeColumn[] = [
minWidth: MIXING_MATERIAL_MIN_COLUMN_WIDTH, minWidth: MIXING_MATERIAL_MIN_COLUMN_WIDTH,
align: 'center', align: 'center',
disabled: true, disabled: true,
//update-begin---author:jiangxh ---date:20260730 for【混炼示方】累计列保留三位小数-----------
props: { precision: 3 },
//update-end---author:jiangxh ---date:20260730 for【混炼示方】累计列保留三位小数-----------
}, },
//update-end---author:cursor ---date:20260525 for【XSLMES-20260525-A41】累计列按种类分组合计只读展示----------- //update-end---author:cursor ---date:20260525 for【XSLMES-20260525-A41】累计列按种类分组合计只读展示-----------
{ title: '顺序', key: 'seqNo', type: JVxeTypes.inputNumber, width: 64, minWidth: MIXING_MATERIAL_MIN_COLUMN_WIDTH, align: 'center' }, { title: '顺序', key: 'seqNo', type: JVxeTypes.inputNumber, width: 64, minWidth: MIXING_MATERIAL_MIN_COLUMN_WIDTH, align: 'center' },
@@ -297,8 +304,10 @@ export function fillMixingMaterialAccumWeight(rows: Recordable[] = []): Recordab
groupEnd++; groupEnd++;
} }
for (let rowIndex = index; rowIndex < groupEnd; rowIndex++) { for (let rowIndex = index; rowIndex < groupEnd; rowIndex++) {
//update-begin---author:jiangxh ---date:20260730 for【混炼示方】累计列保留三位小数-----------
rows[rowIndex].accumWeight = rows[rowIndex].accumWeight =
rowIndex === groupEnd - 1 && sum !== 0 ? roundMixingMaterialNumber(sum) : null; rowIndex === groupEnd - 1 && sum !== 0 ? roundMixingMaterialAccumNumber(sum) : null;
//update-end---author:jiangxh ---date:20260730 for【混炼示方】累计列保留三位小数-----------
} }
index = groupEnd; index = groupEnd;
} }
@@ -315,7 +324,14 @@ function toMixingMaterialNumber(value: unknown): number | null {
} }
/** 混炼示方重量小数位(与后端 BigDecimal 精度一致) */ /** 混炼示方重量小数位(与后端 BigDecimal 精度一致) */
const MIXING_MATERIAL_WEIGHT_SCALE = 6; //update-begin---author:jiangxh ---date:20260730 for【混炼示方】单重列保留三位小数-----------
const MIXING_MATERIAL_WEIGHT_SCALE = 3;
//update-end---author:jiangxh ---date:20260730 for【混炼示方】单重列保留三位小数-----------
//update-begin---author:jiangxh ---date:20260730 for【混炼示方】累计列保留三位小数-----------
/** 累计列小数位 */
const MIXING_MATERIAL_ACCUM_WEIGHT_SCALE = 3;
//update-end---author:jiangxh ---date:20260730 for【混炼示方】累计列保留三位小数-----------
//update-begin---author:cursor ---date:20260526 for【XSLMES-20260526-A60】换算系数/配方参数数值展示优化----------- //update-begin---author:cursor ---date:20260526 for【XSLMES-20260526-A60】换算系数/配方参数数值展示优化-----------
/** 换算系数展示小数位 */ /** 换算系数展示小数位 */
@@ -401,6 +417,22 @@ function roundMixingMaterialNumber(value: number): number {
return Number(value.toFixed(MIXING_MATERIAL_WEIGHT_SCALE)); return Number(value.toFixed(MIXING_MATERIAL_WEIGHT_SCALE));
} }
//update-begin---author:jiangxh ---date:20260730 for【混炼示方】累计列保留三位小数-----------
/** 累计重量四舍五入为三位小数 */
function roundMixingMaterialAccumNumber(value: number): number {
return Number(value.toFixed(MIXING_MATERIAL_ACCUM_WEIGHT_SCALE));
}
/** 格式化累计重量展示文本 */
function formatMixingMaterialAccumWeight(value: unknown): string {
const num = toMixingMaterialNumber(value);
if (num == null) {
return '';
}
return String(roundMixingMaterialAccumNumber(num));
}
//update-end---author:jiangxh ---date:20260730 for【混炼示方】累计列保留三位小数-----------
/** 格式化重量展示文本 */ /** 格式化重量展示文本 */
function formatMixingMaterialWeight(value: unknown): string { function formatMixingMaterialWeight(value: unknown): string {
const num = toMixingMaterialNumber(value); const num = toMixingMaterialNumber(value);
@@ -593,7 +625,9 @@ export function buildMixingMaterialFooterCells(
return { key, width, text: formatTotal(totals.unitWeight), align: 'center', isTotal: true }; return { key, width, text: formatTotal(totals.unitWeight), align: 'center', isTotal: true };
} }
if (key === 'accumWeight') { if (key === 'accumWeight') {
return { key, width, text: formatTotal(totals.accumWeight), align: 'center', isTotal: true }; //update-begin---author:jiangxh ---date:20260730 for【混炼示方】累计列保留三位小数-----------
return { key, width, text: formatMixingMaterialAccumWeight(totals.accumWeight), align: 'center', isTotal: true };
//update-end---author:jiangxh ---date:20260730 for【混炼示方】累计列保留三位小数-----------
} }
const isLabelCol = unitWeightIndex > 0 && index === unitWeightIndex - 1; const isLabelCol = unitWeightIndex > 0 && index === unitWeightIndex - 1;
return { return {

View File

@@ -526,7 +526,10 @@ public class RawMaterialEntryEditDialogViewModel : BaseViewModel, IDialogResulta
.Initialize<WeightRecordPickerDialogViewModel>(vm => .Initialize<WeightRecordPickerDialogViewModel>(vm =>
{ {
pickerVm = vm; pickerVm = vm;
vm.Initialize(Entry?.BillNo); vm.Initialize(
Entry?.BillNo,
SelectedMaterial?.Id ?? Entry?.MaterialId,
SelectedMaterial?.MaterialName ?? Entry?.MaterialName);
}) })
.GetResultAsync<bool>()); .GetResultAsync<bool>());
} }

View File

@@ -24,6 +24,26 @@ public class WeightRecordPickerDialogViewModel : BaseViewModel, IDialogResultabl
set => SetProperty(ref _searchPlateNumber, value); set => SetProperty(ref _searchPlateNumber, value);
} }
/// <summary>入场记录已选密炼物料ID有值时仅展示关联该物料的磅单。</summary>
private string? _filterMixerMaterialId;
private string? _filterMixerMaterialName;
public string FilterHint
{
get
{
if (string.IsNullOrWhiteSpace(_filterMixerMaterialId))
{
return "未选择密炼物料时显示全部进厂磅单;已选物料时仅匹配含该物料的磅单。";
}
var name = string.IsNullOrWhiteSpace(_filterMixerMaterialName)
? _filterMixerMaterialId
: _filterMixerMaterialName;
return $"已按密炼物料「{name}」自动匹配关联磅单";
}
}
public ObservableCollection<MesXslWeightRecord> Records { get; } = new(); public ObservableCollection<MesXslWeightRecord> Records { get; } = new();
private MesXslWeightRecord? _selectedRecord; private MesXslWeightRecord? _selectedRecord;
@@ -40,7 +60,7 @@ public class WeightRecordPickerDialogViewModel : BaseViewModel, IDialogResultabl
} }
public string SelectedRecordDisplay => _selectedRecord != null public string SelectedRecordDisplay => _selectedRecord != null
? $"[{_selectedRecord.BillNo}] 供应商:{_selectedRecord.SenderUnit ?? "-"}" ? $"[{_selectedRecord.BillNo}] 供应商:{_selectedRecord.SenderUnit ?? "-"} 物料:{_selectedRecord.MixerMaterialNames ?? "-"}"
: "选中榜单后点击「确认选择」"; : "选中榜单后点击「确认选择」";
public bool HasSelectedRecord => _selectedRecord != null; public bool HasSelectedRecord => _selectedRecord != null;
@@ -67,16 +87,24 @@ public class WeightRecordPickerDialogViewModel : BaseViewModel, IDialogResultabl
SearchCommand = new DelegateCommand(async () => await LoadAsync()); SearchCommand = new DelegateCommand(async () => await LoadAsync());
ConfirmCommand = new DelegateCommand(Confirm, () => SelectedRecord != null); ConfirmCommand = new DelegateCommand(Confirm, () => SelectedRecord != null);
CancelCommand = new DelegateCommand(() => CloseAction?.Invoke()); CancelCommand = new DelegateCommand(() => CloseAction?.Invoke());
_ = LoadAsync(); // 不在构造时加载:等 Initialize 带入密炼物料过滤条件后再查,避免竞态覆盖筛选结果
} }
public void Initialize(string? billNo) /// <param name="billNo">已选榜单号(用于回显搜索)</param>
/// <param name="mixerMaterialId">已选密炼物料ID有值则只匹配含该物料的磅单</param>
/// <param name="mixerMaterialName">密炼物料名称(提示展示)</param>
public void Initialize(string? billNo, string? mixerMaterialId = null, string? mixerMaterialName = null)
{ {
_filterMixerMaterialId = string.IsNullOrWhiteSpace(mixerMaterialId) ? null : mixerMaterialId.Trim();
_filterMixerMaterialName = string.IsNullOrWhiteSpace(mixerMaterialName) ? null : mixerMaterialName.Trim();
RaisePropertyChanged(nameof(FilterHint));
if (!string.IsNullOrWhiteSpace(billNo)) if (!string.IsNullOrWhiteSpace(billNo))
{ {
SearchBillNo = billNo.Trim(); SearchBillNo = billNo.Trim();
_ = LoadAsync();
} }
_ = LoadAsync();
} }
private async Task LoadAsync() private async Task LoadAsync()
@@ -92,7 +120,7 @@ public class WeightRecordPickerDialogViewModel : BaseViewModel, IDialogResultabl
filterInoutDirection: "1"); filterInoutDirection: "1");
Records.Clear(); Records.Clear();
foreach (var record in result.Records) foreach (var record in result.Records.Where(MatchesSelectedMixerMaterial))
{ {
Records.Add(record); Records.Add(record);
} }
@@ -102,6 +130,11 @@ public class WeightRecordPickerDialogViewModel : BaseViewModel, IDialogResultabl
SelectedRecord = Records.FirstOrDefault(x => SelectedRecord = Records.FirstOrDefault(x =>
string.Equals(x.BillNo, SearchBillNo, StringComparison.OrdinalIgnoreCase)); string.Equals(x.BillNo, SearchBillNo, StringComparison.OrdinalIgnoreCase));
} }
else if (!string.IsNullOrWhiteSpace(_filterMixerMaterialId) && Records.Count == 1)
{
// 仅匹配到一条时自动选中,便于快速确认
SelectedRecord = Records[0];
}
} }
catch catch
{ {
@@ -113,6 +146,25 @@ public class WeightRecordPickerDialogViewModel : BaseViewModel, IDialogResultabl
} }
} }
/// <summary>未指定物料时不过滤;指定时要求磅单 MixerMaterialIds 含该ID。</summary>
private bool MatchesSelectedMixerMaterial(MesXslWeightRecord record)
{
if (string.IsNullOrWhiteSpace(_filterMixerMaterialId))
{
return true;
}
if (string.IsNullOrWhiteSpace(record.MixerMaterialIds))
{
return false;
}
var parts = record.MixerMaterialIds.Split(
new[] { ';', ',', '', '' },
StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
return parts.Any(p => string.Equals(p, _filterMixerMaterialId, StringComparison.OrdinalIgnoreCase));
}
private void Confirm() private void Confirm()
{ {
if (SelectedRecord == null) if (SelectedRecord == null)

View File

@@ -34,6 +34,44 @@ public class WeightRecordEditDialogViewModel : BaseViewModel, IDialogResultable<
public bool IsAddMode => string.IsNullOrWhiteSpace(Record?.Id); public bool IsAddMode => string.IsNullOrWhiteSpace(Record?.Id);
public string DialogTitle => IsAddMode ? "新增磅单" : "编辑磅单"; public string DialogTitle => IsAddMode ? "新增磅单" : "编辑磅单";
/// <summary>毛重输入:变更后自动重算净重</summary>
public double? GrossWeightInput
{
get => Record?.GrossWeight;
set
{
if (Record == null || Nullable.Equals(Record.GrossWeight, value)) return;
Record.GrossWeight = value;
RaisePropertyChanged(nameof(GrossWeightInput));
RecalcNetWeight();
}
}
/// <summary>皮重输入:变更后自动用毛重-皮重填充净重</summary>
public double? TareWeightInput
{
get => Record?.TareWeight;
set
{
if (Record == null || Nullable.Equals(Record.TareWeight, value)) return;
Record.TareWeight = value;
RaisePropertyChanged(nameof(TareWeightInput));
RecalcNetWeight();
}
}
/// <summary>净重(只读展示,由毛重/皮重自动计算)</summary>
public double? NetWeightInput
{
get => Record?.NetWeight;
private set
{
if (Record == null || Nullable.Equals(Record.NetWeight, value)) return;
Record.NetWeight = value;
RaisePropertyChanged(nameof(NetWeightInput));
}
}
public ObservableCollection<KeyValuePair<string, string>> InoutDirectionOptions { get; } = new(); public ObservableCollection<KeyValuePair<string, string>> InoutDirectionOptions { get; } = new();
private bool _result; private bool _result;
@@ -121,6 +159,7 @@ public class WeightRecordEditDialogViewModel : BaseViewModel, IDialogResultable<
}; };
RaisePropertyChanged(nameof(IsAddMode)); RaisePropertyChanged(nameof(IsAddMode));
RaisePropertyChanged(nameof(DialogTitle)); RaisePropertyChanged(nameof(DialogTitle));
RaiseWeightInputsChanged();
} }
public void InitializeForEdit(MesXslWeightRecord record) public void InitializeForEdit(MesXslWeightRecord record)
@@ -151,6 +190,31 @@ public class WeightRecordEditDialogViewModel : BaseViewModel, IDialogResultable<
RaisePropertyChanged(nameof(HasSelectedMixerMaterials)); RaisePropertyChanged(nameof(HasSelectedMixerMaterials));
RaisePropertyChanged(nameof(IsAddMode)); RaisePropertyChanged(nameof(IsAddMode));
RaisePropertyChanged(nameof(DialogTitle)); RaisePropertyChanged(nameof(DialogTitle));
RaiseWeightInputsChanged();
// 编辑打开时若已有毛重+皮重,立即校正净重展示
RecalcNetWeight();
}
private void RaiseWeightInputsChanged()
{
RaisePropertyChanged(nameof(GrossWeightInput));
RaisePropertyChanged(nameof(TareWeightInput));
RaisePropertyChanged(nameof(NetWeightInput));
}
/// <summary>毛重、皮重均有效时:净重 = 毛重 - 皮重(保留两位小数)</summary>
private void RecalcNetWeight()
{
if (Record == null) return;
if (Record.GrossWeight.HasValue && Record.GrossWeight.Value > 0
&& Record.TareWeight.HasValue && Record.TareWeight.Value > 0)
{
NetWeightInput = Math.Round(Record.GrossWeight.Value - Record.TareWeight.Value, 2);
}
else
{
NetWeightInput = null;
}
} }
private async Task SaveAsync() private async Task SaveAsync()
@@ -168,12 +232,8 @@ public class WeightRecordEditDialogViewModel : BaseViewModel, IDialogResultable<
return; return;
} }
// 净重自动计算0 视为未称,不计算净重) // 保存前再算一次,防止未触发属性变更时净重未更新
if (Record.GrossWeight.HasValue && Record.GrossWeight.Value > 0 RecalcNetWeight();
&& Record.TareWeight.HasValue && Record.TareWeight.Value > 0)
Record.NetWeight = Math.Round(Record.GrossWeight.Value - Record.TareWeight.Value, 2);
else
Record.NetWeight = null;
// 写入密炼物料 // 写入密炼物料
Record.MixerMaterialIds = _mixerMaterialIds; Record.MixerMaterialIds = _mixerMaterialIds;

View File

@@ -8,10 +8,11 @@
xmlns:prism="http://prismlibrary.com/" xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True" prism:ViewModelLocator.AutoWireViewModel="True"
mc:Ignorable="d" mc:Ignorable="d"
Width="760"> Width="920">
<Grid Background="{DynamicResource ThirdlyRegionBrush}"> <Grid Background="{DynamicResource ThirdlyRegionBrush}">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/>
<RowDefinition Height="360"/> <RowDefinition Height="360"/>
@@ -34,7 +35,11 @@
Padding="0" HorizontalAlignment="Right" VerticalAlignment="Center"/> Padding="0" HorizontalAlignment="Right" VerticalAlignment="Center"/>
</hc:SimplePanel> </hc:SimplePanel>
<Border Grid.Row="1" Background="{DynamicResource RegionBrush}" Padding="16,10"> <TextBlock Grid.Row="1" Margin="20,0,20,8" FontSize="12"
Foreground="{DynamicResource SecondaryTextBrush}"
Text="{Binding FilterHint}" TextWrapping="Wrap"/>
<Border Grid.Row="2" Background="{DynamicResource RegionBrush}" Padding="16,10">
<Grid> <Grid>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/>
@@ -70,7 +75,7 @@
</Border> </Border>
<DataGrid x:Name="WeightRecordsGrid" <DataGrid x:Name="WeightRecordsGrid"
Grid.Row="2" Grid.Row="3"
Margin="16,8,16,0" Margin="16,8,16,0"
ItemsSource="{Binding Records}" ItemsSource="{Binding Records}"
SelectedItem="{Binding SelectedRecord}" SelectedItem="{Binding SelectedRecord}"
@@ -135,20 +140,21 @@
</Style> </Style>
</DataGrid.CellStyle> </DataGrid.CellStyle>
<DataGrid.Columns> <DataGrid.Columns>
<DataGridTextColumn Header="榜单号" Binding="{Binding BillNo}" Width="180"/> <DataGridTextColumn Header="榜单号" Binding="{Binding BillNo}" Width="160"/>
<DataGridTextColumn Header="车牌号" Binding="{Binding PlateNumber}" Width="100"/> <DataGridTextColumn Header="车牌号" Binding="{Binding PlateNumber}" Width="90"/>
<DataGridTextColumn Header="密炼物料" Binding="{Binding MixerMaterialNames}" Width="160"/>
<DataGridTextColumn Header="供应商(发货单位)" Binding="{Binding SenderUnit}" Width="*"/> <DataGridTextColumn Header="供应商(发货单位)" Binding="{Binding SenderUnit}" Width="*"/>
<DataGridTextColumn Header="净重(KG)" Binding="{Binding NetWeight, StringFormat=N2}" Width="90"/> <DataGridTextColumn Header="净重(KG)" Binding="{Binding NetWeight, StringFormat=N2}" Width="80"/>
<DataGridTextColumn Header="已入场(KG)" Binding="{Binding EnteredWeight, StringFormat=N2}" Width="100"/> <DataGridTextColumn Header="已入场(KG)" Binding="{Binding EnteredWeight, StringFormat=N2}" Width="90"/>
<DataGridTextColumn Header="货物皮重" Binding="{Binding CargoTareWeight, StringFormat=N2}" Width="90"/> <DataGridTextColumn Header="货物皮重" Binding="{Binding CargoTareWeight, StringFormat=N2}" Width="80"/>
<DataGridTextColumn Header="称重日期" Binding="{Binding WeighDate, StringFormat='yyyy-MM-dd'}" Width="110"/> <DataGridTextColumn Header="称重日期" Binding="{Binding WeighDate, StringFormat='yyyy-MM-dd'}" Width="100"/>
</DataGrid.Columns> </DataGrid.Columns>
</DataGrid> </DataGrid>
<Border Grid.Row="3" BorderBrush="{DynamicResource BorderBrush}" BorderThickness="0,1,0,0" <Border Grid.Row="4" BorderBrush="{DynamicResource BorderBrush}" BorderThickness="0,1,0,0"
Padding="16,12"> Padding="16,12">
<Grid> <Grid>
<TextBlock VerticalAlignment="Center" FontSize="13" MaxWidth="420" <TextBlock VerticalAlignment="Center" FontSize="13" MaxWidth="560"
TextTrimming="CharacterEllipsis" HorizontalAlignment="Left" TextTrimming="CharacterEllipsis" HorizontalAlignment="Left"
Text="{Binding SelectedRecordDisplay}"> Text="{Binding SelectedRecordDisplay}">
<TextBlock.Style> <TextBlock.Style>

View File

@@ -144,7 +144,7 @@
<!-- 毛重 --> <!-- 毛重 -->
<hc:Col Span="12"> <hc:Col Span="12">
<hc:NumericUpDown Value="{Binding Record.GrossWeight}" <hc:NumericUpDown Value="{Binding GrossWeightInput, UpdateSourceTrigger=PropertyChanged}"
Minimum="0" Minimum="0"
DecimalPlaces="2" DecimalPlaces="2"
Style="{StaticResource NumericUpDownPlus}" Style="{StaticResource NumericUpDownPlus}"
@@ -158,7 +158,7 @@
<!-- 皮重 --> <!-- 皮重 -->
<hc:Col Span="12"> <hc:Col Span="12">
<hc:NumericUpDown Value="{Binding Record.TareWeight}" <hc:NumericUpDown Value="{Binding TareWeightInput, UpdateSourceTrigger=PropertyChanged}"
Minimum="0" Minimum="0"
DecimalPlaces="2" DecimalPlaces="2"
Style="{StaticResource NumericUpDownPlus}" Style="{StaticResource NumericUpDownPlus}"
@@ -170,17 +170,18 @@
Margin="0,0,0,16"/> Margin="0,0,0,16"/>
</hc:Col> </hc:Col>
<!-- 净重(只读 --> <!-- 净重(自动:毛重-皮重 -->
<hc:Col Span="12"> <hc:Col Span="12">
<hc:NumericUpDown Value="{Binding Record.NetWeight}" <hc:NumericUpDown Value="{Binding NetWeightInput, Mode=OneWay}"
Minimum="0" Minimum="0"
DecimalPlaces="2" DecimalPlaces="2"
Style="{StaticResource NumericUpDownPlus}" Style="{StaticResource NumericUpDownPlus}"
IsEnabled="True" IsReadOnly="True"
IsEnabled="False"
hc:InfoElement.Title="净重(KG)" hc:InfoElement.Title="净重(KG)"
hc:InfoElement.TitleWidth="80" hc:InfoElement.TitleWidth="80"
hc:InfoElement.TitlePlacement="Left" hc:InfoElement.TitlePlacement="Left"
hc:InfoElement.Placeholder="自动计算" hc:InfoElement.Placeholder="毛重-皮重自动计算"
Margin="0,0,0,16"/> Margin="0,0,0,16"/>
</hc:Col> </hc:Col>