This commit is contained in:
ran.shang
2025-12-29 16:06:48 +08:00
parent b853edcfde
commit ee95dfa2c2
1600 changed files with 6997 additions and 7445 deletions

View File

@@ -0,0 +1,105 @@
package com.senmesh.component.dict.controller;
import com.senmesh.common.AlitaResult;
import com.senmesh.common.util.UserContextHolder;
import com.senmesh.component.dict.dto.DictDTO;
import com.senmesh.component.dict.dto.DictDetailQueryDTO;
import com.senmesh.component.dict.dto.DictQueryDTO;
import com.senmesh.component.dict.dto.DropdownDictDetailDTO;
import com.senmesh.component.dict.service.DictCacheService;
import com.senmesh.component.dict.service.DictDetailService;
import com.senmesh.component.dict.service.DictService;
import com.senmesh.tkmybatis.pojo.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Collection;
/**
*
* @author Rey(leijiaping@newyetai.com)
*
*/
@Api(tags = "字典表")
@RestController
@RequestMapping({"/dict"})
public class DictController {
@Autowired
private DictService dictService;
@Autowired
private DictDetailService dictDetailService;
@Autowired
private DictCacheService dictCacheService;
/**
* 新增
*
* @param dict
*/
@ApiOperation("新增字典")
@PostMapping("create")
public AlitaResult<DictDTO> createDict(@RequestBody DictDTO dict) {
dictService.createDict(dict, UserContextHolder.getLoginUserId());
return AlitaResult.success(dict);
}
/**
* 修改
*
* @param dict
*/
@ApiOperation("修改字典")
@PostMapping("modify")
public AlitaResult<DictDTO> modifyDict(@RequestBody DictDTO dict) {
dictService.modifyDict(dict, UserContextHolder.getLoginUserId());
return AlitaResult.success(dict);
}
/**
* 删除
*
* @param dict
*/
@ApiOperation("删除字典")
@PostMapping("remove")
public AlitaResult<DictDTO> removeDict(@RequestBody DictDTO dict) {
dictService.removeDict(dict, UserContextHolder.getLoginUserId());
return AlitaResult.success(dict);
}
/**
* 查询
*
* @param dict
*/
@ApiOperation("后边页面列出字典-带分页")
@GetMapping("page")
public AlitaResult<Page<DictDTO>> page(DictQueryDTO dict) {
dictService.page(dict);
return AlitaResult.success(dict.getPageResult());
}
/**
* 查询
*
* @param dictDetailDTO
*/
@ApiOperation("列出字典")
@GetMapping("lookup")
public AlitaResult<Collection<DropdownDictDetailDTO>> find(DictDetailQueryDTO dictDetailDTO) {
return AlitaResult.success(dictDetailService.getDropdownDictDetails(dictDetailDTO));
}
@ApiOperation("刷新字典-dictCode")
@GetMapping("flush/{dictCode}")
public AlitaResult<Boolean> flushByDictCode(@PathVariable String dictCode){
dictCacheService.removeTreeDictDetailByCode(dictCode);
return AlitaResult.success(Boolean.TRUE);
}
}

View File

@@ -0,0 +1,45 @@
package com.senmesh.component.dict.dao;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import com.senmesh.component.dict.dto.DictDetailDTO;
import com.senmesh.component.dict.dto.DictDetailQueryDTO;
import com.senmesh.component.dict.dto.DropdownDictDetailDTO;
import com.senmesh.component.dict.entity.DictDetail;
import com.senmesh.tkmybatis.mybatis.MyMapper;
import com.senmesh.tkmybatis.pojo.Page;
/**
* @author Rey(leijiaping@newyetai.com)
*/
public interface DictDetailMapper extends MyMapper<DictDetail> {
/**
* 查询
*
* @param page 不为空分页
* @param dictDetail
* @return
*/
List<DictDetailDTO> list(Page<DictDetailDTO> page, @Param("param") DictDetailQueryDTO dictDetailQueryDTO);
/**
* 查询
*
* @param dictDetailDTO
* @return
*/
List<DropdownDictDetailDTO> getDropdownDictDetails(@Param("param") DictDetailQueryDTO dictDetailQueryDTO);
/**
* 获取字典编码
*
* @param dictDetailQueryDTO
* @return
* @author sr on 2020-07-30
*/
List<String> getDictCode(@Param("param") DictDetailQueryDTO dictDetailQueryDTO);
}

