1. 增加字典数据的缓存与 util

2. 引入 Excel 组件
This commit is contained in:
YunaiV
2021-01-13 01:09:26 +08:00
parent ec00936532
commit fc444728c9
22 changed files with 277 additions and 98 deletions

View File

@ -0,0 +1,18 @@
package cn.iocoder.dashboard.framework.dict.config;
import cn.iocoder.dashboard.framework.dict.core.service.DictDataFrameworkService;
import cn.iocoder.dashboard.framework.dict.core.util.DictUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class DictConfiguration {
@Bean
@SuppressWarnings("InstantiationOfUtilityClass")
public DictUtils dictUtils(DictDataFrameworkService service) {
DictUtils.init(service);
return new DictUtils();
}
}

View File

@ -1,6 +1,7 @@
package cn.iocoder.dashboard.framework.dict.core.util;
import cn.iocoder.dashboard.framework.dict.core.service.DictDataFrameworkService;
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dict.SysDictDataDO;
import lombok.extern.slf4j.Slf4j;
/**
@ -16,4 +17,12 @@ public class DictUtils {
log.info("[init][初始化 DictUtils 成功]");
}
public static SysDictDataDO getDictDataFromCache(String type, String value) {
return service.getDictDataFromCache(type, value);
}
public static SysDictDataDO parseDictDataFromCache(String type, String label) {
return service.getDictDataFromCache(type, label);
}
}

View File

@ -11,6 +11,7 @@ import java.math.BigDecimal;
*
* @author ruoyi
*/
@Deprecated
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Excel {

View File

@ -10,6 +10,7 @@ import java.lang.annotation.Target;
*
* @author ruoyi
*/
@Deprecated
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Excels

View File

@ -0,0 +1,19 @@
package cn.iocoder.dashboard.framework.excel.core.annotations;
import cn.iocoder.dashboard.modules.system.enums.dict.DictTypeEnum;
import java.lang.annotation.*;
/**
* 字典格式化
*
* 实现将字典数据的值,格式化成字典数据的标签
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface DictFormat {
DictTypeEnum value();
}

View File

@ -0,0 +1,64 @@
package cn.iocoder.dashboard.framework.excel.core.convert;
import cn.hutool.core.convert.Convert;
import cn.iocoder.dashboard.framework.dict.core.util.DictUtils;
import cn.iocoder.dashboard.framework.excel.core.annotations.DictFormat;
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dict.SysDictDataDO;
import cn.iocoder.dashboard.modules.system.enums.dict.DictTypeEnum;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class DictConvert implements Converter<Object> {
@Override
public Class<?> supportJavaTypeKey() {
throw new UnsupportedOperationException("暂不支持,也不需要");
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
throw new UnsupportedOperationException("暂不支持,也不需要");
}
@Override
public Object convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
// 使用字典解析
DictTypeEnum type = getType(contentProperty);
String label = cellData.getStringValue();
SysDictDataDO dictData = DictUtils.parseDictDataFromCache(type.getValue(), label);
if (dictData == null) {
log.error("[convertToJavaData][type({}) 解析不掉 label({})]", type, label);
return null;
}
// 将 String 的 value 转换成对应的属性
Class<?> fieldClazz = contentProperty.getField().getType();
return Convert.convert(fieldClazz, dictData.getValue());
}
@Override
public CellData<String> convertToExcelData(Object object, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
// 使用字典格式化
DictTypeEnum type = getType(contentProperty);
String value = String.valueOf(object);
SysDictDataDO dictData = DictUtils.getDictDataFromCache(type.getValue(), value);
if (dictData == null) {
log.error("[convertToExcelData][type({}) 转换不了 label({})]", type, value);
return null;
}
// 生成 Excel 小表格
return new CellData<>(dictData.getValue());
}
private static DictTypeEnum getType(ExcelContentProperty contentProperty) {
return contentProperty.getField().getAnnotation(DictFormat.class).value();
}
}

View File

@ -0,0 +1 @@
package cn.iocoder.dashboard.framework.excel.core;

View File

@ -0,0 +1,4 @@
/**
* 基于 EasyExcel 实现 Excel 相关的操作
*/
package cn.iocoder.dashboard.framework.excel;

View File

@ -48,7 +48,7 @@ public class SysDeptController {
}
@ApiOperation("获得部门信息")
@ApiImplicitParam(name = "id", value = "编号", readOnly = true, example = "1024")
@ApiImplicitParam(name = "id", value = "编号", readOnly = true, example = "1024", dataTypeClass = Long.class)
// @PreAuthorize("@ss.hasPermi('system:dept:query')")
@GetMapping("/get")
public CommonResult<SysDeptRespVO> getDept(@RequestParam("id") Long id) {
@ -74,7 +74,7 @@ public class SysDeptController {
}
@ApiOperation("删除部门")
@ApiImplicitParam(name = "id", value = "编号", readOnly = true, example = "1024")
@ApiImplicitParam(name = "id", value = "编号", readOnly = true, example = "1024", dataTypeClass = Long.class)
@PostMapping("delete")
// @PreAuthorize("@ss.hasPermi('system:dept:remove')")
// @Log(title = "部门管理", businessType = BusinessType.DELETE)

View File

@ -73,7 +73,7 @@ public class SysPostController {
}
@ApiOperation("获得岗位信息")
@ApiImplicitParam(name = "id", value = "岗位编号", readOnly = true, example = "1024")
@ApiImplicitParam(name = "id", value = "岗位编号", readOnly = true, example = "1024", dataTypeClass = Long.class)
// @PreAuthorize("@ss.hasPermi('system:post:query')")
@GetMapping(value = "/get")
public CommonResult<SysPostRespVO> getPost(@RequestParam("id") Long id) {

View File

@ -41,7 +41,7 @@ public class SysDictDataController {
}
@ApiOperation("/查询字典数据详细")
@ApiImplicitParam(name = "id", value = "编号", readOnly = true, example = "1024")
@ApiImplicitParam(name = "id", value = "编号", readOnly = true, example = "1024", dataTypeClass = Long.class)
@GetMapping(value = "/get")
// @PreAuthorize("@ss.hasPermi('system:dict:query')")
public CommonResult<SysDictDataRespVO> getDictData(@RequestParam("id") Long id) {
@ -67,7 +67,7 @@ public class SysDictDataController {
}
@ApiOperation("删除字典数据")
@ApiImplicitParam(name = "id", value = "编号", readOnly = true, example = "1024")
@ApiImplicitParam(name = "id", value = "编号", readOnly = true, example = "1024", dataTypeClass = Long.class)
@PostMapping("/delete")
// @PreAuthorize("@ss.hasPermi('system:dict:remove')")
public CommonResult<Boolean> deleteDictData(Long id) {

View File

@ -33,7 +33,7 @@ public class SysDictTypeController {
}
@ApiOperation("/查询字典类型详细")
@ApiImplicitParam(name = "id", value = "编号", readOnly = true, example = "1024")
@ApiImplicitParam(name = "id", value = "编号", readOnly = true, example = "1024", dataTypeClass = Long.class)
@GetMapping(value = "/get")
// @PreAuthorize("@ss.hasPermi('system:dict:query')")
public CommonResult<SysDictTypeRespVO> getDictType(@RequestParam("id") Long id) {
@ -59,7 +59,7 @@ public class SysDictTypeController {
}
@ApiOperation("删除字典类型")
@ApiImplicitParam(name = "id", value = "编号", readOnly = true, example = "1024")
@ApiImplicitParam(name = "id", value = "编号", readOnly = true, example = "1024", dataTypeClass = Long.class)
@PostMapping("/delete")
// @PreAuthorize("@ss.hasPermi('system:dict:remove')")
public CommonResult<Boolean> deleteDictType(Long id) {

View File

@ -88,7 +88,7 @@ public class SysMenuController {
@ApiOperation("删除菜单")
@PostMapping("/delete")
@ApiImplicitParam(name = "id", value = "角色编号", required= true, example = "1024")
@ApiImplicitParam(name = "id", value = "角色编号", required= true, example = "1024", dataTypeClass = Long.class)
// @Log(title = "菜单管理", businessType = BusinessType.DELETE)
public CommonResult<Boolean> deleteMenu(@RequestParam("id") Long id) {
menuService.deleteMenu(id);

View File

@ -30,8 +30,8 @@ public class SysPermissionController {
private SysPermissionService permissionService;
@ApiOperation("获得角色拥有的菜单编号")
@ApiImplicitParam(name = "roleId", value = "角色编号", required = true, dataTypeClass = Long.class)
@GetMapping("/list-role-resources")
@ApiImplicitParam(name = "roleId", value = "角色编号", required = true)
// @RequiresPermissions("system:permission:assign-role-menu")
public CommonResult<Set<Long>> listRoleMenus(Long roleId) {
return success(permissionService.listRoleMenuIds(roleId));
@ -55,7 +55,7 @@ public class SysPermissionController {
}
@ApiOperation("获得管理员拥有的角色编号列表")
@ApiImplicitParam(name = "userId", value = "用户编号", required = true)
@ApiImplicitParam(name = "userId", value = "用户编号", required = true, dataTypeClass = Long.class)
@GetMapping("/list-user-roles")
// @RequiresPermissions("system:permission:assign-user-role")
public CommonResult<Set<Long>> listAdminRoles(@RequestParam("userId") Long userId) {

View File

@ -64,10 +64,10 @@ public class SysRoleController {
@ApiOperation("删除角色")
@PostMapping("/delete")
@ApiImplicitParam(name = "id", value = "角色编号", required = true, example = "1024")
@ApiImplicitParam(name = "id", value = "角色编号", required = true, example = "1024", dataTypeClass = Long.class)
// @PreAuthorize("@ss.hasPermi('system:role:remove')")
// @Log(title = "角色管理", businessType = BusinessType.DELETE)
public CommonResult<Boolean> remove(@RequestParam("id") Long id) {
public CommonResult<Boolean> deleteRole(@RequestParam("id") Long id) {
roleService.deleteRole(id);
return success(true);
}

View File

@ -63,7 +63,7 @@ public class SysUserController {
* 根据用户编号获取详细信息
*/
@ApiOperation("获得用户详情")
@ApiImplicitParam(name = "id", value = "编号", readOnly = true, example = "1024")
@ApiImplicitParam(name = "id", value = "编号", readOnly = true, example = "1024", dataTypeClass = Long.class)
@GetMapping("/get")
// @PreAuthorize("@ss.hasPermi('system:user:query')")
public CommonResult<SysUserRespVO> getInfo(@RequestParam("id") Long id) {
@ -89,7 +89,7 @@ public class SysUserController {
}
@ApiOperation("删除用户")
@ApiImplicitParam(name = "id", value = "编号", readOnly = true, example = "1024")
@ApiImplicitParam(name = "id", value = "编号", readOnly = true, example = "1024", dataTypeClass = Long.class)
@PostMapping("/delete")
// @PreAuthorize("@ss.hasPermi('system:user:remove')")
// @Log(title = "用户管理", businessType = BusinessType.DELETE)

View File

@ -11,20 +11,14 @@ import java.util.Date;
* 用户 Excel 导出响应 VO
*/
@Data
public class SysUserExcelRespVO {
public class SysUserExcelRespBackVO {
@Excel(name = "用户序号", cellType = Excel.ColumnType.NUMERIC, prompt = "用户编号")
private Long id;
/**
* 用户账号
*/
@Excel(name = "登录名称")
private String username;
/**
* 用户昵称
*/
@Excel(name = "用户名称")
private String nickname;

View File

@ -0,0 +1,54 @@
package cn.iocoder.dashboard.modules.system.controller.user.vo.user;
import cn.iocoder.dashboard.framework.excel.core.annotations.DictFormat;
import cn.iocoder.dashboard.framework.excel.core.convert.DictConvert;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
import java.util.Date;
import static cn.iocoder.dashboard.modules.system.enums.dict.DictTypeEnum.SYS_COMMON_STATUS;
import static cn.iocoder.dashboard.modules.system.enums.dict.DictTypeEnum.SYS_USER_SEX;
/**
* 用户 Excel 导出 VO
*/
@Data
public class SysUserExcelVO {
@ExcelProperty("用户编号")
private Long id;
@ExcelProperty("用户名称")
private String username;
@ExcelProperty("用户名称")
private String nickname;
@ExcelProperty("用户邮箱")
private String email;
@ExcelProperty("手机号码")
private String mobile;
@ExcelProperty(value = "用户性别", converter = DictConvert.class)
@DictFormat(SYS_USER_SEX)
private Integer sex;
@ExcelProperty(value = "帐号状态", converter = DictConvert.class)
@DictFormat(SYS_COMMON_STATUS)
private Integer status;
@ExcelProperty("最后登录IP")
private String loginIp;
@ExcelProperty("最后登录时间")
private Date loginDate;
@ExcelProperty("部门名称")
private String deptName;
@ExcelProperty("部门负责人")
private String deptLeader;
}

View File

@ -0,0 +1,23 @@
package cn.iocoder.dashboard.modules.system.enums.dict;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 字典类型的类型枚举
*/
@Getter
@AllArgsConstructor
public enum DictTypeEnum {
SYS_USER_SEX("sys_user_sex"), // 用户性别
SYS_COMMON_STATUS("sys_common_status"), // 系统状态
;
/**
* 值
*/
private final String value;
}

View File

@ -1,6 +1,7 @@
package cn.iocoder.dashboard.modules.system.service.dict;
import cn.iocoder.dashboard.common.pojo.PageResult;
import cn.iocoder.dashboard.framework.dict.core.service.DictDataFrameworkService;
import cn.iocoder.dashboard.modules.system.controller.dict.vo.data.SysDictDataCreateReqVO;
import cn.iocoder.dashboard.modules.system.controller.dict.vo.data.SysDictDataPageReqVO;
import cn.iocoder.dashboard.modules.system.controller.dict.vo.data.SysDictDataUpdateReqVO;
@ -13,8 +14,18 @@ import java.util.List;
*
* @author ruoyi
*/
public interface SysDictDataService {
public interface SysDictDataService extends DictDataFrameworkService {
/**
* 初始化,主要是初始化缓存
*/
void init();
/**
* 获得字典数据列表
*
* @return 字典数据全列表
*/
List<SysDictDataDO> listDictDatas();
/**

View File

@ -12,9 +12,11 @@ import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dict.SysDictData
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dict.SysDictTypeDO;
import cn.iocoder.dashboard.modules.system.service.dict.SysDictDataService;
import cn.iocoder.dashboard.modules.system.service.dict.SysDictTypeService;
import com.google.common.collect.ImmutableTable;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
@ -32,12 +34,42 @@ public class SysDictDataServiceImpl implements SysDictDataService {
.comparing(SysDictDataDO::getDictType)
.thenComparingInt(SysDictDataDO::getSort);
/**
* 字典数据缓存,第二个 key 使用 label
*
* key1字典类型 dictType
* key2字典标签 label
*/
private ImmutableTable<String, String, SysDictDataDO> labelDictDataCache;
/**
* 字典数据缓存,第二个 key 使用 value
*
* key1字典类型 dictType
* key2字典值 value
*/
private ImmutableTable<String, String, SysDictDataDO> valueDictDataCache;
@Resource
private SysDictTypeService dictTypeService;
@Resource
private SysDictDataMapper dictDataMapper;
@Override
public void init() {
// 获得字典数据
List<SysDictDataDO> list = this.listDictDatas();
// 构建缓存
ImmutableTable.Builder<String, String, SysDictDataDO> labelDictDataBuilder = ImmutableTable.builder();
ImmutableTable.Builder<String, String, SysDictDataDO> valueDictDataBuilder = ImmutableTable.builder();
list.forEach(dictData -> {
labelDictDataBuilder.put(dictData.getDictType(), dictData.getLabel(), dictData);
valueDictDataBuilder.put(dictData.getDictType(), dictData.getValue(), dictData);
});
labelDictDataCache = labelDictDataBuilder.build();
valueDictDataCache = valueDictDataBuilder.build();
}
@Override
public List<SysDictDataDO> listDictDatas() {
List<SysDictDataDO> list = dictDataMapper.selectList();
@ -130,4 +162,19 @@ public class SysDictDataServiceImpl implements SysDictDataService {
}
}
@Override
public SysDictDataDO getDictDataFromCache(String type, String value) {
return valueDictDataCache.get(type, value);
}
@Override
public SysDictDataDO parseDictDataFromCache(String type, String label) {
return labelDictDataCache.get(type, label);
}
@Override
public List<SysDictDataDO> listDictDatasFromCache(String type) {
return new ArrayList<>(labelDictDataCache.row(type).values());
}
}