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<SysDictTypeDao, SysDictType> implements IDictTypeService {
|
@Autowired
|
private SysDictDataService sysDictDataService;
|
@Resource
|
private DictionaryParser dictionaryParser;
|
@Autowired
|
private SysDictDataDao sysDictDataDao;
|
|
public List<SysDictType> tree() {
|
User user = UserContext.getUser();
|
if (Constant.Sys.PLATFORM_TENANT_ID.equals(user.getTenantId())) {// 平台的
|
List<SysDictType> dictTypes = baseDao.selectList(new QueryWrapper<SysDictType>().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<SysDictType> list = baseDao.selectList(new QueryWrapper<SysDictType>()
|
.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<SysDictType> 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<Map<String, Object>> importDataDictExcel(MultipartFile mutFile, String progressId) {
|
int count = 0;
|
Date beginDate = new Date();
|
List<Map<String, Object>> list = new ArrayList<>();//存储所有的导入状态
|
Map<String, Object> map;//存储每一行的状态
|
Integer sum = 0; // 总共的条数
|
Integer suc = 0; // 成功的条数
|
Integer err = 0; // 失败的条数
|
int row1 = 0;
|
Map<String, Object> errMap = new HashMap<>();
|
List<DictTypeDto> batchList = new ArrayList<>();
|
ArrayList<DictTypeDto> 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<LifeManagement> lifeManagementList = new ArrayList<LifeManagement>();
|
if (sheets == 1) {
|
Map<String, DictTypeDto> maxCodeMap = new HashMap<String, DictTypeDto>();
|
List<DictTypeDto> 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<SysDictType>().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<SysDictType> all = baseDao.selectList(new QueryWrapper<SysDictType>().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<SysDictType> queryWrapper = new QueryWrapper<SysDictType>()
|
.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<SysDictType> tree = this.tree();
|
SysDictType root = TreeUtils.getTreeRoot(TreeUtils.toList(tree), entity.getPid(), Constant.Sys.DICT_ROOT);
|
if (root == null) {
|
throw new RenException("获取字典类型失败");
|
}
|
List<SysDictType> 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<SysDictType>().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<DictDto> getUserDicts() {
|
Map<Long, List<DictDto>> cache = (Map<Long, List<DictDto>>) 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<DictDto> 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<DictDto> getChildren2(List<SysDictType> children) {
|
List<DictDto> 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<SysDictData> datas = sysDictDataService.getByType(type.getId());
|
if (datas.size() > 0) {
|
for (SysDictData data : datas) {
|
DictItemDto itemDto = new DictItemDto(data.getDictLabel(), String.valueOf(data.getDictValue()));
|
((DictLeafDto) dto).getDataList().add(itemDto);
|
}
|
list.add(dto);
|
}
|
}
|
}
|
}
|
return list;
|
}
|
|
private List<DictDto> getChildren(List<SysDictType> children) {
|
List<DictDto> 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<SysDictData> datas = sysDictDataService.getByType(type.getId());
|
for (SysDictData data : datas) {
|
DictItemDto itemDto = new DictItemDto(data.getDictLabel(), String.valueOf(data.getDictValue()));
|
((DictLeafDto) dto).getDataList().add(itemDto);
|
}
|
}
|
list.add(dto);
|
}
|
return list;
|
}
|
|
/**
|
* 获取字段,包括常量字典
|
*
|
* @return
|
*/
|
public List<DictDto> getDicts() {
|
List<DictDto> 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<SysDictType>().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<SysDictType> list = TreeUtils.toList(dictType);
|
// 1、修改id
|
Map<Long, Long> 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<SysDictData> 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<DictDto> 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<DictItemDto> getDictItemsByDictType(String dictType) {
|
List<DictItemDto> list = new ArrayList<>();
|
DictDto dict = this.getByDictType(dictType);
|
if (dict != null) {
|
if (dict instanceof DictLeafDto) {
|
list.addAll(((DictLeafDto) dict).getDataList());
|
} else {
|
List<DictDto> treeList = TreeUtils.toList(dict.getChildren());
|
for (DictDto dto : treeList) {
|
if (dto instanceof DictLeafDto) {
|
list.addAll(((DictLeafDto) dto).getDataList());
|
}
|
}
|
}
|
}
|
return list;
|
}
|
|
public Map<String, String> getMapDict(Boolean idToNme, String dictType) {
|
List<DictItemDto> list = getDictItemsByDictType(dictType);
|
|
Map<String, String> 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<DictItemDto> 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());
|
}
|
}
|