Commit f942b34d02928e65aea16e49036e9b230fb4f7e1
1 parent
02ff516f
1. 完成用户导出的功能
2. 完成前后端的导出的封装
Showing
16 changed files
with
246 additions
and
131 deletions
ruoyi-ui/src/main.js
| ... | ... | @@ -16,7 +16,7 @@ import './assets/icons' // icon |
| 16 | 16 | import './permission' // permission control |
| 17 | 17 | import { getDicts } from "@/api/system/dict/data"; |
| 18 | 18 | import { getConfigKey } from "@/api/system/config"; |
| 19 | -import { parseTime, resetForm, addDateRange, selectDictLabel, selectDictLabels, download, handleTree } from "@/utils/ruoyi"; | |
| 19 | +import { parseTime, resetForm, addDateRange, selectDictLabel, selectDictLabels, download, handleTree, downloadExcel } from "@/utils/ruoyi"; | |
| 20 | 20 | import Pagination from "@/components/Pagination"; |
| 21 | 21 | // 自定义表格工具扩展 |
| 22 | 22 | import RightToolbar from "@/components/RightToolbar" |
| ... | ... | @@ -33,6 +33,7 @@ Vue.prototype.addDateRange = addDateRange |
| 33 | 33 | Vue.prototype.selectDictLabel = selectDictLabel |
| 34 | 34 | Vue.prototype.selectDictLabels = selectDictLabels |
| 35 | 35 | Vue.prototype.download = download |
| 36 | +Vue.prototype.downloadExcel = downloadExcel | |
| 36 | 37 | Vue.prototype.handleTree = handleTree |
| 37 | 38 | |
| 38 | 39 | Vue.prototype.msgSuccess = function (msg) { | ... | ... |
ruoyi-ui/src/utils/ruoyi.js
| ... | ... | @@ -101,6 +101,21 @@ export function download(fileName) { |
| 101 | 101 | window.location.href = baseURL + "/common/download?fileName=" + encodeURI(fileName) + "&delete=" + true; |
| 102 | 102 | } |
| 103 | 103 | |
| 104 | +// 下载 Excel 方法 | |
| 105 | +export function downloadExcel(data, fileName) { | |
| 106 | + // 创建 blob | |
| 107 | + let blob = new Blob([data], {type: 'application/vnd.ms-excel'}); | |
| 108 | + // 创建 href 超链接,点击进行下载 | |
| 109 | + window.URL = window.URL || window.webkitURL; | |
| 110 | + let href = URL.createObjectURL(blob); | |
| 111 | + let downA = document.createElement("a"); | |
| 112 | + downA.href = href; | |
| 113 | + downA.download = fileName; | |
| 114 | + downA.click(); | |
| 115 | + // 销毁超连接 | |
| 116 | + window.URL.revokeObjectURL(href); | |
| 117 | +} | |
| 118 | + | |
| 104 | 119 | // 字符串格式化(%s ) |
| 105 | 120 | export function sprintf(str) { |
| 106 | 121 | var args = arguments, flag = true, i = 1; | ... | ... |
ruoyi-ui/src/views/system/user/index.vue
| ... | ... | @@ -510,7 +510,7 @@ export default { |
| 510 | 510 | this.reset(); |
| 511 | 511 | }, |
| 512 | 512 | // 取消按钮(角色权限) |
| 513 | - cancelMenu() { | |
| 513 | + cancelRole() { | |
| 514 | 514 | this.openRole = false; |
| 515 | 515 | this.reset(); |
| 516 | 516 | }, |
| ... | ... | @@ -647,7 +647,10 @@ export default { |
| 647 | 647 | }, |
| 648 | 648 | /** 导出按钮操作 */ |
| 649 | 649 | handleExport() { |
| 650 | - const queryParams = this.queryParams; | |
| 650 | + const queryParams = this.addDateRange(this.queryParams, [ | |
| 651 | + this.dateRange[0] ? this.dateRange[0] + ' 00:00:00' : undefined, | |
| 652 | + this.dateRange[1] ? this.dateRange[1] + ' 23:59:59' : undefined, | |
| 653 | + ]); | |
| 651 | 654 | this.$confirm('是否确认导出所有用户数据项?', "警告", { |
| 652 | 655 | confirmButtonText: "确定", |
| 653 | 656 | cancelButtonText: "取消", |
| ... | ... | @@ -655,15 +658,7 @@ export default { |
| 655 | 658 | }).then(function() { |
| 656 | 659 | return exportUser(queryParams); |
| 657 | 660 | }).then(response => { |
| 658 | - // this.download(response.msg); | |
| 659 | - let blob = new Blob([response], {type: 'application/vnd.ms-excel'}); | |
| 660 | - window.URL = window.URL || window.webkitURL; | |
| 661 | - let href = URL.createObjectURL(blob); | |
| 662 | - let downA = document.createElement("a"); | |
| 663 | - downA.href = href;// | |
| 664 | - downA.download = '123321.xls'; | |
| 665 | - downA.click(); | |
| 666 | - window.URL.revokeObjectURL(href); | |
| 661 | + this.downloadExcel(response, '用户数据.xls'); | |
| 667 | 662 | }) |
| 668 | 663 | }, |
| 669 | 664 | /** 导入按钮操作 */ | ... | ... |
src/main/java/cn/iocoder/dashboard/framework/excel/core/convert/DictConvert.java
| ... | ... | @@ -54,7 +54,7 @@ public class DictConvert implements Converter<Object> { |
| 54 | 54 | return null; |
| 55 | 55 | } |
| 56 | 56 | // 生成 Excel 小表格 |
| 57 | - return new CellData<>(dictData.getValue()); | |
| 57 | + return new CellData<>(dictData.getLabel()); | |
| 58 | 58 | } |
| 59 | 59 | |
| 60 | 60 | private static DictTypeEnum getType(ExcelContentProperty contentProperty) { | ... | ... |
src/main/java/cn/iocoder/dashboard/framework/excel/core/util/ExcelUtils.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.framework.excel.core.util; | |
| 2 | + | |
| 3 | +import com.alibaba.excel.EasyExcel; | |
| 4 | +import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy; | |
| 5 | + | |
| 6 | +import javax.servlet.http.HttpServletResponse; | |
| 7 | +import java.io.IOException; | |
| 8 | +import java.net.URLEncoder; | |
| 9 | +import java.util.List; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * Excel 工具类 | |
| 13 | + */ | |
| 14 | +public class ExcelUtils { | |
| 15 | + | |
| 16 | + public static void write(HttpServletResponse response, String filename, String sheetName, | |
| 17 | + Class<?> head, List<?> data) throws IOException { | |
| 18 | + // 设置 header 和 contentType | |
| 19 | + response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8")); | |
| 20 | + response.setContentType("application/vnd.ms-excel;charset=UTF-8"); | |
| 21 | + // 输出 Excel | |
| 22 | + EasyExcel.write(response.getOutputStream(), head) | |
| 23 | + .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 基于 column 长度,自动适配。最大 255 宽度 | |
| 24 | + .sheet(sheetName).doWrite(data); | |
| 25 | + } | |
| 26 | + | |
| 27 | +} | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/system/controller/user/SysUserController.java
| ... | ... | @@ -3,6 +3,7 @@ package cn.iocoder.dashboard.modules.system.controller.user; |
| 3 | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | 4 | import cn.iocoder.dashboard.common.pojo.CommonResult; |
| 5 | 5 | import cn.iocoder.dashboard.common.pojo.PageResult; |
| 6 | +import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils; | |
| 6 | 7 | import cn.iocoder.dashboard.modules.system.controller.user.vo.user.*; |
| 7 | 8 | import cn.iocoder.dashboard.modules.system.convert.user.SysUserConvert; |
| 8 | 9 | import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dept.SysDeptDO; |
| ... | ... | @@ -10,7 +11,7 @@ import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO; |
| 10 | 11 | import cn.iocoder.dashboard.modules.system.service.dept.SysDeptService; |
| 11 | 12 | import cn.iocoder.dashboard.modules.system.service.user.SysUserService; |
| 12 | 13 | import cn.iocoder.dashboard.util.collection.CollectionUtils; |
| 13 | -import com.alibaba.excel.EasyExcel; | |
| 14 | +import cn.iocoder.dashboard.util.collection.MapUtils; | |
| 14 | 15 | import io.swagger.annotations.Api; |
| 15 | 16 | import io.swagger.annotations.ApiImplicitParam; |
| 16 | 17 | import io.swagger.annotations.ApiOperation; |
| ... | ... | @@ -20,7 +21,10 @@ import org.springframework.web.bind.annotation.*; |
| 20 | 21 | import javax.annotation.Resource; |
| 21 | 22 | import javax.servlet.http.HttpServletResponse; |
| 22 | 23 | import java.io.IOException; |
| 23 | -import java.util.*; | |
| 24 | +import java.util.ArrayList; | |
| 25 | +import java.util.Collection; | |
| 26 | +import java.util.List; | |
| 27 | +import java.util.Map; | |
| 24 | 28 | |
| 25 | 29 | import static cn.iocoder.dashboard.common.pojo.CommonResult.success; |
| 26 | 30 | |
| ... | ... | @@ -37,7 +41,7 @@ public class SysUserController { |
| 37 | 41 | @ApiOperation("获得用户分页列表") |
| 38 | 42 | @GetMapping("/page") |
| 39 | 43 | // @PreAuthorize("@ss.hasPermi('system:user:list')") |
| 40 | - public CommonResult<PageResult<SysUserPageItemRespVO>> pageUsers(SysUserPageReqVO reqVO) { | |
| 44 | + public CommonResult<PageResult<SysUserPageItemRespVO>> pageUsers(@Validated SysUserPageReqVO reqVO) { | |
| 41 | 45 | // 获得用户分页列表 |
| 42 | 46 | PageResult<SysUserDO> pageResult = userService.pageUsers(reqVO); |
| 43 | 47 | if (CollUtil.isEmpty(pageResult.getList())) { |
| ... | ... | @@ -45,13 +49,8 @@ public class SysUserController { |
| 45 | 49 | } |
| 46 | 50 | |
| 47 | 51 | // 获得拼接需要的数据 |
| 48 | - Map<Long, SysDeptDO> deptMap; | |
| 49 | 52 | Collection<Long> deptIds = CollectionUtils.convertList(pageResult.getList(), SysUserDO::getDeptId); |
| 50 | - if (CollUtil.isNotEmpty(deptIds)) { | |
| 51 | - deptMap = CollectionUtils.convertMap(deptService.listDepts(deptIds), SysDeptDO::getId); | |
| 52 | - } else { | |
| 53 | - deptMap = Collections.emptyMap(); | |
| 54 | - } | |
| 53 | + Map<Long, SysDeptDO> deptMap = deptService.getDeptMap(deptIds); | |
| 55 | 54 | // 拼接结果返回 |
| 56 | 55 | List<SysUserPageItemRespVO> userList = new ArrayList<>(pageResult.getList().size()); |
| 57 | 56 | pageResult.getList().forEach(user -> { |
| ... | ... | @@ -121,11 +120,29 @@ public class SysUserController { |
| 121 | 120 | |
| 122 | 121 | @ApiOperation("导出用户") |
| 123 | 122 | @GetMapping("/export") |
| 124 | - public void exportUsers(HttpServletResponse response) throws IOException { | |
| 125 | - String fileName = "测试文件.xls"; | |
| 126 | - response.addHeader("Content-Disposition", "attachment;filename=" + fileName); | |
| 127 | - response.setContentType("application/vnd.ms-excel;charset=UTF-8"); | |
| 128 | - EasyExcel.write(response.getOutputStream(), SysUserExcelVO.class).sheet().doWrite(new ArrayList<>()); | |
| 123 | +// @PreAuthorize("@ss.hasPermi('system:user:export')") , @Validated SysUserExportReqVO reqVO | |
| 124 | +// @Log(title = "用户管理", businessType = BusinessType.EXPORT) | |
| 125 | + public void exportUsers(HttpServletResponse response, @Validated SysUserExportReqVO reqVO) throws IOException { | |
| 126 | + // 获得用户列表 | |
| 127 | + List<SysUserDO> users = userService.listUsers(reqVO); | |
| 128 | + | |
| 129 | + // 获得拼接需要的数据 | |
| 130 | + Collection<Long> deptIds = CollectionUtils.convertList(users, SysUserDO::getDeptId); | |
| 131 | + Map<Long, SysDeptDO> deptMap = deptService.getDeptMap(deptIds); | |
| 132 | + // 拼接数据 | |
| 133 | + List<SysUserExcelVO> excelUsers = new ArrayList<>(users.size()); | |
| 134 | + users.forEach(user -> { | |
| 135 | + SysUserExcelVO excelVO = SysUserConvert.INSTANCE.convert02(user); | |
| 136 | + MapUtils.findAndThen(deptMap, user.getDeptId(), dept -> { | |
| 137 | + excelVO.setDeptName(dept.getName()); | |
| 138 | + excelVO.setDeptLeader(dept.getLeader()); | |
| 139 | + }); | |
| 140 | + excelUsers.add(excelVO); | |
| 141 | + }); | |
| 142 | + | |
| 143 | + // 输出 | |
| 144 | + ExcelUtils.write(response, "用户数据.xls", "用户列表", | |
| 145 | + SysUserExcelVO.class, excelUsers); | |
| 129 | 146 | } |
| 130 | 147 | |
| 131 | 148 | // @Log(title = "用户管理", businessType = BusinessType.EXPORT) | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserExcelVO.java
src/main/java/cn/iocoder/dashboard/modules/system/controller/user/vo/user/SysUserExportReqVO.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.system.controller.user.vo.user; | |
| 2 | + | |
| 3 | +import io.swagger.annotations.ApiModel; | |
| 4 | +import io.swagger.annotations.ApiModelProperty; | |
| 5 | +import lombok.AllArgsConstructor; | |
| 6 | +import lombok.Data; | |
| 7 | +import lombok.NoArgsConstructor; | |
| 8 | +import org.springframework.format.annotation.DateTimeFormat; | |
| 9 | + | |
| 10 | +import java.util.Date; | |
| 11 | + | |
| 12 | +import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | |
| 13 | + | |
| 14 | +@ApiModel(value = "用户导出 Request VO", description = "参数和 SysUserPageReqVO 是一致的") | |
| 15 | +@Data | |
| 16 | +@NoArgsConstructor | |
| 17 | +@AllArgsConstructor | |
| 18 | +public class SysUserExportReqVO { | |
| 19 | + | |
| 20 | + @ApiModelProperty(value = "用户账号", example = "yudao", notes = "模糊匹配") | |
| 21 | + private String username; | |
| 22 | + | |
| 23 | + @ApiModelProperty(value = "手机号码", example = "yudao", notes = "模糊匹配") | |
| 24 | + private String mobile; | |
| 25 | + | |
| 26 | + @ApiModelProperty(value = "展示状态", example = "1", notes = "参见 SysCommonStatusEnum 枚举类") | |
| 27 | + private Integer status; | |
| 28 | + | |
| 29 | + @ApiModelProperty(value = "开始时间", example = "2020-10-24") | |
| 30 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 31 | + private Date beginTime; | |
| 32 | + | |
| 33 | + @ApiModelProperty(value = "结束时间", example = "2020-10-24") | |
| 34 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 35 | + private Date endTime; | |
| 36 | + | |
| 37 | + @ApiModelProperty(value = "部门编号", example = "1024", notes = "同时筛选子部门") | |
| 38 | + private Long deptId; | |
| 39 | + | |
| 40 | +} | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/system/convert/user/SysUserConvert.java
| ... | ... | @@ -2,6 +2,7 @@ package cn.iocoder.dashboard.modules.system.convert.user; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.dashboard.common.pojo.PageResult; |
| 4 | 4 | import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserCreateReqVO; |
| 5 | +import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserExcelVO; | |
| 5 | 6 | import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserPageItemRespVO; |
| 6 | 7 | import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserUpdateReqVO; |
| 7 | 8 | import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dept.SysDeptDO; |
| ... | ... | @@ -27,4 +28,6 @@ public interface SysUserConvert { |
| 27 | 28 | |
| 28 | 29 | SysUserDO convert(SysUserUpdateReqVO bean); |
| 29 | 30 | |
| 31 | + SysUserExcelVO convert02(SysUserDO bean); | |
| 32 | + | |
| 30 | 33 | } | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/user/SysUserMapper.java
| ... | ... | @@ -2,6 +2,7 @@ package cn.iocoder.dashboard.modules.system.dal.mysql.dao.user; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.dashboard.framework.mybatis.core.query.QueryWrapperX; |
| 4 | 4 | import cn.iocoder.dashboard.framework.mybatis.core.util.MyBatisUtils; |
| 5 | +import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserExportReqVO; | |
| 5 | 6 | import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserPageReqVO; |
| 6 | 7 | import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO; |
| 7 | 8 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| ... | ... | @@ -9,6 +10,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| 9 | 10 | import com.baomidou.mybatisplus.core.metadata.IPage; |
| 10 | 11 | import org.apache.ibatis.annotations.Mapper; |
| 11 | 12 | |
| 13 | +import java.util.Collection; | |
| 12 | 14 | import java.util.List; |
| 13 | 15 | |
| 14 | 16 | @Mapper |
| ... | ... | @@ -26,7 +28,7 @@ public interface SysUserMapper extends BaseMapper<SysUserDO> { |
| 26 | 28 | return selectOne(new QueryWrapper<SysUserDO>().eq("email", email)); |
| 27 | 29 | } |
| 28 | 30 | |
| 29 | - default IPage<SysUserDO> selectList(SysUserPageReqVO reqVO, List<Long> deptIds) { | |
| 31 | + default IPage<SysUserDO> selectList(SysUserPageReqVO reqVO, Collection<Long> deptIds) { | |
| 30 | 32 | return selectPage(MyBatisUtils.buildPage(reqVO), |
| 31 | 33 | new QueryWrapperX<SysUserDO>().likeIfPresent("username", reqVO.getUsername()) |
| 32 | 34 | .likeIfPresent("mobile", reqVO.getMobile()) |
| ... | ... | @@ -35,5 +37,13 @@ public interface SysUserMapper extends BaseMapper<SysUserDO> { |
| 35 | 37 | .inIfPresent("dept_id", deptIds)); |
| 36 | 38 | } |
| 37 | 39 | |
| 40 | + default List<SysUserDO> selectList(SysUserExportReqVO reqVO, Collection<Long> deptIds) { | |
| 41 | + return selectList(new QueryWrapperX<SysUserDO>().likeIfPresent("username", reqVO.getUsername()) | |
| 42 | + .likeIfPresent("mobile", reqVO.getMobile()) | |
| 43 | + .eqIfPresent("status", reqVO.getStatus()) | |
| 44 | + .betweenIfPresent("create_time", reqVO.getBeginTime(), reqVO.getEndTime()) | |
| 45 | + .inIfPresent("dept_id", deptIds)); | |
| 46 | + } | |
| 47 | + | |
| 38 | 48 | } |
| 39 | 49 | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/system/service/dept/SysDeptService.java
| 1 | 1 | package cn.iocoder.dashboard.modules.system.service.dept; |
| 2 | 2 | |
| 3 | +import cn.hutool.core.collection.CollUtil; | |
| 3 | 4 | import cn.iocoder.dashboard.modules.system.controller.dept.vo.dept.SysDeptCreateReqVO; |
| 4 | 5 | import cn.iocoder.dashboard.modules.system.controller.dept.vo.dept.SysDeptListReqVO; |
| 5 | 6 | import cn.iocoder.dashboard.modules.system.controller.dept.vo.dept.SysDeptUpdateReqVO; |
| 6 | 7 | import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.dept.SysDeptDO; |
| 8 | +import cn.iocoder.dashboard.util.collection.CollectionUtils; | |
| 7 | 9 | |
| 8 | 10 | import java.util.Collection; |
| 11 | +import java.util.Collections; | |
| 9 | 12 | import java.util.List; |
| 13 | +import java.util.Map; | |
| 10 | 14 | |
| 11 | 15 | /** |
| 12 | 16 | * 部门 Service 接口 |
| ... | ... | @@ -36,6 +40,20 @@ public interface SysDeptService { |
| 36 | 40 | List<SysDeptDO> listDepts(Collection<Long> ids); |
| 37 | 41 | |
| 38 | 42 | /** |
| 43 | + * 获得指定编号的部门 Map | |
| 44 | + * | |
| 45 | + * @param ids 部门编号数组 | |
| 46 | + * @return 部门 Map | |
| 47 | + */ | |
| 48 | + default Map<Long, SysDeptDO> getDeptMap(Collection<Long> ids) { | |
| 49 | + if (CollUtil.isEmpty(ids)) { | |
| 50 | + return Collections.emptyMap(); | |
| 51 | + } | |
| 52 | + List<SysDeptDO> list = listDepts(ids); | |
| 53 | + return CollectionUtils.convertMap(list, SysDeptDO::getId); | |
| 54 | + } | |
| 55 | + | |
| 56 | + /** | |
| 39 | 57 | * 筛选部门列表 |
| 40 | 58 | * |
| 41 | 59 | * @param reqVO 筛选条件请求 VO | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/system/service/dict/impl/SysDictDataServiceImpl.java
| ... | ... | @@ -15,6 +15,7 @@ import cn.iocoder.dashboard.modules.system.service.dict.SysDictTypeService; |
| 15 | 15 | import com.google.common.collect.ImmutableTable; |
| 16 | 16 | import org.springframework.stereotype.Service; |
| 17 | 17 | |
| 18 | +import javax.annotation.PostConstruct; | |
| 18 | 19 | import javax.annotation.Resource; |
| 19 | 20 | import java.util.ArrayList; |
| 20 | 21 | import java.util.Comparator; |
| ... | ... | @@ -56,6 +57,7 @@ public class SysDictDataServiceImpl implements SysDictDataService { |
| 56 | 57 | private SysDictDataMapper dictDataMapper; |
| 57 | 58 | |
| 58 | 59 | @Override |
| 60 | + @PostConstruct | |
| 59 | 61 | public void init() { |
| 60 | 62 | // 获得字典数据 |
| 61 | 63 | List<SysDictDataDO> list = this.listDictDatas(); | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserService.java
| ... | ... | @@ -2,23 +2,19 @@ package cn.iocoder.dashboard.modules.system.service.user; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.dashboard.common.pojo.PageResult; |
| 4 | 4 | import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserCreateReqVO; |
| 5 | +import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserExportReqVO; | |
| 5 | 6 | import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserPageReqVO; |
| 6 | 7 | import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserUpdateReqVO; |
| 7 | 8 | import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO; |
| 8 | 9 | |
| 10 | +import java.util.List; | |
| 11 | + | |
| 9 | 12 | /** |
| 10 | 13 | * 用户 Service 接口 |
| 11 | 14 | * |
| 12 | 15 | * @author 芋道源码 |
| 13 | 16 | */ |
| 14 | 17 | public interface SysUserService { |
| 15 | -// /** | |
| 16 | -// * 根据条件分页查询用户列表 | |
| 17 | -// * | |
| 18 | -// * @param user 用户信息 | |
| 19 | -// * @return 用户信息集合信息 | |
| 20 | -// */ | |
| 21 | -// public List<SysUser> selectUserList(SysUser user); | |
| 22 | 18 | |
| 23 | 19 | /** |
| 24 | 20 | * 通过用户名查询用户 |
| ... | ... | @@ -45,6 +41,14 @@ public interface SysUserService { |
| 45 | 41 | PageResult<SysUserDO> pageUsers(SysUserPageReqVO reqVO); |
| 46 | 42 | |
| 47 | 43 | /** |
| 44 | + * 获得用户列表 | |
| 45 | + * | |
| 46 | + * @param reqVO 列表请求 | |
| 47 | + * @return 用户列表 | |
| 48 | + */ | |
| 49 | + List<SysUserDO> listUsers(SysUserExportReqVO reqVO); | |
| 50 | + | |
| 51 | + /** | |
| 48 | 52 | * 创建用户 |
| 49 | 53 | * |
| 50 | 54 | * @param reqVO 用户信息 |
| ... | ... | @@ -84,77 +88,6 @@ public interface SysUserService { |
| 84 | 88 | |
| 85 | 89 | // |
| 86 | 90 | // /** |
| 87 | -// * 根据用户ID查询用户所属角色组 | |
| 88 | -// * | |
| 89 | -// * @param userName 用户名 | |
| 90 | -// * @return 结果 | |
| 91 | -// */ | |
| 92 | -// public String selectUserRoleGroup(String userName); | |
| 93 | -// | |
| 94 | -// /** | |
| 95 | -// * 根据用户ID查询用户所属岗位组 | |
| 96 | -// * | |
| 97 | -// * @param userName 用户名 | |
| 98 | -// * @return 结果 | |
| 99 | -// */ | |
| 100 | -// public String selectUserPostGroup(String userName); | |
| 101 | -// | |
| 102 | -// /** | |
| 103 | -// * 校验用户名称是否唯一 | |
| 104 | -// * | |
| 105 | -// * @param userName 用户名称 | |
| 106 | -// * @return 结果 | |
| 107 | -// */ | |
| 108 | -// public String checkUserNameUnique(String userName); | |
| 109 | -// | |
| 110 | -// /** | |
| 111 | -// * 校验手机号码是否唯一 | |
| 112 | -// * | |
| 113 | -// * @param user 用户信息 | |
| 114 | -// * @return 结果 | |
| 115 | -// */ | |
| 116 | -// public String checkPhoneUnique(SysUser user); | |
| 117 | -// | |
| 118 | -// /** | |
| 119 | -// * 校验email是否唯一 | |
| 120 | -// * | |
| 121 | -// * @param user 用户信息 | |
| 122 | -// * @return 结果 | |
| 123 | -// */ | |
| 124 | -// public String checkEmailUnique(SysUser user); | |
| 125 | -// | |
| 126 | -// /** | |
| 127 | -// * 校验用户是否允许操作 | |
| 128 | -// * | |
| 129 | -// * @param user 用户信息 | |
| 130 | -// */ | |
| 131 | -// public void checkUserAllowed(SysUser user); | |
| 132 | -// | |
| 133 | -// /** | |
| 134 | -// * 新增用户信息 | |
| 135 | -// * | |
| 136 | -// * @param user 用户信息 | |
| 137 | -// * @return 结果 | |
| 138 | -// */ | |
| 139 | -// public int insertUser(SysUser user); | |
| 140 | -// | |
| 141 | -// /** | |
| 142 | -// * 修改用户信息 | |
| 143 | -// * | |
| 144 | -// * @param user 用户信息 | |
| 145 | -// * @return 结果 | |
| 146 | -// */ | |
| 147 | -// public int updateUser(SysUser user); | |
| 148 | -// | |
| 149 | -// /** | |
| 150 | -// * 修改用户状态 | |
| 151 | -// * | |
| 152 | -// * @param user 用户信息 | |
| 153 | -// * @return 结果 | |
| 154 | -// */ | |
| 155 | -// public int updateUserStatus(SysUser user); | |
| 156 | -// | |
| 157 | -// /** | |
| 158 | 91 | // * 修改用户基本信息 |
| 159 | 92 | // * |
| 160 | 93 | // * @param user 用户信息 |
| ... | ... | @@ -187,22 +120,7 @@ public interface SysUserService { |
| 187 | 120 | // * @return 结果 |
| 188 | 121 | // */ |
| 189 | 122 | // public int resetUserPwd(String userName, String password); |
| 190 | -// | |
| 191 | -// /** | |
| 192 | -// * 通过用户ID删除用户 | |
| 193 | -// * | |
| 194 | -// * @param userId 用户ID | |
| 195 | -// * @return 结果 | |
| 196 | -// */ | |
| 197 | -// public int deleteUserById(Long userId); | |
| 198 | -// | |
| 199 | -// /** | |
| 200 | -// * 批量删除用户信息 | |
| 201 | -// * | |
| 202 | -// * @param userIds 需要删除的用户ID | |
| 203 | -// * @return 结果 | |
| 204 | -// */ | |
| 205 | -// public int deleteUserByIds(Long[] userIds); | |
| 123 | + | |
| 206 | 124 | // |
| 207 | 125 | // /** |
| 208 | 126 | // * 导入用户数据 | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/system/service/user/SysUserServiceImpl.java
| ... | ... | @@ -6,6 +6,7 @@ import cn.iocoder.dashboard.common.enums.CommonStatusEnum; |
| 6 | 6 | import cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil; |
| 7 | 7 | import cn.iocoder.dashboard.common.pojo.PageResult; |
| 8 | 8 | import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserCreateReqVO; |
| 9 | +import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserExportReqVO; | |
| 9 | 10 | import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserPageReqVO; |
| 10 | 11 | import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserUpdateReqVO; |
| 11 | 12 | import cn.iocoder.dashboard.modules.system.convert.user.SysUserConvert; |
| ... | ... | @@ -77,15 +78,29 @@ public class SysUserServiceImpl implements SysUserService { |
| 77 | 78 | |
| 78 | 79 | @Override |
| 79 | 80 | public PageResult<SysUserDO> pageUsers(SysUserPageReqVO reqVO) { |
| 80 | - // 处理部门查询条件 | |
| 81 | - List<Long> deptIds = Collections.emptyList(); | |
| 82 | - if (reqVO.getDeptId() != null) { | |
| 83 | - deptIds = CollectionUtils.convertList(deptService.listDeptsByParentIdFromCache( | |
| 84 | - reqVO.getDeptId(), true), SysDeptDO::getId); | |
| 85 | - deptIds.add(reqVO.getDeptId()); | |
| 81 | + return SysUserConvert.INSTANCE.convertPage(userMapper.selectList(reqVO, | |
| 82 | + this.getDeptCondition(reqVO.getDeptId()))); | |
| 83 | + } | |
| 84 | + | |
| 85 | + @Override | |
| 86 | + public List<SysUserDO> listUsers(SysUserExportReqVO reqVO) { | |
| 87 | + return userMapper.selectList(reqVO, this.getDeptCondition(reqVO.getDeptId())); | |
| 88 | + } | |
| 89 | + | |
| 90 | + /** | |
| 91 | + * 获得部门条件:查询指定部门的子部门编号们,包括自身 | |
| 92 | + * | |
| 93 | + * @param deptId 部门编号 | |
| 94 | + * @return 部门编号集合 | |
| 95 | + */ | |
| 96 | + private Set<Long> getDeptCondition(Long deptId) { | |
| 97 | + if (deptId == null) { | |
| 98 | + return Collections.emptySet(); | |
| 86 | 99 | } |
| 87 | - // 执行查询 | |
| 88 | - return SysUserConvert.INSTANCE.convertPage(userMapper.selectList(reqVO, deptIds)); | |
| 100 | + Set<Long> deptIds = CollectionUtils.convertSet(deptService.listDeptsByParentIdFromCache( | |
| 101 | + deptId, true), SysDeptDO::getId); | |
| 102 | + deptIds.add(deptId); // 包括自身 | |
| 103 | + return deptIds; | |
| 89 | 104 | } |
| 90 | 105 | |
| 91 | 106 | @Override | ... | ... |
src/main/java/cn/iocoder/dashboard/util/collection/CollectionUtils.java
| 1 | 1 | package cn.iocoder.dashboard.util.collection; |
| 2 | 2 | |
| 3 | +import cn.hutool.core.collection.CollUtil; | |
| 3 | 4 | import cn.hutool.core.collection.CollectionUtil; |
| 4 | 5 | |
| 5 | 6 | import java.util.*; |
| ... | ... | @@ -19,37 +20,61 @@ public class CollectionUtils { |
| 19 | 20 | } |
| 20 | 21 | |
| 21 | 22 | public static <T> List<T> filterList(Collection<T> from, Predicate<T> predicate) { |
| 23 | + if (CollUtil.isEmpty(from)) { | |
| 24 | + return new ArrayList<>(); | |
| 25 | + } | |
| 22 | 26 | return from.stream().filter(predicate).collect(Collectors.toList()); |
| 23 | 27 | } |
| 24 | 28 | |
| 25 | 29 | public static <T, U> List<U> convertList(List<T> from, Function<T, U> func) { |
| 30 | + if (CollUtil.isEmpty(from)) { | |
| 31 | + return new ArrayList<>(); | |
| 32 | + } | |
| 26 | 33 | return from.stream().map(func).collect(Collectors.toList()); |
| 27 | 34 | } |
| 28 | 35 | |
| 29 | 36 | public static <T, U> Set<U> convertSet(List<T> from, Function<T, U> func) { |
| 37 | + if (CollUtil.isEmpty(from)) { | |
| 38 | + return new HashSet<>(); | |
| 39 | + } | |
| 30 | 40 | return from.stream().map(func).collect(Collectors.toSet()); |
| 31 | 41 | } |
| 32 | 42 | |
| 33 | 43 | public static <T, K> Map<K, T> convertMap(List<T> from, Function<T, K> keyFunc) { |
| 44 | + if (CollUtil.isEmpty(from)) { | |
| 45 | + return new HashMap<>(); | |
| 46 | + } | |
| 34 | 47 | return from.stream().collect(Collectors.toMap(keyFunc, item -> item)); |
| 35 | 48 | } |
| 36 | 49 | |
| 37 | 50 | public static <T, K, V> Map<K, V> convertMap(List<T> from, Function<T, K> keyFunc, Function<T, V> valueFunc) { |
| 51 | + if (CollUtil.isEmpty(from)) { | |
| 52 | + return new HashMap<>(); | |
| 53 | + } | |
| 38 | 54 | return from.stream().collect(Collectors.toMap(keyFunc, valueFunc)); |
| 39 | 55 | } |
| 40 | 56 | |
| 41 | 57 | public static <T, K> Map<K, List<T>> convertMultiMap(List<T> from, Function<T, K> keyFunc) { |
| 58 | + if (CollUtil.isEmpty(from)) { | |
| 59 | + return new HashMap<>(); | |
| 60 | + } | |
| 42 | 61 | return from.stream().collect(Collectors.groupingBy(keyFunc, |
| 43 | 62 | Collectors.mapping(t -> t, Collectors.toList()))); |
| 44 | 63 | } |
| 45 | 64 | |
| 46 | 65 | public static <T, K, V> Map<K, List<V>> convertMultiMap(List<T> from, Function<T, K> keyFunc, Function<T, V> valueFunc) { |
| 66 | + if (CollUtil.isEmpty(from)) { | |
| 67 | + return new HashMap<>(); | |
| 68 | + } | |
| 47 | 69 | return from.stream().collect(Collectors.groupingBy(keyFunc, |
| 48 | 70 | Collectors.mapping(valueFunc, Collectors.toList()))); |
| 49 | 71 | } |
| 50 | 72 | |
| 51 | 73 | // 暂时没想好名字,先以 2 结尾噶 |
| 52 | 74 | public static <T, K, V> Map<K, Set<V>> convertMultiMap2(List<T> from, Function<T, K> keyFunc, Function<T, V> valueFunc) { |
| 75 | + if (CollUtil.isEmpty(from)) { | |
| 76 | + return new HashMap<>(); | |
| 77 | + } | |
| 53 | 78 | return from.stream().collect(Collectors.groupingBy(keyFunc, Collectors.mapping(valueFunc, Collectors.toSet()))); |
| 54 | 79 | } |
| 55 | 80 | ... | ... |
src/main/java/cn/iocoder/dashboard/util/collection/MapUtils.java
| 1 | 1 | package cn.iocoder.dashboard.util.collection; |
| 2 | 2 | |
| 3 | +import cn.hutool.core.collection.CollUtil; | |
| 3 | 4 | import cn.hutool.core.collection.CollectionUtil; |
| 4 | 5 | import com.google.common.collect.Multimap; |
| 5 | 6 | |
| 6 | 7 | import java.util.ArrayList; |
| 7 | 8 | import java.util.Collection; |
| 8 | 9 | import java.util.List; |
| 10 | +import java.util.Map; | |
| 11 | +import java.util.function.Consumer; | |
| 9 | 12 | |
| 10 | 13 | /** |
| 11 | 14 | * Map 工具类 |
| ... | ... | @@ -14,6 +17,13 @@ import java.util.List; |
| 14 | 17 | */ |
| 15 | 18 | public class MapUtils { |
| 16 | 19 | |
| 20 | + /** | |
| 21 | + * 从哈希表表中,获得 keys 对应的所有 value 数组 | |
| 22 | + * | |
| 23 | + * @param multimap 哈希表 | |
| 24 | + * @param keys keys | |
| 25 | + * @return value 数组 | |
| 26 | + */ | |
| 17 | 27 | public static <K, V> List<V> getList(Multimap<K, V> multimap, Collection<K> keys) { |
| 18 | 28 | List<V> result = new ArrayList<>(); |
| 19 | 29 | keys.forEach(k -> { |
| ... | ... | @@ -26,4 +36,23 @@ public class MapUtils { |
| 26 | 36 | return result; |
| 27 | 37 | } |
| 28 | 38 | |
| 39 | + /** | |
| 40 | + * 从哈希表查找到 key 对应的 value,然后进一步处理 | |
| 41 | + * 注意,如果查找到的 value 为 null 时,不进行处理 | |
| 42 | + * | |
| 43 | + * @param map 哈希表 | |
| 44 | + * @param key key | |
| 45 | + * @param consumer 进一步处理的逻辑 | |
| 46 | + */ | |
| 47 | + public static <K, V> void findAndThen(Map<K, V> map, K key, Consumer<V> consumer) { | |
| 48 | + if (CollUtil.isEmpty(map)) { | |
| 49 | + return; | |
| 50 | + } | |
| 51 | + V value = map.get(key); | |
| 52 | + if (value == null) { | |
| 53 | + return; | |
| 54 | + } | |
| 55 | + consumer.accept(value); | |
| 56 | + } | |
| 57 | + | |
| 29 | 58 | } | ... | ... |