package com.zt.modules.sys.service; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.toolkit.IdWorker; import com.zt.common.constant.CacheKey; import com.zt.common.constant.Constant; import com.zt.common.exception.ErrorCode; import com.zt.common.exception.RenException; import com.zt.common.service.BaseService; import com.zt.common.utils.CacheUtils; import com.zt.common.utils.CommonUtils; import com.zt.common.utils.TreeUtils; import com.zt.core.context.User; import com.zt.core.context.UserContext; import com.zt.core.dictionary.DictionaryParser; import com.zt.core.shiro.ImportUtil; import com.zt.core.sys.dto.DictDto; import com.zt.core.sys.dto.DictItemDto; import com.zt.core.sys.dto.DictLeafDto; import com.zt.core.sys.service.IDictTypeService; import com.zt.modules.sys.dao.SysDictDataDao; import com.zt.modules.sys.dao.SysDictTypeDao; import com.zt.modules.sys.dto.DictTypeDto; import com.zt.modules.sys.model.SysDictData; import com.zt.modules.sys.model.SysDictType; import org.apache.commons.lang3.StringUtils; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import java.util.*; import java.util.stream.Collectors; /** * 数据字典 * * @author Mark sunlightcs@gmail.com */ @Service public class SysDictTypeService extends BaseService implements IDictTypeService { @Autowired private SysDictDataService sysDictDataService; @Resource private DictionaryParser dictionaryParser; @Autowired private SysDictDataDao sysDictDataDao; public List tree() { User user = UserContext.getUser(); if (Constant.Sys.PLATFORM_TENANT_ID.equals(user.getTenantId())) {// 平台的 List dictTypes = baseDao.selectList(new QueryWrapper().eq( Constant.TableColumn.IS_DELETE, Constant.Bool.NO).eq(Constant.TableColumn.TENANT_ID, Constant.Sys.PLATFORM_TENANT_ID)); // 这个地方有缓存 for (SysDictType dictType : dictTypes) { dictType.getChildren().clear(); } return TreeUtils.build(dictTypes); } else {// 租户的 // 查询租户和平台的 List list = baseDao.selectList(new QueryWrapper() .eq(Constant.TableColumn.IS_DELETE, Constant.Bool.NO) .eq("is_can_view", Constant.Bool.YES) /* .in(Constant.TableColumn.TENANT_ID, new Long[] { Constant.Sys.PLATFORM_TENANT_ID, user.getTenantId() })*/ .orderByAsc("sort", "dict_type", Constant.TableColumn.TENANT_ID)); // 这个地方有缓存 for (SysDictType dictType : list) { dictType.getChildren().clear(); } final List tree = TreeUtils.build(list); // 过滤:租户的;平台,不存在租户有相同字典类型的 return tree .stream() .filter(type -> !Constant.Sys.PLATFORM_TENANT_ID.equals(type.getTenantId()) || tree.stream() .filter(t -> !t.getId().equals(type.getId()) && t.getDictType().equals(type.getDictType())).count() == 0) .collect(Collectors.toList()); } } public List> importDataDictExcel(MultipartFile mutFile, String progressId) { int count = 0; Date beginDate = new Date(); List> list = new ArrayList<>();//存储所有的导入状态 Map map;//存储每一行的状态 Integer sum = 0; // 总共的条数 Integer suc = 0; // 成功的条数 Integer err = 0; // 失败的条数 int row1 = 0; Map errMap = new HashMap<>(); List batchList = new ArrayList<>(); ArrayList batchUpdateList = new ArrayList<>(); try { // 获取导入文件的后缀名 String fileName = mutFile.getOriginalFilename(); Workbook workbook = null; //解决excel版本问题 if (fileName != null && fileName.endsWith(".xls")) { workbook = new HSSFWorkbook(mutFile.getInputStream()); } else if (fileName != null && fileName.endsWith(".xlsx")) { workbook = new XSSFWorkbook(mutFile.getInputStream()); } assert workbook != null; //断言如果[boolean表达式]为true,则程序继续执行。 如果为false,则程序抛出AssertionError,并终止执行。 int sheets = workbook.getNumberOfSheets(); //List lifeManagementList = new ArrayList(); if (sheets == 1) { Map maxCodeMap = new HashMap(); List listMaxCode = baseDao.getMaxSortList2(); for (DictTypeDto item : listMaxCode ) { String key = item.getDictType(); maxCodeMap.put(key, item); } int typeSort = 0; for (int i = 0; i < sheets; i++) { Sheet sheet = workbook.getSheetAt(i); int num = sheet.getLastRowNum(); // 一共有多少行 String sheetName = sheet.getSheetName(); //获取当前sheet名称 for (int j = 1; j <= num; j++) { CacheUtils.put(progressId, "speed", CommonUtils.getPercent(j, num)); CacheUtils.put(progressId, "msg", "共" + num + "行,已完成第" + j + "行"); DictTypeDto lifeManagement = new DictTypeDto(); boolean isErr = false; row1 = j + 1; String pattern = "yyyy-MM-dd"; Row row = sheet.getRow(row1); String dictName = ImportUtil.getCellValue(row, 0, pattern); //字典名称 String dictType = ImportUtil.getCellValue(row, 1, pattern); //字典类型 String dictLabel = ImportUtil.getCellValue(row, 2, pattern); //字典标签 if (StringUtils.isEmpty(dictName)) { ImportUtil.updateErrMap(errMap, "没有填写字典名称!", sheetName, row1); continue; } if (StringUtils.isEmpty(dictType)) { ImportUtil.updateErrMap(errMap, "没有填写字典类型!", sheetName, row1); continue; } if (StringUtils.isEmpty(dictLabel)) { ImportUtil.updateErrMap(errMap, "没有填写字典标签!", sheetName, row1); continue; } if (maxCodeMap.get(dictType) == null) { SysDictType typeEntity = new SysDictType(); typeEntity.setDictType(dictType); typeEntity.setDictName(dictName); typeSort++; typeEntity.setSort(typeSort); typeEntity.setDelete(false); typeEntity.setCanView(true); baseDao.insert(typeEntity); // DictTypeDto dm = new DictTypeDto(); dm.setDictName(dictName); dm.setDictType(dictType); dm.setDictTypeId(typeEntity.getId()); dm.setSort(0); maxCodeMap.put(dictType, dm); } else { System.out.println("已有数据"); } int itemSort = maxCodeMap.get(dictType).getSort() + 1; maxCodeMap.get(dictType).setSort(itemSort); SysDictData itemEntity = new SysDictData(); itemEntity.setDictTypeId(maxCodeMap.get(dictType).getDictTypeId()); itemEntity.setDictLabel(dictLabel); itemEntity.setDictValue(itemSort); itemEntity.setSort(itemSort); itemEntity.setDelete(false); sysDictDataDao.insert(itemEntity); } } } } catch (Exception e) { e.printStackTrace(); ImportUtil.updateErrMap(errMap, "导入异常" + e.getMessage(), "", row1); //err++; } /* if (batchList.size() > 0 && err == 0) { super.insertBatch(batchList, 100); baseDao.updateOldId(); } if (batchUpdateList.size() > 0) { super.updateBatch(batchUpdateList, 100); }*/ Date nowDate = new Date(); String msg = "字典导入时间:" + CommonUtils.getDatePoor(nowDate, beginDate) + "\r\n"; System.out.println(msg); suc = sum - err; map = new HashMap<>(); map.put("sum", sum + ""); // 所有导入的条数 map.put("suc", suc + ""); // 成功的条数 map.put("err", err + ""); // 失败的条数 list.add(map); list.add(errMap); return list; } @Transactional(rollbackFor = Exception.class) public void insert(SysDictType entity) { // 判断父节点不允许拥有字典列表 if (sysDictDataService.getByType(entity.getPid()).size() > 0) { throw new RenException("请先删除父节点字典列表!"); } if (entity.getPid() == null) {// 根节点,同一个租户下同一个父类型下不能重复 entity.setPid(Constant.Sys.DICT_ROOT); } this.validateCode(entity); // code校验 if (!UserContext.getUser().isPlatform()) {// 租户 // 租户新增根类型,判断是否存在平台定义了不能重载的 if (Constant.Sys.DICT_ROOT.equals(entity.getPid())) { if (baseDao.selectList( new QueryWrapper().eq(Constant.TableColumn.IS_DELETE, Constant.Bool.NO) .eq("is_can_view", Constant.Bool.YES).eq("is_can_overload", Constant.Bool.NO).lambda() .eq(SysDictType::getTenantId, Constant.Sys.PLATFORM_TENANT_ID) .eq(SysDictType::getPid, Constant.Sys.DICT_ROOT) .eq(SysDictType::getDictType, entity.getDictType())).size() > 0) { throw new RenException("该字典类型不允许重载"); } } entity.setCanView(true);// 租户添加的,设置为可见 } else {// 平台 if (!entity.isCanView()) {// 租户不可见 entity.setCanOverload(false); } } super.insert(entity); CacheUtils.remove(Constant.Cache.SYS, CacheKey.SYS_DICT);// 清除缓存 } @Transactional(rollbackFor = Exception.class) public void update(SysDictType entity) { SysDictType tmp = baseDao.selectById(entity.getId()); if (tmp == null) { throw new RenException("查询信息失败"); } List all = baseDao.selectList(new QueryWrapper().eq(Constant.TableColumn.IS_DELETE, Constant.Bool.NO)); TreeUtils.updateValidate(all, entity, tmp); if (!entity.getPid().equals(tmp.getPid())) { // 判断父节点不允许拥有字典列表 if (sysDictDataService.getByType(entity.getPid()).size() > 0) { throw new RenException("请先删除父节点字典列表!"); } } this.validateCode(entity); // code校验 if (UserContext.getUser().isPlatform() && !entity.isCanView()) {// 平台,租户不可见,设置为不可重载 entity.setCanOverload(false); } super.update(entity); CacheUtils.remove(Constant.Cache.SYS, CacheKey.SYS_DICT);// 清除缓存 } private void validateCode(SysDictType entity) { if (Constant.Sys.DICT_ROOT.equals(entity.getPid())) { // 同一个租户下同一个父类型下不能重复 LambdaQueryWrapper queryWrapper = new QueryWrapper() .eq(Constant.TableColumn.IS_DELETE, Constant.Bool.NO).lambda() .eq(SysDictType::getTenantId, UserContext.getUser().getTenantId()) .eq(SysDictType::getPid, entity.getPid()).eq(SysDictType::getDictType, entity.getDictType()); if (entity.getId() != null && entity.getId() > 0) { // 修改 queryWrapper.ne(SysDictType::getId, entity.getId()); } if (baseDao.selectList(queryWrapper).size() > 0) { throw new RenException("字典类型重复"); } } else { List tree = this.tree(); SysDictType root = TreeUtils.getTreeRoot(TreeUtils.toList(tree), entity.getPid(), Constant.Sys.DICT_ROOT); if (root == null) { throw new RenException("获取字典类型失败"); } List treeList = TreeUtils.toList(tree.stream() .filter(type -> type.getId().equals(root.getId())).collect(Collectors.toList()).get(0)); if (treeList .stream() .filter(type -> !type.getId().equals(entity.getId()) && type.getDictType().equals(entity.getDictType())).count() > 0) { throw new RenException("字典类型重复"); } } } @Transactional(rollbackFor = Exception.class) public void delete(Long id) { // 字典类型只支持单个删除 if (baseDao.selectList( new QueryWrapper().eq(Constant.TableColumn.IS_DELETE, Constant.Bool.NO).lambda() .eq(SysDictType::getPid, id)).size() > 0) { throw new RenException("请先删除下级节点!"); } super.deleteLogic(id); CacheUtils.remove(Constant.Cache.SYS, CacheKey.SYS_DICT);// 清除缓存 } /** * 用户字典 * * @return */ public List getUserDicts() { Map> cache = (Map>) CacheUtils.get(Constant.Cache.SYS, CacheKey.SYS_DICT); Long tenantId = UserContext.getUser().getTenantId(); if (cache != null && cache.containsKey(tenantId)) { return cache.get(tenantId); } else { List typeList = new ArrayList<>(); typeList.addAll(this.getChildren(this.tree())); typeList.addAll(this.getChildren2(this.tree())); if (cache == null) { cache = new HashMap<>(); } cache.put(tenantId, typeList); CacheUtils.put(Constant.Cache.SYS, CacheKey.SYS_DICT, cache); return typeList; } } private List getChildren2(List children) { List list = new ArrayList<>(); for (SysDictType type1 : children) { if (type1.getChildren().size() > 0) {// 存在子类型 for (SysDictType type : type1.getChildren()) { DictDto dto; dto = new DictLeafDto(type.getDictType(), type.getDictName()); List datas = sysDictDataService.getByType(type.getId()); if (datas.size() > 0) { for (SysDictData data : datas) { DictItemDto itemDto = new DictItemDto(data.getDictLabel(), String.valueOf(data.getDictValue()), data.getRemark()); ((DictLeafDto) dto).getDataList().add(itemDto); } list.add(dto); } } } } return list; } private List getChildren(List children) { List list = new ArrayList<>(); for (SysDictType type : children) { DictDto dto; if (type.getChildren().size() > 0) {// 存在子类型 dto = new DictDto(type.getDictType(), type.getDictName()); dto.getChildren().addAll(getChildren(type.getChildren()));// 设置子类型 } else {// 叶子节点 dto = new DictLeafDto(type.getDictType(), type.getDictName()); List datas = sysDictDataService.getByType(type.getId()); for (SysDictData data : datas) { DictItemDto itemDto = new DictItemDto(data.getDictLabel(), String.valueOf(data.getDictValue()),data.getRemark()); ((DictLeafDto) dto).getDataList().add(itemDto); } } list.add(dto); } return list; } /** * 获取字段,包括常量字典 * * @return */ public List getDicts() { List list = new ArrayList<>(); list.addAll(this.getUserDicts()); list.addAll(dictionaryParser.getConstantDicts()); return list; } /** * 租户拷贝 * * @param id */ public void copyData(Long id) { SysDictType dictType = this.tree().stream().filter(type -> type.getId().equals(id)).findFirst().get(); if (!Constant.Sys.PLATFORM_TENANT_ID.equals(dictType.getTenantId())) { throw new RenException(ErrorCode.DATA_ERROR); } if (!dictType.isCanOverload()) { throw new RenException("该字典类型不能重载"); } // 这里不会和自己定义的重复 if (baseDao.selectList( new QueryWrapper().eq(Constant.TableColumn.IS_DELETE, Constant.Bool.NO).lambda() .eq(SysDictType::getTenantId, UserContext.getUser().getTenantId()) .eq(SysDictType::getPid, dictType.getPid()) .eq(SysDictType::getDictType, dictType.getDictType())).size() > 0) { throw new RenException(ErrorCode.DATA_ERROR); } List list = TreeUtils.toList(dictType); // 1、修改id Map idMap = new HashMap<>(); for (SysDictType type : list) { Long oldId = type.getId(); type.setId(IdWorker.getId());// 设置新的id idMap.put(oldId, type.getId()); } // 2、修改父Id、租户 User user = UserContext.getUser(); for (SysDictType type : list) { if (!Constant.Sys.DICT_ROOT.equals(type.getPid())) { Long pid = idMap.get(type.getPid()); if (pid == null) { throw new RenException(ErrorCode.DATA_ERROR); } type.setPid(pid);// 设置新的pid } type.setTenantId(user.getTenantId()); type.getChildren().clear(); } // 3、保存字段类型 super.insertBatch(list, 100); // 4、拷贝字段值 List datas = sysDictDataService.getByTypes(idMap.keySet()); for (SysDictData data : datas) { Long dictTypeId = idMap.get(data.getDictTypeId()); if (dictTypeId == null) { throw new RenException(ErrorCode.DATA_ERROR); } data.setId(null); data.setDictTypeId(dictTypeId);// 设置新的id data.setTenantId(user.getTenantId()); } sysDictDataService.insertBatch(datas, 100); CacheUtils.remove(Constant.Cache.SYS, CacheKey.SYS_DICT);// 清除缓存 } /** * 获取字典类型 * * @param dictType * @return */ @Override public DictDto getByDictType(String dictType) { List list = this.getDicts().stream().filter(dict -> dict.getDictType().equals(dictType)) .collect(Collectors.toList()); return list.size() > 0 ? list.get(0) : null; } /** * 获取字典值 * * @param dictType * @return */ @Override public List getDictItemsByDictType(String dictType) { List list = new ArrayList<>(); DictDto dict = this.getByDictType(dictType); if (dict != null) { if (dict instanceof DictLeafDto) { list.addAll(((DictLeafDto) dict).getDataList()); } else { List treeList = TreeUtils.toList(dict.getChildren()); for (DictDto dto : treeList) { if (dto instanceof DictLeafDto) { list.addAll(((DictLeafDto) dto).getDataList()); } } } } return list; } public Map getMapDict(Boolean idToNme, String dictType) { List list = getDictItemsByDictType(dictType); Map result = new HashMap<>(); for (DictItemDto item : list) { if (idToNme) result.put(item.getDictValue().toString(), item.getDictLabel()); else result.put(item.getDictLabel(), item.getDictValue().toString()); } return result; } /** * 获取字典(树)的所有字典值 * * @param dictTypeId * @return */ public List getDictItemsOfDictTree(Long dictTypeId) { SysDictType type = TreeUtils.getTreeRoot(TreeUtils.toList(this.tree()), dictTypeId, Constant.Sys.DICT_ROOT); if (type == null) { throw new RenException("字典类型不存在!"); } return this.getDictItemsByDictType(type.getDictType()); } }