package cn.iocoder.yudao.module.mes.service.pro.feedback; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.mes.dal.dataobject.pro.task.MesProTaskDO; import cn.iocoder.yudao.module.mes.dal.mysql.pro.task.MesProTaskMapper; import cn.iocoder.yudao.module.mes.service.pro.feedback.dto.MesFeedbackParamSnapshot; import cn.iocoder.yudao.module.mes.service.pro.feedback.dto.MesTaskParamSnapshot; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; /** 统一参数校验;调用方须在事务中持有任务锁直到报工保存完成。 */ @Service public class MesFeedbackParamService { @Resource private MesProTaskMapper taskMapper; public MesProTaskDO lockTask(Long taskId) { MesProTaskDO task = taskMapper.selectOne(new LambdaQueryWrapperX() .eq(MesProTaskDO::getId, taskId).last("FOR UPDATE")); if (task == null) throw exception(PRO_TASK_NOT_EXISTS); return task; } /** 草稿允许暂不填写;传值时仍校验属于该任务的模板。 */ public String buildDraft(MesProTaskDO task, List values) { if (task.getParamCollectMode() == null || task.getParamCollectMode() == 0 || CollUtil.isEmpty(values)) return null; return buildSnapshot(task, values, false); } /** 提交前锁定任务;任务共用模式首次提交固化数据,后续报工复制同一快照。 */ public String complete(MesProTaskDO lockedTask, String draftSnapshot) { int mode = lockedTask.getParamCollectMode() == null ? 0 : lockedTask.getParamCollectMode(); if (mode == 0) return null; if (mode != 1 && mode != 2) throw exception(PRO_FEEDBACK_PARAM_INVALID, "采集方式不正确"); if (mode == 2 && StrUtil.isNotBlank(lockedTask.getParamSharedSnapshot())) return lockedTask.getParamSharedSnapshot(); MesFeedbackParamSnapshot draft = StrUtil.isBlank(draftSnapshot) ? null : JsonUtils.parseObject(draftSnapshot, MesFeedbackParamSnapshot.class); String result = buildSnapshot(lockedTask, draft == null ? null : draft.getValues(), true); if (mode == 2) { MesProTaskDO update = new MesProTaskDO().setId(lockedTask.getId()).setParamSharedSnapshot(result); if (taskMapper.updateById(update) != 1) throw exception(PRO_TASK_NOT_EXISTS); } return result; } private String buildSnapshot(MesProTaskDO task, List values, boolean requireAll) { MesTaskParamSnapshot template = JsonUtils.parseObject(task.getParamTemplateSnapshot(), MesTaskParamSnapshot.class); if (template == null || CollUtil.isEmpty(template.getDetails())) throw exception(PRO_FEEDBACK_PARAM_INVALID, "任务缺少参数模板快照"); Map expected = new LinkedHashMap<>(); for (var detail : template.getDetails()) expected.put(detail.getId(), detail); Map submitted = new LinkedHashMap<>(); if (values != null) for (var value : values) { if (value == null || value.getDetailId() == null || !expected.containsKey(value.getDetailId())) throw exception(PRO_FEEDBACK_PARAM_INVALID, "参数不属于当前任务的模板"); if (submitted.containsKey(value.getDetailId())) throw exception(PRO_FEEDBACK_PARAM_INVALID, "参数明细重复"); String text = value.getValue(); if (text != null && text.length() > 100) throw exception(PRO_FEEDBACK_PARAM_INVALID, "参数值不能超过 100 字符"); submitted.put(value.getDetailId(), text); } List normalized = new ArrayList<>(); for (var detail : template.getDetails()) { String value = submitted.get(detail.getId()); if (requireAll && Boolean.TRUE.equals(detail.getRequired()) && StrUtil.isBlank(value)) throw exception(PRO_FEEDBACK_PARAM_INVALID, "请填写必填参数:" + detail.getParamName()); if (StrUtil.isNotBlank(value)) { try { if (Objects.equals(detail.getParamType(), 1) || Objects.equals(detail.getParamType(), 2)) new java.math.BigDecimal(value.trim()); if (Objects.equals(detail.getParamType(), 4)) java.time.LocalTime.parse(value.trim()); if (Objects.equals(detail.getParamType(), 5)) java.time.LocalDate.parse(value.trim()); } catch (RuntimeException ex) { throw exception(PRO_FEEDBACK_PARAM_INVALID, "参数格式不正确:" + detail.getParamName()); } } MesFeedbackParamSnapshot.Value item = new MesFeedbackParamSnapshot.Value(); item.setDetailId(detail.getId()); item.setValue(value); normalized.add(item); } MesFeedbackParamSnapshot result = new MesFeedbackParamSnapshot(); result.setTemplate(template); result.setValues(normalized); return JsonUtils.toJsonString(result); } }