新增配方日志查询功能,记录配方和混炼示方的创建、更新与删除操作,增强数据追溯能力。
This commit is contained in:
@@ -414,3 +414,26 @@ jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/ser
|
|||||||
jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslMixerPsCompileServiceImpl.java
|
jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslMixerPsCompileServiceImpl.java
|
||||||
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/MesXslMixingSpec.data.ts
|
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/MesXslMixingSpec.data.ts
|
||||||
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/MesXslMixingSpecList.vue
|
jeecgboot-vue3/src/views/xslmes/mesXslMixingSpec/MesXslMixingSpecList.vue
|
||||||
|
|
||||||
|
-- author:cursor---date:20260526--for: 【配方日志查询】配合示方/混炼示方修改日志记录与查询接口 -----------
|
||||||
|
jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_107__mes_xsl_formula_spec_edit_log.sql
|
||||||
|
jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslFormulaSpecEditLog.java
|
||||||
|
jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslFormulaSpecEditChangeItemVO.java
|
||||||
|
jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslFormulaSpecEditLogDetailVO.java
|
||||||
|
jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/MesXslFormulaSpecEditLogMapper.java
|
||||||
|
jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/common/MesXslFormulaSpecEditLogDiffUtil.java
|
||||||
|
jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslFormulaSpecEditLogService.java
|
||||||
|
jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslFormulaSpecEditLogServiceImpl.java
|
||||||
|
jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslFormulaSpecEditLogController.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/service/impl/MesXslMixingSpecServiceImpl.java
|
||||||
|
|
||||||
|
-- author:cursor---date:20260526--for: 【配方日志查询】前端列表页与修改对比弹窗 -----------
|
||||||
|
jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpecEditLog/MesXslFormulaSpecEditLog.api.ts
|
||||||
|
jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpecEditLog/MesXslFormulaSpecEditLog.data.ts
|
||||||
|
jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpecEditLog/MesXslFormulaSpecEditLogList.vue
|
||||||
|
jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpecEditLog/components/MesXslFormulaSpecEditLogCompareModal.vue
|
||||||
|
|
||||||
|
-- author:cursor---date:20260526--for: 【配方日志查询】明细对比展示逐行逐字段变更内容 -----------
|
||||||
|
jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/common/MesXslFormulaSpecEditLogDiffUtil.java
|
||||||
|
jeecgboot-vue3/src/views/xslmes/mesXslFormulaSpecEditLog/MesXslFormulaSpecEditLog.data.ts
|
||||||
|
|||||||
@@ -0,0 +1,546 @@
|
|||||||
|
package org.jeecg.modules.xslmes.common;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.alibaba.fastjson.JSONArray;
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.alibaba.fastjson.serializer.SerializerFeature;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.jeecg.modules.xslmes.entity.MesXslFormulaSpec;
|
||||||
|
import org.jeecg.modules.xslmes.entity.MesXslFormulaSpecLine;
|
||||||
|
import org.jeecg.modules.xslmes.vo.MesXslFormulaSpecEditChangeItemVO;
|
||||||
|
import org.jeecg.modules.xslmes.vo.MesXslMixingSpecPage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配方示方修改日志:快照序列化与差异对比
|
||||||
|
*/
|
||||||
|
public final class MesXslFormulaSpecEditLogDiffUtil {
|
||||||
|
|
||||||
|
public static final String SECTION_MAIN = "main";
|
||||||
|
public static final String SECTION_LINE = "line";
|
||||||
|
public static final String SECTION_MATERIAL = "material";
|
||||||
|
public static final String SECTION_STEP = "step";
|
||||||
|
public static final String SECTION_DOWN_STEP = "downStep";
|
||||||
|
public static final String SECTION_TCU = "tcu";
|
||||||
|
|
||||||
|
private static final Set<String> IGNORE_FIELDS = Set.of(
|
||||||
|
"id",
|
||||||
|
"createBy",
|
||||||
|
"createTime",
|
||||||
|
"updateBy",
|
||||||
|
"updateTime",
|
||||||
|
"delFlag",
|
||||||
|
"tenantId",
|
||||||
|
"sysOrgCode",
|
||||||
|
"createBy_dictText",
|
||||||
|
"lineList",
|
||||||
|
"materialList",
|
||||||
|
"stepList",
|
||||||
|
"downStepList",
|
||||||
|
"tcuList");
|
||||||
|
|
||||||
|
private static final Map<String, String> FORMULA_MAIN_LABELS = buildFormulaMainLabels();
|
||||||
|
private static final Map<String, String> MIXING_MAIN_LABELS = buildMixingMainLabels();
|
||||||
|
private static final Map<String, String> SECTION_LABELS = Map.of(
|
||||||
|
SECTION_MAIN, "主表",
|
||||||
|
SECTION_LINE, "配合明细",
|
||||||
|
SECTION_MATERIAL, "橡胶及配合剂",
|
||||||
|
SECTION_STEP, "混合步骤",
|
||||||
|
SECTION_DOWN_STEP, "下密炼机条件",
|
||||||
|
SECTION_TCU, "TCU温度条件");
|
||||||
|
|
||||||
|
private static final Map<String, Map<String, String>> SECTION_FIELD_LABELS = buildSectionFieldLabels();
|
||||||
|
private static final Map<String, String[]> SECTION_SUMMARY_FIELDS = buildSectionSummaryFields();
|
||||||
|
|
||||||
|
private MesXslFormulaSpecEditLogDiffUtil() {}
|
||||||
|
|
||||||
|
public static String buildFormulaSnapshotJson(MesXslFormulaSpec main, List<MesXslFormulaSpecLine> lineList) {
|
||||||
|
Map<String, Object> snapshot = new LinkedHashMap<>(2);
|
||||||
|
snapshot.put(SECTION_MAIN, toJsonObject(main));
|
||||||
|
snapshot.put(SECTION_LINE, lineList == null ? List.of() : lineList);
|
||||||
|
return toJson(snapshot);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String buildMixingSnapshotJson(MesXslMixingSpecPage page) {
|
||||||
|
if (page == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Map<String, Object> snapshot = new LinkedHashMap<>(5);
|
||||||
|
snapshot.put(SECTION_MAIN, toJsonObject(page));
|
||||||
|
snapshot.put(SECTION_MATERIAL, page.getMaterialList() == null ? List.of() : page.getMaterialList());
|
||||||
|
snapshot.put(SECTION_STEP, page.getStepList() == null ? List.of() : page.getStepList());
|
||||||
|
snapshot.put(SECTION_DOWN_STEP, page.getDownStepList() == null ? List.of() : page.getDownStepList());
|
||||||
|
snapshot.put(SECTION_TCU, page.getTcuList() == null ? List.of() : page.getTcuList());
|
||||||
|
return toJson(snapshot);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<MesXslFormulaSpecEditChangeItemVO> compare(
|
||||||
|
String specType, String beforeSnapshot, String afterSnapshot) {
|
||||||
|
List<MesXslFormulaSpecEditChangeItemVO> items = new ArrayList<>();
|
||||||
|
JSONObject before = parseObject(beforeSnapshot);
|
||||||
|
JSONObject after = parseObject(afterSnapshot);
|
||||||
|
Map<String, String> mainLabels = SPEC_TYPE_MIXING.equals(specType) ? MIXING_MAIN_LABELS : FORMULA_MAIN_LABELS;
|
||||||
|
compareMainSection(items, before == null ? null : before.getJSONObject(SECTION_MAIN),
|
||||||
|
after == null ? null : after.getJSONObject(SECTION_MAIN), mainLabels);
|
||||||
|
if (SPEC_TYPE_FORMULA.equals(specType)) {
|
||||||
|
compareChildListSection(items, SECTION_LINE, before, after);
|
||||||
|
} else {
|
||||||
|
compareChildListSection(items, SECTION_MATERIAL, before, after);
|
||||||
|
compareChildListSection(items, SECTION_STEP, before, after);
|
||||||
|
compareChildListSection(items, SECTION_DOWN_STEP, before, after);
|
||||||
|
compareChildListSection(items, SECTION_TCU, before, after);
|
||||||
|
}
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String buildSummary(String actionType, List<MesXslFormulaSpecEditChangeItemVO> items) {
|
||||||
|
if ("create".equals(actionType)) {
|
||||||
|
return "新增示方";
|
||||||
|
}
|
||||||
|
if ("delete".equals(actionType)) {
|
||||||
|
return "删除示方";
|
||||||
|
}
|
||||||
|
if (items == null || items.isEmpty()) {
|
||||||
|
return "内容无变化";
|
||||||
|
}
|
||||||
|
Set<String> labels = new LinkedHashSet<>();
|
||||||
|
for (MesXslFormulaSpecEditChangeItemVO item : items) {
|
||||||
|
if (SECTION_MAIN.equals(item.getSection()) && StringUtils.isNotBlank(item.getFieldLabel())) {
|
||||||
|
labels.add(item.getFieldLabel());
|
||||||
|
} else if (StringUtils.isNotBlank(item.getSectionLabel())) {
|
||||||
|
labels.add(item.getSectionLabel());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (labels.isEmpty()) {
|
||||||
|
return "内容有变更";
|
||||||
|
}
|
||||||
|
String joined = String.join("、", labels);
|
||||||
|
if (joined.length() > 180) {
|
||||||
|
joined = joined.substring(0, 177) + "...";
|
||||||
|
}
|
||||||
|
return "修改:" + joined;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void compareMainSection(
|
||||||
|
List<MesXslFormulaSpecEditChangeItemVO> items,
|
||||||
|
JSONObject before,
|
||||||
|
JSONObject after,
|
||||||
|
Map<String, String> labels) {
|
||||||
|
Set<String> keys = new LinkedHashSet<>();
|
||||||
|
if (before != null) {
|
||||||
|
keys.addAll(before.keySet());
|
||||||
|
}
|
||||||
|
if (after != null) {
|
||||||
|
keys.addAll(after.keySet());
|
||||||
|
}
|
||||||
|
for (String key : keys) {
|
||||||
|
if (IGNORE_FIELDS.contains(key)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String beforeVal = formatValue(before == null ? null : before.get(key));
|
||||||
|
String afterVal = formatValue(after == null ? null : after.get(key));
|
||||||
|
if (Objects.equals(beforeVal, afterVal)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
MesXslFormulaSpecEditChangeItemVO item = new MesXslFormulaSpecEditChangeItemVO();
|
||||||
|
item.setSection(SECTION_MAIN);
|
||||||
|
item.setSectionLabel(SECTION_LABELS.get(SECTION_MAIN));
|
||||||
|
item.setFieldKey(key);
|
||||||
|
item.setFieldLabel(labels.getOrDefault(key, key));
|
||||||
|
item.setBeforeValue(beforeVal);
|
||||||
|
item.setAfterValue(afterVal);
|
||||||
|
items.add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void compareChildListSection(
|
||||||
|
List<MesXslFormulaSpecEditChangeItemVO> items, String section, JSONObject before, JSONObject after) {
|
||||||
|
List<JSONObject> beforeList = toJsonObjectList(before == null ? null : before.get(section));
|
||||||
|
List<JSONObject> afterList = toJsonObjectList(after == null ? null : after.get(section));
|
||||||
|
if (Objects.equals(normalizeListJson(beforeList), normalizeListJson(afterList))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Map<String, String> fieldLabels = SECTION_FIELD_LABELS.getOrDefault(section, Map.of());
|
||||||
|
String[] summaryFields = SECTION_SUMMARY_FIELDS.getOrDefault(section, new String[0]);
|
||||||
|
Map<String, JSONObject> beforeMap = indexRows(beforeList);
|
||||||
|
Map<String, JSONObject> afterMap = indexRows(afterList);
|
||||||
|
Set<String> rowKeys = new LinkedHashSet<>();
|
||||||
|
rowKeys.addAll(beforeMap.keySet());
|
||||||
|
rowKeys.addAll(afterMap.keySet());
|
||||||
|
for (String rowKey : rowKeys) {
|
||||||
|
JSONObject beforeRow = beforeMap.get(rowKey);
|
||||||
|
JSONObject afterRow = afterMap.get(rowKey);
|
||||||
|
String rowLabel = formatRowLabel(rowKey);
|
||||||
|
if (beforeRow == null && afterRow != null) {
|
||||||
|
addChangeItem(items, section, rowKey + "_add", rowLabel + "(新增)", "",
|
||||||
|
formatRowSummary(afterRow, fieldLabels, summaryFields));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (beforeRow != null && afterRow == null) {
|
||||||
|
addChangeItem(items, section, rowKey + "_del", rowLabel + "(删除)",
|
||||||
|
formatRowSummary(beforeRow, fieldLabels, summaryFields), "");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
compareRowFields(items, section, rowKey, rowLabel, beforeRow, afterRow, fieldLabels);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void compareRowFields(
|
||||||
|
List<MesXslFormulaSpecEditChangeItemVO> items,
|
||||||
|
String section,
|
||||||
|
String rowKey,
|
||||||
|
String rowLabel,
|
||||||
|
JSONObject beforeRow,
|
||||||
|
JSONObject afterRow,
|
||||||
|
Map<String, String> fieldLabels) {
|
||||||
|
Set<String> keys = new LinkedHashSet<>();
|
||||||
|
keys.addAll(beforeRow.keySet());
|
||||||
|
keys.addAll(afterRow.keySet());
|
||||||
|
for (String key : keys) {
|
||||||
|
if (IGNORE_FIELDS.contains(key) || isRowMetaField(key)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String beforeVal = formatValue(beforeRow.get(key));
|
||||||
|
String afterVal = formatValue(afterRow.get(key));
|
||||||
|
if (Objects.equals(beforeVal, afterVal)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
addChangeItem(
|
||||||
|
items,
|
||||||
|
section,
|
||||||
|
rowKey + "_" + key,
|
||||||
|
rowLabel + "·" + fieldLabels.getOrDefault(key, key),
|
||||||
|
beforeVal,
|
||||||
|
afterVal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void addChangeItem(
|
||||||
|
List<MesXslFormulaSpecEditChangeItemVO> items,
|
||||||
|
String section,
|
||||||
|
String fieldKey,
|
||||||
|
String fieldLabel,
|
||||||
|
String beforeValue,
|
||||||
|
String afterValue) {
|
||||||
|
MesXslFormulaSpecEditChangeItemVO item = new MesXslFormulaSpecEditChangeItemVO();
|
||||||
|
item.setSection(section);
|
||||||
|
item.setSectionLabel(SECTION_LABELS.getOrDefault(section, section));
|
||||||
|
item.setFieldKey(fieldKey);
|
||||||
|
item.setFieldLabel(fieldLabel);
|
||||||
|
item.setBeforeValue(beforeValue);
|
||||||
|
item.setAfterValue(afterValue);
|
||||||
|
items.add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 按 sortNo 优先、否则按列表序号建立行索引 */
|
||||||
|
private static Map<String, JSONObject> indexRows(List<JSONObject> rows) {
|
||||||
|
Map<String, JSONObject> map = new LinkedHashMap<>();
|
||||||
|
if (rows == null) {
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
int index = 0;
|
||||||
|
for (JSONObject row : rows) {
|
||||||
|
index++;
|
||||||
|
if (row == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Integer sortNo = row.getInteger("sortNo");
|
||||||
|
String key = sortNo != null ? "sort_" + sortNo : "idx_" + index;
|
||||||
|
map.put(key, row);
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String formatRowLabel(String rowKey) {
|
||||||
|
if (rowKey.startsWith("sort_")) {
|
||||||
|
return "第" + rowKey.substring(5) + "行";
|
||||||
|
}
|
||||||
|
if (rowKey.startsWith("idx_")) {
|
||||||
|
return "第" + rowKey.substring(4) + "行";
|
||||||
|
}
|
||||||
|
return rowKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String formatRowSummary(JSONObject row, Map<String, String> fieldLabels, String[] summaryFields) {
|
||||||
|
if (row == null || row.isEmpty()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
List<String> parts = new ArrayList<>();
|
||||||
|
for (String key : summaryFields) {
|
||||||
|
String val = formatValue(row.get(key));
|
||||||
|
if (StringUtils.isBlank(val)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
parts.add(fieldLabels.getOrDefault(key, key) + "=" + val);
|
||||||
|
}
|
||||||
|
if (parts.isEmpty()) {
|
||||||
|
for (String key : fieldLabels.keySet()) {
|
||||||
|
String val = formatValue(row.get(key));
|
||||||
|
if (StringUtils.isBlank(val)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
parts.add(fieldLabels.get(key) + "=" + val);
|
||||||
|
if (parts.size() >= 4) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return String.join(",", parts);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isRowMetaField(String key) {
|
||||||
|
return "formulaSpecId".equals(key) || "mixingSpecId".equals(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<JSONObject> toJsonObjectList(Object listObj) {
|
||||||
|
if (listObj == null) {
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
JSONArray array = listObj instanceof JSONArray jsonArray ? jsonArray : JSON.parseArray(toJson(listObj));
|
||||||
|
if (array == null || array.isEmpty()) {
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
List<JSONObject> rows = new ArrayList<>(array.size());
|
||||||
|
for (int i = 0; i < array.size(); i++) {
|
||||||
|
Object element = array.get(i);
|
||||||
|
if (element instanceof JSONObject jsonObject) {
|
||||||
|
rows.add(jsonObject);
|
||||||
|
} else if (element != null) {
|
||||||
|
rows.add(JSON.parseObject(toJson(element)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<String, Map<String, String>> buildSectionFieldLabels() {
|
||||||
|
Map<String, Map<String, String>> map = new LinkedHashMap<>();
|
||||||
|
map.put(SECTION_LINE, buildFormulaLineLabels());
|
||||||
|
map.put(SECTION_MATERIAL, buildMixingMaterialLabels());
|
||||||
|
map.put(SECTION_STEP, buildMixingStepLabels());
|
||||||
|
map.put(SECTION_DOWN_STEP, buildMixingStepLabels());
|
||||||
|
map.put(SECTION_TCU, buildMixingTcuLabels());
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<String, String[]> buildSectionSummaryFields() {
|
||||||
|
Map<String, String[]> map = new LinkedHashMap<>();
|
||||||
|
map.put(SECTION_LINE, new String[] {"mixerMaterialName", "mixerMaterialCode", "phr", "step"});
|
||||||
|
map.put(SECTION_MATERIAL, new String[] {"mixerMaterialName", "unitWeight", "accumWeight", "seqNo"});
|
||||||
|
map.put(SECTION_STEP, new String[] {"actionName", "actionSec", "tempC", "speedRpm"});
|
||||||
|
map.put(SECTION_DOWN_STEP, new String[] {"actionName", "actionSec", "tempC", "speedRpm"});
|
||||||
|
map.put(SECTION_TCU, new String[] {"sectionType", "frontRotorTemp", "rearRotorTemp", "drugWeighPos"});
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<String, String> buildFormulaLineLabels() {
|
||||||
|
Map<String, String> map = new LinkedHashMap<>();
|
||||||
|
map.put("sortNo", "序号");
|
||||||
|
map.put("phr", "PHR");
|
||||||
|
map.put("mixerMaterialCode", "物料编码");
|
||||||
|
map.put("mixerMaterialName", "物料名称");
|
||||||
|
map.put("materialDesc", "物料描述");
|
||||||
|
map.put("step", "STEP");
|
||||||
|
map.put("weighMode", "称量方式");
|
||||||
|
map.put("weightPercent", "重量%");
|
||||||
|
map.put("volume", "体积");
|
||||||
|
map.put("remark", "备注");
|
||||||
|
for (int i = 1; i <= 7; i++) {
|
||||||
|
map.put("stage" + i, "混合段" + i);
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<String, String> buildMixingMaterialLabels() {
|
||||||
|
Map<String, String> map = new LinkedHashMap<>();
|
||||||
|
map.put("sortNo", "序号");
|
||||||
|
map.put("materialMajor", "物料大类");
|
||||||
|
map.put("materialMinor", "物料小类");
|
||||||
|
map.put("materialKind", "种类");
|
||||||
|
map.put("mixerMaterialName", "物料名称");
|
||||||
|
map.put("mixerMaterialDesc", "物料描述");
|
||||||
|
map.put("unitWeight", "单重");
|
||||||
|
map.put("accumWeight", "累计");
|
||||||
|
map.put("seqNo", "顺序");
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<String, String> buildMixingStepLabels() {
|
||||||
|
Map<String, String> map = new LinkedHashMap<>();
|
||||||
|
map.put("sortNo", "序号");
|
||||||
|
map.put("actionName", "动作");
|
||||||
|
map.put("actionSec", "时间(秒)");
|
||||||
|
map.put("protectSec", "保护时间");
|
||||||
|
map.put("tempC", "温度(℃)");
|
||||||
|
map.put("powerKw", "功率(Kw)");
|
||||||
|
map.put("energyKwh", "能量(Kwh)");
|
||||||
|
map.put("comboMode", "组合");
|
||||||
|
map.put("speedRpm", "转速(rpm)");
|
||||||
|
map.put("pressureMpa", "压力(Mpa)");
|
||||||
|
map.put("boltPercent", "栓(%)");
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<String, String> buildMixingTcuLabels() {
|
||||||
|
Map<String, String> map = new LinkedHashMap<>();
|
||||||
|
map.put("sortNo", "序号");
|
||||||
|
map.put("sectionType", "区分");
|
||||||
|
map.put("frontRotorTemp", "前转子温度");
|
||||||
|
map.put("rearRotorTemp", "后转子温度");
|
||||||
|
map.put("frontChamberTemp", "前混炼室温度");
|
||||||
|
map.put("rearChamberTemp", "后混炼室温度");
|
||||||
|
map.put("topPlugTemp", "上下顶栓温度");
|
||||||
|
map.put("drugWeighPos", "药品称量位置");
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JSONObject parseObject(String json) {
|
||||||
|
if (StringUtils.isBlank(json)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return JSON.parseObject(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JSONObject toJsonObject(Object obj) {
|
||||||
|
if (obj == null) {
|
||||||
|
return new JSONObject();
|
||||||
|
}
|
||||||
|
JSONObject jsonObject = JSON.parseObject(toJson(obj));
|
||||||
|
for (String ignore : IGNORE_FIELDS) {
|
||||||
|
jsonObject.remove(ignore);
|
||||||
|
}
|
||||||
|
return jsonObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String toJson(Object obj) {
|
||||||
|
return JSON.toJSONStringWithDateFormat(
|
||||||
|
obj, "yyyy-MM-dd HH:mm:ss", SerializerFeature.WriteMapNullValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String normalizeListJson(Object listObj) {
|
||||||
|
if (listObj == null) {
|
||||||
|
return "[]";
|
||||||
|
}
|
||||||
|
if (listObj instanceof List<?> list) {
|
||||||
|
return normalizeListJson(list);
|
||||||
|
}
|
||||||
|
return toJson(listObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String normalizeListJson(List<JSONObject> rows) {
|
||||||
|
if (rows == null || rows.isEmpty()) {
|
||||||
|
return "[]";
|
||||||
|
}
|
||||||
|
List<JSONObject> normalized = new ArrayList<>(rows.size());
|
||||||
|
for (JSONObject row : rows) {
|
||||||
|
if (row == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
JSONObject copy = new JSONObject(row);
|
||||||
|
for (String ignore : IGNORE_FIELDS) {
|
||||||
|
copy.remove(ignore);
|
||||||
|
}
|
||||||
|
copy.remove("formulaSpecId");
|
||||||
|
copy.remove("mixingSpecId");
|
||||||
|
normalized.add(copy);
|
||||||
|
}
|
||||||
|
return toJson(normalized);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String formatValue(Object value) {
|
||||||
|
if (value == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if (value instanceof BigDecimal decimal) {
|
||||||
|
return decimal.stripTrailingZeros().toPlainString();
|
||||||
|
}
|
||||||
|
if (value instanceof Date date) {
|
||||||
|
return toJson(date).replace("\"", "");
|
||||||
|
}
|
||||||
|
return String.valueOf(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<String, String> buildFormulaMainLabels() {
|
||||||
|
Map<String, String> map = new LinkedHashMap<>();
|
||||||
|
map.put("category", "分类");
|
||||||
|
map.put("specCode", "示方编号");
|
||||||
|
map.put("rubberCode", "胶料代号");
|
||||||
|
map.put("rubberMaterialId", "胶料ID");
|
||||||
|
map.put("basicFormula", "基本配合");
|
||||||
|
map.put("issueDate", "发行日期");
|
||||||
|
map.put("purpose", "用途");
|
||||||
|
map.put("issueNumber", "发行编号");
|
||||||
|
map.put("mixingStages", "混合段数");
|
||||||
|
map.put("mixingMachine", "混合机器");
|
||||||
|
map.put("issueDeptId", "发行部门ID");
|
||||||
|
map.put("issueDeptName", "发行部门");
|
||||||
|
map.put("status", "状态");
|
||||||
|
map.put("aRubberTotalPhr", "A胶合计PHR");
|
||||||
|
map.put("totalPhr", "总PHR");
|
||||||
|
map.put("naturalRubber", "天然橡胶");
|
||||||
|
map.put("syntheticRubber", "合成橡胶");
|
||||||
|
map.put("totalAmount", "总量");
|
||||||
|
map.put("weightUnitPrice", "重量单价");
|
||||||
|
map.put("volumeUnitPrice", "体积单价");
|
||||||
|
map.put("qRubberSg", "Q胶比重");
|
||||||
|
map.put("aRubberSg", "A胶比重");
|
||||||
|
map.put("proofreadBy", "校对人");
|
||||||
|
map.put("proofreadTime", "校对时间");
|
||||||
|
map.put("auditBy", "审核人");
|
||||||
|
map.put("auditTime", "审核时间");
|
||||||
|
map.put("approveBy", "批准人");
|
||||||
|
map.put("approveTime", "批准时间");
|
||||||
|
for (int i = 1; i <= 7; i++) {
|
||||||
|
map.put("stage" + i + "Total", "混合段" + i + "合计");
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<String, String> buildMixingMainLabels() {
|
||||||
|
Map<String, String> map = new LinkedHashMap<>();
|
||||||
|
map.put("specName", "规格");
|
||||||
|
map.put("purpose", "用途");
|
||||||
|
map.put("machineId", "机台ID");
|
||||||
|
map.put("machineName", "机台");
|
||||||
|
map.put("makeDate", "制作日期");
|
||||||
|
map.put("issueNumber", "发行编号");
|
||||||
|
map.put("convertFactor", "换算系数");
|
||||||
|
map.put("fillVolume", "填充体积");
|
||||||
|
map.put("recycleCarbonSec", "回收炭黑(秒)");
|
||||||
|
map.put("motherRubberSg", "母胶比重");
|
||||||
|
map.put("finalRubberSg", "终炼胶比重");
|
||||||
|
map.put("applyFactory", "适用工厂");
|
||||||
|
map.put("stageCount", "段数");
|
||||||
|
map.put("pureMixSec", "纯混炼时间(秒)");
|
||||||
|
map.put("recycleCarbonKg", "回收炭黑(kg)");
|
||||||
|
map.put("autoSmallPrintSetting", "自动小票打印设置");
|
||||||
|
map.put("setTrainCount", "设定车次");
|
||||||
|
map.put("sideWallWaterTemp", "侧壁水温");
|
||||||
|
map.put("overtimeDischargeSec", "超时排胶(秒)");
|
||||||
|
map.put("overtempDischargeSec", "超温排胶(秒)");
|
||||||
|
map.put("overtempDischargeTemp", "超温排胶温度");
|
||||||
|
map.put("doorWaterTemp", "门水温");
|
||||||
|
map.put("rotorWaterTemp", "转子水温");
|
||||||
|
map.put("maxFeedTemp", "最高投料温度");
|
||||||
|
map.put("draftBy", "编制人");
|
||||||
|
map.put("draftTime", "编制时间");
|
||||||
|
map.put("proofreadBy", "校对人");
|
||||||
|
map.put("proofreadTime", "校对时间");
|
||||||
|
map.put("auditBy", "审核人");
|
||||||
|
map.put("auditTime", "审核时间");
|
||||||
|
map.put("approveBy", "批准人");
|
||||||
|
map.put("approveTime", "批准时间");
|
||||||
|
map.put("changeDate", "变更日期");
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final String SPEC_TYPE_FORMULA = "formula";
|
||||||
|
public static final String SPEC_TYPE_MIXING = "mixing";
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
package org.jeecg.modules.xslmes.controller;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||||
|
import org.jeecg.common.api.vo.Result;
|
||||||
|
import org.jeecg.common.system.base.controller.JeecgController;
|
||||||
|
import org.jeecg.common.system.query.QueryGenerator;
|
||||||
|
import org.jeecg.modules.xslmes.entity.MesXslFormulaSpecEditLog;
|
||||||
|
import org.jeecg.modules.xslmes.service.IMesXslFormulaSpecEditLogService;
|
||||||
|
import org.jeecg.modules.xslmes.vo.MesXslFormulaSpecEditLogDetailVO;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import org.springframework.web.servlet.ModelAndView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配方示方修改日志(只读查询)
|
||||||
|
*/
|
||||||
|
@Tag(name = "配方日志查询")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/xslmes/mesXslFormulaSpecEditLog")
|
||||||
|
@Slf4j
|
||||||
|
public class MesXslFormulaSpecEditLogController
|
||||||
|
extends JeecgController<MesXslFormulaSpecEditLog, IMesXslFormulaSpecEditLogService> {
|
||||||
|
|
||||||
|
@Operation(summary = "配方日志查询-分页列表")
|
||||||
|
@RequiresPermissions("xslmes:mes_xsl_formula_spec_edit_log:list")
|
||||||
|
@GetMapping(value = "/list")
|
||||||
|
public Result<IPage<MesXslFormulaSpecEditLog>> queryPageList(
|
||||||
|
MesXslFormulaSpecEditLog entity,
|
||||||
|
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
|
||||||
|
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
|
||||||
|
HttpServletRequest req) {
|
||||||
|
QueryWrapper<MesXslFormulaSpecEditLog> qw = QueryGenerator.initQueryWrapper(entity, req.getParameterMap());
|
||||||
|
qw.orderByDesc("modify_time");
|
||||||
|
Page<MesXslFormulaSpecEditLog> page = new Page<>(pageNo, pageSize);
|
||||||
|
return Result.OK(service.page(page, qw));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "配方日志查询-详情(含对比项)")
|
||||||
|
@RequiresPermissions("xslmes:mes_xsl_formula_spec_edit_log:list")
|
||||||
|
@GetMapping(value = "/queryById")
|
||||||
|
public Result<MesXslFormulaSpecEditLogDetailVO> queryById(@RequestParam(name = "id", required = true) String id) {
|
||||||
|
MesXslFormulaSpecEditLogDetailVO detail = service.getDetail(id);
|
||||||
|
if (detail == null) {
|
||||||
|
return Result.error("未找到对应数据");
|
||||||
|
}
|
||||||
|
return Result.OK(detail);
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresPermissions("xslmes:mes_xsl_formula_spec_edit_log:exportXls")
|
||||||
|
@RequestMapping(value = "/exportXls")
|
||||||
|
public ModelAndView exportXls(HttpServletRequest request, MesXslFormulaSpecEditLog entity) {
|
||||||
|
return super.exportXls(request, entity, MesXslFormulaSpecEditLog.class, "配方日志查询");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
package org.jeecg.modules.xslmes.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
import org.jeecg.common.aspect.annotation.Dict;
|
||||||
|
import org.jeecgframework.poi.excel.annotation.Excel;
|
||||||
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配方示方修改日志(配合示方/混炼示方)
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@TableName("mes_xsl_formula_spec_edit_log")
|
||||||
|
@Accessors(chain = true)
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
@Schema(description = "配方示方修改日志")
|
||||||
|
public class MesXslFormulaSpecEditLog implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@TableId(type = IdType.ASSIGN_ID)
|
||||||
|
@Schema(description = "主键")
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
@Excel(name = "示方分类", width = 12, dicCode = "xslmes_formula_spec_edit_log_type")
|
||||||
|
@Dict(dicCode = "xslmes_formula_spec_edit_log_type")
|
||||||
|
@Schema(description = "示方分类 formula=配合示方 mixing=混炼示方")
|
||||||
|
private String specType;
|
||||||
|
|
||||||
|
@Schema(description = "示方主表ID")
|
||||||
|
private String specId;
|
||||||
|
|
||||||
|
@Excel(name = "示方标识", width = 22)
|
||||||
|
@Schema(description = "示方标识(胶料代号/规格名)")
|
||||||
|
private String specTitle;
|
||||||
|
|
||||||
|
@Excel(name = "发行编号", width = 16)
|
||||||
|
@Schema(description = "发行编号")
|
||||||
|
private String issueNumber;
|
||||||
|
|
||||||
|
@Excel(name = "操作类型", width = 10, dicCode = "xslmes_formula_spec_edit_log_action")
|
||||||
|
@Dict(dicCode = "xslmes_formula_spec_edit_log_action")
|
||||||
|
@Schema(description = "操作类型 create=新增 update=修改 delete=删除")
|
||||||
|
private String actionType;
|
||||||
|
|
||||||
|
@Excel(name = "修改内容", width = 50)
|
||||||
|
@Schema(description = "修改内容摘要")
|
||||||
|
private String changeSummary;
|
||||||
|
|
||||||
|
@Schema(description = "变更前快照JSON")
|
||||||
|
private String beforeSnapshot;
|
||||||
|
|
||||||
|
@Schema(description = "变更后快照JSON")
|
||||||
|
private String afterSnapshot;
|
||||||
|
|
||||||
|
@Excel(name = "修改时间", width = 20, format = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
@Schema(description = "修改时间")
|
||||||
|
private Date modifyTime;
|
||||||
|
|
||||||
|
@Schema(description = "修改人账号")
|
||||||
|
private String modifyBy;
|
||||||
|
|
||||||
|
@Excel(name = "修改人", width = 14)
|
||||||
|
@Schema(description = "修改人姓名")
|
||||||
|
private String modifyByName;
|
||||||
|
|
||||||
|
@Schema(description = "租户ID")
|
||||||
|
private Integer tenantId;
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package org.jeecg.modules.xslmes.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import org.jeecg.modules.xslmes.entity.MesXslFormulaSpecEditLog;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配方示方修改日志
|
||||||
|
*/
|
||||||
|
public interface MesXslFormulaSpecEditLogMapper extends BaseMapper<MesXslFormulaSpecEditLog> {}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package org.jeecg.modules.xslmes.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import java.util.List;
|
||||||
|
import org.jeecg.modules.xslmes.entity.MesXslFormulaSpec;
|
||||||
|
import org.jeecg.modules.xslmes.entity.MesXslFormulaSpecEditLog;
|
||||||
|
import org.jeecg.modules.xslmes.entity.MesXslFormulaSpecLine;
|
||||||
|
import org.jeecg.modules.xslmes.vo.MesXslFormulaSpecEditChangeItemVO;
|
||||||
|
import org.jeecg.modules.xslmes.vo.MesXslFormulaSpecEditLogDetailVO;
|
||||||
|
import org.jeecg.modules.xslmes.vo.MesXslMixingSpecPage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配方示方修改日志
|
||||||
|
*/
|
||||||
|
public interface IMesXslFormulaSpecEditLogService extends IService<MesXslFormulaSpecEditLog> {
|
||||||
|
|
||||||
|
String SPEC_TYPE_FORMULA = "formula";
|
||||||
|
String SPEC_TYPE_MIXING = "mixing";
|
||||||
|
String ACTION_CREATE = "create";
|
||||||
|
String ACTION_UPDATE = "update";
|
||||||
|
String ACTION_DELETE = "delete";
|
||||||
|
|
||||||
|
void recordFormulaCreate(MesXslFormulaSpec main, List<MesXslFormulaSpecLine> lineList);
|
||||||
|
|
||||||
|
void recordFormulaUpdate(
|
||||||
|
MesXslFormulaSpec beforeMain,
|
||||||
|
List<MesXslFormulaSpecLine> beforeLines,
|
||||||
|
MesXslFormulaSpec afterMain,
|
||||||
|
List<MesXslFormulaSpecLine> afterLines);
|
||||||
|
|
||||||
|
void recordFormulaDelete(MesXslFormulaSpec main, List<MesXslFormulaSpecLine> lineList);
|
||||||
|
|
||||||
|
void recordMixingCreate(MesXslMixingSpecPage after);
|
||||||
|
|
||||||
|
void recordMixingUpdate(MesXslMixingSpecPage before, MesXslMixingSpecPage after);
|
||||||
|
|
||||||
|
void recordMixingDelete(MesXslMixingSpecPage before);
|
||||||
|
|
||||||
|
MesXslFormulaSpecEditLogDetailVO getDetail(String id);
|
||||||
|
|
||||||
|
List<MesXslFormulaSpecEditChangeItemVO> buildChangeItems(
|
||||||
|
String specType, String beforeSnapshot, String afterSnapshot);
|
||||||
|
}
|
||||||
@@ -0,0 +1,256 @@
|
|||||||
|
package org.jeecg.modules.xslmes.service.impl;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.shiro.SecurityUtils;
|
||||||
|
import org.jeecg.common.system.vo.LoginUser;
|
||||||
|
import org.jeecg.modules.xslmes.common.MesXslFormulaSpecEditLogDiffUtil;
|
||||||
|
import org.jeecg.modules.xslmes.entity.MesXslFormulaSpec;
|
||||||
|
import org.jeecg.modules.xslmes.entity.MesXslFormulaSpecEditLog;
|
||||||
|
import org.jeecg.modules.xslmes.entity.MesXslFormulaSpecLine;
|
||||||
|
import org.jeecg.modules.xslmes.mapper.MesXslFormulaSpecEditLogMapper;
|
||||||
|
import org.jeecg.modules.xslmes.service.IMesXslFormulaSpecEditLogService;
|
||||||
|
import org.jeecg.modules.xslmes.vo.MesXslFormulaSpecEditChangeItemVO;
|
||||||
|
import org.jeecg.modules.xslmes.vo.MesXslFormulaSpecEditLogDetailVO;
|
||||||
|
import org.jeecg.modules.xslmes.vo.MesXslMixingSpecPage;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配方示方修改日志
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class MesXslFormulaSpecEditLogServiceImpl
|
||||||
|
extends ServiceImpl<MesXslFormulaSpecEditLogMapper, MesXslFormulaSpecEditLog>
|
||||||
|
implements IMesXslFormulaSpecEditLogService {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void recordFormulaCreate(MesXslFormulaSpec main, List<MesXslFormulaSpecLine> lineList) {
|
||||||
|
if (main == null || StringUtils.isBlank(main.getId())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String afterSnapshot = MesXslFormulaSpecEditLogDiffUtil.buildFormulaSnapshotJson(main, lineList);
|
||||||
|
List<MesXslFormulaSpecEditChangeItemVO> items =
|
||||||
|
buildChangeItems(SPEC_TYPE_FORMULA, null, afterSnapshot);
|
||||||
|
saveLog(SPEC_TYPE_FORMULA, main.getId(), resolveFormulaTitle(main), main.getIssueNumber(),
|
||||||
|
ACTION_CREATE, null, afterSnapshot, items, main.getTenantId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void recordFormulaUpdate(
|
||||||
|
MesXslFormulaSpec beforeMain,
|
||||||
|
List<MesXslFormulaSpecLine> beforeLines,
|
||||||
|
MesXslFormulaSpec afterMain,
|
||||||
|
List<MesXslFormulaSpecLine> afterLines) {
|
||||||
|
if (afterMain == null || StringUtils.isBlank(afterMain.getId())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String beforeSnapshot = MesXslFormulaSpecEditLogDiffUtil.buildFormulaSnapshotJson(beforeMain, beforeLines);
|
||||||
|
String afterSnapshot = MesXslFormulaSpecEditLogDiffUtil.buildFormulaSnapshotJson(afterMain, afterLines);
|
||||||
|
List<MesXslFormulaSpecEditChangeItemVO> items =
|
||||||
|
buildChangeItems(SPEC_TYPE_FORMULA, beforeSnapshot, afterSnapshot);
|
||||||
|
if (items.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
saveLog(
|
||||||
|
SPEC_TYPE_FORMULA,
|
||||||
|
afterMain.getId(),
|
||||||
|
resolveFormulaTitle(afterMain),
|
||||||
|
afterMain.getIssueNumber(),
|
||||||
|
ACTION_UPDATE,
|
||||||
|
beforeSnapshot,
|
||||||
|
afterSnapshot,
|
||||||
|
items,
|
||||||
|
afterMain.getTenantId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void recordFormulaDelete(MesXslFormulaSpec main, List<MesXslFormulaSpecLine> lineList) {
|
||||||
|
if (main == null || StringUtils.isBlank(main.getId())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String beforeSnapshot = MesXslFormulaSpecEditLogDiffUtil.buildFormulaSnapshotJson(main, lineList);
|
||||||
|
List<MesXslFormulaSpecEditChangeItemVO> items =
|
||||||
|
buildChangeItems(SPEC_TYPE_FORMULA, beforeSnapshot, null);
|
||||||
|
saveLog(
|
||||||
|
SPEC_TYPE_FORMULA,
|
||||||
|
main.getId(),
|
||||||
|
resolveFormulaTitle(main),
|
||||||
|
main.getIssueNumber(),
|
||||||
|
ACTION_DELETE,
|
||||||
|
beforeSnapshot,
|
||||||
|
null,
|
||||||
|
items,
|
||||||
|
main.getTenantId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void recordMixingCreate(MesXslMixingSpecPage after) {
|
||||||
|
if (after == null || StringUtils.isBlank(after.getId())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String afterSnapshot = MesXslFormulaSpecEditLogDiffUtil.buildMixingSnapshotJson(after);
|
||||||
|
List<MesXslFormulaSpecEditChangeItemVO> items =
|
||||||
|
buildChangeItems(SPEC_TYPE_MIXING, null, afterSnapshot);
|
||||||
|
saveLog(
|
||||||
|
SPEC_TYPE_MIXING,
|
||||||
|
after.getId(),
|
||||||
|
resolveMixingTitle(after),
|
||||||
|
after.getIssueNumber(),
|
||||||
|
ACTION_CREATE,
|
||||||
|
null,
|
||||||
|
afterSnapshot,
|
||||||
|
items,
|
||||||
|
after.getTenantId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void recordMixingUpdate(MesXslMixingSpecPage before, MesXslMixingSpecPage after) {
|
||||||
|
if (after == null || StringUtils.isBlank(after.getId())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String beforeSnapshot = MesXslFormulaSpecEditLogDiffUtil.buildMixingSnapshotJson(before);
|
||||||
|
String afterSnapshot = MesXslFormulaSpecEditLogDiffUtil.buildMixingSnapshotJson(after);
|
||||||
|
List<MesXslFormulaSpecEditChangeItemVO> items =
|
||||||
|
buildChangeItems(SPEC_TYPE_MIXING, beforeSnapshot, afterSnapshot);
|
||||||
|
if (items.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
saveLog(
|
||||||
|
SPEC_TYPE_MIXING,
|
||||||
|
after.getId(),
|
||||||
|
resolveMixingTitle(after),
|
||||||
|
after.getIssueNumber(),
|
||||||
|
ACTION_UPDATE,
|
||||||
|
beforeSnapshot,
|
||||||
|
afterSnapshot,
|
||||||
|
items,
|
||||||
|
after.getTenantId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void recordMixingDelete(MesXslMixingSpecPage before) {
|
||||||
|
if (before == null || StringUtils.isBlank(before.getId())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String beforeSnapshot = MesXslFormulaSpecEditLogDiffUtil.buildMixingSnapshotJson(before);
|
||||||
|
List<MesXslFormulaSpecEditChangeItemVO> items =
|
||||||
|
buildChangeItems(SPEC_TYPE_MIXING, beforeSnapshot, null);
|
||||||
|
saveLog(
|
||||||
|
SPEC_TYPE_MIXING,
|
||||||
|
before.getId(),
|
||||||
|
resolveMixingTitle(before),
|
||||||
|
before.getIssueNumber(),
|
||||||
|
ACTION_DELETE,
|
||||||
|
beforeSnapshot,
|
||||||
|
null,
|
||||||
|
items,
|
||||||
|
before.getTenantId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MesXslFormulaSpecEditLogDetailVO getDetail(String id) {
|
||||||
|
MesXslFormulaSpecEditLog row = getById(id);
|
||||||
|
if (row == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
MesXslFormulaSpecEditLogDetailVO detail = new MesXslFormulaSpecEditLogDetailVO();
|
||||||
|
detail.setId(row.getId());
|
||||||
|
detail.setSpecType(row.getSpecType());
|
||||||
|
detail.setSpecId(row.getSpecId());
|
||||||
|
detail.setSpecTitle(row.getSpecTitle());
|
||||||
|
detail.setIssueNumber(row.getIssueNumber());
|
||||||
|
detail.setActionType(row.getActionType());
|
||||||
|
detail.setChangeSummary(row.getChangeSummary());
|
||||||
|
detail.setBeforeSnapshot(row.getBeforeSnapshot());
|
||||||
|
detail.setAfterSnapshot(row.getAfterSnapshot());
|
||||||
|
detail.setModifyTime(row.getModifyTime());
|
||||||
|
detail.setModifyBy(row.getModifyBy());
|
||||||
|
detail.setModifyByName(row.getModifyByName());
|
||||||
|
detail.setTenantId(row.getTenantId());
|
||||||
|
detail.setBeforeData(parseSnapshot(row.getBeforeSnapshot()));
|
||||||
|
detail.setAfterData(parseSnapshot(row.getAfterSnapshot()));
|
||||||
|
detail.setChangeItems(buildChangeItems(row.getSpecType(), row.getBeforeSnapshot(), row.getAfterSnapshot()));
|
||||||
|
return detail;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<MesXslFormulaSpecEditChangeItemVO> buildChangeItems(
|
||||||
|
String specType, String beforeSnapshot, String afterSnapshot) {
|
||||||
|
return MesXslFormulaSpecEditLogDiffUtil.compare(specType, beforeSnapshot, afterSnapshot);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveLog(
|
||||||
|
String specType,
|
||||||
|
String specId,
|
||||||
|
String specTitle,
|
||||||
|
String issueNumber,
|
||||||
|
String actionType,
|
||||||
|
String beforeSnapshot,
|
||||||
|
String afterSnapshot,
|
||||||
|
List<MesXslFormulaSpecEditChangeItemVO> items,
|
||||||
|
Integer tenantId) {
|
||||||
|
LoginUser loginUser = resolveLoginUser();
|
||||||
|
MesXslFormulaSpecEditLog row = new MesXslFormulaSpecEditLog();
|
||||||
|
row.setSpecType(specType);
|
||||||
|
row.setSpecId(specId);
|
||||||
|
row.setSpecTitle(specTitle);
|
||||||
|
row.setIssueNumber(issueNumber);
|
||||||
|
row.setActionType(actionType);
|
||||||
|
row.setChangeSummary(MesXslFormulaSpecEditLogDiffUtil.buildSummary(actionType, items));
|
||||||
|
row.setBeforeSnapshot(beforeSnapshot);
|
||||||
|
row.setAfterSnapshot(afterSnapshot);
|
||||||
|
row.setModifyTime(new Date());
|
||||||
|
if (loginUser != null) {
|
||||||
|
row.setModifyBy(loginUser.getUsername());
|
||||||
|
row.setModifyByName(StringUtils.defaultIfBlank(loginUser.getRealname(), loginUser.getUsername()));
|
||||||
|
} else {
|
||||||
|
row.setModifyByName("未知");
|
||||||
|
}
|
||||||
|
row.setTenantId(tenantId);
|
||||||
|
save(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Object parseSnapshot(String snapshot) {
|
||||||
|
if (StringUtils.isBlank(snapshot)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return JSON.parse(snapshot);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String resolveFormulaTitle(MesXslFormulaSpec main) {
|
||||||
|
if (main == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotBlank(main.getRubberCode())) {
|
||||||
|
return main.getRubberCode();
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotBlank(main.getSpecCode())) {
|
||||||
|
return main.getSpecCode();
|
||||||
|
}
|
||||||
|
return main.getIssueNumber();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String resolveMixingTitle(MesXslMixingSpecPage page) {
|
||||||
|
if (page == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return StringUtils.defaultIfBlank(page.getSpecName(), page.getIssueNumber());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static LoginUser resolveLoginUser() {
|
||||||
|
try {
|
||||||
|
Object principal = SecurityUtils.getSubject().getPrincipal();
|
||||||
|
if (principal instanceof LoginUser loginUser) {
|
||||||
|
return loginUser;
|
||||||
|
}
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
// 免密或未登录场景
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -37,6 +37,7 @@ import org.jeecg.modules.xslmes.entity.MesXslMixingSpecMaterial;
|
|||||||
import org.jeecg.modules.xslmes.mapper.MesXslFormulaSpecLineMapper;
|
import org.jeecg.modules.xslmes.mapper.MesXslFormulaSpecLineMapper;
|
||||||
import org.jeecg.modules.xslmes.mapper.MesXslFormulaSpecMapper;
|
import org.jeecg.modules.xslmes.mapper.MesXslFormulaSpecMapper;
|
||||||
import org.jeecg.modules.xslmes.service.IMesXslEquipmentLedgerService;
|
import org.jeecg.modules.xslmes.service.IMesXslEquipmentLedgerService;
|
||||||
|
import org.jeecg.modules.xslmes.service.IMesXslFormulaSpecEditLogService;
|
||||||
import org.jeecg.modules.xslmes.service.IMesXslFormulaSpecService;
|
import org.jeecg.modules.xslmes.service.IMesXslFormulaSpecService;
|
||||||
import org.jeecg.modules.xslmes.service.IMesXslFormulaSpecSettingService;
|
import org.jeecg.modules.xslmes.service.IMesXslFormulaSpecSettingService;
|
||||||
import org.jeecg.modules.xslmes.service.IMesXslMixerMaterialKindCfgService;
|
import org.jeecg.modules.xslmes.service.IMesXslMixerMaterialKindCfgService;
|
||||||
@@ -95,6 +96,9 @@ public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecM
|
|||||||
@Resource
|
@Resource
|
||||||
private IMesXslMixerMaterialKindCfgService mesXslMixerMaterialKindCfgService;
|
private IMesXslMixerMaterialKindCfgService mesXslMixerMaterialKindCfgService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private IMesXslFormulaSpecEditLogService mesXslFormulaSpecEditLogService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void saveMain(MesXslFormulaSpec main, List<MesXslFormulaSpecLine> lineList) {
|
public void saveMain(MesXslFormulaSpec main, List<MesXslFormulaSpecLine> lineList) {
|
||||||
@@ -105,21 +109,43 @@ public class MesXslFormulaSpecServiceImpl extends ServiceImpl<MesXslFormulaSpecM
|
|||||||
this.save(main);
|
this.save(main);
|
||||||
insertLines(main, lineList);
|
insertLines(main, lineList);
|
||||||
refreshMainSummary(main.getId());
|
refreshMainSummary(main.getId());
|
||||||
|
//update-begin---author:cursor ---date:20260526 for:【配方日志查询】配合示方新增落库修改日志-----------
|
||||||
|
MesXslFormulaSpec saved = getByIdWithLines(main.getId());
|
||||||
|
if (saved != null) {
|
||||||
|
mesXslFormulaSpecEditLogService.recordFormulaCreate(saved, saved.getLineList());
|
||||||
|
}
|
||||||
|
//update-end---author:cursor ---date:20260526 for:【配方日志查询】配合示方新增落库修改日志-----------
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void updateMain(MesXslFormulaSpec main, List<MesXslFormulaSpecLine> lineList) {
|
public void updateMain(MesXslFormulaSpec main, List<MesXslFormulaSpecLine> lineList) {
|
||||||
|
//update-begin---author:cursor ---date:20260526 for:【配方日志查询】配合示方编辑前抓取快照-----------
|
||||||
|
MesXslFormulaSpec before = getByIdWithLines(main.getId());
|
||||||
|
//update-end---author:cursor ---date:20260526 for:【配方日志查询】配合示方编辑前抓取快照-----------
|
||||||
fillMainDefaults(main);
|
fillMainDefaults(main);
|
||||||
this.updateById(main);
|
this.updateById(main);
|
||||||
lineMapper.delete(new LambdaQueryWrapper<MesXslFormulaSpecLine>().eq(MesXslFormulaSpecLine::getFormulaSpecId, main.getId()));
|
lineMapper.delete(new LambdaQueryWrapper<MesXslFormulaSpecLine>().eq(MesXslFormulaSpecLine::getFormulaSpecId, main.getId()));
|
||||||
insertLines(main, lineList);
|
insertLines(main, lineList);
|
||||||
refreshMainSummary(main.getId());
|
refreshMainSummary(main.getId());
|
||||||
|
//update-begin---author:cursor ---date:20260526 for:【配方日志查询】配合示方编辑落库修改日志-----------
|
||||||
|
MesXslFormulaSpec after = getByIdWithLines(main.getId());
|
||||||
|
if (after != null) {
|
||||||
|
mesXslFormulaSpecEditLogService.recordFormulaUpdate(
|
||||||
|
before, before == null ? null : before.getLineList(), after, after.getLineList());
|
||||||
|
}
|
||||||
|
//update-end---author:cursor ---date:20260526 for:【配方日志查询】配合示方编辑落库修改日志-----------
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void delMain(String id) {
|
public void delMain(String id) {
|
||||||
|
//update-begin---author:cursor ---date:20260526 for:【配方日志查询】配合示方删除落库修改日志-----------
|
||||||
|
MesXslFormulaSpec before = getByIdWithLines(id);
|
||||||
|
if (before != null) {
|
||||||
|
mesXslFormulaSpecEditLogService.recordFormulaDelete(before, before.getLineList());
|
||||||
|
}
|
||||||
|
//update-end---author:cursor ---date:20260526 for:【配方日志查询】配合示方删除落库修改日志-----------
|
||||||
lineMapper.delete(new LambdaQueryWrapper<MesXslFormulaSpecLine>().eq(MesXslFormulaSpecLine::getFormulaSpecId, id));
|
lineMapper.delete(new LambdaQueryWrapper<MesXslFormulaSpecLine>().eq(MesXslFormulaSpecLine::getFormulaSpecId, id));
|
||||||
this.removeById(id);
|
this.removeById(id);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import org.jeecg.modules.xslmes.mapper.MesXslMixingSpecMapper;
|
|||||||
import org.jeecg.modules.xslmes.mapper.MesXslMixingSpecMaterialMapper;
|
import org.jeecg.modules.xslmes.mapper.MesXslMixingSpecMaterialMapper;
|
||||||
import org.jeecg.modules.xslmes.mapper.MesXslMixingSpecStepMapper;
|
import org.jeecg.modules.xslmes.mapper.MesXslMixingSpecStepMapper;
|
||||||
import org.jeecg.modules.xslmes.mapper.MesXslMixingSpecTcuMapper;
|
import org.jeecg.modules.xslmes.mapper.MesXslMixingSpecTcuMapper;
|
||||||
|
import org.jeecg.modules.xslmes.service.IMesXslFormulaSpecEditLogService;
|
||||||
import org.jeecg.modules.xslmes.service.IMesXslMixingSpecService;
|
import org.jeecg.modules.xslmes.service.IMesXslMixingSpecService;
|
||||||
import org.jeecg.modules.xslmes.vo.MesXslMixingSpecPage;
|
import org.jeecg.modules.xslmes.vo.MesXslMixingSpecPage;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@@ -74,6 +75,9 @@ public class MesXslMixingSpecServiceImpl extends ServiceImpl<MesXslMixingSpecMap
|
|||||||
@Resource
|
@Resource
|
||||||
private ISysCategoryService sysCategoryService;
|
private ISysCategoryService sysCategoryService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private IMesXslFormulaSpecEditLogService mesXslFormulaSpecEditLogService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void saveMain(
|
public void saveMain(
|
||||||
@@ -93,6 +97,12 @@ public class MesXslMixingSpecServiceImpl extends ServiceImpl<MesXslMixingSpecMap
|
|||||||
trace.step("saveMain", "mainId", main.getId());
|
trace.step("saveMain", "mainId", main.getId());
|
||||||
saveChildren(main.getId(), materialList, stepList, downStepList, tcuList, trace);
|
saveChildren(main.getId(), materialList, stepList, downStepList, tcuList, trace);
|
||||||
trace.finish();
|
trace.finish();
|
||||||
|
//update-begin---author:cursor ---date:20260526 for:【配方日志查询】混炼示方新增落库修改日志-----------
|
||||||
|
MesXslMixingSpecPage saved = queryPageById(main.getId());
|
||||||
|
if (saved != null) {
|
||||||
|
mesXslFormulaSpecEditLogService.recordMixingCreate(saved);
|
||||||
|
}
|
||||||
|
//update-end---author:cursor ---date:20260526 for:【配方日志查询】混炼示方新增落库修改日志-----------
|
||||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A17】混炼示方主子表新增保存-----------
|
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A17】混炼示方主子表新增保存-----------
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,6 +119,9 @@ public class MesXslMixingSpecServiceImpl extends ServiceImpl<MesXslMixingSpecMap
|
|||||||
trace.logPayloadSize(materialList, stepList, downStepList, tcuList);
|
trace.logPayloadSize(materialList, stepList, downStepList, tcuList);
|
||||||
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A47】混炼示方保存分步骤性能日志-----------
|
//update-end---author:cursor ---date:20260525 for:【XSLMES-20260525-A47】混炼示方保存分步骤性能日志-----------
|
||||||
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A17】混炼示方主子表编辑保存-----------
|
//update-begin---author:cursor ---date:20260522 for:【XSLMES-20260522-A17】混炼示方主子表编辑保存-----------
|
||||||
|
//update-begin---author:cursor ---date:20260526 for:【配方日志查询】混炼示方编辑前抓取快照-----------
|
||||||
|
MesXslMixingSpecPage before = queryPageById(main.getId());
|
||||||
|
//update-end---author:cursor ---date:20260526 for:【配方日志查询】混炼示方编辑前抓取快照-----------
|
||||||
normalizeMain(main);
|
normalizeMain(main);
|
||||||
trace.step("normalizeMain");
|
trace.step("normalizeMain");
|
||||||
this.updateById(main);
|
this.updateById(main);
|
||||||
@@ -116,6 +129,12 @@ public class MesXslMixingSpecServiceImpl extends ServiceImpl<MesXslMixingSpecMap
|
|||||||
clearChildren(main.getId(), trace);
|
clearChildren(main.getId(), trace);
|
||||||
saveChildren(main.getId(), materialList, stepList, downStepList, tcuList, trace);
|
saveChildren(main.getId(), materialList, stepList, downStepList, tcuList, trace);
|
||||||
trace.finish();
|
trace.finish();
|
||||||
|
//update-begin---author:cursor ---date:20260526 for:【配方日志查询】混炼示方编辑落库修改日志-----------
|
||||||
|
MesXslMixingSpecPage after = queryPageById(main.getId());
|
||||||
|
if (after != null) {
|
||||||
|
mesXslFormulaSpecEditLogService.recordMixingUpdate(before, after);
|
||||||
|
}
|
||||||
|
//update-end---author:cursor ---date:20260526 for:【配方日志查询】混炼示方编辑落库修改日志-----------
|
||||||
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A17】混炼示方主子表编辑保存-----------
|
//update-end---author:cursor ---date:20260522 for:【XSLMES-20260522-A17】混炼示方主子表编辑保存-----------
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,6 +169,14 @@ public class MesXslMixingSpecServiceImpl extends ServiceImpl<MesXslMixingSpecMap
|
|||||||
if (CollectionUtils.isEmpty(mains)) {
|
if (CollectionUtils.isEmpty(mains)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
//update-begin---author:cursor ---date:20260526 for:【配方日志查询】混炼示方删除落库修改日志-----------
|
||||||
|
for (String id : ids) {
|
||||||
|
MesXslMixingSpecPage before = queryPageById(id);
|
||||||
|
if (before != null) {
|
||||||
|
mesXslFormulaSpecEditLogService.recordMixingDelete(before);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//update-end---author:cursor ---date:20260526 for:【配方日志查询】混炼示方删除落库修改日志-----------
|
||||||
clearChildrenBatch(ids);
|
clearChildrenBatch(ids);
|
||||||
this.removeByIds(ids);
|
this.removeByIds(ids);
|
||||||
Set<String> specNames = new LinkedHashSet<>();
|
Set<String> specNames = new LinkedHashSet<>();
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package org.jeecg.modules.xslmes.vo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配方日志字段级对比项
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Schema(description = "配方日志对比项")
|
||||||
|
public class MesXslFormulaSpecEditChangeItemVO {
|
||||||
|
|
||||||
|
@Schema(description = "所属区块 main/line/material/step/downStep/tcu")
|
||||||
|
private String section;
|
||||||
|
|
||||||
|
@Schema(description = "区块中文名")
|
||||||
|
private String sectionLabel;
|
||||||
|
|
||||||
|
@Schema(description = "字段键")
|
||||||
|
private String fieldKey;
|
||||||
|
|
||||||
|
@Schema(description = "字段中文名")
|
||||||
|
private String fieldLabel;
|
||||||
|
|
||||||
|
@Schema(description = "变更前值")
|
||||||
|
private String beforeValue;
|
||||||
|
|
||||||
|
@Schema(description = "变更后值")
|
||||||
|
private String afterValue;
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package org.jeecg.modules.xslmes.vo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import java.util.List;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import org.jeecg.modules.xslmes.entity.MesXslFormulaSpecEditLog;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配方日志详情(含对比项)
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Schema(description = "配方日志详情")
|
||||||
|
public class MesXslFormulaSpecEditLogDetailVO extends MesXslFormulaSpecEditLog {
|
||||||
|
|
||||||
|
@Schema(description = "变更前快照对象")
|
||||||
|
private Object beforeData;
|
||||||
|
|
||||||
|
@Schema(description = "变更后快照对象")
|
||||||
|
private Object afterData;
|
||||||
|
|
||||||
|
@Schema(description = "字段级对比项")
|
||||||
|
private List<MesXslFormulaSpecEditChangeItemVO> changeItems;
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,10 @@
|
|||||||
|
-- 分类字典:统一租户ID为1002(幂等)
|
||||||
|
SET NAMES utf8mb4;
|
||||||
|
|
||||||
|
SET @mes_tenant_id = 1002;
|
||||||
|
|
||||||
|
UPDATE `sys_category`
|
||||||
|
SET `tenant_id` = @mes_tenant_id,
|
||||||
|
`update_by` = 'admin',
|
||||||
|
`update_time` = NOW()
|
||||||
|
WHERE IFNULL(`tenant_id`, 0) <> @mes_tenant_id;
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
-- 配方日志查询:配合示方/混炼示方修改日志表 + 字典 + 菜单
|
||||||
|
SET NAMES utf8mb4;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS `mes_xsl_formula_spec_edit_log` (
|
||||||
|
`id` varchar(32) NOT NULL COMMENT '主键',
|
||||||
|
`spec_type` varchar(20) NOT NULL COMMENT '示方分类 formula=配合示方 mixing=混炼示方',
|
||||||
|
`spec_id` varchar(32) NOT NULL COMMENT '示方主表ID',
|
||||||
|
`spec_title` varchar(200) DEFAULT NULL COMMENT '示方标识(胶料代号/规格名)',
|
||||||
|
`issue_number` varchar(64) DEFAULT NULL COMMENT '发行编号',
|
||||||
|
`action_type` varchar(20) NOT NULL COMMENT '操作类型 create=新增 update=修改 delete=删除',
|
||||||
|
`change_summary` varchar(2000) DEFAULT NULL COMMENT '修改内容摘要',
|
||||||
|
`before_snapshot` longtext COMMENT '变更前快照JSON',
|
||||||
|
`after_snapshot` longtext COMMENT '变更后快照JSON',
|
||||||
|
`modify_time` datetime DEFAULT NULL COMMENT '修改时间',
|
||||||
|
`modify_by` varchar(64) DEFAULT NULL COMMENT '修改人账号',
|
||||||
|
`modify_by_name` varchar(100) DEFAULT NULL COMMENT '修改人姓名',
|
||||||
|
`tenant_id` int DEFAULT NULL COMMENT '租户ID',
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `idx_fsel_spec_type` (`spec_type`),
|
||||||
|
KEY `idx_fsel_spec_id` (`spec_id`),
|
||||||
|
KEY `idx_fsel_issue_no` (`issue_number`),
|
||||||
|
KEY `idx_fsel_modify_time` (`modify_time`),
|
||||||
|
KEY `idx_fsel_tenant` (`tenant_id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='MES配方示方修改日志';
|
||||||
|
|
||||||
|
INSERT IGNORE INTO `sys_dict` (`id`, `dict_name`, `dict_code`, `description`, `del_flag`, `create_by`, `create_time`, `type`, `tenant_id`)
|
||||||
|
VALUES ('1995000000000000107', '配方日志示方分类', 'xslmes_formula_spec_edit_log_type', '配方日志查询-示方分类', 0, 'admin', NOW(), 0, 1002);
|
||||||
|
|
||||||
|
INSERT IGNORE INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`)
|
||||||
|
VALUES ('1995000000000001071', '1995000000000000107', '配合示方', 'formula', 1, 1, 'admin', NOW());
|
||||||
|
|
||||||
|
INSERT IGNORE INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`)
|
||||||
|
VALUES ('1995000000000001072', '1995000000000000107', '混炼示方', 'mixing', 2, 1, 'admin', NOW());
|
||||||
|
|
||||||
|
INSERT IGNORE INTO `sys_dict` (`id`, `dict_name`, `dict_code`, `description`, `del_flag`, `create_by`, `create_time`, `type`, `tenant_id`)
|
||||||
|
VALUES ('1995000000000000108', '配方日志操作类型', 'xslmes_formula_spec_edit_log_action', '配方日志查询-操作类型', 0, 'admin', NOW(), 0, 1002);
|
||||||
|
|
||||||
|
INSERT IGNORE INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`)
|
||||||
|
VALUES ('1995000000000001081', '1995000000000000108', '新增', 'create', 1, 1, 'admin', NOW());
|
||||||
|
|
||||||
|
INSERT IGNORE INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`)
|
||||||
|
VALUES ('1995000000000001082', '1995000000000000108', '修改', 'update', 2, 1, 'admin', NOW());
|
||||||
|
|
||||||
|
INSERT IGNORE INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `sort_order`, `status`, `create_by`, `create_time`)
|
||||||
|
VALUES ('1995000000000001083', '1995000000000000108', '删除', 'delete', 3, 1, 'admin', NOW());
|
||||||
|
|
||||||
|
INSERT IGNORE INTO `sys_permission` (
|
||||||
|
`id`, `parent_id`, `name`, `url`, `component`, `is_route`, `component_name`, `redirect`,
|
||||||
|
`menu_type`, `perms`, `perms_type`, `sort_no`, `always_show`, `icon`, `is_leaf`, `keep_alive`,
|
||||||
|
`hidden`, `hide_tab`, `description`, `create_by`, `create_time`, `update_by`, `update_time`,
|
||||||
|
`del_flag`, `rule_flag`, `status`, `internal_or_external`
|
||||||
|
) VALUES (
|
||||||
|
'177925970995560', '1900000000000000810', '配方日志查询', '/xslmes/mesXslFormulaSpecEditLog',
|
||||||
|
'xslmes/mesXslFormulaSpecEditLog/MesXslFormulaSpecEditLogList', 1, 'MesXslFormulaSpecEditLogList', NULL,
|
||||||
|
1, NULL, '0', 5.50, 0, 'ant-design:file-search-outlined', 0, 1,
|
||||||
|
0, 0, '配合示方/混炼示方修改日志查询与对比', 'admin', NOW(), 'admin', NOW(),
|
||||||
|
0, 0, '1', 0
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT IGNORE INTO `sys_permission` (`id`, `parent_id`, `name`, `menu_type`, `perms`, `perms_type`, `sort_no`, `is_route`, `is_leaf`, `hidden`, `status`, `del_flag`, `create_by`, `create_time`)
|
||||||
|
VALUES ('177925970995561', '177925970995560', '查询', 2, 'xslmes:mes_xsl_formula_spec_edit_log:list', '1', 1.00, 0, 1, 0, '1', 0, 'admin', NOW());
|
||||||
|
|
||||||
|
INSERT IGNORE INTO `sys_permission` (`id`, `parent_id`, `name`, `menu_type`, `perms`, `perms_type`, `sort_no`, `is_route`, `is_leaf`, `hidden`, `status`, `del_flag`, `create_by`, `create_time`)
|
||||||
|
VALUES ('177925970995562', '177925970995560', '导出', 2, 'xslmes:mes_xsl_formula_spec_edit_log:exportXls', '1', 2.00, 0, 1, 0, '1', 0, 'admin', NOW());
|
||||||
|
|
||||||
|
INSERT INTO `sys_role_permission` (`id`, `role_id`, `permission_id`, `data_rule_ids`, `operate_date`, `operate_ip`)
|
||||||
|
SELECT REPLACE(UUID(), '-', ''), r.id, p.id, NULL, NOW(), '127.0.0.1'
|
||||||
|
FROM `sys_role` r
|
||||||
|
CROSS JOIN `sys_permission` p
|
||||||
|
WHERE r.`role_code` = 'admin'
|
||||||
|
AND p.`id` IN ('177925970995560', '177925970995561', '177925970995562')
|
||||||
|
AND NOT EXISTS (
|
||||||
|
SELECT 1 FROM `sys_role_permission` rp
|
||||||
|
WHERE rp.`role_id` = r.id AND rp.`permission_id` = p.id
|
||||||
|
);
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""生成分类字典「行政区划」Flyway SQL(国家-省-市-县)"""
|
||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
MYSQL_DIR = Path(__file__).resolve().parents[1]
|
||||||
|
JEECG_BOOT = Path(__file__).resolve().parents[9]
|
||||||
|
PCA_PATH = JEECG_BOOT / 'jeecg-boot-base-core/src/main/resources/static/pca.json'
|
||||||
|
OUT_PATH = MYSQL_DIR / 'V3.9.2_105__sys_region_category_dict.sql'
|
||||||
|
|
||||||
|
MES_TENANT_ID = 1002
|
||||||
|
|
||||||
|
pca = json.loads(PCA_PATH.read_text(encoding='utf-8'))
|
||||||
|
|
||||||
|
OTHER_COUNTRIES = [
|
||||||
|
('阿富汗', 'AF'), ('阿尔巴尼亚', 'AL'), ('阿尔及利亚', 'DZ'), ('安道尔', 'AD'), ('安哥拉', 'AO'),
|
||||||
|
('安提瓜和巴布达', 'AG'), ('阿根廷', 'AR'), ('亚美尼亚', 'AM'), ('澳大利亚', 'AU'), ('奥地利', 'AT'),
|
||||||
|
('阿塞拜疆', 'AZ'), ('巴哈马', 'BS'), ('巴林', 'BH'), ('孟加拉国', 'BD'), ('巴巴多斯', 'BB'),
|
||||||
|
('白俄罗斯', 'BY'), ('比利时', 'BE'), ('伯利兹', 'BZ'), ('贝宁', 'BJ'), ('不丹', 'BT'),
|
||||||
|
('玻利维亚', 'BO'), ('波黑', 'BA'), ('博茨瓦纳', 'BW'), ('巴西', 'BR'), ('文莱', 'BN'),
|
||||||
|
('保加利亚', 'BG'), ('布基纳法索', 'BF'), ('布隆迪', 'BI'), ('佛得角', 'CV'), ('柬埔寨', 'KH'),
|
||||||
|
('喀麦隆', 'CM'), ('加拿大', 'CA'), ('中非', 'CF'), ('乍得', 'TD'), ('智利', 'CL'),
|
||||||
|
('哥伦比亚', 'CO'), ('科摩罗', 'KM'), ('刚果(布)', 'CG'), ('刚果(金)', 'CD'), ('哥斯达黎加', 'CR'),
|
||||||
|
('科特迪瓦', 'CI'), ('克罗地亚', 'HR'), ('古巴', 'CU'), ('塞浦路斯', 'CY'), ('捷克', 'CZ'),
|
||||||
|
('丹麦', 'DK'), ('吉布提', 'DJ'), ('多米尼克', 'DM'), ('多米尼加', 'DO'), ('厄瓜多尔', 'EC'),
|
||||||
|
('埃及', 'EG'), ('萨尔瓦多', 'SV'), ('赤道几内亚', 'GQ'), ('厄立特里亚', 'ER'), ('爱沙尼亚', 'EE'),
|
||||||
|
('斯威士兰', 'SZ'), ('埃塞俄比亚', 'ET'), ('斐济', 'FJ'), ('芬兰', 'FI'), ('法国', 'FR'),
|
||||||
|
('加蓬', 'GA'), ('冈比亚', 'GM'), ('格鲁吉亚', 'GE'), ('德国', 'DE'), ('加纳', 'GH'),
|
||||||
|
('希腊', 'GR'), ('格林纳达', 'GD'), ('危地马拉', 'GT'), ('几内亚', 'GN'), ('几内亚比绍', 'GW'),
|
||||||
|
('圭亚那', 'GY'), ('海地', 'HT'), ('洪都拉斯', 'HN'), ('匈牙利', 'HU'), ('冰岛', 'IS'),
|
||||||
|
('印度', 'IN'), ('印度尼西亚', 'ID'), ('伊朗', 'IR'), ('伊拉克', 'IQ'), ('爱尔兰', 'IE'),
|
||||||
|
('以色列', 'IL'), ('意大利', 'IT'), ('牙买加', 'JM'), ('日本', 'JP'), ('约旦', 'JO'),
|
||||||
|
('哈萨克斯坦', 'KZ'), ('肯尼亚', 'KE'), ('基里巴斯', 'KI'), ('科威特', 'KW'), ('吉尔吉斯斯坦', 'KG'),
|
||||||
|
('老挝', 'LA'), ('拉脱维亚', 'LV'), ('黎巴嫩', 'LB'), ('莱索托', 'LS'), ('利比里亚', 'LR'),
|
||||||
|
('利比亚', 'LY'), ('列支敦士登', 'LI'), ('立陶宛', 'LT'), ('卢森堡', 'LU'), ('马达加斯加', 'MG'),
|
||||||
|
('马拉维', 'MW'), ('马来西亚', 'MY'), ('马尔代夫', 'MV'), ('马里', 'ML'), ('马耳他', 'MT'),
|
||||||
|
('马绍尔群岛', 'MH'), ('毛里塔尼亚', 'MR'), ('毛里求斯', 'MU'), ('墨西哥', 'MX'), ('密克罗尼西亚', 'FM'),
|
||||||
|
('摩尔多瓦', 'MD'), ('摩纳哥', 'MC'), ('蒙古', 'MN'), ('黑山', 'ME'), ('摩洛哥', 'MA'),
|
||||||
|
('莫桑比克', 'MZ'), ('缅甸', 'MM'), ('纳米比亚', 'NA'), ('瑙鲁', 'NR'), ('尼泊尔', 'NP'),
|
||||||
|
('荷兰', 'NL'), ('新西兰', 'NZ'), ('尼加拉瓜', 'NI'), ('尼日尔', 'NE'), ('尼日利亚', 'NG'),
|
||||||
|
('朝鲜', 'KP'), ('北马其顿', 'MK'), ('挪威', 'NO'), ('阿曼', 'OM'), ('巴基斯坦', 'PK'),
|
||||||
|
('帕劳', 'PW'), ('巴拿马', 'PA'), ('巴布亚新几内亚', 'PG'), ('巴拉圭', 'PY'), ('秘鲁', 'PE'),
|
||||||
|
('菲律宾', 'PH'), ('波兰', 'PL'), ('葡萄牙', 'PT'), ('卡塔尔', 'QA'), ('罗马尼亚', 'RO'),
|
||||||
|
('俄罗斯', 'RU'), ('卢旺达', 'RW'), ('圣基茨和尼维斯', 'KN'), ('圣卢西亚', 'LC'), ('圣文森特和格林纳丁斯', 'VC'),
|
||||||
|
('萨摩亚', 'WS'), ('圣马力诺', 'SM'), ('圣多美和普林西比', 'ST'), ('沙特阿拉伯', 'SA'), ('塞内加尔', 'SN'),
|
||||||
|
('塞尔维亚', 'RS'), ('塞舌尔', 'SC'), ('塞拉利昂', 'SL'), ('新加坡', 'SG'), ('斯洛伐克', 'SK'),
|
||||||
|
('斯洛文尼亚', 'SI'), ('所罗门群岛', 'SB'), ('索马里', 'SO'), ('南非', 'ZA'), ('韩国', 'KR'),
|
||||||
|
('南苏丹', 'SS'), ('西班牙', 'ES'), ('斯里兰卡', 'LK'), ('苏丹', 'SD'), ('苏里南', 'SR'),
|
||||||
|
('瑞典', 'SE'), ('瑞士', 'CH'), ('叙利亚', 'SY'), ('塔吉克斯坦', 'TJ'), ('坦桑尼亚', 'TZ'),
|
||||||
|
('泰国', 'TH'), ('东帝汶', 'TL'), ('多哥', 'TG'), ('汤加', 'TO'), ('特立尼达和多巴哥', 'TT'),
|
||||||
|
('突尼斯', 'TN'), ('土耳其', 'TR'), ('土库曼斯坦', 'TM'), ('图瓦卢', 'TV'), ('乌干达', 'UG'),
|
||||||
|
('乌克兰', 'UA'), ('阿联酋', 'AE'), ('英国', 'GB'), ('美国', 'US'), ('乌拉圭', 'UY'),
|
||||||
|
('乌兹别克斯坦', 'UZ'), ('瓦努阿图', 'VU'), ('梵蒂冈', 'VA'), ('委内瑞拉', 'VE'), ('越南', 'VN'),
|
||||||
|
('也门', 'YE'), ('赞比亚', 'ZM'), ('津巴布韦', 'ZW'),
|
||||||
|
]
|
||||||
|
|
||||||
|
seq = 0
|
||||||
|
|
||||||
|
|
||||||
|
def make_id(code: str) -> str:
|
||||||
|
global seq
|
||||||
|
if code.isdigit():
|
||||||
|
return f'1995{int(code):015d}'
|
||||||
|
seq += 1
|
||||||
|
return f'1995900000000{seq:06d}'
|
||||||
|
|
||||||
|
|
||||||
|
def esc(s: str) -> str:
|
||||||
|
return s.replace('\\', '\\\\').replace("'", "''")
|
||||||
|
|
||||||
|
|
||||||
|
nodes = []
|
||||||
|
root_id = '1995000000000000001'
|
||||||
|
nodes.append({'id': root_id, 'pid': '0', 'name': '行政区划', 'code': 'SYS_REGION', 'has_child': '1'})
|
||||||
|
|
||||||
|
cn_id = make_id('86')
|
||||||
|
nodes.append({'id': cn_id, 'pid': root_id, 'name': '中国', 'code': 'SYS_REGION_86', 'has_child': '1'})
|
||||||
|
|
||||||
|
for prov_code, prov_name in pca['86'].items():
|
||||||
|
prov_id = make_id(prov_code)
|
||||||
|
cities = pca.get(prov_code, {})
|
||||||
|
nodes.append({'id': prov_id, 'pid': cn_id, 'name': prov_name, 'code': prov_code, 'has_child': '1' if cities else '0'})
|
||||||
|
for city_code, city_name in cities.items():
|
||||||
|
city_id = make_id(city_code)
|
||||||
|
counties = pca.get(city_code, {})
|
||||||
|
nodes.append({'id': city_id, 'pid': prov_id, 'name': city_name, 'code': city_code, 'has_child': '1' if counties else '0'})
|
||||||
|
for county_code, county_name in counties.items():
|
||||||
|
nodes.append({'id': make_id(county_code), 'pid': city_id, 'name': county_name, 'code': county_code, 'has_child': '0'})
|
||||||
|
|
||||||
|
for name, iso in OTHER_COUNTRIES:
|
||||||
|
nodes.append({'id': make_id(f'C{iso}'), 'pid': root_id, 'name': name, 'code': f'SYS_REGION_{iso}', 'has_child': '0'})
|
||||||
|
|
||||||
|
lines = [
|
||||||
|
'-- 分类字典:国家-省-市-县 四级行政区划(幂等)',
|
||||||
|
'-- 数据来源:JeecgBoot pca.json + ISO3166 国家列表',
|
||||||
|
'SET NAMES utf8mb4;',
|
||||||
|
'',
|
||||||
|
]
|
||||||
|
batch_size = 50
|
||||||
|
for i in range(0, len(nodes), batch_size):
|
||||||
|
batch = nodes[i : i + batch_size]
|
||||||
|
lines.append('INSERT INTO `sys_category` (`id`, `pid`, `name`, `code`, `has_child`, `is_rubber`, `tenant_id`, `create_by`, `create_time`)')
|
||||||
|
values = []
|
||||||
|
for n in batch:
|
||||||
|
values.append(
|
||||||
|
"SELECT '{id}', '{pid}', '{name}', '{code}', '{has_child}', '0', {tenant_id}, 'admin', NOW() FROM DUAL "
|
||||||
|
"WHERE NOT EXISTS (SELECT 1 FROM `sys_category` WHERE `code` = '{code}')".format(
|
||||||
|
id=n['id'], pid=n['pid'], name=esc(n['name']), code=n['code'], has_child=n['has_child'], tenant_id=MES_TENANT_ID
|
||||||
|
)
|
||||||
|
)
|
||||||
|
lines.append('\nUNION ALL\n'.join(values))
|
||||||
|
lines.append(';')
|
||||||
|
lines.append('')
|
||||||
|
|
||||||
|
OUT_PATH.write_text('\n'.join(lines), encoding='utf-8')
|
||||||
|
print(f'Generated {len(nodes)} nodes -> {OUT_PATH}')
|
||||||
|
print(f'File size: {OUT_PATH.stat().st_size / 1024:.1f} KB')
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import { defHttp } from '/@/utils/http/axios';
|
||||||
|
|
||||||
|
enum Api {
|
||||||
|
list = '/xslmes/mesXslFormulaSpecEditLog/list',
|
||||||
|
queryById = '/xslmes/mesXslFormulaSpecEditLog/queryById',
|
||||||
|
exportXls = '/xslmes/mesXslFormulaSpecEditLog/exportXls',
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getExportUrl = Api.exportXls;
|
||||||
|
|
||||||
|
export const list = (params) => defHttp.get({ url: Api.list, params });
|
||||||
|
|
||||||
|
export const queryById = (params) => defHttp.get({ url: Api.queryById, params });
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
import { BasicColumn, FormSchema } from '/@/components/Table';
|
||||||
|
|
||||||
|
export const SPEC_TYPE_DICT = 'xslmes_formula_spec_edit_log_type';
|
||||||
|
export const ACTION_TYPE_DICT = 'xslmes_formula_spec_edit_log_action';
|
||||||
|
|
||||||
|
export const columns: BasicColumn[] = [
|
||||||
|
{
|
||||||
|
title: '示方分类',
|
||||||
|
align: 'center',
|
||||||
|
dataIndex: 'specType_dictText',
|
||||||
|
width: 110,
|
||||||
|
},
|
||||||
|
{ title: '示方标识', align: 'center', dataIndex: 'specTitle', width: 180, ellipsis: true },
|
||||||
|
{ title: '发行编号', align: 'center', dataIndex: 'issueNumber', width: 140 },
|
||||||
|
{
|
||||||
|
title: '操作类型',
|
||||||
|
align: 'center',
|
||||||
|
dataIndex: 'actionType_dictText',
|
||||||
|
width: 90,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '修改内容',
|
||||||
|
align: 'left',
|
||||||
|
dataIndex: 'changeSummary',
|
||||||
|
width: 320,
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '修改时间',
|
||||||
|
align: 'center',
|
||||||
|
dataIndex: 'modifyTime',
|
||||||
|
width: 165,
|
||||||
|
},
|
||||||
|
{ title: '修改人', align: 'center', dataIndex: 'modifyByName', width: 110 },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const searchFormSchema: FormSchema[] = [
|
||||||
|
{
|
||||||
|
label: '示方分类',
|
||||||
|
field: 'specType',
|
||||||
|
component: 'JDictSelectTag',
|
||||||
|
componentProps: { dictCode: SPEC_TYPE_DICT, placeholder: '全部' },
|
||||||
|
colProps: { span: 6 },
|
||||||
|
},
|
||||||
|
{ label: '示方标识', field: 'specTitle', component: 'JInput', colProps: { span: 6 } },
|
||||||
|
{ label: '发行编号', field: 'issueNumber', component: 'JInput', colProps: { span: 6 } },
|
||||||
|
{
|
||||||
|
label: '操作类型',
|
||||||
|
field: 'actionType',
|
||||||
|
component: 'JDictSelectTag',
|
||||||
|
componentProps: { dictCode: ACTION_TYPE_DICT, placeholder: '全部' },
|
||||||
|
colProps: { span: 6 },
|
||||||
|
},
|
||||||
|
{ label: '修改人', field: 'modifyByName', component: 'Input', colProps: { span: 6 } },
|
||||||
|
{
|
||||||
|
label: '修改时间',
|
||||||
|
field: 'modifyTime',
|
||||||
|
component: 'RangePicker',
|
||||||
|
colProps: { span: 8 },
|
||||||
|
componentProps: {
|
||||||
|
showTime: true,
|
||||||
|
valueFormat: 'YYYY-MM-DD HH:mm:ss',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const changeItemColumns: BasicColumn[] = [
|
||||||
|
{ title: '区块', align: 'center', dataIndex: 'sectionLabel', width: 120 },
|
||||||
|
{ title: '字段/行', align: 'center', dataIndex: 'fieldLabel', width: 160 },
|
||||||
|
{
|
||||||
|
title: '变更前',
|
||||||
|
align: 'left',
|
||||||
|
dataIndex: 'beforeValue',
|
||||||
|
width: 280,
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '变更后',
|
||||||
|
align: 'left',
|
||||||
|
dataIndex: 'afterValue',
|
||||||
|
width: 280,
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<BasicTable @register="registerTable">
|
||||||
|
<template #tableTitle>
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
v-auth="'xslmes:mes_xsl_formula_spec_edit_log:exportXls'"
|
||||||
|
preIcon="ant-design:export-outlined"
|
||||||
|
@click="onExportXls"
|
||||||
|
>
|
||||||
|
导出
|
||||||
|
</a-button>
|
||||||
|
</template>
|
||||||
|
<template #action="{ record }">
|
||||||
|
<TableAction
|
||||||
|
:actions="[
|
||||||
|
{
|
||||||
|
label: '查看对比',
|
||||||
|
onClick: handleCompare.bind(null, record),
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</BasicTable>
|
||||||
|
<MesXslFormulaSpecEditLogCompareModal @register="registerCompareModal" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" name="xslmes-mesXslFormulaSpecEditLog" setup>
|
||||||
|
import { reactive } from 'vue';
|
||||||
|
import { BasicTable, TableAction } from '/@/components/Table';
|
||||||
|
import { useModal } from '/@/components/Modal';
|
||||||
|
import { useListPage } from '/@/hooks/system/useListPage';
|
||||||
|
import MesXslFormulaSpecEditLogCompareModal from './components/MesXslFormulaSpecEditLogCompareModal.vue';
|
||||||
|
import { columns, searchFormSchema } from './MesXslFormulaSpecEditLog.data';
|
||||||
|
import { list, getExportUrl } from './MesXslFormulaSpecEditLog.api';
|
||||||
|
|
||||||
|
const queryParam = reactive<any>({});
|
||||||
|
const [registerCompareModal, { openModal: openCompareModal }] = useModal();
|
||||||
|
|
||||||
|
const { tableContext, onExportXls } = useListPage({
|
||||||
|
tableProps: {
|
||||||
|
title: '配方日志查询',
|
||||||
|
api: list,
|
||||||
|
columns,
|
||||||
|
canResize: true,
|
||||||
|
showIndexColumn: true,
|
||||||
|
tableSetting: { cacheKey: 'mesXslFormulaSpecEditLog_v20260526' },
|
||||||
|
formConfig: {
|
||||||
|
schemas: searchFormSchema,
|
||||||
|
labelWidth: 90,
|
||||||
|
autoSubmitOnEnter: true,
|
||||||
|
showAdvancedButton: true,
|
||||||
|
fieldMapToTime: [['modifyTime', ['modifyTime_begin', 'modifyTime_end'], 'YYYY-MM-DD HH:mm:ss']],
|
||||||
|
},
|
||||||
|
actionColumn: {
|
||||||
|
title: '操作',
|
||||||
|
dataIndex: 'action',
|
||||||
|
width: 110,
|
||||||
|
fixed: 'right',
|
||||||
|
slots: { customRender: 'action' },
|
||||||
|
},
|
||||||
|
beforeFetch: (params) => Object.assign(params, queryParam),
|
||||||
|
},
|
||||||
|
exportConfig: {
|
||||||
|
name: '配方日志查询',
|
||||||
|
url: getExportUrl,
|
||||||
|
params: queryParam,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const [registerTable] = tableContext;
|
||||||
|
|
||||||
|
function handleCompare(record: Recordable) {
|
||||||
|
openCompareModal(true, { record });
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
<template>
|
||||||
|
<BasicModal
|
||||||
|
v-bind="$attrs"
|
||||||
|
@register="registerModal"
|
||||||
|
title="配方修改对比"
|
||||||
|
:width="1100"
|
||||||
|
destroyOnClose
|
||||||
|
:showOkBtn="false"
|
||||||
|
cancelText="关闭"
|
||||||
|
>
|
||||||
|
<a-spin :spinning="loading">
|
||||||
|
<a-descriptions bordered :column="2" size="small" class="mb-4">
|
||||||
|
<a-descriptions-item label="示方分类">{{ detail?.specType_dictText || detail?.specType || '-' }}</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="操作类型">{{ detail?.actionType_dictText || detail?.actionType || '-' }}</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="示方标识">{{ detail?.specTitle || '-' }}</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="发行编号">{{ detail?.issueNumber || '-' }}</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="修改人">{{ detail?.modifyByName || '-' }}</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="修改时间">{{ detail?.modifyTime || '-' }}</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="修改内容" :span="2">{{ detail?.changeSummary || '-' }}</a-descriptions-item>
|
||||||
|
</a-descriptions>
|
||||||
|
|
||||||
|
<a-tabs v-model:activeKey="activeTab">
|
||||||
|
<a-tab-pane key="changes" tab="字段对比">
|
||||||
|
<BasicTable
|
||||||
|
:columns="changeItemColumns"
|
||||||
|
:dataSource="changeItems"
|
||||||
|
:pagination="false"
|
||||||
|
:canResize="false"
|
||||||
|
size="small"
|
||||||
|
bordered
|
||||||
|
rowKey="rowKey"
|
||||||
|
/>
|
||||||
|
<a-empty v-if="!loading && changeItems.length === 0" description="暂无字段级差异(新增/删除或无变更字段)" />
|
||||||
|
</a-tab-pane>
|
||||||
|
<a-tab-pane key="before" tab="变更前快照">
|
||||||
|
<pre class="snapshot-pre">{{ formatSnapshot(detail?.beforeData) }}</pre>
|
||||||
|
</a-tab-pane>
|
||||||
|
<a-tab-pane key="after" tab="变更后快照">
|
||||||
|
<pre class="snapshot-pre">{{ formatSnapshot(detail?.afterData) }}</pre>
|
||||||
|
</a-tab-pane>
|
||||||
|
</a-tabs>
|
||||||
|
</a-spin>
|
||||||
|
</BasicModal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { BasicModal, useModalInner } from '/@/components/Modal';
|
||||||
|
import { BasicTable } from '/@/components/Table';
|
||||||
|
import { changeItemColumns } from '../MesXslFormulaSpecEditLog.data';
|
||||||
|
import { queryById } from '../MesXslFormulaSpecEditLog.api';
|
||||||
|
|
||||||
|
defineEmits(['register']);
|
||||||
|
|
||||||
|
const loading = ref(false);
|
||||||
|
const activeTab = ref('changes');
|
||||||
|
const detail = ref<Recordable | null>(null);
|
||||||
|
const changeItems = ref<Recordable[]>([]);
|
||||||
|
|
||||||
|
const [registerModal, { setModalProps }] = useModalInner(async (data) => {
|
||||||
|
activeTab.value = 'changes';
|
||||||
|
detail.value = null;
|
||||||
|
changeItems.value = [];
|
||||||
|
setModalProps({ confirmLoading: false });
|
||||||
|
const id = data?.record?.id;
|
||||||
|
if (!id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
loading.value = true;
|
||||||
|
try {
|
||||||
|
const result = await queryById({ id });
|
||||||
|
detail.value = result || {};
|
||||||
|
changeItems.value = (result?.changeItems || []).map((item, index) => ({
|
||||||
|
...item,
|
||||||
|
rowKey: `${item.section || ''}_${item.fieldKey || ''}_${index}`,
|
||||||
|
}));
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function formatSnapshot(data: unknown) {
|
||||||
|
if (data == null) {
|
||||||
|
return '(无)';
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return JSON.stringify(data, null, 2);
|
||||||
|
} catch {
|
||||||
|
return String(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.snapshot-pre {
|
||||||
|
max-height: 480px;
|
||||||
|
overflow: auto;
|
||||||
|
margin: 0;
|
||||||
|
padding: 12px;
|
||||||
|
background: #fafafa;
|
||||||
|
border: 1px solid #f0f0f0;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.5;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user