diff --git a/README.md b/README.md index eaf21f20..cf51c5d5 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,14 @@ | 后端工程 | https://gitee.com/youlaiorg/youlai-boot | | 前端工程 | https://gitee.com/youlaiorg/vue3-element-admin | + + +## 接口文档 + +- `knife4j` 接口文档:[http://localhost:8989/doc.html](http://localhost:8989/doc.html) + +- `swagger` 接口文档:[http://localhost:8989/swagger-ui/index.html](http://localhost:8989/swagger-ui/index.html) + ## 项目运行 ### 1. 数据库创建 @@ -38,7 +46,7 @@ ### 4. 前端启动 -参考前端工程说明文档:[README.md](https://gitee.com/youlaiorg/vue3-element-admin#%E9%A1%B9%E7%9B%AE%E5%90%AF%E5%8A%A8) +文档:[README.md](https://gitee.com/youlaiorg/vue3-element-admin#%E9%A1%B9%E7%9B%AE%E5%90%AF%E5%8A%A8) ## 开发规范 diff --git a/src/main/java/com/youlai/system/common/util/ExcelUtils.java b/src/main/java/com/youlai/system/common/util/ExcelUtils.java index f107230b..d9ba301c 100644 --- a/src/main/java/com/youlai/system/common/util/ExcelUtils.java +++ b/src/main/java/com/youlai/system/common/util/ExcelUtils.java @@ -1,7 +1,6 @@ package com.youlai.system.common.util; import com.alibaba.excel.EasyExcel; -import com.youlai.system.framework.easyexcel.ExcelResult; import com.youlai.system.framework.easyexcel.MyAnalysisEventListener; import java.io.InputStream; @@ -14,11 +13,9 @@ import java.io.InputStream; */ public class ExcelUtils { - public static ExcelResult importExcel(InputStream is, Class clazz, MyAnalysisEventListener listener) { + public static String importExcel(InputStream is, Class clazz, MyAnalysisEventListener listener) { EasyExcel.read(is, clazz, listener).sheet().doRead(); - ExcelResult excelResult = listener.getResult(); - return excelResult; + String msg = listener.getMsg(); + return msg; } - - } diff --git a/src/main/java/com/youlai/system/config/WebMvcConfig.java b/src/main/java/com/youlai/system/config/WebMvcConfig.java index 92911c96..5da79802 100644 --- a/src/main/java/com/youlai/system/config/WebMvcConfig.java +++ b/src/main/java/com/youlai/system/config/WebMvcConfig.java @@ -4,20 +4,20 @@ import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import jakarta.validation.Validation; +import jakarta.validation.Validator; +import jakarta.validation.ValidatorFactory; import lombok.extern.slf4j.Slf4j; import org.hibernate.validator.HibernateValidator; import org.springframework.beans.factory.config.AutowireCapableBeanFactory; -import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.validation.beanvalidation.SpringConstraintValidatorFactory; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; -import jakarta.validation.Validation; -import jakarta.validation.Validator; -import jakarta.validation.ValidatorFactory; import java.math.BigInteger; import java.text.SimpleDateFormat; import java.util.List; @@ -29,6 +29,8 @@ public class WebMvcConfig implements WebMvcConfigurer { @Override public void configureMessageConverters(List> converters) { + converters.add(new StringHttpMessageConverter()); + MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter(); ObjectMapper objectMapper = jackson2HttpMessageConverter.getObjectMapper(); objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); @@ -42,7 +44,7 @@ public class WebMvcConfig implements WebMvcConfigurer { objectMapper.registerModule(simpleModule); jackson2HttpMessageConverter.setObjectMapper(objectMapper); - converters.add(0, jackson2HttpMessageConverter); + converters.add(jackson2HttpMessageConverter); } @Bean diff --git a/src/main/java/com/youlai/system/controller/SysUserController.java b/src/main/java/com/youlai/system/controller/SysUserController.java index 6586e07b..d8abb02d 100644 --- a/src/main/java/com/youlai/system/controller/SysUserController.java +++ b/src/main/java/com/youlai/system/controller/SysUserController.java @@ -7,7 +7,6 @@ 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.framework.easyexcel.ExcelResult; import com.youlai.system.listener.UserImportListener; import com.youlai.system.pojo.vo.UserImportVO; import com.youlai.system.pojo.form.UserForm; @@ -149,8 +148,8 @@ public class SysUserController { @PostMapping("/_import") public Result importUsers(@Parameter(name = "部门ID") Long deptId, MultipartFile file) throws IOException { UserImportListener listener = new UserImportListener(deptId); - ExcelResult excelResult = ExcelUtils.importExcel(file.getInputStream(), UserImportVO.class, listener); - return Result.success(excelResult.getMsg()); + String msg = ExcelUtils.importExcel(file.getInputStream(), UserImportVO.class, listener); + return Result.success(msg); } @Operation(summary = "导出用户") diff --git a/src/main/java/com/youlai/system/converter/UserConverter.java b/src/main/java/com/youlai/system/converter/UserConverter.java index 7bdd02ec..7dbb7bcb 100644 --- a/src/main/java/com/youlai/system/converter/UserConverter.java +++ b/src/main/java/com/youlai/system/converter/UserConverter.java @@ -5,6 +5,7 @@ import com.youlai.system.pojo.bo.UserBO; import com.youlai.system.pojo.entity.SysUser; import com.youlai.system.pojo.form.UserForm; import com.youlai.system.pojo.bo.UserFormBO; +import com.youlai.system.pojo.vo.UserImportVO; import com.youlai.system.pojo.vo.UserInfoVO; import com.youlai.system.pojo.vo.UserPageVO; import org.mapstruct.InheritInverseConfiguration; @@ -22,13 +23,13 @@ import org.mapstruct.Mappings; public interface UserConverter { @Mappings({ - @Mapping(target = "genderLabel", expression = "java(com.youlai.system.common.base.IBaseEnum.getLabelByValue(po.getGender(), com.youlai.system.common.enums.GenderEnum.class))") + @Mapping(target = "genderLabel", expression = "java(com.youlai.system.common.base.IBaseEnum.getLabelByValue(bo.getGender(), com.youlai.system.common.enums.GenderEnum.class))") }) - UserPageVO po2Vo(UserBO po); + UserPageVO bo2Vo(UserBO bo); - Page po2Vo(Page po); + Page bo2Vo(Page bo); - UserForm po2Form(UserFormBO po); + UserForm bo2Form(UserFormBO bo); UserForm entity2Form(SysUser entity); @@ -38,7 +39,8 @@ public interface UserConverter { @Mappings({ @Mapping(target = "userId", source = "id") }) - UserInfoVO entity2LoginUser(SysUser entity); + UserInfoVO entity2UserInfoVo(SysUser entity); + SysUser importVo2Entity(UserImportVO vo); } diff --git a/src/main/java/com/youlai/system/framework/easyexcel/ExcelResult.java b/src/main/java/com/youlai/system/framework/easyexcel/ExcelResult.java deleted file mode 100644 index d1a37136..00000000 --- a/src/main/java/com/youlai/system/framework/easyexcel/ExcelResult.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.youlai.system.framework.easyexcel; - -import java.util.List; - -/** - * Excel 读取结果 - * - * @author: haoxr - * @date: 2023/03/01 - */ -public interface ExcelResult { - - List getList(); - - String getMsg(); - -} diff --git a/src/main/java/com/youlai/system/framework/easyexcel/MyAnalysisEventListener.java b/src/main/java/com/youlai/system/framework/easyexcel/MyAnalysisEventListener.java index 00259e60..6dec9710 100644 --- a/src/main/java/com/youlai/system/framework/easyexcel/MyAnalysisEventListener.java +++ b/src/main/java/com/youlai/system/framework/easyexcel/MyAnalysisEventListener.java @@ -9,5 +9,7 @@ import com.alibaba.excel.event.AnalysisEventListener; * @date: 2023/03/01 */ public abstract class MyAnalysisEventListener extends AnalysisEventListener { - public abstract ExcelResult getResult(); + + private String msg; + public abstract String getMsg(); } diff --git a/src/main/java/com/youlai/system/framework/mybatisplus/MyDataPermissionHandler.java b/src/main/java/com/youlai/system/framework/mybatisplus/MyDataPermissionHandler.java index efe7c894..49d6161b 100644 --- a/src/main/java/com/youlai/system/framework/mybatisplus/MyDataPermissionHandler.java +++ b/src/main/java/com/youlai/system/framework/mybatisplus/MyDataPermissionHandler.java @@ -79,7 +79,7 @@ public class MyDataPermissionHandler implements DataPermissionHandler { // 默认部门及子部门数据权限 default: deptId = SecurityUtils.getDeptId(); - appendSqlStr = deptColumnName + " IN ( SELECT id FROM sys_dept WHERE id = " + deptId + " or find_in_set( " + deptId + " , tree_path ) )"; + appendSqlStr = deptColumnName + " IN ( SELECT id FROM sys_dept WHERE id = " + deptId + " OR FIND_IN_SET( " + deptId + " , tree_path ) )"; break; } diff --git a/src/main/java/com/youlai/system/listener/UserImportListener.java b/src/main/java/com/youlai/system/listener/UserImportListener.java index b8f14af3..c17d382a 100644 --- a/src/main/java/com/youlai/system/listener/UserImportListener.java +++ b/src/main/java/com/youlai/system/listener/UserImportListener.java @@ -1,21 +1,29 @@ package com.youlai.system.listener; +import cn.hutool.core.lang.Validator; +import cn.hutool.core.util.StrUtil; import cn.hutool.extra.spring.SpringUtil; import cn.hutool.json.JSONUtil; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.util.ListUtils; -import com.youlai.system.framework.easyexcel.ExcelResult; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.youlai.system.common.base.IBaseEnum; +import com.youlai.system.common.constant.SystemConstants; +import com.youlai.system.common.enums.GenderEnum; +import com.youlai.system.converter.UserConverter; import com.youlai.system.framework.easyexcel.MyAnalysisEventListener; +import com.youlai.system.pojo.entity.SysUser; import com.youlai.system.pojo.vo.UserImportVO; import com.youlai.system.service.SysUserService; import lombok.extern.slf4j.Slf4j; +import org.springframework.security.crypto.password.PasswordEncoder; import java.util.List; /** * 用户导入监听器 *