View File

@@ -0,0 +1,24 @@
package com.senmesh.component.dict.dao;
import com.senmesh.component.dict.dto.DictDTO;
import com.senmesh.component.dict.dto.DictQueryDTO;
import com.senmesh.component.dict.entity.Dict;
import com.senmesh.tkmybatis.mybatis.MyMapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* @author Rey(leijiaping@newyetai.com)
*/
public interface DictMapper extends MyMapper<Dict> {
/**
* 分页查询
*
* @param dict
* @return
*/
List<DictDTO> list(@Param("param") DictQueryDTO dict);
}

View File

@@ -0,0 +1,35 @@
package com.senmesh.component.dict.dto;
import java.io.Serializable;
import java.util.List;
import com.senmesh.common.dto.BaseDTO;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
/**
* @author sr on 2020-07-30
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder
public class DictDTO extends BaseDTO implements Serializable {
/** **/
private static final long serialVersionUID = -8242172908364818906L;
@ApiModelProperty("字典编码")
private String dictCode;
@ApiModelProperty("字典名称")
private String dictName;
@ApiModelProperty("数据字典详情列表")
private List<DictDetailDTO> dictDetailList;
}

View File

@@ -0,0 +1,54 @@
package com.senmesh.component.dict.dto;
import com.google.common.collect.Lists;
import com.senmesh.common.dto.BaseDTO;
import com.senmesh.common.util.TreeNode;
import io.swagger.annotations.ApiModelProperty;
import lombok.*;
import lombok.experimental.SuperBuilder;
import java.util.List;
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
@Data
@SuperBuilder
public class DictDetailDTO extends BaseDTO implements TreeNode<Long, DictDetailDTO> {
/**
*
**/
private static final long serialVersionUID = -1396551692759999448L;
@ApiModelProperty("字典ID")
private Long dictId;
@ApiModelProperty("字典编码")
private String dictCode;
@ApiModelProperty("字典明细编码")
private String dictDetailCode;
@ApiModelProperty("字典明细名称")
private String dictDetailName;
@ApiModelProperty("顺序")
private Integer dictOrder;
@ApiModelProperty("父子项的ID")
private Long parentId;
@ApiModelProperty("父子项的Name")
private String parentName;
private List<DictDetailDTO> children = Lists.newArrayList();
@Override
public void addChildren(DictDetailDTO node) {
this.children.add(node);
}
}

View File

@@ -0,0 +1,59 @@
package com.senmesh.component.dict.dto;
import com.senmesh.common.dto.PageQueryDTO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
*
* @author Rey(leijiaping@newyetai.com)
*
*/
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Data
@ApiModel("字典详情")
public class DictDetailQueryDTO extends PageQueryDTO {
/**
*
*/
private static final long serialVersionUID = 2138839246462138493L;
@ApiModelProperty("字典类型")
private String type;
@ApiModelProperty("字典类型-多个字典类型(查询)")
private String[] types;
@ApiModelProperty("字典id")
private Long dictId;
@ApiModelProperty("字典名称")
private String dictName;
@ApiModelProperty("字典编码")
private String dictCode;
@ApiModelProperty("字典明细id")
private Long dictDetailId;
@ApiModelProperty("字典明细名称")
private String dictDetailName;
@ApiModelProperty("字典明细编码")
private String dictDetailCode;
@ApiModelProperty("父id")
private Long parentId;
@ApiModelProperty("查询值,同时筛选 dictCode,dictName")
private String queryCode;
}

View File

@@ -0,0 +1,34 @@
package com.senmesh.component.dict.dto;
import com.senmesh.common.dto.PageQueryDTO;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author sr on 2020-07-30
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class DictQueryDTO extends PageQueryDTO {
/** **/
private static final long serialVersionUID = -8242172908364818906L;
@ApiModelProperty("字典id")
private Long dictId;
@ApiModelProperty("字典编码")
private String dictCode;
@ApiModelProperty("字典名称")
private String dictName;
@ApiModelProperty("查询值,同时筛选 dictCode,dictName")
private String queryCode;
}

