diff --git a/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java b/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java index 56d6d50..ff49bd1 100644 --- a/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java +++ b/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java @@ -207,6 +207,10 @@ public class ShiroConfig { filterChainDefinitionMap.put("/xslmes/mesXslRawMaterialEntry/anon/**", "anon"); // MES原材料卡片免密接口(供桌面端调用) filterChainDefinitionMap.put("/xslmes/mesXslRawMaterialCard/anon/**", "anon"); + // MES仓库管理只读免密接口(供桌面端下拉筛选调用) + filterChainDefinitionMap.put("/xslmes/mesXslWarehouse/anon/**", "anon"); + // MES库区管理免密接口(供桌面端调用) + filterChainDefinitionMap.put("/xslmes/mesXslWarehouseArea/anon/**", "anon"); // MES密炼物料管理免密接口(供桌面端调用) filterChainDefinitionMap.put("/mes/material/mixerMaterial/anon/**", "anon"); // 系统分类字典免密接口(供桌面端调用) 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 accbd7e..c4f5c7e 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 @@ -18,12 +18,16 @@ import org.jeecg.modules.xslmes.entity.MesXslRawMaterialCard; import org.jeecg.modules.xslmes.entity.MesXslRawMaterialEntry; import org.jeecg.modules.xslmes.entity.MesXslSupplier; import org.jeecg.modules.xslmes.entity.MesXslVehicle; +import org.jeecg.modules.xslmes.entity.MesXslWarehouse; +import org.jeecg.modules.xslmes.entity.MesXslWarehouseArea; import org.jeecg.modules.xslmes.entity.MesXslWeightRecord; import org.jeecg.modules.xslmes.service.IMesXslCustomerService; import org.jeecg.modules.xslmes.service.IMesXslRawMaterialCardService; import org.jeecg.modules.xslmes.service.IMesXslRawMaterialEntryService; import org.jeecg.modules.xslmes.service.IMesXslSupplierService; import org.jeecg.modules.xslmes.service.IMesXslVehicleService; +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.springframework.web.bind.annotation.*; @@ -52,6 +56,8 @@ public class MesXslDesktopAnonController { private final IMesXslWeightRecordService weightRecordService; private final IMesXslRawMaterialEntryService rawMaterialEntryService; private final IMesXslRawMaterialCardService rawMaterialCardService; + private final IMesXslWarehouseService warehouseService; + private final IMesXslWarehouseAreaService warehouseAreaService; private final MesXslStompNotifyService stompNotify; // ═══════════════════════════ 车辆管理 ═══════════════════════════ @@ -565,6 +571,162 @@ public class MesXslDesktopAnonController { return Result.OK("批量删除成功!"); } + /** + * 「重新拆码」专用:按拆码明细 ID 列表批量删除原材料卡片。 + * dryRun=true 时仅返回匹配数量,不删除;用于桌面端弹窗确认前展示「将清空 N 条卡片」。 + */ + @Operation(summary = "原材料卡片-免密按拆码明细ID批量删除(dryRun=true 仅统计)") + @PostMapping("/xslmes/mesXslRawMaterialCard/anon/deleteBySplitDetailIds") + public Result rawMaterialCardAnonDeleteBySplitDetailIds( + @RequestParam(name = "splitDetailIds") String splitDetailIds, + @RequestParam(name = "dryRun", required = false, defaultValue = "false") Boolean dryRun) { + if (oConvertUtils.isEmpty(splitDetailIds)) { + return Result.OK(0); + } + java.util.List idList = java.util.Arrays.stream(splitDetailIds.split(",")) + .map(String::trim) + .filter(s -> !s.isEmpty()) + .distinct() + .collect(java.util.stream.Collectors.toList()); + if (idList.isEmpty()) { + return Result.OK(0); + } + long count = rawMaterialCardService.lambdaQuery() + .in(MesXslRawMaterialCard::getSplitDetailId, idList) + .count(); + if (Boolean.TRUE.equals(dryRun)) { + return Result.OK((int) count); + } + boolean ok = rawMaterialCardService.lambdaUpdate() + .in(MesXslRawMaterialCard::getSplitDetailId, idList) + .remove(); + if (ok) { + stompNotify.publishRawMaterialCardChanged("batchDelete", String.join(",", idList)); + } + return Result.OK((int) count); + } + + // ═══════════════════════════ 仓库管理(只读,供桌面端下拉选取) ═══════════════════════════ + + @Operation(summary = "仓库-免密分页列表查询(供桌面端筛选使用)") + @GetMapping("/xslmes/mesXslWarehouse/anon/list") + public Result> warehouseAnonList( + MesXslWarehouse mesXslWarehouse, + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "200") Integer pageSize, + HttpServletRequest req) { + QueryWrapper qw = QueryGenerator.initQueryWrapper(mesXslWarehouse, req.getParameterMap()); + qw.orderByAsc("warehouse_name"); + IPage page = warehouseService.page(new Page<>(pageNo, pageSize), qw); + return Result.OK(page); + } + + // ═══════════════════════════ 库区管理 ═══════════════════════════ + + @Operation(summary = "库区-免密分页列表查询") + @GetMapping("/xslmes/mesXslWarehouseArea/anon/list") + public Result> warehouseAreaAnonList( + MesXslWarehouseArea mesXslWarehouseArea, + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, + HttpServletRequest req) { + QueryWrapper qw = QueryGenerator.initQueryWrapper(mesXslWarehouseArea, req.getParameterMap()); + IPage page = warehouseAreaService.page(new Page<>(pageNo, pageSize), qw); + return Result.OK(page); + } + + @Operation(summary = "库区-免密通过id查询") + @GetMapping("/xslmes/mesXslWarehouseArea/anon/queryById") + public Result warehouseAreaAnonQueryById(@RequestParam(name = "id") String id) { + MesXslWarehouseArea entity = warehouseAreaService.getById(id); + return entity != null ? Result.OK(entity) : Result.error("未找到对应数据"); + } + + @Operation(summary = "库区-免密添加") + @PostMapping("/xslmes/mesXslWarehouseArea/anon/add") + public Result warehouseAreaAnonAdd(@RequestBody MesXslWarehouseArea entity) { + if (oConvertUtils.isEmpty(entity.getAreaCode()) || entity.getAreaCode().trim().isEmpty()) { + return Result.error("库区编码不能为空"); + } + if (warehouseAreaService.existsSameAreaCode(entity.getAreaCode().trim(), null)) { + return Result.error("库区编码已存在,不允许重复"); + } + if (entity.getStatus() == null || entity.getStatus().isEmpty()) { + entity.setStatus("0"); + } + warehouseAreaService.save(entity); + stompNotify.publishWarehouseAreaChanged("add", entity.getId()); + return Result.OK("添加成功!"); + } + + @Operation(summary = "库区-免密编辑") + @RequestMapping(value = "/xslmes/mesXslWarehouseArea/anon/edit", method = {RequestMethod.PUT, RequestMethod.POST}) + public Result warehouseAreaAnonEdit(@RequestBody MesXslWarehouseArea entity) { + if (oConvertUtils.isEmpty(entity.getId())) { + return Result.error("主键不能为空"); + } + if (oConvertUtils.isEmpty(entity.getAreaCode()) || entity.getAreaCode().trim().isEmpty()) { + return Result.error("库区编码不能为空"); + } + if (warehouseAreaService.existsSameAreaCode(entity.getAreaCode().trim(), entity.getId())) { + return Result.error("库区编码已存在,不允许重复"); + } + boolean ok = warehouseAreaService.updateById(entity); + if (!ok) { + return Result.error("数据已被他人修改,请刷新后重试"); + } + stompNotify.publishWarehouseAreaChanged("edit", entity.getId()); + return Result.OK("编辑成功!"); + } + + @Operation(summary = "库区-免密删除") + @DeleteMapping("/xslmes/mesXslWarehouseArea/anon/delete") + public Result warehouseAreaAnonDelete(@RequestParam(name = "id") String id) { + warehouseAreaService.removeById(id); + stompNotify.publishWarehouseAreaChanged("delete", id); + return Result.OK("删除成功!"); + } + + @Operation(summary = "库区-免密批量删除") + @DeleteMapping("/xslmes/mesXslWarehouseArea/anon/deleteBatch") + public Result warehouseAreaAnonDeleteBatch(@RequestParam(name = "ids") String ids) { + warehouseAreaService.removeByIds(Arrays.asList(ids.split(","))); + stompNotify.publishWarehouseAreaChanged("batchDelete", ids); + return Result.OK("批量删除成功!"); + } + + @Operation(summary = "库区-免密启用/停用") + @PostMapping("/xslmes/mesXslWarehouseArea/anon/updateStatus") + public Result warehouseAreaAnonUpdateStatus( + @RequestParam(name = "id") String id, + @RequestParam(name = "status") String status) { + if (!"0".equals(status) && !"1".equals(status)) { + return Result.error("状态参数非法"); + } + boolean ok = warehouseAreaService.lambdaUpdate() + .eq(MesXslWarehouseArea::getId, id) + .set(MesXslWarehouseArea::getStatus, status) + .update(); + if (ok) { + stompNotify.publishWarehouseAreaChanged("status", id); + } + return ok ? Result.OK("操作成功") : Result.error("操作失败"); + } + + @Operation(summary = "库区-免密校验库区编码是否重复") + @GetMapping("/xslmes/mesXslWarehouseArea/anon/checkAreaCode") + public Result warehouseAreaAnonCheckAreaCode( + @RequestParam(name = "areaCode") String areaCode, + @RequestParam(name = "dataId", required = false) String dataId) { + if (oConvertUtils.isEmpty(areaCode) || areaCode.trim().isEmpty()) { + return Result.OK("该值可用!"); + } + if (warehouseAreaService.existsSameAreaCode(areaCode.trim(), dataId)) { + return Result.error("该库区编码已存在"); + } + return Result.OK("该值可用!"); + } + // ─────────────────────────── 车辆私有辅助 ──────────────────────────── private void applyWeightBillType(MesXslWeightRecord record) { 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 219af62..9a5c115 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 @@ -10,6 +10,7 @@ import org.jeecg.modules.xslmes.service.IMesXslRawMaterialEntryService; import org.jeecg.modules.xslmes.service.MesXslStompNotifyService; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.extern.slf4j.Slf4j; @@ -82,6 +83,18 @@ public class MesXslRawMaterialEntryController extends JeecgController batchStockIn(@RequestParam(name = "ids", required = true) String ids) { + UpdateWrapper uw = new UpdateWrapper<>(); + uw.in("id", Arrays.asList(ids.split(","))).set("stock_balance", "1"); + mesXslRawMaterialEntryService.update(uw); + stompNotify.publishRawMaterialEntryChanged("batchStockIn", ids); + return Result.OK("结存入库成功!"); + } + @AutoLog(value = "原料入场记录-批量删除") @Operation(summary = "原料入场记录-批量删除") @RequiresPermissions("xslmes:mes_xsl_raw_material_entry:deleteBatch") diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslWarehouseAreaController.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslWarehouseAreaController.java new file mode 100644 index 0000000..8f75448 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslWarehouseAreaController.java @@ -0,0 +1,183 @@ +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 jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.jeecg.common.api.vo.Result; +import org.jeecg.common.aspect.annotation.AutoLog; +import org.jeecg.common.system.base.controller.JeecgController; +import org.jeecg.common.system.query.QueryGenerator; +import org.jeecg.common.util.oConvertUtils; +import org.jeecg.modules.xslmes.entity.MesXslWarehouseArea; +import org.jeecg.modules.xslmes.service.IMesXslWarehouseAreaService; +import org.jeecg.modules.xslmes.service.MesXslStompNotifyService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.ModelAndView; + +import java.util.Arrays; +import java.util.List; + +/** + * MES 库区管理 + */ +@Tag(name = "MES库区管理") +@RestController +@RequestMapping("/xslmes/mesXslWarehouseArea") +@Slf4j +public class MesXslWarehouseAreaController extends JeecgController { + + @Autowired + private IMesXslWarehouseAreaService mesXslWarehouseAreaService; + + @Autowired + private MesXslStompNotifyService stompNotify; + + @Operation(summary = "MES库区管理-分页列表查询") + @GetMapping(value = "/list") + public Result> queryPageList( + MesXslWarehouseArea mesXslWarehouseArea, + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, + HttpServletRequest req) { + QueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(mesXslWarehouseArea, req.getParameterMap()); + Page page = new Page<>(pageNo, pageSize); + IPage pageList = mesXslWarehouseAreaService.page(page, queryWrapper); + return Result.OK(pageList); + } + + @AutoLog(value = "MES库区管理-添加") + @Operation(summary = "MES库区管理-添加") + @RequiresPermissions("xslmes:mes_xsl_warehouse_area:add") + @PostMapping(value = "/add") + public Result add(@RequestBody MesXslWarehouseArea mesXslWarehouseArea) { + if (mesXslWarehouseAreaService.existsSameAreaCode(mesXslWarehouseArea.getAreaCode(), null)) { + return Result.error("库区编码已存在"); + } + if (mesXslWarehouseArea.getStatus() == null || mesXslWarehouseArea.getStatus().isEmpty()) { + mesXslWarehouseArea.setStatus("0"); + } + mesXslWarehouseAreaService.save(mesXslWarehouseArea); + stompNotify.publishWarehouseAreaChanged("add", mesXslWarehouseArea.getId()); + return Result.OK("添加成功!"); + } + + @AutoLog(value = "MES库区管理-编辑") + @Operation(summary = "MES库区管理-编辑") + @RequiresPermissions("xslmes:mes_xsl_warehouse_area:edit") + @RequestMapping(value = "/edit", method = {RequestMethod.PUT, RequestMethod.POST}) + public Result edit(@RequestBody MesXslWarehouseArea mesXslWarehouseArea) { + if (mesXslWarehouseAreaService.existsSameAreaCode(mesXslWarehouseArea.getAreaCode(), mesXslWarehouseArea.getId())) { + return Result.error("库区编码已存在"); + } + mesXslWarehouseAreaService.updateById(mesXslWarehouseArea); + stompNotify.publishWarehouseAreaChanged("edit", mesXslWarehouseArea.getId()); + return Result.OK("编辑成功!"); + } + + @AutoLog(value = "MES库区管理-停用/启用") + @Operation(summary = "MES库区管理-停用/启用(字典 xslmes_unit_status:0启用 1停用)") + @RequiresPermissions("xslmes:mes_xsl_warehouse_area:updateStatus") + @PostMapping(value = "/updateStatus") + public Result updateStatus( + @RequestParam(name = "id", required = true) String id, + @RequestParam(name = "status", required = true) String status) { + if (!"0".equals(status) && !"1".equals(status)) { + return Result.error("状态参数非法"); + } + boolean ok = mesXslWarehouseAreaService.lambdaUpdate() + .eq(MesXslWarehouseArea::getId, id) + .set(MesXslWarehouseArea::getStatus, status) + .update(); + stompNotify.publishWarehouseAreaChanged("edit", id); + return ok ? Result.OK("操作成功") : Result.error("操作失败"); + } + + @Operation(summary = "校验库区编码是否重复(同租户,dataId 为编辑时当前主键)") + @GetMapping(value = "/checkAreaCode") + public Result checkAreaCode( + @RequestParam(name = "areaCode", required = true) String areaCode, + @RequestParam(name = "dataId", required = false) String dataId) { + if (oConvertUtils.isEmpty(areaCode) || areaCode.trim().isEmpty()) { + return Result.OK("该值可用!"); + } + if (mesXslWarehouseAreaService.existsSameAreaCode(areaCode, dataId)) { + return Result.error("该库区编码已存在"); + } + return Result.OK("该值可用!"); + } + + @AutoLog(value = "MES库区管理-批量添加") + @Operation(summary = "MES库区管理-批量添加(为指定仓库一次性创建多条库区)") + @RequiresPermissions("xslmes:mes_xsl_warehouse_area:add") + @PostMapping(value = "/batchAdd") + public Result batchAdd(@RequestBody List list) { + if (list == null || list.isEmpty()) { + return Result.error("请至少添加一条库区记录"); + } + for (MesXslWarehouseArea area : list) { + if (oConvertUtils.isEmpty(area.getAreaCode()) || area.getAreaCode().trim().isEmpty()) { + return Result.error("库区编码不能为空"); + } + if (mesXslWarehouseAreaService.existsSameAreaCode(area.getAreaCode(), null)) { + return Result.error("库区编码「" + area.getAreaCode() + "」已存在,请修改后重试"); + } + if (area.getStatus() == null || area.getStatus().isEmpty()) { + area.setStatus("0"); + } + } + mesXslWarehouseAreaService.saveBatch(list); + for (MesXslWarehouseArea area : list) { + stompNotify.publishWarehouseAreaChanged("add", area.getId()); + } + return Result.OK("批量添加成功,共创建 " + list.size() + " 个库区!"); + } + + @AutoLog(value = "MES库区管理-删除") + @Operation(summary = "MES库区管理-删除") + @RequiresPermissions("xslmes:mes_xsl_warehouse_area:delete") + @DeleteMapping(value = "/delete") + public Result delete(@RequestParam(name = "id", required = true) String id) { + mesXslWarehouseAreaService.removeById(id); + stompNotify.publishWarehouseAreaChanged("delete", id); + return Result.OK("删除成功!"); + } + + @AutoLog(value = "MES库区管理-批量删除") + @Operation(summary = "MES库区管理-批量删除") + @RequiresPermissions("xslmes:mes_xsl_warehouse_area:deleteBatch") + @DeleteMapping(value = "/deleteBatch") + public Result deleteBatch(@RequestParam(name = "ids", required = true) String ids) { + mesXslWarehouseAreaService.removeByIds(Arrays.asList(ids.split(","))); + stompNotify.publishWarehouseAreaChanged("batchDelete", ids); + return Result.OK("批量删除成功!"); + } + + @Operation(summary = "MES库区管理-通过id查询") + @GetMapping(value = "/queryById") + public Result queryById(@RequestParam(name = "id", required = true) String id) { + MesXslWarehouseArea entity = mesXslWarehouseAreaService.getById(id); + if (entity == null) { + return Result.error("未找到对应数据"); + } + return Result.OK(entity); + } + + @RequiresPermissions("xslmes:mes_xsl_warehouse_area:exportXls") + @RequestMapping(value = "/exportXls") + public ModelAndView exportXls(HttpServletRequest request, MesXslWarehouseArea mesXslWarehouseArea) { + return super.exportXls(request, mesXslWarehouseArea, MesXslWarehouseArea.class, "MES库区管理"); + } + + @RequiresPermissions("xslmes:mes_xsl_warehouse_area:importExcel") + @RequestMapping(value = "/importExcel", method = RequestMethod.POST) + public Result importExcel(HttpServletRequest request, HttpServletResponse response) { + return super.importExcel(request, response, MesXslWarehouseArea.class); + } +} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslWeightRecordController.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslWeightRecordController.java index 4f76fb6..9e112f0 100644 --- a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslWeightRecordController.java +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/controller/MesXslWeightRecordController.java @@ -14,6 +14,7 @@ import org.jeecg.common.aspect.annotation.AutoLog; import org.jeecg.common.system.base.controller.JeecgController; import org.jeecg.common.system.query.QueryGenerator; import org.jeecg.modules.xslmes.entity.MesXslWeightRecord; +import org.jeecg.modules.xslmes.service.IMesXslRawMaterialEntryService; import org.jeecg.modules.xslmes.service.IMesXslWeightRecordService; import org.jeecg.modules.xslmes.service.MesXslStompNotifyService; import org.springframework.beans.factory.annotation.Autowired; @@ -23,8 +24,12 @@ import org.springframework.web.servlet.ModelAndView; import java.math.BigDecimal; import java.text.SimpleDateFormat; import java.util.Arrays; +import java.util.Collections; import java.util.Date; +import java.util.List; +import java.util.Map; import java.util.Random; +import java.util.stream.Collectors; /** * 地磅数据记录 @@ -39,6 +44,8 @@ public class MesXslWeightRecordController extends JeecgController page = new Page<>(pageNo, pageSize); IPage pageList = mesXslWeightRecordService.page(page, queryWrapper); + fillEnteredWeight(pageList.getRecords()); return Result.OK(pageList); } @@ -112,6 +120,7 @@ public class MesXslWeightRecordController extends JeecgController records) { + if (records == null || records.isEmpty()) { + return; + } + List billNos = records.stream() + .map(MesXslWeightRecord::getBillNo) + .filter(s -> s != null && !s.isBlank()) + .distinct() + .collect(Collectors.toList()); + if (billNos.isEmpty()) { + return; + } + Map sumMap = rawMaterialEntryService.sumEnteredWeightByBillNos(billNos); + for (MesXslWeightRecord r : records) { + BigDecimal v = (r.getBillNo() == null) ? null : sumMap.get(r.getBillNo()); + r.setEnteredWeight(v != null ? v : BigDecimal.ZERO); + } + } } diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslRawMaterialCard.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslRawMaterialCard.java index 54d020d..2fbfe9a 100644 --- a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslRawMaterialCard.java +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslRawMaterialCard.java @@ -37,6 +37,14 @@ public class MesXslRawMaterialCard implements Serializable { @Schema(description = "条码") private String barcode; + /** + * 关联的拆码明细行 ID(GUID)。 + * 「生成原材料卡片」时由桌面端把对应 RawMaterialSplitDetailItem.Id 写入; + * 「重新拆码」时按入场记录 portion_detail_ids 反查、IN 批量清除关联卡片。 + */ + @Schema(description = "关联的拆码明细行 ID(GUID)") + private String splitDetailId; + @Excel(name = "批次号", width = 20) @Schema(description = "批次号") private String batchNo; 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 053dba6..8885a30 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 @@ -102,6 +102,32 @@ public class MesXslRawMaterialEntry implements Serializable { @Schema(description = "每份包数(支持多行拆码明细拼接)") private String portionPackages; + /** + * 拆码明细库位拼接(以 / 分隔,末尾带 /,如 1F-A01/1F-A02/)。 + * 与 warehouseLocation(基础资料整票级单值)区分:本字段保存每行明细各自的库位, + * 用于桌面端「新增原料入场记录」重新打开后回填每行库位。 + */ + @Excel(name = "明细库位", width = 24) + @Schema(description = "拆码明细库位拼接(以 / 分隔,末尾带 /,如 1F-A01/1F-A02/)") + private String portionWarehouseLocations; + + /** + * 拆码明细每行的 GUID 拼接(以 / 分隔,末尾带 /)。 + * 与 total_portions / portion_weight / portion_packages / portion_warehouse_locations + * 按相同分隔规则、行序对齐,供「重新拆码」时按 IN 批量删除原材料卡片。 + */ + @Schema(description = "拆码明细每行的 GUID 拼接(以 / 分隔,末尾带 /)") + private String portionDetailIds; + + /** + * 拆码明细行级「已生成卡片」标志拼接(以 / 分隔,末尾带 /,1=已生成 0=未生成)。 + * 桌面端 GenerateRawMaterialCardsAsync 按此字段过滤待生成行(HasCard==false 的行才参与生成), + * 避免靠 print_flag 推断导致「保存后新增行被误判为已打印」的问题。 + * 历史记录留空时桌面端降级使用 print_flag 推断,与旧行为兼容。 + */ + @Schema(description = "拆码明细行级「已生成卡片」标志拼接(以 / 分隔,1=已生成 0=未生成,如 1/1/0/)") + private String portionCardFlags; + @Excel(name = "检测结果", width = 12, dicCode = "xslmes_test_result") @Dict(dicCode = "xslmes_test_result") @Schema(description = "检测结果(字典 xslmes_test_result:0未检 1合格 2不合格)") diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslWarehouseArea.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslWarehouseArea.java new file mode 100644 index 0000000..64e8b8e --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslWarehouseArea.java @@ -0,0 +1,70 @@ +package org.jeecg.modules.xslmes.entity; + +import com.baomidou.mybatisplus.annotation.TableLogic; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.jeecg.common.aspect.annotation.Dict; +import org.jeecg.common.system.base.entity.JeecgEntity; +import org.jeecgframework.poi.excel.annotation.Excel; + +import java.io.Serializable; + +/** + * MES 库区管理 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("mes_xsl_warehouse_area") +@Schema(description = "MES库区管理") +public class MesXslWarehouseArea extends JeecgEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + @Excel(name = "库区编码", width = 18) + @Schema(description = "库区编码(同租户唯一)") + private String areaCode; + + @Excel(name = "库区名称", width = 22) + @Schema(description = "库区名称") + private String areaName; + + @Schema(description = "所属仓库ID") + private String warehouseId; + + @Excel(name = "所属仓库", width = 22) + @Schema(description = "所属仓库名称(冗余,由仓库带出)") + private String warehouseName; + + @Excel(name = "仓库分类", width = 14, dictTable = "sys_category", dicText = "name", dicCode = "id") + @Dict(dictTable = "sys_category", dicText = "name", dicCode = "id") + @Schema(description = "仓库分类(sys_category.id,由仓库自动带出,根编码 XSLMES_WH)") + private String warehouseCategory; + + @Excel(name = "最大存放量", width = 14) + @Schema(description = "最大存放量") + private Integer maxCapacity; + + @Excel(name = "实际存放量", width = 14) + @Schema(description = "实际存放量") + private Integer actualCapacity; + + @Excel(name = "备注", width = 30) + @Schema(description = "备注") + private String remark; + + @Excel(name = "状态", width = 10, dicCode = "xslmes_unit_status") + @Dict(dicCode = "xslmes_unit_status") + @Schema(description = "状态:0启用 1停用") + private String status; + + @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/entity/MesXslWeightRecord.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslWeightRecord.java index 415325b..26f8753 100644 --- a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslWeightRecord.java +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/entity/MesXslWeightRecord.java @@ -1,5 +1,6 @@ package org.jeecg.modules.xslmes.entity; +import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.annotation.JsonFormat; @@ -118,4 +119,14 @@ public class MesXslWeightRecord extends JeecgEntity implements Serializable { @Schema(description = "租户ID") private Integer tenantId; + + /** + * 已入场重量(KG)—— 实时计算,不落库。 + * 数据来源:所有引用本榜单(bill_no 匹配)的原料入场记录的拆码明细。 + * 公式:每条 entry 按 "x/y/z/" 拆分 totalPortions 和 portionWeight, + * 逐位 (份数 × 每份重量) 累加;再把所有匹配 entry 的结果再次累加。 + */ + @TableField(exist = false) + @Schema(description = "已入场重量(KG),由原料入场记录的拆码明细实时累计") + private BigDecimal enteredWeight; } diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/MesXslWarehouseAreaMapper.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/MesXslWarehouseAreaMapper.java new file mode 100644 index 0000000..807ffaa --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/MesXslWarehouseAreaMapper.java @@ -0,0 +1,12 @@ +package org.jeecg.modules.xslmes.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; +import org.jeecg.modules.xslmes.entity.MesXslWarehouseArea; + +/** + * MES 库区管理 Mapper + */ +@Mapper +public interface MesXslWarehouseAreaMapper extends BaseMapper { +} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/xml/MesXslWarehouseAreaMapper.xml b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/xml/MesXslWarehouseAreaMapper.xml new file mode 100644 index 0000000..1b3bec0 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/mapper/xml/MesXslWarehouseAreaMapper.xml @@ -0,0 +1,4 @@ + + + + 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 df6290c..418e95e 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 @@ -3,6 +3,10 @@ package org.jeecg.modules.xslmes.service; import org.jeecg.modules.xslmes.entity.MesXslRawMaterialEntry; import com.baomidou.mybatisplus.extension.service.IService; +import java.math.BigDecimal; +import java.util.Collection; +import java.util.Map; + /** * @Description: 原料入场记录 * @Author: jeecg-boot @@ -19,4 +23,15 @@ public interface IMesXslRawMaterialEntryService extends IService + * 计算口径:对每条匹配 bill_no 的入场记录,将 totalPortions 和 portionWeight 按 "x/y/z/" 拆分, + * 逐位 (份数 × 每份重量) 累加,再把所有匹配 entry 的结果加在一起。 + * + * @param billNos 榜单号集合(去重前后都可) + * @return billNo -> 累计已入场重量;查不到的 billNo 不会出现在 map 中 + */ + Map sumEnteredWeightByBillNos(Collection billNos); } diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslWarehouseAreaService.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslWarehouseAreaService.java new file mode 100644 index 0000000..1046865 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/IMesXslWarehouseAreaService.java @@ -0,0 +1,15 @@ +package org.jeecg.modules.xslmes.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import org.jeecg.modules.xslmes.entity.MesXslWarehouseArea; + +/** + * MES 库区管理 + */ +public interface IMesXslWarehouseAreaService extends IService { + + /** + * 同租户下是否已存在相同库区编码(编辑时传 excludeId 排除自身) + */ + boolean existsSameAreaCode(String areaCode, String excludeId); +} diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/MesXslStompNotifyService.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/MesXslStompNotifyService.java index 5bbe5ab..2ec033d 100644 --- a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/MesXslStompNotifyService.java +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/MesXslStompNotifyService.java @@ -65,6 +65,11 @@ public class MesXslStompNotifyService { publish("/topic/sync/sys-dicts", "SYS_DICT_CHANGED", "dictId", dictId, action); } + /** 广播库区数据变更事件到 /topic/sync/mes-warehouse-areas */ + public void publishWarehouseAreaChanged(String action, String warehouseAreaId) { + publish("/topic/sync/mes-warehouse-areas", "MES_WAREHOUSE_AREA_CHANGED", "warehouseAreaId", warehouseAreaId, action); + } + // ─────────────────────────── 私有辅助 ──────────────────────────── private void publish(String topic, String cmd, String idKey, String idValue, String action) { 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 8e150db..72ab6bc 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 @@ -7,8 +7,17 @@ import org.jeecg.modules.xslmes.mapper.MesXslRawMaterialEntryMapper; import org.jeecg.modules.xslmes.service.IMesXslRawMaterialEntryService; import org.springframework.stereotype.Service; +import java.math.BigDecimal; import java.text.SimpleDateFormat; +import java.util.Collection; +import java.util.Collections; import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; /** * @Description: 原料入场记录 @@ -33,4 +42,76 @@ public class MesXslRawMaterialEntryServiceImpl return prefix + String.format("%03d", count + 1); } + + @Override + public Map sumEnteredWeightByBillNos(Collection billNos) { + if (billNos == null || billNos.isEmpty()) { + return Collections.emptyMap(); + } + + // 1) 去重 + 过滤空值 + Set distinct = billNos.stream() + .filter(s -> s != null && !s.isBlank()) + .collect(Collectors.toCollection(HashSet::new)); + if (distinct.isEmpty()) { + return Collections.emptyMap(); + } + + // 2) 一次查询拿到所有匹配 entry 的 (billNo, totalPortions, portionWeight) + // 只 select 三列,避免拉无关大字段 + LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); + qw.in(MesXslRawMaterialEntry::getBillNo, distinct) + .select(MesXslRawMaterialEntry::getBillNo, + MesXslRawMaterialEntry::getTotalPortions, + MesXslRawMaterialEntry::getPortionWeight); + List rows = this.list(qw); + + // 3) Java 端按 "x/y/z/" 拆分并逐位 (份数 × 每份重量) 累加 + Map result = new HashMap<>(); + for (MesXslRawMaterialEntry row : rows) { + BigDecimal sub = sumOnePackPositions(row.getTotalPortions(), row.getPortionWeight()); + if (sub.compareTo(BigDecimal.ZERO) == 0) continue; + result.merge(row.getBillNo(), sub, BigDecimal::add); + } + return result; + } + + /** + * 把一条入场记录的 totalPortions/portionWeight 按 "x/y/z/" 解析后,逐位 (份数 × 每份重量) 累加。 + * 任一位置解析失败或缺失,跳过该位置(不抛异常,确保前端展示降级可用)。 + */ + private static BigDecimal sumOnePackPositions(String totalPortions, String portionWeight) { + String[] portionsArr = splitJoined(totalPortions); + String[] weightsArr = splitJoined(portionWeight); + if (portionsArr.length == 0 || weightsArr.length == 0) { + return BigDecimal.ZERO; + } + int n = Math.min(portionsArr.length, weightsArr.length); + BigDecimal sum = BigDecimal.ZERO; + for (int i = 0; i < n; i++) { + BigDecimal portions = tryParseBigDecimal(portionsArr[i]); + BigDecimal weight = tryParseBigDecimal(weightsArr[i]); + if (portions == null || weight == null) continue; + sum = sum.add(portions.multiply(weight)); + } + return sum; + } + + private static String[] splitJoined(String value) { + if (value == null || value.isBlank()) return new String[0]; + // 兼容 "x/y/z" 与 "x/y/z/" 两种格式,过滤空段 + return java.util.Arrays.stream(value.split("/")) + .map(String::trim) + .filter(s -> !s.isEmpty()) + .toArray(String[]::new); + } + + private static BigDecimal tryParseBigDecimal(String s) { + if (s == null || s.isBlank()) return null; + try { + return new BigDecimal(s.trim()); + } catch (NumberFormatException ex) { + return null; + } + } } diff --git a/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslWarehouseAreaServiceImpl.java b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslWarehouseAreaServiceImpl.java new file mode 100644 index 0000000..d4a2908 --- /dev/null +++ b/jeecg-boot/jeecg-boot-module/jeecg-module-xslmes/src/main/java/org/jeecg/modules/xslmes/service/impl/MesXslWarehouseAreaServiceImpl.java @@ -0,0 +1,27 @@ +package org.jeecg.modules.xslmes.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.apache.commons.lang3.StringUtils; +import org.jeecg.modules.xslmes.entity.MesXslWarehouseArea; +import org.jeecg.modules.xslmes.mapper.MesXslWarehouseAreaMapper; +import org.jeecg.modules.xslmes.service.IMesXslWarehouseAreaService; +import org.springframework.stereotype.Service; + +/** + * MES 库区管理 + */ +@Service +public class MesXslWarehouseAreaServiceImpl extends ServiceImpl implements IMesXslWarehouseAreaService { + + @Override + public boolean existsSameAreaCode(String areaCode, String excludeId) { + if (StringUtils.isBlank(areaCode)) { + return false; + } + String code = areaCode.trim(); + return this.lambdaQuery() + .eq(MesXslWarehouseArea::getAreaCode, code) + .ne(StringUtils.isNotBlank(excludeId), MesXslWarehouseArea::getId, excludeId) + .count() > 0L; + } +} diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysCategoryServiceImpl.java b/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysCategoryServiceImpl.java index f96bd57..cff09f8 100644 --- a/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysCategoryServiceImpl.java +++ b/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysCategoryServiceImpl.java @@ -31,7 +31,6 @@ public class SysCategoryServiceImpl extends ServiceImpl().eq(SysCategory::getCode, customCode)); + if(exists > 0){ + throw new JeecgBootException("分类编码【"+customCode+"】已存在,请更换!"); + } + sysCategory.setCode(customCode); + } sysCategory.setPid(categoryPid); baseMapper.insert(sysCategory); } @@ -68,6 +79,18 @@ public class SysCategoryServiceImpl extends ServiceImpl() + .eq(SysCategory::getCode, newCode) + .ne(SysCategory::getId, sysCategory.getId())); + if(exists > 0){ + throw new JeecgBootException("分类编码【"+newCode+"】已存在,请更换!"); + } + sysCategory.setCode(newCode); + } baseMapper.updateById(sysCategory); } diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_45__mes_xsl_warehouse_area.sql b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_45__mes_xsl_warehouse_area.sql new file mode 100644 index 0000000..c37be35 --- /dev/null +++ b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_45__mes_xsl_warehouse_area.sql @@ -0,0 +1,100 @@ +-- 库区管理:建表 + 菜单权限(幂等) + +-- ===================== 1. 建表 ===================== +CREATE TABLE IF NOT EXISTS `mes_xsl_warehouse_area` ( + `id` varchar(32) NOT NULL COMMENT '主键', + `area_code` varchar(100) DEFAULT NULL COMMENT '库区编码(同租户唯一)', + `area_name` varchar(200) DEFAULT NULL COMMENT '库区名称', + `warehouse_id` varchar(32) DEFAULT NULL COMMENT '所属仓库ID', + `warehouse_name` varchar(200) DEFAULT NULL COMMENT '所属仓库名称(冗余)', + `warehouse_category` varchar(36) DEFAULT NULL COMMENT '仓库分类(sys_category.id,由仓库带出,根编码 XSLMES_WH)', + `max_capacity` int DEFAULT NULL COMMENT '最大存放量', + `actual_capacity` int DEFAULT NULL COMMENT '实际存放量', + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + `status` varchar(10) DEFAULT '0' COMMENT '状态(字典 xslmes_unit_status:0启用 1停用)', + `create_by` varchar(50) DEFAULT NULL COMMENT '创建人', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(50) DEFAULT NULL COMMENT '更新人', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + `del_flag` int DEFAULT 0 COMMENT '删除标记(0正常 1已删除)', + `tenant_id` int DEFAULT 1002 COMMENT '租户ID', + PRIMARY KEY (`id`), + KEY `idx_wa_warehouse_id` (`warehouse_id`), + KEY `idx_wa_area_code` (`area_code`), + KEY `idx_wa_warehouse_category` (`warehouse_category`), + KEY `idx_wa_status` (`status`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='MES库区管理'; + +-- ===================== 2. 菜单权限(父菜单:MES XSL 1900000000000000300)===================== +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 '1900000000000000550', '1900000000000000300', '库区管理', '/xslmes/mesXslWarehouseArea', 'xslmes/mesXslWarehouseArea/MesXslWarehouseAreaList', 1, NULL, NULL, 1, NULL, '0', 13.00, 0, 'ant-design:appstore-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` = '1900000000000000550'); + +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 '1900000000000000551', '1900000000000000550', '添加', NULL, NULL, 0, NULL, NULL, 2, 'xslmes:mes_xsl_warehouse_area:add', '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` = '1900000000000000551'); + +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 '1900000000000000552', '1900000000000000550', '编辑', NULL, NULL, 0, NULL, NULL, 2, 'xslmes:mes_xsl_warehouse_area:edit', '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` = '1900000000000000552'); + +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 '1900000000000000553', '1900000000000000550', '删除', NULL, NULL, 0, NULL, NULL, 2, 'xslmes:mes_xsl_warehouse_area:delete', '1', 3.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` = '1900000000000000553'); + +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 '1900000000000000554', '1900000000000000550', '批量删除', NULL, NULL, 0, NULL, NULL, 2, 'xslmes:mes_xsl_warehouse_area:deleteBatch', '1', 4.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` = '1900000000000000554'); + +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 '1900000000000000555', '1900000000000000550', '导出', NULL, NULL, 0, NULL, NULL, 2, 'xslmes:mes_xsl_warehouse_area:exportXls', '1', 5.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` = '1900000000000000555'); + +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 '1900000000000000556', '1900000000000000550', '导入', NULL, NULL, 0, NULL, NULL, 2, 'xslmes:mes_xsl_warehouse_area:importExcel', '1', 6.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` = '1900000000000000556'); + +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 '1900000000000000557', '1900000000000000550', '启用/停用', NULL, NULL, 0, NULL, NULL, 2, 'xslmes:mes_xsl_warehouse_area:updateStatus', '1', 7.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` = '1900000000000000557'); + +-- ===================== 3. 角色菜单授权(admin 角色)===================== +INSERT INTO `sys_role_permission` (`id`, `role_id`, `permission_id`, `data_rule_ids`, `operate_date`, `operate_ip`) +SELECT REPLACE(UUID(), '-', ''), r.id, '1900000000000000550', 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` = '1900000000000000550'); + +INSERT INTO `sys_role_permission` (`id`, `role_id`, `permission_id`, `data_rule_ids`, `operate_date`, `operate_ip`) +SELECT REPLACE(UUID(), '-', ''), r.id, '1900000000000000551', 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` = '1900000000000000551'); + +INSERT INTO `sys_role_permission` (`id`, `role_id`, `permission_id`, `data_rule_ids`, `operate_date`, `operate_ip`) +SELECT REPLACE(UUID(), '-', ''), r.id, '1900000000000000552', 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` = '1900000000000000552'); + +INSERT INTO `sys_role_permission` (`id`, `role_id`, `permission_id`, `data_rule_ids`, `operate_date`, `operate_ip`) +SELECT REPLACE(UUID(), '-', ''), r.id, '1900000000000000553', 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` = '1900000000000000553'); + +INSERT INTO `sys_role_permission` (`id`, `role_id`, `permission_id`, `data_rule_ids`, `operate_date`, `operate_ip`) +SELECT REPLACE(UUID(), '-', ''), r.id, '1900000000000000554', 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` = '1900000000000000554'); + +INSERT INTO `sys_role_permission` (`id`, `role_id`, `permission_id`, `data_rule_ids`, `operate_date`, `operate_ip`) +SELECT REPLACE(UUID(), '-', ''), r.id, '1900000000000000555', 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` = '1900000000000000555'); + +INSERT INTO `sys_role_permission` (`id`, `role_id`, `permission_id`, `data_rule_ids`, `operate_date`, `operate_ip`) +SELECT REPLACE(UUID(), '-', ''), r.id, '1900000000000000556', 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` = '1900000000000000556'); + +INSERT INTO `sys_role_permission` (`id`, `role_id`, `permission_id`, `data_rule_ids`, `operate_date`, `operate_ip`) +SELECT REPLACE(UUID(), '-', ''), r.id, '1900000000000000557', 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` = '1900000000000000557'); diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_46__mes_xsl_raw_material_entry_portion_warehouse_locations.sql b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_46__mes_xsl_raw_material_entry_portion_warehouse_locations.sql new file mode 100644 index 0000000..8fa7b95 --- /dev/null +++ b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_46__mes_xsl_raw_material_entry_portion_warehouse_locations.sql @@ -0,0 +1,22 @@ +-- ============================================================ +-- 原料入场记录表:新增「拆码明细库位」拼接字段 portion_warehouse_locations +-- 背景:桌面端「拆码明细」每行均可独立选择库位,需要把多行的库位 +-- 与「总份数 / 每份总重(KG) / 每份包数」一样以 "/" 分隔拼接持久化, +-- 便于生成原材料卡片之后再次打开入场记录时正确回填每行库位。 +-- 字段:portion_warehouse_locations VARCHAR(500) DEFAULT NULL +-- 形如:"1F-A01/1F-A02/2F-B05/" +-- 注意:原 warehouse_location 字段保留,作为「基础资料」区的整票级单值。 +-- 幂等:列已存在则跳过 ADD。 +-- ============================================================ + +SET @col_exists := ( + SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = 'mes_xsl_raw_material_entry' + AND COLUMN_NAME = 'portion_warehouse_locations' +); +SET @ddl := IF(@col_exists > 0, + 'SELECT 1', + 'ALTER TABLE `mes_xsl_raw_material_entry` ADD COLUMN `portion_warehouse_locations` varchar(500) DEFAULT NULL COMMENT ''拆码明细库位拼接(以 / 分隔,末尾带 /,如 1F-A01/1F-A02/)'' AFTER `warehouse_location`' +); +PREPARE s FROM @ddl; EXECUTE s; DEALLOCATE PREPARE s; diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_47__split_detail_id.sql b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_47__split_detail_id.sql new file mode 100644 index 0000000..017b21e --- /dev/null +++ b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_47__split_detail_id.sql @@ -0,0 +1,49 @@ +-- ============================================================ +-- 拆码明细 ID 关联: +-- 1) mes_xsl_raw_material_card.split_detail_id VARCHAR(64) — 关联到拆码明细行(每行一个 GUID) +-- 2) mes_xsl_raw_material_entry.portion_detail_ids VARCHAR(800) — 拆码明细每行的 GUID 拼接(以 / 分隔,末尾带 /) +-- +-- 用途: +-- - 「生成原材料卡片」时把当前明细行的 ID 写入卡片 split_detail_id; +-- - 「重新拆码」时按入场记录的 portion_detail_ids 反查并清除所有关联卡片。 +-- 幂等:列已存在则跳过 ADD。 +-- ============================================================ + +-- 1) mes_xsl_raw_material_card.split_detail_id +SET @col_exists := ( + SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = 'mes_xsl_raw_material_card' + AND COLUMN_NAME = 'split_detail_id' +); +SET @ddl := IF(@col_exists > 0, + 'SELECT 1', + 'ALTER TABLE `mes_xsl_raw_material_card` ADD COLUMN `split_detail_id` varchar(64) DEFAULT NULL COMMENT ''关联的拆码明细行 ID(GUID,可空,便于按入场记录批删)'' AFTER `barcode`' +); +PREPARE s FROM @ddl; EXECUTE s; DEALLOCATE PREPARE s; + +-- 1.1) 为 split_detail_id 加普通索引(重新拆码批删按此字段 IN 过滤) +SET @idx_exists := ( + SELECT COUNT(*) FROM information_schema.STATISTICS + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = 'mes_xsl_raw_material_card' + AND INDEX_NAME = 'idx_card_split_detail_id' +); +SET @ddl := IF(@idx_exists > 0, + 'SELECT 1', + 'ALTER TABLE `mes_xsl_raw_material_card` ADD INDEX `idx_card_split_detail_id` (`split_detail_id`)' +); +PREPARE s FROM @ddl; EXECUTE s; DEALLOCATE PREPARE s; + +-- 2) mes_xsl_raw_material_entry.portion_detail_ids +SET @col_exists := ( + SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = 'mes_xsl_raw_material_entry' + AND COLUMN_NAME = 'portion_detail_ids' +); +SET @ddl := IF(@col_exists > 0, + 'SELECT 1', + 'ALTER TABLE `mes_xsl_raw_material_entry` ADD COLUMN `portion_detail_ids` varchar(800) DEFAULT NULL COMMENT ''拆码明细每行的 GUID 拼接(以 / 分隔,末尾带 /,与 total_portions 等同行对齐)'' AFTER `portion_warehouse_locations`' +); +PREPARE s FROM @ddl; EXECUTE s; DEALLOCATE PREPARE s; diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_48__mes_xsl_raw_material_entry_portion_card_flags.sql b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_48__mes_xsl_raw_material_entry_portion_card_flags.sql new file mode 100644 index 0000000..9949aa0 --- /dev/null +++ b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_48__mes_xsl_raw_material_entry_portion_card_flags.sql @@ -0,0 +1,24 @@ +-- ============================================================ +-- 原料入场记录表:新增「行级 已生成卡片 标志」拼接字段 portion_card_flags +-- 背景:之前桌面端用 entry.print_flag(整票) 推断每行的 HasCard, +-- 导致已打印记录上新增的明细行(保存后未生成卡片)也被误判为「已打印」, +-- 且会绕过「未打印才允许生成」的过滤,造成重复加卡风险。 +-- 修复:把每行的 HasCard 真实状态按 / 分隔拼接持久化, +-- 桌面端「生成原材料卡片」前以本字段为唯一依据过滤。 +-- 字段:portion_card_flags VARCHAR(500) DEFAULT NULL +-- 形如:"1/1/0/" 表示该入场记录 3 条明细中前 2 行已生成卡片、第 3 行未生成。 +-- 历史数据:留空时桌面端降级用 print_flag 推断,与原行为兼容。 +-- 幂等:列已存在则跳过 ADD。 +-- ============================================================ + +SET @col_exists := ( + SELECT COUNT(*) FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = 'mes_xsl_raw_material_entry' + AND COLUMN_NAME = 'portion_card_flags' +); +SET @ddl := IF(@col_exists > 0, + 'SELECT 1', + 'ALTER TABLE `mes_xsl_raw_material_entry` ADD COLUMN `portion_card_flags` varchar(500) DEFAULT NULL COMMENT ''拆码明细行级 已生成卡片 标志拼接(以 / 分隔,1=已生成 0=未生成,末尾带 /,如 1/1/0/)'' AFTER `portion_warehouse_locations`' +); +PREPARE s FROM @ddl; EXECUTE s; DEALLOCATE PREPARE s; diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_49__mes_xsl_raw_material_entry_stock_in_perm.sql b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_49__mes_xsl_raw_material_entry_stock_in_perm.sql new file mode 100644 index 0000000..7733372 --- /dev/null +++ b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/flyway/sql/mysql/V3.9.2_49__mes_xsl_raw_material_entry_stock_in_perm.sql @@ -0,0 +1,23 @@ +-- 原料入场记录:新增「结存入库」按钮权限(parent_id=1900000000000000530,sort_no=7) + +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`) VALUES +('1900000000000000537', '1900000000000000530', '结存入库', NULL, NULL, 0, NULL, NULL, 2, 'xslmes:mes_xsl_raw_material_entry:stockIn', '1', 7.00, 0, NULL, 1, 0, 0, 0, NULL, 'admin', NOW(), 'admin', NOW(), 0, 0, '1', 0) +ON DUPLICATE KEY UPDATE + `parent_id` = VALUES(`parent_id`), + `name` = VALUES(`name`), + `menu_type` = VALUES(`menu_type`), + `perms` = VALUES(`perms`), + `perms_type` = VALUES(`perms_type`), + `sort_no` = VALUES(`sort_no`), + `del_flag` = VALUES(`del_flag`), + `status` = VALUES(`status`), + `update_by` = VALUES(`update_by`), + `update_time` = VALUES(`update_time`); + +-- 默认管理员角色授权 +INSERT INTO `sys_role_permission` (`id`, `role_id`, `permission_id`, `data_rule_ids`, `operate_date`, `operate_ip`) +SELECT REPLACE(UUID(), '-', ''), 'f6817f48af4fb3af11b9e8bf182f618b', '1900000000000000537', NULL, NOW(), '127.0.0.1' +WHERE NOT EXISTS ( + SELECT 1 FROM `sys_role_permission` + WHERE `role_id` = 'f6817f48af4fb3af11b9e8bf182f618b' AND `permission_id` = '1900000000000000537' +); diff --git a/jeecgboot-vue3/src/views/system/category/category.data.ts b/jeecgboot-vue3/src/views/system/category/category.data.ts index 31e0b5a..334560e 100644 --- a/jeecgboot-vue3/src/views/system/category/category.data.ts +++ b/jeecgboot-vue3/src/views/system/category/category.data.ts @@ -63,4 +63,14 @@ export const formSchema: FormSchema[] = [ required: true, component: 'Input', }, + { + label: '分类编码', + field: 'code', + component: 'Input', + componentProps: { + // 新增时:留空则后端按 FillRule 自动生成(如 A01.A02); + // 编辑时:保留原值,避免缺字段提交导致编码被清空。 + placeholder: '留空将按规则自动生成(如 A01.A02)', + }, + }, ]; diff --git a/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialCard/MesXslRawMaterialCard.data.ts b/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialCard/MesXslRawMaterialCard.data.ts index 2131077..b393301 100644 --- a/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialCard/MesXslRawMaterialCard.data.ts +++ b/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialCard/MesXslRawMaterialCard.data.ts @@ -7,13 +7,13 @@ export const columns: BasicColumn[] = [ title: '条码', align: 'center', dataIndex: 'barcode', - width: 160, + width: 200, }, { title: '批次号', align: 'center', dataIndex: 'batchNo', - width: 160, + width: 180, }, { title: '入场日期', diff --git a/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialCard/MesXslRawMaterialCardList.vue b/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialCard/MesXslRawMaterialCardList.vue index 024e6f9..797888d 100644 --- a/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialCard/MesXslRawMaterialCardList.vue +++ b/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialCard/MesXslRawMaterialCardList.vue @@ -123,12 +123,14 @@ } async function handlePriorityChange(record, checked: boolean) { + const newVal = checked ? '1' : '0'; + const oldVal = record.priorityPickup; + record.priorityPickup = newVal; try { - await updatePriority(record.id, checked ? '1' : '0'); - record.priorityPickup = checked ? '1' : '0'; - createMessage.success('优先出库设置已更新'); + await updatePriority(record.id, newVal); } catch { - createMessage.error('更新失败,请重试'); + record.priorityPickup = oldVal; + createMessage.error('优先出库更新失败,请重试'); } } diff --git a/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialEntry/MesXslRawMaterialEntry.api.ts b/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialEntry/MesXslRawMaterialEntry.api.ts index 7197324..9748756 100644 --- a/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialEntry/MesXslRawMaterialEntry.api.ts +++ b/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialEntry/MesXslRawMaterialEntry.api.ts @@ -9,6 +9,7 @@ enum Api { edit = '/xslmes/mesXslRawMaterialEntry/edit', deleteOne = '/xslmes/mesXslRawMaterialEntry/delete', deleteBatch = '/xslmes/mesXslRawMaterialEntry/deleteBatch', + batchStockIn = '/xslmes/mesXslRawMaterialEntry/batchStockIn', importExcel = '/xslmes/mesXslRawMaterialEntry/importExcel', exportXls = '/xslmes/mesXslRawMaterialEntry/exportXls', } @@ -39,6 +40,9 @@ export const batchDelete = (params, handleSuccess) => { }); }; +export const batchStockIn = (ids: string) => + defHttp.put({ url: Api.batchStockIn, params: { ids } }, { joinParamsToUrl: true }); + export const saveOrUpdate = (params, isUpdate) => { let url = isUpdate ? Api.edit : Api.save; return defHttp.post({ url: url, params }); diff --git a/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialEntry/MesXslRawMaterialEntry.data.ts b/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialEntry/MesXslRawMaterialEntry.data.ts index 2f1ad37..9851deb 100644 --- a/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialEntry/MesXslRawMaterialEntry.data.ts +++ b/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialEntry/MesXslRawMaterialEntry.data.ts @@ -1,8 +1,8 @@ import { BasicColumn, FormSchema } from '/@/components/Table'; export const columns: BasicColumn[] = [ - { title: '条码', align: 'center', dataIndex: 'barcode', width: 160 }, - { title: '批次号', align: 'center', dataIndex: 'batchNo', width: 140 }, + { title: '条码', align: 'center', dataIndex: 'barcode', width: 200 }, + { title: '批次号', align: 'center', dataIndex: 'batchNo', width: 180 }, { title: '入场时间', align: 'center', diff --git a/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialEntry/MesXslRawMaterialEntryList.vue b/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialEntry/MesXslRawMaterialEntryList.vue index c4979a0..90641bc 100644 --- a/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialEntry/MesXslRawMaterialEntryList.vue +++ b/jeecgboot-vue3/src/views/xslmes/mesXslRawMaterialEntry/MesXslRawMaterialEntryList.vue @@ -5,6 +5,7 @@ 新增 导出 导入 + 结存入库