- * https://easyexcel.opensource.alibaba.com/docs/current/quickstart/read + * 最简单的读监听器:https://easyexcel.opensource.alibaba.com/docs/current/quickstart/read * * @author haoxr * @date 2022/4/10 20:49 @@ -28,11 +36,19 @@ public class UserImportListener extends MyAnalysisEventListener { */ private static final int BATCH_COUNT = 100; + private int validCount; + + private int invalidCount; + + private int currentIndex; + + StringBuilder msg = new StringBuilder(); + + /** * 缓存的数据 */ - private List cachedUserList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT); - + private List cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT); /** * 部门ID @@ -41,12 +57,17 @@ public class UserImportListener extends MyAnalysisEventListener { private final SysUserService userService; + private final PasswordEncoder passwordEncoder; + + private final UserConverter userConverter; + public UserImportListener(Long deptId) { this.deptId = deptId; this.userService = SpringUtil.getBean(SysUserService.class); + this.passwordEncoder = SpringUtil.getBean(PasswordEncoder.class); + this.userConverter = SpringUtil.getBean(UserConverter.class); } - /** * 每一条数据解析都会来调用 * @@ -56,10 +77,61 @@ public class UserImportListener extends MyAnalysisEventListener { @Override public void invoke(UserImportVO userImportVO, AnalysisContext analysisContext) { log.info("解析到一条用户数据:{}", JSONUtil.toJsonStr(userImportVO)); + currentIndex++; + StringBuilder rowMsg = new StringBuilder(); + boolean rowFlag = true; + // 校验数据 + + String username = userImportVO.getUsername(); + if (StrUtil.isBlank(username)) { + rowFlag = false; + rowMsg.append("用户名为空;"); + } else { + long count = userService.count(new LambdaQueryWrapper().eq(SysUser::getUsername, username)); + if (count > 0) { + rowFlag = false; + rowMsg.append("用户名已存在;"); + } + } + + String nickname = userImportVO.getNickname(); + if (StrUtil.isBlank(nickname)) { + rowFlag = false; + rowMsg.append("用户昵称为空;"); + } + String mobile = userImportVO.getMobile(); + if (StrUtil.isBlank(mobile)) { + rowFlag = false; + rowMsg.append("手机号码为空;"); + } else { + if (!Validator.isMobile(mobile)) { + rowFlag = false; + rowMsg.append("手机号码不正确;"); + } + } + if (rowFlag) { + validCount++; + SysUser entity = userConverter.importVo2Entity(userImportVO); + // 默认密码 + entity.setPassword(passwordEncoder.encode(SystemConstants.DEFAULT_PASSWORD)); + // 性别转换 + Integer gender = (Integer) IBaseEnum.getValueByLabel(userImportVO.getGender(), GenderEnum.class); + entity.setGender(gender); + entity.setDeptId(deptId); + cachedDataList.add(entity); + } else { + invalidCount++; + msg.append("第" + currentIndex + "行数据校验失败:").append(rowMsg + "
"); + } + + if (cachedDataList.size() > BATCH_COUNT) { + saveData(); + cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT); + } } @@ -70,21 +142,20 @@ public class UserImportListener extends MyAnalysisEventListener { */ @Override public void doAfterAllAnalysed(AnalysisContext analysisContext) { + // 这里也要保存数据,确保最后遗留的数据也存储到数据库 + saveData(); + msg = new StringBuilder("导入用户结束:成功" + validCount + "条;失败" + invalidCount + "条
").append(msg); + } + /** + * 存储数据库 + */ + private void saveData() { + userService.saveBatch(cachedDataList); } @Override - public ExcelResult getResult() { - return new ExcelResult() { - @Override - public List getList() { - return null; - } - - @Override - public String getMsg() { - return null; - } - }; + public String getMsg() { + return this.msg.toString(); } } diff --git a/src/main/java/com/youlai/system/service/SysUserService.java b/src/main/java/com/youlai/system/service/SysUserService.java index 5b766736..93b379de 100644 --- a/src/main/java/com/youlai/system/service/SysUserService.java +++ b/src/main/java/com/youlai/system/service/SysUserService.java @@ -85,13 +85,6 @@ public interface SysUserService extends IService { UserAuthInfo getUserAuthInfo(String username); - /** - * 导入用户 - * - * @param userImportVO - * @return - */ - String importUsers(UserImportVO userImportVO) throws IOException; /** * 获取导出用户列表 diff --git a/src/main/java/com/youlai/system/service/impl/SysUserServiceImpl.java b/src/main/java/com/youlai/system/service/impl/SysUserServiceImpl.java index 857337a1..511506cc 100644 --- a/src/main/java/com/youlai/system/service/impl/SysUserServiceImpl.java +++ b/src/main/java/com/youlai/system/service/impl/SysUserServiceImpl.java @@ -19,7 +19,6 @@ import com.youlai.system.pojo.entity.SysUser; import com.youlai.system.pojo.form.UserForm; import com.youlai.system.pojo.query.UserPageQuery; import com.youlai.system.pojo.vo.UserExportVO; -import com.youlai.system.pojo.vo.UserImportVO; import com.youlai.system.pojo.vo.UserInfoVO; import com.youlai.system.pojo.vo.UserPageVO; import com.youlai.system.service.SysMenuService; @@ -32,7 +31,6 @@ import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.io.IOException; import java.util.Arrays; import java.util.List; import java.util.Set; @@ -49,7 +47,9 @@ import java.util.stream.Collectors; public class SysUserServiceImpl extends ServiceImpl implements SysUserService { private final PasswordEncoder passwordEncoder; + private final SysUserRoleService userRoleService; + private final UserConverter userConverter; private final SysMenuService menuService; @@ -73,10 +73,10 @@ public class SysUserServiceImpl extends ServiceImpl impl Page page = new Page<>(pageNum, pageSize); // 查询数据 - Page userPoPage = this.baseMapper.listUserPages(page, queryParams); + Page userBoPage = this.baseMapper.listUserPages(page, queryParams); // 实体转换 - Page userVoPage = userConverter.po2Vo(userPoPage); + Page userVoPage = userConverter.bo2Vo(userBoPage); return userVoPage; } @@ -91,7 +91,7 @@ public class SysUserServiceImpl extends ServiceImpl impl public UserForm getUserFormData(Long userId) { UserFormBO userFormBO = this.baseMapper.getUserDetail(userId); // 实体转换po->form - UserForm userForm = userConverter.po2Form(userFormBO); + UserForm userForm = userConverter.bo2Form(userFormBO); return userForm; } @@ -216,19 +216,6 @@ public class SysUserServiceImpl extends ServiceImpl impl return userAuthInfo; } - /** - * 导入用户 - * - * @param userImportVO - * @return - */ - @Transactional - @Override - public String importUsers(UserImportVO userImportVO) throws IOException { - - return "导入成功"; - - } /** * 获取导出用户列表 @@ -259,14 +246,14 @@ public class SysUserServiceImpl extends ServiceImpl impl ) ); // entity->VO - UserInfoVO userInfoVO = userConverter.entity2LoginUser(user); + UserInfoVO userInfoVO = userConverter.entity2UserInfoVo(user); // 用户角色集合 Set roles = SecurityUtils.getRoles(); userInfoVO.setRoles(roles); // 用户权限集合 - Set perms = (Set)redisTemplate.opsForValue().get("USER_PERMS:" + user.getId()); + Set perms = (Set) redisTemplate.opsForValue().get("USER_PERMS:" + user.getId()); userInfoVO.setPerms(perms); return userInfoVO; diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 945358ae..edfd6936 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -53,3 +53,11 @@ minio: # 自定义域名(非必须),Nginx配置反向代理转发文件路径 custom-domain: + +# 接口文档 +springdoc: + swagger-ui: + enabled: true + api-docs: + enabled: true + diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml index f9645975..4e6c1997 100644 --- a/src/main/resources/application-prod.yml +++ b/src/main/resources/application-prod.yml @@ -46,11 +46,18 @@ auth: # MinIO 分布式文件系统 minio: - endpoint: http://localhost:9000 + endpoint: http://www.youlai.tech:9000 access-key: minioadmin - secret-key: minioadmin - # 存储桶名称 - bucket-name: default + secret-key: youlaitech + bucket-name: youlai-boot # 自定义域名(非必须),Nginx配置反向代理转发文件路径 - custom-domain: + custom-domain: https://oss.youlai.tech + + +# 接口文档 +springdoc: + swagger-ui: + enabled: true + api-docs: + enabled: true diff --git a/src/main/resources/excel-templates/用户导入模板.xlsx b/src/main/resources/excel-templates/用户导入模板.xlsx index 60166214..36a208cc 100644 Binary files a/src/main/resources/excel-templates/用户导入模板.xlsx and b/src/main/resources/excel-templates/用户导入模板.xlsx differ diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml index a7dae9aa..bb4b5a08 100644 --- a/src/main/resources/logback-spring.xml +++ b/src/main/resources/logback-spring.xml @@ -10,7 +10,7 @@ - true + DEBUG