diff --git a/ruoyi-oa/src/main/java/com/ruoyi/oa/controller/SysOaWarehouseController.java b/ruoyi-oa/src/main/java/com/ruoyi/oa/controller/SysOaWarehouseController.java index adbe18e..8cc5e52 100644 --- a/ruoyi-oa/src/main/java/com/ruoyi/oa/controller/SysOaWarehouseController.java +++ b/ruoyi-oa/src/main/java/com/ruoyi/oa/controller/SysOaWarehouseController.java @@ -183,6 +183,8 @@ public class SysOaWarehouseController extends BaseController { }); sysOaWarehouseMaster.setWarehouseList(list); sysOaWarehouseMaster.setMasterNum(UUID.randomUUID().toString()); + // 导入入口跳过"必须关联采购需求"校验,后续可在采购需求处手动关联 + sysOaWarehouseMaster.setSkipRequirementCheck(true); iSysOaWarehouseMasterService.insertByBo(sysOaWarehouseMaster); return R.ok(result.getAnalysis()); } diff --git a/ruoyi-oa/src/main/java/com/ruoyi/oa/domain/bo/SysOaWarehouseMasterBo.java b/ruoyi-oa/src/main/java/com/ruoyi/oa/domain/bo/SysOaWarehouseMasterBo.java index 39e0059..4075b69 100644 --- a/ruoyi-oa/src/main/java/com/ruoyi/oa/domain/bo/SysOaWarehouseMasterBo.java +++ b/ruoyi-oa/src/main/java/com/ruoyi/oa/domain/bo/SysOaWarehouseMasterBo.java @@ -83,6 +83,11 @@ public class SysOaWarehouseMasterBo extends BaseEntity { private Long requirementId; + /** + * 导入场景跳过"必须关联采购需求"校验(仅 import 入口传 true) + */ + private transient Boolean skipRequirementCheck; + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date startTime; diff --git a/ruoyi-oa/src/main/java/com/ruoyi/oa/im/ImCredentialsController.java b/ruoyi-oa/src/main/java/com/ruoyi/oa/im/ImCredentialsController.java index 5d5d157..658643b 100644 --- a/ruoyi-oa/src/main/java/com/ruoyi/oa/im/ImCredentialsController.java +++ b/ruoyi-oa/src/main/java/com/ruoyi/oa/im/ImCredentialsController.java @@ -9,11 +9,14 @@ import com.ruoyi.system.mapper.SysUserMapper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.HashMap; +import java.util.List; import java.util.Map; /** @@ -64,6 +67,49 @@ public class ImCredentialsController extends BaseController { return R.ok(data); } + /** + * 给指定 OA 用户在 OpenIM 注册账号(如未注册)。 + * 用于发消息前确保对方 imUserId 存在 —— 解决 OpenIM "RecordNotFoundError 1004"。 + *

支持单个或批量,幂等。 + */ + @PostMapping("/ensure") + public R> ensureTargets(@RequestBody Map body) { + if (LoginHelper.getUserId() == null) return R.fail("未登录"); + @SuppressWarnings("unchecked") + List raw = (List) body.get("userIds"); + if (raw == null || raw.isEmpty()) return R.fail("userIds 不能为空"); + + int ok = 0, fail = 0; + Map results = new HashMap<>(); + for (Object o : raw) { + Long uid; + try { + uid = Long.parseLong(o.toString()); + } catch (Exception e) { + fail++; + continue; + } + ImBind exist = bindMapper.selectById(uid); + if (exist != null && exist.getImUserId() != null && !exist.getImUserId().isEmpty()) { + ok++; + results.put(uid.toString(), exist.getImUserId()); + continue; + } + ImBind bind = ensureBind(uid); + if (bind != null) { + ok++; + results.put(uid.toString(), bind.getImUserId()); + } else { + fail++; + } + } + Map data = new HashMap<>(); + data.put("ok", ok); + data.put("fail", fail); + data.put("bindings", results); + return R.ok(data); + } + /** 给指定 OA userId 在 OpenIM 主 API 直接注册一个账号并落 bind 表 */ private ImBind ensureBind(Long oaUserId) { SysUser u = userMapper.selectById(oaUserId); diff --git a/ruoyi-oa/src/main/java/com/ruoyi/oa/service/impl/SysOaWarehouseMasterServiceImpl.java b/ruoyi-oa/src/main/java/com/ruoyi/oa/service/impl/SysOaWarehouseMasterServiceImpl.java index ae43a6e..73666fc 100644 --- a/ruoyi-oa/src/main/java/com/ruoyi/oa/service/impl/SysOaWarehouseMasterServiceImpl.java +++ b/ruoyi-oa/src/main/java/com/ruoyi/oa/service/impl/SysOaWarehouseMasterServiceImpl.java @@ -171,9 +171,11 @@ public class SysOaWarehouseMasterServiceImpl implements ISysOaWarehouseMasterSer add.setRemark("办公耗材自动写入"); } - // 规则 2:入库(type=1)必须强关联采购需求(requirement_id) + // 规则 2:入库(type=1)默认必须强关联采购需求(requirement_id); + // 导入入口会显式传 skipRequirementCheck=true,单纯导入物料,后续在采购需求处手动关联 if (add.getType() != null && add.getType() == 1 - && add.getRequirementId() == null) { + && add.getRequirementId() == null + && !Boolean.TRUE.equals(bo.getSkipRequirementCheck())) { throw new RuntimeException("入库必须关联采购需求,请先选择需求"); } diff --git a/ruoyi-oa/src/main/java/com/ruoyi/oa/service/impl/SysOaWarehouseTaskServiceImpl.java b/ruoyi-oa/src/main/java/com/ruoyi/oa/service/impl/SysOaWarehouseTaskServiceImpl.java index 224685d..6af25d8 100644 --- a/ruoyi-oa/src/main/java/com/ruoyi/oa/service/impl/SysOaWarehouseTaskServiceImpl.java +++ b/ruoyi-oa/src/main/java/com/ruoyi/oa/service/impl/SysOaWarehouseTaskServiceImpl.java @@ -168,6 +168,8 @@ public class SysOaWarehouseTaskServiceImpl implements ISysOaWarehouseTaskService sysOaWarehouseMaster.setStatus(0L); sysOaWarehouseMaster.setMasterNum(UUID.randomUUID().toString()); sysOaWarehouseMaster.setSignUser(LoginHelper.getNickName()); + // 操作时间必须落库,否则前端按 signTime 排序/筛选时看不到今天提报的单 + sysOaWarehouseMaster.setSignTime(new java.util.Date()); Boolean flag = masterMapper.insert(sysOaWarehouseMaster) > 0; Long masterId = sysOaWarehouseMaster.getMasterId(); for (SysOaWarehouseTaskBo sysOaWarehouseTaskBo : boList) { diff --git a/ruoyi-ui/src/views/oa/projectOutWarehouse/components/OutWarehouseDetailTable.vue b/ruoyi-ui/src/views/oa/projectOutWarehouse/components/OutWarehouseDetailTable.vue index 177e33f..fb83f1c 100644 --- a/ruoyi-ui/src/views/oa/projectOutWarehouse/components/OutWarehouseDetailTable.vue +++ b/ruoyi-ui/src/views/oa/projectOutWarehouse/components/OutWarehouseDetailTable.vue @@ -14,11 +14,18 @@ + + +