新增混炼示方生成预览与批量创建功能,优化相关字段及用户交互,修复界面显示问题,增强系统稳定性和用户体验。
This commit is contained in:
@@ -132,3 +132,60 @@ jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/MesXslMixingSpec.api.ts
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/MesXslMixingSpec.data.ts
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/MesXslMixingSpecList.vue
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/components/MesXslMixingSpecModal.vue
|
||||
|
||||
-- author:cursor---date:20260522--for: 【XSLMES-20260522-A33】新增混炼示方主表/明细字段交互优化 ---
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/MesXslMixingSpec.data.ts
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/components/MesXslMixingSpecModal.vue
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixerAction/components/MesXslMixerActionSelectModal.vue
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixerCondition/components/MesXslMixerConditionSelectModal.vue
|
||||
|
||||
-- author:cursor---date:20260522--for: 【XSLMES-20260522-A34】混炼示方动作/组合改为下拉选择 ---
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/MesXslMixingSpec.data.ts
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/components/MesXslMixingSpecModal.vue
|
||||
|
||||
-- author:cursor---date:20260522--for: 【XSLMES-20260522-A35】混炼示方动作/组合列常显下拉倒三角 ---
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/MesXslMixingSpec.data.ts
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/components/MesXslMixingSpecModal.vue
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/components/MesXslMixingStepSelectCell.vue
|
||||
|
||||
-- author:cursor---date:20260522--for: 【XSLMES-20260522-A38】F段明细加入最后一段B炼好胶(如三段用B2)+Q列配合剂 ---
|
||||
jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslFormulaSpecServiceImpl.java
|
||||
|
||||
-- author:cursor---date:20260522--for: 【XSLMES-20260522-A38】B2/Bn明细改为上一段胶料一条(B{n-1}+胶料名)+本段列配合剂 ---
|
||||
jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslFormulaSpecServiceImpl.java
|
||||
|
||||
-- author:cursor---date:20260522--for: 【XSLMES-20260522-A38】修复B2与B1相同:按列增量拼接并支持列2+非Q配合剂 ---
|
||||
jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslFormulaSpecServiceImpl.java
|
||||
jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslFormulaMixingGenerateRowVO.java
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/components/MesXslFormulaGenerateMixingModal.vue
|
||||
|
||||
-- author:cursor---date:20260522--for: 【XSLMES-20260522-A38】生成混炼示方B段改为Bn=B(n-1)+第n列有值配合剂增量拼接 ---
|
||||
jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslFormulaSpecServiceImpl.java
|
||||
|
||||
-- author:cursor---date:20260522--for: 【XSLMES-20260522-A38】生成混炼示方明细种类按分类字典is_rubber显示胶料或小类名 ---
|
||||
jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslFormulaSpecServiceImpl.java
|
||||
|
||||
-- author:cursor---date:20260522--for: 【XSLMES-20260522-A38】生成混炼示方编号原样追加胶料代号中胶料名称后的后缀 ---
|
||||
jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslFormulaSpecServiceImpl.java
|
||||
|
||||
-- author:cursor---date:20260522--for: 【XSLMES-20260522-A38】生成混炼示方明细按STEP过滤:B段仅A物料、F段仅Q物料 ---
|
||||
jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslFormulaSpecServiceImpl.java
|
||||
|
||||
-- author:cursor---date:20260522--for: 【XSLMES-20260522-A38】配合示方生成混炼示方(预览段×机台批量创建) ---
|
||||
jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslFormulaMixingGenerate*.java
|
||||
jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslFormulaSpecService.java
|
||||
jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslFormulaSpecServiceImpl.java
|
||||
jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslFormulaSpecController.java
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/MesXslFormulaSpec.api.ts
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/MesXslFormulaSpecList.vue
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/components/MesXslFormulaSpecModal.vue
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpec/components/MesXslFormulaGenerateMixingModal.vue
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectConfig/components/MesXslEquipmentLedgerMultiSelectModal.vue
|
||||
|
||||
-- author:cursor---date:20260522--for: 【XSLMES-20260522-A36】混炼示方动作/组合下拉列表被表格裁切修复 ---
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/components/MesXslMixingStepSelectCell.vue
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/components/MesXslMixingSpecModal.vue
|
||||
|
||||
-- author:cursor---date:20260522--for: 【XSLMES-20260522-A37】未选机台点击动作/组合提示请先选择机台 ---
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/components/MesXslMixingStepSelectCell.vue
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/components/MesXslMixingSpecModal.vue
|
||||
|
||||
@@ -25,6 +25,8 @@ import org.jeecg.modules.xslmes.entity.MesXslFormulaSpec;
|
||||
import org.jeecg.modules.xslmes.entity.MesXslFormulaSpecLine;
|
||||
import org.jeecg.modules.xslmes.service.IMesXslFormulaSpecService;
|
||||
import org.jeecg.modules.xslmes.service.IMesXslFormulaSpecSettingService;
|
||||
import org.jeecg.modules.xslmes.vo.MesXslFormulaMixingGeneratePreviewVO;
|
||||
import org.jeecg.modules.xslmes.vo.MesXslFormulaMixingGenerateRequestVO;
|
||||
import org.jeecg.modules.xslmes.vo.MesXslFormulaRubberContentSettingVO;
|
||||
import org.jeecg.modules.xslmes.vo.MesXslFormulaSpecPage;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
@@ -173,6 +175,32 @@ public class MesXslFormulaSpecController extends JeecgController<MesXslFormulaSp
|
||||
}
|
||||
//update-end---author:cursor ---date:20260521 for:【配合示方】含胶率物料小类可配置-----------
|
||||
|
||||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A38】配合示方生成混炼示方-----------
|
||||
@Operation(summary = "MES配合示方-生成混炼示方预览")
|
||||
@GetMapping(value = "/buildMixingGeneratePreview")
|
||||
public Result<MesXslFormulaMixingGeneratePreviewVO> buildMixingGeneratePreview(
|
||||
@RequestParam(name = "formulaSpecId", required = true) String formulaSpecId) {
|
||||
try {
|
||||
return Result.OK(mesXslFormulaSpecService.buildMixingGeneratePreview(formulaSpecId));
|
||||
} catch (IllegalArgumentException ex) {
|
||||
return Result.error(ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@AutoLog(value = "MES配合示方-生成混炼示方")
|
||||
@Operation(summary = "MES配合示方-生成混炼示方")
|
||||
@RequiresPermissions("xslmes:mes_xsl_mixing_spec:add")
|
||||
@PostMapping(value = "/generateMixingSpec")
|
||||
public Result<Map<String, Object>> generateMixingSpec(@RequestBody MesXslFormulaMixingGenerateRequestVO request) {
|
||||
try {
|
||||
int count = mesXslFormulaSpecService.generateMixingSpecFromFormula(request);
|
||||
return Result.OK("成功生成 " + count + " 条混炼示方", Map.of("count", count));
|
||||
} catch (IllegalArgumentException ex) {
|
||||
return Result.error(ex.getMessage());
|
||||
}
|
||||
}
|
||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A38】配合示方生成混炼示方-----------
|
||||
|
||||
@RequiresPermissions("xslmes:mes_xsl_formula_spec:exportXls")
|
||||
@RequestMapping(value = "/exportXls")
|
||||
public ModelAndView exportXls(HttpServletRequest request, MesXslFormulaSpec model) {
|
||||
|
||||
@@ -75,8 +75,8 @@ public class MesXslMixingSpec implements Serializable {
|
||||
@Schema(description = "适用工厂")
|
||||
private String applyFactory;
|
||||
|
||||
@Schema(description = "段数")
|
||||
private Integer stageCount;
|
||||
@Schema(description = "段数(当前/总,如2/3)")
|
||||
private String stageCount;
|
||||
|
||||
@Schema(description = "纯混炼时间(秒)")
|
||||
private Integer pureMixSec;
|
||||
|
||||
@@ -7,6 +7,8 @@ import java.util.List;
|
||||
import org.jeecg.modules.xslmes.entity.MesXslFormulaSpec;
|
||||
import org.jeecg.modules.xslmes.entity.MesXslFormulaSpecLine;
|
||||
import org.jeecg.modules.xslmes.entity.MesXslMixerPsCompile;
|
||||
import org.jeecg.modules.xslmes.vo.MesXslFormulaMixingGeneratePreviewVO;
|
||||
import org.jeecg.modules.xslmes.vo.MesXslFormulaMixingGenerateRequestVO;
|
||||
|
||||
public interface IMesXslFormulaSpecService extends IService<MesXslFormulaSpec> {
|
||||
|
||||
@@ -36,4 +38,18 @@ public interface IMesXslFormulaSpecService extends IService<MesXslFormulaSpec> {
|
||||
*/
|
||||
void syncFromMixerPsWorkflow(MesXslMixerPsCompile ps, String mixerPsTargetStatus);
|
||||
//update-end---author:cursor ---date:20260522 for:【配合示方】密炼PS审批联动同步状态与审批人-----------
|
||||
|
||||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A38】配合示方生成混炼示方预览与批量创建-----------
|
||||
/**
|
||||
* 根据配合示方混合段数构建生成混炼示方预览行(示方编号 + 段信息)
|
||||
*/
|
||||
MesXslFormulaMixingGeneratePreviewVO buildMixingGeneratePreview(String formulaSpecId);
|
||||
|
||||
/**
|
||||
* 按预览行×机台批量生成混炼示方(含橡胶及配合剂明细)
|
||||
*
|
||||
* @return 成功生成的混炼示方条数
|
||||
*/
|
||||
int generateMixingSpecFromFormula(MesXslFormulaMixingGenerateRequestVO request);
|
||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A38】配合示方生成混炼示方预览与批量创建-----------
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import jakarta.annotation.Resource;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
@@ -14,6 +15,8 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.time.LocalDate;
|
||||
import java.time.ZoneId;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@@ -22,13 +25,23 @@ import org.jeecg.modules.mes.material.entity.MesMixerMaterial;
|
||||
import org.jeecg.modules.mes.material.service.IMesMaterialService;
|
||||
import org.jeecg.modules.mes.material.service.IMesMixerMaterialService;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.modules.system.entity.SysCategory;
|
||||
import org.jeecg.modules.system.service.ISysCategoryService;
|
||||
import org.jeecg.modules.xslmes.entity.MesXslFormulaSpec;
|
||||
import org.jeecg.modules.xslmes.entity.MesXslFormulaSpecLine;
|
||||
import org.jeecg.modules.xslmes.entity.MesXslMixerPsCompile;
|
||||
import org.jeecg.modules.xslmes.entity.MesXslMixingSpec;
|
||||
import org.jeecg.modules.xslmes.entity.MesXslMixingSpecMaterial;
|
||||
import org.jeecg.modules.xslmes.mapper.MesXslFormulaSpecLineMapper;
|
||||
import org.jeecg.modules.xslmes.mapper.MesXslFormulaSpecMapper;
|
||||
import org.jeecg.modules.xslmes.service.IMesXslFormulaSpecService;
|
||||
import org.jeecg.modules.xslmes.service.IMesXslFormulaSpecSettingService;
|
||||
import org.jeecg.modules.xslmes.service.IMesXslMixingSpecService;
|
||||
import org.jeecg.modules.xslmes.vo.MesXslFormulaMixingGenerateMachineVO;
|
||||
import org.jeecg.modules.xslmes.vo.MesXslFormulaMixingGeneratePreviewItemVO;
|
||||
import org.jeecg.modules.xslmes.vo.MesXslFormulaMixingGeneratePreviewVO;
|
||||
import org.jeecg.modules.xslmes.vo.MesXslFormulaMixingGenerateRequestVO;
|
||||
import org.jeecg.modules.xslmes.vo.MesXslFormulaMixingGenerateRowVO;
|
||||
import org.jeecg.modules.system.entity.SysUser;
|
||||
import org.jeecg.modules.system.service.ISysUserService;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -57,6 +70,12 @@ public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecM
|
||||
@Resource
|
||||
private ISysUserService sysUserService;
|
||||
|
||||
@Resource
|
||||
private IMesXslMixingSpecService mesXslMixingSpecService;
|
||||
|
||||
@Resource
|
||||
private ISysCategoryService sysCategoryService;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void saveMain(MesXslFormulaSpec main, List<MesXslFormulaSpecLine> lineList) {
|
||||
@@ -434,4 +453,488 @@ public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecM
|
||||
this.update(wrapper);
|
||||
}
|
||||
//update-end---author:cursor ---date:20260522 for:【配合示方】密炼PS审批联动同步状态与审批人-----------
|
||||
|
||||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A38】配合示方生成混炼示方预览与批量创建-----------
|
||||
@Override
|
||||
public MesXslFormulaMixingGeneratePreviewVO buildMixingGeneratePreview(String formulaSpecId) {
|
||||
MesXslFormulaSpec main = getByIdWithLines(formulaSpecId);
|
||||
if (main == null) {
|
||||
throw new IllegalArgumentException("未找到配合示方数据");
|
||||
}
|
||||
int stageCount = normalizeMixingStages(main.getMixingStages());
|
||||
if (stageCount <= 0) {
|
||||
throw new IllegalArgumentException("请先维护混合段数");
|
||||
}
|
||||
String rubberName = resolveRubberName(main);
|
||||
String formulaCodeSuffix = resolveFormulaCodeSuffix(main);
|
||||
boolean hasQ = hasStepQ(main.getLineList());
|
||||
List<MesXslFormulaMixingGeneratePreviewItemVO> items = new ArrayList<>();
|
||||
int aIndex = 0;
|
||||
for (int i = 1; i <= stageCount; i++) {
|
||||
boolean isQSegment = hasQ && i == stageCount;
|
||||
MesXslFormulaMixingGeneratePreviewItemVO item = new MesXslFormulaMixingGeneratePreviewItemVO();
|
||||
item.setRowKey(i);
|
||||
item.setStageIndex(i);
|
||||
if (isQSegment) {
|
||||
item.setStepType("Q");
|
||||
item.setSpecCode(appendFormulaCodeSuffix("F" + rubberName, formulaCodeSuffix));
|
||||
item.setASegmentIndex(null);
|
||||
} else {
|
||||
aIndex++;
|
||||
item.setStepType("A");
|
||||
item.setASegmentIndex(aIndex);
|
||||
item.setSpecCode(appendFormulaCodeSuffix("B" + aIndex + rubberName, formulaCodeSuffix));
|
||||
}
|
||||
items.add(item);
|
||||
}
|
||||
MesXslFormulaMixingGeneratePreviewVO preview = new MesXslFormulaMixingGeneratePreviewVO();
|
||||
preview.setFormulaSpecId(formulaSpecId);
|
||||
preview.setRubberName(rubberName);
|
||||
preview.setMixingStages(stageCount);
|
||||
preview.setItems(items);
|
||||
return preview;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public int generateMixingSpecFromFormula(MesXslFormulaMixingGenerateRequestVO request) {
|
||||
if (request == null || oConvertUtils.isEmpty(request.getFormulaSpecId())) {
|
||||
throw new IllegalArgumentException("配合示方ID不能为空");
|
||||
}
|
||||
if (CollectionUtils.isEmpty(request.getRows())) {
|
||||
throw new IllegalArgumentException("请至少配置一行示方与机台");
|
||||
}
|
||||
MesXslFormulaSpec formula = getByIdWithLines(request.getFormulaSpecId());
|
||||
if (formula == null) {
|
||||
throw new IllegalArgumentException("未找到配合示方数据");
|
||||
}
|
||||
List<MesXslFormulaSpecLine> lines = formula.getLineList();
|
||||
if (CollectionUtils.isEmpty(lines)) {
|
||||
throw new IllegalArgumentException("配合示方明细为空,无法生成混炼示方");
|
||||
}
|
||||
Map<String, MesMixerMaterial> mixerCache = new HashMap<>();
|
||||
Map<String, String> categoryNameCache = new HashMap<>();
|
||||
Map<String, Boolean> categoryRubberCache = new HashMap<>();
|
||||
int created = 0;
|
||||
int totalStages = normalizeMixingStages(formula.getMixingStages());
|
||||
Date today = Date.from(LocalDate.now().atStartOfDay(ZoneId.systemDefault()).toInstant());
|
||||
for (MesXslFormulaMixingGenerateRowVO row : request.getRows()) {
|
||||
if (row == null || oConvertUtils.isEmpty(row.getSpecCode()) || row.getStageIndex() == null) {
|
||||
continue;
|
||||
}
|
||||
if (CollectionUtils.isEmpty(row.getMachines())) {
|
||||
throw new IllegalArgumentException("示方「" + row.getSpecCode() + "」请至少选择一个机台");
|
||||
}
|
||||
String materialStep = resolveMixingMaterialStep(row);
|
||||
int mixingColumn = resolveMixingColumn(row, formula);
|
||||
List<MesXslMixingSpecMaterial> materials = buildMixingMaterials(
|
||||
formula, lines, mixingColumn, materialStep, mixerCache, categoryNameCache, categoryRubberCache);
|
||||
for (MesXslFormulaMixingGenerateMachineVO machine : row.getMachines()) {
|
||||
if (machine == null || oConvertUtils.isEmpty(machine.getMachineId())) {
|
||||
continue;
|
||||
}
|
||||
MesXslMixingSpec mixing = new MesXslMixingSpec();
|
||||
mixing.setSpecName(row.getSpecCode());
|
||||
mixing.setPurpose(formula.getPurpose());
|
||||
mixing.setIssueNumber(formula.getIssueNumber());
|
||||
mixing.setMachineId(machine.getMachineId());
|
||||
mixing.setMachineName(machine.getMachineName());
|
||||
mixing.setMakeDate(today);
|
||||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A40】生成时写入段数当前/总如2/3-----------
|
||||
if (row.getStageIndex() != null && totalStages > 0) {
|
||||
mixing.setStageCount(row.getStageIndex() + "/" + totalStages);
|
||||
} else if (row.getStageIndex() != null) {
|
||||
mixing.setStageCount(String.valueOf(row.getStageIndex()));
|
||||
}
|
||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A40】生成时写入段数当前/总如2/3-----------
|
||||
if ("Q".equalsIgnoreCase(row.getStepType())) {
|
||||
mixing.setFinalRubberSg(formula.getQRubberSg());
|
||||
} else {
|
||||
mixing.setMotherRubberSg(formula.getARubberSg());
|
||||
}
|
||||
mesXslMixingSpecService.saveMain(mixing, materials, null, null, null);
|
||||
created++;
|
||||
}
|
||||
}
|
||||
if (created <= 0) {
|
||||
throw new IllegalArgumentException("未生成任何混炼示方,请检查机台配置");
|
||||
}
|
||||
return created;
|
||||
}
|
||||
|
||||
private int normalizeMixingStages(Integer mixingStages) {
|
||||
if (mixingStages == null || mixingStages <= 0) {
|
||||
return 0;
|
||||
}
|
||||
return Math.min(mixingStages, 7);
|
||||
}
|
||||
|
||||
private String resolveRubberName(MesXslFormulaSpec main) {
|
||||
if (StringUtils.isNotBlank(main.getBasicFormula())) {
|
||||
return main.getBasicFormula().trim();
|
||||
}
|
||||
if (StringUtils.isNotBlank(main.getRubberMaterialId())) {
|
||||
MesMaterial rubber = mesMaterialService.getById(main.getRubberMaterialId());
|
||||
if (rubber != null && StringUtils.isNotBlank(rubber.getMaterialName())) {
|
||||
return rubber.getMaterialName().trim();
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 配合示方胶料代号/示方编号中,胶料名称之后的后缀原样截取(如 SA01、SB01 等,不做固定拼接)。
|
||||
*/
|
||||
private String resolveFormulaCodeSuffix(MesXslFormulaSpec main) {
|
||||
if (main == null) {
|
||||
return "";
|
||||
}
|
||||
String code = StringUtils.isNotBlank(main.getRubberCode()) ? main.getRubberCode().trim() : "";
|
||||
if (StringUtils.isBlank(code) && StringUtils.isNotBlank(main.getSpecCode())) {
|
||||
code = main.getSpecCode().trim();
|
||||
}
|
||||
if (StringUtils.isBlank(code)) {
|
||||
return "";
|
||||
}
|
||||
String rubberName = resolveRubberName(main);
|
||||
if (StringUtils.isBlank(rubberName)) {
|
||||
return "";
|
||||
}
|
||||
int nameIndex = code.indexOf(rubberName);
|
||||
if (nameIndex >= 0 && nameIndex + rubberName.length() < code.length()) {
|
||||
return code.substring(nameIndex + rubberName.length());
|
||||
}
|
||||
String dNamePrefix = "D" + rubberName;
|
||||
if (code.startsWith(dNamePrefix) && code.length() > dNamePrefix.length()) {
|
||||
return code.substring(dNamePrefix.length());
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private String appendFormulaCodeSuffix(String baseSpecCode, String formulaCodeSuffix) {
|
||||
if (StringUtils.isBlank(baseSpecCode)) {
|
||||
return baseSpecCode;
|
||||
}
|
||||
if (StringUtils.isBlank(formulaCodeSuffix)) {
|
||||
return baseSpecCode;
|
||||
}
|
||||
return baseSpecCode + formulaCodeSuffix;
|
||||
}
|
||||
|
||||
private boolean hasStepQ(List<MesXslFormulaSpecLine> lines) {
|
||||
if (CollectionUtils.isEmpty(lines)) {
|
||||
return false;
|
||||
}
|
||||
for (MesXslFormulaSpecLine line : lines) {
|
||||
if (line != null && "Q".equalsIgnoreCase(line.getStep())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** 解析 B/F 段对应的配合示方混合段列号 */
|
||||
private int resolveMixingColumn(MesXslFormulaMixingGenerateRowVO row, MesXslFormulaSpec formula) {
|
||||
if ("Q".equalsIgnoreCase(resolveMixingMaterialStep(row))) {
|
||||
Integer stages = formula != null ? formula.getMixingStages() : null;
|
||||
if (stages != null && stages > 0) {
|
||||
return Math.min(stages, 7);
|
||||
}
|
||||
}
|
||||
if (row != null && row.getASegmentIndex() != null && row.getASegmentIndex() > 0) {
|
||||
return Math.min(row.getASegmentIndex(), 7);
|
||||
}
|
||||
if (row != null && row.getStageIndex() != null && row.getStageIndex() > 0) {
|
||||
return Math.min(row.getStageIndex(), 7);
|
||||
}
|
||||
String specCode = row != null ? row.getSpecCode() : null;
|
||||
if (StringUtils.isNotBlank(specCode)) {
|
||||
Matcher matcher = Pattern.compile("(?i)B(\\d+)").matcher(specCode.trim());
|
||||
if (matcher.find()) {
|
||||
return Math.min(Integer.parseInt(matcher.group(1)), 7);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* B1=第一段配合剂(列1 STEP=A);Bn(n>1)=上一段胶料示方一条(B{n-1}+胶料名)+本段列n配合剂。
|
||||
* F 段=最后一段B炼好胶一条(如三段时B2+胶料名)+本列 STEP=Q 配合剂。
|
||||
*/
|
||||
private String resolveMixingMaterialStep(MesXslFormulaMixingGenerateRowVO row) {
|
||||
if (row != null && StringUtils.isNotBlank(row.getStepType())) {
|
||||
return row.getStepType().trim().toUpperCase();
|
||||
}
|
||||
String specCode = row != null ? row.getSpecCode() : null;
|
||||
if (StringUtils.isNotBlank(specCode) && specCode.trim().toUpperCase().startsWith("F")) {
|
||||
return "Q";
|
||||
}
|
||||
return "A";
|
||||
}
|
||||
|
||||
private List<MesXslMixingSpecMaterial> buildMixingMaterials(
|
||||
MesXslFormulaSpec formula,
|
||||
List<MesXslFormulaSpecLine> lines,
|
||||
int stageIndex,
|
||||
String materialStep,
|
||||
Map<String, MesMixerMaterial> mixerCache,
|
||||
Map<String, String> categoryNameCache,
|
||||
Map<String, Boolean> categoryRubberCache) {
|
||||
String stepFilter = StringUtils.isNotBlank(materialStep) ? materialStep.trim().toUpperCase() : "A";
|
||||
List<MesXslMixingSpecMaterial> materials = new ArrayList<>();
|
||||
int sort = 0;
|
||||
if ("Q".equals(stepFilter)) {
|
||||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A38】F段加入最后一段B炼好胶料一条再加Q配合剂-----------
|
||||
String rubberName = resolveRubberName(formula);
|
||||
String codeSuffix = resolveFormulaCodeSuffix(formula);
|
||||
int lastBSegment = resolveLastBSegmentIndex(formula, lines);
|
||||
if (lastBSegment > 0) {
|
||||
String motherSpecCode = appendFormulaCodeSuffix("B" + lastBSegment + rubberName, codeSuffix);
|
||||
BigDecimal motherWeight = resolveStageCumulativeTotal(formula, lines, lastBSegment);
|
||||
materials.add(createMotherRubberMaterial(motherSpecCode, rubberName, motherWeight, materials.size()));
|
||||
}
|
||||
appendQStageColumnAgents(lines, stageIndex, materials, mixerCache, categoryNameCache, categoryRubberCache);
|
||||
reindexMaterialSortNo(materials);
|
||||
return materials;
|
||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A38】F段加入最后一段B炼好胶料一条再加Q配合剂-----------
|
||||
}
|
||||
int bColumn = Math.max(stageIndex, 1);
|
||||
String rubberName = resolveRubberName(formula);
|
||||
String codeSuffix = resolveFormulaCodeSuffix(formula);
|
||||
if (bColumn <= 1) {
|
||||
appendBStageColumnAgents(lines, 1, materials, mixerCache, categoryNameCache, categoryRubberCache);
|
||||
reindexMaterialSortNo(materials);
|
||||
return materials;
|
||||
}
|
||||
// B2/B3…:上一段炼好胶料一条(如 B1+胶料名) + 本段列配合剂
|
||||
int prevB = bColumn - 1;
|
||||
String motherSpecCode = appendFormulaCodeSuffix("B" + prevB + rubberName, codeSuffix);
|
||||
BigDecimal motherWeight = resolveStageCumulativeTotal(formula, lines, prevB);
|
||||
materials.add(createMotherRubberMaterial(motherSpecCode, rubberName, motherWeight, materials.size()));
|
||||
appendBStageColumnAgents(lines, bColumn, materials, mixerCache, categoryNameCache, categoryRubberCache);
|
||||
reindexMaterialSortNo(materials);
|
||||
return materials;
|
||||
}
|
||||
|
||||
/** 含 Q 时最后一段 B 的段号(如混合段3段则最后 B 为 B2) */
|
||||
private int resolveLastBSegmentIndex(MesXslFormulaSpec formula, List<MesXslFormulaSpecLine> lines) {
|
||||
int stageCount = normalizeMixingStages(formula != null ? formula.getMixingStages() : null);
|
||||
if (stageCount <= 0 || !hasStepQ(lines)) {
|
||||
return 0;
|
||||
}
|
||||
return stageCount > 1 ? stageCount - 1 : 0;
|
||||
}
|
||||
|
||||
/** F 段本列:STEP=Q 且该列有数值的配合剂 */
|
||||
private void appendQStageColumnAgents(
|
||||
List<MesXslFormulaSpecLine> lines,
|
||||
int column,
|
||||
List<MesXslMixingSpecMaterial> materials,
|
||||
Map<String, MesMixerMaterial> mixerCache,
|
||||
Map<String, String> categoryNameCache,
|
||||
Map<String, Boolean> categoryRubberCache) {
|
||||
for (MesXslFormulaSpecLine line : lines) {
|
||||
if (!isLineStep(line, "Q")) {
|
||||
continue;
|
||||
}
|
||||
BigDecimal unitWeight = readStageValue(line, column);
|
||||
if (!hasStageNumericValue(unitWeight)) {
|
||||
continue;
|
||||
}
|
||||
materials.add(
|
||||
toMixingMaterial(line, unitWeight, materials.size(), mixerCache, categoryNameCache, categoryRubberCache));
|
||||
}
|
||||
}
|
||||
|
||||
/** 本段列:STEP=A 且该列有数值的配合剂 */
|
||||
private void appendBStageColumnAgents(
|
||||
List<MesXslFormulaSpecLine> lines,
|
||||
int column,
|
||||
List<MesXslMixingSpecMaterial> materials,
|
||||
Map<String, MesMixerMaterial> mixerCache,
|
||||
Map<String, String> categoryNameCache,
|
||||
Map<String, Boolean> categoryRubberCache) {
|
||||
for (MesXslFormulaSpecLine line : lines) {
|
||||
if (!isLineStep(line, "A")) {
|
||||
continue;
|
||||
}
|
||||
BigDecimal unitWeight = resolveBColumnUnitWeight(line, column);
|
||||
if (!hasStageNumericValue(unitWeight)) {
|
||||
continue;
|
||||
}
|
||||
materials.add(
|
||||
toMixingMaterial(line, unitWeight, materials.size(), mixerCache, categoryNameCache, categoryRubberCache));
|
||||
}
|
||||
}
|
||||
|
||||
/** 上一段密炼产出胶料(一条):示方编号 B{n-1}+胶料名,种类=胶料 */
|
||||
private MesXslMixingSpecMaterial createMotherRubberMaterial(
|
||||
String motherSpecCode, String rubberName, BigDecimal unitWeight, int sortNo) {
|
||||
MesXslMixingSpecMaterial material = new MesXslMixingSpecMaterial();
|
||||
material.setSortNo(sortNo);
|
||||
material.setMixerMaterialName(motherSpecCode);
|
||||
material.setMixerMaterialDesc(StringUtils.isNotBlank(rubberName) ? rubberName : motherSpecCode);
|
||||
material.setMaterialKind("胶料");
|
||||
material.setUnitWeight(unitWeight);
|
||||
return material;
|
||||
}
|
||||
|
||||
/** 混合段累计合计:优先主表 stageNTotal,否则按明细该列求和 */
|
||||
private BigDecimal resolveStageCumulativeTotal(MesXslFormulaSpec formula, List<MesXslFormulaSpecLine> lines, int column) {
|
||||
BigDecimal fromMain = readStageTotalFromMain(formula, column);
|
||||
if (hasStageNumericValue(fromMain)) {
|
||||
return fromMain;
|
||||
}
|
||||
BigDecimal sum = BigDecimal.ZERO;
|
||||
boolean hasAny = false;
|
||||
for (MesXslFormulaSpecLine line : lines) {
|
||||
if (line == null) {
|
||||
continue;
|
||||
}
|
||||
BigDecimal w = readStageValue(line, column);
|
||||
if (!hasStageNumericValue(w)) {
|
||||
continue;
|
||||
}
|
||||
sum = sum.add(w);
|
||||
hasAny = true;
|
||||
}
|
||||
return hasAny ? sum : null;
|
||||
}
|
||||
|
||||
private BigDecimal readStageTotalFromMain(MesXslFormulaSpec formula, int column) {
|
||||
if (formula == null || column < 1 || column > 7) {
|
||||
return null;
|
||||
}
|
||||
return switch (column) {
|
||||
case 1 -> formula.getStage1Total();
|
||||
case 2 -> formula.getStage2Total();
|
||||
case 3 -> formula.getStage3Total();
|
||||
case 4 -> formula.getStage4Total();
|
||||
case 5 -> formula.getStage5Total();
|
||||
case 6 -> formula.getStage6Total();
|
||||
case 7 -> formula.getStage7Total();
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
/** B 段单重:优先取当前列;第1列 STEP=A 可回退 PHR */
|
||||
private BigDecimal resolveBColumnUnitWeight(MesXslFormulaSpecLine line, int column) {
|
||||
BigDecimal weight = readStageValue(line, column);
|
||||
if (hasStageNumericValue(weight)) {
|
||||
return weight;
|
||||
}
|
||||
if (column == 1 && isLineStep(line, "A") && line.getPhr() != null) {
|
||||
return line.getPhr();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void reindexMaterialSortNo(List<MesXslMixingSpecMaterial> materials) {
|
||||
for (int i = 0; i < materials.size(); i++) {
|
||||
materials.get(i).setSortNo(i);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isLineStep(MesXslFormulaSpecLine line, String step) {
|
||||
if (line == null || StringUtils.isBlank(step)) {
|
||||
return false;
|
||||
}
|
||||
String lineStep = StringUtils.isNotBlank(line.getStep()) ? line.getStep().trim().toUpperCase() : "";
|
||||
return step.equalsIgnoreCase(lineStep);
|
||||
}
|
||||
|
||||
/** 混合段列是否有有效数值(非空且非 0) */
|
||||
private boolean hasStageNumericValue(BigDecimal value) {
|
||||
return value != null && value.compareTo(BigDecimal.ZERO) != 0;
|
||||
}
|
||||
|
||||
private MesXslMixingSpecMaterial toMixingMaterial(
|
||||
MesXslFormulaSpecLine line,
|
||||
BigDecimal unitWeight,
|
||||
int sortNo,
|
||||
Map<String, MesMixerMaterial> mixerCache,
|
||||
Map<String, String> categoryNameCache,
|
||||
Map<String, Boolean> categoryRubberCache) {
|
||||
MesXslMixingSpecMaterial material = new MesXslMixingSpecMaterial();
|
||||
material.setSortNo(sortNo);
|
||||
material.setMixerMaterialName(line.getMixerMaterialName());
|
||||
material.setMixerMaterialDesc(
|
||||
StringUtils.isNotBlank(line.getMaterialDesc()) ? line.getMaterialDesc() : line.getMixerMaterialName());
|
||||
material.setUnitWeight(unitWeight);
|
||||
fillMaterialCategory(material, line.getMixerMaterialId(), mixerCache, categoryNameCache, categoryRubberCache);
|
||||
return material;
|
||||
}
|
||||
|
||||
private BigDecimal readStageValue(MesXslFormulaSpecLine line, int stageIndex) {
|
||||
if (line == null || stageIndex < 1 || stageIndex > 7) {
|
||||
return null;
|
||||
}
|
||||
return switch (stageIndex) {
|
||||
case 1 -> line.getStage1();
|
||||
case 2 -> line.getStage2();
|
||||
case 3 -> line.getStage3();
|
||||
case 4 -> line.getStage4();
|
||||
case 5 -> line.getStage5();
|
||||
case 6 -> line.getStage6();
|
||||
case 7 -> line.getStage7();
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
private void fillMaterialCategory(
|
||||
MesXslMixingSpecMaterial material,
|
||||
String mixerMaterialId,
|
||||
Map<String, MesMixerMaterial> mixerCache,
|
||||
Map<String, String> categoryNameCache,
|
||||
Map<String, Boolean> categoryRubberCache) {
|
||||
if (oConvertUtils.isEmpty(mixerMaterialId)) {
|
||||
return;
|
||||
}
|
||||
MesMixerMaterial mixer = mixerCache.computeIfAbsent(mixerMaterialId, id -> mesMixerMaterialService.getById(id));
|
||||
if (mixer == null) {
|
||||
return;
|
||||
}
|
||||
String majorName = resolveCategoryName(mixer.getMajorCategoryId(), categoryNameCache);
|
||||
String minorName = resolveCategoryName(mixer.getMinorCategoryId(), categoryNameCache);
|
||||
material.setMaterialMajor(majorName);
|
||||
material.setMaterialMinor(minorName);
|
||||
material.setMaterialKind(resolveMixingMaterialKind(mixer.getMinorCategoryId(), minorName, categoryRubberCache));
|
||||
}
|
||||
|
||||
/**
|
||||
* 种类:物料小类在分类字典勾选「胶料」则显示「胶料」,否则显示小类分类名称。
|
||||
*/
|
||||
private String resolveMixingMaterialKind(
|
||||
String minorCategoryId, String minorCategoryName, Map<String, Boolean> categoryRubberCache) {
|
||||
if (isCategoryRubber(minorCategoryId, categoryRubberCache)) {
|
||||
return "胶料";
|
||||
}
|
||||
if (StringUtils.isNotBlank(minorCategoryName)) {
|
||||
return minorCategoryName;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isCategoryRubber(String categoryId, Map<String, Boolean> cache) {
|
||||
if (oConvertUtils.isEmpty(categoryId)) {
|
||||
return false;
|
||||
}
|
||||
return Boolean.TRUE.equals(cache.computeIfAbsent(categoryId, this::loadCategoryIsRubber));
|
||||
}
|
||||
|
||||
private Boolean loadCategoryIsRubber(String categoryId) {
|
||||
SysCategory category = sysCategoryService.getById(categoryId);
|
||||
return category != null && "1".equals(category.getIsRubber());
|
||||
}
|
||||
|
||||
private String resolveCategoryName(String categoryId, Map<String, String> cache) {
|
||||
if (oConvertUtils.isEmpty(categoryId)) {
|
||||
return null;
|
||||
}
|
||||
return cache.computeIfAbsent(categoryId, id -> {
|
||||
SysCategory category = sysCategoryService.getById(id);
|
||||
return category != null ? category.getName() : null;
|
||||
});
|
||||
}
|
||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A38】配合示方生成混炼示方预览与批量创建-----------
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package org.jeecg.modules.xslmes.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/** 生成混炼示方:机台 */
|
||||
@Data
|
||||
@Schema(description = "生成混炼示方机台")
|
||||
public class MesXslFormulaMixingGenerateMachineVO {
|
||||
|
||||
@Schema(description = "设备台账ID")
|
||||
private String machineId;
|
||||
|
||||
@Schema(description = "机台名称")
|
||||
private String machineName;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package org.jeecg.modules.xslmes.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/** 生成混炼示方:预览行 */
|
||||
@Data
|
||||
@Schema(description = "生成混炼示方预览行")
|
||||
public class MesXslFormulaMixingGeneratePreviewItemVO {
|
||||
|
||||
@Schema(description = "行键(段序号)")
|
||||
private Integer rowKey;
|
||||
|
||||
@Schema(description = "示方编号(规格)")
|
||||
private String specCode;
|
||||
|
||||
@Schema(description = "混合段序号 1-7")
|
||||
private Integer stageIndex;
|
||||
|
||||
@Schema(description = "段类型:A 或 Q")
|
||||
private String stepType;
|
||||
|
||||
@Schema(description = "A段序号(仅A段有值)")
|
||||
private Integer aSegmentIndex;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package org.jeecg.modules.xslmes.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import java.util.List;
|
||||
import lombok.Data;
|
||||
|
||||
/** 生成混炼示方:预览结果 */
|
||||
@Data
|
||||
@Schema(description = "生成混炼示方预览")
|
||||
public class MesXslFormulaMixingGeneratePreviewVO {
|
||||
|
||||
@Schema(description = "配合示方ID")
|
||||
private String formulaSpecId;
|
||||
|
||||
@Schema(description = "胶料名称")
|
||||
private String rubberName;
|
||||
|
||||
@Schema(description = "混合段数")
|
||||
private Integer mixingStages;
|
||||
|
||||
@Schema(description = "预览行")
|
||||
private List<MesXslFormulaMixingGeneratePreviewItemVO> items;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package org.jeecg.modules.xslmes.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import java.util.List;
|
||||
import lombok.Data;
|
||||
|
||||
/** 生成混炼示方:确认请求 */
|
||||
@Data
|
||||
@Schema(description = "生成混炼示方确认请求")
|
||||
public class MesXslFormulaMixingGenerateRequestVO {
|
||||
|
||||
@Schema(description = "配合示方ID")
|
||||
private String formulaSpecId;
|
||||
|
||||
@Schema(description = "确认行")
|
||||
private List<MesXslFormulaMixingGenerateRowVO> rows;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package org.jeecg.modules.xslmes.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import java.util.List;
|
||||
import lombok.Data;
|
||||
|
||||
/** 生成混炼示方:确认行(含机台) */
|
||||
@Data
|
||||
@Schema(description = "生成混炼示方确认行")
|
||||
public class MesXslFormulaMixingGenerateRowVO {
|
||||
|
||||
@Schema(description = "示方编号(规格)")
|
||||
private String specCode;
|
||||
|
||||
@Schema(description = "混合段序号 1-7")
|
||||
private Integer stageIndex;
|
||||
|
||||
@Schema(description = "A段序号(B1/B2…,仅A段有值)")
|
||||
private Integer aSegmentIndex;
|
||||
|
||||
@Schema(description = "段类型:A 或 Q")
|
||||
private String stepType;
|
||||
|
||||
@Schema(description = "机台列表")
|
||||
private List<MesXslFormulaMixingGenerateMachineVO> machines;
|
||||
}
|
||||
@@ -418,3 +418,11 @@ jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectRecord/MesXslEquipInspectRecor
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectRecord/MesXslEquipInspectRecordList.vue
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectRecord/components/MesXslEquipInspectRecordModal.vue
|
||||
jeecgboot-vue3/src/views/xslmes/mesXslEquipInspectRecord/components/MesXslEquipInspectRecordHandleModal.vue
|
||||
-- author:cursor---date:20260522--for: 【XSLMES-20260522-A31】分类字典原辅材料子类增加胶料标记字段 ---
|
||||
jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_99__sys_category_is_rubber.sql
|
||||
jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/entity/SysCategory.java
|
||||
jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysCategoryServiceImpl.java
|
||||
jeecgboot-vue3/src/views/system/category/category.constants.ts
|
||||
jeecgboot-vue3/src/views/system/category/category.data.ts
|
||||
jeecgboot-vue3/src/views/system/category/components/CategoryModal.vue
|
||||
jeecgboot-vue3/src/views/mes/material/modules/MesMixerMaterialSysCategoryModal.vue
|
||||
|
||||
@@ -49,6 +49,9 @@ public class SysCategory implements Serializable,Comparable<SysCategory>{
|
||||
/**是否有子节点*/
|
||||
@Excel(name = "是否有子节点(1:有)", width = 15)
|
||||
private java.lang.String hasChild;
|
||||
/**是否胶料(仅原辅材料子类有效) 1是/0否*/
|
||||
@Excel(name = "是否胶料", width = 15)
|
||||
private java.lang.String isRubber;
|
||||
|
||||
/**租户ID*/
|
||||
private java.lang.Integer tenantId;
|
||||
|
||||
@@ -29,6 +29,9 @@ import java.util.stream.Collectors;
|
||||
@Service
|
||||
public class SysCategoryServiceImpl extends ServiceImpl<SysCategoryMapper, SysCategory> implements ISysCategoryService {
|
||||
|
||||
/** 原辅材料分类编码(其子类可标记为胶料) */
|
||||
private static final String MATERIAL_RAW_AUX_CODE = "XSLMES_MATERIAL_RAW_AUX";
|
||||
|
||||
@Override
|
||||
public void addSysCategory(SysCategory sysCategory) {
|
||||
String categoryPid = ISysCategoryService.ROOT_PID_VALUE;
|
||||
@@ -64,6 +67,9 @@ public class SysCategoryServiceImpl extends ServiceImpl<SysCategoryMapper, SysCa
|
||||
sysCategory.setCode(customCode);
|
||||
}
|
||||
sysCategory.setPid(categoryPid);
|
||||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A31】原辅材料子类胶料标记归一化-----------
|
||||
normalizeIsRubber(sysCategory);
|
||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A31】原辅材料子类胶料标记归一化-----------
|
||||
baseMapper.insert(sysCategory);
|
||||
}
|
||||
|
||||
@@ -91,9 +97,35 @@ public class SysCategoryServiceImpl extends ServiceImpl<SysCategoryMapper, SysCa
|
||||
}
|
||||
sysCategory.setCode(newCode);
|
||||
}
|
||||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A31】原辅材料子类胶料标记归一化-----------
|
||||
normalizeIsRubber(sysCategory);
|
||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A31】原辅材料子类胶料标记归一化-----------
|
||||
baseMapper.updateById(sysCategory);
|
||||
}
|
||||
|
||||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A31】原辅材料子类胶料标记归一化-----------
|
||||
/**
|
||||
* 胶料标记仅对「原辅材料」直接子类生效,其余节点强制为 0。
|
||||
*/
|
||||
private void normalizeIsRubber(SysCategory sysCategory) {
|
||||
if (sysCategory == null) {
|
||||
return;
|
||||
}
|
||||
if (!"1".equals(sysCategory.getIsRubber())) {
|
||||
sysCategory.setIsRubber("0");
|
||||
return;
|
||||
}
|
||||
if (oConvertUtils.isEmpty(sysCategory.getPid()) || ISysCategoryService.ROOT_PID_VALUE.equals(sysCategory.getPid())) {
|
||||
sysCategory.setIsRubber("0");
|
||||
return;
|
||||
}
|
||||
SysCategory parent = baseMapper.selectById(sysCategory.getPid());
|
||||
if (parent == null || !MATERIAL_RAW_AUX_CODE.equals(parent.getCode())) {
|
||||
sysCategory.setIsRubber("0");
|
||||
}
|
||||
}
|
||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A31】原辅材料子类胶料标记归一化-----------
|
||||
|
||||
@Override
|
||||
public List<TreeSelectModel> queryListByCode(String pcode) throws JeecgBootException{
|
||||
String pid = ROOT_PID_VALUE;
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
-- 段数存「当前段/总段数」文本,如 2/3(不新增字段)
|
||||
ALTER TABLE `mes_xsl_mixing_spec`
|
||||
MODIFY COLUMN `stage_count` varchar(20) DEFAULT NULL COMMENT '段数(当前/总)';
|
||||
@@ -0,0 +1,4 @@
|
||||
-- 回退误加的 stage_count_total,并确保 stage_count 为 varchar
|
||||
ALTER TABLE `mes_xsl_mixing_spec` DROP COLUMN IF EXISTS `stage_count_total`;
|
||||
ALTER TABLE `mes_xsl_mixing_spec`
|
||||
MODIFY COLUMN `stage_count` varchar(20) DEFAULT NULL COMMENT '段数(当前/总)';
|
||||
@@ -0,0 +1,20 @@
|
||||
-- 分类字典:原辅材料子类增加「胶料」标记字段(幂等)
|
||||
SET NAMES utf8mb4;
|
||||
|
||||
SET @db = DATABASE();
|
||||
|
||||
SET @sql = IF(
|
||||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'sys_category' AND COLUMN_NAME = 'is_rubber') = 0,
|
||||
'ALTER TABLE `sys_category` ADD COLUMN `is_rubber` varchar(1) DEFAULT ''0'' COMMENT ''是否胶料 1是/0否'' AFTER `has_child`',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- 天然胶、合成胶、再生胶默认标记为胶料
|
||||
UPDATE `sys_category`
|
||||
SET `is_rubber` = '1', `update_by` = 'admin', `update_time` = NOW()
|
||||
WHERE `code` IN (
|
||||
'XSLMES_MATERIAL_RAW_AUX_TRJ',
|
||||
'XSLMES_MATERIAL_RAW_AUX_HCJ',
|
||||
'XSLMES_MATERIAL_RAW_AUX_ZSJ'
|
||||
);
|
||||
@@ -10,6 +10,13 @@ import { BasicModal, useModalInner } from '/@/components/Modal';
|
||||
import { BasicForm, useForm } from '/@/components/Form';
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
import { loadTreeData } from '/@/views/system/category/category.api';
|
||||
import {
|
||||
MATERIAL_RAW_AUX_CODE,
|
||||
materialRawAuxCategoryId,
|
||||
isMaterialRawAuxSubCategory,
|
||||
toIsRubberFlag,
|
||||
fromIsRubberFlag,
|
||||
} from '/@/views/system/category/category.constants';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import type { FormSchema } from '/@/components/Form';
|
||||
import type { Recordable } from '/@/types/global';
|
||||
@@ -34,6 +41,15 @@ const schemas: FormSchema[] = [
|
||||
required: true,
|
||||
componentProps: { maxlength: 50, placeholder: '请输入分类名称' },
|
||||
},
|
||||
{
|
||||
label: ' ',
|
||||
field: 'isRubber',
|
||||
component: 'Checkbox',
|
||||
defaultValue: false,
|
||||
renderComponentContent: '胶料',
|
||||
colProps: { span: 24 },
|
||||
ifShow: ({ values }) => isMaterialRawAuxSubCategory(values.pid),
|
||||
},
|
||||
];
|
||||
|
||||
const [registerForm, { resetFields, setFieldsValue, validate, updateSchema, scrollToField }] = useForm({
|
||||
@@ -64,10 +80,30 @@ async function buildPidTree(): Promise<Recordable[]> {
|
||||
];
|
||||
}
|
||||
|
||||
async function ensureMaterialRawAuxCategoryId() {
|
||||
if (materialRawAuxCategoryId.value) {
|
||||
return;
|
||||
}
|
||||
const res = await defHttp.get(
|
||||
{ url: '/sys/category/loadOne', params: { field: 'code', val: MATERIAL_RAW_AUX_CODE } },
|
||||
{ isTransformResponse: false },
|
||||
);
|
||||
if (res?.success && res?.result?.id) {
|
||||
materialRawAuxCategoryId.value = res.result.id;
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeSubmitValues(values: Recordable) {
|
||||
const payload = { ...values };
|
||||
payload.isRubber = isMaterialRawAuxSubCategory(payload.pid) ? toIsRubberFlag(payload.isRubber) : '0';
|
||||
return payload;
|
||||
}
|
||||
|
||||
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
|
||||
await resetFields();
|
||||
setModalProps({ confirmLoading: false });
|
||||
isUpdate.value = !!data?.isUpdate;
|
||||
await ensureMaterialRawAuxCategoryId();
|
||||
const tree = await buildPidTree();
|
||||
if (!tree.length) {
|
||||
createMessage.warning('未加载到物料分类树,请确认分类字典根编码 XSLMES_MATERIAL 已存在');
|
||||
@@ -89,7 +125,7 @@ const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data
|
||||
|
||||
if (unref(isUpdate) && data?.record?.id) {
|
||||
const cat = await defHttp.get<Recordable>({ url: '/sys/category/queryById', params: { id: data.record.id } });
|
||||
await setFieldsValue({ id: cat.id, pid: cat.pid, name: cat.name });
|
||||
await setFieldsValue({ id: cat.id, pid: cat.pid, name: cat.name, isRubber: fromIsRubberFlag(cat.isRubber) });
|
||||
} else {
|
||||
const pid = data?.parentId != null && data.parentId !== '' ? String(data.parentId) : '';
|
||||
await setFieldsValue({ pid: pid || undefined, name: '' });
|
||||
@@ -100,13 +136,13 @@ const title = computed(() => (unref(isUpdate) ? '编辑物料分类' : '新增
|
||||
|
||||
async function handleSubmit() {
|
||||
try {
|
||||
const values = await validate();
|
||||
const values = normalizeSubmitValues(await validate());
|
||||
setModalProps({ confirmLoading: true });
|
||||
if (unref(isUpdate)) {
|
||||
const full = await defHttp.get<Recordable>({ url: '/sys/category/queryById', params: { id: values.id } });
|
||||
await editMaterialSysCategory({ ...full, pid: values.pid, name: values.name });
|
||||
await editMaterialSysCategory({ ...full, pid: values.pid, name: values.name, isRubber: values.isRubber });
|
||||
} else {
|
||||
await saveMaterialSysCategory({ pid: values.pid, name: values.name });
|
||||
await saveMaterialSysCategory({ pid: values.pid, name: values.name, isRubber: values.isRubber });
|
||||
}
|
||||
closeModal();
|
||||
emit('success');
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import { ref } from 'vue';
|
||||
|
||||
/** MES 物料分类 - 原辅材料编码 */
|
||||
export const MATERIAL_RAW_AUX_CODE = 'XSLMES_MATERIAL_RAW_AUX';
|
||||
|
||||
/** 原辅材料分类节点 ID(运行时加载) */
|
||||
export const materialRawAuxCategoryId = ref('');
|
||||
|
||||
/** 是否为原辅材料的直接子类 */
|
||||
export function isMaterialRawAuxSubCategory(pid?: string) {
|
||||
return !!materialRawAuxCategoryId.value && pid === materialRawAuxCategoryId.value;
|
||||
}
|
||||
|
||||
/** 表单 Checkbox 布尔值 -> 数据库存储值 */
|
||||
export function toIsRubberFlag(value: unknown) {
|
||||
return value === true || value === '1' ? '1' : '0';
|
||||
}
|
||||
|
||||
/** 数据库存储值 -> 表单 Checkbox 布尔值 */
|
||||
export function fromIsRubberFlag(value: unknown) {
|
||||
return value === '1' || value === 1 || value === true;
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { BasicColumn } from '/@/components/Table';
|
||||
import { FormSchema } from '/@/components/Table';
|
||||
import { isMaterialRawAuxSubCategory } from './category.constants';
|
||||
|
||||
export const columns: BasicColumn[] = [
|
||||
{
|
||||
@@ -73,4 +74,13 @@ export const formSchema: FormSchema[] = [
|
||||
placeholder: '留空将按规则自动生成(如 A01.A02)',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: ' ',
|
||||
field: 'isRubber',
|
||||
component: 'Checkbox',
|
||||
defaultValue: false,
|
||||
renderComponentContent: '胶料',
|
||||
colProps: { span: 24 },
|
||||
show: ({ values }) => isMaterialRawAuxSubCategory(values.pid),
|
||||
},
|
||||
];
|
||||
|
||||
@@ -9,12 +9,40 @@
|
||||
import { BasicForm, useForm } from '/src/components/Form';
|
||||
import { formSchema } from '../category.data';
|
||||
import { loadTreeData, saveOrUpdateDict } from '../category.api';
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
import {
|
||||
MATERIAL_RAW_AUX_CODE,
|
||||
materialRawAuxCategoryId,
|
||||
isMaterialRawAuxSubCategory,
|
||||
toIsRubberFlag,
|
||||
fromIsRubberFlag,
|
||||
} from '../category.constants';
|
||||
import type { Recordable } from '/@/types/global';
|
||||
// 获取emit
|
||||
const emit = defineEmits(['register', 'success']);
|
||||
const isUpdate = ref(true);
|
||||
const expandedRowKeys = ref([]);
|
||||
const treeData = ref([]);
|
||||
const isSubAdd = ref(false);
|
||||
|
||||
async function ensureMaterialRawAuxCategoryId() {
|
||||
if (materialRawAuxCategoryId.value) {
|
||||
return;
|
||||
}
|
||||
const res = await defHttp.get(
|
||||
{ url: '/sys/category/loadOne', params: { field: 'code', val: MATERIAL_RAW_AUX_CODE } },
|
||||
{ isTransformResponse: false },
|
||||
);
|
||||
if (res?.success && res?.result?.id) {
|
||||
materialRawAuxCategoryId.value = res.result.id;
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeSubmitValues(values: Recordable) {
|
||||
const payload = { ...values };
|
||||
payload.isRubber = isMaterialRawAuxSubCategory(payload.pid) ? toIsRubberFlag(payload.isRubber) : '0';
|
||||
return payload;
|
||||
}
|
||||
//表单配置
|
||||
const [registerForm, { resetFields, setFieldsValue, validate, updateSchema }] = useForm({
|
||||
schemas: formSchema,
|
||||
@@ -35,12 +63,14 @@
|
||||
expandedRowKeys.value = [];
|
||||
setModalProps({ confirmLoading: false, minHeight: 80 });
|
||||
isUpdate.value = !!data?.isUpdate;
|
||||
await ensureMaterialRawAuxCategoryId();
|
||||
// 代码逻辑说明: 分类字典data.record为空报错------------
|
||||
isSubAdd.value = !data?.isUpdate && data.record && data.record.id;
|
||||
if (data?.record) {
|
||||
//表单赋值
|
||||
await setFieldsValue({
|
||||
...data.record,
|
||||
isRubber: fromIsRubberFlag(data.record.isRubber),
|
||||
});
|
||||
}
|
||||
//父级节点树信息
|
||||
@@ -76,6 +106,7 @@
|
||||
async function handleSubmit() {
|
||||
try {
|
||||
let values = await validate();
|
||||
values = normalizeSubmitValues(values);
|
||||
setModalProps({ confirmLoading: true });
|
||||
//提交表单
|
||||
await saveOrUpdateDict(values, isUpdate.value);
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
<template>
|
||||
<BasicModal v-bind="$attrs" title="选择机台(可多选)" :width="1000" @register="registerModal" @ok="handleOk">
|
||||
<BasicTable @register="registerTable" />
|
||||
</BasicModal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import { BasicModal, useModalInner } from '/@/components/Modal';
|
||||
import { BasicTable, useTable } from '/@/components/Table';
|
||||
import { list } from '/@/views/xslmes/mesXslEquipmentLedger/MesXslEquipmentLedger.api';
|
||||
|
||||
const emit = defineEmits(['register', 'select']);
|
||||
|
||||
const selectedRows = ref<Recordable[]>([]);
|
||||
|
||||
function handleSelectionChange(_keys: string[], rows: Recordable[]) {
|
||||
selectedRows.value = rows || [];
|
||||
}
|
||||
|
||||
const [registerTable, { reload, getSelectRows, setSelectedRowKeys, clearSelectedRowKeys }] = useTable({
|
||||
api: list,
|
||||
columns: [
|
||||
{ title: '设备名称', dataIndex: 'equipmentName', width: 160 },
|
||||
{ title: '设备编号', dataIndex: 'equipmentCode', width: 140 },
|
||||
{ title: '设备类别', dataIndex: 'equipmentCategoryName', width: 120 },
|
||||
{ title: '设备类型', dataIndex: 'equipmentTypeName', width: 120 },
|
||||
],
|
||||
rowKey: 'id',
|
||||
useSearchForm: true,
|
||||
formConfig: {
|
||||
labelWidth: 90,
|
||||
schemas: [
|
||||
{ label: '设备名称', field: 'equipmentName', component: 'Input', colProps: { span: 8 } },
|
||||
{ label: '设备编号', field: 'equipmentCode', component: 'Input', colProps: { span: 8 } },
|
||||
],
|
||||
},
|
||||
pagination: { pageSize: 10 },
|
||||
canResize: false,
|
||||
showIndexColumn: false,
|
||||
immediate: true,
|
||||
rowSelection: {
|
||||
type: 'checkbox',
|
||||
columnWidth: 48,
|
||||
onChange: handleSelectionChange,
|
||||
},
|
||||
clickToRowSelect: true,
|
||||
});
|
||||
|
||||
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
|
||||
selectedRows.value = [];
|
||||
clearSelectedRowKeys?.();
|
||||
setModalProps({ confirmLoading: false });
|
||||
const preset = (data?.selectedMachines || []) as Array<{ machineId?: string }>;
|
||||
const keys = preset.map((m) => m.machineId).filter(Boolean) as string[];
|
||||
if (keys.length) {
|
||||
setSelectedRowKeys?.(keys);
|
||||
}
|
||||
reload();
|
||||
});
|
||||
|
||||
async function handleOk() {
|
||||
const rows = ((getSelectRows?.() || []) as Recordable[]).length
|
||||
? (getSelectRows?.() || []) as Recordable[]
|
||||
: selectedRows.value;
|
||||
const machines = rows
|
||||
.filter((r) => r?.id)
|
||||
.map((r) => ({
|
||||
machineId: r.id,
|
||||
machineName: r.equipmentName || '',
|
||||
machineCode: r.equipmentCode || '',
|
||||
}));
|
||||
emit('select', machines);
|
||||
closeModal();
|
||||
}
|
||||
</script>
|
||||
@@ -14,6 +14,8 @@ enum Api {
|
||||
generateRubberCode = '/xslmes/mesXslFormulaSpec/generateRubberCode',
|
||||
getRubberContentSetting = '/xslmes/mesXslFormulaSpec/getRubberContentSetting',
|
||||
saveRubberContentSetting = '/xslmes/mesXslFormulaSpec/saveRubberContentSetting',
|
||||
buildMixingGeneratePreview = '/xslmes/mesXslFormulaSpec/buildMixingGeneratePreview',
|
||||
generateMixingSpec = '/xslmes/mesXslFormulaSpec/generateMixingSpec',
|
||||
}
|
||||
|
||||
export const getExportUrl = Api.exportXls;
|
||||
@@ -41,3 +43,9 @@ export const batchDelete = (params, handleSuccess) => {
|
||||
};
|
||||
|
||||
export const saveOrUpdate = (params, isUpdate) => defHttp.post({ url: isUpdate ? Api.edit : Api.save, params });
|
||||
|
||||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A38】配合示方生成混炼示方-----------
|
||||
export const buildMixingGeneratePreview = (params) =>
|
||||
defHttp.get({ url: Api.buildMixingGeneratePreview, params }, { successMessageMode: 'none' });
|
||||
export const generateMixingSpec = (params) => defHttp.post({ url: Api.generateMixingSpec, params });
|
||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A38】配合示方生成混炼示方-----------
|
||||
|
||||
@@ -36,27 +36,40 @@
|
||||
</a-button>
|
||||
</a-dropdown>
|
||||
<super-query :config="superQueryConfig" @search="handleSuperQuery" />
|
||||
<a-button
|
||||
type="primary"
|
||||
v-auth="'xslmes:mes_xsl_mixing_spec:add'"
|
||||
preIcon="ant-design:thunderbolt-outlined"
|
||||
@click="handleGenerateMixing"
|
||||
>
|
||||
生成混炼示方
|
||||
</a-button>
|
||||
</template>
|
||||
<template #action="{ record }">
|
||||
<TableAction :actions="getTableActions(record)" :dropDownActions="getDropDownAction(record)" />
|
||||
</template>
|
||||
</BasicTable>
|
||||
<MesXslFormulaSpecModal @register="registerModal" @success="handleSuccess" />
|
||||
<MesXslFormulaGenerateMixingModal @register="registerGenerateMixingModal" @success="handleGenerateMixingSuccess" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" name="xslmes-mesXslFormulaSpec" setup>
|
||||
import { reactive } from 'vue';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import { BasicTable, TableAction } from '/@/components/Table';
|
||||
import { useModal } from '/@/components/Modal';
|
||||
import { useListPage } from '/@/hooks/system/useListPage';
|
||||
import Icon from '/@/components/Icon';
|
||||
import MesXslFormulaSpecModal from './components/MesXslFormulaSpecModal.vue';
|
||||
import MesXslFormulaGenerateMixingModal from './components/MesXslFormulaGenerateMixingModal.vue';
|
||||
import { columns, searchFormSchema, superQuerySchema } from './MesXslFormulaSpec.data';
|
||||
import { list, deleteOne, batchDelete, getExportUrl, getImportUrl } from './MesXslFormulaSpec.api';
|
||||
|
||||
const { createMessage } = useMessage();
|
||||
const queryParam = reactive<any>({});
|
||||
const [registerModal, { openModal }] = useModal();
|
||||
const [registerGenerateMixingModal, { openModal: openGenerateMixingModal }] = useModal();
|
||||
|
||||
const { tableContext, onExportXls, onImportXls } = useListPage({
|
||||
tableProps: {
|
||||
@@ -125,6 +138,19 @@
|
||||
selectedRowKeys.value = [];
|
||||
}
|
||||
|
||||
function handleGenerateMixing() {
|
||||
const keys = selectedRowKeys.value || [];
|
||||
if (keys.length !== 1) {
|
||||
createMessage.warning('请勾选一条配合示方数据');
|
||||
return;
|
||||
}
|
||||
openGenerateMixingModal(true, { formulaSpecId: keys[0] });
|
||||
}
|
||||
|
||||
function handleGenerateMixingSuccess() {
|
||||
selectedRowKeys.value = [];
|
||||
}
|
||||
|
||||
function canEdit(record: Recordable) {
|
||||
return !record?.status || record.status === 'compile';
|
||||
}
|
||||
|
||||
@@ -0,0 +1,193 @@
|
||||
<template>
|
||||
<BasicModal
|
||||
v-bind="$attrs"
|
||||
title="生成混炼示方"
|
||||
:width="880"
|
||||
destroyOnClose
|
||||
@register="registerModal"
|
||||
@ok="handleConfirm"
|
||||
>
|
||||
<a-spin :spinning="loading">
|
||||
<div v-if="rubberName" class="generate-mixing-tip">
|
||||
胶料名称:<strong>{{ rubberName }}</strong>,混合段数:<strong>{{ mixingStages }}</strong>,确认后将按「预览行 × 机台」生成混炼示方。
|
||||
</div>
|
||||
<a-table
|
||||
:columns="tableColumns"
|
||||
:data-source="tableRows"
|
||||
:pagination="false"
|
||||
row-key="rowKey"
|
||||
size="small"
|
||||
bordered
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.dataIndex === 'machines'">
|
||||
<div class="machine-cell">
|
||||
<a-input
|
||||
:value="formatMachineNames(record.machines)"
|
||||
readonly
|
||||
placeholder="请点击选择机台(可多选)"
|
||||
class="machine-picker-input"
|
||||
@click="openMachinePicker(record)"
|
||||
/>
|
||||
<a-button type="link" size="small" @click="openMachinePicker(record)">选择</a-button>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
<div v-if="totalGenerateCount > 0" class="generate-mixing-summary">
|
||||
预计生成 <strong>{{ totalGenerateCount }}</strong> 条混炼示方
|
||||
</div>
|
||||
</a-spin>
|
||||
<MesXslEquipmentLedgerMultiSelectModal @register="registerMachineModal" @select="onMachineSelect" />
|
||||
</BasicModal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref } from 'vue';
|
||||
import { BasicModal, useModal, useModalInner } from '/@/components/Modal';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import MesXslEquipmentLedgerMultiSelectModal from '/@/views/xslmes/mesXslEquipInspectConfig/components/MesXslEquipmentLedgerMultiSelectModal.vue';
|
||||
import { buildMixingGeneratePreview, generateMixingSpec } from '../MesXslFormulaSpec.api';
|
||||
|
||||
const emit = defineEmits(['register', 'success']);
|
||||
|
||||
const { createMessage } = useMessage();
|
||||
const loading = ref(false);
|
||||
const formulaSpecId = ref('');
|
||||
const rubberName = ref('');
|
||||
const mixingStages = ref(0);
|
||||
const tableRows = ref<Recordable[]>([]);
|
||||
const editingRowKey = ref<number | null>(null);
|
||||
|
||||
function formatStageCountText(record: Recordable) {
|
||||
const current = record?.stageIndex;
|
||||
const total = mixingStages.value;
|
||||
if (total > 0) {
|
||||
return `${current ?? ''}/${total}`;
|
||||
}
|
||||
return current != null ? String(current) : '';
|
||||
}
|
||||
|
||||
const tableColumns = [
|
||||
{ title: '示方编号', dataIndex: 'specCode', width: 220 },
|
||||
{ title: '段数', dataIndex: 'stageIndex', width: 72, customRender: ({ record }) => formatStageCountText(record) },
|
||||
{ title: '机台', dataIndex: 'machines' },
|
||||
];
|
||||
|
||||
const totalGenerateCount = computed(() =>
|
||||
tableRows.value.reduce((sum, row) => sum + (row.machines?.length || 0), 0),
|
||||
);
|
||||
|
||||
const [registerMachineModal, { openModal: openMachineModalInner }] = useModal();
|
||||
|
||||
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
|
||||
formulaSpecId.value = data?.formulaSpecId || '';
|
||||
tableRows.value = [];
|
||||
rubberName.value = '';
|
||||
mixingStages.value = 0;
|
||||
setModalProps({ confirmLoading: false });
|
||||
if (!formulaSpecId.value) {
|
||||
createMessage.warning('未指定配合示方');
|
||||
return;
|
||||
}
|
||||
loading.value = true;
|
||||
try {
|
||||
const preview = await buildMixingGeneratePreview({ formulaSpecId: formulaSpecId.value });
|
||||
rubberName.value = preview?.rubberName || '';
|
||||
mixingStages.value = preview?.mixingStages || 0;
|
||||
tableRows.value = (preview?.items || []).map((item: Recordable) => ({
|
||||
rowKey: item.rowKey,
|
||||
specCode: item.specCode,
|
||||
stageIndex: item.stageIndex,
|
||||
aSegmentIndex: item.aSegmentIndex,
|
||||
stepType: item.stepType,
|
||||
machines: [],
|
||||
}));
|
||||
if (!tableRows.value.length) {
|
||||
createMessage.warning('无可生成的混炼段,请检查混合段数');
|
||||
}
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
});
|
||||
|
||||
function formatMachineNames(machines: Recordable[] = []) {
|
||||
return machines.map((m) => m.machineName).filter(Boolean).join('、');
|
||||
}
|
||||
|
||||
function openMachinePicker(record: Recordable) {
|
||||
editingRowKey.value = record.rowKey;
|
||||
openMachineModalInner(true, { selectedMachines: record.machines || [] });
|
||||
}
|
||||
|
||||
function onMachineSelect(machines: Recordable[]) {
|
||||
const key = editingRowKey.value;
|
||||
if (key == null) {
|
||||
return;
|
||||
}
|
||||
const row = tableRows.value.find((r) => r.rowKey === key);
|
||||
if (row) {
|
||||
row.machines = machines || [];
|
||||
}
|
||||
editingRowKey.value = null;
|
||||
}
|
||||
|
||||
async function handleConfirm() {
|
||||
if (!formulaSpecId.value) {
|
||||
createMessage.warning('未指定配合示方');
|
||||
return;
|
||||
}
|
||||
if (!tableRows.value.length) {
|
||||
createMessage.warning('无可生成的混炼段');
|
||||
return;
|
||||
}
|
||||
const emptyMachine = tableRows.value.find((r) => !r.machines?.length);
|
||||
if (emptyMachine) {
|
||||
createMessage.warning(`请为示方「${emptyMachine.specCode}」选择机台`);
|
||||
return;
|
||||
}
|
||||
setModalProps({ confirmLoading: true });
|
||||
try {
|
||||
const res = await generateMixingSpec({
|
||||
formulaSpecId: formulaSpecId.value,
|
||||
rows: tableRows.value.map((r) => ({
|
||||
specCode: r.specCode,
|
||||
stageIndex: r.stageIndex,
|
||||
aSegmentIndex: r.aSegmentIndex,
|
||||
stepType: r.stepType,
|
||||
machines: (r.machines || []).map((m: Recordable) => ({
|
||||
machineId: m.machineId,
|
||||
machineName: m.machineName,
|
||||
})),
|
||||
})),
|
||||
});
|
||||
const count = Number(res?.count ?? 0);
|
||||
createMessage.success(count > 0 ? `成功生成 ${count} 条混炼示方` : '生成成功');
|
||||
closeModal();
|
||||
emit('success');
|
||||
} finally {
|
||||
setModalProps({ confirmLoading: false });
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.generate-mixing-tip {
|
||||
margin-bottom: 12px;
|
||||
color: rgba(0, 0, 0, 0.65);
|
||||
}
|
||||
.machine-cell {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
.machine-picker-input {
|
||||
flex: 1;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.generate-mixing-summary {
|
||||
margin-top: 12px;
|
||||
text-align: right;
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
}
|
||||
</style>
|
||||
@@ -8,6 +8,17 @@
|
||||
@register="registerModal"
|
||||
@ok="handleSubmit"
|
||||
>
|
||||
<template #insertFooter>
|
||||
<a-button
|
||||
v-if="showGenerateMixingBtn"
|
||||
type="primary"
|
||||
v-auth="'xslmes:mes_xsl_mixing_spec:add'"
|
||||
preIcon="ant-design:thunderbolt-outlined"
|
||||
@click="handleGenerateMixing"
|
||||
>
|
||||
生成混炼示方
|
||||
</a-button>
|
||||
</template>
|
||||
<template #title>
|
||||
<span class="formula-spec-modal-title">{{ title }}</span>
|
||||
<a-tooltip title="含胶率物料小类设置">
|
||||
@@ -390,6 +401,7 @@
|
||||
@getSelectResult="onIssueDeptSelect"
|
||||
/>
|
||||
<MesXslFormulaRubberContentSettingModal @register="registerRubberContentSettingModal" @success="onRubberContentSettingSaved" />
|
||||
<MesXslFormulaGenerateMixingModal @register="registerGenerateMixingModal" />
|
||||
</BasicModal>
|
||||
</template>
|
||||
|
||||
@@ -439,6 +451,7 @@
|
||||
} from '../MesXslFormulaSpec.data';
|
||||
import { saveOrUpdate, queryById, generateRubberCode as generateRubberCodeApi, getRubberContentSetting } from '../MesXslFormulaSpec.api';
|
||||
import MesXslFormulaRubberContentSettingModal from './MesXslFormulaRubberContentSettingModal.vue';
|
||||
import MesXslFormulaGenerateMixingModal from './MesXslFormulaGenerateMixingModal.vue';
|
||||
import MesXslFormulaLineColumnSetting from './MesXslFormulaLineColumnSetting.vue';
|
||||
import { queryById as queryMixerById } from '/@/views/mes/material/MesMixerMaterial.api';
|
||||
import { buildUUID } from '/@/utils/uuid';
|
||||
@@ -518,6 +531,7 @@
|
||||
const [registerIssueNumberModal, { openModal: openIssueNumberModalInner }] = useModal();
|
||||
const [registerIssueDeptModal, { openModal: openIssueDeptModalInner }] = useModal();
|
||||
const [registerRubberContentSettingModal, { openModal: openRubberContentSettingModal }] = useModal();
|
||||
const [registerGenerateMixingModal, { openModal: openGenerateMixingModal }] = useModal();
|
||||
const issueDeptPickerValue = ref<string>('');
|
||||
const rubberMaterialPickerId = ref<string>('');
|
||||
const mixerPsCompilePickerId = ref<string>('');
|
||||
@@ -1172,6 +1186,19 @@
|
||||
return !unref(isUpdate) ? '新增配合示方' : '编辑配合示方';
|
||||
});
|
||||
|
||||
const showGenerateMixingBtn = computed(
|
||||
() => !showFooterFlag.value && unref(isUpdate) && !!loadedMainRecord.value?.id,
|
||||
);
|
||||
|
||||
function handleGenerateMixing() {
|
||||
const id = loadedMainRecord.value?.id;
|
||||
if (!id) {
|
||||
createMessage.warning('请先保存配合示方');
|
||||
return;
|
||||
}
|
||||
openGenerateMixingModal(true, { formulaSpecId: id });
|
||||
}
|
||||
|
||||
async function handleLineValueChange(event) {
|
||||
const { row, column } = event || {};
|
||||
if (!row || !column) {
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
<template>
|
||||
<BasicModal v-bind="$attrs" title="选择密炼机动作" :width="960" @register="registerModal" @ok="handleOk">
|
||||
<BasicTable @register="registerTable" />
|
||||
</BasicModal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import { BasicModal, useModalInner } from '/@/components/Modal';
|
||||
import { BasicTable, useTable } from '/@/components/Table';
|
||||
import { list, queryById } from '../MesXslMixerAction.api';
|
||||
import { columns as actionColumns, searchFormSchema } from '../MesXslMixerAction.data';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
|
||||
const emit = defineEmits(['register', 'select']);
|
||||
const { createMessage } = useMessage();
|
||||
|
||||
const equipmentId = ref('');
|
||||
const selectedRow = ref<Recordable | null>(null);
|
||||
|
||||
const [registerTable, { reload, getSelectRowKeys, getSelectRows, setSelectedRowKeys, clearSelectedRowKeys }] = useTable({
|
||||
api: list,
|
||||
columns: actionColumns,
|
||||
rowKey: 'id',
|
||||
useSearchForm: true,
|
||||
formConfig: {
|
||||
labelWidth: 90,
|
||||
schemas: searchFormSchema,
|
||||
},
|
||||
pagination: { pageSize: 10 },
|
||||
canResize: false,
|
||||
showIndexColumn: false,
|
||||
immediate: true,
|
||||
beforeFetch: (params) => ({
|
||||
...params,
|
||||
equipmentId: equipmentId.value || undefined,
|
||||
}),
|
||||
rowSelection: {
|
||||
type: 'radio',
|
||||
columnWidth: 48,
|
||||
onChange: (_keys, rows) => {
|
||||
selectedRow.value = rows?.[0] ?? null;
|
||||
},
|
||||
},
|
||||
clickToRowSelect: true,
|
||||
});
|
||||
|
||||
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
|
||||
equipmentId.value = (data?.equipmentId as string) || '';
|
||||
selectedRow.value = null;
|
||||
clearSelectedRowKeys?.();
|
||||
setModalProps({ confirmLoading: false });
|
||||
const actionId = data?.actionId as string | undefined;
|
||||
if (actionId) {
|
||||
setSelectedRowKeys?.([actionId]);
|
||||
try {
|
||||
const raw = await queryById({ id: actionId });
|
||||
const row = (raw as Recordable)?.id != null ? raw : (raw as Recordable)?.result;
|
||||
if (row) {
|
||||
selectedRow.value = row;
|
||||
}
|
||||
} catch {
|
||||
// 忽略
|
||||
}
|
||||
}
|
||||
reload();
|
||||
});
|
||||
|
||||
async function handleOk() {
|
||||
const keys = (getSelectRowKeys?.() || []) as string[];
|
||||
let row = selectedRow.value || ((getSelectRows?.() || []) as Recordable[])[0];
|
||||
if (!row && keys.length) {
|
||||
try {
|
||||
const raw = await queryById({ id: keys[0] });
|
||||
row = (raw as Recordable)?.id != null ? raw : (raw as Recordable)?.result;
|
||||
} catch {
|
||||
// 忽略
|
||||
}
|
||||
}
|
||||
if (!row?.id) {
|
||||
createMessage.warning('请选择一条密炼机动作');
|
||||
return;
|
||||
}
|
||||
emit('select', {
|
||||
actionId: row.id,
|
||||
actionName: row.actionName || '',
|
||||
actionCode: row.actionCode || '',
|
||||
});
|
||||
closeModal();
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,91 @@
|
||||
<template>
|
||||
<BasicModal v-bind="$attrs" title="选择密炼机条件" :width="960" @register="registerModal" @ok="handleOk">
|
||||
<BasicTable @register="registerTable" />
|
||||
</BasicModal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import { BasicModal, useModalInner } from '/@/components/Modal';
|
||||
import { BasicTable, useTable } from '/@/components/Table';
|
||||
import { list, queryById } from '../MesXslMixerCondition.api';
|
||||
import { columns as conditionColumns, searchFormSchema } from '../MesXslMixerCondition.data';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
|
||||
const emit = defineEmits(['register', 'select']);
|
||||
const { createMessage } = useMessage();
|
||||
|
||||
const equipmentId = ref('');
|
||||
const selectedRow = ref<Recordable | null>(null);
|
||||
|
||||
const [registerTable, { reload, getSelectRowKeys, getSelectRows, setSelectedRowKeys, clearSelectedRowKeys }] = useTable({
|
||||
api: list,
|
||||
columns: conditionColumns.slice(0, 4),
|
||||
rowKey: 'id',
|
||||
useSearchForm: true,
|
||||
formConfig: {
|
||||
labelWidth: 90,
|
||||
schemas: searchFormSchema,
|
||||
},
|
||||
pagination: { pageSize: 10 },
|
||||
canResize: false,
|
||||
showIndexColumn: false,
|
||||
immediate: true,
|
||||
beforeFetch: (params) => ({
|
||||
...params,
|
||||
equipmentId: equipmentId.value || undefined,
|
||||
}),
|
||||
rowSelection: {
|
||||
type: 'radio',
|
||||
columnWidth: 48,
|
||||
onChange: (_keys, rows) => {
|
||||
selectedRow.value = rows?.[0] ?? null;
|
||||
},
|
||||
},
|
||||
clickToRowSelect: true,
|
||||
});
|
||||
|
||||
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
|
||||
equipmentId.value = (data?.equipmentId as string) || '';
|
||||
selectedRow.value = null;
|
||||
clearSelectedRowKeys?.();
|
||||
setModalProps({ confirmLoading: false });
|
||||
const conditionId = data?.conditionId as string | undefined;
|
||||
if (conditionId) {
|
||||
setSelectedRowKeys?.([conditionId]);
|
||||
try {
|
||||
const raw = await queryById({ id: conditionId });
|
||||
const row = (raw as Recordable)?.id != null ? raw : (raw as Recordable)?.result;
|
||||
if (row) {
|
||||
selectedRow.value = row;
|
||||
}
|
||||
} catch {
|
||||
// 忽略
|
||||
}
|
||||
}
|
||||
reload();
|
||||
});
|
||||
|
||||
async function handleOk() {
|
||||
const keys = (getSelectRowKeys?.() || []) as string[];
|
||||
let row = selectedRow.value || ((getSelectRows?.() || []) as Recordable[])[0];
|
||||
if (!row && keys.length) {
|
||||
try {
|
||||
const raw = await queryById({ id: keys[0] });
|
||||
row = (raw as Recordable)?.id != null ? raw : (raw as Recordable)?.result;
|
||||
} catch {
|
||||
// 忽略
|
||||
}
|
||||
}
|
||||
if (!row?.id) {
|
||||
createMessage.warning('请选择一条密炼机条件');
|
||||
return;
|
||||
}
|
||||
emit('select', {
|
||||
conditionId: row.id,
|
||||
conditionName: row.conditionName || '',
|
||||
conditionCode: row.conditionCode || '',
|
||||
});
|
||||
closeModal();
|
||||
}
|
||||
</script>
|
||||
@@ -35,7 +35,7 @@ export const columns: BasicColumn[] = [
|
||||
{ title: '机台', align: 'center', dataIndex: 'machineName', width: 120 },
|
||||
{ title: '制作日期', align: 'center', dataIndex: 'makeDate', width: 120 },
|
||||
{ title: '发行编号', align: 'center', dataIndex: 'issueNumber', width: 150 },
|
||||
{ title: '段数', align: 'center', dataIndex: 'stageCount', width: 80 },
|
||||
{ title: '段数', align: 'center', dataIndex: 'stageCount', width: 88 },
|
||||
{ title: '纯混炼时间(秒)', align: 'center', dataIndex: 'pureMixSec', width: 130 },
|
||||
{ title: '变更日期', align: 'center', dataIndex: 'changeDate', width: 120 },
|
||||
{ title: '修改时间', align: 'center', dataIndex: 'updateTime', width: 165 },
|
||||
@@ -49,18 +49,21 @@ export const searchFormSchema: FormSchema[] = [
|
||||
|
||||
export const mainSchema: FormSchema[] = [
|
||||
{ label: '', field: 'id', component: 'Input', show: false },
|
||||
{ label: '', field: 'machineId', component: 'Input', show: false },
|
||||
{ label: '规格', field: 'specName', component: 'Input', required: true, colProps: { span: 8 } },
|
||||
{ label: '用途', field: 'purpose', component: 'AutoComplete', required: true, colProps: { span: 8 } },
|
||||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A33】混炼示方基本信息字段优化-----------
|
||||
{ label: '用途', field: 'purpose', component: 'Input', required: true, colProps: { span: 8 } },
|
||||
{ label: '机台', field: 'machineName', component: 'Input', colProps: { span: 8 } },
|
||||
{ label: '制作日期', field: 'makeDate', component: 'DatePicker', colProps: { span: 8 }, componentProps: { valueFormat: 'YYYY-MM-DD' } },
|
||||
{ label: '发行编号', field: 'issueNumber', component: 'AutoComplete', required: true, colProps: { span: 8 } },
|
||||
{ label: '发行编号', field: 'issueNumber', component: 'Input', required: true, colProps: { span: 8 } },
|
||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A33】混炼示方基本信息字段优化-----------
|
||||
{ label: '换算系数', field: 'convertFactor', component: 'InputNumber', colProps: { span: 8 }, componentProps: { precision: 6, style: { width: '100%' } } },
|
||||
{ label: '填充体积', field: 'fillVolume', component: 'InputNumber', colProps: { span: 8 }, componentProps: { precision: 6, style: { width: '100%' } } },
|
||||
{ label: '回收炭黑(秒)', field: 'recycleCarbonSec', component: 'InputNumber', colProps: { span: 8 }, componentProps: { precision: 0, style: { width: '100%' } } },
|
||||
{ label: '母胶比重', field: 'motherRubberSg', component: 'InputNumber', colProps: { span: 8 }, componentProps: { precision: 6, style: { width: '100%' } } },
|
||||
{ label: '终炼胶比重', field: 'finalRubberSg', component: 'InputNumber', colProps: { span: 8 }, componentProps: { precision: 6, style: { width: '100%' } } },
|
||||
{ label: '适用工厂', field: 'applyFactory', component: 'Input', colProps: { span: 8 } },
|
||||
{ label: '段数', field: 'stageCount', component: 'InputNumber', colProps: { span: 8 }, componentProps: { precision: 0, style: { width: '100%' } } },
|
||||
{ label: '段数', field: 'stageCount', component: 'Input', colProps: { span: 8 }, componentProps: { placeholder: '如 2/3' } },
|
||||
{ label: '纯混炼时间(秒)', field: 'pureMixSec', component: 'InputNumber', colProps: { span: 8 }, componentProps: { precision: 0, style: { width: '100%' } } },
|
||||
{ label: '回收炭黑(KG)', field: 'recycleCarbonKg', component: 'InputNumber', colProps: { span: 8 }, componentProps: { precision: 6, style: { width: '100%' } } },
|
||||
{ label: '自动小料打印设定', field: 'autoSmallPrintSetting', component: 'Input', colProps: { span: 8 } },
|
||||
@@ -198,13 +201,32 @@ export function calcMixingMaterialTableWidth(columns: JVxeColumn[], widthMap: Re
|
||||
export const MIXING_STEP_MIN_COLUMN_WIDTH = 48;
|
||||
|
||||
export const stepColumns: JVxeColumn[] = [
|
||||
{ title: '动作', key: 'actionName', type: JVxeTypes.input, width: 120, minWidth: MIXING_STEP_MIN_COLUMN_WIDTH },
|
||||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A35】混合步骤动作/组合列常显下拉倒三角-----------
|
||||
{
|
||||
title: '动作',
|
||||
key: 'actionName',
|
||||
type: JVxeTypes.slot,
|
||||
slotName: 'actionNameSlot',
|
||||
width: 120,
|
||||
minWidth: MIXING_STEP_MIN_COLUMN_WIDTH,
|
||||
},
|
||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A35】混合步骤动作/组合列常显下拉倒三角-----------
|
||||
{ title: '时间(")', key: 'actionSec', type: JVxeTypes.inputNumber, width: 80, minWidth: MIXING_STEP_MIN_COLUMN_WIDTH, align: 'center' },
|
||||
{ title: '保护时间', key: 'protectSec', type: JVxeTypes.inputNumber, width: 80, minWidth: MIXING_STEP_MIN_COLUMN_WIDTH, align: 'center' },
|
||||
{ title: '温度(℃)', key: 'tempC', type: JVxeTypes.inputNumber, width: 80, minWidth: MIXING_STEP_MIN_COLUMN_WIDTH, align: 'center' },
|
||||
{ title: '功率(Kw)', key: 'powerKw', type: JVxeTypes.inputNumber, width: 80, minWidth: MIXING_STEP_MIN_COLUMN_WIDTH, align: 'center' },
|
||||
{ title: '能量(Kwh)', key: 'energyKwh', type: JVxeTypes.inputNumber, width: 80, minWidth: MIXING_STEP_MIN_COLUMN_WIDTH, align: 'center' },
|
||||
{ title: '组合', key: 'comboMode', type: JVxeTypes.input, width: 72, minWidth: MIXING_STEP_MIN_COLUMN_WIDTH, align: 'center' },
|
||||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A35】混合步骤动作/组合列常显下拉倒三角-----------
|
||||
{
|
||||
title: '组合',
|
||||
key: 'comboMode',
|
||||
type: JVxeTypes.slot,
|
||||
slotName: 'comboModeSlot',
|
||||
width: 72,
|
||||
minWidth: MIXING_STEP_MIN_COLUMN_WIDTH,
|
||||
align: 'center',
|
||||
},
|
||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A35】混合步骤动作/组合列常显下拉倒三角-----------
|
||||
{ title: '转速(rpm)', key: 'speedRpm', type: JVxeTypes.inputNumber, width: 80, minWidth: MIXING_STEP_MIN_COLUMN_WIDTH, align: 'center' },
|
||||
{ title: '压力(Mpa)', key: 'pressureMpa', type: JVxeTypes.inputNumber, width: 80, minWidth: MIXING_STEP_MIN_COLUMN_WIDTH, align: 'center' },
|
||||
{ title: '栓(%)', key: 'boltPercent', type: JVxeTypes.inputNumber, width: 72, minWidth: MIXING_STEP_MIN_COLUMN_WIDTH, align: 'center' },
|
||||
@@ -281,7 +303,9 @@ export const MIXING_TCU_COLUMN_WIDTH_CACHE_KEY = 'mes_xsl_mixing_spec_tcu_column
|
||||
export const MIXING_TCU_MIN_COLUMN_WIDTH = 48;
|
||||
|
||||
export const tcuColumns: JVxeColumn[] = [
|
||||
{ title: '区分', key: 'sectionType', type: JVxeTypes.select, dictCode: 'xslmes_mixing_tcu_section', width: 96, minWidth: MIXING_TCU_MIN_COLUMN_WIDTH, align: 'center' },
|
||||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A33】TCU区分固定上/下密炼机-----------
|
||||
{ title: '区分', key: 'sectionType', type: JVxeTypes.select, dictCode: 'xslmes_mixing_tcu_section', disabled: true, width: 96, minWidth: MIXING_TCU_MIN_COLUMN_WIDTH, align: 'center' },
|
||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A33】TCU区分固定上/下密炼机-----------
|
||||
{ title: '前转子温度', key: 'frontRotorTemp', type: JVxeTypes.inputNumber, width: 76, minWidth: MIXING_TCU_MIN_COLUMN_WIDTH, align: 'center' },
|
||||
{ title: '后转子温度', key: 'rearRotorTemp', type: JVxeTypes.inputNumber, width: 76, minWidth: MIXING_TCU_MIN_COLUMN_WIDTH, align: 'center' },
|
||||
{ title: '前混炼室温度', key: 'frontChamberTemp', type: JVxeTypes.inputNumber, width: 76, minWidth: MIXING_TCU_MIN_COLUMN_WIDTH, align: 'center' },
|
||||
@@ -580,8 +604,36 @@ export function createEmptyDownStepRows(count = DEFAULT_MIXING_DOWN_STEP_ROW_COU
|
||||
return createEmptyMixingRows(count);
|
||||
}
|
||||
|
||||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A33】TCU默认两行及上密炼机药品称默认值-----------
|
||||
/** 上密炼机 TCU 行默认药品称量位置(药品称) */
|
||||
export const MIXING_TCU_UP_MIXER_DRUG_WEIGH_POS = 'drug_scale';
|
||||
|
||||
/** 构建 TCU 温度条件默认两行(上密炼机/下密炼机) */
|
||||
export function buildDefaultMixingTcuRows(rows: Recordable[] = []): Recordable[] {
|
||||
const up =
|
||||
rows.find((r) => r.sectionType === 'up_mixer') ||
|
||||
({ sectionType: 'up_mixer', drugWeighPos: MIXING_TCU_UP_MIXER_DRUG_WEIGH_POS } as Recordable);
|
||||
if (up.sectionType === 'up_mixer' && !up.drugWeighPos) {
|
||||
up.drugWeighPos = MIXING_TCU_UP_MIXER_DRUG_WEIGH_POS;
|
||||
}
|
||||
const down = rows.find((r) => r.sectionType === 'down_mixer') || ({ sectionType: 'down_mixer', drugWeighPos: undefined } as Recordable);
|
||||
return [up, down];
|
||||
}
|
||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A33】TCU默认两行及上密炼机药品称默认值-----------
|
||||
|
||||
/** 确保明细行具备唯一 id(JVxeTable 依赖 rowKey=id) */
|
||||
export function normalizeMixingDetailRows(rows: Recordable[] = []): Recordable[] {
|
||||
return (rows || []).map((row) => ({ ...row, id: row?.id || buildUUID() }));
|
||||
}
|
||||
|
||||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A39】编辑页明细补齐默认空行与新增一致-----------
|
||||
/** 编辑/详情加载时补齐明细默认空行(不少于 defaultCount,已有数据行保留) */
|
||||
export function ensureMixingDetailRows(rows: Recordable[] = [], defaultCount: number): Recordable[] {
|
||||
const normalized = normalizeMixingDetailRows(rows);
|
||||
if (normalized.length >= defaultCount) {
|
||||
return normalized;
|
||||
}
|
||||
return [...normalized, ...createEmptyMixingRows(defaultCount - normalized.length)];
|
||||
}
|
||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A39】编辑页明细补齐默认空行与新增一致-----------
|
||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A22】明细表默认空行数-----------
|
||||
|
||||
@@ -28,22 +28,28 @@
|
||||
</td>
|
||||
<th class="formTitle" colspan="1">发行编号</th>
|
||||
<td class="formValue" colspan="3">
|
||||
<a-select
|
||||
v-model:value="sheetForm.issueNumber"
|
||||
show-search
|
||||
allow-clear
|
||||
:options="issueNumberOptions"
|
||||
<a-input
|
||||
:value="sheetForm.issueNumber"
|
||||
readonly
|
||||
placeholder="请点击选择密炼PS"
|
||||
:disabled="!showFooter"
|
||||
:filter-option="selectFilterOption"
|
||||
:bordered="false"
|
||||
class="form-input"
|
||||
style="width: 100%"
|
||||
:class="['form-input', 'mixing-picker-input', { 'is-filled': !!sheetForm.issueNumber }]"
|
||||
@click="openIssueNumberPicker"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="formValue" colspan="2" rowspan="2">
|
||||
<a-input v-model:value="sheetForm.machineName" :disabled="!showFooter" :bordered="false" class="form-input" />
|
||||
<a-input
|
||||
:value="sheetForm.machineName"
|
||||
readonly
|
||||
placeholder="请点击选择设备台账"
|
||||
:disabled="!showFooter"
|
||||
:bordered="false"
|
||||
:class="['form-input', 'mixing-picker-input', { 'is-filled': !!sheetForm.machineName }]"
|
||||
@click="openMachinePicker"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -63,16 +69,13 @@
|
||||
<tr>
|
||||
<th class="formTitle required" rowspan="2">用途</th>
|
||||
<td class="formValue" colspan="3" rowspan="2">
|
||||
<a-select
|
||||
<a-input
|
||||
v-model:value="sheetForm.purpose"
|
||||
show-search
|
||||
placeholder="请输入用途"
|
||||
allow-clear
|
||||
:options="purposeOptions"
|
||||
:disabled="!showFooter"
|
||||
:filter-option="selectFilterOption"
|
||||
:bordered="false"
|
||||
class="form-input"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</td>
|
||||
<th class="formTitle" colspan="1">母胶比重</th>
|
||||
@@ -81,7 +84,13 @@
|
||||
</td>
|
||||
<th class="formTitle">段数</th>
|
||||
<td class="formValue" colspan="2">
|
||||
<a-input-number v-model:value="sheetForm.stageCount" :disabled="!showFooter" :precision="0" :bordered="false" class="form-input" style="width: 100%" />
|
||||
<a-input
|
||||
v-model:value="sheetForm.stageCount"
|
||||
placeholder="如 2/3"
|
||||
:disabled="!showFooter"
|
||||
:bordered="false"
|
||||
class="form-input"
|
||||
/>
|
||||
</td>
|
||||
<th class="formTitle" colspan="1">纯混炼时间(秒)</th>
|
||||
<td class="formValue">
|
||||
@@ -253,7 +262,28 @@
|
||||
:disabled="!showFooter"
|
||||
@resizable-change="handleStepColumnResize"
|
||||
@column-resizable-change="handleStepColumnResize"
|
||||
/>
|
||||
>
|
||||
<template #actionNameSlot="{ row }">
|
||||
<MesXslMixingStepSelectCell
|
||||
:row="row"
|
||||
field="actionName"
|
||||
:options="mixerActionSelectOptions"
|
||||
:disabled="!showFooter"
|
||||
:machine-id="sheetForm.machineId"
|
||||
:placeholder="stepSelectPlaceholder"
|
||||
/>
|
||||
</template>
|
||||
<template #comboModeSlot="{ row }">
|
||||
<MesXslMixingStepSelectCell
|
||||
:row="row"
|
||||
field="comboMode"
|
||||
:options="mixerConditionSelectOptions"
|
||||
:disabled="!showFooter"
|
||||
:machine-id="sheetForm.machineId"
|
||||
:placeholder="stepSelectPlaceholder"
|
||||
/>
|
||||
</template>
|
||||
</JVxeTable>
|
||||
</div>
|
||||
<!--update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A21】混合步骤与下密炼机列宽同步可调----------- -->
|
||||
</div>
|
||||
@@ -282,7 +312,28 @@
|
||||
:disabled="!showFooter"
|
||||
@resizable-change="handleStepColumnResize"
|
||||
@column-resizable-change="handleStepColumnResize"
|
||||
/>
|
||||
>
|
||||
<template #actionNameSlot="{ row }">
|
||||
<MesXslMixingStepSelectCell
|
||||
:row="row"
|
||||
field="actionName"
|
||||
:options="mixerActionSelectOptions"
|
||||
:disabled="!showFooter"
|
||||
:machine-id="sheetForm.machineId"
|
||||
:placeholder="stepSelectPlaceholder"
|
||||
/>
|
||||
</template>
|
||||
<template #comboModeSlot="{ row }">
|
||||
<MesXslMixingStepSelectCell
|
||||
:row="row"
|
||||
field="comboMode"
|
||||
:options="mixerConditionSelectOptions"
|
||||
:disabled="!showFooter"
|
||||
:machine-id="sheetForm.machineId"
|
||||
:placeholder="stepSelectPlaceholder"
|
||||
/>
|
||||
</template>
|
||||
</JVxeTable>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -317,13 +368,17 @@
|
||||
</div>
|
||||
|
||||
<BasicForm v-show="false" @register="registerForm" />
|
||||
|
||||
<MesXslEquipmentLedgerSelectModal @register="registerMachineModal" @select="onMachineSelect" />
|
||||
<MesXslMixerPsCompileSelectModal @register="registerIssueNumberModal" @select="onIssueNumberSelect" />
|
||||
</div>
|
||||
</BasicModal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, reactive, ref, unref } from 'vue';
|
||||
import { BasicModal, useModalInner } from '/@/components/Modal';
|
||||
import dayjs from 'dayjs';
|
||||
import { BasicModal, useModal, useModalInner } from '/@/components/Modal';
|
||||
import { BasicForm, useForm } from '/@/components/Form/index';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import { useUserStore } from '/@/store/modules/user';
|
||||
@@ -351,14 +406,23 @@ import {
|
||||
createEmptyMaterialRows,
|
||||
createEmptyStepRows,
|
||||
createEmptyDownStepRows,
|
||||
normalizeMixingDetailRows,
|
||||
ensureMixingDetailRows,
|
||||
DEFAULT_MIXING_MATERIAL_ROW_COUNT,
|
||||
DEFAULT_MIXING_STEP_ROW_COUNT,
|
||||
DEFAULT_MIXING_DOWN_STEP_ROW_COUNT,
|
||||
buildDefaultMixingTcuRows,
|
||||
MIXING_MATERIAL_MIN_COLUMN_WIDTH,
|
||||
MIXING_TCU_MIN_COLUMN_WIDTH,
|
||||
MIXING_STEP_MIN_COLUMN_WIDTH,
|
||||
} from '../MesXslMixingSpec.data';
|
||||
import { saveOrUpdate, queryById, queryIssueNumberOptions, queryPurposeOptions } from '../MesXslMixingSpec.api';
|
||||
import { saveOrUpdate, queryById } from '../MesXslMixingSpec.api';
|
||||
import MesXslMixingMaterialColumnSetting from './MesXslMixingMaterialColumnSetting.vue';
|
||||
import MesXslMixingTableRowHeightSetting from './MesXslMixingTableRowHeightSetting.vue';
|
||||
import MesXslMixingStepSelectCell from './MesXslMixingStepSelectCell.vue';
|
||||
import { list as mixerActionList } from '/@/views/xslmes/mesXslMixerAction/MesXslMixerAction.api';
|
||||
import { list as mixerConditionList } from '/@/views/xslmes/mesXslMixerCondition/MesXslMixerCondition.api';
|
||||
import MesXslEquipmentLedgerSelectModal from '/@/views/xslmes/mesXslEquipInspectConfig/components/MesXslEquipmentLedgerSelectModal.vue';
|
||||
import MesXslMixerPsCompileSelectModal from '/@/views/xslmes/mesXslMixerPsCompile/components/MesXslMixerPsCompileSelectModal.vue';
|
||||
|
||||
const emit = defineEmits(['register', 'success']);
|
||||
const { createMessage } = useMessage();
|
||||
@@ -366,8 +430,11 @@ const userStore = useUserStore();
|
||||
|
||||
const isUpdate = ref(false);
|
||||
const showFooter = ref(true);
|
||||
const issueNumberOptions = ref<{ label: string; value: string }[]>([]);
|
||||
const purposeOptions = ref<{ label: string; value: string }[]>([]);
|
||||
const mixerPsCompilePickerId = ref('');
|
||||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A34】混合步骤动作/组合下拉选项-----------
|
||||
const mixerActionOptions = ref<{ title: string; value: string }[]>([]);
|
||||
const mixerConditionOptions = ref<{ title: string; value: string }[]>([]);
|
||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A34】混合步骤动作/组合下拉选项-----------
|
||||
|
||||
const materialRef = ref();
|
||||
const stepRef = ref();
|
||||
@@ -414,10 +481,12 @@ const tcuTableLayoutKey = computed(
|
||||
() => `${tcuHeightPref.value.rowHeight}-${tcuHeightPref.value.visibleRowCount}-${tcuTableWidth.value}`,
|
||||
);
|
||||
const stepTableLayoutKey = computed(
|
||||
() => `${stepHeightPref.value.rowHeight}-${stepHeightPref.value.visibleRowCount}-${visibleStepColumns.value.length}`,
|
||||
() =>
|
||||
`${stepHeightPref.value.rowHeight}-${stepHeightPref.value.visibleRowCount}-${mixerActionOptions.value.length}-${mixerConditionOptions.value.length}`,
|
||||
);
|
||||
const downStepTableLayoutKey = computed(
|
||||
() => `${downStepHeightPref.value.rowHeight}-${downStepHeightPref.value.visibleRowCount}-${visibleStepColumns.value.length}`,
|
||||
() =>
|
||||
`${downStepHeightPref.value.rowHeight}-${downStepHeightPref.value.visibleRowCount}-${mixerActionOptions.value.length}-${mixerConditionOptions.value.length}`,
|
||||
);
|
||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A32】四明细表行高/展示行数设置持久化-----------
|
||||
|
||||
@@ -478,8 +547,58 @@ function handleTcuColumnResize(params: Recordable) {
|
||||
|
||||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A21】混合步骤与下密炼机列宽同步可调-----------
|
||||
const stepColumnWidths = ref<Record<string, number>>(loadMixingStepColumnWidths());
|
||||
|
||||
function extractPageRecords(raw: Recordable) {
|
||||
if (Array.isArray(raw?.records)) {
|
||||
return raw.records;
|
||||
}
|
||||
if (Array.isArray(raw?.result?.records)) {
|
||||
return raw.result.records;
|
||||
}
|
||||
if (Array.isArray(raw)) {
|
||||
return raw;
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
function buildMixerSelectOptions(records: Recordable[], labelKey: string) {
|
||||
const seen = new Set<string>();
|
||||
const options: { title: string; value: string }[] = [];
|
||||
records.forEach((item) => {
|
||||
const label = String(item?.[labelKey] || '').trim();
|
||||
if (!label || seen.has(label)) {
|
||||
return;
|
||||
}
|
||||
seen.add(label);
|
||||
options.push({ title: label, value: label });
|
||||
});
|
||||
return options;
|
||||
}
|
||||
|
||||
async function loadMixerStepOptions(equipmentId?: string) {
|
||||
if (!equipmentId) {
|
||||
mixerActionOptions.value = [];
|
||||
mixerConditionOptions.value = [];
|
||||
return;
|
||||
}
|
||||
const params = { equipmentId, pageNo: 1, pageSize: 500 };
|
||||
const [actionRaw, conditionRaw] = await Promise.all([mixerActionList(params), mixerConditionList(params)]);
|
||||
mixerActionOptions.value = buildMixerSelectOptions(extractPageRecords(actionRaw), 'actionName');
|
||||
mixerConditionOptions.value = buildMixerSelectOptions(extractPageRecords(conditionRaw), 'conditionName');
|
||||
}
|
||||
|
||||
const visibleStepColumns = computed(() => applyMixingStepColumnWidths(stepColumns, stepColumnWidths.value));
|
||||
|
||||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A35】混合步骤动作/组合列常显下拉倒三角-----------
|
||||
const mixerActionSelectOptions = computed(() =>
|
||||
mixerActionOptions.value.map((item) => ({ label: item.title, value: item.value })),
|
||||
);
|
||||
const mixerConditionSelectOptions = computed(() =>
|
||||
mixerConditionOptions.value.map((item) => ({ label: item.title, value: item.value })),
|
||||
);
|
||||
const stepSelectPlaceholder = computed(() => '');
|
||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A35】混合步骤动作/组合列常显下拉倒三角-----------
|
||||
|
||||
function handleStepColumnResize(params: Recordable) {
|
||||
const column = params?.resizeColumn ?? params?.column;
|
||||
const key = column?.params?.key ?? column?.field;
|
||||
@@ -505,6 +624,7 @@ const sheetForm = reactive<Recordable>({
|
||||
id: '',
|
||||
specName: '',
|
||||
purpose: '',
|
||||
machineId: '',
|
||||
machineName: '',
|
||||
makeDate: '',
|
||||
issueNumber: '',
|
||||
@@ -514,7 +634,7 @@ const sheetForm = reactive<Recordable>({
|
||||
motherRubberSg: null,
|
||||
finalRubberSg: null,
|
||||
applyFactory: '',
|
||||
stageCount: null,
|
||||
stageCount: '',
|
||||
pureMixSec: null,
|
||||
recycleCarbonKg: null,
|
||||
autoSmallPrintSetting: '',
|
||||
@@ -587,27 +707,43 @@ const [registerForm, { resetFields, setFieldsValue, validate, setProps }] = useF
|
||||
baseColProps: { span: 8 },
|
||||
});
|
||||
|
||||
const selectFilterOption = (input: string, option: any) => String(option?.label || '').toLowerCase().includes(input.toLowerCase());
|
||||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A33】混炼示方主表选择弹窗-----------
|
||||
const [registerMachineModal, { openModal: openMachineModalInner }] = useModal();
|
||||
const [registerIssueNumberModal, { openModal: openIssueNumberModalInner }] = useModal();
|
||||
|
||||
async function applyAutoCompleteSource() {
|
||||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A17】混炼示方用途/发行编号联想-----------
|
||||
const issueRows = await queryIssueNumberOptions({});
|
||||
const purposeRows = await queryPurposeOptions({});
|
||||
const toOptions = (rows: any) => {
|
||||
const list = Array.isArray(rows) ? rows : rows?.result || [];
|
||||
return list.map((item) => ({ label: item.label, value: item.value }));
|
||||
};
|
||||
issueNumberOptions.value = toOptions(issueRows);
|
||||
purposeOptions.value = toOptions(purposeRows);
|
||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A17】混炼示方用途/发行编号联想-----------
|
||||
function openMachinePicker() {
|
||||
if (!showFooter.value) {
|
||||
return;
|
||||
}
|
||||
openMachineModalInner(true, { equipmentLedgerId: sheetForm.machineId || '' });
|
||||
}
|
||||
|
||||
async function onMachineSelect(payload: Recordable | null) {
|
||||
sheetForm.machineId = payload?.equipmentLedgerId || '';
|
||||
sheetForm.machineName = payload?.equipmentName || '';
|
||||
await loadMixerStepOptions(sheetForm.machineId);
|
||||
}
|
||||
|
||||
function openIssueNumberPicker() {
|
||||
if (!showFooter.value) {
|
||||
return;
|
||||
}
|
||||
openIssueNumberModalInner(true, { psCompileId: mixerPsCompilePickerId.value || '' });
|
||||
}
|
||||
|
||||
function onIssueNumberSelect(payload: Recordable | null) {
|
||||
if (!payload) {
|
||||
return;
|
||||
}
|
||||
mixerPsCompilePickerId.value = payload.psCompileId || '';
|
||||
sheetForm.issueNumber = payload.psCode || '';
|
||||
}
|
||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A33】混炼示方主表选择弹窗-----------
|
||||
|
||||
function ensureTcuDefaultRows(rows: Recordable[] = []) {
|
||||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A17】TCU子表默认固定两行-----------
|
||||
const up = rows.find((r) => r.sectionType === 'up_mixer') || { sectionType: 'up_mixer' };
|
||||
const down = rows.find((r) => r.sectionType === 'down_mixer') || { sectionType: 'down_mixer', drugWeighPos: undefined };
|
||||
return [up, down];
|
||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A17】TCU子表默认固定两行-----------
|
||||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A33】TCU默认两行及上密炼机药品称默认值-----------
|
||||
return buildDefaultMixingTcuRows(rows);
|
||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A33】TCU默认两行及上密炼机药品称默认值-----------
|
||||
}
|
||||
|
||||
function handleTcuValueChange(event) {
|
||||
@@ -629,8 +765,10 @@ function resetSheetForm() {
|
||||
sheetForm[key] =
|
||||
key === 'specName' ||
|
||||
key === 'purpose' ||
|
||||
key === 'machineId' ||
|
||||
key === 'machineName' ||
|
||||
key === 'issueNumber' ||
|
||||
key === 'stageCount' ||
|
||||
key.endsWith('By') ||
|
||||
key === 'applyFactory' ||
|
||||
key === 'autoSmallPrintSetting'
|
||||
@@ -644,6 +782,7 @@ function resetSheetForm() {
|
||||
sheetForm.auditTime = '';
|
||||
sheetForm.approveTime = '';
|
||||
sheetForm.changeDate = '';
|
||||
mixerPsCompilePickerId.value = '';
|
||||
refreshSignDisplay({});
|
||||
}
|
||||
|
||||
@@ -670,25 +809,29 @@ const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data
|
||||
stepData.value = [];
|
||||
downStepData.value = [];
|
||||
tcuData.value = ensureTcuDefaultRows([]);
|
||||
await loadMixerStepOptions('');
|
||||
isUpdate.value = !!data?.isUpdate;
|
||||
showFooter.value = !!data?.showFooter;
|
||||
await setProps({ disabled: !showFooter.value });
|
||||
setModalProps({ showOkBtn: showFooter.value, showCancelBtn: showFooter.value, confirmLoading: false });
|
||||
await applyAutoCompleteSource();
|
||||
if (isUpdate.value && data?.record?.id) {
|
||||
const raw = await queryById({ id: data.record.id });
|
||||
const row = raw?.result || raw;
|
||||
Object.assign(sheetForm, row || {});
|
||||
refreshSignDisplay(row || {});
|
||||
await loadMixerStepOptions(sheetForm.machineId);
|
||||
await syncSheetToForm();
|
||||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A22】明细表默认空行数-----------
|
||||
materialData.value = normalizeMixingDetailRows(row?.materialList || []);
|
||||
stepData.value = normalizeMixingDetailRows(row?.stepList || []);
|
||||
downStepData.value = normalizeMixingDetailRows(row?.downStepList || []);
|
||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A22】明细表默认空行数-----------
|
||||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A39】编辑页明细补齐默认空行与新增一致-----------
|
||||
materialData.value = ensureMixingDetailRows(row?.materialList || [], DEFAULT_MIXING_MATERIAL_ROW_COUNT);
|
||||
stepData.value = ensureMixingDetailRows(row?.stepList || [], DEFAULT_MIXING_STEP_ROW_COUNT);
|
||||
downStepData.value = ensureMixingDetailRows(row?.downStepList || [], DEFAULT_MIXING_DOWN_STEP_ROW_COUNT);
|
||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A39】编辑页明细补齐默认空行与新增一致-----------
|
||||
tcuData.value = ensureTcuDefaultRows(row?.tcuList || []);
|
||||
} else {
|
||||
const userInfo = userStore.getUserInfo || {};
|
||||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A33】新增混炼示方制作日期默认当天-----------
|
||||
sheetForm.makeDate = dayjs().format('YYYY-MM-DD');
|
||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A33】新增混炼示方制作日期默认当天-----------
|
||||
refreshSignDisplay({
|
||||
createBy_dictText: userInfo.realname,
|
||||
createBy: userInfo.username,
|
||||
@@ -856,6 +999,15 @@ async function handleSubmit() {
|
||||
:deep(.form-input.ant-picker-suffix) {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
:deep(.mixing-picker-input) {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
:deep(.mixing-picker-input.is-filled) {
|
||||
color: #262626;
|
||||
}
|
||||
|
||||
}
|
||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A17】顶部施工表对齐旧系统13列表格-----------
|
||||
|
||||
@@ -1099,6 +1251,20 @@ async function handleSubmit() {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A35】混合步骤动作/组合列常显下拉倒三角-----------
|
||||
.panel-right :deep(.vxe-body--column.col--actionName),
|
||||
.panel-right :deep(.vxe-body--column.col--comboMode) {
|
||||
padding: 0 !important;
|
||||
overflow: visible !important;
|
||||
}
|
||||
|
||||
.panel-right :deep(.vxe-body--column.col--actionName .vxe-cell),
|
||||
.panel-right :deep(.vxe-body--column.col--comboMode .vxe-cell) {
|
||||
padding: 0 !important;
|
||||
overflow: visible !important;
|
||||
}
|
||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A35】混合步骤动作/组合列常显下拉倒三角-----------
|
||||
|
||||
.sheet-sign-footer {
|
||||
border-top: 1px solid #d9d9d9;
|
||||
background: #fff;
|
||||
@@ -1171,4 +1337,10 @@ async function handleSubmit() {
|
||||
background: #fcfdfd;
|
||||
}
|
||||
}
|
||||
|
||||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A36】动作/组合下拉挂到body避免被表格裁切-----------
|
||||
.mixing-step-select-dropdown {
|
||||
z-index: 2100 !important;
|
||||
}
|
||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A36】动作/组合下拉挂到body避免被表格裁切-----------
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
<template>
|
||||
<a-select
|
||||
:value="row[field]"
|
||||
:options="options"
|
||||
:disabled="disabled"
|
||||
:open="dropdownOpen"
|
||||
allow-clear
|
||||
show-search
|
||||
:bordered="false"
|
||||
size="small"
|
||||
class="mixing-step-select"
|
||||
popup-class-name="mixing-step-select-dropdown"
|
||||
:placeholder="placeholder"
|
||||
:get-popup-container="getPopupContainer"
|
||||
@update:value="handleChange"
|
||||
@dropdown-visible-change="handleDropdownVisibleChange"
|
||||
@click.stop
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
|
||||
const props = defineProps<{
|
||||
row: Recordable;
|
||||
field: string;
|
||||
options: { label: string; value: string }[];
|
||||
disabled?: boolean;
|
||||
placeholder?: string;
|
||||
machineId?: string;
|
||||
}>();
|
||||
|
||||
const { createMessage } = useMessage();
|
||||
const dropdownOpen = ref(false);
|
||||
|
||||
function handleChange(value: string | undefined) {
|
||||
props.row[props.field] = value;
|
||||
}
|
||||
|
||||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A37】未选机台点击动作/组合提示请先选择机台-----------
|
||||
function handleDropdownVisibleChange(visible: boolean) {
|
||||
if (props.disabled) {
|
||||
dropdownOpen.value = false;
|
||||
return;
|
||||
}
|
||||
if (visible && !props.machineId) {
|
||||
createMessage.warning('请先选择机台');
|
||||
dropdownOpen.value = false;
|
||||
return;
|
||||
}
|
||||
dropdownOpen.value = visible;
|
||||
}
|
||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A37】未选机台点击动作/组合提示请先选择机台-----------
|
||||
|
||||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A36】动作/组合下拉挂到body避免被表格裁切-----------
|
||||
function getPopupContainer() {
|
||||
return document.body;
|
||||
}
|
||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A36】动作/组合下拉挂到body避免被表格裁切-----------
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.mixing-step-select {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
:deep(.ant-select) {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
:deep(.ant-select-selector) {
|
||||
border: none !important;
|
||||
box-shadow: none !important;
|
||||
background: transparent !important;
|
||||
padding: 0 18px 0 2px !important;
|
||||
min-height: 24px !important;
|
||||
height: 100% !important;
|
||||
display: flex !important;
|
||||
align-items: center !important;
|
||||
}
|
||||
|
||||
:deep(.ant-select-selection-item),
|
||||
:deep(.ant-select-selection-placeholder) {
|
||||
line-height: 1.2 !important;
|
||||
text-align: center;
|
||||
padding-inline-end: 0 !important;
|
||||
}
|
||||
|
||||
:deep(.ant-select-selection-search-input) {
|
||||
height: 100% !important;
|
||||
}
|
||||
|
||||
:deep(.ant-select-arrow) {
|
||||
right: 2px;
|
||||
margin-top: -3px;
|
||||
color: #666;
|
||||
font-size: 10px;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
:deep(.ant-select-clear) {
|
||||
right: 14px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user