View File

@@ -0,0 +1,38 @@
package com.senmesh.component.dict.dto;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Data
@ApiModel("下拉字典详情")
public class DropdownDictDetailDTO implements Serializable{
/** **/
private static final long serialVersionUID = -6549004852720101531L;
@ApiModelProperty("明细id")
private Long detailId;
@ApiModelProperty("字典类型")
private String type;
@ApiModelProperty("字典编码")
private String dictDetailCode;
@ApiModelProperty("字典名称")
private String dictDetailName;
@ApiModelProperty("顺序")
private Integer dictOrder;
}

View File

@@ -0,0 +1,46 @@
package com.senmesh.component.dict.entity;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableName;
import com.senmesh.common.entity.BaseEntity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
* @author Rey(leijiaping @ newyetai.com)
*/
@TableName("xs_dict")
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
@Data
public class Dict extends BaseEntity {
/** **/
private static final long serialVersionUID = 1802939371884168684L;
/**
* 字典编码
*/
private String dictCode;
/**
* 字典名称
*/
private String dictName;
@Builder
public Dict(Long id, Boolean deleted, Long createBy, Date createTime, Long updateBy,
Date updateTime, Long proxyBy, String dictCode, String dictName) {
super(id, deleted, createBy, createTime, updateBy, updateTime, proxyBy);
this.dictCode = dictCode;
this.dictName = dictName;
}
}

View File

@@ -0,0 +1,65 @@
package com.senmesh.component.dict.entity;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableName;
import com.senmesh.common.entity.BaseEntity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
* @author Rey(leijiaping @ newyetai.com)
*/
@TableName("xs_dict_detail")
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
@Builder
@Data
public class DictDetail extends BaseEntity {
/** **/
private static final long serialVersionUID = -1396551692759999448L;
/**
* 字典ID
*/
private Long dictId;
/**
* 字典明细编码
*/
private String dictDetailCode;
/**
* 字典明细名称
*/
private String dictDetailName;
/**
* 顺序
*/
private Integer dictOrder;
/**
* 父子项的ID
*/
private Long parentId;
@Builder
public DictDetail(Long id, Boolean deleted, Long createBy, Date createTime,
Long updateBy, Date updateTime, Long proxyBy, Long dictId,
String dictDetailCode, String dictDetailName, Integer dictOrder, Long parentId) {
super(id, deleted, createBy, createTime, updateBy, updateTime, proxyBy);
this.dictId = dictId;
this.dictDetailCode = dictDetailCode;
this.dictDetailName = dictDetailName;
this.dictOrder = dictOrder;
this.parentId = parentId;
}
}

View File

