From 0c5e29044ab39c9db25f52d380d63740bbb7e674 Mon Sep 17 00:00:00 2001 From: geht <2947093423@qq.com> Date: Fri, 15 May 2026 15:08:07 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=8E=9F=E6=96=99=E5=85=A5?= =?UTF-8?q?=E5=9C=BA=E8=AE=B0=E5=BD=95=E7=9A=84=E5=85=8D=E5=AF=86=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=E5=92=8C=E5=88=A0=E9=99=A4=E5=8A=9F=E8=83=BD=EF=BC=8C?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E7=BA=A7=E8=81=94=E5=88=A0=E9=99=A4=E5=85=B3?= =?UTF-8?q?=E8=81=94=E5=8E=9F=E6=9D=90=E6=96=99=E5=8D=A1=E7=89=87=E3=80=82?= =?UTF-8?q?=E9=87=8D=E6=9E=84=E7=9B=B8=E5=85=B3=E6=9C=8D=E5=8A=A1=E5=92=8C?= =?UTF-8?q?=E6=8E=A7=E5=88=B6=E5=99=A8=E4=BB=A5=E5=A2=9E=E5=BC=BA=E9=80=BB?= =?UTF-8?q?=E8=BE=91=E5=88=A0=E9=99=A4=E6=94=AF=E6=8C=81=EF=BC=8C=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E6=95=B0=E6=8D=AE=E5=A4=84=E7=90=86=E6=B5=81=E7=A8=8B?= =?UTF-8?q?=EF=BC=8C=E7=A1=AE=E4=BF=9D=E6=95=B0=E6=8D=AE=E4=B8=80=E8=87=B4?= =?UTF-8?q?=E6=80=A7=E5=92=8C=E5=87=86=E7=A1=AE=E6=80=A7=E3=80=82=E5=90=8C?= =?UTF-8?q?=E6=97=B6=EF=BC=8C=E6=9B=B4=E6=96=B0=E5=89=8D=E7=AB=AF=E8=A1=A8?= =?UTF-8?q?=E5=8D=95=E4=BB=A5=E6=94=AF=E6=8C=81=E6=96=B0=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MesXslDesktopAnonController.java | 50 ++- .../MesXslRawMaterialCardController.java | 7 +- ...esXslRawMaterialCardEditLogController.java | 62 +++ .../MesXslRawMaterialEntryController.java | 53 ++- ...slRawMaterialEntryDeleteLogController.java | 49 +++ .../entity/MesXslRawMaterialCardEditLog.java | 94 +++++ .../xslmes/entity/MesXslRawMaterialEntry.java | 6 + .../MesXslRawMaterialCardEditLogMapper.java | 9 + .../mapper/MesXslRawMaterialEntryMapper.java | 15 +- .../xml/MesXslRawMaterialEntryMapper.xml | 11 + .../IMesXslRawMaterialCardEditLogService.java | 9 + .../IMesXslRawMaterialCardService.java | 11 + .../IMesXslRawMaterialEntryService.java | 29 +- ...sXslRawMaterialCardEditLogServiceImpl.java | 15 + .../MesXslRawMaterialCardServiceImpl.java | 109 ++++- .../MesXslRawMaterialEntryServiceImpl.java | 121 ++++++ .../vo/MesXslRawMaterialCardBriefVO.java | 30 ++ .../vo/MesXslRawMaterialEntryDeleteLogVO.java | 35 ++ ....9.2_58__mes_xsl_raw_storage_root_menu.sql | 11 + .../V3.9.2_59__xslmes_print_dot_ws_dict.sql | 17 + ...60__mes_xsl_raw_material_card_edit_log.sql | 53 +++ ...ial_entry_del_flag_and_delete_log_menu.sql | 45 ++ .../src/views/system/dict/dict.data.ts | 4 +- .../MesXslRawMaterialCard.data.ts | 59 ++- .../MesXslRawMaterialCardList.vue | 198 +++++---- .../components/MesXslRawMaterialCardModal.vue | 383 +++++++++++++++++- .../MesXslRawMaterialCardEditLog.api.ts | 10 + .../MesXslRawMaterialCardEditLog.data.ts | 45 ++ .../MesXslRawMaterialCardEditLogList.vue | 44 ++ .../MesXslRawMaterialEntry.api.ts | 38 +- .../MesXslRawMaterialEntryList.vue | 215 +++++++--- .../MesXslRawMaterialEntryDeleteLog.api.ts | 7 + .../MesXslRawMaterialEntryDeleteLog.data.ts | 31 ++ .../MesXslRawMaterialEntryDeleteLogList.vue | 33 ++ 34 files changed, 1693 insertions(+), 215 deletions(-) create mode 100644 jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslRawMaterialCardEditLogController.java create mode 100644 jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslRawMaterialEntryDeleteLogController.java create mode 100644 jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslRawMaterialCardEditLog.java create mode 100644 jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/MesXslRawMaterialCardEditLogMapper.java create mode 100644 jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslRawMaterialCardEditLogService.java create mode 100644 jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslRawMaterialCardEditLogServiceImpl.java create mode 100644 jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslRawMaterialCardBriefVO.java create mode 100644 jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslRawMaterialEntryDeleteLogVO.java create mode 100644 jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_58__mes_xsl_raw_storage_root_menu.sql create mode 100644 jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_59__xslmes_print_dot_ws_dict.sql create mode 100644 jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_60__mes_xsl_raw_material_card_edit_log.sql create mode 100644 jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_61__mes_xsl_raw_material_entry_del_flag_and_delete_log_menu.sql create mode 100644 jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialCardEditLog/MesXslRawMaterialCardEditLog.api.ts create mode 100644 jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialCardEditLog/MesXslRawMaterialCardEditLog.data.ts create mode 100644 jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialCardEditLog/MesXslRawMaterialCardEditLogList.vue create mode 100644 jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialEntryDeleteLog/MesXslRawMaterialEntryDeleteLog.api.ts create mode 100644 jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialEntryDeleteLog/MesXslRawMaterialEntryDeleteLog.data.ts create mode 100644 jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialEntryDeleteLog/MesXslRawMaterialEntryDeleteLogList.vue diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslDesktopAnonController.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslDesktopAnonController.java index 76f5f84..25e9840 100644 --- a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslDesktopAnonController.java +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslDesktopAnonController.java @@ -40,13 +40,16 @@ import org.jeecg.modules.xslmes.service.IMesXslWarehouseAreaService; import org.jeecg.modules.xslmes.service.IMesXslWarehouseService; import org.jeecg.modules.xslmes.service.IMesXslWeightRecordService; import org.jeecg.modules.xslmes.service.MesXslStompNotifyService; +import org.jeecg.modules.xslmes.vo.MesXslRawMaterialCardBriefVO; import org.springframework.web.bind.annotation.*; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Optional; import org.apache.commons.lang3.StringUtils; /** @@ -511,19 +514,48 @@ public class MesXslDesktopAnonController { return Result.OK("编辑成功!"); } + @Operation(summary = "原料入场记录-免密查询关联原材料卡片") + @GetMapping("/xslmes/mesXslRawMaterialEntry/anon/linkedRawMaterialCards") + public Result> rawMaterialEntryAnonLinkedRawMaterialCards( + @RequestParam(name = "ids") String ids) { + List idList = Arrays.stream(ids.split(",")) + .map(String::trim) + .filter(s -> !s.isEmpty()) + .distinct() + .toList(); + return Result.OK(rawMaterialEntryService.listLinkedRawMaterialCards(idList)); + } + @Operation(summary = "原料入场记录-免密删除") @DeleteMapping("/xslmes/mesXslRawMaterialEntry/anon/delete") - public Result rawMaterialEntryAnonDelete(@RequestParam(name = "id") String id) { - rawMaterialEntryService.removeById(id); - stompNotify.publishRawMaterialEntryChanged("delete", id); + public Result rawMaterialEntryAnonDelete( + @RequestParam(name = "id") String id, + @RequestParam(name = "cascadeDeleteCards", defaultValue = "true") boolean cascadeDeleteCards) { + Optional> blocked = + rawMaterialEntryService.removeEntriesRespectingLinkedCards(List.of(id), cascadeDeleteCards); + if (blocked.isPresent()) { + return Result.error( + "存在已生成的原材料卡片但未允许级联删除,请传 cascadeDeleteCards=true。", blocked.get()); + } return Result.OK("删除成功!"); } @Operation(summary = "原料入场记录-免密批量删除") @DeleteMapping("/xslmes/mesXslRawMaterialEntry/anon/deleteBatch") - public Result rawMaterialEntryAnonDeleteBatch(@RequestParam(name = "ids") String ids) { - rawMaterialEntryService.removeByIds(Arrays.asList(ids.split(","))); - stompNotify.publishRawMaterialEntryChanged("batchDelete", ids); + public Result rawMaterialEntryAnonDeleteBatch( + @RequestParam(name = "ids") String ids, + @RequestParam(name = "cascadeDeleteCards", defaultValue = "true") boolean cascadeDeleteCards) { + List idList = Arrays.stream(ids.split(",")) + .map(String::trim) + .filter(s -> !s.isEmpty()) + .distinct() + .toList(); + Optional> blocked = + rawMaterialEntryService.removeEntriesRespectingLinkedCards(idList, cascadeDeleteCards); + if (blocked.isPresent()) { + return Result.error( + "存在已生成的原材料卡片但未允许级联删除,请传 cascadeDeleteCards=true。", blocked.get()); + } return Result.OK("批量删除成功!"); } @@ -563,9 +595,11 @@ public class MesXslDesktopAnonController { if (oConvertUtils.isEmpty(entity.getId())) { return Result.error("主键不能为空"); } - boolean ok = rawMaterialCardService.updateById(entity); + boolean ok = + rawMaterialCardService.updateEditableInventoryFields( + entity, "桌面端免密编辑", "桌面端(免密)"); if (!ok) { - return Result.error("数据已被他人修改,请刷新后重试"); + return Result.error("未找到数据或更新失败,请刷新后重试"); } stompNotify.publishRawMaterialCardChanged("edit", entity.getId()); return Result.OK("编辑成功!"); diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslRawMaterialCardController.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslRawMaterialCardController.java index 902e33a..453f123 100644 --- a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslRawMaterialCardController.java +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslRawMaterialCardController.java @@ -138,7 +138,12 @@ public class MesXslRawMaterialCardController extends JeecgController edit(@RequestBody MesXslRawMaterialCard mesXslRawMaterialCard) { - mesXslRawMaterialCardService.updateById(mesXslRawMaterialCard); + boolean ok = + mesXslRawMaterialCardService.updateEditableInventoryFields( + mesXslRawMaterialCard, "Web端原材料卡片", null); + if (!ok) { + return Result.error("未找到数据或更新失败,请刷新后重试"); + } stompNotify.publishRawMaterialCardChanged("edit", mesXslRawMaterialCard.getId()); return Result.OK("编辑成功!"); } diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslRawMaterialCardEditLogController.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslRawMaterialCardEditLogController.java new file mode 100644 index 0000000..984774d --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslRawMaterialCardEditLogController.java @@ -0,0 +1,62 @@ +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.MesXslRawMaterialCardEditLog; +import org.jeecg.modules.xslmes.service.IMesXslRawMaterialCardEditLogService; +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/mesXslRawMaterialCardEditLog") +@Slf4j +public class MesXslRawMaterialCardEditLogController + extends JeecgController { + + @Operation(summary = "原材料卡片修改日志-分页列表查询") + @RequiresPermissions("xslmes:mes_xsl_raw_material_card_edit_log:list") + @GetMapping(value = "/list") + public Result> queryPageList( + MesXslRawMaterialCardEditLog entity, + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, + HttpServletRequest req) { + QueryWrapper qw = QueryGenerator.initQueryWrapper(entity, req.getParameterMap()); + qw.orderByDesc("modify_time"); + Page page = new Page<>(pageNo, pageSize); + return Result.OK(service.page(page, qw)); + } + + @Operation(summary = "原材料卡片修改日志-通过id查询") + @RequiresPermissions("xslmes:mes_xsl_raw_material_card_edit_log:list") + @GetMapping(value = "/queryById") + public Result queryById(@RequestParam(name = "id", required = true) String id) { + MesXslRawMaterialCardEditLog row = service.getById(id); + if (row == null) { + return Result.error("未找到对应数据"); + } + return Result.OK(row); + } + + @RequiresPermissions("xslmes:mes_xsl_raw_material_card_edit_log:exportXls") + @RequestMapping(value = "/exportXls") + public ModelAndView exportXls(HttpServletRequest request, MesXslRawMaterialCardEditLog entity) { + return super.exportXls(request, entity, MesXslRawMaterialCardEditLog.class, "原材料卡片修改日志"); + } +} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslRawMaterialEntryController.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslRawMaterialEntryController.java index df44d4e..4872421 100644 --- a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslRawMaterialEntryController.java +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslRawMaterialEntryController.java @@ -15,6 +15,7 @@ import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.apache.shiro.authz.annotation.Logical; @@ -34,6 +35,7 @@ import org.jeecg.modules.xslmes.constant.MesXslPrintConstants; import org.jeecg.modules.xslmes.entity.MesXslRawMaterialEntry; import org.jeecg.modules.xslmes.service.IMesXslRawMaterialEntryService; import org.jeecg.modules.xslmes.service.MesXslStompNotifyService; +import org.jeecg.modules.xslmes.vo.MesXslRawMaterialCardBriefVO; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; @@ -105,13 +107,36 @@ public class MesXslRawMaterialEntryController extends JeecgController> linkedRawMaterialCards( + @RequestParam(name = "ids", required = true) String ids) { + List idList = Arrays.stream(ids.split(",")) + .map(String::trim) + .filter(s -> !s.isEmpty()) + .distinct() + .toList(); + return Result.OK(mesXslRawMaterialEntryService.listLinkedRawMaterialCards(idList)); + } + @AutoLog(value = "原料入场记录-通过id删除") - @Operation(summary = "原料入场记录-通过id删除") + @Operation(summary = "原料入场记录-通过id删除(cascadeDeleteCards=true 时同时删除关联原材料卡片)") @RequiresPermissions("xslmes:mes_xsl_raw_material_entry:delete") @DeleteMapping(value = "/delete") - public Result delete(@RequestParam(name = "id", required = true) String id) { - mesXslRawMaterialEntryService.removeById(id); - stompNotify.publishRawMaterialEntryChanged("delete", id); + public Result delete( + @RequestParam(name = "id", required = true) String id, + @RequestParam(name = "cascadeDeleteCards", defaultValue = "false") boolean cascadeDeleteCards) { + Optional> blocked = + mesXslRawMaterialEntryService.removeEntriesRespectingLinkedCards( + List.of(id), cascadeDeleteCards); + if (blocked.isPresent()) { + return Result.error( + "该原料入场记录已生成原材料卡片,确认删除时将一并删除下列卡片。请传 cascadeDeleteCards=true 重试。", + blocked.get()); + } return Result.OK("删除成功!"); } @@ -130,12 +155,24 @@ public class MesXslRawMaterialEntryController extends JeecgController deleteBatch(@RequestParam(name = "ids", required = true) String ids) { - this.mesXslRawMaterialEntryService.removeByIds(Arrays.asList(ids.split(","))); - stompNotify.publishRawMaterialEntryChanged("batchDelete", ids); + public Result deleteBatch( + @RequestParam(name = "ids", required = true) String ids, + @RequestParam(name = "cascadeDeleteCards", defaultValue = "false") boolean cascadeDeleteCards) { + List idList = Arrays.stream(ids.split(",")) + .map(String::trim) + .filter(s -> !s.isEmpty()) + .distinct() + .toList(); + Optional> blocked = + mesXslRawMaterialEntryService.removeEntriesRespectingLinkedCards(idList, cascadeDeleteCards); + if (blocked.isPresent()) { + return Result.error( + "选中记录关联的原材料卡片仍存在,确认删除时将一并删除下列卡片。请传 cascadeDeleteCards=true 重试。", + blocked.get()); + } return Result.OK("批量删除成功!"); } diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslRawMaterialEntryDeleteLogController.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslRawMaterialEntryDeleteLogController.java new file mode 100644 index 0000000..16c21e9 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslRawMaterialEntryDeleteLogController.java @@ -0,0 +1,49 @@ +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 org.apache.shiro.authz.annotation.RequiresPermissions; +import org.jeecg.common.api.vo.Result; +import org.jeecg.common.constant.CommonConstant; +import org.jeecg.common.system.query.QueryGenerator; +import org.jeecg.modules.xslmes.entity.MesXslRawMaterialEntry; +import org.jeecg.modules.xslmes.service.IMesXslRawMaterialEntryService; +import org.jeecg.modules.xslmes.vo.MesXslRawMaterialEntryDeleteLogVO; +import org.springframework.beans.factory.annotation.Autowired; +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; + +/** + * 原料入场删除日志:查询已逻辑删除的入场记录(不落单独日志表) + */ +@Tag(name = "原料入场删除日志") +@RestController +@RequestMapping("/xslmes/mesXslRawMaterialEntryDeleteLog") +public class MesXslRawMaterialEntryDeleteLogController { + + @Autowired + private IMesXslRawMaterialEntryService mesXslRawMaterialEntryService; + + @Operation(summary = "原料入场删除日志-分页查询") + @RequiresPermissions("xslmes:mes_xsl_raw_material_entry_delete_log:list") + @GetMapping(value = "/list") + public Result> queryPageList( + MesXslRawMaterialEntry query, + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, + HttpServletRequest req) { + MesXslRawMaterialEntry q = query == null ? new MesXslRawMaterialEntry() : query; + q.setDelFlag(null); + QueryWrapper qw = QueryGenerator.initQueryWrapper(q, req.getParameterMap()); + qw.eq("del_flag", CommonConstant.DEL_FLAG_1); + qw.orderByDesc("update_time").orderByDesc("create_time"); + Page page = new Page<>(pageNo, pageSize); + return Result.OK(mesXslRawMaterialEntryService.pageDeletedLog(page, qw)); + } +} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslRawMaterialCardEditLog.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslRawMaterialCardEditLog.java new file mode 100644 index 0000000..097c35e --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslRawMaterialCardEditLog.java @@ -0,0 +1,94 @@ +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.math.BigDecimal; +import java.util.Date; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.jeecgframework.poi.excel.annotation.Excel; +import org.springframework.format.annotation.DateTimeFormat; + +/** + * 原材料卡片修改日志(编辑剩余量/库区时落库) + */ +@Data +@TableName("mes_xsl_raw_material_card_edit_log") +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = false) +@Schema(description = "原材料卡片修改日志") +public class MesXslRawMaterialCardEditLog implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(type = IdType.ASSIGN_ID) + @Schema(description = "主键") + private String id; + + @Excel(name = "卡片ID", width = 28) + @Schema(description = "原材料卡片ID") + private String cardId; + + @Excel(name = "条码", width = 22) + @Schema(description = "条码") + private String barcode; + + @Excel(name = "批次号", width = 18) + @Schema(description = "批次号") + private String batchNo; + + @Excel(name = "物料名称", width = 22) + @Schema(description = "物料名称") + private String materialName; + + @Excel(name = "物料ID", width = 22) + @Schema(description = "物料ID") + private String materialId; + + @Excel(name = "修改前重量", width = 14) + @Schema(description = "修改前剩余重量") + private BigDecimal beforeRemainingWeight; + + @Excel(name = "修改前数量", width = 12) + @Schema(description = "修改前剩余数量") + private Integer beforeRemainingQty; + + @Excel(name = "修改后重量", width = 14) + @Schema(description = "修改后剩余重量") + private BigDecimal afterRemainingWeight; + + @Excel(name = "修改前库区", width = 16) + @Schema(description = "修改前库区") + private String beforeWarehouseArea; + + @Excel(name = "修改后数量", width = 12) + @Schema(description = "修改后剩余数量") + private Integer afterRemainingQty; + + @Excel(name = "修改后库区", width = 16) + @Schema(description = "修改后库区") + private String afterWarehouseArea; + + @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; + + @Excel(name = "修改人姓名", width = 16) + @Schema(description = "修改人姓名") + private String modifyByName; + + @Excel(name = "租户ID", width = 10) + @Schema(description = "租户ID") + private Integer tenantId; + + @Excel(name = "数值来源", width = 22) + @Schema(description = "数值来源") + private String dataSource; +} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslRawMaterialEntry.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslRawMaterialEntry.java index 8885a30..9635bcf 100644 --- a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslRawMaterialEntry.java +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslRawMaterialEntry.java @@ -5,6 +5,7 @@ import java.math.BigDecimal; import java.util.Date; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import com.fasterxml.jackson.annotation.JsonFormat; @@ -204,6 +205,11 @@ public class MesXslRawMaterialEntry implements Serializable { @Schema(description = "更新日期") private Date updateTime; + /**逻辑删除(0正常 1已删除);删除接口改为打标,便于「删除日志」查询。*/ + @Schema(description = "逻辑删除(0正常 1已删除)") + @TableLogic + private Integer delFlag; + @Schema(description = "租户ID") private Integer tenantId; } diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/MesXslRawMaterialCardEditLogMapper.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/MesXslRawMaterialCardEditLogMapper.java new file mode 100644 index 0000000..33797fd --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/MesXslRawMaterialCardEditLogMapper.java @@ -0,0 +1,9 @@ +package org.jeecg.modules.xslmes.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.jeecg.modules.xslmes.entity.MesXslRawMaterialCardEditLog; + +/** + * 原材料卡片修改日志 + */ +public interface MesXslRawMaterialCardEditLogMapper extends BaseMapper {} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/MesXslRawMaterialEntryMapper.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/MesXslRawMaterialEntryMapper.java index fa01893..8be222b 100644 --- a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/MesXslRawMaterialEntryMapper.java +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/MesXslRawMaterialEntryMapper.java @@ -1,7 +1,13 @@ package org.jeecg.modules.xslmes.mapper; -import org.jeecg.modules.xslmes.entity.MesXslRawMaterialEntry; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Constants; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Param; +import org.jeecg.modules.xslmes.entity.MesXslRawMaterialEntry; +import org.jeecg.modules.xslmes.vo.MesXslRawMaterialEntryDeleteLogVO; /** * @Description: 原料入场记录 @@ -10,4 +16,11 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; * @Version: V1.0 */ public interface MesXslRawMaterialEntryMapper extends BaseMapper { + + /** + * 分页查询已逻辑删除的入场记录(自定义 SQL,不按未删除过滤) + */ + IPage selectDeletedPage( + Page page, + @Param(Constants.WRAPPER) QueryWrapper queryWrapper); } diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/xml/MesXslRawMaterialEntryMapper.xml b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/xml/MesXslRawMaterialEntryMapper.xml index d17f69c..25c6146 100644 --- a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/xml/MesXslRawMaterialEntryMapper.xml +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/xml/MesXslRawMaterialEntryMapper.xml @@ -1,4 +1,15 @@ + + diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslRawMaterialCardEditLogService.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslRawMaterialCardEditLogService.java new file mode 100644 index 0000000..08fc43c --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslRawMaterialCardEditLogService.java @@ -0,0 +1,9 @@ +package org.jeecg.modules.xslmes.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import org.jeecg.modules.xslmes.entity.MesXslRawMaterialCardEditLog; + +/** + * 原材料卡片修改日志 + */ +public interface IMesXslRawMaterialCardEditLogService extends IService {} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslRawMaterialCardService.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslRawMaterialCardService.java index 97ac1cd..139689e 100644 --- a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslRawMaterialCardService.java +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslRawMaterialCardService.java @@ -10,4 +10,15 @@ import com.baomidou.mybatisplus.extension.service.IService; * @Version: V1.0 */ public interface IMesXslRawMaterialCardService extends IService { + + /** + * 列表/桌面端「编辑」仅允许调整剩余数量、剩余重量与库区,其它字段忽略且不写库。 + * + * @param incoming 至少包含 id;仅读取 remainingQuantity、remainingWeight、warehouseArea + * @param dataSource 数值来源说明(如 Web端原材料卡片、桌面端免密编辑),空则默认 Web端 + * @param modifierRealnameOverride 修改人姓名;空则取当前登录用户真实姓名(免密接口可传入固定文案) + * @return 是否存在主键且更新成功(受影响行大于 0) + */ + boolean updateEditableInventoryFields( + MesXslRawMaterialCard incoming, String dataSource, String modifierRealnameOverride); } diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslRawMaterialEntryService.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslRawMaterialEntryService.java index c2f9172..a38537a 100644 --- a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslRawMaterialEntryService.java +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslRawMaterialEntryService.java @@ -1,11 +1,18 @@ package org.jeecg.modules.xslmes.service; -import org.jeecg.modules.xslmes.entity.MesXslRawMaterialEntry; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.IService; +import org.jeecg.modules.xslmes.entity.MesXslRawMaterialEntry; +import org.jeecg.modules.xslmes.vo.MesXslRawMaterialCardBriefVO; +import org.jeecg.modules.xslmes.vo.MesXslRawMaterialEntryDeleteLogVO; import java.math.BigDecimal; import java.util.Collection; +import java.util.List; import java.util.Map; +import java.util.Optional; /** * @Description: 原料入场记录 @@ -15,6 +22,26 @@ import java.util.Map; */ public interface IMesXslRawMaterialEntryService extends IService { + /** + * 原料入场删除日志:分页查询已逻辑删除的记录(仅条码/批次/创建人/创建时间/物料名称)。 + */ + IPage pageDeletedLog( + Page page, + QueryWrapper queryWrapper); + + /** + * 根据入场记录主键查询已生成的原材料卡片(按拆码明细 ID 优先,否则按条码+批次等降级关联)。 + */ + List listLinkedRawMaterialCards(Collection entryIds); + + /** + * 删除入场记录;若存在关联卡片且 cascadeDeleteCards=false,不删除任何数据并返回关联列表。 + * + * @return empty 表示已删除入场记录(并在 cascade 为 true 时删除关联卡片);非空则为被拦截时的关联卡片 + */ + Optional> removeEntriesRespectingLinkedCards( + Collection entryIds, boolean cascadeDeleteCards); + /** * 生成条码/批次号 * 格式:QH + 物料编码 + 日期(yyMMdd) + 当日序号(001起) diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslRawMaterialCardEditLogServiceImpl.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslRawMaterialCardEditLogServiceImpl.java new file mode 100644 index 0000000..94e4520 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslRawMaterialCardEditLogServiceImpl.java @@ -0,0 +1,15 @@ +package org.jeecg.modules.xslmes.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.jeecg.modules.xslmes.entity.MesXslRawMaterialCardEditLog; +import org.jeecg.modules.xslmes.mapper.MesXslRawMaterialCardEditLogMapper; +import org.jeecg.modules.xslmes.service.IMesXslRawMaterialCardEditLogService; +import org.springframework.stereotype.Service; + +/** + * 原材料卡片修改日志 + */ +@Service +public class MesXslRawMaterialCardEditLogServiceImpl + extends ServiceImpl + implements IMesXslRawMaterialCardEditLogService {} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslRawMaterialCardServiceImpl.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslRawMaterialCardServiceImpl.java index 0a308ab..03982ab 100644 --- a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslRawMaterialCardServiceImpl.java +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslRawMaterialCardServiceImpl.java @@ -1,10 +1,20 @@ package org.jeecg.modules.xslmes.service.impl; -import org.jeecg.modules.xslmes.entity.MesXslRawMaterialCard; -import org.jeecg.modules.xslmes.mapper.MesXslRawMaterialCardMapper; -import org.jeecg.modules.xslmes.service.IMesXslRawMaterialCardService; -import org.springframework.stereotype.Service; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import java.math.BigDecimal; +import java.util.Date; +import java.util.Objects; +import org.apache.commons.lang3.StringUtils; +import org.apache.shiro.SecurityUtils; +import org.jeecg.common.system.vo.LoginUser; +import org.jeecg.modules.xslmes.entity.MesXslRawMaterialCard; +import org.jeecg.modules.xslmes.entity.MesXslRawMaterialCardEditLog; +import org.jeecg.modules.xslmes.mapper.MesXslRawMaterialCardMapper; +import org.jeecg.modules.xslmes.service.IMesXslRawMaterialCardEditLogService; +import org.jeecg.modules.xslmes.service.IMesXslRawMaterialCardService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; /** * @Description: 原材料卡片 @@ -13,5 +23,94 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; * @Version: V1.0 */ @Service -public class MesXslRawMaterialCardServiceImpl extends ServiceImpl implements IMesXslRawMaterialCardService { +public class MesXslRawMaterialCardServiceImpl extends ServiceImpl + implements IMesXslRawMaterialCardService { + + @Autowired + private IMesXslRawMaterialCardEditLogService editLogService; + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean updateEditableInventoryFields( + MesXslRawMaterialCard incoming, String dataSource, String modifierRealnameOverride) { + if (incoming == null || StringUtils.isBlank(incoming.getId())) { + return false; + } + MesXslRawMaterialCard existing = getById(incoming.getId()); + if (existing == null) { + return false; + } + String area = incoming.getWarehouseArea(); + String areaTrimmed = area == null ? null : StringUtils.trimToNull(area); + + boolean weightChanged = !bigDecimalEquals(existing.getRemainingWeight(), incoming.getRemainingWeight()); + boolean qtyChanged = !Objects.equals(existing.getRemainingQuantity(), incoming.getRemainingQuantity()); + boolean areaChanged = !Objects.equals(normArea(existing.getWarehouseArea()), areaTrimmed); + boolean anyChanged = weightChanged || qtyChanged || areaChanged; + + boolean ok = lambdaUpdate() + .eq(MesXslRawMaterialCard::getId, incoming.getId()) + .set(MesXslRawMaterialCard::getRemainingWeight, incoming.getRemainingWeight()) + .set(MesXslRawMaterialCard::getRemainingQuantity, incoming.getRemainingQuantity()) + .set(MesXslRawMaterialCard::getWarehouseArea, areaTrimmed) + .update(); + if (!ok) { + return false; + } + if (!anyChanged) { + return true; + } + String ds = StringUtils.isNotBlank(dataSource) ? dataSource : "Web端原材料卡片"; + String modifier = resolveModifierName(modifierRealnameOverride); + MesXslRawMaterialCardEditLog logRow = new MesXslRawMaterialCardEditLog(); + logRow.setCardId(existing.getId()); + logRow.setBarcode(existing.getBarcode()); + logRow.setBatchNo(existing.getBatchNo()); + logRow.setMaterialName(existing.getMaterialName()); + logRow.setMaterialId(existing.getMaterialId()); + logRow.setBeforeRemainingWeight(existing.getRemainingWeight()); + logRow.setBeforeRemainingQty(existing.getRemainingQuantity()); + logRow.setAfterRemainingWeight(incoming.getRemainingWeight()); + logRow.setBeforeWarehouseArea(existing.getWarehouseArea()); + logRow.setAfterRemainingQty(incoming.getRemainingQuantity()); + logRow.setAfterWarehouseArea(areaTrimmed); + logRow.setModifyTime(new Date()); + logRow.setModifyByName(modifier); + logRow.setTenantId(existing.getTenantId()); + logRow.setDataSource(ds); + editLogService.save(logRow); + return true; + } + + private static String normArea(String s) { + return s == null ? null : StringUtils.trimToNull(s); + } + + private static boolean bigDecimalEquals(BigDecimal a, BigDecimal b) { + if (a == null && b == null) { + return true; + } + if (a == null || b == null) { + return false; + } + return a.compareTo(b) == 0; + } + + private static String resolveModifierName(String override) { + if (StringUtils.isNotBlank(override)) { + return override; + } + try { + Object p = SecurityUtils.getSubject().getPrincipal(); + if (p instanceof LoginUser) { + String name = ((LoginUser) p).getRealname(); + if (StringUtils.isNotBlank(name)) { + return name; + } + } + } catch (Exception ignored) { + // 免密或未登录场景 + } + return "未知"; + } } diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslRawMaterialEntryServiceImpl.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslRawMaterialEntryServiceImpl.java index 9dd3cb6..9d53511 100644 --- a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslRawMaterialEntryServiceImpl.java +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslRawMaterialEntryServiceImpl.java @@ -1,7 +1,10 @@ package org.jeecg.modules.xslmes.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.jeecg.modules.xslmes.entity.MesXslRawMaterialCard; import org.jeecg.modules.xslmes.entity.MesXslRawMaterialInventory; @@ -12,6 +15,9 @@ import org.jeecg.modules.xslmes.service.IMesXslRawMaterialCardService; import org.jeecg.modules.xslmes.service.IMesXslRawMaterialInventoryService; import org.jeecg.modules.xslmes.service.IMesXslRawMaterialEntryService; import org.jeecg.modules.xslmes.service.IMesXslWarehouseAreaService; +import org.jeecg.modules.xslmes.service.MesXslStompNotifyService; +import org.jeecg.modules.xslmes.vo.MesXslRawMaterialCardBriefVO; +import org.jeecg.modules.xslmes.vo.MesXslRawMaterialEntryDeleteLogVO; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; @@ -20,13 +26,17 @@ import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -49,6 +59,117 @@ public class MesXslRawMaterialEntryServiceImpl private IMesXslWarehouseAreaService mesXslWarehouseAreaService; @Autowired private JdbcTemplate jdbcTemplate; + @Autowired + private MesXslStompNotifyService stompNotify; + + @Override + public IPage pageDeletedLog( + Page page, QueryWrapper queryWrapper) { + return baseMapper.selectDeletedPage(page, queryWrapper); + } + + @Override + public List listLinkedRawMaterialCards(Collection entryIds) { + if (entryIds == null || entryIds.isEmpty()) { + return Collections.emptyList(); + } + List distinctIds = entryIds.stream() + .filter(Objects::nonNull) + .map(String::trim) + .filter(s -> !s.isEmpty()) + .distinct() + .toList(); + if (distinctIds.isEmpty()) { + return Collections.emptyList(); + } + List entries = this.listByIds(distinctIds); + Map byId = new LinkedHashMap<>(); + for (MesXslRawMaterialEntry entry : entries) { + for (MesXslRawMaterialCard card : findLinkedCardsForEntry(entry)) { + if (card.getId() != null) { + byId.putIfAbsent(card.getId(), card); + } + } + } + return byId.values().stream().map(MesXslRawMaterialEntryServiceImpl::toCardBrief).toList(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Optional> removeEntriesRespectingLinkedCards( + Collection entryIds, boolean cascadeDeleteCards) { + if (entryIds == null || entryIds.isEmpty()) { + return Optional.empty(); + } + List distinctIds = entryIds.stream() + .filter(Objects::nonNull) + .map(String::trim) + .filter(s -> !s.isEmpty()) + .distinct() + .toList(); + if (distinctIds.isEmpty()) { + return Optional.empty(); + } + List linked = listLinkedRawMaterialCards(distinctIds); + if (!linked.isEmpty() && !cascadeDeleteCards) { + return Optional.of(linked); + } + if (!linked.isEmpty()) { + List cardIds = linked.stream() + .map(MesXslRawMaterialCardBriefVO::getId) + .filter(Objects::nonNull) + .distinct() + .toList(); + if (!cardIds.isEmpty()) { + mesXslRawMaterialCardService.removeByIds(cardIds); + stompNotify.publishRawMaterialCardChanged("batchDelete", String.join(",", cardIds)); + } + } + this.removeByIds(distinctIds); + String action = distinctIds.size() > 1 ? "batchDelete" : "delete"; + stompNotify.publishRawMaterialEntryChanged(action, String.join(",", distinctIds)); + return Optional.empty(); + } + + /** 单条入场记录关联的原材料卡片:优先拆码明细 GUID,其次条码+批次等 */ + private List findLinkedCardsForEntry(MesXslRawMaterialEntry entry) { + if (entry == null) { + return Collections.emptyList(); + } + String[] splitIds = splitJoined(entry.getPortionDetailIds()); + if (splitIds.length > 0) { + return mesXslRawMaterialCardService + .lambdaQuery() + .in(MesXslRawMaterialCard::getSplitDetailId, Arrays.asList(splitIds)) + .list(); + } + String bc = normalizeText(entry.getBarcode()); + String bn = normalizeText(entry.getBatchNo()); + if (!bc.isEmpty() && !bn.isEmpty()) { + return mesXslRawMaterialCardService + .lambdaQuery() + .eq(MesXslRawMaterialCard::getBarcode, bc) + .eq(MesXslRawMaterialCard::getBatchNo, bn) + .list(); + } + if (!bc.isEmpty()) { + return mesXslRawMaterialCardService.lambdaQuery().eq(MesXslRawMaterialCard::getBarcode, bc).list(); + } + if (!bn.isEmpty()) { + return mesXslRawMaterialCardService.lambdaQuery().eq(MesXslRawMaterialCard::getBatchNo, bn).list(); + } + return Collections.emptyList(); + } + + private static MesXslRawMaterialCardBriefVO toCardBrief(MesXslRawMaterialCard c) { + MesXslRawMaterialCardBriefVO v = new MesXslRawMaterialCardBriefVO(); + v.setId(c.getId()); + v.setBarcode(c.getBarcode()); + v.setBatchNo(c.getBatchNo()); + v.setMaterialName(c.getMaterialName()); + v.setSplitDetailId(c.getSplitDetailId()); + return v; + } @Override public String generateBarcode(String materialCode) { diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslRawMaterialCardBriefVO.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslRawMaterialCardBriefVO.java new file mode 100644 index 0000000..30e3fc8 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslRawMaterialCardBriefVO.java @@ -0,0 +1,30 @@ +package org.jeecg.modules.xslmes.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import java.io.Serializable; +import lombok.Data; + +/** + * 原材料卡片简要信息(入场删除确认弹窗用) + */ +@Data +@Schema(description = "原材料卡片简要信息") +public class MesXslRawMaterialCardBriefVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "卡片主键") + private String id; + + @Schema(description = "条码") + private String barcode; + + @Schema(description = "批次号") + private String batchNo; + + @Schema(description = "物料名称") + private String materialName; + + @Schema(description = "关联拆码明细行ID(可空)") + private String splitDetailId; +} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslRawMaterialEntryDeleteLogVO.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslRawMaterialEntryDeleteLogVO.java new file mode 100644 index 0000000..b58286b --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/vo/MesXslRawMaterialEntryDeleteLogVO.java @@ -0,0 +1,35 @@ +package org.jeecg.modules.xslmes.vo; + +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 org.springframework.format.annotation.DateTimeFormat; + +/** + * 原料入场「删除日志」列表专用 VO(仅展示字段,不落单独日志表) + */ +@Data +@Schema(description = "原料入场删除日志展示") +public class MesXslRawMaterialEntryDeleteLogVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "条码") + private String barcode; + + @Schema(description = "批次号") + private String batchNo; + + @Schema(description = "创建人") + private String createBy; + + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Schema(description = "创建时间") + private Date createTime; + + @Schema(description = "物料名称") + private String materialName; +} diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_58__mes_xsl_raw_storage_root_menu.sql b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_58__mes_xsl_raw_storage_root_menu.sql new file mode 100644 index 0000000..aa2c8d6 --- /dev/null +++ b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_58__mes_xsl_raw_storage_root_menu.sql @@ -0,0 +1,11 @@ +-- 一级菜单:MES原料仓储(目录;默认重定向至已有原材料库区看板) + +INSERT 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`) +SELECT '1900000000000000700', '', 'MES原料仓储', '/xslmesRawStorage', 'layouts/default/index', 1, NULL, '/xslmes/mesXslRawMaterialWarehouseBoard', 0, NULL, '0', 81.50, 0, 'ant-design:inbox-outlined', 0, 0, 0, 0, 'MES 原料仓储(一级目录,子菜单可后续挂接或从系统管理中调整)', 'admin', NOW(), 'admin', NOW(), 0, 0, '1', 0 +FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `sys_permission` WHERE `id` = '1900000000000000700'); + +-- admin 角色授权(幂等) +INSERT INTO `sys_role_permission` (`id`, `role_id`, `permission_id`, `data_rule_ids`, `operate_date`, `operate_ip`) +SELECT REPLACE(UUID(), '-', ''), r.id, '1900000000000000700', NULL, NOW(), '127.0.0.1' +FROM `sys_role` r WHERE r.`role_code` = 'admin' + AND NOT EXISTS (SELECT 1 FROM `sys_role_permission` rp WHERE rp.`role_id` = r.id AND rp.`permission_id` = '1900000000000000700'); diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_59__xslmes_print_dot_ws_dict.sql b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_59__xslmes_print_dot_ws_dict.sql new file mode 100644 index 0000000..49331d7 --- /dev/null +++ b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_59__xslmes_print_dot_ws_dict.sql @@ -0,0 +1,17 @@ +-- PrintDot WebSocket 地址字典(item_text 展示名称,item_value 为完整 ws 地址,可在系统字典中维护多条) + +INSERT INTO `sys_dict` (`id`, `dict_name`, `dict_code`, `description`, `del_flag`, `create_by`, `create_time`, `type`, `tenant_id`) +SELECT REPLACE(UUID(), '-', ''), 'PrintDot WS地址', 'xslmes_print_dot_ws', '原材料卡片等页面桥接器 WebSocket 地址;文本为说明,值为完整 ws URL', 0, 'admin', NOW(), 0, 1002 +FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `sys_dict` WHERE `dict_code` = 'xslmes_print_dot_ws' AND `del_flag` = 0); + +INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`) +SELECT REPLACE(UUID(), '-', ''), d.id, '本机 PrintDot', 'ws://127.0.0.1:1122/ws', '本机默认端口', 1, 1, 'admin', NOW() +FROM `sys_dict` d +WHERE d.`dict_code` = 'xslmes_print_dot_ws' + AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.id AND i.`item_value` = 'ws://127.0.0.1:1122/ws'); + +INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`) +SELECT REPLACE(UUID(), '-', ''), d.id, '本机(备用回环)', 'ws://localhost:1122/ws', '与 127.0.0.1 等价场景', 2, 1, 'admin', NOW() +FROM `sys_dict` d +WHERE d.`dict_code` = 'xslmes_print_dot_ws' + AND NOT EXISTS (SELECT 1 FROM `sys_dict_item` i WHERE i.`dict_id` = d.id AND i.`item_value` = 'ws://localhost:1122/ws'); diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_60__mes_xsl_raw_material_card_edit_log.sql b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_60__mes_xsl_raw_material_card_edit_log.sql new file mode 100644 index 0000000..a50caba --- /dev/null +++ b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_60__mes_xsl_raw_material_card_edit_log.sql @@ -0,0 +1,53 @@ +-- 原材料卡片修改日志:表 + 菜单(挂到「MES原料仓储」1900000000000000700 下) + +CREATE TABLE IF NOT EXISTS `mes_xsl_raw_material_card_edit_log` ( + `id` varchar(32) NOT NULL COMMENT '主键', + `card_id` varchar(32) NOT NULL COMMENT '原材料卡片ID', + `barcode` varchar(100) DEFAULT NULL COMMENT '条码', + `batch_no` varchar(100) DEFAULT NULL COMMENT '批次号', + `material_name` varchar(200) DEFAULT NULL COMMENT '物料名称', + `material_id` varchar(32) DEFAULT NULL COMMENT '物料ID', + `before_remaining_weight` decimal(12,3) DEFAULT NULL COMMENT '修改前剩余重量', + `before_remaining_qty` int DEFAULT NULL COMMENT '修改前剩余数量', + `after_remaining_weight` decimal(12,3) DEFAULT NULL COMMENT '修改后剩余重量', + `before_warehouse_area` varchar(100) DEFAULT NULL COMMENT '修改前库区', + `after_remaining_qty` int DEFAULT NULL COMMENT '修改后剩余数量', + `after_warehouse_area` varchar(100) DEFAULT NULL COMMENT '修改后库区', + `modify_time` datetime DEFAULT NULL COMMENT '修改时间', + `modify_by_name` varchar(100) DEFAULT NULL COMMENT '修改人姓名', + `tenant_id` int DEFAULT NULL COMMENT '租户ID', + `data_source` varchar(100) DEFAULT NULL COMMENT '数值来源(Web端/桌面端等)', + PRIMARY KEY (`id`), + KEY `idx_rmcel_card_id` (`card_id`), + KEY `idx_rmcel_barcode` (`barcode`), + KEY `idx_rmcel_modify` (`modify_time`), + KEY `idx_rmcel_tenant` (`tenant_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='原材料卡片修改日志'; + +-- 菜单 +INSERT 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`) +SELECT '1900000000000000710', '1900000000000000700', '原材料卡片修改日志', '/xslmes/mesXslRawMaterialCardEditLog', 'xslmes/mesXslRawMaterialCardEditLog/MesXslRawMaterialCardEditLogList', 1, NULL, NULL, 1, NULL, '0', 13.00, 0, 'ant-design:history-outlined', 0, 1, 0, 0, '记录 Web/桌面端编辑原材料卡片剩余量与库区', 'admin', NOW(), 'admin', NOW(), 0, 0, '1', 0 +FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `sys_permission` WHERE `id` = '1900000000000000710'); + +INSERT 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`) +SELECT '1900000000000000711', '1900000000000000710', '查询', NULL, NULL, 0, NULL, NULL, 2, 'xslmes:mes_xsl_raw_material_card_edit_log:list', '1', 1.00, 0, NULL, 1, 0, 0, 0, NULL, 'admin', NOW(), 'admin', NOW(), 0, 0, '1', 0 +FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `sys_permission` WHERE `id` = '1900000000000000711'); + +INSERT 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`) +SELECT '1900000000000000712', '1900000000000000710', '导出', NULL, NULL, 0, NULL, NULL, 2, 'xslmes:mes_xsl_raw_material_card_edit_log:exportXls', '1', 2.00, 0, NULL, 1, 0, 0, 0, NULL, 'admin', NOW(), 'admin', NOW(), 0, 0, '1', 0 +FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `sys_permission` WHERE `id` = '1900000000000000712'); + +INSERT INTO `sys_role_permission` (`id`, `role_id`, `permission_id`, `data_rule_ids`, `operate_date`, `operate_ip`) +SELECT REPLACE(UUID(), '-', ''), r.id, '1900000000000000710', NULL, NOW(), '127.0.0.1' +FROM `sys_role` r WHERE r.`role_code` = 'admin' + AND NOT EXISTS (SELECT 1 FROM `sys_role_permission` rp WHERE rp.`role_id` = r.id AND rp.`permission_id` = '1900000000000000710'); + +INSERT INTO `sys_role_permission` (`id`, `role_id`, `permission_id`, `data_rule_ids`, `operate_date`, `operate_ip`) +SELECT REPLACE(UUID(), '-', ''), r.id, '1900000000000000711', NULL, NOW(), '127.0.0.1' +FROM `sys_role` r WHERE r.`role_code` = 'admin' + AND NOT EXISTS (SELECT 1 FROM `sys_role_permission` rp WHERE rp.`role_id` = r.id AND rp.`permission_id` = '1900000000000000711'); + +INSERT INTO `sys_role_permission` (`id`, `role_id`, `permission_id`, `data_rule_ids`, `operate_date`, `operate_ip`) +SELECT REPLACE(UUID(), '-', ''), r.id, '1900000000000000712', NULL, NOW(), '127.0.0.1' +FROM `sys_role` r WHERE r.`role_code` = 'admin' + AND NOT EXISTS (SELECT 1 FROM `sys_role_permission` rp WHERE rp.`role_id` = r.id AND rp.`permission_id` = '1900000000000000712'); diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_61__mes_xsl_raw_material_entry_del_flag_and_delete_log_menu.sql b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_61__mes_xsl_raw_material_entry_del_flag_and_delete_log_menu.sql new file mode 100644 index 0000000..4b02321 --- /dev/null +++ b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_61__mes_xsl_raw_material_entry_del_flag_and_delete_log_menu.sql @@ -0,0 +1,45 @@ +-- 原料入场记录:逻辑删除字段 + 「原料入场删除日志」只读菜单(MES原料仓储下) +-- 说明:删除改为逻辑删除(del_flag=1),本页面仅查询已删除记录展示,不另建日志表。 + +SET @col_exists := ( + SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = 'mes_xsl_raw_material_entry' + AND COLUMN_NAME = 'del_flag' +); +SET @ddl := IF(@col_exists > 0, + 'SELECT 1', + 'ALTER TABLE `mes_xsl_raw_material_entry` ADD COLUMN `del_flag` int NOT NULL DEFAULT 0 COMMENT ''逻辑删除(0正常 1已删除)'' AFTER `tenant_id`' +); +PREPARE s FROM @ddl; EXECUTE s; DEALLOCATE PREPARE s; + +SET @idx_exists := ( + SELECT COUNT(*) FROM information_schema.STATISTICS + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = 'mes_xsl_raw_material_entry' + AND INDEX_NAME = 'idx_rme_del_flag' +); +SET @idx_ddl := IF(@idx_exists > 0, + 'SELECT 1', + 'ALTER TABLE `mes_xsl_raw_material_entry` ADD KEY `idx_rme_del_flag` (`del_flag`)' +); +PREPARE s2 FROM @idx_ddl; EXECUTE s2; DEALLOCATE PREPARE s2; + +-- 菜单 +INSERT 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`) +SELECT '1900000000000000720', '1900000000000000700', '原料入场删除日志', '/xslmes/mesXslRawMaterialEntryDeleteLog', 'xslmes/mesXslRawMaterialEntryDeleteLog/MesXslRawMaterialEntryDeleteLogList', 1, NULL, NULL, 1, NULL, '0', 14.00, 0, 'ant-design:delete-row-outlined', 0, 1, 0, 0, '查询已逻辑删除的原料入场记录(仅展示条码/批次/创建人/时间/物料名称)', 'admin', NOW(), 'admin', NOW(), 0, 0, '1', 0 +FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `sys_permission` WHERE `id` = '1900000000000000720'); + +INSERT 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`) +SELECT '1900000000000000721', '1900000000000000720', '查询', NULL, NULL, 0, NULL, NULL, 2, 'xslmes:mes_xsl_raw_material_entry_delete_log:list', '1', 1.00, 0, NULL, 1, 0, 0, 0, NULL, 'admin', NOW(), 'admin', NOW(), 0, 0, '1', 0 +FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `sys_permission` WHERE `id` = '1900000000000000721'); + +INSERT INTO `sys_role_permission` (`id`, `role_id`, `permission_id`, `data_rule_ids`, `operate_date`, `operate_ip`) +SELECT REPLACE(UUID(), '-', ''), r.id, '1900000000000000720', NULL, NOW(), '127.0.0.1' +FROM `sys_role` r WHERE r.`role_code` = 'admin' + AND NOT EXISTS (SELECT 1 FROM `sys_role_permission` rp WHERE rp.`role_id` = r.id AND rp.`permission_id` = '1900000000000000720'); + +INSERT INTO `sys_role_permission` (`id`, `role_id`, `permission_id`, `data_rule_ids`, `operate_date`, `operate_ip`) +SELECT REPLACE(UUID(), '-', ''), r.id, '1900000000000000721', NULL, NOW(), '127.0.0.1' +FROM `sys_role` r WHERE r.`role_code` = 'admin' + AND NOT EXISTS (SELECT 1 FROM `sys_role_permission` rp WHERE rp.`role_id` = r.id AND rp.`permission_id` = '1900000000000000721'); diff --git a/jeecgboot-vue3/src/views/system/dict/dict.data.ts b/jeecgboot-vue3/src/views/system/dict/dict.data.ts index 8e7ea97..a198d29 100644 --- a/jeecgboot-vue3/src/views/system/dict/dict.data.ts +++ b/jeecgboot-vue3/src/views/system/dict/dict.data.ts @@ -150,9 +150,7 @@ export const itemFormSchema: FormSchema[] = [ if (!value) { return Promise.reject('请输入数据值'); } - if (new RegExp("[`~!@#$^&*()=|{}'.<>《》/?!¥()—【】‘;:”“。,、?]").test(value)) { - return Promise.reject('数据值不能包含特殊字符!'); - } + // 允许 URL 等场景(如 ws://host:port/path),重复性由 dictItemCheck 校验 return new Promise((resolve, reject) => { let params = { dictId: values.dictId, diff --git a/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialCard/MesXslRawMaterialCard.data.ts b/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialCard/MesXslRawMaterialCard.data.ts index b393301..80e21bc 100644 --- a/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialCard/MesXslRawMaterialCard.data.ts +++ b/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialCard/MesXslRawMaterialCard.data.ts @@ -155,7 +155,8 @@ export const searchFormSchema: FormSchema[] = [ }, ]; -export const formSchema: FormSchema[] = [ +/** 新增:完整字段 */ +export const formSchemaAdd: FormSchema[] = [ { label: '', field: 'id', @@ -288,6 +289,62 @@ export const formSchema: FormSchema[] = [ }, ]; +/** + * 编辑/详情:仅展示条码、批次号、物料、剩余数量、剩余重量、库区; + * 条码/批次号/物料只读,仅剩余数量、剩余重量、库区可编辑(详情时由表单全局禁用)。 + */ +export const formSchemaEdit: FormSchema[] = [ + { + label: '', + field: 'id', + component: 'Input', + show: false, + }, + { + label: '条码', + field: 'barcode', + component: 'Input', + componentProps: { disabled: true }, + colProps: { span: 24 }, + }, + { + label: '批次号', + field: 'batchNo', + component: 'Input', + componentProps: { disabled: true }, + colProps: { span: 24 }, + }, + { + label: '物料名称', + field: 'materialName', + component: 'Input', + componentProps: { disabled: true }, + colProps: { span: 24 }, + }, + { + label: '剩余数量', + field: 'remainingQuantity', + component: 'InputNumber', + componentProps: { placeholder: '请输入剩余数量', min: 0, precision: 0 }, + colProps: { span: 24 }, + }, + { + label: '剩余重量', + field: 'remainingWeight', + component: 'InputNumber', + componentProps: { placeholder: '请输入剩余重量', min: 0, precision: 3 }, + colProps: { span: 24 }, + }, + { + label: '库区', + field: 'warehouseArea', + component: 'Input', + slot: 'warehouseAreaPickSlot', + helpMessage: '编辑时点击输入框,在右侧列表中选择库区(保存库区编码)', + colProps: { span: 24 }, + }, +]; + export const superQuerySchema = { barcode: { title: '条码', order: 0, view: 'text' }, batchNo: { title: '批次号', order: 1, view: 'text' }, diff --git a/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialCard/MesXslRawMaterialCardList.vue b/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialCard/MesXslRawMaterialCardList.vue index 97bdd46..dec50f4 100644 --- a/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialCard/MesXslRawMaterialCardList.vue +++ b/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialCard/MesXslRawMaterialCardList.vue @@ -7,23 +7,15 @@ 新增 导出 导入 - - PrintDot 桥接 - - - - 下载打印插件 + 下载打印插件 - 刷新打印机 - - 添加 + 刷新打印机 @@ -101,6 +86,8 @@ import { BasicTable, useTable, TableAction } from '/@/components/Table'; import { useModal } from '/@/components/Modal'; import { useListPage } from '/@/hooks/system/useListPage'; + import { initDictOptions } from '/@/utils/dict'; + import { JDictSelectTag } from '/@/components/Form'; import MesXslRawMaterialCardModal from './components/MesXslRawMaterialCardModal.vue'; import RawMaterialCardPrintPreviewModal from './components/RawMaterialCardPrintPreviewModal.vue'; import { columns, searchFormSchema, superQuerySchema } from './MesXslRawMaterialCard.data'; @@ -126,19 +113,20 @@ } from '/@/views/print/template/utils/printDotBridge'; const { createMessage } = useMessage(); - const LS_PRINT_DOT_ENABLED = 'qhmes_print_dot_enabled'; - const printDotEnabled = ref(localStorage.getItem(LS_PRINT_DOT_ENABLED) !== '0'); - const printDotCfg = getPrintDotBridgeConfig(); - const printDotWsUrl = ref(printDotCfg.wsUrl); - const printDotKey = ref(printDotCfg.key); + /** 与 Flyway 中 sys_dict.dict_code 一致 */ + const PRINT_DOT_WS_DICT = 'xslmes_print_dot_ws'; + const printDotWsUrl = ref(''); + /** 是否已成功连接桥并拿到响应(用于隐藏「下载打印插件」) */ + const printDotConnected = ref(false); function persistPrintDotConfig() { - setPrintDotBridgeConfig(printDotWsUrl.value, printDotKey.value); + setPrintDotBridgeConfig(String(printDotWsUrl.value || '').trim(), ''); void refreshPrinterOptions(false); } - function onPrintDotEnabledChange() { - localStorage.setItem(LS_PRINT_DOT_ENABLED, printDotEnabled.value ? '1' : '0'); + function onPrintDotWsUrlChange() { + printDotConnected.value = false; + persistPrintDotConfig(); } function downloadPrintPlugin() { @@ -210,9 +198,12 @@ /** 与打印模板列表共用 localStorage 键,打印机选择保持一致 */ const printerOptions = ref>([]); const selectedPrinterName = ref('__system_default__'); - const manualPrinterName = ref(''); const printLoading = ref(false); + /** 固定 key,便于关闭 loading(避免返回值在某些场景下未能 removeNotice) */ + const PRINT_ROW_LOADING_KEY = 'mesXslRawMaterialCard-print-row'; + const PRINT_BATCH_LOADING_KEY = 'mesXslRawMaterialCard-print-batch'; + /** 与打印模板列表启用 PrintDot 时一致:仅本机桥接打印机 */ const printerSelectPlaceholder = '选择打印机(PrintDot 桥接)'; @@ -228,18 +219,13 @@ optionMap.set('__system_default__', { label: '系统默认打印机', value: '__system_default__' }); try { const dotList = await fetchPrintDotPrinters(); + printDotConnected.value = true; dotList.forEach((p) => { const name = String(p.name || '').trim(); if (!name) return; const defMark = p.isDefault ? '(默认)' : ''; optionMap.set(name, { label: `${name}${defMark}`, value: name }); }); - if (selectedPrinterName.value && !optionMap.has(selectedPrinterName.value)) { - optionMap.set(selectedPrinterName.value, { - label: `${selectedPrinterName.value}(手动)`, - value: selectedPrinterName.value, - }); - } printerOptions.value = Array.from(optionMap.values()); if (showMessage) { if (dotList.length) { @@ -249,12 +235,7 @@ } } } catch (e: unknown) { - if (selectedPrinterName.value && !optionMap.has(selectedPrinterName.value)) { - optionMap.set(selectedPrinterName.value, { - label: `${selectedPrinterName.value}(手动)`, - value: selectedPrinterName.value, - }); - } + printDotConnected.value = false; printerOptions.value = Array.from(optionMap.values()); if (showMessage) { createMessage.warning(`PrintDot:${e instanceof Error ? e.message : String(e)}`); @@ -262,18 +243,6 @@ } } - function addManualPrinter() { - const name = String(manualPrinterName.value || '').trim(); - if (!name) return; - const exists = printerOptions.value.some((item) => item.value === name); - if (!exists) { - printerOptions.value = [...printerOptions.value, { label: `${name}(手动)`, value: name }]; - } - selectedPrinterName.value = name; - manualPrinterName.value = ''; - createMessage.success('已添加打印机'); - } - async function executePrint(record: Recordable, options?: { silentSuccess?: boolean }) { try { const prep = (await prepareNativePrint(record.id as string)) as Record; @@ -323,6 +292,7 @@ localStorage.getItem(PRINT_TEMPLATE_SELECTED_PRINTER_KEY) || '__system_default__', }); + /** 单行/批量外层会统一 toast,此处避免重复 success */ if (!options?.silentSuccess) { createMessage.success('已通过 PrintDot 提交打印'); } @@ -332,66 +302,94 @@ } function handlePrintSelected() { - if (!printDotEnabled.value) { - createMessage.warning('请先开启 PrintDot 桥接'); - return; - } const rows = selectedRows.value || []; if (!rows.length) { createMessage.warning('请至少勾选一条记录后再点击「打印选中」'); return; } printLoading.value = true; - const hideLoadingMsg = createMessage.loading(`正在打印 ${rows.length} 条记录,请稍候…`, 0); + createMessage.destroy(PRINT_BATCH_LOADING_KEY); + createMessage.loading({ + content: `正在打印 ${rows.length} 条记录,请稍候…`, + key: PRINT_BATCH_LOADING_KEY, + duration: 0, + }); (async () => { - let ok = 0; - let firstError = ''; - for (const row of rows) { - try { - await executePrint(row, { silentSuccess: true }); - ok += 1; - } catch (e: unknown) { - if (!firstError) { - firstError = e instanceof Error ? e.message : String(e); + try { + let ok = 0; + let firstError = ''; + for (const row of rows) { + try { + await executePrint(row, { silentSuccess: true }); + ok += 1; + } catch (e: unknown) { + if (!firstError) { + firstError = e instanceof Error ? e.message : String(e); + } } } + if (ok === rows.length) { + createMessage.success(`已通过 PrintDot 提交 ${ok} 条打印任务`); + } else { + createMessage.warning( + `打印完成:成功 ${ok},失败 ${rows.length - ok}${firstError ? `。首条错误:${firstError}` : ''}` + ); + } + } finally { + createMessage.destroy(PRINT_BATCH_LOADING_KEY); + printLoading.value = false; } - if (ok === rows.length) { - createMessage.success(`已通过 PrintDot 提交 ${ok} 条打印任务`); - } else { - createMessage.warning(`打印完成:成功 ${ok},失败 ${rows.length - ok}${firstError ? `。首条错误:${firstError}` : ''}`); - } - hideLoadingMsg(); - printLoading.value = false; })(); } - function handlePrintRow(record: Recordable) { - if (!printDotEnabled.value) { - createMessage.warning('请先开启 PrintDot 桥接'); - return; - } + async function handlePrintRow(record: Recordable) { printLoading.value = true; - const hideLoadingMsg = createMessage.loading('正在生成 PDF 并提交打印,版面复杂时可能需数十秒,请稍候…', 0); - executePrint(record) - .then(() => { - createMessage.success('已通过 PrintDot 提交打印'); - }) - .catch((e: unknown) => { - createMessage.error(e instanceof Error ? e.message : String(e)); - }) - .finally(() => { - hideLoadingMsg(); - printLoading.value = false; - }); + createMessage.destroy(PRINT_ROW_LOADING_KEY); + createMessage.loading({ + content: '正在生成 PDF 并提交打印,版面复杂时可能需数十秒,请稍候…', + key: PRINT_ROW_LOADING_KEY, + duration: 0, + }); + try { + await executePrint(record, { silentSuccess: true }); + createMessage.success('已通过 PrintDot 提交打印'); + } catch (e: unknown) { + createMessage.error(e instanceof Error ? e.message : String(e)); + } finally { + createMessage.destroy(PRINT_ROW_LOADING_KEY); + printLoading.value = false; + } } - onMounted(() => { - const saved = localStorage.getItem(PRINT_TEMPLATE_SELECTED_PRINTER_KEY); - if (saved) { - selectedPrinterName.value = saved; + onMounted(async () => { + const cfg = getPrintDotBridgeConfig(); + // 密钥不再使用,写入空串 + setPrintDotBridgeConfig(cfg.wsUrl, ''); + printDotWsUrl.value = cfg.wsUrl || ''; + + try { + const raw = await initDictOptions(PRINT_DOT_WS_DICT); + const items = Array.isArray(raw) ? raw : []; + const values = items + .map((it: Recordable) => String(it.value ?? it.itemValue ?? '').trim()) + .filter(Boolean); + const valueSet = new Set(values); + if (valueSet.size && printDotWsUrl.value && !valueSet.has(String(printDotWsUrl.value).trim())) { + printDotWsUrl.value = values[0]; + setPrintDotBridgeConfig(printDotWsUrl.value, ''); + } else if (valueSet.size && !printDotWsUrl.value.trim()) { + printDotWsUrl.value = values[0]; + setPrintDotBridgeConfig(printDotWsUrl.value, ''); + } + } catch { + /* 字典未配置时沿用 localStorage */ } - refreshPrinterOptions(false); + + const savedPrinter = localStorage.getItem(PRINT_TEMPLATE_SELECTED_PRINTER_KEY); + if (savedPrinter) { + selectedPrinterName.value = savedPrinter; + } + await refreshPrinterOptions(false); }); function handleSuperQuery(params) { diff --git a/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialCard/components/MesXslRawMaterialCardModal.vue b/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialCard/components/MesXslRawMaterialCardModal.vue index a80223d..92cb47e 100644 --- a/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialCard/components/MesXslRawMaterialCardModal.vue +++ b/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialCard/components/MesXslRawMaterialCardModal.vue @@ -1,6 +1,66 @@ @@ -8,36 +68,169 @@ import { ref, computed, unref } from 'vue'; import { BasicModal, useModalInner } from '/@/components/Modal'; import { BasicForm, useForm } from '/@/components/Form/index'; - import { formSchema } from '../MesXslRawMaterialCard.data'; + import { Icon } from '/@/components/Icon'; + import { formSchemaAdd, formSchemaEdit } from '../MesXslRawMaterialCard.data'; import { saveOrUpdate } from '../MesXslRawMaterialCard.api'; + import { list as warehouseAreaList } from '/@/views/xslmes/mesXslWarehouseArea/MesXslWarehouseArea.api'; + + /** 库区行(列表接口 records) */ + interface WarehouseAreaRow { + id?: string; + areaCode: string; + areaName?: string; + /** 所属仓库名称(列表接口冗余字段) */ + warehouseName?: string; + } const emit = defineEmits(['register', 'success']); const isUpdate = ref(true); + /** 与标题逻辑一致:showFooter 为 true 表示可编辑(编辑),false 为详情 */ const isDetail = ref(false); - const [registerForm, { setProps, resetFields, setFieldsValue, validate, scrollToField }] = useForm({ + const formEditable = ref(true); + const areaPanelVisible = ref(false); + const areaSearch = ref(''); + const areaLoading = ref(false); + const areaRows = ref([]); + const pickedAreaCode = ref(''); + + const [registerForm, { setProps, resetFields, setFieldsValue, validate, scrollToField, resetSchema }] = useForm({ labelWidth: 120, - schemas: formSchema, + schemas: formSchemaAdd, showActionButtonGroup: false, baseColProps: { span: 12 }, }); + const showSidePane = computed(() => unref(isUpdate) && unref(formEditable) && unref(areaPanelVisible)); + + const modalWidth = computed(() => { + if (!unref(isUpdate)) { + return 1000; + } + return unref(showSidePane) ? 980 : 640; + }); + + const modalBodyStyle = computed(() => + unref(isUpdate) ? { paddingTop: '12px', paddingBottom: '8px' } : undefined + ); + + const layoutClass = computed(() => ({ + 'raw-card-modal__layout--split': unref(showSidePane), + })); + + const filteredAreaRows = computed(() => { + const q = unref(areaSearch).trim().toLowerCase(); + const rows = unref(areaRows); + if (!q) { + return rows; + } + return rows.filter( + (r) => + (r.areaCode || '').toLowerCase().includes(q) || + (r.areaName || '').toLowerCase().includes(q) || + (r.warehouseName || '').toLowerCase().includes(q) + ); + }); + + function warehouseAreaTriggerText(code: string | undefined | null) { + const c = (code || '').trim(); + if (!c) { + return ''; + } + const row = unref(areaRows).find((r) => (r.areaCode || '').trim() === c); + if (!row) { + return c; + } + const wh = (row.warehouseName || '').trim(); + const an = (row.areaName || '').trim(); + if (wh && an) { + return `${wh} · ${an}(${row.areaCode})`; + } + if (an) { + return `${an}(${row.areaCode})`; + } + return row.areaCode || c; + } + + let warehouseAreasLoadPromise: Promise | null = null; + + async function loadEnabledWarehouseAreas() { + if (warehouseAreasLoadPromise) { + return warehouseAreasLoadPromise; + } + warehouseAreasLoadPromise = (async () => { + areaLoading.value = true; + try { + const page = await warehouseAreaList({ + pageNo: 1, + pageSize: 5000, + status: '0', + }); + const records = (page?.records || []) as WarehouseAreaRow[]; + areaRows.value = records; + } catch { + areaRows.value = []; + } finally { + areaLoading.value = false; + } + })(); + try { + await warehouseAreasLoadPromise; + } finally { + warehouseAreasLoadPromise = null; + } + } + + async function onWarehouseAreaTriggerClick() { + if (!unref(formEditable)) { + return; + } + areaPanelVisible.value = true; + areaSearch.value = ''; + if (!unref(areaRows).length) { + await loadEnabledWarehouseAreas(); + } + } + + function onPickWarehouseArea(row: WarehouseAreaRow) { + if (!row?.areaCode || !unref(formEditable)) { + return; + } + const code = String(row.areaCode).trim(); + pickedAreaCode.value = code; + void setFieldsValue({ warehouseArea: code }); + } + const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => { + areaPanelVisible.value = false; + areaSearch.value = ''; await resetFields(); + const isAdd = !data?.isUpdate; + await resetSchema(isAdd ? formSchemaAdd : formSchemaEdit); + await setProps({ + disabled: !data?.showFooter, + baseColProps: { span: isAdd ? 12 : 24 }, + }); setModalProps({ confirmLoading: false, showCancelBtn: !!data?.showFooter, showOkBtn: !!data?.showFooter }); isUpdate.value = !!data?.isUpdate; isDetail.value = !!data?.showFooter; + formEditable.value = !!data?.showFooter; if (unref(isUpdate)) { + // 先写入行数据,避免等待库区列表接口导致整表单长时间空白 + pickedAreaCode.value = String(data.record?.warehouseArea || '').trim(); await setFieldsValue({ ...data.record }); + void loadEnabledWarehouseAreas(); + } else { + areaRows.value = []; + pickedAreaCode.value = ''; } - setProps({ disabled: !data?.showFooter }); }); const title = computed(() => (!unref(isUpdate) ? '新增' : !unref(isDetail) ? '详情' : '编辑')); - async function handleSubmit(v) { + async function handleSubmit() { try { - let values = await validate(); + const values = await validate(); setModalProps({ confirmLoading: true }); await saveOrUpdate(values, isUpdate.value); closeModal(); @@ -57,6 +250,158 @@ + + + diff --git a/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialCardEditLog/MesXslRawMaterialCardEditLog.api.ts b/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialCardEditLog/MesXslRawMaterialCardEditLog.api.ts new file mode 100644 index 0000000..f509821 --- /dev/null +++ b/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialCardEditLog/MesXslRawMaterialCardEditLog.api.ts @@ -0,0 +1,10 @@ +import { defHttp } from '/@/utils/http/axios'; + +enum Api { + list = '/xslmes/mesXslRawMaterialCardEditLog/list', + exportXls = '/xslmes/mesXslRawMaterialCardEditLog/exportXls', +} + +export const getExportUrl = Api.exportXls; + +export const list = (params) => defHttp.get({ url: Api.list, params }); diff --git a/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialCardEditLog/MesXslRawMaterialCardEditLog.data.ts b/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialCardEditLog/MesXslRawMaterialCardEditLog.data.ts new file mode 100644 index 0000000..484fd5b --- /dev/null +++ b/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialCardEditLog/MesXslRawMaterialCardEditLog.data.ts @@ -0,0 +1,45 @@ +import { BasicColumn, FormSchema } from '/@/components/Table'; + +export const columns: BasicColumn[] = [ + { title: '条码', align: 'center', dataIndex: 'barcode', width: 240 }, + { title: '批次号', align: 'center', dataIndex: 'batchNo', width: 220 }, + { title: '物料名称', align: 'center', dataIndex: 'materialName', width: 320 }, + { title: '修改前重量', align: 'center', dataIndex: 'beforeRemainingWeight', width: 110 }, + { title: '修改前数量', align: 'center', dataIndex: 'beforeRemainingQty', width: 100 }, + { title: '修改前库区', align: 'center', dataIndex: 'beforeWarehouseArea', width: 120 }, + { title: '修改后重量', align: 'center', dataIndex: 'afterRemainingWeight', width: 110 }, + { title: '修改后数量', align: 'center', dataIndex: 'afterRemainingQty', width: 100 }, + { title: '修改后库区', align: 'center', dataIndex: 'afterWarehouseArea', width: 120 }, + { + title: '修改时间', + align: 'center', + dataIndex: 'modifyTime', + width: 165, + }, + { title: '修改人姓名', align: 'center', dataIndex: 'modifyByName', width: 120 }, + { title: '数值来源', align: 'center', dataIndex: 'dataSource', width: 160, ellipsis: true }, +]; + +export const searchFormSchema: FormSchema[] = [ + { label: '条码', field: 'barcode', component: 'JInput', colProps: { span: 6 } }, + { label: '批次号', field: 'batchNo', component: 'JInput', colProps: { span: 6 } }, + { label: '物料名称', field: 'materialName', component: 'Input', colProps: { span: 6 } }, + { label: '修改人', field: 'modifyByName', component: 'Input', colProps: { span: 6 } }, + { + label: '数值来源', + field: 'dataSource', + component: 'Input', + colProps: { span: 6 }, + componentProps: { placeholder: '如 Web端原材料卡片' }, + }, + { + label: '修改时间', + field: 'modifyTime', + component: 'RangePicker', + colProps: { span: 8 }, + componentProps: { + showTime: true, + valueFormat: 'YYYY-MM-DD HH:mm:ss', + }, + }, +]; diff --git a/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialCardEditLog/MesXslRawMaterialCardEditLogList.vue b/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialCardEditLog/MesXslRawMaterialCardEditLogList.vue new file mode 100644 index 0000000..299559f --- /dev/null +++ b/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialCardEditLog/MesXslRawMaterialCardEditLogList.vue @@ -0,0 +1,44 @@ + + + diff --git a/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialEntry/MesXslRawMaterialEntry.api.ts b/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialEntry/MesXslRawMaterialEntry.api.ts index 1a17fe5..c60ed93 100644 --- a/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialEntry/MesXslRawMaterialEntry.api.ts +++ b/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialEntry/MesXslRawMaterialEntry.api.ts @@ -1,14 +1,11 @@ import { defHttp } from '/@/utils/http/axios'; -import { useMessage } from '/@/hooks/web/useMessage'; -const { createConfirm } = useMessage(); - -enum Api { - list = '/xslmes/mesXslRawMaterialEntry/list', +enum Api { list = '/xslmes/mesXslRawMaterialEntry/list', save = '/xslmes/mesXslRawMaterialEntry/add', edit = '/xslmes/mesXslRawMaterialEntry/edit', deleteOne = '/xslmes/mesXslRawMaterialEntry/delete', deleteBatch = '/xslmes/mesXslRawMaterialEntry/deleteBatch', + linkedRawMaterialCards = '/xslmes/mesXslRawMaterialEntry/linkedRawMaterialCards', batchStockIn = '/xslmes/mesXslRawMaterialEntry/batchStockIn', importExcel = '/xslmes/mesXslRawMaterialEntry/importExcel', exportXls = '/xslmes/mesXslRawMaterialEntry/exportXls', @@ -20,26 +17,29 @@ enum Api { export const getExportUrl = Api.exportXls; export const getImportUrl = Api.importExcel; +/** 删除前:查询入场记录关联的已生成原材料卡片 */ +export const getLinkedRawMaterialCards = (ids: string) => + defHttp.get({ url: Api.linkedRawMaterialCards, params: { ids } }); + +export interface MesXslRawMaterialCardBrief { + id?: string; + barcode?: string; + batchNo?: string; + materialName?: string; + splitDetailId?: string; +} + export const list = (params) => defHttp.get({ url: Api.list, params }); -export const deleteOne = (params, handleSuccess) => { +export const deleteOne = (params: { id: string; cascadeDeleteCards?: boolean }, handleSuccess?: () => void) => { return defHttp.delete({ url: Api.deleteOne, params }, { joinParamsToUrl: true }).then(() => { - handleSuccess(); + handleSuccess?.(); }); }; -export const batchDelete = (params, handleSuccess) => { - createConfirm({ - iconType: 'warning', - title: '确认删除', - content: '是否删除选中数据', - okText: '确认', - cancelText: '取消', - onOk: () => { - return defHttp.delete({ url: Api.deleteBatch, data: params }, { joinParamsToUrl: true }).then(() => { - handleSuccess(); - }); - }, +export const batchDelete = (params: { ids: string; cascadeDeleteCards?: boolean }, handleSuccess?: () => void) => { + return defHttp.delete({ url: Api.deleteBatch, params }, { joinParamsToUrl: true }).then(() => { + handleSuccess?.(); }); }; diff --git a/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialEntry/MesXslRawMaterialEntryList.vue b/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialEntry/MesXslRawMaterialEntryList.vue index 503e868..e1c8e64 100644 --- a/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialEntry/MesXslRawMaterialEntryList.vue +++ b/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialEntry/MesXslRawMaterialEntryList.vue @@ -6,23 +6,16 @@ 导出 导入 结存入库 - - PrintDot 桥接 - - + - - 下载打印插件 + 下载打印插件 - 刷新打印机 - - 添加 + 刷新打印机 @@ -80,11 +66,13 @@