✨ Introducing new features. closed #3038 用户导入导出、日志导出

This commit is contained in:
lbw committed 2021-08-05 11:03:20 +08:00
1 parent e5469fcd98
commit ff977f2f3d
12 files changed
+314 -4

No files matched your search

+4
View File
@@ -284,6 +284,7 @@ INSERT INTO `sys_menu` VALUES (1100, '用户管理', NULL, '/admin/user/index',
INSERT INTO `sys_menu` VALUES (1101, '用户新增', 'sys_user_add', NULL, 1100, NULL, 1, '0', '1', '2017-11-08 09:52:09', '2021-05-25 03:12:55', '0', 1);
INSERT INTO `sys_menu` VALUES (1102, '用户修改', 'sys_user_edit', NULL, 1100, NULL, 1, '0', '1', '2017-11-08 09:52:48', '2021-05-25 03:12:55', '0', 1);
INSERT INTO `sys_menu` VALUES (1103, '用户删除', 'sys_user_del', NULL, 1100, NULL, 1, '0', '1', '2017-11-08 09:54:01', '2021-05-25 03:12:55', '0', 1);
INSERT INTO `sys_menu` VALUES (1104, '导入导出', 'sys_user_export', NULL, 1100, NULL, 1, '0', '1', '2017-11-08 09:54:01', '2021-05-25 03:12:55', '0', 1);
INSERT INTO `sys_menu` VALUES (1200, '菜单管理', NULL, '/admin/menu/index', 1000, 'icon-caidanguanli', 2, '0', '0', '2017-11-08 09:57:27', '2020-03-24 08:56:38', '0', 1);
INSERT INTO `sys_menu` VALUES (1201, '菜单新增', 'sys_menu_add', NULL, 1200, NULL, 1, '0', '1', '2017-11-08 10:15:53', '2021-05-25 03:12:55', '0', 1);
INSERT INTO `sys_menu` VALUES (1202, '菜单修改', 'sys_menu_edit', NULL, 1200, NULL, 1, '0', '1', '2017-11-08 10:16:23', '2021-05-25 03:12:55', '0', 1);
@@ -304,6 +305,7 @@ INSERT INTO `sys_menu` VALUES (1503, '租户删除', 'admin_systenant_del', NULL
INSERT INTO `sys_menu` VALUES (2000, '系统管理', NULL, '/admin', -1, 'icon-xitongpeizhi', 1, '0', '0', '2017-11-07 20:56:00', '2020-03-24 08:56:55', '0', 1);
INSERT INTO `sys_menu` VALUES (2100, '日志管理', NULL, '/admin/log/index', 2000, 'icon-rizhi', 5, '0', '0', '2017-11-20 14:06:22', '2020-03-24 08:56:56', '0', 1);
INSERT INTO `sys_menu` VALUES (2101, '日志删除', 'sys_log_del', NULL, 2100, NULL, 1, '0', '1', '2017-11-20 20:37:37', '2021-05-25 03:12:55', '0', 1);
INSERT INTO `sys_menu` VALUES (2102, '导入导出', 'sys_log_export', NULL, 2100, NULL, 1, '0', '1', '2017-11-08 09:54:01', '2021-05-25 03:12:55', '0', 1);
INSERT INTO `sys_menu` VALUES (2200, '字典管理', NULL, '/admin/dict/index', 2000, 'icon-navicon-zdgl', 6, '0', '0', '2017-11-29 11:30:52', '2020-03-24 08:56:58', '0', 1);
INSERT INTO `sys_menu` VALUES (2201, '字典删除', 'sys_dict_del', NULL, 2200, NULL, 1, '0', '1', '2017-11-29 11:30:11', '2021-05-25 03:12:55', '0', 1);
INSERT INTO `sys_menu` VALUES (2202, '字典新增', 'sys_dict_add', NULL, 2200, NULL, 1, '0', '1', '2018-05-11 22:34:55', '2021-05-25 03:12:55', '0', 1);
@@ -522,6 +524,7 @@ INSERT INTO `sys_role_menu` VALUES (1, 1100);
INSERT INTO `sys_role_menu` VALUES (1, 1101);
INSERT INTO `sys_role_menu` VALUES (1, 1102);
INSERT INTO `sys_role_menu` VALUES (1, 1103);
INSERT INTO `sys_role_menu` VALUES (1, 1104);
INSERT INTO `sys_role_menu` VALUES (1, 1200);
INSERT INTO `sys_role_menu` VALUES (1, 1201);
INSERT INTO `sys_role_menu` VALUES (1, 1202);
@@ -542,6 +545,7 @@ INSERT INTO `sys_role_menu` VALUES (1, 1503);
INSERT INTO `sys_role_menu` VALUES (1, 2000);
INSERT INTO `sys_role_menu` VALUES (1, 2100);
INSERT INTO `sys_role_menu` VALUES (1, 2101);
INSERT INTO `sys_role_menu` VALUES (1, 2102);
INSERT INTO `sys_role_menu` VALUES (1, 2200);
INSERT INTO `sys_role_menu` VALUES (1, 2201);
INSERT INTO `sys_role_menu` VALUES (1, 2202);
+7
View File
@@ -27,6 +27,7 @@
<ijpay.version>2.7.6</ijpay.version>
<groovy.version>3.0.3</groovy.version>
<jsoup.version>1.13.1</jsoup.version>
<excel.version>0.5.0</excel.version>
<security.oauth.version>2.3.6.RELEASE</security.oauth.version>
<fastjson.version>1.2.75</fastjson.version>
<xxl.job.version>2.2.0</xxl.job.version>
@@ -215,6 +216,12 @@
<artifactId>jsoup</artifactId>
<version>${jsoup.version}</version>
</dependency>
<!-- excel 导入导出 https://github.com/pig-mesh/excel-spring-boot-starter -->
<dependency>
<groupId>com.pig4cloud.excel</groupId>
<artifactId>excel-spring-boot-starter</artifactId>
<version>${excel.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
+5
View File
@@ -49,5 +49,10 @@
<groupId>com.pig4cloud</groupId>
<artifactId>pigx-common-feign</artifactId>
</dependency>
<!-- excel 导入导出 -->
<dependency>
<groupId>com.pig4cloud.excel</groupId>
<artifactId>excel-spring-boot-starter</artifactId>
</dependency>
</dependencies>
</project>
@@ -19,6 +19,8 @@
package com.pig4cloud.pigx.admin.api.entity;
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
@@ -48,6 +50,7 @@ public class SysLog implements Serializable {
* 编号
*/
@TableId(type = IdType.AUTO)
@ExcelProperty("日志编号")
@ApiModelProperty(value = "日志编号")
private Long id;
@@ -55,6 +58,7 @@ public class SysLog implements Serializable {
* 日志类型
*/
@NotBlank(message = "日志类型不能为空")
@ExcelProperty("日志类型(0-正常 9-错误)")
@ApiModelProperty(value = "日志类型")
private String type;
@@ -62,30 +66,35 @@ public class SysLog implements Serializable {
* 日志标题
*/
@NotBlank(message = "日志标题不能为空")
@ExcelProperty("日志标题")
@ApiModelProperty(value = "日志标题")
private String title;
/**
* 创建者
*/
@ExcelProperty("创建人")
@ApiModelProperty(value = "创建人")
private String createBy;
/**
* 创建时间
*/
@ExcelProperty("创建时间")
@ApiModelProperty(value = "创建时间")
private LocalDateTime createTime;
/**
* 更新时间
*/
@ExcelIgnore
@ApiModelProperty(value = "更新时间")
private LocalDateTime updateTime;
/**
* 操作IP地址
*/
@ExcelProperty("操作ip地址")
@ApiModelProperty(value = "操作ip地址")
private String remoteAddr;
@@ -98,36 +107,42 @@ public class SysLog implements Serializable {
/**
* 请求URI
*/
@ExcelProperty("浏览器")
@ApiModelProperty(value = "请求uri")
private String requestUri;
/**
* 操作方式
*/
@ExcelProperty("操作方式")
@ApiModelProperty(value = "操作方式")
private String method;
/**
* 操作提交的数据
*/
@ExcelProperty("提交数据")
@ApiModelProperty(value = "提交数据")
private String params;
/**
* 执行时间
*/
@ExcelProperty("执行时间")
@ApiModelProperty(value = "方法执行时间")
private Long time;
/**
* 异常信息
*/
@ExcelProperty("异常信息")
@ApiModelProperty(value = "异常信息")
private String exception;
/**
* 服务ID
*/
@ExcelProperty("应用标识")
@ApiModelProperty(value = "应用标识")
private String serviceId;
@@ -135,6 +150,7 @@ public class SysLog implements Serializable {
* 删除标记
*/
@TableLogic
@ExcelIgnore
@ApiModelProperty(value = "删除标记,1:已删除,0:正常")
private String delFlag;
@@ -0,0 +1,69 @@
package com.pig4cloud.pigx.admin.api.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* 用户excel 对应的实体
*
* @author lengleng
* @date 2021/8/4
*/
@Data
@ColumnWidth(30)
public class UserExcelVO implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@ExcelProperty("用户编号")
private Integer userId;
/**
* 用户名
*/
@NotBlank(message = "用户名不能为空")
@ExcelProperty("用户名")
private String username;
/**
* 手机号
*/
@NotBlank(message = "手机号不能为空")
@ExcelProperty("手机号")
private String phone;
/**
* 部门名称
*/
@NotBlank(message = "部门名称不能为空")
@ExcelProperty("部门名称")
private String deptName;
/**
* 角色列表
*/
@NotBlank(message = "角色不能为空")
@ExcelProperty("角色")
private String roleNameList;
/**
* 锁定标记
*/
@ExcelProperty("锁定标记,0:正常,9:已锁定")
private String lockFlag;
/**
* 创建时间
*/
@ExcelProperty(value = "创建时间")
private LocalDateTime createTime;
}
@@ -19,12 +19,15 @@
package com.pig4cloud.pigx.admin.controller;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pig4cloud.pigx.admin.api.dto.SysLogDTO;
import com.pig4cloud.pigx.admin.api.entity.SysLog;
import com.pig4cloud.pigx.admin.api.vo.PreLogVO;
import com.pig4cloud.pigx.admin.service.SysLogService;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.security.annotation.Inner;
import com.pig4cloud.plugin.excel.annotation.ResponseExcel;
import io.swagger.annotations.Api;
import lombok.AllArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
@@ -92,4 +95,16 @@ public class SysLogController {
return R.ok(sysLogService.saveBatchLogs(preLogVoList));
}
/**
* 导出excel 表格
* @param sysLog 查询条件
* @return
*/
@ResponseExcel
@GetMapping("/export")
@PreAuthorize("@pms.hasPermission('sys_log_export')")
public List<SysLog> export(SysLog sysLog) {
return sysLogService.list(Wrappers.query(sysLog));
}
}
@@ -24,19 +24,25 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pig4cloud.pigx.admin.api.dto.UserDTO;
import com.pig4cloud.pigx.admin.api.entity.SysUser;
import com.pig4cloud.pigx.admin.api.vo.UserExcelVO;
import com.pig4cloud.pigx.admin.service.SysUserService;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.log.annotation.SysLog;
import com.pig4cloud.pigx.common.security.annotation.Inner;
import com.pig4cloud.pigx.common.security.util.SecurityUtils;
import com.pig4cloud.plugin.excel.annotation.RequestExcel;
import com.pig4cloud.plugin.excel.annotation.ResponseExcel;
import com.pig4cloud.plugin.excel.vo.ErrorMessage;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List;
/**
* @author lengleng
@@ -170,4 +176,31 @@ public class SysUserController {
return R.ok(userService.listAncestorUsers(username));
}
/**
* 导出excel 表格
* @param userDTO 查询条件
* @return
*/
@ResponseExcel
@GetMapping("/export")
@PreAuthorize("@pms.hasPermission('sys_log_export')")
public List export(UserDTO userDTO) {
return userService.listUser(userDTO);
}
/**
* 导入用户
* @param excelVOList 用户列表
* @param bindingResult 错误信息列表
* @return R
*/
@PostMapping("/import")
@PreAuthorize("@pms.hasPermission('sys_log_export')")
public R importUser(@RequestExcel List<UserExcelVO> excelVOList, BindingResult bindingResult) {
// 通用校验获取失败的数据
List<ErrorMessage> errorMessageList = (List<ErrorMessage>) bindingResult.getTarget();
return userService.importUser(excelVOList, bindingResult);
}
}
@@ -29,6 +29,8 @@ import com.pig4cloud.pigx.common.data.datascope.PigxBaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* <p>
* 用户表 Mapper 接口
@@ -63,4 +65,12 @@ public interface SysUserMapper extends PigxBaseMapper<SysUser> {
*/
UserVO getUserVoById(Integer id);
/**
* 查询用户列表
* @param userDTO 查询条件
* @param dataScope 数据权限声明
* @return
*/
List<UserVO> selectVoListByScope(@Param("query") UserDTO userDTO, DataScope dataScope);
}
@@ -25,8 +25,10 @@ import com.baomidou.mybatisplus.extension.service.IService;
import com.pig4cloud.pigx.admin.api.dto.UserDTO;
import com.pig4cloud.pigx.admin.api.dto.UserInfo;
import com.pig4cloud.pigx.admin.api.entity.SysUser;
import com.pig4cloud.pigx.admin.api.vo.UserExcelVO;
import com.pig4cloud.pigx.admin.api.vo.UserVO;
import com.pig4cloud.pigx.common.core.util.R;
import org.springframework.validation.BindingResult;
import java.util.List;
@@ -93,4 +95,19 @@ public interface SysUserService extends IService<SysUser> {
*/
Boolean saveUser(UserDTO userDto);
/**
* 查询全部的用户
* @param userDTO 查询条件
* @return list
*/
List<UserExcelVO> listUser(UserDTO userDTO);
/**
* excel 导入用户
* @param excelVOList excel 列表数据
* @param bindingResult 错误数据
* @return ok fail
*/
R importUser(List<UserExcelVO> excelVOList, BindingResult bindingResult);
}
@@ -60,7 +60,6 @@ public class SysDeptServiceImpl extends ServiceImpl<SysDeptMapper, SysDept> impl
/**
* 添加信息部门
*
* @param dept 部门
* @return
*/
@@ -76,7 +75,6 @@ public class SysDeptServiceImpl extends ServiceImpl<SysDeptMapper, SysDept> impl
/**
* 删除部门
*
* @param id 部门 ID
* @return 成功、失败
*/
@@ -99,7 +97,6 @@ public class SysDeptServiceImpl extends ServiceImpl<SysDeptMapper, SysDept> impl
/**
* 更新部门
*
* @param sysDept 部门信息
* @return 成功、失败
*/
@@ -118,7 +115,6 @@ public class SysDeptServiceImpl extends ServiceImpl<SysDeptMapper, SysDept> impl
/**
* 查询全部部门树
*
* @return 树
*/
@Override
@@ -19,6 +19,7 @@
package com.pig4cloud.pigx.admin.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
@@ -28,6 +29,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pig4cloud.pigx.admin.api.dto.UserDTO;
import com.pig4cloud.pigx.admin.api.dto.UserInfo;
import com.pig4cloud.pigx.admin.api.entity.*;
import com.pig4cloud.pigx.admin.api.vo.UserExcelVO;
import com.pig4cloud.pigx.admin.api.vo.UserVO;
import com.pig4cloud.pigx.admin.mapper.SysUserMapper;
import com.pig4cloud.pigx.admin.service.*;
@@ -35,6 +37,7 @@ import com.pig4cloud.pigx.common.core.constant.CacheConstants;
import com.pig4cloud.pigx.common.core.constant.CommonConstants;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.data.datascope.DataScope;
import com.pig4cloud.plugin.excel.vo.ErrorMessage;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
@@ -43,10 +46,12 @@ import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BindingResult;
import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
@@ -212,4 +217,105 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
return this.list(Wrappers.<SysUser>query().lambda().eq(SysUser::getDeptId, parentId));
}
/**
* 查询全部的用户
* @param userDTO 查询条件
* @return list
*/
@Override
public List<UserExcelVO> listUser(UserDTO userDTO) {
// 根据数据权限查询全部的用户信息
List<UserVO> voList = baseMapper.selectVoListByScope(userDTO, new DataScope());
// 转换成execl 对象输出
List<UserExcelVO> userExcelVOList = voList.stream().map(userVO -> {
UserExcelVO excelVO = new UserExcelVO();
BeanUtils.copyProperties(userVO, excelVO);
String roleNameList = userVO.getRoleList().stream().map(SysRole::getRoleName)
.collect(Collectors.joining(StrUtil.COMMA));
excelVO.setRoleNameList(roleNameList);
return excelVO;
}).collect(Collectors.toList());
return userExcelVOList;
}
/**
* excel 导入用户, 插入正确的 错误的提示行号
* @param excelVOList excel 列表数据
* @param bindingResult 错误数据
* @return ok fail
*/
@Override
public R importUser(List<UserExcelVO> excelVOList, BindingResult bindingResult) {
// 通用校验获取失败的数据
List<ErrorMessage> errorMessageList = (List<ErrorMessage>) bindingResult.getTarget();
// 个性化校验逻辑
List<SysUser> userList = this.list();
List<SysDept> deptList = sysDeptService.list();
List<SysRole> roleList = sysRoleService.list();
// 执行数据插入操作 组装 UserDto
for (int i = 0; i < excelVOList.size(); i++) {
UserExcelVO excel = excelVOList.get(i);
Set<String> errorMsg = new HashSet<>();
// 校验用户名是否存在
boolean exsitUserName = userList.stream()
.anyMatch(sysUser -> excel.getUsername().equals(sysUser.getUsername()));
if (exsitUserName) {
errorMsg.add(String.format("%s 用户名已存在", excel.getUsername()));
}
// 判断输入的部门名称列表是否合法
Optional<SysDept> deptOptional = deptList.stream()
.filter(dept -> excel.getDeptName().equals(dept.getName())).findFirst();
if (!deptOptional.isPresent()) {
errorMsg.add(String.format("%s 部门名称不存在", excel.getDeptName()));
}
// 判断输入的角色名称列表是否合法
List<String> roleNameList = StrUtil.split(excel.getRoleNameList(), StrUtil.COMMA);
List<SysRole> roleCollList = roleList.stream()
.filter(role -> roleNameList.stream().anyMatch(name -> role.getRoleName().equals(name)))
.collect(Collectors.toList());
if (roleCollList.size() != roleNameList.size()) {
errorMsg.add(String.format("%s 角色名称不存在", excel.getRoleNameList()));
}
// 数据合法情况
if (CollUtil.isEmpty(errorMsg)) {
insertExcelUser(excel, deptOptional, roleCollList);
}
else {
// 数据不合法情况
errorMessageList.add(new ErrorMessage((long) (i + 2), errorMsg));
}
}
if (CollUtil.isNotEmpty(errorMessageList)) {
return R.failed(errorMessageList);
}
return R.ok();
}
/**
* 插入excel User
*/
private void insertExcelUser(UserExcelVO excel, Optional<SysDept> deptOptional, List<SysRole> roleCollList) {
UserDTO userDTO = new UserDTO();
userDTO.setUsername(excel.getUsername());
userDTO.setPhone(excel.getPhone());
// 批量导入初始密码为手机号
userDTO.setPassword(userDTO.getPhone());
// 根据部门名称查询部门ID
userDTO.setDeptId(deptOptional.get().getDeptId());
// 根据角色名称查询角色ID
List<Integer> roleIdList = roleCollList.stream().map(SysRole::getRoleId).collect(Collectors.toList());
userDTO.setRole(roleIdList);
// 插入用户
this.saveUser(userDTO);
}
}
@@ -169,4 +169,36 @@
</where>
ORDER BY u.create_time DESC
</select>
<select id="selectVoListByScope" resultMap="baseResultMap">
SELECT
u.user_id,
u.username,
u.password,
u.salt,
u.phone,
u.avatar,
u.wx_openid,
u.qq_openid,
u.dept_id,
u.create_time ucreate_time,
u.update_time uupdate_time,
u.del_flag,
u.lock_flag,
u.tenant_id,
d.name dept_name
FROM
sys_user u
LEFT JOIN sys_dept d ON d.dept_id = u.dept_id
<where>
u.del_flag = '0'
<if test="query.username != null and query.username != ''">
AND u.username LIKE CONCAT('%',#{query.username},'%')
</if>
<if test="query.deptId != null and query.deptId != ''">
AND u.dept_id = #{query.deptId}
</if>
</where>
ORDER BY u.create_time DESC
</select>
</mapper>