list = this.selectList(wrapper);
+ if (CollUtil.isEmpty(list)) {
+ return CollUtil.newArrayList();
+ }
+ return BeanCopyUtils.copyList(list, voClass);
+ }
+
+ default > P selectVoPage(IPage page, Wrapper wrapper) {
+ return selectVoPage(page, wrapper, this.currentVoClass());
+ }
+
+ /**
+ * 分页查询VO
+ */
+ default > P selectVoPage(IPage page, Wrapper wrapper, Class voClass) {
+ IPage pageData = this.selectPage(page, wrapper);
+ IPage voPage = new Page<>(pageData.getCurrent(), pageData.getSize(), pageData.getTotal());
+ if (CollUtil.isEmpty(pageData.getRecords())) {
+ return (P) voPage;
+ }
+ voPage.setRecords(BeanCopyUtils.copyList(pageData.getRecords(), voClass));
+ return (P) voPage;
+ }
+
+}
diff --git a/api-admin/src/main/java/com/glxp/sale/admin/dao/inout/IoCodeLostMapper.java b/api-admin/src/main/java/com/glxp/sale/admin/dao/inout/IoCodeLostMapper.java
new file mode 100644
index 0000000..88f8fa0
--- /dev/null
+++ b/api-admin/src/main/java/com/glxp/sale/admin/dao/inout/IoCodeLostMapper.java
@@ -0,0 +1,14 @@
+package com.glxp.sale.admin.dao.inout;
+
+import com.glxp.sale.admin.dao.BaseMapperPlus;
+import com.glxp.sale.admin.entity.inout.IoCodeLostEntity;
+import com.glxp.sale.admin.res.inout.IoCodeLostResponse;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+@Mapper
+public interface IoCodeLostMapper extends BaseMapperPlus {
+ List selectLost(IoCodeLostEntity ioCodeLostEntity);
+}
+
diff --git a/api-admin/src/main/java/com/glxp/sale/admin/entity/inout/IoCodeLostEntity.java b/api-admin/src/main/java/com/glxp/sale/admin/entity/inout/IoCodeLostEntity.java
new file mode 100644
index 0000000..90b4ad4
--- /dev/null
+++ b/api-admin/src/main/java/com/glxp/sale/admin/entity/inout/IoCodeLostEntity.java
@@ -0,0 +1,111 @@
+package com.glxp.sale.admin.entity.inout;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * 扫码缺失字段信息补齐表
+ */
+@Data
+@TableName(value = "io_code_lost")
+public class IoCodeLostEntity {
+ @TableId(value = "id", type = IdType.AUTO)
+ private Integer id;
+
+ /**
+ * UDI码
+ */
+ @TableField(value = "code")
+ private String code;
+
+ /**
+ * 批次号
+ */
+ @TableField(value = "batchNo")
+ private String batchNo;
+
+ /**
+ * 生产日期
+ */
+ @TableField(value = "produceDate")
+ private String produceDate;
+
+ /**
+ * 失效日期
+ */
+ @TableField(value = "expireDate")
+ private String expireDate;
+
+ /**
+ * 序列号
+ */
+ @TableField(value = "serialNo")
+ private String serialNo;
+
+ /**
+ * 供应商
+ */
+ @TableField(value = "supId")
+ private String supId;
+
+ /**
+ * 创建时间
+ */
+ @TableField(value = "createTime")
+ private Date createTime;
+
+ /**
+ * 更新时间
+ */
+ @TableField(value = "updateTime")
+ private Date updateTime;
+
+ /**
+ * 备注
+ */
+ @TableField(value = "remark")
+ private String remark;
+
+
+ @TableField(value = "nameCode")
+ private String nameCode;
+
+ @TableField(exist = false)
+ private String cpmctymc;
+
+ @TableField(exist = false)
+ private String ggxh;
+
+ @TableField(exist = false)
+ private String startTime;
+
+ @TableField(exist = false)
+ private String endTime;
+
+
+
+ public static final String COL_ID = "id";
+
+ public static final String COL_CODE = "code";
+
+ public static final String COL_BATCHNO = "batchNo";
+
+ public static final String COL_PRODUCEDATE = "produceDate";
+
+ public static final String COL_EXPIREDATE = "expireDate";
+
+ public static final String COL_SERIALNO = "serialNo";
+
+ public static final String COL_SUPID = "supId";
+
+ public static final String COL_CREATETIME = "createTime";
+
+ public static final String COL_UPDATETIME = "updateTime";
+
+ public static final String COL_REMARK = "remark";
+}
diff --git a/api-admin/src/main/java/com/glxp/sale/admin/res/inout/IoCodeLostResponse.java b/api-admin/src/main/java/com/glxp/sale/admin/res/inout/IoCodeLostResponse.java
new file mode 100644
index 0000000..68c6927
--- /dev/null
+++ b/api-admin/src/main/java/com/glxp/sale/admin/res/inout/IoCodeLostResponse.java
@@ -0,0 +1,69 @@
+package com.glxp.sale.admin.res.inout;
+
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * @author : zhangsan
+ * @date : 2023/3/22 11:08
+ * @modyified By :
+ */
+@Data
+public class IoCodeLostResponse {
+
+ private Integer id;
+
+ private String code;
+
+
+ private String batchNo;
+
+
+ private String produceDate;
+
+
+ private String expireDate;
+
+
+ private String serialNo;
+
+
+ private String supId;
+
+
+ private Date createTime;
+
+
+ private Date updateTime;
+
+
+ private String remark;
+
+ //产品名称
+ private String cpmctymc;
+ //规格型号
+ private String ggxh;
+
+ public static final String COL_ID = "id";
+
+ public static final String COL_CODE = "code";
+
+ public static final String COL_BATCHNO = "batchNo";
+
+ public static final String COL_PRODUCEDATE = "produceDate";
+
+ public static final String COL_EXPIREDATE = "expireDate";
+
+ public static final String COL_SERIALNO = "serialNo";
+
+ public static final String COL_SUPID = "supId";
+
+ public static final String COL_CREATETIME = "createTime";
+
+ public static final String COL_UPDATETIME = "updateTime";
+
+ public static final String COL_REMARK = "remark";
+
+
+}
diff --git a/api-admin/src/main/java/com/glxp/sale/admin/service/inout/IoCodeLostService.java b/api-admin/src/main/java/com/glxp/sale/admin/service/inout/IoCodeLostService.java
new file mode 100644
index 0000000..4d1d5f3
--- /dev/null
+++ b/api-admin/src/main/java/com/glxp/sale/admin/service/inout/IoCodeLostService.java
@@ -0,0 +1,23 @@
+package com.glxp.sale.admin.service.inout;
+
+
+import com.glxp.sale.admin.entity.inout.IoCodeLostEntity;
+import com.glxp.sale.admin.res.inout.IoCodeLostResponse;
+
+import java.util.List;
+
+public interface IoCodeLostService {
+
+ List selectLost(IoCodeLostEntity ioCodeLostEntity);
+
+
+ IoCodeLostEntity findByCode(String code);
+
+ int insert(IoCodeLostEntity ioCodeLostEntity);
+
+ boolean insertOrUpdate(IoCodeLostEntity ioCodeLostEntity);
+
+ int deleteByCode(String code);
+
+ int update(IoCodeLostEntity ioCodeLostEntity);
+}
diff --git a/api-admin/src/main/java/com/glxp/sale/admin/service/inout/impl/IoCodeLostServiceImpl.java b/api-admin/src/main/java/com/glxp/sale/admin/service/inout/impl/IoCodeLostServiceImpl.java
new file mode 100644
index 0000000..aea8fee
--- /dev/null
+++ b/api-admin/src/main/java/com/glxp/sale/admin/service/inout/impl/IoCodeLostServiceImpl.java
@@ -0,0 +1,51 @@
+package com.glxp.sale.admin.service.inout.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.glxp.sale.admin.dao.inout.IoCodeLostMapper;
+import com.glxp.sale.admin.entity.inout.IoCodeLostEntity;
+import com.glxp.sale.admin.res.inout.IoCodeLostResponse;
+import com.glxp.sale.admin.service.inout.IoCodeLostService;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+@Service
+public class IoCodeLostServiceImpl implements IoCodeLostService {
+
+ @Resource
+ IoCodeLostMapper codeLostEntityMapper;
+
+
+ @Override
+ public List selectLost(IoCodeLostEntity ioCodeLostEntity) {
+ return codeLostEntityMapper.selectLost(ioCodeLostEntity);
+ }
+
+ @Override
+ public IoCodeLostEntity findByCode(String code) {
+
+ return codeLostEntityMapper.selectOne(new QueryWrapper().eq("code", code));
+ }
+
+ @Override
+ public int insert(IoCodeLostEntity ioCodeLostEntity) {
+
+ return codeLostEntityMapper.insert(ioCodeLostEntity);
+ }
+
+ @Override
+ public boolean insertOrUpdate(IoCodeLostEntity ioCodeLostEntity) {
+ return codeLostEntityMapper.insertOrUpdate(ioCodeLostEntity);
+ }
+
+ @Override
+ public int deleteByCode(String code) {
+ return codeLostEntityMapper.delete(new QueryWrapper().eq("code", code));
+ }
+
+ @Override
+ public int update(IoCodeLostEntity ioCodeLostEntity) {
+ return codeLostEntityMapper.updateById(ioCodeLostEntity);
+ }
+}
diff --git a/api-admin/src/main/java/com/glxp/sale/admin/thread/IoTransInoutService.java b/api-admin/src/main/java/com/glxp/sale/admin/thread/IoTransInoutService.java
index f9c239e..ae43b81 100644
--- a/api-admin/src/main/java/com/glxp/sale/admin/thread/IoTransInoutService.java
+++ b/api-admin/src/main/java/com/glxp/sale/admin/thread/IoTransInoutService.java
@@ -675,6 +675,7 @@ public class IoTransInoutService {
orderEntity = orderService.findById(orderEntity.getId());
if (orderEntity.getContrastStatus() != ConstantStatus.ORDER_CHECK_FAIL) {
orderService.updateOrderStatus(orderEntity.getId(), ConstantStatus.ORDER_STATUS_CHECK);
+ genLostCode(orderEntity.getId());
}
}
}
@@ -696,6 +697,7 @@ public class IoTransInoutService {
orderService.updateOrder(orderEntity);
printOrder(orderEntity.getId());
}
+ genLostCode(orderEntity.getId());
}
public String checkOriginExitSup(BussinessTypeEntity bussinessTypeEntity, WarehouseEntity warehouseEntity) {
@@ -1049,6 +1051,47 @@ public class IoTransInoutService {
return stockOrderEntity;
}
+
+ @Resource
+ IoCodeLostService codeLostService;
+
+ @Async
+ public void genLostCode(String orderId) {
+ List ioCodeEntities = warehouseService.findByReceiptId(orderId);
+ for (WarehouseEntity codeEntity : ioCodeEntities) {
+ UdiEntity udiEntity = FilterUdiUtils.getUdi(codeEntity.getCode());
+ IoCodeLostEntity codeLostEntity = codeLostService.findByCode(codeEntity.getCode());
+ if (codeLostEntity == null)
+ codeLostEntity = new IoCodeLostEntity();
+
+ //校验是否写入缺失表
+ boolean isTrue = false;
+ if (udiEntity != null) {
+ if (!StrUtil.trimToEmpty(codeEntity.getBatchNo()).equals(StrUtil.trimToEmpty(udiEntity.getBatchNo()))) {
+ if (StrUtil.isNotEmpty(codeEntity.getBatchNo())) {
+ codeLostEntity.setBatchNo(codeEntity.getBatchNo());
+ isTrue = true;
+ }
+ }
+ if (!StrUtil.trimToEmpty(codeEntity.getProduceDate()).equals(StrUtil.trimToEmpty(udiEntity.getProduceDate()))) {
+ if (StrUtil.isNotEmpty(codeEntity.getProduceDate())) {
+ codeLostEntity.setProduceDate(codeEntity.getProduceDate());
+ isTrue = true;
+ }
+ }
+ if (!StrUtil.trimToEmpty(codeEntity.getExpireDate()).equals(StrUtil.trimToEmpty(udiEntity.getExpireDate()))) {
+ if (StrUtil.isNotEmpty(codeEntity.getExpireDate())) {
+ codeLostEntity.setExpireDate(codeEntity.getExpireDate());
+ isTrue = true;
+ }
+ }
+ if (isTrue)
+ codeLostService.insertOrUpdate(codeLostEntity);
+ }
+
+ }
+ }
+
}
diff --git a/api-admin/src/main/java/com/glxp/sale/admin/util/BeanCopyUtils.java b/api-admin/src/main/java/com/glxp/sale/admin/util/BeanCopyUtils.java
new file mode 100644
index 0000000..6bd5b0b
--- /dev/null
+++ b/api-admin/src/main/java/com/glxp/sale/admin/util/BeanCopyUtils.java
@@ -0,0 +1,184 @@
+package com.glxp.sale.admin.util;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.lang.SimpleCache;
+import cn.hutool.core.map.MapUtil;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.ReflectUtil;
+import cn.hutool.core.util.StrUtil;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.springframework.cglib.beans.BeanCopier;
+import org.springframework.cglib.beans.BeanMap;
+import org.springframework.cglib.core.Converter;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * bean深拷贝工具(基于 cglib 性能优异)
+ *
+ * 重点 cglib 不支持 拷贝到链式对象
+ * 例如: 源对象 拷贝到 目标(链式对象)
+ * 请区分好`浅拷贝`和`深拷贝`再做使用
+ *
+ * @author Lion Li
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class BeanCopyUtils {
+
+ /**
+ * 单对象基于class创建拷贝
+ *
+ * @param source 数据来源实体
+ * @param desc 描述对象 转换后的对象
+ * @return desc
+ */
+ public static V copy(T source, Class desc) {
+ if (ObjectUtil.isNull(source)) {
+ return null;
+ }
+ if (ObjectUtil.isNull(desc)) {
+ return null;
+ }
+ final V target = ReflectUtil.newInstanceIfPossible(desc);
+ return copy(source, target);
+ }
+
+ /**
+ * 单对象基于对象创建拷贝
+ *
+ * @param source 数据来源实体
+ * @param desc 转换后的对象
+ * @return desc
+ */
+ public static V copy(T source, V desc) {
+ if (ObjectUtil.isNull(source)) {
+ return null;
+ }
+ if (ObjectUtil.isNull(desc)) {
+ return null;
+ }
+ BeanCopier beanCopier = BeanCopierCache.INSTANCE.get(source.getClass(), desc.getClass(), null);
+ beanCopier.copy(source, desc, null);
+ return desc;
+ }
+
+ /**
+ * 列表对象基于class创建拷贝
+ *
+ * @param sourceList 数据来源实体列表
+ * @param desc 描述对象 转换后的对象
+ * @return desc
+ */
+ public static List copyList(List sourceList, Class desc) {
+ if (ObjectUtil.isNull(sourceList)) {
+ return null;
+ }
+ if (CollUtil.isEmpty(sourceList)) {
+ return CollUtil.newArrayList();
+ }
+ return StreamUtils.toList(sourceList, source -> {
+ V target = ReflectUtil.newInstanceIfPossible(desc);
+ copy(source, target);
+ return target;
+ });
+ }
+
+ /**
+ * bean拷贝到map
+ *
+ * @param bean 数据来源实体
+ * @return map对象
+ */
+ @SuppressWarnings("unchecked")
+ public static Map copyToMap(T bean) {
+ if (ObjectUtil.isNull(bean)) {
+ return null;
+ }
+ return BeanMap.create(bean);
+ }
+
+ /**
+ * map拷贝到bean
+ *
+ * @param map 数据来源
+ * @param beanClass bean类
+ * @return bean对象
+ */
+ public static T mapToBean(Map map, Class beanClass) {
+ if (MapUtil.isEmpty(map)) {
+ return null;
+ }
+ if (ObjectUtil.isNull(beanClass)) {
+ return null;
+ }
+ T bean = ReflectUtil.newInstanceIfPossible(beanClass);
+ return mapToBean(map, bean);
+ }
+
+ /**
+ * map拷贝到bean
+ *
+ * @param map 数据来源
+ * @param bean bean对象
+ * @return bean对象
+ */
+ public static T mapToBean(Map map, T bean) {
+ if (MapUtil.isEmpty(map)) {
+ return null;
+ }
+ if (ObjectUtil.isNull(bean)) {
+ return null;
+ }
+ BeanMap.create(bean).putAll(map);
+ return bean;
+ }
+
+ /**
+ * BeanCopier属性缓存
+ * 缓存用于防止多次反射造成的性能问题
+ *
+ * @author Looly
+ * @since 5.4.1
+ */
+ public enum BeanCopierCache {
+ /**
+ * BeanCopier属性缓存单例
+ */
+ INSTANCE;
+
+ private final SimpleCache cache = new SimpleCache<>();
+
+ /**
+ * 获得类与转换器生成的key在{@link BeanCopier}的Map中对应的元素
+ *
+ * @param srcClass 源Bean的类
+ * @param targetClass 目标Bean的类
+ * @param converter 转换器
+ * @return Map中对应的BeanCopier
+ */
+ public BeanCopier get(Class> srcClass, Class> targetClass, Converter converter) {
+ final String key = genKey(srcClass, targetClass, converter);
+ return cache.get(key, () -> BeanCopier.create(srcClass, targetClass, converter != null));
+ }
+
+ /**
+ * 获得类与转换器生成的key
+ *
+ * @param srcClass 源Bean的类
+ * @param targetClass 目标Bean的类
+ * @param converter 转换器
+ * @return 属性名和Map映射的key
+ */
+ private String genKey(Class> srcClass, Class> targetClass, Converter converter) {
+ final StringBuilder key = StrUtil.builder()
+ .append(srcClass.getName()).append('#').append(targetClass.getName());
+ if(null != converter){
+ key.append('#').append(converter.getClass().getName());
+ }
+ return key.toString();
+ }
+ }
+
+}
diff --git a/api-admin/src/main/java/com/glxp/sale/admin/util/StreamUtils.java b/api-admin/src/main/java/com/glxp/sale/admin/util/StreamUtils.java
new file mode 100644
index 0000000..acb2601
--- /dev/null
+++ b/api-admin/src/main/java/com/glxp/sale/admin/util/StreamUtils.java
@@ -0,0 +1,247 @@
+package com.glxp.sale.admin.util;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.map.MapUtil;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.*;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class StreamUtils {
+
+ /**
+ * 将collection过滤
+ *
+ * @param collection 需要转化的集合
+ * @param function 过滤方法
+ * @return 过滤后的list
+ */
+ public static List filter(Collection collection, Predicate function) {
+ if (CollUtil.isEmpty(collection)) {
+ return CollUtil.newArrayList();
+ }
+ return collection.stream().filter(function).collect(Collectors.toList());
+ }
+
+ /**
+ * 将collection拼接
+ *
+ * @param collection 需要转化的集合
+ * @param function 拼接方法
+ * @return 拼接后的list
+ */
+ public static String join(Collection collection, Function function) {
+ return join(collection, function, ",");
+ }
+
+ /**
+ * 将collection拼接
+ *
+ * @param collection 需要转化的集合
+ * @param function 拼接方法
+ * @param delimiter 拼接符
+ * @return 拼接后的list
+ */
+ public static String join(Collection collection, Function function, CharSequence delimiter) {
+ if (CollUtil.isEmpty(collection)) {
+ return StringUtils.EMPTY;
+ }
+ return collection.stream().map(function).filter(Objects::nonNull).collect(Collectors.joining(delimiter));
+ }
+
+ /**
+ * 将collection排序
+ *
+ * @param collection 需要转化的集合
+ * @param comparing 排序方法
+ * @return 排序后的list
+ */
+ public static List sorted(Collection collection, Comparator comparing) {
+ if (CollUtil.isEmpty(collection)) {
+ return CollUtil.newArrayList();
+ }
+ return collection.stream().sorted(comparing).collect(Collectors.toList());
+ }
+
+ /**
+ * 将collection转化为类型不变的map
+ * {@code Collection ----> Map}
+ *
+ * @param collection 需要转化的集合
+ * @param key V类型转化为K类型的lambda方法
+ * @param collection中的泛型
+ * @param map中的key类型
+ * @return 转化后的map
+ */
+ public static Map toIdentityMap(Collection collection, Function key) {
+ if (CollUtil.isEmpty(collection)) {
+ return MapUtil.newHashMap();
+ }
+ return collection.stream().collect(Collectors.toMap(key, Function.identity(), (l, r) -> l));
+ }
+
+ /**
+ * 将Collection转化为map(value类型与collection的泛型不同)
+ * {@code Collection -----> Map }
+ *
+ * @param collection 需要转化的集合
+ * @param key E类型转化为K类型的lambda方法
+ * @param value E类型转化为V类型的lambda方法
+ * @param collection中的泛型
+ * @param map中的key类型
+ * @param map中的value类型
+ * @return 转化后的map
+ */
+ public static Map toMap(Collection collection, Function key, Function value) {
+ if (CollUtil.isEmpty(collection)) {
+ return MapUtil.newHashMap();
+ }
+ return collection.stream().collect(Collectors.toMap(key, value, (l, r) -> l));
+ }
+
+ /**
+ * 将collection按照规则(比如有相同的班级id)分类成map
+ * {@code Collection -------> Map> }
+ *
+ * @param collection 需要分类的集合
+ * @param key 分类的规则
+ * @param collection中的泛型
+ * @param map中的key类型
+ * @return 分类后的map
+ */
+ public static Map> groupByKey(Collection collection, Function key) {
+ if (CollUtil.isEmpty(collection)) {
+ return MapUtil.newHashMap();
+ }
+ return collection
+ .stream()
+ .collect(Collectors.groupingBy(key, LinkedHashMap::new, Collectors.toList()));
+ }
+
+ /**
+ * 将collection按照两个规则(比如有相同的年级id,班级id)分类成双层map
+ * {@code Collection ---> Map>> }
+ *
+ * @param collection 需要分类的集合
+ * @param key1 第一个分类的规则
+ * @param key2 第二个分类的规则
+ * @param 集合元素类型
+ * @param 第一个map中的key类型
+ * @param 第二个map中的key类型
+ * @return 分类后的map
+ */
+ public static Map>> groupBy2Key(Collection collection, Function key1, Function key2) {
+ if (CollUtil.isEmpty(collection)) {
+ return MapUtil.newHashMap();
+ }
+ return collection
+ .stream()
+ .collect(Collectors.groupingBy(key1, LinkedHashMap::new, Collectors.groupingBy(key2, LinkedHashMap::new, Collectors.toList())));
+ }
+
+ /**
+ * 将collection按照两个规则(比如有相同的年级id,班级id)分类成双层map
+ * {@code Collection ---> Map> }
+ *
+ * @param collection 需要分类的集合
+ * @param key1 第一个分类的规则
+ * @param key2 第二个分类的规则
+ * @param 第一个map中的key类型
+ * @param 第二个map中的key类型
+ * @param collection中的泛型
+ * @return 分类后的map
+ */
+ public static Map> group2Map(Collection collection, Function key1, Function key2) {
+ if (CollUtil.isEmpty(collection) || key1 == null || key2 == null) {
+ return MapUtil.newHashMap();
+ }
+ return collection
+ .stream()
+ .collect(Collectors.groupingBy(key1, LinkedHashMap::new, Collectors.toMap(key2, Function.identity(), (l, r) -> l)));
+ }
+
+ /**
+ * 将collection转化为List集合,但是两者的泛型不同
+ * {@code Collection ------> List }
+ *
+ * @param collection 需要转化的集合
+ * @param function collection中的泛型转化为list泛型的lambda表达式
+ * @param collection中的泛型
+ * @param List中的泛型
+ * @return 转化后的list
+ */
+ public static List toList(Collection collection, Function function) {
+ if (CollUtil.isEmpty(collection)) {
+ return CollUtil.newArrayList();
+ }
+ return collection
+ .stream()
+ .map(function)
+ .filter(Objects::nonNull)
+ .collect(Collectors.toList());
+ }
+
+ /**
+ * 将collection转化为Set集合,但是两者的泛型不同
+ * {@code Collection ------> Set }
+ *
+ * @param collection 需要转化的集合
+ * @param function collection中的泛型转化为set泛型的lambda表达式
+ * @param collection中的泛型
+ * @param Set中的泛型
+ * @return 转化后的Set
+ */
+ public static Set toSet(Collection collection, Function function) {
+ if (CollUtil.isEmpty(collection) || function == null) {
+ return CollUtil.newHashSet();
+ }
+ return collection
+ .stream()
+ .map(function)
+ .filter(Objects::nonNull)
+ .collect(Collectors.toSet());
+ }
+
+
+ /**
+ * 合并两个相同key类型的map
+ *
+ * @param map1 第一个需要合并的 map
+ * @param map2 第二个需要合并的 map
+ * @param merge 合并的lambda,将key value1 value2合并成最终的类型,注意value可能为空的情况
+ * @param map中的key类型
+ * @param 第一个 map的value类型
+ * @param 第二个 map的value类型
+ * @param 最终map的value类型
+ * @return 合并后的map
+ */
+ public static Map merge(Map map1, Map map2, BiFunction merge) {
+ if (MapUtil.isEmpty(map1) && MapUtil.isEmpty(map2)) {
+ return MapUtil.newHashMap();
+ } else if (MapUtil.isEmpty(map1)) {
+ map1 = MapUtil.newHashMap();
+ } else if (MapUtil.isEmpty(map2)) {
+ map2 = MapUtil.newHashMap();
+ }
+ Set key = new HashSet<>();
+ key.addAll(map1.keySet());
+ key.addAll(map2.keySet());
+ Map map = new HashMap<>();
+ for (K t : key) {
+ X x = map1.get(t);
+ Y y = map2.get(t);
+ V z = merge.apply(x, y);
+ if (z != null) {
+ map.put(t, z);
+ }
+ }
+ return map;
+ }
+
+}
diff --git a/api-admin/src/main/resources/application-dev.properties b/api-admin/src/main/resources/application-dev.properties
index 4c84389..d06debe 100644
--- a/api-admin/src/main/resources/application-dev.properties
+++ b/api-admin/src/main/resources/application-dev.properties
@@ -1,7 +1,7 @@
# \u751F\u4EA7\u73AF\u5883
server.port=9996
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
-spring.datasource.jdbc-url=jdbc:mysql://127.0.0.1:3306/spms_ph?allowMultiQueries=true&serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
+spring.datasource.jdbc-url=jdbc:mysql://127.0.0.1:3306/spms_yxz?allowMultiQueries=true&serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.hikari.connection-timeout=60000
diff --git a/api-admin/src/main/resources/mybatis/mapper/inout/IoCodeLostMapper.xml b/api-admin/src/main/resources/mybatis/mapper/inout/IoCodeLostMapper.xml
new file mode 100644
index 0000000..e6cb92f
--- /dev/null
+++ b/api-admin/src/main/resources/mybatis/mapper/inout/IoCodeLostMapper.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+