@@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.senmesh.component.dict.dao.DictDetailMapper">
<sql id="queryFromSql">
from
xs_dict dict
inner join xs_dict_detail detail on dict.id = detail.dict_id
where
dict.deleted = 0 and detail.deleted = 0
<if test='param.dictName != null and param.dictName.trim() != ""'>
<bind name="dictNameLike" value="'%' + param.dictName + '%'" />
AND dict.dict_name like #{dictNameLike}
</if>
<if test='param.dictCode != null and param.dictCode.trim() != ""'>
AND dict.dict_code = #{param.dictCode}
</if>
<if test='param.dictId != null'>
AND detail.dict_id = #{param.dictId}
</if>
<if test='param.dictDetailId != null'>
AND detail.id = #{param.dictDetailId}
</if>
<if test='param.dictDetailName != null and param.dictDetailName.trim() != ""'>
<bind name="dictDetailNameLike" value="'%' + param.dictDetailName + '%'" />
AND detail.dict_detail_name like #{dictDetailNameLike}
</if>
<if test='param.dictDetailCode != null and param.dictDetailCode.trim() != ""'>
AND detail.dict_detail_code = #{param.dictDetailCode}
</if>
<if test='param.parentId != null'>
AND detail.parent_id = #{param.parentId}
</if>
<if test='param.type != null and param.type.trim() != ""'>
AND dict.dict_code = #{param.type}
</if>
<if test='param.types != null'>
AND dict.dict_code in
<foreach collection="param.types" item="code" open="(" close=")" separator=",">
#{code}
</foreach>
</if>
<if test='param.queryCode != null and param.queryCode.trim() != ""'>
<bind name="queryCodeLike" value="'%' + param.queryCode + '%'" />
AND (detail.dict_detail_name like #{queryCodeLike} OR detail.dict_detail_code like #{queryCodeLike})
</if>
</sql>
<select id="list" resultType="com.senmesh.component.dict.dto.DictDetailDTO">
select
detail.*,
(select dict_detail_name from xs_dict_detail son where son.id = detail.parent_id) as parent_name,
dict.dict_code
<include refid="queryFromSql"></include>
order by detail.dict_order
</select>
<select id="getDropdownDictDetails" resultType="com.senmesh.component.dict.dto.DropdownDictDetailDTO">
SELECT
detail.id as detail_id,
dict.dict_code as 'type',
detail.dict_detail_code,
detail.dict_detail_name,
detail.dict_order
<include refid="queryFromSql"></include>
order by detail.dict_order
</select>
<select id="getDictCode" resultType="string">
select distinct dict.dict_code
<include refid="queryFromSql"></include>
</select>
</mapper>

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.senmesh.component.dict.dao.DictMapper">
<select id="list" resultType="com.senmesh.component.dict.dto.DictDTO">
SELECT * FROM xs_dict
<where>
deleted = 0
<if test='param.dictId != null'>
AND id = #{param.dictId}
</if>
<if test='param.dictName != null and param.dictName.trim() != ""'>
<bind name="dictNameLike" value="'%' + param.dictName + '%'" />
AND dict_name like #{dictNameLike}
</if>
<if test='param.dictCode != null and param.dictCode.trim() != ""'>
AND dict_code = #{param.dictCode}
</if>
<if test='param.queryCode != null and param.queryCode.trim() != ""'>
<bind name="queryCodeLike" value="'%' + param.queryCode + '%'" />
AND (dict_name like #{queryCodeLike} OR dict_code like #{queryCodeLike})
</if>
</where>
</select>
</mapper>

View File

@@ -0,0 +1,24 @@
package com.senmesh.component.dict.mapstruct;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import com.senmesh.component.dict.dto.DictDetailDTO;
import com.senmesh.component.dict.entity.DictDetail;
/**
* @author sr on 2020-07-30
*/
@Mapper
public interface DictDetailMapMapper {
DictDetailMapMapper INSTANCE = Mappers.getMapper(DictDetailMapMapper.class);
/**
* @param dictDetailDTO
* @return
* @author sr on 2020-07-30
*/
DictDetail toEntity(DictDetailDTO dictDetailDTO);
}

View File

@@ -0,0 +1,39 @@
package com.senmesh.component.dict.mapstruct;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import com.senmesh.component.dict.dto.DictDTO;
import com.senmesh.component.dict.dto.DictQueryDTO;
import com.senmesh.component.dict.entity.Dict;
/**
* @author sr on 2020-07-30
*/
@Mapper
public interface DictMapMapper {
DictMapMapper INSTANCE = Mappers.getMapper(DictMapMapper.class);
/**
* @param dictDetailDTO
* @return
* @author sr on 2020-07-30
*/
Dict toEntity(DictDTO dictDTO);
/**
* @param dictQueryDTO
* @return
* @author sr on 2020-07-30
*/
Dict toEntity(DictQueryDTO dictQueryDTO);
/**
* @param dict
* @return
* @author sr on 2020-07-30
*/
DictDTO toDto(Dict dict);
}

View File

@@ -0,0 +1,47 @@
package com.senmesh.component.dict.service;
import java.util.List;
import com.senmesh.component.dict.dto.DictDetailDTO;
/**
* 字典缓存
*
* @author sr on 2020-04-03
*/
public interface DictCacheService {
/**
* 获取dictCode的树形数据字典缓存
*
* @param dictCode
* @return
* @author sr on 2020-04-03
*/
List<DictDetailDTO> getTreeDictDetailByCode(String dictCode);
/**
* 更新dictCode的树形数据字典缓存
*
* @param dictCode
* @return
* @author sr on 2020-04-03
*/
List<DictDetailDTO> putTreeDictDetailByCode(String dictCode);
/**
* 清除dictCode的树形数据字典缓存
*
* @param dictCode
* @author sr on 2020-04-03
*/
void removeTreeDictDetailByCode(String dictCode);
/**
* 清除树形数据字典缓存
*
* @author sr on 2020-04-03
*/
void removeTreeDictDetail();
}

View File

@@ -0,0 +1,107 @@
package com.senmesh.component.dict.service;
import com.senmesh.component.dict.dto.DictDetailDTO;
import com.senmesh.component.dict.dto.DictDetailQueryDTO;
import com.senmesh.component.dict.dto.DropdownDictDetailDTO;
import com.senmesh.tkmybatis.pojo.Page;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
*
* @author Rey(leijiaping@newyetai.com)
*
*/
public interface DictDetailService {
/**
* 新增
*
* @param dictDetail
* @param operateUserId
*/
void createDictDetail(DictDetailDTO dictDetail, Long operateUserId);
/**
* 修改
*
* @param dictDetail
*/
void modifyDictDetail(DictDetailDTO dictDetail, Long operateUserId);
/**
* 删除
*
* @param dictDetail
*/
void removeDictDetail(DictDetailDTO dictDetail, Long operateUserId);
/**
* 查询
*
* @param page
* @param dictDetail
*/
void page(Page<DictDetailDTO> page, DictDetailQueryDTO dictDetail);
/**
* 查询
*
* @param dictDetailDTO
*/
Collection<DropdownDictDetailDTO> getDropdownDictDetails(DictDetailQueryDTO dictDetailDTO);
/**
* 查询
*
* @param dictDetail
*/
List<DictDetailDTO> list(DictDetailQueryDTO dictDetail);
/**
* 获取map
* @param parentType
* @return
*/
Map<String, DropdownDictDetailDTO> getDictDetailsMap(String parentType);
/**
* 获取map
* @param parentCode
* @param operateUserId
* @return
*/
Map<String, String> getDictDetailMap(String parentCode, Long operateUserId);
/**
* 获取字典详情
* @param dictId
* @param code
* @param parentId
* @return
*/
DictDetailDTO findDetail(Long dictId, String code, Long parentId);
/**
* 刷新字典缓存
*
* @param dictDetail
* @author sr on 2020-07-30
*/
void refreshDictCache(DictDetailQueryDTO dictDetailQueryDTO);
/**
* 根据给定的type类型,返回Map
* 以 auth_status 为例子,返回的Map key->value 为
* authStatus1->未认证
* authStatus2->认证中
* authStatus3->认证成功
* authStatus4->认证失败
*
* @param types
* @return
*/
Map<String, String> getMapByTypes(List<String> types);
}

View File

@@ -0,0 +1,46 @@
package com.senmesh.component.dict.service;
import com.senmesh.component.dict.dto.DictDTO;
import com.senmesh.component.dict.dto.DictQueryDTO;
/**
*
* @author Rey(leijiaping@newyetai.com)
*
*/
public interface DictService{
/**
* 新增
*
* @param dict
* @return
*/
DictDTO createDict(DictDTO dict, Long operateUserId);
/**
* 修改
*
* @param dict
* @return
*/
DictDTO modifyDict(DictDTO dict, Long operateUserId);
/**
* 删除
*
* @param dict
*/
void removeDict(DictDTO dict, Long operateUserId);
/**
* 查询
*
* @param dict
*/
void page(DictQueryDTO dict);
DictDTO find(DictQueryDTO dict);
DictDTO findOrInsert(DictQueryDTO dict, Long operateUserId);
}

View File

@@ -0,0 +1,55 @@
package com.senmesh.component.dict.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import com.senmesh.common.constant.CacheConstants;
import com.senmesh.common.util.TreeHelper;
import com.senmesh.component.dict.dao.DictDetailMapper;
import com.senmesh.component.dict.dto.DictDetailDTO;
import com.senmesh.component.dict.dto.DictDetailQueryDTO;
import com.senmesh.component.dict.service.DictCacheService;
/**
* @author sr on 2020-04-03
*/
@Service
public class DictCacheServiceImpl implements DictCacheService {
@Autowired
private DictDetailMapper dictDetailMapper;
@Override
@Cacheable(key = "#dictCode", value = CacheConstants.CACHE_NAME_DICT)
public List<DictDetailDTO> getTreeDictDetailByCode(String dictCode) {
DictDetailQueryDTO queryDTO = DictDetailQueryDTO.builder().dictCode(dictCode).build();
queryDTO.disablePage();
List<DictDetailDTO> details =
dictDetailMapper.list(null, queryDTO);
return TreeHelper.buildTree(null, details);
}
@Override
@CachePut(key = "#dictCode", value = CacheConstants.CACHE_NAME_DICT)
public List<DictDetailDTO> putTreeDictDetailByCode(String dictCode) {
return this.getTreeDictDetailByCode(dictCode);
}
@Override
@CacheEvict(key = "#dictCode", value = CacheConstants.CACHE_NAME_DICT)
public void removeTreeDictDetailByCode(String dictCode) {
// do nothing...
}
@Override
@CacheEvict(allEntries = true, value = CacheConstants.CACHE_NAME_DICT)
public void removeTreeDictDetail() {
// do nothing...
}
}

View File

@@ -0,0 +1,150 @@
package com.senmesh.component.dict.service.impl;
import com.google.common.base.CaseFormat;
import com.google.common.collect.Maps;
import com.senmesh.common.exception.util.Assert;
import com.senmesh.component.dict.dao.DictDetailMapper;
import com.senmesh.component.dict.dto.*;
import com.senmesh.component.dict.mapstruct.DictDetailMapMapper;
import com.senmesh.component.dict.service.DictCacheService;
import com.senmesh.component.dict.service.DictDetailService;
import com.senmesh.component.dict.service.DictService;
import com.senmesh.tkmybatis.pojo.Page;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
*
* @author Rey(leijiaping@newyetai.com)
*
*/
@Service
public class DictDetailServiceImpl implements DictDetailService {
@Resource
private DictDetailMapper dictDetailMapper;
@Autowired
private DictService dictService;
@Autowired
private DictCacheService dictCacheService;
@Override
public Map<String, String> getMapByTypes(List<String> types) {
if (CollectionUtils.isEmpty(types)) {
return Maps.newHashMap();
}
Map<String, String> dictCodeMap = types.stream().collect(Collectors.toMap(dictCode -> dictCode, dictCode -> CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, dictCode)));
List<DropdownDictDetailDTO> dictDetails = dictDetailMapper
.getDropdownDictDetails(DictDetailQueryDTO.builder().types(types.toArray(new String[0])).build());
return dictDetails.stream().collect(Collectors.toMap(item ->
dictCodeMap.get(item.getType()) + item.getDictDetailCode()
, DropdownDictDetailDTO::getDictDetailName));
}
@Override
public void createDictDetail(DictDetailDTO dictDetail, Long operateUserId) {
dictDetailMapper.saveEntity(DictDetailMapMapper.INSTANCE.toEntity(dictDetail), operateUserId);
refreshDictCache(dictDetail.getDictId());
}
@Override
public void modifyDictDetail(DictDetailDTO dictDetail, Long operateUserId) {
dictDetailMapper.updateEntitySelective(DictDetailMapMapper.INSTANCE.toEntity(dictDetail), operateUserId);
refreshDictCache(dictDetail.getDictId());
}
@Override
public void removeDictDetail(DictDetailDTO dictDetail, Long operateUserId) {
dictDetailMapper.deleteEntity(DictDetailMapMapper.INSTANCE.toEntity(dictDetail), operateUserId);
refreshDictCache(dictDetail.getDictId());
}
/**
* 刷新缓存
*
* @param dictDetail 字典详情
* @author sr on 2020-07-30
*/
private void refreshDictCache(Long dictId) {
Assert.notNull(dictId, "字典id不能为空");
this.refreshDictCache(DictDetailQueryDTO.builder().dictId(dictId).build());
}
@Override
public void page(Page<DictDetailDTO> page, DictDetailQueryDTO dictDetail) {
dictDetailMapper.list(page, dictDetail);
}
@Override
public Collection<DropdownDictDetailDTO> getDropdownDictDetails(DictDetailQueryDTO dictDetailDTO) {
boolean dtoIsNull = dictDetailDTO == null || (StringUtils.isBlank(dictDetailDTO.getType())
&& ArrayUtils.isEmpty(dictDetailDTO.getTypes()));
if (dtoIsNull) {
return null;
}
return dictDetailMapper.getDropdownDictDetails(dictDetailDTO);
}
@Override
public List<DictDetailDTO> list(DictDetailQueryDTO dictDetail) {
return dictDetailMapper.list(null, dictDetail);
}
@Override
public Map<String, DropdownDictDetailDTO> getDictDetailsMap(String parentType) {
DictDetailQueryDTO queryDTO = new DictDetailQueryDTO();
queryDTO.setType(parentType);
Collection<DropdownDictDetailDTO> details = getDropdownDictDetails(queryDTO);
if (details == null || details.size() == 0) {
return null;
}
Map<String, DropdownDictDetailDTO> dictMap = Maps.newHashMapWithExpectedSize(details.size());
for (DropdownDictDetailDTO dto : details) {
dictMap.put(dto.getDictDetailName(), dto);
}
return dictMap;
}
@Override
public Map<String, String> getDictDetailMap(String parentCode, Long operateUserId) {
DictDTO dict = dictService.findOrInsert(DictQueryDTO.builder().dictCode(parentCode).build(), operateUserId);
List<DictDetailDTO> details = list(DictDetailQueryDTO.builder().dictId(dict.getId()).build());
if (details == null || details.size() == 0) {
return Maps.newHashMap();
}
Map<String, String> dictMap = Maps.newHashMapWithExpectedSize(details.size());
for (DictDetailDTO detail : details) {
dictMap.put(detail.getDictDetailCode(), detail.getDictDetailName());
}
return dictMap;
}
@Override
public DictDetailDTO findDetail(Long dictId, String code, Long parentId) {
List<DictDetailDTO> list = list(DictDetailQueryDTO.builder().dictId(dictId).dictDetailCode(code).parentId(parentId).build());
if(CollectionUtils.isEmpty(list)){
return null;
}
return list.get(0);
}
@Override
public void refreshDictCache(DictDetailQueryDTO dictDetailQueryDTO) {
dictDetailQueryDTO.setNeedPage(Boolean.FALSE);
List<String> dictCodes = dictDetailMapper.getDictCode(dictDetailQueryDTO);
dictCodes.forEach(dictCode -> dictCacheService.putTreeDictDetailByCode(dictCode));
}
}

View File

@@ -0,0 +1,96 @@
package com.senmesh.component.dict.service.impl;
import com.senmesh.common.constant.ExceptionMsgs;
import com.senmesh.common.exception.util.ExceptionUtils;
import com.senmesh.component.dict.dao.DictMapper;
import com.senmesh.component.dict.dto.DictDTO;
import com.senmesh.component.dict.dto.DictQueryDTO;
import com.senmesh.component.dict.entity.Dict;
import com.senmesh.component.dict.mapstruct.DictMapMapper;
import com.senmesh.component.dict.service.DictCacheService;
import com.senmesh.component.dict.service.DictService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @author Rey(leijiaping @ newyetai.com)
*/
@Service
public class DictServiceImpl implements DictService {
@Autowired
private DictMapper dictMapper;
@Autowired
private DictCacheService dictCacheService;
@Override
public DictDTO createDict(DictDTO dict, Long operateUserId) {
String dictCode = dict.getDictCode();
ExceptionUtils.throwBusinessException(
dictMapper.existsEntity(Dict.builder().dictCode(dictCode).build()),
ExceptionMsgs.ENTITY_HAS_EXISTS);
Dict dictEntity=DictMapMapper.INSTANCE.toEntity(dict);
dictMapper.saveEntity(dictEntity, operateUserId);
dictCacheService.putTreeDictDetailByCode(dictCode);
dict.setId(dictEntity.getId());
return dict;
}
@Override
public DictDTO modifyDict(DictDTO dict, Long operateUserId) {
String dictCode = dict.getDictCode();
Long dictId = dict.getId();
ExceptionUtils.throwBusinessException(
dictMapper.existsEntity(Dict.builder().id(dictId).dictCode(dictCode).build()),
ExceptionMsgs.ENTITY_HAS_EXISTS);
dictMapper.updateEntitySelective(DictMapMapper.INSTANCE.toEntity(dict), operateUserId);
refreshDictCache(dictId, dictCode);
return dict;
}
private void refreshDictCache(Long dictId, String newDictCode) {
String dictCode = dictMapper.getById(dictId).getDictCode();
if (newDictCode != null && !dictCode.equals(newDictCode)) {
dictCacheService.putTreeDictDetailByCode(newDictCode);
}
dictCacheService.putTreeDictDetailByCode(dictCode);
}
@Override
public void removeDict(DictDTO dict, Long operateUserId) {
dictMapper.deleteEntity(DictMapMapper.INSTANCE.toEntity(dict), operateUserId);
refreshDictCache(dict.getId(), null);
}
@Override
public void page(DictQueryDTO dict) {
dictMapper.list(dict);
}
@Override
public DictDTO find(DictQueryDTO dict) {
List<DictDTO> dictDtos = dictMapper.list(dict);
return dictDtos.isEmpty() ? null : dictDtos.get(0);
}
@Override
public DictDTO findOrInsert(DictQueryDTO dictQueryDTO, Long operateUserId) {
DictDTO result = find(dictQueryDTO);
if (result == null) {
synchronized (this) {
result = find(dictQueryDTO);
if (result == null) {
Dict dict = DictMapMapper.INSTANCE.toEntity(dictQueryDTO);
dictMapper.saveEntity(dict, operateUserId);
result = DictMapMapper.INSTANCE.toDto(dict);
}
}
}
return result;
}
}

View File

@@ -0,0 +1,64 @@
package com.senmesh.component.dict.util;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.senmesh.component.dict.dto.DictDetailDTO;
import com.senmesh.component.dict.entity.Dict;
import com.senmesh.component.dict.service.DictCacheService;
/**
* 字典工具类
* @author sr on 2019-12-09
*/
@Component
public class DictUtils {
private static DictCacheService dictCacheService;
@Autowired
public void setDictCacheService(DictCacheService dictCacheService) {
this.dictCacheService = dictCacheService;
}
/**
* 校验对应字典编码是否存在
* @param id
* @param dictCode
* @return
* @author sr on 2019-12-09
*/
public static Dict toCheckDuplicateCode(Dict dict) {
return Dict.builder().id(dict.getId()).dictCode(dict.getDictCode()).build();
}
public static List<DictDetailDTO> getCacheTree(String dictCode){
return dictCacheService.getTreeDictDetailByCode(dictCode);
}
/**
* 获取数据字典明细map(detailCode:detailName)
* @param dictCode
* @return
* @author sr on 2022-02-21
*/
public static Map<String, String> getCodeNameMap(String dictCode) {
return dictCacheService.getTreeDictDetailByCode(dictCode).stream().collect(
Collectors.toMap(DictDetailDTO::getDictDetailCode, DictDetailDTO::getDictDetailName));
}
/**
* 获取数据字典明细map(detailName:detailCode)
* @param dictCode
* @return
* @author sr on 2022-06-30
*/
public static Map<String, String> getNameCodeMap(String dictCode) {
return dictCacheService.getTreeDictDetailByCode(dictCode).stream().collect(
Collectors.toMap(DictDetailDTO::getDictDetailName, DictDetailDTO::getDictDetailCode));
}
}