refactor: 系统功能重构

This commit is contained in:
hxr
2024-06-24 08:15:46 +08:00
parent 5a6ae48bcd
commit 7d1fcfbef4
71 changed files with 900 additions and 1048 deletions

View File

@@ -2,11 +2,12 @@ package com.youlai.system.common.exception;
import com.youlai.system.common.result.IResultCode;
import lombok.Getter;
import org.slf4j.helpers.MessageFormatter;
/**
* 自定义业务异常
*
* @author haoxr
* @author Ray
* @since 2022/7/31
*/
@Getter
@@ -19,17 +20,19 @@ public class BusinessException extends RuntimeException {
this.resultCode = errorCode;
}
public BusinessException(String message){
super(message);
}
public BusinessException(String message, Throwable cause){
public BusinessException(String message, Throwable cause) {
super(message, cause);
}
public BusinessException(Throwable cause){
public BusinessException(Throwable cause) {
super(cause);
}
public BusinessException(String message, Object... args) {
super(formatMessage(message, args));
}
private static String formatMessage(String message, Object... args) {
return MessageFormatter.arrayFormat(message, args).getMessage();
}
}

View File

@@ -1,6 +1,6 @@
package com.youlai.system.controller;
import com.youlai.system.plugin.dupsubmit.annotation.PreventDuplicateSubmit;
import com.youlai.system.plugin.norepeat.annotation.PreventRepeatSubmit;
import com.youlai.system.common.model.Option;
import com.youlai.system.common.result.Result;
import com.youlai.system.model.form.DeptForm;
@@ -11,7 +11,6 @@ import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
@@ -29,23 +28,36 @@ import java.util.List;
@RequestMapping("/api/v1/dept")
@RequiredArgsConstructor
public class SysDeptController {
private final SysDeptService deptService;
@Operation(summary = "获取部门列表")
@GetMapping
public Result<List<DeptVO>> listDepartments(
@ParameterObject DeptQuery queryParams
public Result<List<DeptVO>> getDeptList(
DeptQuery queryParams
) {
List<DeptVO> list = deptService.listDepartments(queryParams);
List<DeptVO> list = deptService.getDeptList(queryParams);
return Result.success(list);
}
@Operation(summary = "获取部门下拉选项")
@GetMapping("/options")
public Result<List<Option>> listDeptOptions() {
public Result<List<Option>> getDeptOptions() {
List<Option> list = deptService.listDeptOptions();
return Result.success(list);
}
@Operation(summary = "新增部门")
@PostMapping
@PreAuthorize("@ss.hasPerm('sys:dept:add')")
@PreventRepeatSubmit
public Result saveDept(
@Valid @RequestBody DeptForm formData
) {
Long id = deptService.saveDept(formData);
return Result.success(id);
}
@Operation(summary = "获取部门表单数据")
@GetMapping("/{deptId}/form")
public Result<DeptForm> getDeptForm(
@@ -55,17 +67,6 @@ public class SysDeptController {
return Result.success(deptForm);
}
@Operation(summary = "新增部门")
@PostMapping
@PreAuthorize("@ss.hasPerm('sys:dept:add')")
@PreventDuplicateSubmit
public Result saveDept(
@Valid @RequestBody DeptForm formData
) {
Long id = deptService.saveDept(formData);
return Result.success(id);
}
@Operation(summary = "修改部门")
@PutMapping(value = "/{deptId}")
@PreAuthorize("@ss.hasPerm('sys:dept:edit')")

View File

@@ -3,26 +3,24 @@ package com.youlai.system.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.youlai.system.common.result.PageResult;
import com.youlai.system.common.result.Result;
import com.youlai.system.plugin.dupsubmit.annotation.PreventDuplicateSubmit;
import com.youlai.system.model.form.DictForm;
import com.youlai.system.model.form.DictTypeForm;
import com.youlai.system.model.query.DictPageQuery;
import com.youlai.system.model.query.DictTypePageQuery;
import com.youlai.system.model.vo.DictPageVO;
import com.youlai.system.model.vo.DictTypePageVO;
import com.youlai.system.common.model.Option;
import com.youlai.system.plugin.norepeat.annotation.PreventRepeatSubmit;
import com.youlai.system.model.form.DictForm;
import com.youlai.system.model.query.DictTypePageQuery;
import com.youlai.system.service.SysDictService;
import com.youlai.system.service.SysDictTypeService;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 字典控制层
*
* @author Ray Hao
* @since 2.9.0
*/
@Tag(name = "06.字典接口")
@RestController
@RequestMapping("/api/v1/dict")
@@ -31,21 +29,19 @@ public class SysDictController {
private final SysDictService dictService;
private final SysDictTypeService dictTypeService;
@Operation(summary = "字典分页列表")
@GetMapping("/page")
public PageResult<DictPageVO> getDictPage(
@ParameterObject DictPageQuery queryParams
DictTypePageQuery queryParams
) {
Page<DictPageVO> result = dictService.getDictPage(queryParams);
return PageResult.success(result);
}
@Operation(summary = "字典数据表单数据")
@Operation(summary = "字典表单")
@GetMapping("/{id}/form")
public Result<DictForm> getDictForm(
@Parameter(description ="字典ID") @PathVariable Long id
@Parameter(description = "字典ID") @PathVariable Long id
) {
DictForm formData = dictService.getDictForm(id);
return Result.success(formData);
@@ -54,11 +50,9 @@ public class SysDictController {
@Operation(summary = "新增字典")
@PostMapping
@PreAuthorize("@ss.hasPerm('sys:dict:add')")
@PreventDuplicateSubmit
public Result saveDict(
@RequestBody DictForm DictForm
) {
boolean result = dictService.saveDict(DictForm);
@PreventRepeatSubmit
public Result saveDict(@RequestBody DictForm formData) {
boolean result = dictService.saveDict(formData);
return Result.judge(result);
}
@@ -76,70 +70,12 @@ public class SysDictController {
@Operation(summary = "删除字典")
@DeleteMapping("/{ids}")
@PreAuthorize("@ss.hasPerm('sys:dict:delete')")
public Result deleteDict(
@Parameter(description ="字典ID多个以英文逗号(,)拼接") @PathVariable String ids
public Result deleteDictionaries(
@Parameter(description = "字典ID多个以英文逗号(,)拼接") @PathVariable String ids
) {
boolean result = dictService.deleteDict(ids);
return Result.judge(result);
dictService.deleteDictByIds(ids);
return Result.success();
}
@Operation(summary = "字典下拉列表")
@GetMapping("/{typeCode}/options")
public Result<List<Option>> listDictOptions(
@Parameter(description ="字典类型编码") @PathVariable String typeCode
) {
List<Option> list = dictService.listDictOptions(typeCode);
return Result.success(list);
}
/*----------------------------------------------------*/
@Operation(summary = "字典类型分页列表")
@GetMapping("/types/page")
public PageResult<DictTypePageVO> getDictTypePage(
@ParameterObject DictTypePageQuery queryParams
) {
Page<DictTypePageVO> result = dictTypeService.getDictTypePage(queryParams);
return PageResult.success(result);
}
@Operation(summary = "字典类型表单数据")
@GetMapping("/types/{id}/form")
public Result<DictTypeForm> getDictTypeForm(
@Parameter(description ="字典ID") @PathVariable Long id
) {
DictTypeForm dictTypeForm = dictTypeService.getDictTypeForm(id);
return Result.success(dictTypeForm);
}
@Operation(summary = "新增字典类型")
@PostMapping("/types")
@PreAuthorize("@ss.hasPerm('sys:dict_type:add')")
@PreventDuplicateSubmit
public Result saveDictType(@RequestBody DictTypeForm dictTypeForm) {
boolean result = dictTypeService.saveDictType(dictTypeForm);
return Result.judge(result);
}
@Operation(summary = "修改字典类型")
@PutMapping("/types/{id}")
@PreAuthorize("@ss.hasPerm('sys:dict_type:edit')")
public Result updateDictType(@PathVariable Long id, @RequestBody DictTypeForm dictTypeForm) {
boolean status = dictTypeService.updateDictType(id, dictTypeForm);
return Result.judge(status);
}
@Operation(summary = "删除字典类型")
@DeleteMapping("/types/{ids}")
@PreAuthorize("@ss.hasPerm('sys:dict_type:delete')")
public Result deleteDictTypes(
@Parameter(description ="字典类型ID多个以英文逗号(,)分割") @PathVariable String ids
) {
boolean result = dictTypeService.deleteDictTypes(ids);
return Result.judge(result);
}
}

View File

@@ -1,7 +1,7 @@
package com.youlai.system.controller;
import com.youlai.system.common.result.Result;
import com.youlai.system.plugin.dupsubmit.annotation.PreventDuplicateSubmit;
import com.youlai.system.plugin.norepeat.annotation.PreventRepeatSubmit;
import com.youlai.system.model.form.MenuForm;
import com.youlai.system.model.query.MenuQuery;
import com.youlai.system.model.vo.MenuVO;
@@ -10,12 +10,9 @@ import com.youlai.system.model.vo.RouteVO;
import com.youlai.system.service.SysMenuService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
@@ -38,7 +35,7 @@ public class SysMenuController {
@Operation(summary = "菜单列表")
@GetMapping
public Result<List<MenuVO>> listMenus( @ParameterObject MenuQuery queryParams) {
public Result<List<MenuVO>> listMenus(MenuQuery queryParams) {
List<MenuVO> menuList = menuService.listMenus(queryParams);
return Result.success(menuList);
}
@@ -60,7 +57,7 @@ public class SysMenuController {
@Operation(summary = "菜单表单数据")
@GetMapping("/{id}/form")
public Result<MenuForm> getMenuForm(
@Parameter(description = "菜单ID") @PathVariable Long id
@Parameter(description = "菜单ID") @PathVariable Long id
) {
MenuForm menu = menuService.getMenuForm(id);
return Result.success(menu);
@@ -69,7 +66,7 @@ public class SysMenuController {
@Operation(summary = "新增菜单")
@PostMapping
@PreAuthorize("@ss.hasPerm('sys:menu:add')")
@PreventDuplicateSubmit
@PreventRepeatSubmit
public Result addMenu(@RequestBody MenuForm menuForm) {
boolean result = menuService.saveMenu(menuForm);
return Result.judge(result);
@@ -89,7 +86,7 @@ public class SysMenuController {
@DeleteMapping("/{id}")
@PreAuthorize("@ss.hasPerm('sys:menu:delete')")
public Result deleteMenu(
@Parameter(description ="菜单ID多个以英文(,)分割") @PathVariable("id") Long id
@Parameter(description = "菜单ID多个以英文(,)分割") @PathVariable("id") Long id
) {
boolean result = menuService.deleteMenu(id);
return Result.judge(result);
@@ -98,11 +95,11 @@ public class SysMenuController {
@Operation(summary = "修改菜单显示状态")
@PatchMapping("/{menuId}")
public Result updateMenuVisible(
@Parameter(description = "菜单ID") @PathVariable Long menuId,
@Parameter(description = "显示状态(1:显示;0:隐藏)") Integer visible
@Parameter(description = "菜单ID") @PathVariable Long menuId,
@Parameter(description = "显示状态(1:显示;0:隐藏)") Integer visible
) {
boolean result =menuService.updateMenuVisible(menuId, visible);
boolean result = menuService.updateMenuVisible(menuId, visible);
return Result.judge(result);
}

View File

@@ -1,7 +1,7 @@
package com.youlai.system.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.youlai.system.plugin.dupsubmit.annotation.PreventDuplicateSubmit;
import com.youlai.system.plugin.norepeat.annotation.PreventRepeatSubmit;
import com.youlai.system.common.model.Option;
import com.youlai.system.common.result.PageResult;
import com.youlai.system.common.result.Result;
@@ -13,7 +13,6 @@ import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
@@ -32,7 +31,7 @@ public class SysRoleController {
@Operation(summary = "角色分页列表")
@GetMapping("/page")
public PageResult<RolePageVO> getRolePage(
@ParameterObject RolePageQuery queryParams
RolePageQuery queryParams
) {
Page<RolePageVO> result = roleService.getRolePage(queryParams);
return PageResult.success(result);
@@ -48,7 +47,7 @@ public class SysRoleController {
@Operation(summary = "新增角色")
@PostMapping
@PreAuthorize("@ss.hasPerm('sys:role:add')")
@PreventDuplicateSubmit
@PreventRepeatSubmit
public Result addRole(@Valid @RequestBody RoleForm roleForm) {
boolean result = roleService.saveRole(roleForm);
return Result.judge(result);

View File

@@ -7,13 +7,13 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
import com.youlai.system.common.result.PageResult;
import com.youlai.system.common.result.Result;
import com.youlai.system.common.util.ExcelUtils;
import com.youlai.system.plugin.dupsubmit.annotation.PreventDuplicateSubmit;
import com.youlai.system.model.dto.UserImportDTO;
import com.youlai.system.plugin.norepeat.annotation.PreventRepeatSubmit;
import com.youlai.system.plugin.easyexcel.UserImportListener;
import com.youlai.system.model.vo.UserImportVO;
import com.youlai.system.model.form.UserForm;
import com.youlai.system.model.entity.SysUser;
import com.youlai.system.model.query.UserPageQuery;
import com.youlai.system.model.vo.UserExportVO;
import com.youlai.system.model.dto.UserExportDTO;
import com.youlai.system.model.vo.UserInfoVO;
import com.youlai.system.model.vo.UserPageVO;
import com.youlai.system.service.SysUserService;
@@ -21,7 +21,6 @@ import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@@ -54,7 +53,7 @@ public class SysUserController {
@Operation(summary = "用户分页列表")
@GetMapping("/page")
public PageResult<UserPageVO> listPagedUsers(
@ParameterObject UserPageQuery queryParams
UserPageQuery queryParams
) {
IPage<UserPageVO> result = userService.listPagedUsers(queryParams);
return PageResult.success(result);
@@ -63,7 +62,7 @@ public class SysUserController {
@Operation(summary = "新增用户")
@PostMapping
@PreAuthorize("@ss.hasPerm('sys:user:add')")
@PreventDuplicateSubmit
@PreventRepeatSubmit
public Result saveUser(
@RequestBody @Valid UserForm userForm
) {
@@ -149,9 +148,9 @@ public class SysUserController {
@Operation(summary = "导入用户")
@PostMapping("/import")
public Result importUsers(@Parameter(description = "部门ID") Long deptId, MultipartFile file) throws IOException {
UserImportListener listener = new UserImportListener(deptId);
String msg = ExcelUtils.importExcel(file.getInputStream(), UserImportVO.class, listener);
public Result importUsers( MultipartFile file) throws IOException {
UserImportListener listener = new UserImportListener();
String msg = ExcelUtils.importExcel(file.getInputStream(), UserImportDTO.class, listener);
return Result.success(msg);
}
@@ -162,8 +161,8 @@ public class SysUserController {
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
List<UserExportVO> exportUserList = userService.listExportUsers(queryParams);
EasyExcel.write(response.getOutputStream(), UserExportVO.class).sheet("用户列表")
List<UserExportDTO> exportUserList = userService.listExportUsers(queryParams);
EasyExcel.write(response.getOutputStream(), UserExportDTO.class).sheet("用户列表")
.doWrite(exportUserList);
}
}

View File

@@ -14,9 +14,10 @@ import org.mapstruct.Mapper;
@Mapper(componentModel = "spring")
public interface DeptConverter {
DeptForm entity2Form(SysDept entity);
DeptVO entity2Vo(SysDept entity);
DeptForm convertToForm(SysDept entity);
DeptVO convertToVo(SysDept entity);
SysDept form2Entity(DeptForm deptForm);
SysDept convertToEntity(DeptForm deptForm);
}

View File

@@ -4,22 +4,20 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.youlai.system.model.entity.SysDict;
import com.youlai.system.model.form.DictForm;
import com.youlai.system.model.vo.DictPageVO;
import org.mapstruct.InheritInverseConfiguration;
import org.mapstruct.Mapper;
/**
* 字典数据项对象转换器
* 字典 对象转换器
*
* @author haoxr
* @author Ray Hao
* @since 2022/6/8
*/
@Mapper(componentModel = "spring")
public interface DictConverter {
Page<DictPageVO> entity2Page(Page<SysDict> page);
Page<DictPageVO> convertToPageVo(Page<SysDict> page);
DictForm entity2Form(SysDict entity);
DictForm convertToForm(SysDict entity);
@InheritInverseConfiguration(name="entity2Form")
SysDict form2Entity(DictForm entity);
SysDict convertToEntity(DictForm entity);
}

View File

@@ -0,0 +1,40 @@
package com.youlai.system.converter;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.youlai.system.common.model.Option;
import com.youlai.system.model.entity.SysDictItem;
import com.youlai.system.model.form.DictForm;
import com.youlai.system.model.vo.DictPageVO;
import org.mapstruct.InheritInverseConfiguration;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import java.util.List;
/**
* 字典项 对象转换器
*
* @author Ray
* @since 2022/6/8
*/
@Mapper(componentModel = "spring")
public interface DictItemConverter {
Page<DictPageVO> convertToPageVo(Page<SysDictItem> page);
DictForm convertToForm(SysDictItem entity);
SysDictItem convertToEntity(DictForm.DictItem dictFormDictItems);
List<SysDictItem> convertToEntity(List<DictForm.DictItem> dictFormDictItems);
DictForm.DictItem convertToDictFormDictItem(SysDictItem entity);
List<DictForm.DictItem> convertToDictFormDictItem(List<SysDictItem> entities);
@Mappings({
@Mapping(target = "value", source = "id"),
@Mapping(target = "label", source = "name")
})
Option convertToOption(SysDictItem dictItem);
List<Option> convertToOption(List<SysDictItem> dictItems);
}

View File

@@ -1,23 +0,0 @@
package com.youlai.system.converter;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.youlai.system.model.entity.SysDictType;
import com.youlai.system.model.form.DictTypeForm;
import com.youlai.system.model.vo.DictTypePageVO;
import org.mapstruct.Mapper;
/**
* 字典类型对象转换器
*
* @author haoxr
* @since 2022/6/8
*/
@Mapper(componentModel = "spring")
public interface DictTypeConverter {
Page<DictTypePageVO> entity2Page(Page<SysDictType> page);
DictTypeForm entity2Form(SysDictType entity);
SysDictType form2Entity(DictTypeForm entity);
}

View File

@@ -15,7 +15,7 @@ import org.mapstruct.Mapping;
@Mapper(componentModel = "spring")
public interface MenuConverter {
MenuVO entity2Vo(SysMenu entity);
MenuVO convertToVo(SysMenu entity);
@Mapping(target = "params", ignore = true)
MenuForm convertToForm(SysMenu entity);

View File

@@ -20,7 +20,7 @@ import java.util.List;
@Mapper(componentModel = "spring")
public interface RoleConverter {
Page<RolePageVO> entity2Page(Page<SysRole> page);
Page<RolePageVO> convertToPageVo(Page<SysRole> page);
@Mappings({
@Mapping(target = "value", source = "id"),
@@ -31,7 +31,7 @@ public interface RoleConverter {
List<Option> entities2Options(List<SysRole> roles);
SysRole form2Entity(RoleForm roleForm);
SysRole convertToEntity(RoleForm roleForm);
RoleForm entity2Form(SysRole entity);
RoleForm convertToForm(SysRole entity);
}

View File

@@ -4,7 +4,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.youlai.system.model.bo.UserBO;
import com.youlai.system.model.entity.SysUser;
import com.youlai.system.model.form.UserForm;
import com.youlai.system.model.vo.UserImportVO;
import com.youlai.system.model.dto.UserImportDTO;
import com.youlai.system.model.vo.UserInfoVO;
import com.youlai.system.model.vo.UserPageVO;
import org.mapstruct.InheritInverseConfiguration;
@@ -28,16 +28,16 @@ public interface UserConverter {
Page<UserPageVO> bo2PageVo(Page<UserBO> bo);
UserForm entity2Form(SysUser entity);
UserForm convertToForm(SysUser entity);
@InheritInverseConfiguration(name = "entity2Form")
SysUser form2Entity(UserForm entity);
@InheritInverseConfiguration(name = "convertToForm")
SysUser convertToEntity(UserForm entity);
@Mappings({
@Mapping(target = "userId", source = "id")
})
UserInfoVO toUserInfoVo(SysUser entity);
SysUser importVo2Entity(UserImportVO vo);
SysUser convertToEntity(UserImportDTO vo);
}

View File

@@ -0,0 +1,20 @@
package com.youlai.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.youlai.system.model.entity.SysDictItem;
import org.apache.ibatis.annotations.Mapper;
/**
* 字典项 访问层
*
* @author Ray Hao
* @since 2.9.0
*/
@Mapper
public interface SysDictItemMapper extends BaseMapper<SysDictItem> {
}

View File

@@ -1,12 +1,29 @@
package com.youlai.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.youlai.system.model.entity.SysDict;
import com.youlai.system.model.query.DictTypePageQuery;
import com.youlai.system.model.vo.DictPageVO;
import org.apache.ibatis.annotations.Mapper;
/**
* 字典 访问层
*
* @author Ray Hao
* @since 2.9.0
*/
@Mapper
public interface SysDictMapper extends BaseMapper<SysDict> {
/**
* 字典分页列表
*
* @param page 分页参数
* @param queryParams 查询参数
* @return
*/
Page<DictPageVO> getDictPage(Page<DictPageVO> page, DictTypePageQuery queryParams);
}

View File

@@ -1,14 +0,0 @@
package com.youlai.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.youlai.system.model.entity.SysDictType;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface SysDictTypeMapper extends BaseMapper<SysDictType> {
}

View File

@@ -20,11 +20,4 @@ public interface SysMenuMapper extends BaseMapper<SysMenu> {
List<RouteBO> listRoutes();
/**
* 获取角色权限集合
*
* @param roles
* @return
*/
Set<String> listRolePerms(Set<String> roles);
}

View File

@@ -6,6 +6,7 @@ import com.youlai.system.model.entity.SysRoleMenu;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
import java.util.Set;
/**
* 角色菜单访问层
@@ -28,4 +29,13 @@ public interface SysRoleMenuMapper extends BaseMapper<SysRoleMenu> {
* 获取权限和拥有权限的角色列表
*/
List<RolePermsBO> getRolePermsList(String roleCode);
/**
* 获取角色权限集合
*
* @param roles
* @return
*/
Set<String> listRolePerms(Set<String> roles);
}

View File

@@ -8,7 +8,7 @@ import com.youlai.system.model.bo.UserBO;
import com.youlai.system.model.entity.SysUser;
import com.youlai.system.model.dto.UserAuthInfo;
import com.youlai.system.model.query.UserPageQuery;
import com.youlai.system.model.vo.UserExportVO;
import com.youlai.system.model.dto.UserExportDTO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@@ -55,5 +55,5 @@ public interface SysUserMapper extends BaseMapper<SysUser> {
* @return
*/
@DataPermission(deptAlias = "u")
List<UserExportVO> listExportUsers(UserPageQuery queryParams);
List<UserExportDTO> listExportUsers(UserPageQuery queryParams);
}

View File

@@ -24,14 +24,19 @@ public class RouteBO {
private String name;
/**
* 菜单类型(1-菜单2-目录3-外链4-按钮权限)
* 菜单类型(1-菜单 2-目录 3-外链 4-按钮)
*/
private MenuTypeEnum type;
/**
* 路由路径(浏览器地址栏路径)
* 路由名称Vue Router 中定义的路由名称)
*/
private String path;
private String routeName;
/**
* 路由路径Vue Router 中定义的 URL 路径)
*/
private String routePath;
/**
* 组件路径(vue页面完整路径省略.vue后缀)

View File

@@ -1,66 +0,0 @@
package com.youlai.system.model.bo;
import lombok.Data;
import java.util.List;
/**
* user表单持久化对象
*
* @author haoxr
* @since 2022/6/10
*/
@Data
public class UserFormBO {
/**
* 用户ID
*/
private Long id;
/**
* 用户名
*/
private String username;
/**
* 用户昵称
*/
private String nickname;
/**
* 手机号
*/
private String mobile;
/**
* 性别(1:男;2:女)
*/
private Integer gender;
/**
* 用户头像
*/
private String avatar;
/**
* 用户邮箱
*/
private String email;
/**
* 状态(1:启用;0:禁用)
*/
private Integer status;
/**
* 部门ID
*/
private Long deptId;
/**
* 角色ID集合
*/
private List<Long> roleIds;
}

View File

@@ -9,17 +9,17 @@ import lombok.NoArgsConstructor;
/**
* 验证码响应对象
*
* @author haoxr
* @author Ray Hao
* @since 2023/03/24
*/
@Schema(description ="验证码响应对象")
@Schema(description = "验证码响应对象")
@Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CaptchaResult {
@Schema(description = "验证码缓存key")
@Schema(description = "验证码ID")
private String captchaKey;
@Schema(description = "验证码图片Base64字符串")

View File

@@ -1,4 +1,4 @@
package com.youlai.system.model.vo;
package com.youlai.system.model.dto;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
@@ -16,7 +16,7 @@ import java.time.LocalDateTime;
@Data
@ColumnWidth(20)
public class UserExportVO {
public class UserExportDTO {
@ExcelProperty(value = "用户名")
private String username;

View File

@@ -1,4 +1,4 @@
package com.youlai.system.model.vo;
package com.youlai.system.model.dto;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
@@ -10,7 +10,7 @@ import lombok.Data;
* @since 2022/4/10
*/
@Data
public class UserImportVO {
public class UserImportDTO {
@ExcelProperty(value = "用户名")
private String username;
@@ -30,4 +30,7 @@ public class UserImportVO {
@ExcelProperty("角色")
private String roleCodes;
@ExcelProperty("部门")
private String deptCode;
}

View File

@@ -4,12 +4,17 @@ import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.youlai.system.common.base.BaseEntity;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
/**
* 部门
* 部门 实体
*
* @author Ray
* @since 2024/06/23
*/
@Data
@Getter
@Setter
public class SysDept extends BaseEntity {
/**
* 主键
@@ -22,6 +27,11 @@ public class SysDept extends BaseEntity {
*/
private String name;
/**
* 部门编码
*/
private String code;
/**
* 父节点id
*/
@@ -38,17 +48,18 @@ public class SysDept extends BaseEntity {
private Integer sort;
/**
* 状态(1:正常;0:禁用)
* 状态(1-正常 0-禁用)
*/
private Integer status;
/**
* 逻辑删除标识(1:已删除;0:未删除)
* 创建人 ID
*/
private Integer deleted;
private Long createBy;
/**
* 更新人 ID
*/
private Long updateBy;
}

View File

@@ -1,63 +1,42 @@
package com.youlai.system.model.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import com.youlai.system.common.base.BaseEntity;
import lombok.Data;
/**
* 字典数据表
* 字典实体
*
* @author haoxr
* @since 2022/12/17
*/
@Data
public class SysDict implements Serializable {
public class SysDict extends BaseEntity {
/**
* 主键
* 主键
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 字典类型编码
*/
private String typeCode;
/**
* 字典项名称
* 类型名称
*/
private String name;
/**
* 字典项值
* 类型编码
*/
private String value;
private String code;
/**
* 排序
*/
private Integer sort;
/**
* 状态(1:正常;0:禁用)
* 状态(0:正常;1:禁用)
*/
private Integer status;
/**
* 是否默认(1:是;0:否)
*/
private Integer defaulted;
/**
* 备注
*/
private String remark;
@TableField(exist = false)
private static final long serialVersionUID = 1L;
}

View File

@@ -2,35 +2,47 @@ package com.youlai.system.model.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.youlai.system.common.base.BaseEntity;
import java.io.Serializable;
import lombok.Data;
/**
* 字典类型实体
* 字典实体
*
* @author haoxr
* @since 2022/12/17
*/
@Data
public class SysDictType extends BaseEntity {
public class SysDictItem implements Serializable {
/**
* 主键
* 主键
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 类型名称
* 字典类ID
*/
private Long dictId;
/**
* 字典项名称
*/
private String name;
/**
* 类型编码
* 字典项值
*/
private String code;
private String value;
/**
* 状态(0:正常;1:禁用)
* 排序
*/
private Integer sort;
/**
* 状态1-正常0-禁用
*/
private Integer status;

View File

@@ -2,19 +2,21 @@ package com.youlai.system.model.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.youlai.system.common.base.BaseEntity;
import com.youlai.system.common.enums.MenuTypeEnum;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import java.time.LocalDateTime;
/**
* 菜单实体对象
* 菜单 实体
*
* @author haoxr
* @author Ray
* @since 2023/3/6
*/
@TableName(value ="sys_menu")
@Data
public class SysMenu extends BaseEntity {
@Getter
@Setter
public class SysMenu {
/**
* 菜单ID
*/
@@ -37,9 +39,14 @@ public class SysMenu extends BaseEntity {
private MenuTypeEnum type;
/**
* 路由路径(浏览器地址栏路径)
* 路由名称Vue Router 中定义的路由名称)
*/
private String path;
private String routeName;
/**
* 路由路径Vue Router 中定义的 URL 路径)
*/
private String routePath;
/**
* 组件路径(vue页面完整路径省略.vue后缀)
@@ -92,4 +99,14 @@ public class SysMenu extends BaseEntity {
@TableField(updateStrategy = FieldStrategy.ALWAYS)
private String params;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
/**
* 更新时间
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
}

View File

@@ -2,18 +2,21 @@ package com.youlai.system.model.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.youlai.system.common.base.BaseEntity;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
/**
* 角色
* 角色 实体
*
* @author Ray
* @since 2024/6/23
*/
@TableName(value ="sys_role")
@Data
@Getter
@Setter
public class SysRole extends BaseEntity {
/**
*
* 主键
*/
@TableId(type = IdType.AUTO)
private Long id;
@@ -34,17 +37,22 @@ public class SysRole extends BaseEntity {
private Integer sort;
/**
* 角色状态(1-正常0-停用)
* 角色状态(1-正常 0-停用)
*/
private Integer status;
/**
* 逻辑删除标识(0-未删除1-已删除)
*/
private Integer deleted;
/**
* 数据权限
*/
private Integer dataScope;
/**
* 创建人 ID
*/
private Long createBy;
/**
* 更新人 ID
*/
private Long updateBy;
}

View File

@@ -3,15 +3,17 @@ package com.youlai.system.model.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.youlai.system.common.base.BaseEntity;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
/**
* 用户
* 用户 实体
*/
@Data
@Getter
@Setter
public class SysUser extends BaseEntity {
/**
*
* 用户 ID
*/
@TableId(type = IdType.AUTO)
private Long id;
@@ -27,7 +29,7 @@ public class SysUser extends BaseEntity {
private String nickname;
/**
* 性别((1:男;2:女))
* 性别((1-男 2-女 0-保密)
*/
private Integer gender;
@@ -52,7 +54,7 @@ public class SysUser extends BaseEntity {
private String mobile;
/**
* 用户状态((1:正常;0:禁用))
* 状态((1-正常 0-禁用)
*/
private Integer status;
@@ -62,8 +64,12 @@ public class SysUser extends BaseEntity {
private String email;
/**
* 逻辑删除标识(0:未删除;1:已删除)
* 创建人 ID
*/
private Integer deleted;
private Long createBy;
/**
* 更新人 ID
*/
private Long updateBy;
}

View File

@@ -2,26 +2,31 @@ package com.youlai.system.model.form;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
@Schema(description = "部门表单对象")
@Data
@Getter
@Setter
public class DeptForm {
@Schema(description="部门ID")
@Schema(description="部门ID", example = "1001")
private Long id;
@Schema(description="部门名称")
@Schema(description="部门名称", example = "研发部")
private String name;
@Schema(description="部门ID")
@Schema(description="部门编号", example = "RD001")
private String code;
@Schema(description="父部门ID", example = "1000")
@NotNull(message = "父部门ID不能为空")
private Long parentId;
@Schema(description="状态(1:启用;0:禁用)")
@Schema(description="状态(1:启用;0:禁用)", example = "1")
private Integer status;
@Schema(description="排序(数字越小排名越靠前)")
@Schema(description="排序(数字越小排名越靠前)", example = "1")
private Integer sort;
}

View File

@@ -3,30 +3,57 @@ package com.youlai.system.model.form;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
@Schema(description = "字典表单对象")
import java.util.List;
/**
* 字典表单对象
*
* @author Ray Hao
* @since 2.9.0
*/
@Schema(description = "字典")
@Data
public class DictForm {
@Schema(description="字典ID")
@Schema(description = "字典ID",example = "1")
private Long id;
@Schema(description="类型编码")
private String typeCode;
@Schema(description="字典名称")
@Schema(description = "字典名称",example = "性别")
private String name;
@Schema(description="字典值")
private String value;
@Schema(description = "字典编码", example ="gender")
private String code;
@Schema(description="状态(1:启用;0:禁用)")
@Schema(description = "字典状态1-启用0-禁用)", example = "1")
private Integer status;
@Schema(description="排序")
private Integer sort;
@Schema(description = "字典数据项列表",example = "[{\"id\":1,\"name\":\"\",\"value\":\"1\",\"sort\":1,\"status\":1},{\"id\":2,\"name\":\"\",\"value\":\"2\",\"sort\":2,\"status\":1}]")
private List<DictItem> dictItems;
@Schema(description = "字典数据项")
@Getter
@Setter
public static class DictItem {
@Schema(description = "字典ID")
private Long id;
@Schema(description = "字典名称")
private String name;
@Schema(description = "字典值")
private String value;
@Schema(description = "排序")
private Integer sort;
@Schema(description = "状态1-启用0-禁用)")
private Integer status;
}
@Schema(description = "字典备注")
private String remark;
}

View File

@@ -1,26 +0,0 @@
package com.youlai.system.model.form;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "字典类型")
@Data
public class DictTypeForm {
@Schema(description="字典类型ID")
private Long id;
@Schema(description="类型名称")
private String name;
@Schema(description="类型编码")
private String code;
@Schema(description="类型状态(1:启用;0:禁用)")
private Integer status;
@Schema(description = "备注")
private String remark;
}

View File

@@ -6,8 +6,13 @@ import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
import java.util.Map;
/**
* 菜单表单对象
*
* @author Ray
* @since 2024/06/23
*/
@Schema(description = "菜单表单对象")
@Data
public class MenuForm {
@@ -21,11 +26,14 @@ public class MenuForm {
@Schema(description = "菜单名称")
private String name;
@Schema(description = "菜单类型(1-菜单2-目录3-外链4-按钮权限)")
@Schema(description = "菜单类型1-菜单 2-目录 3-外链 4-按钮")
private MenuTypeEnum type;
@Schema(description = "路由名称")
private String routeName;
@Schema(description = "路由路径")
private String path;
private String routePath;
@Schema(description = "组件路径(vue页面完整路径省略.vue后缀)")
private String component;

View File

@@ -12,6 +12,6 @@ public class DictPageQuery extends BasePageQuery {
@Schema(description="关键字(字典项名称)")
private String keywords;
@Schema(description="字典类型编码")
@Schema(description="字典编码")
private String typeCode;
}

View File

@@ -5,7 +5,7 @@ import com.youlai.system.common.base.BasePageQuery;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description ="字典类型分页查询对象")
@Schema(description ="字典分页查询对象")
@Data
public class DictTypePageQuery extends BasePageQuery {

View File

@@ -20,6 +20,9 @@ public class DeptVO {
@Schema(description = "部门名称")
private String name;
@Schema(description = "部门编号")
private String code;
@Schema(description = "排序")
private Integer sort;

View File

@@ -2,22 +2,58 @@ package com.youlai.system.model.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
@Schema(description ="字典分页对象")
@Data
import java.util.List;
/**
* 字典分页VO
*
* @author Ray
* @since 0.0.1
*/
@Schema(description = "字典分页对象")
@Getter
@Setter
public class DictPageVO {
@Schema(description="字典ID")
@Schema(description = "字典ID")
private Long id;
@Schema(description="字典名称")
@Schema(description = "字典名称")
private String name;
@Schema(description="字典")
private String value;
@Schema(description = "字典编码")
private String code;
@Schema(description="状态(1:启用;0:禁用)")
@Schema(description = "字典状态1-启用0-禁用")
private Integer status;
@Schema(description = "字典项列表")
private List<DictItem> dictItems;
@Schema(description = "字典")
@Getter
@Setter
public static class DictItem {
@Schema(description = "字典项ID")
private Long id;
@Schema(description = "字典项名称")
private String name;
@Schema(description = "字典项值")
private String value;
@Schema(description = "排序")
private Integer sort;
@Schema(description = "状态1-启用0-禁用)")
private Integer status;
}
}

View File

@@ -1,23 +0,0 @@
package com.youlai.system.model.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description ="字典类型分页对象")
@Data
public class DictTypePageVO {
@Schema(description="字典类型ID")
private Long id;
@Schema(description="类型名称")
private String name;
@Schema(description="类型编码")
private String code;
@Schema(description="状态1:启用;0:禁用")
private Integer status;
}

View File

@@ -23,8 +23,11 @@ public class MenuVO {
@Schema(description="菜单类型")
private MenuTypeEnum type;
@Schema(description = "路由名称")
private String routeName;
@Schema(description = "路由路径")
private String path;
private String routePath;
@Schema(description = "组件路径")
private String component;

View File

@@ -12,10 +12,12 @@ import com.youlai.system.common.constant.SystemConstants;
import com.youlai.system.common.enums.GenderEnum;
import com.youlai.system.common.enums.StatusEnum;
import com.youlai.system.converter.UserConverter;
import com.youlai.system.model.dto.UserImportDTO;
import com.youlai.system.model.entity.SysDept;
import com.youlai.system.model.entity.SysRole;
import com.youlai.system.model.entity.SysUser;
import com.youlai.system.model.entity.SysUserRole;
import com.youlai.system.model.vo.UserImportVO;
import com.youlai.system.service.SysDeptService;
import com.youlai.system.service.SysRoleService;
import com.youlai.system.service.SysUserRoleService;
import com.youlai.system.service.SysUserService;
@@ -28,13 +30,13 @@ import java.util.stream.Collectors;
/**
* 用户导入监听器
* <p>
* <a href="https://easyexcel.opensource.alibaba.com/docs/current/quickstart/read#%E6%9C%80%E7%AE%80%E5%8D%95%E7%9A%84%E8%AF%BB%E7%9A%84%E7%9B%91%E5%90%AC%E5%99%A8">最简单的读的监听器</a>
* <a href="https://easyexcel.opensource.alibaba.com/docs/current/quickstart/read#%E6%9C%80%E7%AE%80%E5%8D%95%E7%9A%84%E8%AF%BB%E7%9A%84%E7%9B%91%E5%90%AC%E5%99%A8">最简单的读的监听器</a>
*
* @author haoxr
* @since 2022/4/10 20:49
* @author Ray
* @since 2022/4/10
*/
@Slf4j
public class UserImportListener extends MyAnalysisEventListener<UserImportVO> {
public class UserImportListener extends MyAnalysisEventListener<UserImportDTO> {
// 有效条数
@@ -46,25 +48,19 @@ public class UserImportListener extends MyAnalysisEventListener<UserImportVO> {
// 导入返回信息
StringBuilder msg = new StringBuilder();
// 部门ID
private final Long deptId;
private final SysUserService userService;
private final PasswordEncoder passwordEncoder;
private final UserConverter userConverter;
private final SysRoleService roleService;
private final SysUserRoleService userRoleService;
private final SysDeptService deptService;
public UserImportListener(Long deptId) {
this.deptId = deptId;
public UserImportListener() {
this.userService = SpringUtil.getBean(SysUserService.class);
this.passwordEncoder = SpringUtil.getBean(PasswordEncoder.class);
this.roleService = SpringUtil.getBean(SysRoleService.class);
this.userRoleService = SpringUtil.getBean(SysUserRoleService.class);
this.deptService = SpringUtil.getBean(SysDeptService.class);
this.userConverter = SpringUtil.getBean(UserConverter.class);
}
@@ -74,16 +70,15 @@ public class UserImportListener extends MyAnalysisEventListener<UserImportVO> {
* 1. 数据校验;全字段校验
* 2. 数据持久化;
*
* @param userImportVO 一行数据,类似于 {@link AnalysisContext#readRowHolder()}
* @param analysisContext
* @param userImportDTO 一行数据,类似于 {@link AnalysisContext#readRowHolder()}
*/
@Override
public void invoke(UserImportVO userImportVO, AnalysisContext analysisContext) {
log.info("解析到一条用户数据:{}", JSONUtil.toJsonStr(userImportVO));
public void invoke(UserImportDTO userImportDTO, AnalysisContext analysisContext) {
log.info("解析到一条用户数据:{}", JSONUtil.toJsonStr(userImportDTO));
// 校验数据
StringBuilder validationMsg = new StringBuilder();
String username = userImportVO.getUsername();
String username = userImportDTO.getUsername();
if (StrUtil.isBlank(username)) {
validationMsg.append("用户名为空;");
} else {
@@ -93,12 +88,12 @@ public class UserImportListener extends MyAnalysisEventListener<UserImportVO> {
}
}
String nickname = userImportVO.getNickname();
String nickname = userImportDTO.getNickname();
if (StrUtil.isBlank(nickname)) {
validationMsg.append("用户昵称为空;");
}
String mobile = userImportVO.getMobile();
String mobile = userImportDTO.getMobile();
if (StrUtil.isBlank(mobile)) {
validationMsg.append("手机号码为空;");
} else {
@@ -109,29 +104,38 @@ public class UserImportListener extends MyAnalysisEventListener<UserImportVO> {
if (validationMsg.isEmpty()) {
// 校验通过,持久化至数据库
SysUser entity = userConverter.importVo2Entity(userImportVO);
entity.setDeptId(deptId); // 部门
SysUser entity = userConverter.convertToEntity(userImportDTO);
entity.setPassword(passwordEncoder.encode(SystemConstants.DEFAULT_PASSWORD)); // 默认密码
// 性别翻译
String genderLabel = userImportVO.getGenderLabel();
String genderLabel = userImportDTO.getGenderLabel();
if (StrUtil.isNotBlank(genderLabel)) {
Integer genderValue = (Integer) IBaseEnum.getValueByLabel(genderLabel, GenderEnum.class);
entity.setGender(genderValue);
}
// 角色解析
String roleCodes = userImportVO.getRoleCodes();
String roleCodes = userImportDTO.getRoleCodes();
List<Long> roleIds = null;
if (StrUtil.isNotBlank(roleCodes)) {
roleIds = roleService.list(
new LambdaQueryWrapper<SysRole>()
.in(SysRole::getCode, roleCodes.split(","))
.in(SysRole::getCode, (Object) roleCodes.split(","))
.eq(SysRole::getStatus, StatusEnum.ENABLE.getValue())
.select(SysRole::getId)
).stream()
.map(SysRole::getId)
.collect(Collectors.toList());
}
// 部门解析
String deptCode = userImportDTO.getDeptCode();
if (StrUtil.isNotBlank(deptCode)) {
SysDept dept = deptService.getOne(new LambdaQueryWrapper<SysDept>().eq(SysDept::getCode, deptCode)
.select(SysDept::getId)
);
if (dept != null) {
entity.setDeptId(dept.getId());
}
}
boolean saveResult = userService.save(entity);
@@ -150,18 +154,17 @@ public class UserImportListener extends MyAnalysisEventListener<UserImportVO> {
}
} else {
invalidCount++;
msg.append("" + (validCount + invalidCount) + "行数据校验失败:").append(validationMsg + "<br/>");
msg.append("").append(validCount + invalidCount).append("行数据校验失败:").append(validationMsg + "<br/>");
}
}
/**
* 所有数据解析完成会来调用
*
* @param analysisContext
*/
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
log.info("所有数据解析完成!");
}
@@ -169,7 +172,6 @@ public class UserImportListener extends MyAnalysisEventListener<UserImportVO> {
@Override
public String getMsg() {
// 总结信息
String summaryMsg = StrUtil.format("导入用户结束:成功{}条,失败{}条;<br/>{}", validCount, invalidCount, msg);
return summaryMsg;
return StrUtil.format("导入用户结束:成功{}条,失败{}条;<br/>{}", validCount, invalidCount, msg);
}
}

View File

@@ -1,10 +1,13 @@
package com.youlai.system.plugin.dupsubmit.annotation;
package com.youlai.system.plugin.norepeat.annotation;
import java.lang.annotation.*;
/**
* 防止重复提交注解
* <p>
* 该注解用于方法上防止在指定时间内的重复提交
* 默认时间为5秒
*
* @author haoxr
* @since 2.3.0
@@ -13,10 +16,10 @@ import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface PreventDuplicateSubmit {
public @interface PreventRepeatSubmit {
/**
* 防重提交锁过期时间()
* 锁过期时间
* <p>
* 默认5秒内不允许重复提交
*/

View File

@@ -1,4 +1,4 @@
package com.youlai.system.plugin.dupsubmit.aspect;
package com.youlai.system.plugin.norepeat.aspect;
import cn.hutool.core.util.StrUtil;
import cn.hutool.jwt.JWTUtil;
@@ -6,7 +6,7 @@ import cn.hutool.jwt.RegisteredPayload;
import com.youlai.system.common.constant.SecurityConstants;
import com.youlai.system.common.exception.BusinessException;
import com.youlai.system.common.result.ResultCode;
import com.youlai.system.plugin.dupsubmit.annotation.PreventDuplicateSubmit;
import com.youlai.system.plugin.norepeat.annotation.PreventRepeatSubmit;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -41,17 +41,17 @@ public class DuplicateSubmitAspect {
/**
* 防重复提交切点
*/
@Pointcut("@annotation(preventDuplicateSubmit)")
public void preventDuplicateSubmitPointCut(PreventDuplicateSubmit preventDuplicateSubmit) {
@Pointcut("@annotation(preventRepeatSubmit)")
public void preventDuplicateSubmitPointCut(PreventRepeatSubmit preventRepeatSubmit) {
log.info("定义防重复提交切点");
}
@Around("preventDuplicateSubmitPointCut(preventDuplicateSubmit)")
public Object doAround(ProceedingJoinPoint pjp, PreventDuplicateSubmit preventDuplicateSubmit) throws Throwable {
@Around("preventDuplicateSubmitPointCut(preventRepeatSubmit)")
public Object doAround(ProceedingJoinPoint pjp, PreventRepeatSubmit preventRepeatSubmit) throws Throwable {
String resubmitLockKey = generateResubmitLockKey();
if (resubmitLockKey != null) {
int expire = preventDuplicateSubmit.expire(); // 防重提交锁过期时间
int expire = preventRepeatSubmit.expire(); // 防重提交锁过期时间
RLock lock = redissonClient.getLock(resubmitLockKey);
boolean lockResult = lock.tryLock(0, expire, TimeUnit.SECONDS); // 获取锁失败直接返回 false
if (!lockResult) {

View File

@@ -21,7 +21,7 @@ public interface SysDeptService extends IService<SysDept> {
*
* @return
*/
List<DeptVO> listDepartments(DeptQuery queryParams);
List<DeptVO> getDeptList(DeptQuery queryParams);
/**
* 部门树形下拉选项

View File

@@ -0,0 +1,20 @@
package com.youlai.system.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.youlai.system.model.entity.SysDictItem;
/**
* 字典项 接口
*
* @author Ray Hao
* @since 2023/3/4
*/
public interface SysDictItemService extends IService<SysDictItem> {
/**
* 根据字典ID删除字典项
*
* @param dictId 字典ID
*/
void removeByDictId(Long dictId);
}

View File

@@ -2,68 +2,74 @@ package com.youlai.system.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.youlai.system.common.model.Option;
import com.youlai.system.model.entity.SysDict;
import com.youlai.system.model.form.DictForm;
import com.youlai.system.model.query.DictPageQuery;
import com.youlai.system.model.query.DictTypePageQuery;
import com.youlai.system.model.vo.DictPageVO;
import com.youlai.system.common.model.Option;
import java.util.List;
/**
* 字典接口
* 数据字典业务接口
*
* @author haoxr
* @since 2023/3/4
* @since 2022/10/12
*/
public interface SysDictService extends IService<SysDict> {
/**
* 字典数据项分页列表
*
* @param queryParams
* @return
*/
Page<DictPageVO> getDictPage(DictPageQuery queryParams);
/**
* 字典数据项表单
* 字典分页列表
*
* @param id 字典数据项ID
* @param queryParams 分页查询对象
* @return
*/
Page<DictPageVO> getDictPage(DictTypePageQuery queryParams);
/**
* 获取字典表单详情
*
* @param id 字典ID
* @return
*/
DictForm getDictForm(Long id);
/**
* 新增字典数据项
* 新增字典
*
* @param dictForm 字典数据项表单
* @param dictForm 字典表单
* @return
*/
boolean saveDict(DictForm dictForm);
/**
* 修改字典数据项
* 修改字典
*
* @param id 字典数据项ID
* @param dictForm 字典数据项表单
* @param id
* @param dictForm 字典表单
* @return
*/
boolean updateDict(Long id, DictForm dictForm);
/**
* 删除字典数据项
* 删除字典
*
* @param idsStr 字典数据项ID多个以英文逗号(,)分割
* @param idsStr 字典ID多个以英文逗号(,)分割
* @return
*/
boolean deleteDict(String idsStr);
void deleteDictByIds(String idsStr);
/**
* 获取字典下拉列表
* 获取字典的数据项
*
* @param typeCode
* @return
*/
List<Option> listDictOptions(String typeCode);
List<Option> listDictItemsByCode(String typeCode);
}

View File

@@ -1,73 +0,0 @@
package com.youlai.system.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.youlai.system.common.model.Option;
import com.youlai.system.model.entity.SysDictType;
import com.youlai.system.model.form.DictTypeForm;
import com.youlai.system.model.query.DictTypePageQuery;
import com.youlai.system.model.vo.DictTypePageVO;
import java.util.List;
/**
* 数据字典类型业务接口
*
* @author haoxr
* @since 2022/10/12
*/
public interface SysDictTypeService extends IService<SysDictType> {
/**
* 字典类型分页列表
*
* @param queryParams 分页查询对象
* @return
*/
Page<DictTypePageVO> getDictTypePage(DictTypePageQuery queryParams);
/**
* 获取字典类型表单详情
*
* @param id 字典类型ID
* @return
*/
DictTypeForm getDictTypeForm(Long id);
/**
* 新增字典类型
*
* @param dictTypeForm 字典类型表单
* @return
*/
boolean saveDictType(DictTypeForm dictTypeForm);
/**
* 修改字典类型
*
* @param id
* @param dictTypeForm 字典类型表单
* @return
*/
boolean updateDictType(Long id, DictTypeForm dictTypeForm);
/**
* 删除字典类型
*
* @param idsStr 字典类型ID多个以英文逗号(,)分割
* @return
*/
boolean deleteDictTypes(String idsStr);
/**
* 获取字典类型的数据项
*
* @param typeCode
* @return
*/
List<Option> listDictItemsByTypeCode(String typeCode);
}

View File

@@ -9,7 +9,6 @@ import com.youlai.system.model.vo.MenuVO;
import com.youlai.system.model.vo.RouteVO;
import java.util.List;
import java.util.Set;
/**
* 菜单业务接口
@@ -21,31 +20,24 @@ public interface SysMenuService extends IService<SysMenu> {
/**
* 获取菜单表格列表
*
* @return
*/
List<MenuVO> listMenus(MenuQuery queryParams);
/**
* 获取菜单下拉列表
*
* @return
*/
List<Option> listMenuOptions();
/**
* 新增菜单
*
* @param menu
* @return
* @param menuForm 菜单表单对象
*/
boolean saveMenu(MenuForm menu);
boolean saveMenu(MenuForm menuForm);
/**
* 获取路由列表
*
* @return
*/
List<RouteVO> listRoutes();
@@ -53,32 +45,21 @@ public interface SysMenuService extends IService<SysMenu> {
* 修改菜单显示状态
*
* @param menuId 菜单ID
* @param visible 是否显示(1->显示2->隐藏)
* @return
* @param visible 是否显示(1-显示 2-隐藏)
*/
boolean updateMenuVisible(Long menuId, Integer visible);
/**
* 获取角色权限集合
*
* @param roles
* @return
*/
Set<String> listRolePerms(Set<String> roles);
/**
* 获取菜单表单数据
*
* @param id 菜单ID
* @return
*/
MenuForm getMenuForm(Long id);
/**
* 删除菜单
*
* @param id
* @return
* @param id 菜单ID
*/
boolean deleteMenu(Long id);
}

View File

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
import com.youlai.system.model.entity.SysRoleMenu;
import java.util.List;
import java.util.Set;
/**
* 角色菜单业务接口
@@ -43,4 +44,11 @@ public interface SysRoleMenuService extends IService<SysRoleMenu> {
*/
void refreshRolePermsCache(String oldRoleCode, String newRoleCode);
/**
* 获取角色权限集合
*
* @param roles 角色编码集合
* @return 权限集合
*/
Set<String> getRolePermsByRoleCodes(Set<String> roles);
}

View File

@@ -7,7 +7,7 @@ import com.youlai.system.model.entity.SysUser;
import com.youlai.system.model.form.UserForm;
import com.youlai.system.model.dto.UserAuthInfo;
import com.youlai.system.model.query.UserPageQuery;
import com.youlai.system.model.vo.UserExportVO;
import com.youlai.system.model.dto.UserExportDTO;
import com.youlai.system.model.vo.UserInfoVO;
import com.youlai.system.model.vo.UserPageVO;
@@ -90,7 +90,7 @@ public interface SysUserService extends IService<SysUser> {
* @param queryParams
* @return
*/
List<UserExportVO> listExportUsers(UserPageQuery queryParams);
List<UserExportDTO> listExportUsers(UserPageQuery queryParams);
/**

View File

@@ -24,10 +24,10 @@ import java.util.Set;
import java.util.stream.Collectors;
/**
* 部门业务实现类
* 部门 业务实现类
*
* @author haoxr
* @since 2021-08-22
* @author Ray
* @since 2021/08/22
*/
@Service
@RequiredArgsConstructor
@@ -40,7 +40,7 @@ public class SysDeptServiceImpl extends ServiceImpl<SysDeptMapper, SysDept> impl
* 获取部门列表
*/
@Override
public List<DeptVO> listDepartments(DeptQuery queryParams) {
public List<DeptVO> getDeptList(DeptQuery queryParams) {
// 查询参数
String keywords = queryParams.getKeywords();
Integer status = queryParams.getStatus();
@@ -85,11 +85,11 @@ public class SysDeptServiceImpl extends ServiceImpl<SysDeptMapper, SysDept> impl
return deptList.stream()
.filter(dept -> dept.getParentId().equals(parentId))
.map(dept -> {
DeptVO deptVO = deptConverter.entity2Vo(dept);
DeptVO deptVO = deptConverter.convertToVo(dept);
List<DeptVO> children = recurDeptList(dept.getId(), deptList);
deptVO.setChildren(children);
return deptVO;
}).collect(Collectors.toList());
}).toList();
}
/**
@@ -134,14 +134,14 @@ public class SysDeptServiceImpl extends ServiceImpl<SysDeptMapper, SysDept> impl
@Override
public Long saveDept(DeptForm formData) {
// 校验部门名称是否存在
String name = formData.getName();
String code = formData.getCode();
long count = this.count(new LambdaQueryWrapper<SysDept>()
.eq(SysDept::getName, name)
.eq(SysDept::getCode, code)
);
Assert.isTrue(count == 0, "部门名称已存在");
Assert.isTrue(count == 0, "部门编号已存在");
// form->entity
SysDept entity = deptConverter.form2Entity(formData);
SysDept entity = deptConverter.convertToEntity(formData);
// 生成部门路径(tree_path)格式父节点tree_path + , + 父节点ID用于删除部门时级联删除子部门
String treePath = generateDeptTreePath(formData.getParentId());
@@ -154,6 +154,20 @@ public class SysDeptServiceImpl extends ServiceImpl<SysDeptMapper, SysDept> impl
return entity.getId();
}
/**
* 获取部门表单
*
* @param deptId 部门ID
* @return 部门表单对象
*/
@Override
public DeptForm getDeptForm(Long deptId) {
SysDept entity = this.getById(deptId);
return deptConverter.convertToForm(entity);
}
/**
* 更新部门
*
@@ -163,16 +177,17 @@ public class SysDeptServiceImpl extends ServiceImpl<SysDeptMapper, SysDept> impl
*/
@Override
public Long updateDept(Long deptId, DeptForm formData) {
// 校验部门名称是否存在
String name = formData.getName();
// 校验部门名称/部门编号是否存在
String code = formData.getCode();
long count = this.count(new LambdaQueryWrapper<SysDept>()
.eq(SysDept::getName, name)
.ne(SysDept::getId, deptId)
.eq(SysDept::getCode, code)
);
Assert.isTrue(count == 0, "部门名称已存在");
Assert.isTrue(count == 0, "部门编号已存在");
// form->entity
SysDept entity = deptConverter.form2Entity(formData);
SysDept entity = deptConverter.convertToEntity(formData);
entity.setId(deptId);
// 生成部门路径(tree_path)格式父节点tree_path + , + 父节点ID用于删除部门时级联删除子部门
@@ -194,7 +209,7 @@ public class SysDeptServiceImpl extends ServiceImpl<SysDeptMapper, SysDept> impl
* @return 部门表格层级列表
*/
public static List<Option> recurDeptTreeOptions(long parentId, List<SysDept> deptList) {
List<Option> list = CollectionUtil.emptyIfNull(deptList).stream()
return CollectionUtil.emptyIfNull(deptList).stream()
.filter(dept -> dept.getParentId().equals(parentId))
.map(dept -> {
Option option = new Option(dept.getId(), dept.getName());
@@ -205,7 +220,6 @@ public class SysDeptServiceImpl extends ServiceImpl<SysDeptMapper, SysDept> impl
return option;
})
.collect(Collectors.toList());
return list;
}
@@ -230,28 +244,6 @@ public class SysDeptServiceImpl extends ServiceImpl<SysDeptMapper, SysDept> impl
return true;
}
/**
* 获取部门详情
*
* @param deptId 部门ID
* @return 部门表单对象
*/
@Override
public DeptForm getDeptForm(Long deptId) {
SysDept entity = this.getOne(new LambdaQueryWrapper<SysDept>()
.eq(SysDept::getId, deptId)
.select(
SysDept::getId,
SysDept::getName,
SysDept::getParentId,
SysDept::getStatus,
SysDept::getSort
));
return deptConverter.entity2Form(entity);
}
/**
* 部门路径生成

View File

@@ -0,0 +1,33 @@
package com.youlai.system.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.youlai.system.mapper.SysDictItemMapper;
import com.youlai.system.model.entity.SysDictItem;
import com.youlai.system.service.SysDictItemService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
/**
* 数据字典 服务实现类
*
* @author haoxr
* @since 2022/10/12
*/
@Service
@RequiredArgsConstructor
public class SysDictItemServiceImpl extends ServiceImpl<SysDictItemMapper, SysDictItem> implements SysDictItemService {
/**
* 根据字典ID删除字典项
*
* @param dictId 字典ID
*/
@Override
public void removeByDictId(Long dictId) {
}
}

View File

@@ -1,28 +1,32 @@
package com.youlai.system.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.youlai.system.converter.DictConverter;
import com.youlai.system.mapper.SysDictMapper;
import com.youlai.system.converter.DictItemConverter;
import com.youlai.system.model.entity.SysDict;
import com.youlai.system.model.form.DictForm;
import com.youlai.system.model.query.DictPageQuery;
import com.youlai.system.model.vo.DictPageVO;
import com.youlai.system.model.entity.SysDictItem;
import com.youlai.system.common.model.Option;
import com.youlai.system.mapper.SysDictMapper;
import com.youlai.system.model.form.DictForm;
import com.youlai.system.model.query.DictTypePageQuery;
import com.youlai.system.model.vo.DictPageVO;
import com.youlai.system.service.SysDictItemService;
import com.youlai.system.service.SysDictService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Arrays;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
/**
* 数据字典业务实现类
* 数据字典业务实现类
*
* @author haoxr
* @since 2022/10/12
@@ -31,133 +35,193 @@ import java.util.stream.Collectors;
@RequiredArgsConstructor
public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> implements SysDictService {
private final SysDictItemService dictItemService;
private final DictConverter dictConverter;
private final DictItemConverter dictItemConverter;
/**
* 字典数据项分页列表
* 字典分页列表
*
* @param queryParams
* @return
* @param queryParams 分页查询对象
*/
@Override
public Page<DictPageVO> getDictPage(DictPageQuery queryParams) {
public Page<DictPageVO> getDictPage(DictTypePageQuery queryParams) {
// 查询参数
int pageNum = queryParams.getPageNum();
int pageSize = queryParams.getPageSize();
String keywords = queryParams.getKeywords();
String typeCode = queryParams.getTypeCode();
// 查询数据
Page<SysDict> dictItemPage = this.page(
new Page<>(pageNum, pageSize),
new LambdaQueryWrapper<SysDict>()
.like(StrUtil.isNotBlank(keywords), SysDict::getName, keywords)
.eq(StrUtil.isNotBlank(typeCode), SysDict::getTypeCode, typeCode)
.select(SysDict::getId, SysDict::getName, SysDict::getValue, SysDict::getStatus)
);
// 实体转换
Page<DictPageVO> pageResult = dictConverter.entity2Page(dictItemPage);
return pageResult;
return this.baseMapper.getDictPage(new Page<>(pageNum, pageSize), queryParams);
}
/**
* 字典数据项表单详情
* 新增字典
*
* @param id 字典数据项ID
* @return
* @param dictForm 字典表单数据
*/
@Override
public boolean saveDict(DictForm dictForm) {
// 保存字典
SysDict entity = dictConverter.convertToEntity(dictForm);
// 校验 code 是否唯一
long count = this.count(new LambdaQueryWrapper<SysDict>()
.eq(SysDict::getCode, entity.getCode())
);
Assert.isTrue(count == 0, "字典编码已存在");
boolean result = this.save(entity);
// 保存字典项
if (result) {
List<DictForm.DictItem> dictFormDictItems = dictForm.getDictItems();
List<SysDictItem> dictItems = dictItemConverter.convertToEntity(dictFormDictItems);
dictItems.forEach(dictItem -> dictItem.setDictId(entity.getId()));
dictItemService.saveBatch(dictItems);
}
return result;
}
/**
* 获取字典表单详情
*
* @param id 字典ID
*/
@Override
public DictForm getDictForm(Long id) {
// 获取entity
SysDict entity = this.getOne(new LambdaQueryWrapper<SysDict>()
.eq(SysDict::getId, id)
.select(
SysDict::getId,
SysDict::getTypeCode,
SysDict::getName,
SysDict::getValue,
SysDict::getStatus,
SysDict::getSort,
SysDict::getRemark
));
Assert.isTrue(entity != null, "字典数据项不存在");
// 获取字典
SysDict entity = this.getById(id);
Assert.isTrue(entity != null, "字典不存在");
DictForm dictForm = dictConverter.convertToForm(entity);
// 实体转换
DictForm dictForm = dictConverter.entity2Form(entity);
// 获取字典项集合
List<SysDictItem> dictItems = dictItemService.list(new LambdaQueryWrapper<SysDictItem>()
.eq(SysDictItem::getDictId, id)
);
// 转换数据项
List<DictForm.DictItem> dictItemList = dictItemConverter.convertToDictFormDictItem(dictItems);
dictForm.setDictItems(dictItemList);
return dictForm;
}
/**
* 新增字典数据项
* 修改字典
*
* @param dictForm 字典数据项表单
* @return
*/
@Override
public boolean saveDict(DictForm dictForm) {
// 实体对象转换 form->entity
SysDict entity = dictConverter.form2Entity(dictForm);
// 持久化
boolean result = this.save(entity);
return result;
}
/**
* 修改字典数据项
*
* @param id 字典数据项ID
* @param dictForm 字典数据项表单
* @return
* @param id 字典ID
* @param dictForm 字典表单
*/
@Override
public boolean updateDict(Long id, DictForm dictForm) {
SysDict entity = dictConverter.form2Entity(dictForm);
// 更新字典
SysDict entity = dictConverter.convertToEntity(dictForm);
// 校验 code 是否唯一
long count = this.count(new LambdaQueryWrapper<SysDict>()
.eq(SysDict::getCode, entity.getCode())
.ne(SysDict::getId, id)
);
Assert.isTrue(count == 0, "字典编码已存在");
boolean result = this.updateById(entity);
if (result) {
// 更新字典项
List<DictForm.DictItem> dictFormDictItems = dictForm.getDictItems();
List<SysDictItem> dictItems = dictItemConverter.convertToEntity(dictFormDictItems);
// 获取当前数据库中的字典项
List<SysDictItem> currentDictItemEntities = dictItemService.list(new LambdaQueryWrapper<SysDictItem>()
.eq(SysDictItem::getDictId, id)
);
// 获取当前数据库中存在的字典项ID集合
Set<Long> currentDictItemIds = currentDictItemEntities.stream()
.map(SysDictItem::getId)
.collect(Collectors.toSet());
// 获取新提交的字典项ID集合
Set<Long> newAttrIds = dictItems.stream()
.map(SysDictItem::getId)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
// 需要删除的字典项ID集合存在于数据库但不在新提交的字典项中
Set<Long> idsToDelete = new HashSet<>(currentDictItemIds);
idsToDelete.removeAll(newAttrIds);
// 删除不在新提交字典项中的旧字典项
if (!idsToDelete.isEmpty()) {
dictItemService.removeByIds(idsToDelete);
}
// 更新或新增字典项
for (SysDictItem dictItem : dictItems) {
if (dictItem.getId() != null && currentDictItemIds.contains(dictItem.getId())) {
// 更新现有字典项
dictItemService.updateById(dictItem);
} else {
// 新增字典项
dictItem.setDictId(id);
dictItemService.save(dictItem);
}
}
}
return result;
}
/**
* 删除字典数据项
* 删除字典
*
* @param idsStr 字典数据项ID多个以英文逗号(,)分割
* @return
* @param ids 字典ID多个以英文逗号(,)分割
*/
@Override
public boolean deleteDict(String idsStr) {
Assert.isTrue(StrUtil.isNotBlank(idsStr), "删除数据为空");
//
List<Long> ids = Arrays.asList(idsStr.split(","))
.stream()
.map(id -> Long.parseLong(id))
.collect(Collectors.toList());
@Transactional
public void deleteDictByIds(String ids) {
// 删除字典数据项
boolean result = this.removeByIds(ids);
return result;
Assert.isTrue(StrUtil.isNotBlank(ids), "请选择需要删除字典");
List<String> idList = Arrays.stream(ids.split(","))
.toList();
for (String id : idList) {
boolean result = this.removeById(id);
if (result) {
// 删除字典下的字典项
dictItemService.removeByDictId(Convert.toLong(id));
}
}
}
/**
* 获取字典下拉列表
* 获取字典的数据项
*
* @param typeCode
* @return
* @param code 字典编码
*/
@Override
public List<Option> listDictOptions(String typeCode) {
// 据字典
List<SysDict> dictList = this.list(new LambdaQueryWrapper<SysDict>()
.eq(SysDict::getTypeCode, typeCode)
.select(SysDict::getValue, SysDict::getName)
public List<Option> listDictItemsByCode(String code) {
// 据字典编码获取字典ID
SysDict dict = this.getOne(new LambdaQueryWrapper<SysDict>()
.eq(SysDict::getCode, code)
.select(SysDict::getId)
.last("limit 1")
);
// 如果字典不存在,则返回空集合
if (dict == null) {
return CollectionUtil.newArrayList();
}
// 获取字典项
List<SysDictItem> dictItems = dictItemService.list(
new LambdaQueryWrapper<SysDictItem>()
.eq(SysDictItem::getDictId, dict.getId())
);
// 转换下拉数据
List<Option> options = CollectionUtil.emptyIfNull(dictList)
.stream()
.map(dictItem -> new Option(dictItem.getValue(), dictItem.getName()))
.collect(Collectors.toList());
// 转换为 Option
List<Option> options = dictItemConverter.convertToOption(dictItems);
return options;
}
}

View File

@@ -1,206 +0,0 @@
package com.youlai.system.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.youlai.system.model.entity.SysDict;
import com.youlai.system.common.model.Option;
import com.youlai.system.converter.DictTypeConverter;
import com.youlai.system.mapper.SysDictTypeMapper;
import com.youlai.system.model.entity.SysDictType;
import com.youlai.system.model.form.DictTypeForm;
import com.youlai.system.model.query.DictTypePageQuery;
import com.youlai.system.model.vo.DictTypePageVO;
import com.youlai.system.service.SysDictService;
import com.youlai.system.service.SysDictTypeService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* 数据字典类型业务实现类
*
* @author haoxr
* @since 2022/10/12
*/
@Service
@RequiredArgsConstructor
public class SysDictTypeServiceImpl extends ServiceImpl<SysDictTypeMapper, SysDictType> implements SysDictTypeService {
private final SysDictService dictItemService;
private final DictTypeConverter dictTypeConverter;
/**
* 字典分页列表
*
* @param queryParams 分页查询对象
* @return
*/
@Override
public Page<DictTypePageVO> getDictTypePage(DictTypePageQuery queryParams) {
// 查询参数
int pageNum = queryParams.getPageNum();
int pageSize = queryParams.getPageSize();
String keywords = queryParams.getKeywords();
// 查询数据
Page<SysDictType> dictTypePage = this.page(
new Page<>(pageNum, pageSize),
new LambdaQueryWrapper<SysDictType>()
.like(StrUtil.isNotBlank(keywords), SysDictType::getName, keywords)
.or()
.like(StrUtil.isNotBlank(keywords), SysDictType::getCode, keywords)
.select(
SysDictType::getId,
SysDictType::getName,
SysDictType::getCode,
SysDictType::getStatus,
SysDictType::getRemark
)
);
// 实体转换
Page<DictTypePageVO> pageResult = dictTypeConverter.entity2Page(dictTypePage);
return pageResult;
}
/**
* 获取字典类型表单详情
*
* @param id 字典类型ID
* @return
*/
@Override
public DictTypeForm getDictTypeForm(Long id) {
// 获取entity
SysDictType entity = this.getOne(new LambdaQueryWrapper<SysDictType>()
.eq(SysDictType::getId, id)
.select(
SysDictType::getId,
SysDictType::getName,
SysDictType::getCode,
SysDictType::getStatus,
SysDictType::getRemark
));
Assert.isTrue(entity != null, "字典类型不存在");
// 实体转换
DictTypeForm dictTypeForm = dictTypeConverter.entity2Form(entity);
return dictTypeForm;
}
/**
* 新增字典类型
*
* @param dictTypeForm
* @return
*/
@Override
public boolean saveDictType(DictTypeForm dictTypeForm) {
// 实体对象转换 form->entity
SysDictType entity = dictTypeConverter.form2Entity(dictTypeForm);
// 持久化
boolean result = this.save(entity);
return result;
}
/**
* 修改字典类型
*
* @param id 字典类型ID
* @param dictTypeForm 字典类型表单
* @return
*/
@Override
public boolean updateDictType(Long id, DictTypeForm dictTypeForm) {
// 获取字典类型
SysDictType sysDictType = this.getById(id);
Assert.isTrue(sysDictType != null, "字典类型不存在");
SysDictType entity = dictTypeConverter.form2Entity(dictTypeForm);
boolean result = this.updateById(entity);
if (result) {
// 字典类型code变化同步修改字典项的类型code
String oldCode = sysDictType.getCode();
String newCode = dictTypeForm.getCode();
if (!StrUtil.equals(oldCode, newCode)) {
dictItemService.update(new LambdaUpdateWrapper<SysDict>()
.eq(SysDict::getTypeCode, oldCode)
.set(SysDict::getTypeCode, newCode)
);
}
}
return result;
}
/**
* 删除字典类型
*
* @param idsStr 字典类型ID多个以英文逗号(,)分割
* @return
*/
@Override
@Transactional
public boolean deleteDictTypes(String idsStr) {
Assert.isTrue(StrUtil.isNotBlank(idsStr), "删除数据为空");
List ids = Arrays.asList(idsStr.split(","))
.stream()
.collect(Collectors.toList());
// 删除字典数据项
List<String> dictTypeCodes = this.list(new LambdaQueryWrapper<SysDictType>()
.in(SysDictType::getId, ids)
.select(SysDictType::getCode))
.stream()
.map(dictType -> dictType.getCode())
.collect(Collectors.toList()
);
if (CollectionUtil.isNotEmpty(dictTypeCodes)) {
dictItemService.remove(new LambdaQueryWrapper<SysDict>()
.in(SysDict::getTypeCode, dictTypeCodes));
}
// 删除字典类型
boolean result = this.removeByIds(ids);
return result;
}
/**
* 获取字典类型的数据项
*
* @param typeCode
* @return
*/
@Override
public List<Option> listDictItemsByTypeCode(String typeCode) {
// 数据字典项
List<SysDict> dictItems = dictItemService.list(new LambdaQueryWrapper<SysDict>()
.eq(SysDict::getTypeCode, typeCode)
.select(SysDict::getValue, SysDict::getName)
);
// 转换下拉数据
List<Option> options = CollectionUtil.emptyIfNull(dictItems)
.stream()
.map(dictItem -> new Option(dictItem.getValue(), dictItem.getName()))
.collect(Collectors.toList());
return options;
}
}

View File

@@ -96,7 +96,7 @@ public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> impl
.stream()
.filter(menu -> menu.getParentId().equals(parentId))
.map(entity -> {
MenuVO menuVO = menuConverter.entity2Vo(entity);
MenuVO menuVO = menuConverter.convertToVo(entity);
List<MenuVO> children = buildMenuTree(entity.getId(), menuList);
menuVO.setChildren(children);
return menuVO;
@@ -144,8 +144,7 @@ public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> impl
@Cacheable(cacheNames = "menu", key = "'routes'")
public List<RouteVO> listRoutes() {
List<RouteBO> menuList = this.baseMapper.listRoutes();
List<RouteVO> routes = buildRoutes(SystemConstants.ROOT_NODE_ID, menuList);
return routes;
return buildRoutes(SystemConstants.ROOT_NODE_ID, menuList);
}
/**
@@ -177,9 +176,17 @@ public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> impl
*/
private RouteVO toRouteVo(RouteBO routeBO) {
RouteVO routeVO = new RouteVO();
String routeName = StringUtils.capitalize(StrUtil.toCamelCase(routeBO.getPath(), '-')); // 路由 name 需要驼峰,首字母大写
routeVO.setName(routeName); // 根据name路由跳转 this.$router.push({name:xxx})
routeVO.setPath(routeBO.getPath()); // 根据path路由跳转 this.$router.push({path:xxx})
// 获取路由名称
String routeName = routeBO.getRouteName();
if (StrUtil.isBlank(routeName)) {
// 路由 name 需要驼峰,首字母大写
routeName = StringUtils.capitalize(StrUtil.toCamelCase(routeBO.getRoutePath(), '-'));
}
// 根据name路由跳转 this.$router.push({name:xxx})
routeVO.setName(routeName);
// 根据path路由跳转 this.$router.push({path:xxx})
routeVO.setPath(routeBO.getRoutePath());
routeVO.setRedirect(routeBO.getRedirect());
routeVO.setComponent(routeBO.getComponent());
@@ -200,7 +207,8 @@ public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> impl
if (StrUtil.isNotBlank(paramsJson)) {
ObjectMapper objectMapper = new ObjectMapper();
try {
Map<String, String> paramMap = objectMapper.readValue(paramsJson, new TypeReference<>() {});
Map<String, String> paramMap = objectMapper.readValue(paramsJson, new TypeReference<>() {
});
meta.setParams(paramMap);
} catch (Exception e) {
throw new RuntimeException("解析参数失败", e);
@@ -220,9 +228,9 @@ public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> impl
MenuTypeEnum menuType = menuForm.getType();
if (menuType == MenuTypeEnum.CATALOG) { // 如果是外链
String path = menuForm.getPath();
String path = menuForm.getRoutePath();
if (menuForm.getParentId() == 0 && !path.startsWith("/")) {
menuForm.setPath("/" + path); // 一级目录需以 / 开头
menuForm.setRoutePath("/" + path); // 一级目录需以 / 开头
}
menuForm.setComponent("Layout");
} else if (menuType == MenuTypeEnum.EXTLINK) { // 如果是目录
@@ -239,7 +247,7 @@ public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> impl
if (CollectionUtil.isNotEmpty(params)) {
entity.setParams(JSONUtil.toJsonStr(params.stream()
.collect(Collectors.toMap(KeyValue::getKey, KeyValue::getValue))));
}else{
} else {
entity.setParams(null);
}
@@ -285,17 +293,6 @@ public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> impl
);
}
/**
* 获取角色权限(Code)集合
*
* @param roles 角色Code集合
* @return 权限集合
*/
@Override
public Set<String> listRolePerms(Set<String> roles) {
return this.baseMapper.listRolePerms(roles);
}
/**
* 获取菜单表单数据
*
@@ -313,7 +310,8 @@ public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> impl
ObjectMapper objectMapper = new ObjectMapper();
try {
// 解析 JSON 字符串为 Map<String, String>
Map<String, String> paramMap = objectMapper.readValue(params, new TypeReference<>() {});
Map<String, String> paramMap = objectMapper.readValue(params, new TypeReference<>() {
});
// 转换为 List<KeyValue> 格式 [{key:"id", value:"1"}, {key:"name", value:"张三"}]
List<KeyValue> transformedList = paramMap.entrySet().stream()
@@ -353,5 +351,4 @@ public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> impl
}
}

View File

@@ -9,6 +9,7 @@ import com.youlai.system.model.entity.SysRoleMenu;
import com.youlai.system.service.SysRoleMenuService;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
@@ -19,11 +20,12 @@ import java.util.Set;
/**
* 角色菜单业务实现
*
* @author haoxr
* @author Ray
* @since 2.5.0
*/
@Service
@RequiredArgsConstructor
@Slf4j
public class SysRoleMenuServiceImpl extends ServiceImpl<SysRoleMenuMapper, SysRoleMenu> implements SysRoleMenuService {
private final RedisTemplate<String, Object> redisTemplate;
@@ -33,6 +35,7 @@ public class SysRoleMenuServiceImpl extends ServiceImpl<SysRoleMenuMapper, SysRo
*/
@PostConstruct
public void initRolePermsCache() {
log.info("初始化权限缓存... ");
refreshRolePermsCache();
}
@@ -83,7 +86,7 @@ public class SysRoleMenuServiceImpl extends ServiceImpl<SysRoleMenuMapper, SysRo
redisTemplate.opsForHash().delete(SecurityConstants.ROLE_PERMS_PREFIX, oldRoleCode);
// 添加新角色权限缓存
List<RolePermsBO> list =this.baseMapper.getRolePermsList(newRoleCode);
List<RolePermsBO> list = this.baseMapper.getRolePermsList(newRoleCode);
if (CollectionUtil.isNotEmpty(list)) {
RolePermsBO rolePerms = list.get(0);
if (rolePerms == null) {
@@ -95,6 +98,16 @@ public class SysRoleMenuServiceImpl extends ServiceImpl<SysRoleMenuMapper, SysRo
}
}
/**
* 获取角色权限集合
*
* @param roles 角色编码集合
* @return 权限集合
*/
@Override
public Set<String> getRolePermsByRoleCodes(Set<String> roles) {
return this.baseMapper.listRolePerms(roles);
}
/**
* 获取角色拥有的菜单ID集合
@@ -104,8 +117,7 @@ public class SysRoleMenuServiceImpl extends ServiceImpl<SysRoleMenuMapper, SysRo
*/
@Override
public List<Long> listMenuIdsByRoleId(Long roleId) {
List<Long> menuIds = this.baseMapper.listMenuIdsByRoleId(roleId);
return menuIds;
return this.baseMapper.listMenuIdsByRoleId(roleId);
}
}

View File

@@ -70,7 +70,7 @@ public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> impl
);
// 实体转换
return roleConverter.entity2Page(rolePage);
return roleConverter.convertToPageVo(rolePage);
}
/**
@@ -118,7 +118,7 @@ public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> impl
Assert.isTrue(count == 0, "角色名称或角色编码已存在,请修改后重试!");
// 实体转换
SysRole role = roleConverter.form2Entity(roleForm);
SysRole role = roleConverter.convertToEntity(roleForm);
boolean result = this.saveOrUpdate(role);
if (result) {
@@ -143,7 +143,7 @@ public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> impl
@Override
public RoleForm getRoleForm(Long roleId) {
SysRole entity = this.getById(roleId);
return roleConverter.entity2Form(entity);
return roleConverter.convertToForm(entity);
}
/**

View File

@@ -18,7 +18,7 @@ import com.youlai.system.model.bo.UserBO;
import com.youlai.system.model.entity.SysUser;
import com.youlai.system.model.form.UserForm;
import com.youlai.system.model.query.UserPageQuery;
import com.youlai.system.model.vo.UserExportVO;
import com.youlai.system.model.dto.UserExportDTO;
import com.youlai.system.model.vo.UserInfoVO;
import com.youlai.system.model.vo.UserPageVO;
import com.youlai.system.security.service.PermissionService;
@@ -49,7 +49,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
private final UserConverter userConverter;
private final SysMenuService menuService;
private final SysRoleMenuService roleMenuService;
private final SysRoleService roleService;
@@ -105,7 +105,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
Assert.isTrue(count == 0, "用户名已存在");
// 实体转换 form->entity
SysUser entity = userConverter.form2Entity(userForm);
SysUser entity = userConverter.convertToEntity(userForm);
// 设置默认加密密码
String defaultEncryptPwd = passwordEncoder.encode(SystemConstants.DEFAULT_PASSWORD);
@@ -141,7 +141,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
Assert.isTrue(count == 0, "用户名已存在");
// form -> entity
SysUser entity = userConverter.form2Entity(userForm);
SysUser entity = userConverter.convertToEntity(userForm);
// 修改用户
boolean result = this.updateById(entity);
@@ -197,7 +197,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
if (userAuthInfo != null) {
Set<String> roles = userAuthInfo.getRoles();
if (CollectionUtil.isNotEmpty(roles)) {
Set<String> perms = menuService.listRolePerms(roles);
Set<String> perms = roleMenuService.getRolePermsByRoleCodes(roles);
userAuthInfo.setPerms(perms);
}
@@ -213,10 +213,10 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
* 获取导出用户列表
*
* @param queryParams 查询参数
* @return {@link List<UserExportVO>} 导出用户列表
* @return {@link List< UserExportDTO >} 导出用户列表
*/
@Override
public List<UserExportVO> listExportUsers(UserPageQuery queryParams) {
public List<UserExportDTO> listExportUsers(UserPageQuery queryParams) {
return this.baseMapper.listExportUsers(queryParams);
}