package com.zy.asrs.service.impl; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; 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 com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.core.common.Cools; import com.core.exception.CoolException; import com.zy.asrs.entity.BasMap; import com.zy.asrs.entity.LocMast; import com.zy.asrs.mapper.BasMapMapper; import com.zy.asrs.service.BasMapService; import com.zy.asrs.service.LocMastService; import com.zy.asrs.utils.Utils; import com.zy.common.utils.RedisUtil; import com.zy.core.enums.RedisKeyType; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.Date; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @Service("basMapService") public class BasMapServiceImpl extends ServiceImpl implements BasMapService { @Autowired private LocMastService locMastService; @Autowired private RedisUtil redisUtil; @Override public BasMap selectLatestMap(Integer lev) { return this.baseMapper.selectLatestMap(lev); } @Override public boolean deleteByLev(Integer lev) { return this.baseMapper.deleteByLev(lev); } @Override public List getLevList() { return this.baseMapper.selectList(new QueryWrapper<>()).stream().map(BasMap::getLev).collect(Collectors.toList()); } @Override public IPage pageLight(Page page, QueryWrapper wrapper) { QueryWrapper queryWrapper = wrapper == null ? new QueryWrapper<>() : wrapper; queryWrapper.select("id", "create_time", "update_time", "lev", "base_row", "base_row_code", "base_bay", "base_bay_code"); return this.baseMapper.selectPage(page, queryWrapper); } @Override public BasMap selectPayloadById(Integer id) { return this.baseMapper.selectPayloadById(id); } @Override @Transactional public void saveMapPayloadInBatches(Integer lev, String data, String originData, Date updateTime) { if (lev == null || lev <= 0) { throw new CoolException("楼层不能为空"); } Date now = updateTime == null ? new Date() : updateTime; BasMap basMap = this.getOne(new QueryWrapper().select("id", "data").eq("lev", lev)); boolean existingMap = basMap != null; if (basMap == null) { basMap = insertLightMap(lev, now); } if (existingMap) { updateLastDataOnly(basMap.getId(), basMap.getData()); } updateDataOnly(basMap.getId(), data, now); updateOriginDataOnly(basMap.getId(), originData); } private BasMap insertLightMap(Integer lev, Date now) { BasMap insertMap = new BasMap(); insertMap.setLev(lev); insertMap.setCreateTime(now); insertMap.setUpdateTime(now); if (!this.save(insertMap)) { throw new CoolException("地图基础信息保存失败"); } return insertMap; } private void updateLastDataOnly(Integer id, String lastData) { UpdateWrapper updateWrapper = new UpdateWrapper<>(); updateWrapper.eq("id", id) .set("last_data", lastData); if (!this.update(updateWrapper)) { throw new CoolException("地图历史数据保存失败"); } } private void updateDataOnly(Integer id, String data, Date updateTime) { UpdateWrapper updateWrapper = new UpdateWrapper<>(); updateWrapper.eq("id", id) .set("data", data) .set("update_time", updateTime); if (!this.update(updateWrapper)) { throw new CoolException("地图运行数据保存失败"); } } private void updateOriginDataOnly(Integer id, String originData) { UpdateWrapper updateWrapper = new UpdateWrapper<>(); updateWrapper.eq("id", id) .set("origin_data", originData); if (!this.update(updateWrapper)) { throw new CoolException("地图编辑数据保存失败"); } } @Override @Transactional public int syncLocMastByMap(Integer lev) { if (lev == null || lev <= 0) { throw new CoolException("请输入有效楼层"); } List locLevList = new ArrayList<>(locMastService.getLevList()); if (Cools.isEmpty(locLevList) || !locLevList.contains(lev)) { throw new CoolException("第" + lev + "层暂无库位数据,请先初始化库位"); } List basMapList = this.list(new QueryWrapper().orderByAsc("lev")); if (Cools.isEmpty(basMapList)) { throw new CoolException("请先初始化地图"); } Map basMapByLev = new LinkedHashMap<>(); for (BasMap basMap : basMapList) { if (basMap != null && basMap.getLev() != null) { basMapByLev.put(basMap.getLev(), basMap); } } BasMap fallbackMap = basMapByLev.size() == 1 ? basMapList.get(0) : null; BasMap basMap = basMapByLev.get(lev); if (basMap == null) { basMap = fallbackMap; } if (basMap == null) { throw new CoolException("第" + lev + "层缺少地图,无法同步locType"); } List targetList = buildTargetLocMeta(basMap, lev); List currentList = new ArrayList<>(locMastService.selectLocByLev(lev)); if (targetList.size() != currentList.size()) { throw new CoolException("第" + lev + "层地图货架数(" + targetList.size() + ")与现有库位数(" + currentList.size() + ")不一致,无法同步locType"); } int updatedCount = syncLevelLocType(lev, currentList, targetList); refreshLocMastMapListCache(); redisUtil.del(RedisKeyType.LOC_MAP_BASE.key); return updatedCount; } private int syncLevelLocType(Integer lev, List currentList, List targetList) { Map targetByLocNo = new LinkedHashMap<>(); for (TargetLocMeta target : targetList) { if (targetByLocNo.put(target.locNo, target) != null) { throw new CoolException("第" + lev + "层存在重复库位号:" + target.locNo); } } Date now = new Date(); int updatedCount = 0; for (LocMast current : currentList) { TargetLocMeta target = targetByLocNo.get(current.getLocNo()); if (target == null) { throw new CoolException("第" + lev + "层地图中未找到库位号:" + current.getLocNo()); } if (java.util.Objects.equals(current.getLocType(), target.locType)) { continue; } UpdateWrapper updateWrapper = new UpdateWrapper<>(); updateWrapper.eq("loc_no", current.getLocNo()) .set("loc_type", target.locType) .set("modi_time", now); if (!locMastService.update(null, updateWrapper)) { throw new CoolException("第" + lev + "层库位locType同步失败:" + current.getLocNo()); } updatedCount++; } return updatedCount; } private void refreshLocMastMapListCache() { List locMastList = locMastService.list(new QueryWrapper().eq("lev1", 1)); redisUtil.set(RedisKeyType.LOC_MAST_MAP_LIST.key, JSON.toJSONString(locMastList), 60 * 60 * 24); } private List buildTargetLocMeta(BasMap basMap, Integer targetLev) { if (basMap == null || Cools.isEmpty(basMap.getData())) { throw new CoolException("第" + targetLev + "层地图数据为空,无法同步locType"); } List> dataList; try { dataList = JSON.parseObject(basMap.getData(), List.class); } catch (Exception e) { throw new CoolException("第" + targetLev + "层地图数据格式错误,无法同步locType"); } if (Cools.isEmpty(dataList)) { throw new CoolException("第" + targetLev + "层地图数据为空,无法同步locType"); } List targetList = new ArrayList<>(); int initRow = 1; for (int mapX = 0; mapX < dataList.size(); mapX++) { List row = dataList.get(mapX); if (row == null) { continue; } int initBay = -1; for (int mapY = 0; mapY < row.size(); mapY++) { JSONObject cell = row.get(mapY); if (cell == null || !"shelf".equals(cell.getString("type"))) { continue; } if (initBay == -1) { initBay = 2; } String value = cell.getString("value"); int userConfigRow = -1; int userConfigBay = -1; try { String[] split = value.split("-"); userConfigRow = Integer.parseInt(split[0]); userConfigBay = Integer.parseInt(split[1]); } catch (Exception ignored) { } if (userConfigBay != -1) { initRow = userConfigRow; initBay = userConfigBay; } targetList.add(new TargetLocMeta( Utils.getLocNo(initRow, initBay, targetLev), Utils.getLocNo(mapX, mapY, targetLev) )); initBay++; } if (initBay != -1) { initRow++; } } return targetList; } private static final class TargetLocMeta { private final String locNo; private final String locType; private TargetLocMeta(String locNo, String locType) { this.locNo = locNo; this.locType = locType; } } }