commit 68636e5209f7e9cbb11ea2d3c2a24593fba144e9 Author: Bunny <1319900154@qq.com> Date: Mon Nov 11 12:03:29 2024 +0800 init diff --git a/ LICENSE b/ LICENSE new file mode 100644 index 0000000..e796427 --- /dev/null +++ b/ LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Bunny + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a593848 --- /dev/null +++ b/.gitignore @@ -0,0 +1,36 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ +logs/ +!**/src/main/resources/application-prod.yml + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/ReadMe.md b/ReadMe.md new file mode 100644 index 0000000..6819f37 --- /dev/null +++ b/ReadMe.md @@ -0,0 +1,943 @@ +# 项目预览 + +不知道为什么,图床用的使自己的,Gitee就是不显示其它GitHub和Gitea都能显示就Gitee显示不出来 + +或者把项目clone下来看也可以 + +**线上地址** + +- 正式线上预览地址:http://111.229.137.235/#/welcome + +- 测试预览地址:http://106.15.251.123/#/welcome + - 服务器到期时间:12月30日 + +**Github地址** + +- [前端地址](https://github.com/BunnyMaster/bunny-admin-web.git) +- [后端地址](https://github.com/BunnyMaster/bunny-admin-server) + +**Gitee地址** + +- [前端地址](https://gitee.com/BunnyBoss/bunny-admin-web) +- [后端地址](https://gitee.com/BunnyBoss/bunny-admin-server) + +## 环境搭建 + +### 安装docker内容 + +如果使用是centos或者是rocky + +```shell +# 更新yum 和 dnf +yum update -y +dnf update -y + +# 安装必要依赖 +yum install -y yum-utils device-mapper-persistent-data lvm2 + +# 设置镜像源 +sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo +yum list docker-ce --showduplicates | sort -r + +# 安装docker +yum -y install docker-ce.x86_64 + +# 开机启动docker +systemctl enable docker +systemctl start docker +``` + +### 安装Redis + +#### 编写配置文件 + +```sh +mkdir /bunny/docker_data/my_redis/ -p +vim /bunny/docker_data/my_redis/redis.conf +``` + +**添加以下内容** + +有注释大概率启动不了 + +``` +# bind 127.0.0.1 #注释掉这部分,使redis可以外部访问 +daemonize no #用守护线程的方式启动 +requirepass 123456 +appendonly yes #redis持久化  默认是no +tcp-keepalive 300 #防止出现远程主机强迫关闭了一个现有的连接的错误 默认是300 +``` + +**删除注释** + +``` +daemonize no +requirepass 123456 +appendonly yes +tcp-keepalive 300 +``` + +#### 启动Redis + +```sh +docker pull redis:7.0.10 +docker run -p 6379:6379 --name redis_master \ +-v /bunny/docker_data/redis_master/redis.conf:/etc/redis/redis.conf \ +-v/bunny/docker_data/redis_master/data:/data \ +--restart=always -d redis:7.0.10 --appendonly yes +``` + +### 安装Minio + +```sh +docker run -d \ + -p 9000:9000 \ + -p 9090:9090 \ + --name minio_master --restart=always \ + -v /bunny/docker/minio/data:/data \ + -e "MINIO_ROOT_USER=bunny" \ + -e "MINIO_ROOT_PASSWORD=02120212" \ + minio/minio server /data --console-address ":9090" +``` + +### 安装MySQL + +**设置开机启动** + +**执行启动3306:** + +```sh +docker stop master +docker rm master + +docker run --name master -p 3306:3306 \ +-v /bunny/docker_data/mysql/master/etc/my.cnf:/etc/my.cnf \ +-v /bunny/docker_data/mysql/master/data:/var/lib/mysql \ +--restart=always --privileged=true \ + -e MYSQL_ROOT_PASSWORD=02120212 \ + -e TZ=Asia/Shanghai \ + mysql:8.0.33 --lower-case-table-names=1 +``` + +**执行启动3304:** + +其中有创建备份目录 + +```shell +docker stop slave_3304 +docker rm slave_3304 + +docker run --name slave_3304 -p 3304:3306 \ + -v /bunny/docker_data/mysql/slave_3304/etc/my.cnf:/etc/my.cnf \ + -v /bunny/docker_data/mysql/slave_3304/data:/var/lib/mysql \ + -v /bunny/docker_data/mysql/slave_3304/backup:\ + --restart=always --privileged=true \ + -e MYSQL_ROOT_PASSWORD=02120212 \ + -e TZ=Asia/Shanghai \ + mysql:8.0.33 --lower-case-table-names=1 +``` + +**修改密码:** + +```sh +docker exec -it mysql_master /bin/bash +mysql -uroot -p02120212 +use mysql +ALTER USER 'root'@'%' IDENTIFIED BY "02120212"; +FLUSH PRIVILEGES; +``` + +> my.cnf 配置 +> +> ```sql +> [mysqld] +> skip-host-cache +> skip-name-resolve +> secure-file-priv=/var/lib/mysql-files +> user=mysql +> +> # 设置字符集 +> character-set-server=utf8mb4 +> collation-server=utf8mb4_unicode_ci +> +> # 设置服务器ID(如果是复制集群,确保每个节点的ID唯一) +> server-id=1 +> +> # 启用二进制日志 +> log-bin=mysql-bin +> +> # 设置表名不区分大小写 +> lower_case_table_names = 1 +> +> ``` + +### 数据库文件 + +在后端文件的根目录中 + +![image-20241107133345299](http://116.196.101.14:9000/docs/image-20241107133345299.png) + +# 项目特点 + +### 按钮权限显示 + +如果当前用户在这个页面中只有【添加】和【删除】那么页面按钮中只会显示出【添加按钮】和【删除按钮】 + +### 去除前后空格 + +后端配置了自动去除前端传递的空字符串,如果传递的内容前后有空格会自动去除前后的空格 + +![image-20241105215241811](http://116.196.101.14:9000/docs/image-20241105215241811.png) + +代码内容 + +```java +@ControllerAdvice +public class ControllerStringParamTrimConfig { + + /** + * 创建 String trim 编辑器 + * 构造方法中 boolean 参数含义为如果是空白字符串,是否转换为null + * 即如果为true,那么 " " 会被转换为 null,否者为 "" + */ + @InitBinder + public void initBinder(WebDataBinder binder) { + StringTrimmerEditor propertyEditor = new StringTrimmerEditor(false); + // 为 String 类对象注册编辑器 + binder.registerCustomEditor(String.class, propertyEditor); + } + + @Bean + public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() { + return jacksonObjectMapperBuilder -> { + // 为 String 类型自定义反序列化操作 + jacksonObjectMapperBuilder + .deserializerByType(String.class, new StdScalarDeserializer(String.class) { + @Override + public String deserialize(JsonParser jsonParser, DeserializationContext ctx) throws IOException { + // 去除全部空格 + // return StringUtils.trimAllWhitespace(jsonParser.getValueAsString()); + // 仅去除前后空格 + return jsonParser.getValueAsString().trim(); + } + }); + }; + } +} +``` + +### 项目接口和页面 + +接口地址有两个: + +1. knife4j +2. swagger + +接口地址://localhost:7070/doc.html#/home + +![image-20241105213953503](http://116.196.101.14:9000/docs/image-20241105213953503.png) + +swagger接口地址:http://localhost:7070/swagger-ui/index.html + +![image-20241105214100720](http://116.196.101.14:9000/docs/image-20241105214100720.png) + +前端接口地址:http://localhost:7000/#/welcome + +![image-20241105214230389](http://116.196.101.14:9000/docs/image-20241105214230389.png) + +## 登录功能 + +可以选择邮箱登录或者是密码直接登录,两者不互用。 + +### 账号登录 + +![image-20241105212146456](http://116.196.101.14:9000/docs/image-20241105212146456.png) + +#### 业务需求 + +- 用户输入用户名和密码进行登录 + +#### 实现思路 + +- 用户输入账号和密码和数据库中账号密码进行比对,成功后进行页面跳转 +- 如果账户禁用会显示账户已封禁 + +**后端实现文件位置** + +- 拦截请求为`/admin/login`的请求之后进行登录验证的判断 + +![image-20241105212722043](http://116.196.101.14:9000/docs/image-20241105212722043.png) + +### 邮箱登录 + +![image-20241105212255972](http://116.196.101.14:9000/docs/image-20241105212255972.png) + +#### 业务需求 + +- 用户输入邮箱账号、密码、邮箱验证码之后进行登录 + +#### 实现思路 + +- 需要验证用户输入的邮箱格式是否正确。 +- 在未输入验证码的情况下输入密码会提示用户,同时后端也会进行验证。如果输入了邮箱验证码但是Redis中不存在或已过期,会提示:邮箱验证码不存在或已过期。 +- 之后对邮箱账号和密码进行判断包括邮箱验证码进行判断 +- 判断逻辑如下,文件位置如上图所示。 + +```java +/** + * * 自定义验证 + * 判断邮箱验证码是否正确 + */ +@Override +public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) { + ObjectMapper objectMapper = new ObjectMapper(); + try { + loginDto = objectMapper.readValue(request.getInputStream(), LoginDto.class); + + // type不能为空 + String type = loginDto.getType(); + if (!StringUtils.hasText(type)) { + out(response, Result.error(ResultCodeEnum.REQUEST_IS_EMPTY)); + return null; + } + + String emailCode = loginDto.getEmailCode(); + String username = loginDto.getUsername(); + String password = loginDto.getPassword(); + + // 如果有邮箱验证码,表示是邮箱登录 + if (type.equals("email")) { + emailCode = emailCode.toLowerCase(); + Object redisEmailCode = redisTemplate.opsForValue().get(RedisUserConstant.getAdminUserEmailCodePrefix(username)); + if (redisEmailCode == null) { + out(response, Result.error(ResultCodeEnum.EMAIL_CODE_EMPTY)); + return null; + } + + // 判断用户邮箱验证码是否和Redis中发送的验证码 + if (!emailCode.equals(redisEmailCode.toString().toLowerCase())) { + out(response, Result.error(ResultCodeEnum.EMAIL_CODE_NOT_MATCHING)); + return null; + } + } + + Authentication authenticationToken = new UsernamePasswordAuthenticationToken(username, password); + return getAuthenticationManager().authenticate(authenticationToken); + } catch (IOException e) { + out(response, Result.error(ResultCodeEnum.ILLEGAL_DATA_REQUEST)); + return null; + } +} +``` + +## 首页功能 + +![image-20241105212403630](http://116.196.101.14:9000/docs/image-20241105212403630.png) + +功能菜单,首页图表展示部分功能已经由这个模板作者设计好,其中需要注意的是,如果要查看历史消息或者是进入消息页面可以双击![image-20241105213346408](http://116.196.101.14:9000/docs/image-20241105213346408.png)既可进入消息页面 + +### 消息功能 + +![image-20241105213539594](http://116.196.101.14:9000/docs/image-20241105213539594-1730813844820-2.png) + +#### 业务需求 + +1. 消息页面的展示,包含删除、批量删除、选中已读和当前页面所有消息都标为已读 +2. 当用户对左侧菜单点击时可以过滤出消息内容,展示不同的消息类型 + +![image-20241105213720011](http://116.196.101.14:9000/docs/image-20241105213720011.png) + +3. 可以点击已读和全部进行筛选消息 + +![image-20241105214342220](http://116.196.101.14:9000/docs/image-20241105214342220.png) + +3. 可以根据标题进行搜搜 +4. 包含分页 + +#### 实现思路 + +1. 显示当前消息类型,用户点击时带参数请求,只带当前消息类型,不默认携带已读状态查询,然后从数据库筛选并返回结果。 + +2. 点击"已读"选项时,若选择"全部"(之前是设置为undefined,这样就不会携带参数了,但是底下会有警告),现在改为空字符串,后端只需过滤掉空字符串即可。 + +3. 删除选定数据,若用户选择列表并筛选出所有ID,将数据传递给后端(用户删除为逻辑删除)。 + +4. 全部标为已读![image-20241106131949217](http://116.196.101.14:9000/docs/image-20241106131949217.png),类似删除操作,筛选出选中数据的ID,然后传递给后端以标记为已读。 + +5. 将所有数据标记为已读!当前页面前端使用map提取所有ID,整合成ID列表传递给后端,表示页面上所有数据已读。 + +6. 输入标题后,随输入变化进行搜索。 + +**后端代码位置** + +![image-20241105213922824](http://116.196.101.14:9000/docs/image-20241105213922824.png) + +### 用户管理 + +![image-20241106002713514](http://116.196.101.14:9000/docs/image-20241106002713514.png) + +#### 需求分析 + +1. 用户操作需要包含CURD的操作 +2. 为了方便在用户中需要给出快速禁用当前用户按钮 +3. 需要显示用户头像、性别、最后登录的IP地址和归属地 +4. 在左侧中需要包含部分查询 +5. 可以根据点击的部门查询当前部门下的用户 +6. 根据用户可以强制下线、管理员可以修改用户密码、为用户分配角色 + +![image-20241106002908657](http://116.196.101.14:9000/docs/image-20241106002908657.png) + +#### 实现思路 + +**上传头像** + +前端需要剪裁图片内容进行上传,后端将前端上传的头像存储到Minio中,在上传头像中可以有几菜单可以看到功能菜单。 + +![image-20241106003056116](http://116.196.101.14:9000/docs/image-20241106003056116.png) + +右击时可以看到功能菜单,如上传、下载等功能 + +![image-20241106003154056](http://116.196.101.14:9000/docs/image-20241106003154056.png) + +**重置密码** + +重置密码需要判断当前用户密码是否是符合指定的密码格式,并且会根据当前输入密码计算得分如果当前密码复杂则得分越高那么密码强度越强 + +![image-20241106003256994](http://116.196.101.14:9000/docs/image-20241106003256994.png) + +重置密码组件在前端的公共组件文件中 + +![image-20241106003426573](http://116.196.101.14:9000/docs/image-20241106003426573.png) + +**分配角色** + +- 给用户分配了admin角色后,其他路由绑定和权限设置就不再需要了,因为后端会根据admin角色在前端用户信息中设置通用权限码,如`*`、`*::*`、`*::*::*`,表示前端用户可以访问所有权限并查看所有内容。 +- 管理员有权对用户进行角色分配,这涉及到许多操作,包括菜单显示和接口访问权限。角色与权限相关联,角色也与菜单相关联。 + +- 当用户访问菜单时,会根据其角色看到其所属的菜单内容。随后,角色与权限接口相关联,根据用户的权限来决定是否显示操作按钮。后端会根据用户的权限验证其是否可以访问当前接口。 + +- 用户登录或刷新页面时会重新获取用户信息,用户信息中包含角色和权限信息。利用角色和权限信息与前端传递的路径进行比对判断,如果用户包含菜单角色,则可以访问。如果用户包含前端路由中的权限,则表示该权限可以访问。后端也会进行权限判断,以防止通过接口文档等方式访问。 + +- 分配好角色后,菜单会根据当前路由角色匹配用户角色,从而根据用户角色显示相应的菜单内容。 + +![image-20241106004533031](http://116.196.101.14:9000/docs/image-20241106004533031.png) + +### 角色管理 + +角色管理包含CURD和权限分配操作 + +![image-20241106132548236](http://116.196.101.14:9000/docs/image-20241106132548236.png) + +#### 业务需求 + +用户对角色进行CURD操作,点击权限设置时让用户分配权限 + +#### 实现思路 + +1. 在设计的表中,如果存在相同的角色码,系统会提示用户当前角色已经存在。 + +![image-20241106132938024](http://116.196.101.14:9000/docs/image-20241106132938024.png) + +2. 后端会根据角色的ID分配权限的ID列表。 + +![image-20241106135600255](http://116.196.101.14:9000/docs/image-20241106135600255.png) + +3. 后端在角色权限表中会根据角色的ID分配权限内容。在角色权限表中,会先删除当前角色所有的权限内容,然后再进行权限内容的重新分配。 + +```java +public void assignPowersToRole(AssignPowersToRoleDto dto) { + List powerIds = dto.getPowerIds(); + Long roleId = dto.getRoleId(); + + // 删除这个角色下所有权限 + baseMapper.deleteBatchRoleIdsWithPhysics(List.of(roleId)); + + // 保存分配数据 + List rolePowerList = powerIds.stream().map(powerId -> { + RolePower rolePower = new RolePower(); + rolePower.setRoleId(roleId); + rolePower.setPowerId(powerId); + return rolePower; + }).toList(); + saveBatch(rolePowerList); + + // 找到所有和当前更新角色相同的用户 + List roleIds = userRoleMapper.selectList(Wrappers.lambdaQuery().eq(UserRole::getRoleId, roleId)) + .stream().map(UserRole::getUserId).toList(); + + // 根据Id查找所有用户 + List adminUsers = userMapper.selectList(Wrappers.lambdaQuery().in(!roleIds.isEmpty(), AdminUser::getId, roleIds)); + + // 用户为空时不更新Redis的key + if (adminUsers.isEmpty()) return; + + // 更新Redis中用户信息 + List userIds = adminUsers.stream().map(AdminUser::getId).toList(); + roleFactory.updateUserRedisInfo(userIds); +} +``` + +### 权限管理 + +![image-20241106135954104](http://116.196.101.14:9000/docs/image-20241106135954104.png) + +![image-20241106140006176](http://116.196.101.14:9000/docs/image-20241106140006176.png) + +在权限配置中,添加/修改权限时的请求地址为后端接口的请求地址,请求地址使用了【`正则表达式`】判断和【`antpath`】方式填写 + +> ### 正则表达式 +> +> #### 作用和用法: +> +> - **作用**:正则表达式用于描述字符串的特征,可以用来匹配、查找、替换等字符串操作。 +> - **用法**:在Java中,可以使用`java.util.regex`包来支持正则表达式的使用。例如,可以使用`Pattern`和`Matcher`类来编译和匹配正则表达式。 +> +> #### 示例: +> +> ```java +> // 匹配邮箱地址的正则表达式示例 +> String emailRegex = "\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Z|a-z]{2,}\\b"; +> String email = "example@email.com"; +> +> Pattern pattern = Pattern.compile(emailRegex); +> Matcher matcher = pattern.matcher(email); +> +> if (matcher.find()) { +> System.out.println("Valid email address"); +> } else { +> System.out.println("Invalid email address"); +> } +> ``` +> +> ### Ant Path +> +> #### 作用和用法: +> +> - **作用**:Ant Path是Spring框架中用来匹配URL路径的一种模式匹配方式,类似于Unix系统中的路径匹配规则。 +> - **用法**:在Spring中,Ant Path可以用来匹配URL路径,例如在配置Spring的URL映射时可以使用Ant Path来指定匹配规则。 +> +> #### 示例: +> +> ```java +> // Ant Path示例 +> String pattern = "/users/*/profile"; +> String path = "/users/123/profile"; +> +> AntPathMatcher matcher = new AntPathMatcher(); +> if (matcher.match(pattern, path)) { +> System.out.println("Pattern matched!"); +> } else { +> System.out.println("Pattern not matched!"); +> } +> ``` +> +> Ant Path中支持一些通配符,例如`*`匹配任意字符(除了路径分隔符),`**`匹配任意字符,包括路径分隔符。Ant Path是一种方便的路径匹配方式,可以用来匹配URL路径、文件路径等。 + +#### 业务需求 + +1. 对权限表进行CURD操作 +2. 在表格中点击新增时,父级id为当前点击行的id + +#### 实现思路 + +点击当前行父级id为当前的行的id + +![image-20241106140420845](http://116.196.101.14:9000/docs/image-20241106140420845.png) + +#### 权限判断实现方式 + +##### 后端判断方式 + +判断权限是否可以访问,后端实现判断逻辑 + +![image-20241106003921315](http://116.196.101.14:9000/docs/image-20241106003921315.png) + +##### 前端判断方式 + +角色分配方式有下面几种想洗参考:https://pure-admin.github.io/vue-pure-admin/#/permission/button/router,[文档页面](https://pure-admin.github.io/pure-admin-doc/pages/routerMenu/#%E4%B8%BA%E4%BB%80%E4%B9%88%E8%B7%AF%E7%94%B1%E7%9A%84-name-%E5%BF%85%E5%86%99-%E8%80%8C%E4%B8%94%E5%BF%85%E9%A1%BB%E5%94%AF%E4%B8%80) + +1. 使用标签方式 + +![image-20241106004247600](http://116.196.101.14:9000/docs/image-20241106004247600.png) + +2. 使用函数方式 + +![image-20241106004310635](http://116.196.101.14:9000/docs/image-20241106004310635.png) + +3. 使用指令方式 + +![image-20241106005252328](http://116.196.101.14:9000/docs/image-20241106005252328.png) + +在前端utils文件夹下有`auth.ts`文件里面包含了权限码信息,如果当前菜单属性中包含这个权限码表示可以访问这个权限 + +![image-20241106004433489](http://116.196.101.14:9000/docs/image-20241106004433489.png) + +![image-20241106004500855](http://116.196.101.14:9000/docs/image-20241106004500855.png) + +### 菜单管理 + +![image-20241106140545328](http://116.196.101.14:9000/docs/image-20241106140545328.png) + +### 菜单路由 + +在做菜单返回时必须要了解角色和权限表 + +![image-20241105213516679](http://116.196.101.14:9000/docs/image-20241105213516679.png) + +#### 需求分析 + +1. 从数据库中返回出所有的菜单,其中需要整合成前端所要的形式,需要包含`roles`和`auths`,及其其它参数。 +2. 用户需要根据自己的角色访问不同的菜单。 +3. 如果当前用户不可以访问某些按钮需要隐藏。 +4. 用户通过其它手段访问如:swagger、knife4j、apifox、postman这种工具访问需要做权限验证,如果当前用户不满足访问这些接口后端需要拒绝。 +5. 如果已经添加了菜单名称、路由等级、路由路径会提示`xxx已存在`![image-20241106132818902](http://116.196.101.14:9000/docs/image-20241106132818902.png) + +6. 在数据库中为部分字段建立了唯一索引 + +![image-20241106132908309](http://116.196.101.14:9000/docs/image-20241106132908309.png) + +#### 实现思路 + +1. 角色和权限哪些可以访问的页面交给前端,在模板中已经设计好,如果用户访问了自己看不到的菜单会出现`403`页面;判断方式是根据后端返回的菜单中如果包含当前用户的角色就表示可以访问当前的菜单,如果用户信息中没有这个角色则表示不可以访问这个页面。 +2. 页面是否可以访问只是在操作上,如果用户通过接口访问是阻止不了的,所以这时后端需要在后端中进行判断,当前的访问路径是否是被允许的,也就是这个用户是否有这个权限,权限表设计中包含了请求路径 +3. 后端需要判断用户请求这个接口是否有权访问 + +> 整合成前端格式返回需要递归,后端根据当前用户访问的菜单需要进行递归菜单数据之后返回前端,并将这些菜单绑定的角色放置在`roles`中,之后根据角色查询全新啊相关内容,要将权限内容放置在`auths`中. +> +> 如果包含子菜单需要防止在`children`数组中,后端实现时如果没有子菜单默认是空数组而不是`null` +> +> 大致如下: +> +> ```json +> { +> "menuType": 0, +> "title": "admin_user", +> "path": "/system/admin-user", +> "component": "/system/adminUser/index", +> "meta": { +> "icon": "ic:round-manage-accounts", +> "title": "admin_user", +> "rank": 2, +> "roles": [ +> "admin", +> "all_page", +> "system", +> "test" +> ], +> "auths": [ +> "message::updateMessage", +> "menuIcon::getMenuIconList", +> "admin::messageReceived", +> "config::getWebConfig", +> "admin::config", +> "i18n::getI18n", +> .... +> ], +> "frameSrc": "" +> }, +> "children": [], +> "id": "1841803086252548097", +> "parentId": "1", +> "name": "admin_user", +> "rank": 2 +> } +> ``` + +### 部门管理 + +![image-20241106140738517](http://116.196.101.14:9000/docs/image-20241106140738517.png) + +![image-20241106140728748](http://116.196.101.14:9000/docs/image-20241106140728748.png) + +#### 业务需求 + +1. 包含CURD +2. 在用户管理中可以选择对应的部门 + +#### 实现思路 + +1. CURD接口文件如下 + +![image-20241106140826034](http://116.196.101.14:9000/docs/image-20241106140826034.png) + +2. 管理员为用户分配部门 + +![image-20241106140942278](http://116.196.101.14:9000/docs/image-20241106140942278.png) + +### 菜单图标 + +![image-20241106141037894](http://116.196.101.14:9000/docs/image-20241106141037894.png) + +![image-20241106141102601](http://116.196.101.14:9000/docs/image-20241106141102601.png) + +#### 业务需求 + +1. 用户在菜单中可以选择存储在数据库中的图标内容 +2. 包含CURD内容 + +#### 实现思路 + +后端需要返回接口格式实体类如下 + +```java +public class MenuIconVo extends BaseUserVo { + + @Schema(name = "iconCode", title = "icon类名") + private String iconCode; + + @Schema(name = "iconName", title = "icon 名称") + private String iconName; + +} +``` + +![image-20241106141521051](http://116.196.101.14:9000/docs/image-20241106141521051.png) + +前端封装好的组件 + +![image-20241106141626697](http://116.196.101.14:9000/docs/image-20241106141626697.png) + +### 邮箱相关 + +#### 业务需求 + +1. 邮件用户配置CURD +2. 邮件模板CURD +3. 邮件用户中只能有一个是默认的,如果当前修改其它项需要将其它已经启用改为不启用 +4. 邮件模板需要绑定邮件用户 + +### 实现思路 + +邮件模板中,添加或者修改时前端需要返回所有的邮件模板用户,添加或者修改时将用户ID存储在邮件模板的数据字段中 + +![image-20241106141920350](http://116.196.101.14:9000/docs/image-20241106141920350.png) + +### web配置 + +![image-20241106142001190](http://116.196.101.14:9000/docs/image-20241106142001190.png) + +### 系统监控 + +#### 服务监控 + +从SpringBoot的Actuator中获取信息,页面采用响应式 + +![image-20241106142208794](http://116.196.101.14:9000/docs/image-20241106142208794.png) + +#### 系统缓存 + +当前内容被SpringBoot缓存会显示在这 + +![image-20241106142253759](http://116.196.101.14:9000/docs/image-20241106142253759.png) + +### 定时任务 + +采用Quarter持久化存储,所有的可以使用的定时任务都在这 + +![image-20241106142429924](http://116.196.101.14:9000/docs/image-20241106142429924.png) + +#### 页面展示 + +![image-20241106142449033](http://116.196.101.14:9000/docs/image-20241106142449033.png) + +![](http://116.196.101.14:9000/docs/image-20241106142449033-1730874298898-1.png) + +### 多语言管理 + +![image-20241106142531047](http://116.196.101.14:9000/docs/image-20241106142531047.png) + +![image-20241106142544172](http://116.196.101.14:9000/docs/image-20241106142544172.png) + +### 日志管理 + +![image-20241106142606017](http://116.196.101.14:9000/docs/image-20241106142606017.png) + +![image-20241106142614917](http://116.196.101.14:9000/docs/image-20241106142614917.png) + +### 消息管理 + +管理员可以发送消息告诉xxx用户,在主页中会显示![image-20241106142908363](http://116.196.101.14:9000/docs/image-20241106142908363.png) + +之后点击时会看到消息封面、标题、简介、消息等级、消息等级内容 + +![image-20241106142949366](http://116.196.101.14:9000/docs/image-20241106142949366.png) + +#### 消息类型 + +![image-20241106143008098](http://116.196.101.14:9000/docs/image-20241106143008098.png) + +包含CURD,用户编辑消息发送时可以在选择 + +![image-20241106144017015](http://116.196.101.14:9000/docs/image-20241106144017015.png) + +同时在用户消息栏中也会显示对应内容 + +![image-20241106144050996](http://116.196.101.14:9000/docs/image-20241106144050996.png) + +前端判断逻辑如下 + +![image-20241106144146081](http://116.196.101.14:9000/docs/image-20241106144146081.png) + +#### 消息编辑 + +提供md编辑器和富文本编辑器 + +![image-20241106144223976](http://116.196.101.14:9000/docs/image-20241106144223976.png) + +![image-20241106144246068](http://116.196.101.14:9000/docs/image-20241106144246068.png) + +消息接受用户,如果不填写表示全部的用户,填写后会根据填写的内容存储在用户接受表中![image-20241106144522442](http://116.196.101.14:9000/docs/image-20241106144522442.png) + +![image-20241106144449463](http://116.196.101.14:9000/docs/image-20241106144449463.png) + +消息等级是显示消息样式颜色,文字内容为消息简介内容 + +![image-20241106144407453](http://116.196.101.14:9000/docs/image-20241106144407453.png) + +#### 消息接收管理 + +根据上面所选的接受用户会出现在下面的用户接受表中,可以对当前用户是否已读进行修改 + +![image-20241106144307885](http://116.196.101.14:9000/docs/image-20241106144307885.png) + +#### 消息发送管理 + +之前编辑过的消息都会在这 + +![image-20241106144317746](http://116.196.101.14:9000/docs/image-20241106144317746.png) + +# 环境部署 + +使用Docker进行部署,后端接口地址以`/admin`开头,但前端默认请求前缀为`/api`,因此在请求时需要进行替换。详细内容请参考以下【项目部署】说明。 + +## 配置相关 + +### docker文件 + +```dockerfile +# 使用官方的 Nginx 镜像作为基础镜像 +FROM nginx + +# 删除默认的 Nginx 配置文件 +RUN rm /etc/nginx/conf.d/default.conf + +# 将自定义的 Nginx 配置文件复制到容器中 +COPY nginx.conf /etc/nginx/conf.d/default.conf + +# 设置时区,构建镜像时执行的命令 +RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime +RUN echo "Asia/Shanghai" > /etc/timezone + +# 创建一个目录来存放前端项目文件 +WORKDIR /usr/share/nginx/html + +# 将前端项目打包文件复制到 Nginx 的默认静态文件目录 +COPY dist/ /usr/share/nginx/html +# 复制到nginx目录下 +COPY dist/ /etc/nginx/html + +# 暴露 Nginx 的默认端口 +EXPOSE 80 + +# 自动启动 Nginx +CMD ["nginx", "-g", "daemon off;"] +``` + +### NGINX文件 + +在请求中会使用代理所以会拿不到用户真实的IP地址,素以在要NGINX侠做下面的配置,这样用户在访问时就可以拿到真实的IP了 + +```nginx +proxy_set_header X-Real-IP $remote_addr; +proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; +proxy_set_header X-Forwarded-Proto $scheme; +``` + +#### 如果需要使用https协议 + +```dockerfile +COPY bunny-web.site.csr /etc/nginx/bunny-web.site.csr +COPY bunny-web.site.key /etc/nginx/bunny-web.site.key +COPY bunny-web.site_bundle.crt /etc/nginx/bunny-web.site_bundle.crt +COPY bunny-web.site_bundle.pem /etc/nginx/bunny-web.site_bundle.pem +``` + +NGINX的文件 + +```nginx +map $http_upgrade $connection_upgrade { + default upgrade; + '' close; +} + +server { + listen 80; + listen [::]:80; + server_name localhost; + + location / { + root /etc/nginx/html; + index index.html index.htm; + try_files $uri /index.html; + } + + # 后端跨域请求 + location ~/admin/ { + proxy_pass http://172.17.0.1:8000; + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + error_page 404 404.html; + + location = /50x.html { + root html; + } +} +``` + +## 项目部署 + +使用WebStorm进行项目部署,项目上线时默认端口为80。因此,Docker默认暴露的IP端口也应为80,NGINX中默认暴露的端口也是80,三者应一一对应。 + +若无法下载,请先使用pnpm下载。若不需使用pnpm,请删除或修改相应内容。 + +![image-20241026025057129](http://116.196.101.14:9000/docs/auth/undefinedimage-20241026025057129.png) + +### docker配置 + +![image-20241026024116090](http://116.196.101.14:9000/docs/auth/undefinedimage-20241026024116090.png) + +### 配置环境 + +设置启动端口号和项目地址机器后端请求地址 + +![image-20241026024813858](http://116.196.101.14:9000/docs/auth/undefinedimage-20241026024813858.png) + +#### 配置线上环境 + +设置项目启动端口号,线上环境默认请求路径为`/admin`,需在NGINX中将访问请求前缀更改为`/admin`。 + +![image-20241026024940747](http://116.196.101.14:9000/docs/auth/undefinedimage-20241026024940747.png) + +![image-20241026024243785](http://116.196.101.14:9000/docs/auth/undefinedimage-20241026024243785.png) + +#### 配置开发环境 + +开发环境默认IP为7000,若与本地项目端口冲突,请修改。后端请求地址为7070。 + +前端设置的请求前缀为`/api`,但后端接受的前缀为`/admin`,因此需在服务中修改此内容。 + +![image-20241026024318644](http://116.196.101.14:9000/docs/auth/undefinedimage-20241026024318644.png) + +**修改请求路径** + +![image-20241026031651591](http://116.196.101.14:9000/docs/auth/undefinedimage-20241026031651591.png) + +### 部署命令 + +```bash +docker build -f Dockerfile -t bunny_auth_web:1.0.0 . && docker run -p 80:80 --name bunny_auth_web --restart always bunny_auth_web:1.0.0 +``` diff --git a/common/common-generator/pom.xml b/common/common-generator/pom.xml new file mode 100644 index 0000000..37851e7 --- /dev/null +++ b/common/common-generator/pom.xml @@ -0,0 +1,44 @@ + + 4.0.0 + + cn.bunny + common + 0.0.1-SNAPSHOT + + + common-generator + jar + + common-utils + https://maven.apache.org + + + UTF-8 + + + + + javax.xml.bind + jaxb-api + 2.1 + + + + com.baomidou + mybatis-plus-generator + 3.5.6 + + + org.apache.velocity + velocity-engine-core + 2.3 + + + + com.google.guava + guava + 33.3.0-jre + + + diff --git a/common/common-generator/src/main/java/cn/bunny/common/generator/entity/BaseField.java b/common/common-generator/src/main/java/cn/bunny/common/generator/entity/BaseField.java new file mode 100644 index 0000000..d4e0a79 --- /dev/null +++ b/common/common-generator/src/main/java/cn/bunny/common/generator/entity/BaseField.java @@ -0,0 +1,30 @@ +package cn.bunny.common.generator.entity; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@ApiModel(value = "BaseEntity对象", description = "生成类基础内容") +public class BaseField { + @ApiModelProperty("字段名称") + private String name; + + @ApiModelProperty("注释内容") + private String annotation; + + @ApiModelProperty("TS类型") + private String type; + + @ApiModelProperty("是否必须参数") + private Boolean require; + + @ApiModelProperty("是否必须参数消息内容") + private String requireMessage; +} diff --git a/common/common-generator/src/main/java/cn/bunny/common/generator/entity/BaseResultMap.java b/common/common-generator/src/main/java/cn/bunny/common/generator/entity/BaseResultMap.java new file mode 100644 index 0000000..af19c77 --- /dev/null +++ b/common/common-generator/src/main/java/cn/bunny/common/generator/entity/BaseResultMap.java @@ -0,0 +1,21 @@ +package cn.bunny.common.generator.entity; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "BaseResultMap对象", title = "数据库基础字段返回映射", description = "数据库基础字段返回映射") +public class BaseResultMap { + + @Schema(name = "column", title = "数据库字段") + private String column; + + @Schema(name = "property", title = "实体类字段") + private String property; +} diff --git a/common/common-generator/src/main/java/cn/bunny/common/generator/entity/ColumnsField.java b/common/common-generator/src/main/java/cn/bunny/common/generator/entity/ColumnsField.java new file mode 100644 index 0000000..d1e3cc4 --- /dev/null +++ b/common/common-generator/src/main/java/cn/bunny/common/generator/entity/ColumnsField.java @@ -0,0 +1,21 @@ +package cn.bunny.common.generator.entity; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@ApiModel(value = "ColumnsField对象", description = "columns列字段名称") +public class ColumnsField { + @ApiModelProperty("列字段名称") + private String name; + + @ApiModelProperty("列字段值") + private String value; +} diff --git a/common/common-generator/src/main/java/cn/bunny/common/generator/entity/StoreTypeField.java b/common/common-generator/src/main/java/cn/bunny/common/generator/entity/StoreTypeField.java new file mode 100644 index 0000000..3fb03a0 --- /dev/null +++ b/common/common-generator/src/main/java/cn/bunny/common/generator/entity/StoreTypeField.java @@ -0,0 +1,26 @@ +package cn.bunny.common.generator.entity; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@ApiModel(value = "StoreTypeField对象", description = "仓库类型生成内容") +public class StoreTypeField { + + private List baseFieldList; + + @ApiModelProperty("接口名称") + private String interfaceName; + + @ApiModelProperty("接口注释内容") + private String interfaceAnnotation; +} \ No newline at end of file diff --git a/common/common-generator/src/main/java/cn/bunny/common/generator/generator/AdminCodeGenerator.java b/common/common-generator/src/main/java/cn/bunny/common/generator/generator/AdminCodeGenerator.java new file mode 100644 index 0000000..fc4bf6b --- /dev/null +++ b/common/common-generator/src/main/java/cn/bunny/common/generator/generator/AdminCodeGenerator.java @@ -0,0 +1,78 @@ +package cn.bunny.common.generator.generator; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.generator.FastAutoGenerator; +import com.baomidou.mybatisplus.generator.config.OutputFile; +import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Collections; + +public class AdminCodeGenerator { + // 数据连接 + // public static final String sqlHost = "jdbc:mysql://192.168.3.98:3304/family_financial?serverTimezone=GMT%2B8&useSSL=false&characterEncoding=utf-8&allowPublicKeyRetrieval=true"; + public static final String sqlHost = "jdbc:mysql://rm-bp12z6hlv46vi6g8mro.mysql.rds.aliyuncs.com:3306/family_financial?serverTimezone=GMT%2B8&useSSL=false&characterEncoding=utf-8&allowPublicKeyRetrieval=true"; + // 作者名称 + public static final String author = "Bunny"; + // 公共路径 + // public static final String outputDir = "D:\\Project\\web\\PC\\financial\\financial-server\\service"; + public static final String outputDir = "D:\\MyFolder\\financial\\financial-server\\service"; + // 实体类名称 + public static final String entity = "Bunny"; + + public static void main(String[] args) { + Generation("sys_category"); + } + + /** + * 根据表名生成相应结构代码 + * + * @param tableName 表名 + */ + public static void Generation(String... tableName) { + // 修改数据库路径、账户、密码 + // FastAutoGenerator.create(sqlHost, "root", "02120212") + FastAutoGenerator.create(sqlHost, "family_financial_prod", "0212family_financial") + .globalConfig(builder -> { + // 添加作者名称 + builder.author(author) + // 启用swagger + .enableSwagger() + // 指定输出目录 + .outputDir(outputDir + "/src/main/java"); + }) + .packageConfig(builder -> builder.entity(entity)// 实体类包名 + // 父包名。如果为空,将下面子包名必须写全部, 否则就只需写子包名 + .parent("cn.bunny.services") + .controller("controller")// 控制层包名 + .mapper("mapper")// mapper层包名 + .service("service")// service层包名 + .serviceImpl("service.impl")// service实现类包名 + // 自定义mapper.xml文件输出目录 + .pathInfo(Collections.singletonMap(OutputFile.xml, outputDir + "/src/main/resources/mapper"))) + .strategyConfig(builder -> { + // 设置要生成的表名 + builder.addInclude(tableName) + .addTablePrefix("sys_", "v_", "log_") + .entityBuilder() + .enableLombok() + .enableChainModel() + .naming(NamingStrategy.underline_to_camel)// 数据表映射实体命名策略:默认下划线转驼峰underline_to_camel + .columnNaming(NamingStrategy.underline_to_camel)// 表字段映射实体属性命名规则:默认null,不指定按照naming执行 + .idType(IdType.AUTO)// 添加全局主键类型 + .formatFileName("%s")// 格式化实体名称,%s取消首字母I, + .mapperBuilder() + .mapperAnnotation(Mapper.class)// 开启mapper注解 + .enableBaseResultMap()// 启用xml文件中的BaseResultMap 生成 + .enableBaseColumnList()// 启用xml文件中的BaseColumnList + .formatMapperFileName("%sMapper")// 格式化Dao类名称 + .formatXmlFileName("%sMapper")// 格式化xml文件名称 + .serviceBuilder() + .formatServiceFileName("%sService")// 格式化 service 接口文件名称 + .formatServiceImplFileName("%sServiceImpl")// 格式化 service 接口文件名称 + .controllerBuilder() + .enableRestStyle(); + }) + .execute(); + } +} diff --git a/common/common-generator/src/main/java/cn/bunny/common/generator/generator/WebGeneratorCode.java b/common/common-generator/src/main/java/cn/bunny/common/generator/generator/WebGeneratorCode.java new file mode 100644 index 0000000..1d46415 --- /dev/null +++ b/common/common-generator/src/main/java/cn/bunny/common/generator/generator/WebGeneratorCode.java @@ -0,0 +1,275 @@ +package cn.bunny.common.generator.generator; + +import cn.bunny.common.generator.entity.BaseField; +import cn.bunny.common.generator.entity.BaseResultMap; +import cn.bunny.common.generator.utils.GeneratorCodeUtils; +import cn.bunny.dao.dto.system.configuration.category.CategoryAddDto; +import cn.bunny.dao.dto.system.configuration.category.CategoryDto; +import cn.bunny.dao.dto.system.configuration.category.CategoryUpdateDto; +import cn.bunny.dao.entity.financial.Category; +import cn.bunny.dao.vo.configuration.CategoryVo; +import com.baomidou.mybatisplus.annotation.TableName; +import com.google.common.base.CaseFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import org.apache.velocity.Template; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.Velocity; +import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; + +import java.io.FileWriter; +import java.io.IOException; +import java.lang.reflect.Field; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Arrays; +import java.util.List; +import java.util.Properties; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * * 代码生成器入口点 + */ +@Service +public class WebGeneratorCode { + // 公共路径 + // public static String commonPath = "D:\\Project\\web\\PC\\financial\\financial-web\\src"; + public static String commonPath = "D:\\MyFolder\\financial\\financial-web\\src"; + // 生成API请求路径 + public static String apiPath = commonPath + "\\api\\v1\\financial\\"; + // 生成vue路径 + public static String vuePath = commonPath + "\\views\\financial\\"; + // 生成仓库路径 + public static String storePath = commonPath + "\\store\\financial\\"; + // 后端controller + public static String controllerPath = "D:\\MyFolder\\financial\\financial-server\\service\\src\\main\\java\\cn\\bunny\\services\\controller\\financial\\"; + public static String servicePath = "D:\\MyFolder\\financial\\financial-server\\service\\src\\main\\java\\cn\\bunny\\services\\service\\financial\\"; + public static String serviceImplPath = "D:\\MyFolder\\financial\\financial-server\\service\\src\\main\\java\\cn\\bunny\\services\\service\\financial\\impl\\"; + public static String mapperPath = "D:\\MyFolder\\financial\\financial-server\\service\\src\\main\\java\\cn\\bunny\\services\\mapper\\financial\\"; + public static String resourceMapperPath = "D:\\MyFolder\\financial\\financial-server\\service\\src\\main\\resources\\mapper\\financial\\"; + + public static void main(String[] args) throws Exception { + Class originalClass = Category.class; + Class dtoClass = CategoryDto.class; + Class addDtoClass = CategoryAddDto.class; + Class updateDtoClass = CategoryUpdateDto.class; + Class voClass = CategoryVo.class; + + // 设置velocity资源加载器 + Properties prop = new Properties(); + prop.put("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader"); + Velocity.init(prop); + // 创建Velocity容器 + VelocityContext context = new VelocityContext(); + + // 原始类名称 + String originalName = originalClass.getSimpleName(); + // 转成开头小写类名称,作为文件名 + String lowercaseName = originalName.substring(0, 1).toLowerCase() + originalName.substring(1); + // 转成中划线,做vue命名使用 + String lowerHyphen = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_HYPHEN, originalName); + // 生成字段xxx管理 + String classDescription = originalClass.getAnnotation(Schema.class).description(); + // 类注解标题 + String classTitle = originalClass.getAnnotation(Schema.class).title(); + + context.put("originalName", originalName); + context.put("lowercaseName", lowercaseName); + context.put("lowerHyphen", lowerHyphen); + context.put("classDescription", classDescription); + context.put("classTitle", classTitle); + context.put("leftBrace", "${"); + context.put("date", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + + // 生成前端内容 + generatorWebCode(dtoClass, addDtoClass, context); + + // 生成后端 + generatorServerCode(originalClass, dtoClass, voClass, context); + + // 写入文件 + writeFiles(lowercaseName, lowerHyphen, originalName, context); + } + + /** + * * web端生成字段 + */ + public static void generatorWebCode(Class dtoClass, Class addDtoClass, VelocityContext context) { + // 生成 Store 中 form 表单内容 + List formList = Arrays.stream(dtoClass.getDeclaredFields()) + .filter(field -> !field.getName().equals("id")) + .map(field -> BaseField.builder().name(field.getName()).annotation(field.getAnnotation(Schema.class).title()).build()) + .toList(); + + // 添加表单字段值 + List addFormList = Arrays.stream(addDtoClass.getDeclaredFields()).map(Field::getName).toList(); + + // 是否必须字段设置 + List baseFieldList = Arrays.stream(addDtoClass.getDeclaredFields()).map(field -> { + try { + String message = ""; + boolean hasMessage = false; + // 验证消息 + NotBlank messageAnnotation = field.getAnnotation(NotBlank.class); + if (messageAnnotation != null) { + message = messageAnnotation.message(); + hasMessage = StringUtils.hasText(message); + if (!hasMessage) message = field.getAnnotation(NotNull.class).message(); + } + + + // 设置基础字段注解和是否必填项 + BaseField baseField = new BaseField(); + baseField.setName(field.getName()); + baseField.setType(baseField.getType()); + baseField.setAnnotation(field.getAnnotation(Schema.class).title()); + baseField.setType(GeneratorCodeUtils.convertJavaTypeToTypeScript(field.getType())); + baseField.setRequire(hasMessage); + if (hasMessage) baseField.setRequireMessage(message); + + return baseField; + } catch (Exception e) { + throw new RuntimeException(e); + } + }).toList(); + + // 生成查询表单字段 + context.put("formList", formList); + context.put("addFormList", addFormList); + context.put("baseFieldList", baseFieldList); + } + + /** + * 生成后端内容 + */ + public static void generatorServerCode(Class originalClass, Class dtoClass, Class voClass, VelocityContext context) { + Field[] superFields = originalClass.getSuperclass().getDeclaredFields(); + Field[] declaredFields = originalClass.getDeclaredFields(); + Field[] mergedArray = new Field[superFields.length + declaredFields.length]; + System.arraycopy(superFields, 0, mergedArray, 0, superFields.length); + System.arraycopy(declaredFields, 0, mergedArray, superFields.length, declaredFields.length); + + // 添加BaseResultMap + List baseResultMaps = Arrays.stream(mergedArray).map(field -> { + // 转成下划线 + String fieldName = field.getName(); + String lowerUnderscore = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, fieldName); + + BaseResultMap baseResultMap = new BaseResultMap(); + baseResultMap.setColumn(lowerUnderscore); + baseResultMap.setProperty(fieldName); + return baseResultMap; + }).toList(); + + // 分页查询内容 + List pageQueryMap = Arrays.stream(dtoClass.getDeclaredFields()).map(field -> { + String name = field.getName(); + String column = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, name); + + return BaseResultMap.builder().column(column).property(name).build(); + }).toList(); + + // 生层Base_Column_List + String baseColumnList = Stream.of(mergedArray) + .map(field -> CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, field.getName())) + .collect(Collectors.joining(", ")); + + // 表名 + String tableName = originalClass.getAnnotation(TableName.class).value(); + + context.put("baseResultMaps", baseResultMaps); + context.put("type", originalClass.getName()); + context.put("voClassType", voClass.getName()); + context.put("baseColumnList", baseColumnList); + context.put("tableName", tableName); + context.put("pageQueryMap", pageQueryMap); + } + + /** + * * 写入文件 + */ + public static void writeFiles(String lowercaseName, String lowerHyphen, String originalName, VelocityContext context) throws IOException { + context.put("apiPath", GeneratorCodeUtils.ReplacePathHandle(apiPath) + lowercaseName); + context.put("storePath", GeneratorCodeUtils.ReplacePathHandle(storePath) + lowercaseName); + context.put("typesPath", GeneratorCodeUtils.ReplacePathHandle(vuePath) + lowercaseName + "/utils/types"); + context.put("hookPath", GeneratorCodeUtils.ReplacePathHandle(vuePath) + lowercaseName + "/utils/hooks"); + context.put("columnsPath", GeneratorCodeUtils.ReplacePathHandle(vuePath) + lowercaseName + "/utils/columns"); + context.put("dialogPath", GeneratorCodeUtils.ReplacePathHandle(vuePath) + lowercaseName + "/" + lowerHyphen + "-dialog.vue"); + + // 写入api模板 + Template apiTemplate = Velocity.getTemplate("vms/web/api.vm", "UTF-8"); + FileWriter apiTemplateFileWriter = new FileWriter(apiPath + lowercaseName + ".ts"); + apiTemplate.merge(context, apiTemplateFileWriter); + apiTemplateFileWriter.close(); + + // 写入弹窗模板 + Template dialogTemplate = Velocity.getTemplate("vms/web/dialog.vm", "UTF-8"); + FileWriter dialogTemplateFileWriter = new FileWriter(vuePath + lowercaseName + "\\" + lowerHyphen + "-dialog.vue"); + dialogTemplate.merge(context, dialogTemplateFileWriter); + dialogTemplateFileWriter.close(); + + // 写入hook模板 + Template hookTemplate = Velocity.getTemplate("vms/web/hook.vm", "UTF-8"); + FileWriter hookTemplateFileWriter = new FileWriter(vuePath + lowercaseName + "\\utils\\hooks.ts"); + hookTemplate.merge(context, hookTemplateFileWriter); + hookTemplateFileWriter.close(); + + // 写入hook模板 + Template storeTemplate = Velocity.getTemplate("vms/web/store.vm", "UTF-8"); + FileWriter storeTemplateFileWriter = new FileWriter(storePath + "\\" + lowercaseName + ".ts"); + storeTemplate.merge(context, storeTemplateFileWriter); + storeTemplateFileWriter.close(); + + // 写入types模板 + Template typesTemplate = Velocity.getTemplate("vms/web/types.vm", "UTF-8"); + FileWriter typesTemplateFileWriter = new FileWriter(vuePath + lowercaseName + "\\utils\\types.ts"); + typesTemplate.merge(context, typesTemplateFileWriter); + typesTemplateFileWriter.close(); + + // 写入index模板 + Template indexTemplate = Velocity.getTemplate("vms/web/index.vm", "UTF-8"); + FileWriter indexTemplateFileWriter = new FileWriter(vuePath + lowercaseName + "\\index.vue"); + indexTemplate.merge(context, indexTemplateFileWriter); + indexTemplateFileWriter.close(); + + // 写入columns模板 + Template columnsTemplate = Velocity.getTemplate("vms/web/columns.vm", "UTF-8"); + FileWriter columnsTemplateFileWriter = new FileWriter(vuePath + lowercaseName + "\\utils\\columns.ts"); + columnsTemplate.merge(context, columnsTemplateFileWriter); + columnsTemplateFileWriter.close(); + + // 写入controller模板 + Template controllerTemplate = Velocity.getTemplate("vms/server/controller.vm", "UTF-8"); + FileWriter controllerTemplateFileWriter = new FileWriter(controllerPath + originalName + "Controller.java"); + controllerTemplate.merge(context, controllerTemplateFileWriter); + controllerTemplateFileWriter.close(); + + // 写入servicePath模板 + Template servicePathTemplate = Velocity.getTemplate("vms/server/service.vm", "UTF-8"); + FileWriter servicePathTemplateFileWriter = new FileWriter(servicePath + originalName + "Service.java"); + servicePathTemplate.merge(context, servicePathTemplateFileWriter); + servicePathTemplateFileWriter.close(); + + // 写入serviceImplPath模板 + Template serviceImplPathTemplate = Velocity.getTemplate("vms/server/serviceImpl.vm", "UTF-8"); + FileWriter serviceImplPathTemplateFileWriter = new FileWriter(serviceImplPath + originalName + "ServiceImpl.java"); + serviceImplPathTemplate.merge(context, serviceImplPathTemplateFileWriter); + serviceImplPathTemplateFileWriter.close(); + + // 写入serviceImplPath模板 + Template mapperPathTemplate = Velocity.getTemplate("vms/server/mapper.vm", "UTF-8"); + FileWriter mapperPathTemplateFileWriter = new FileWriter(mapperPath + originalName + "Mapper.java"); + mapperPathTemplate.merge(context, mapperPathTemplateFileWriter); + mapperPathTemplateFileWriter.close(); + + // 写入resourceMapperPath模板 + Template resourceMapperPathTemplate = Velocity.getTemplate("vms/server/resourceMapper.vm", "UTF-8"); + FileWriter resourceMapperPathTemplateFileWriter = new FileWriter(resourceMapperPath + originalName + "Mapper.xml"); + resourceMapperPathTemplate.merge(context, resourceMapperPathTemplateFileWriter); + resourceMapperPathTemplateFileWriter.close(); + } +} + diff --git a/common/common-generator/src/main/java/cn/bunny/common/generator/utils/GeneratorCodeUtils.java b/common/common-generator/src/main/java/cn/bunny/common/generator/utils/GeneratorCodeUtils.java new file mode 100644 index 0000000..470e33e --- /dev/null +++ b/common/common-generator/src/main/java/cn/bunny/common/generator/utils/GeneratorCodeUtils.java @@ -0,0 +1,98 @@ +package cn.bunny.common.generator.utils; + +import cn.bunny.common.generator.entity.BaseField; +import cn.bunny.common.generator.entity.StoreTypeField; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import java.lang.reflect.Field; +import java.util.*; + +import static cn.bunny.common.generator.generator.WebGeneratorCode.commonPath; + + +public class GeneratorCodeUtils { + public static String convertJavaTypeToTypeScript(Class javaType) { + if (javaType.isPrimitive()) { + return getPrimitiveTypeMapping(javaType.getSimpleName()); + } else if (javaType.isArray()) { + return "Array<" + convertJavaTypeToTypeScript(javaType.getComponentType()) + ">"; + } else if (javaType.equals(List.class) || javaType.equals(Set.class) || javaType.equals(Map.class)) { + return "any"; + } else { + return getPrimitiveTypeMapping(javaType.getSimpleName()); + } + } + + /** + * * 将Java类型转成JS/TS类型 + * + * @param primitiveType Java的类型 + * @return 转换后的类型 + */ + private static String getPrimitiveTypeMapping(String primitiveType) { + return switch (primitiveType) { + case "int", "long", "short", "byte", "float", "double", "Byte", "Integer", "Long", "Float", "Double" -> + "number"; + case "boolean", "Boolean" -> "boolean"; + case "char", "Character", "String" -> "string"; + default -> "any"; + }; + } + + /** + * * 生成返回对象类字段 + * 返回字段包含:TS接口名称,TS接口名称注释,TS接口字段、TS字段类型、TS字段注释、TS字段注释解释 + * + * @param voClass 返回对象类 + * @return 整理好返回字段 + */ + public static StoreTypeField handleGenerator(Class voClass) { + // 类的详细信息 + String interfaceAnnotation = voClass.getAnnotation(ApiModel.class).description(); + + // 字段 + List fields = new ArrayList<>(Arrays.stream(voClass.getDeclaredFields()).toList()); + List superList = Arrays.stream(voClass.getSuperclass().getDeclaredFields()).toList(); + fields.addAll(superList); + + List list = fields.stream() + .map(field -> { + field.setAccessible(true); + + // 将类型转成TS + Class type = field.getType(); + String convertJavaTypeToTypeScript = GeneratorCodeUtils.convertJavaTypeToTypeScript(type); + + // 注释内容 + String annotationName = Objects.requireNonNull(field.getAnnotation(ApiModelProperty.class).name()); + // 注释解释 + String value = field.getAnnotation(ApiModelProperty.class).value(); + + // 构建返回内容 + BaseField storeTypeField = new BaseField(); + storeTypeField.setName(field.getName()); + storeTypeField.setAnnotation(annotationName); + storeTypeField.setType(convertJavaTypeToTypeScript); + + return storeTypeField; + }).toList(); + + StoreTypeField storeTypeField = new StoreTypeField(); + storeTypeField.setBaseFieldList(list); + storeTypeField.setInterfaceName(voClass.getSimpleName()); + storeTypeField.setInterfaceAnnotation(interfaceAnnotation); + + return storeTypeField; + } + + /** + * * 通用处理路径内容 + * + * @param path 路径 + * @return 处理好的路径 + */ + public static String ReplacePathHandle(String path) { + return "@" + path.replace(commonPath, "").replace("\\", "/"); + } +} \ No newline at end of file diff --git a/common/common-generator/src/main/resources/vms/server/controller.vm b/common/common-generator/src/main/resources/vms/server/controller.vm new file mode 100644 index 0000000..6421204 --- /dev/null +++ b/common/common-generator/src/main/resources/vms/server/controller.vm @@ -0,0 +1,65 @@ +package cn.bunny.services.controller; + +import cn.bunny.dao.pojo.result.Result; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Mono; +import cn.bunny.dao.pojo.result.PageResult; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; + +import java.util.List; + +/** + *

+ * ${classTitle}表 前端控制器 + *

+ * + * @author Bunny + * @since ${date} + */ +@Tag(name = "${classTitle}", description = "${classTitle}相关接口") +@RestController +@RequestMapping("admin/${lowercaseName}") +public class ${originalName}Controller { + + @Autowired + private ${originalName}Service ${lowercaseName}Service; + + @Operation(summary = "分页查询${classTitle}", description = "分页查询${classTitle}") + @GetMapping("get${originalName}List/{page}/{limit}") + public Mono>> get${originalName}List( + @Parameter(name = "page", description = "当前页", required = true) + @PathVariable("page") Integer page, + @Parameter(name = "limit", description = "每页记录数", required = true) + @PathVariable("limit") Integer limit, + ${originalName}Dto dto) { + Page<${originalName}> pageParams = new Page<>(page, limit); + PageResult<${originalName}Vo> pageResult = ${lowercaseName}Service.get${originalName}List(pageParams, dto); + return Mono.just(Result.success(pageResult)); + } + + @Operation(summary = "添加${classTitle}", description = "添加${classTitle}") + @PostMapping("add${originalName}") + public Mono> add${originalName}(@Valid @RequestBody ${originalName}AddDto dto) { + ${lowercaseName}Service.add${originalName}(dto); + return Mono.just(Result.success(ResultCodeEnum.ADD_SUCCESS)); + } + + @Operation(summary = "更新${classTitle}", description = "更新${classTitle}") + @PutMapping("update${originalName}") + public Mono> update${originalName}(@Valid @RequestBody ${originalName}UpdateDto dto) { + ${lowercaseName}Service.update${originalName}(dto); + return Mono.just(Result.success(ResultCodeEnum.UPDATE_SUCCESS)); + } + + @Operation(summary = "删除${classTitle}", description = "删除${classTitle}") + @DeleteMapping("delete${originalName}") + public Mono> delete${originalName}(@RequestBody List ids) { + ${lowercaseName}Service.delete${originalName}(ids); + return Mono.just(Result.success(ResultCodeEnum.DELETE_SUCCESS)); + } +} diff --git a/common/common-generator/src/main/resources/vms/server/mapper.vm b/common/common-generator/src/main/resources/vms/server/mapper.vm new file mode 100644 index 0000000..5029be8 --- /dev/null +++ b/common/common-generator/src/main/resources/vms/server/mapper.vm @@ -0,0 +1,35 @@ +package cn.bunny.services.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Param; +import java.util.List; + +/** + *

+ * ${classTitle} Mapper 接口 + *

+ * + * @author Bunny + * @since ${date} + */ +@Mapper +public interface ${originalName}Mapper extends BaseMapper<${originalName}> { + + /** + * * 分页查询${classTitle}内容 + * + * @param pageParams ${classTitle}分页参数 + * @param dto ${classTitle}查询表单 + * @return ${classTitle}分页结果 + */ + IPage<${originalName}Vo> selectListByPage(@Param("page") Page<${originalName}> pageParams, @Param("dto") ${originalName}Dto dto); + + /** + * 物理删除${classTitle} + * + * @param ids 删除 id 列表 + */ + void deleteBatchIdsWithPhysics(List ids); +} diff --git a/common/common-generator/src/main/resources/vms/server/resourceMapper.vm b/common/common-generator/src/main/resources/vms/server/resourceMapper.vm new file mode 100644 index 0000000..2b1d789 --- /dev/null +++ b/common/common-generator/src/main/resources/vms/server/resourceMapper.vm @@ -0,0 +1,46 @@ + + + + + + + #foreach($field in $baseResultMaps) + + #end + + + + + $baseColumnList + + + + + + + + delete + from $tableName + where id in + + #{id} + + + + diff --git a/common/common-generator/src/main/resources/vms/server/service.vm b/common/common-generator/src/main/resources/vms/server/service.vm new file mode 100644 index 0000000..fafe220 --- /dev/null +++ b/common/common-generator/src/main/resources/vms/server/service.vm @@ -0,0 +1,49 @@ +package cn.bunny.services.service; + +import cn.bunny.dao.entity.system.MenuIcon; +import cn.bunny.dao.pojo.result.PageResult; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import jakarta.validation.Valid; + +import java.util.HashMap; +import java.util.List; + +/** + *

+ * ${classTitle} 服务类 + *

+ * + * @author Bunny + * @since ${date} + */ +public interface ${originalName}Service extends IService<${originalName}> { + + /** + * * 获取${classTitle}列表 + * + * @return ${classTitle}返回列表 + */ + PageResult<${originalName}Vo> get${originalName}List(Page<${originalName}> pageParams, ${originalName}Dto dto); + + /** + * * 添加${classTitle} + * + * @param dto 添加表单 + */ + void add${originalName}(@Valid ${originalName}AddDto dto); + + /** + * * 更新${classTitle} + * + * @param dto 更新表单 + */ + void update${originalName}(@Valid ${originalName}UpdateDto dto); + + /** + * * 删除|批量删除${classTitle}类型 + * + * @param ids 删除id列表 + */ + void delete${originalName}(List ids); +} diff --git a/common/common-generator/src/main/resources/vms/server/serviceImpl.vm b/common/common-generator/src/main/resources/vms/server/serviceImpl.vm new file mode 100644 index 0000000..b418d2b --- /dev/null +++ b/common/common-generator/src/main/resources/vms/server/serviceImpl.vm @@ -0,0 +1,78 @@ +package cn.bunny.services.service.impl; + +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.services.mapper.${originalName}Mapper; +import cn.bunny.services.service.${originalName}Service; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * ${classTitle} 服务实现类 + *

+ * + * @author Bunny + * @since ${date} + */ +@Service +public class ${originalName}ServiceImpl extends ServiceImpl<${originalName}Mapper, ${originalName}> implements ${originalName}Service { + + /** + * * ${classTitle} 服务实现类 + * + * @param pageParams ${classTitle}分页查询page对象 + * @param dto ${classTitle}分页查询对象 + * @return 查询分页${classTitle}返回对象 + */ + @Override + public PageResult<${originalName}Vo> get${originalName}List(Page<${originalName}> pageParams, ${originalName}Dto dto) { + IPage<${originalName}Vo> page = baseMapper.selectListByPage(pageParams, dto); + + return PageResult.<${originalName}Vo>builder() + .list(page.getRecords()) + .pageNo(page.getCurrent()) + .pageSize(page.getSize()) + .total(page.getTotal()) + .build(); + } + /** + * 添加${classTitle} + * + * @param dto ${classTitle}添加 + */ + @Override + public void add${originalName}(@Valid ${originalName}AddDto dto) { + // 保存数据 + ${originalName} ${lowercaseName} = new ${originalName}(); + BeanUtils.copyProperties(dto, ${lowercaseName}); + save(${lowercaseName}); + } + + /** + * 更新${classTitle} + * + * @param dto ${classTitle}更新 + */ + @Override + public void update${originalName}(@Valid ${originalName}UpdateDto dto) { + // 更新内容 + ${originalName} ${lowercaseName} = new ${originalName}(); + BeanUtils.copyProperties(dto, ${lowercaseName}); + updateById(${lowercaseName}); + } + + /** + * 删除|批量删除${classTitle} + * + * @param ids 删除id列表 + */ + @Override + public void delete${originalName}(List ids) { + baseMapper.deleteBatchIdsWithPhysics(ids); + } +} diff --git a/common/common-generator/src/main/resources/vms/web/api.vm b/common/common-generator/src/main/resources/vms/web/api.vm new file mode 100644 index 0000000..b49e6ae --- /dev/null +++ b/common/common-generator/src/main/resources/vms/web/api.vm @@ -0,0 +1,22 @@ +import { http } from '@/api/service/request'; +import type { BaseResult, ResultTable } from '@/api/service/types'; + +/** ${classDescription}---获取${classDescription}列表 */ +export const fetchGet${originalName}List = (data: any) => { + return http.request>('get', `${lowercaseName}/get${originalName}List/${data.currentPage}/${data.pageSize}`, { params: data }); +}; + +/** ${classDescription}---添加${classDescription} */ +export const fetchAdd${originalName} = (data: any) => { + return http.request>('post', '${lowercaseName}/add${originalName}', { data }); +}; + +/** ${classDescription}---更新${classDescription} */ +export const fetchUpdate${originalName} = (data: any) => { + return http.request>('put', '${lowercaseName}/update${originalName}', { data }); +}; + +/** ${classDescription}---删除${classDescription} */ +export const fetchDelete${originalName} = (data: any) => { + return http.request>('delete', '${lowercaseName}/delete${originalName}', { data }); +}; \ No newline at end of file diff --git a/common/common-generator/src/main/resources/vms/web/columns.vm b/common/common-generator/src/main/resources/vms/web/columns.vm new file mode 100644 index 0000000..712c6cc --- /dev/null +++ b/common/common-generator/src/main/resources/vms/web/columns.vm @@ -0,0 +1,27 @@ +import { reactive, ref } from 'vue'; +import { $t } from '@/plugins/i18n'; +import type { FormRules } from 'element-plus'; + +// 表格列 +export const columns: TableColumnList = [ +{ type: 'selection', align: 'left' }, +{ type: 'index', index: (index: number) => index + 1, label: '序号', width: 60 }, +#foreach($field in $baseFieldList) +// $field.annotation +{ label: $t('$field.name'), prop: '$field.name' }, +#end +{ label: $t('table.updateTime'), prop: 'updateTime', sortable: true, width: 160 }, +{ label: $t('table.createTime'), prop: 'createTime', sortable: true, width: 160 }, +{ label: $t('table.createUser'), prop: 'createUser', slot: 'createUser', width: 130 }, +{ label: $t('table.updateUser'), prop: 'updateUser', slot: 'updateUser', width: 130 }, +{ label: $t('table.operation'), fixed: 'right', width: 210, slot: 'operation' }, +]; + +// 添加规则 +export const rules = reactive +({ + #foreach($field in $baseFieldList) + // $field.annotation + $field.name: [{ required: true, message: `$leftBrace$t('input')}$leftBrace$t('${field.name}')}`, trigger: 'blur' }], + #end + }); diff --git a/common/common-generator/src/main/resources/vms/web/dialog.vm b/common/common-generator/src/main/resources/vms/web/dialog.vm new file mode 100644 index 0000000..14324e0 --- /dev/null +++ b/common/common-generator/src/main/resources/vms/web/dialog.vm @@ -0,0 +1,36 @@ + + + diff --git a/common/common-generator/src/main/resources/vms/web/hook.vm b/common/common-generator/src/main/resources/vms/web/hook.vm new file mode 100644 index 0000000..f948132 --- /dev/null +++ b/common/common-generator/src/main/resources/vms/web/hook.vm @@ -0,0 +1,130 @@ +import { deviceDetection } from '@pureadmin/utils'; +import { addDialog } from '@/components/BaseDialog/index'; +import ${originalName}Dialog from '${dialogPath}'; +import { use${originalName}Store } from '${storePath}'; +import { h, ref } from 'vue'; +import { messageBox } from '@/utils/message'; +import type { FormItemProps } from '${typesPath}'; +import { $t } from '@/plugins/i18n'; +import { message, messageBox } from "@/utils/message"; +import DeleteBatchDialog from "@/components/Table/DeleteBatchDialog.vue"; + +export const formRef = ref(); +// 删除ids +export const deleteIds = ref([]); +const ${lowercaseName}Store = use${originalName}Store(); + +/** 搜索初始化${classTitle} */ +export async function onSearch() { + ${lowercaseName}Store.loading = true; + await ${lowercaseName}Store.get${originalName}List(); + ${lowercaseName}Store.loading = false; +} + +/** 添加${classTitle} */ +export function onAdd() { + addDialog({ + title: `$leftBrace $t("addNew")}$leftBrace$t("${lowercaseName}")}`, + width: '30%', + props: { + formInline: { +#foreach($item in $addFormList) + $!{item}: undefined, +#end + }, + }, + draggable: true, + fullscreenIcon: true, + closeOnClickModal: false, + contentRenderer: () => h(${originalName}Dialog, { ref: formRef }), + beforeSure: (done, { options }) => { + const form = options.props.formInline as FormItemProps; + formRef.value.formRef.validate(async (valid: any) => { + if (!valid) return; + + const result = await ${lowercaseName}Store.add${originalName}(form); + if (!result) return; + done(); + await onSearch(); + }); + }, + }); +} + +/** 更新${classTitle} */ +export function onUpdate(row: any) { + addDialog({ + title: `$leftBrace$t("modify")}$leftBrace$t("${lowercaseName}")}`, + width: '30%', + props: { + formInline: { +#foreach($item in $addFormList) + $!{item}: row.$!{item}, +#end + } +}, + draggable: true, + fullscreenIcon: true, + closeOnClickModal: false, + contentRenderer: () => h(${originalName}Dialog, { ref: formRef }), + beforeSure: (done, { options }) => { + const form = options.props.formInline as FormItemProps; + formRef.value.formRef.validate(async (valid: any) => { + if (!valid) return; + + const result = await ${lowercaseName}Store.update${originalName}({ ...form, id: row.id }); + if (!result) return; + done(); + await onSearch(); + }); + }, + }); +} + +/** 删除${classTitle} */ +export const onDelete = async (row: any) => { + const id = row.id; + + // 是否确认删除 + const result = await messageBox({ + title: $t('confirmDelete'), + showMessage: false, + confirmMessage: undefined, + cancelMessage: $t("cancel_delete"), + }); + if (!result) return; + + // 删除数据 + await ${lowercaseName}Store.delete${originalName}([id]); + await onSearch(); +}; + +/** 批量删除 */ +export const onDeleteBatch = async () => { + const ids = deleteIds.value; + const formDeletedBatchRef = ref(); + + addDialog({ + title: $t('deleteBatchTip'), + width: '30%', + props: { formInline: { confirmText: '' } }, + draggable: true, + fullscreenIcon: true, + closeOnClickModal: false, + contentRenderer: () => h(DeleteBatchDialog, { ref: formDeletedBatchRef }), + beforeSure: (done, { options }) => { + formDeletedBatchRef.value.formDeletedBatchRef.validate(async (valid: any) => { + if (!valid) return; + + const text = options.props.formInline.confirmText.toLowerCase(); + if (text === 'yes' || text === 'y') { + // 删除数据 + await ${lowercaseName}Store.delete${originalName}(ids); + await onSearch(); + + done(); + } else message($t('deleteBatchTip'), { type: 'warning' }); + }); + }, + }); +}; \ No newline at end of file diff --git a/common/common-generator/src/main/resources/vms/web/index.vm b/common/common-generator/src/main/resources/vms/web/index.vm new file mode 100644 index 0000000..668241a --- /dev/null +++ b/common/common-generator/src/main/resources/vms/web/index.vm @@ -0,0 +1,121 @@ + + + diff --git a/common/common-generator/src/main/resources/vms/web/store.vm b/common/common-generator/src/main/resources/vms/web/store.vm new file mode 100644 index 0000000..7b504d6 --- /dev/null +++ b/common/common-generator/src/main/resources/vms/web/store.vm @@ -0,0 +1,69 @@ +import { defineStore } from 'pinia'; +import { fetchAdd${originalName}, fetchDelete${originalName}, fetchGet${originalName}List, fetchUpdate${originalName} } from '${apiPath}'; +import { pageSizes } from '@/enums/baseConstant'; +import { storeMessage } from '@/utils/message'; +import { storePagination } from '@/store/useStorePagination'; + +/** +* ${classTitle} Store +*/ +export const use${originalName}Store = defineStore('${lowercaseName}Store', { +state() { +return { +// ${classTitle}列表 +datalist: [], +// 查询表单 +form: { +#foreach($item in $formList) +// $!{item.annotation} + $!{item.name}: undefined, +#end +}, +// 分页查询结果 +pagination: { +currentPage: 1, +pageSize: 30, +total: 1, +pageSizes, +}, +// 加载 +loading: false, +}; +}, +getters: {}, +actions: { +/** 获取${classTitle} */ +async get${originalName}List() { +// 整理请求参数 +const data = { ...this.pagination, ...this.form }; +delete data.pageSizes; +delete data.total; +delete data.background; + +// 获取${classTitle}列表 +const result = await fetchGet${originalName}List(data); + +// 公共页面函数hook +const pagination = storePagination.bind(this); +return pagination(result); +}, + +/** 添加${classTitle} */ +async add${originalName}(data: any) { +const result = await fetchAdd${originalName}(data); +return storeMessage(result); +}, + +/** 修改${classTitle} */ +async update${originalName}(data: any) { +const result = await fetchUpdate${originalName}(data); +return storeMessage(result); +}, + +/** 删除${classTitle} */ +async delete${originalName}(data: any) { +const result = await fetchDelete${originalName}(data); +return storeMessage(result); +}, +}, +}); diff --git a/common/common-generator/src/main/resources/vms/web/types.vm b/common/common-generator/src/main/resources/vms/web/types.vm new file mode 100644 index 0000000..07dab1f --- /dev/null +++ b/common/common-generator/src/main/resources/vms/web/types.vm @@ -0,0 +1,12 @@ +// 添加或者修改表单元素 +export interface FormItemProps { +#foreach($field in $baseFieldList) + // $field.annotation + $field.name: $field.type; +#end +} + +// 添加或修改表单Props +export interface FormProps { + formInline: FormItemProps; +} diff --git a/common/pom.xml b/common/pom.xml new file mode 100644 index 0000000..fab81f8 --- /dev/null +++ b/common/pom.xml @@ -0,0 +1,53 @@ + + 4.0.0 + + cn.bunny + financial-admin-server + 0.0.1-SNAPSHOT + + + common + pom + common Maven Webapp + https://maven.apache.org + + service-utils + common-generator + + + + + cn.bunny + dao + 0.0.1-SNAPSHOT + + + org.springframework.boot + spring-boot-starter-web + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + + + io.jsonwebtoken + jjwt + + + + cn.hutool + hutool-all + + + + mysql + mysql-connector-java + + + + com.zaxxer + HikariCP + + + diff --git a/common/service-utils/pom.xml b/common/service-utils/pom.xml new file mode 100644 index 0000000..f846523 --- /dev/null +++ b/common/service-utils/pom.xml @@ -0,0 +1,70 @@ + + 4.0.0 + + cn.bunny + common + 0.0.1-SNAPSHOT + + + service-utils + jar + service-utils + https://maven.apache.org + + + UTF-8 + + + + + + javax.xml.bind + jaxb-api + 2.3.1 + + + + org.apache.httpcomponents + httpclient + 4.5.14 + + + + org.springframework.boot + spring-boot-starter-data-redis + + + + org.redisson + redisson + 3.26.1 + + + + io.minio + minio + + + + org.lionsoul + ip2region + 2.6.5 + + + + org.springframework + spring-websocket + + + + org.springframework.boot + spring-boot-starter-mail + + + + org.springframework.boot + spring-boot-starter-validation + + + diff --git a/common/service-utils/src/main/java/cn/bunny/common/service/config/ControllerStringParamTrimConfig.java b/common/service-utils/src/main/java/cn/bunny/common/service/config/ControllerStringParamTrimConfig.java new file mode 100644 index 0000000..2694d23 --- /dev/null +++ b/common/service-utils/src/main/java/cn/bunny/common/service/config/ControllerStringParamTrimConfig.java @@ -0,0 +1,46 @@ +package cn.bunny.common.service.config; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer; +import org.springframework.beans.propertyeditors.StringTrimmerEditor; +import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.web.bind.WebDataBinder; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.InitBinder; + +import java.io.IOException; + +@ControllerAdvice +public class ControllerStringParamTrimConfig { + + /** + * 创建 String trim 编辑器 + * 构造方法中 boolean 参数含义为如果是空白字符串,是否转换为null + * 即如果为true,那么 " " 会被转换为 null,否者为 "" + */ + @InitBinder + public void initBinder(WebDataBinder binder) { + StringTrimmerEditor propertyEditor = new StringTrimmerEditor(false); + // 为 String 类对象注册编辑器 + binder.registerCustomEditor(String.class, propertyEditor); + } + + @Bean + public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() { + return jacksonObjectMapperBuilder -> { + // 为 String 类型自定义反序列化操作 + jacksonObjectMapperBuilder + .deserializerByType(String.class, new StdScalarDeserializer(String.class) { + @Override + public String deserialize(JsonParser jsonParser, DeserializationContext ctx) throws IOException { + // 去除全部空格 + // return StringUtils.trimAllWhitespace(jsonParser.getValueAsString()); + // 仅去除前后空格 + return jsonParser.getValueAsString().trim(); + } + }); + }; + } +} \ No newline at end of file diff --git a/common/service-utils/src/main/java/cn/bunny/common/service/config/Knife4jConfig.java b/common/service-utils/src/main/java/cn/bunny/common/service/config/Knife4jConfig.java new file mode 100644 index 0000000..c06abee --- /dev/null +++ b/common/service-utils/src/main/java/cn/bunny/common/service/config/Knife4jConfig.java @@ -0,0 +1,33 @@ +package cn.bunny.common.service.config; + +import io.swagger.v3.oas.models.ExternalDocumentation; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Contact; +import io.swagger.v3.oas.models.info.Info; +import io.swagger.v3.oas.models.info.License; +import lombok.extern.slf4j.Slf4j; +import org.springdoc.core.models.GroupedOpenApi; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@Slf4j +public class Knife4jConfig { + @Bean + public OpenAPI openAPI() { + // 作者等信息 + Contact contact = new Contact().name("Bunny").email("1319900154@qq.com").url("http://z-bunny.cn"); + // 使用协议 + License license = new License().name("MIT").url("https://MUT.com"); + // 相关信息 + Info info = new Info().title("Bunny-Admin").description("权限管理模板").version("v1.0.0").contact(contact).license(license).termsOfService("MIT"); + + return new OpenAPI().info(info).externalDocs(new ExternalDocumentation()); + } + + // 管理员相关分类接口 + @Bean + public GroupedOpenApi groupedOpenAdminApi() { + return GroupedOpenApi.builder().group("默认请求接口").pathsToMatch("/admin/**").build(); + } +} diff --git a/common/service-utils/src/main/java/cn/bunny/common/service/config/MyBatisPlusFieldConfig.java b/common/service-utils/src/main/java/cn/bunny/common/service/config/MyBatisPlusFieldConfig.java new file mode 100644 index 0000000..6f6e278 --- /dev/null +++ b/common/service-utils/src/main/java/cn/bunny/common/service/config/MyBatisPlusFieldConfig.java @@ -0,0 +1,41 @@ +package cn.bunny.common.service.config; + +import cn.bunny.common.service.context.BaseContext; +import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; +import org.apache.ibatis.reflection.MetaObject; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; + +/** + * 配置MP在修改和新增时的操作 + */ +@Component +public class MyBatisPlusFieldConfig implements MetaObjectHandler { + + /** + * 使用mp做添加操作时候,这个方法执行 + */ + @Override + public void insertFill(MetaObject metaObject) { + // 设置属性值 + this.strictInsertFill(metaObject, "isDeleted", Integer.class, 0); + this.setFieldValByName("createTime", LocalDateTime.now(), metaObject); + this.setFieldValByName("updateTime", LocalDateTime.now(), metaObject); + if (BaseContext.getUsername() != null) { + this.setFieldValByName("createUser", BaseContext.getUserId(), metaObject); + this.setFieldValByName("updateUser", BaseContext.getUserId(), metaObject); + } + } + + /** + * 使用mp做修改操作时候,这个方法执行 + */ + @Override + public void updateFill(MetaObject metaObject) { + if (BaseContext.getUserId() != null) { + this.setFieldValByName("updateTime", LocalDateTime.now(), metaObject); + this.setFieldValByName("updateUser", BaseContext.getUserId(), metaObject); + } + } +} diff --git a/common/service-utils/src/main/java/cn/bunny/common/service/config/MybatisPlusConfig.java b/common/service-utils/src/main/java/cn/bunny/common/service/config/MybatisPlusConfig.java new file mode 100644 index 0000000..beb7258 --- /dev/null +++ b/common/service-utils/src/main/java/cn/bunny/common/service/config/MybatisPlusConfig.java @@ -0,0 +1,36 @@ +package cn.bunny.common.service.config; + +import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +/** + * Mybatis-Plus配置类 + */ +@EnableTransactionManagement +@Configuration +@Slf4j +public class MybatisPlusConfig { + + @Bean + public MybatisPlusInterceptor mybatisPlusInterceptor() { + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + // 分页插件 + PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL); + // 设置最大分页为100 + paginationInnerInterceptor.setMaxLimit(600L); + interceptor.addInnerInterceptor(paginationInnerInterceptor); + // 乐观锁 + interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); + // 防止全表删除 + interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor()); + + return interceptor; + } +} diff --git a/common/service-utils/src/main/java/cn/bunny/common/service/config/RedisConfiguration.java b/common/service-utils/src/main/java/cn/bunny/common/service/config/RedisConfiguration.java new file mode 100644 index 0000000..be3f46b --- /dev/null +++ b/common/service-utils/src/main/java/cn/bunny/common/service/config/RedisConfiguration.java @@ -0,0 +1,141 @@ +package cn.bunny.common.service.config; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; +import lombok.extern.slf4j.Slf4j; +import org.springframework.cache.CacheManager; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Primary; +import org.springframework.data.redis.cache.RedisCacheConfiguration; +import org.springframework.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializationContext; +import org.springframework.data.redis.serializer.StringRedisSerializer; +import org.springframework.stereotype.Component; + +import java.time.Duration; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +/** + * 设置Redis序列化 + */ +@Component +@Slf4j +public class RedisConfiguration { + /** + * 使用StringRedisSerializer序列化为字符串 + */ + @Bean + public RedisTemplate redisTemplate(LettuceConnectionFactory connectionFactory) { + RedisTemplate redisTemplate = new RedisTemplate<>(); + redisTemplate.setConnectionFactory(connectionFactory); + // 设置key序列化为string + redisTemplate.setKeySerializer(new StringRedisSerializer()); + + // 设置value序列化为JSON,使用GenericJackson2JsonRedisSerializer替换默认序列化 + redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); + redisTemplate.setHashKeySerializer(new StringRedisSerializer()); + redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); + + // 开启Redis事务 + redisTemplate.setEnableTransactionSupport(true); + return redisTemplate; + } + + /** + * * 配置Redis过期时间 + * 一个月 + * 解决cache(@Cacheable)把数据缓存到redis中的value是乱码问题 + */ + @Bean + @Primary + @SuppressWarnings("all") + public CacheManager cacheManagerWithMouth(RedisConnectionFactory factory) { + // 配置序列化 + RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() + .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())) + .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jsonRedisSerializer())) + .entryTtl(Duration.ofDays(30)); + + return RedisCacheManager.builder(factory).cacheDefaults(config).build(); + } + + /** + * * 配置redis过期时间 + * 半个月 + * + * @param factory + * @return + */ + @Bean + @SuppressWarnings("all") + public CacheManager cacheManagerWithHalfOfMouth(RedisConnectionFactory factory) { + // 配置序列化 + RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() + .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())) + .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jsonRedisSerializer())) + .entryTtl(Duration.ofDays(15)); + + return RedisCacheManager.builder(factory).cacheDefaults(config).build(); + } + + /** + * * 配置Redis过期时间1小时 + * + * @param factory + * @return + */ + @Bean + @SuppressWarnings("all") + public CacheManager cacheManagerWithHours(RedisConnectionFactory factory) { + // 配置序列化 + RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() + .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())) + .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jsonRedisSerializer())) + .entryTtl(Duration.ofHours(1)); + + return RedisCacheManager.builder(factory).cacheDefaults(config).build(); + } + + /** + * 指定的日期模式 + */ + public Jackson2JsonRedisSerializer jsonRedisSerializer() { + // LocalDatetime序列化,默认不兼容jdk8日期序列化 + JavaTimeModule timeModule = new JavaTimeModule(); + timeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd"))); + timeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd"))); + timeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + timeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + + // 对象序列化 + ObjectMapper mapper = new ObjectMapper(); + + // 设置ObjectMapper访问权限 + mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + + // 记录序列化之后的数据类型,方便反序列化 + // mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL); + mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.EVERYTHING); + + // 关闭默认的日期格式化方式,默认UTC日期格式 yyyy-MM-dd’T’HH:mm:ss.SSS + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + mapper.registerModule(timeModule); + + return new Jackson2JsonRedisSerializer<>(mapper, Object.class); + } +} diff --git a/common/service-utils/src/main/java/cn/bunny/common/service/context/BaseContext.java b/common/service-utils/src/main/java/cn/bunny/common/service/context/BaseContext.java new file mode 100644 index 0000000..949c520 --- /dev/null +++ b/common/service-utils/src/main/java/cn/bunny/common/service/context/BaseContext.java @@ -0,0 +1,40 @@ +package cn.bunny.common.service.context; + +import cn.bunny.dao.vo.system.user.LoginVo; + +public class BaseContext { + private static final ThreadLocal userId = new ThreadLocal<>(); + private static final ThreadLocal username = new ThreadLocal<>(); + private static final ThreadLocal loginVo = new ThreadLocal<>(); + + // 用户id相关 + public static Long getUserId() { + return userId.get(); + } + + public static void setUserId(Long _userId) { + userId.set(_userId); + } + + public static String getUsername() { + return username.get(); + } + + public static void setUsername(String _username) { + username.set(_username); + } + + public static LoginVo getLoginVo() { + return loginVo.get(); + } + + public static void setLoginVo(LoginVo _loginVo) { + loginVo.set(_loginVo); + } + + public static void removeUser() { + username.remove(); + userId.remove(); + loginVo.remove(); + } +} \ No newline at end of file diff --git a/common/service-utils/src/main/java/cn/bunny/common/service/exception/BunnyException.java b/common/service-utils/src/main/java/cn/bunny/common/service/exception/BunnyException.java new file mode 100644 index 0000000..d300d33 --- /dev/null +++ b/common/service-utils/src/main/java/cn/bunny/common/service/exception/BunnyException.java @@ -0,0 +1,33 @@ +package cn.bunny.common.service.exception; + +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.extern.slf4j.Slf4j; + +@NoArgsConstructor +@Getter +@ToString +@Slf4j +public class BunnyException extends RuntimeException { + Integer code;// 状态码 + String message;// 描述信息 + + public BunnyException(Integer code, String message) { + super(message); + this.code = code; + this.message = message; + } + + public BunnyException(String message) { + super(message); + this.message = message; + } + + public BunnyException(ResultCodeEnum codeEnum) { + super(codeEnum.getMessage()); + this.code = codeEnum.getCode(); + this.message = codeEnum.getMessage(); + } +} diff --git a/common/service-utils/src/main/java/cn/bunny/common/service/exception/GlobalExceptionHandler.java b/common/service-utils/src/main/java/cn/bunny/common/service/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..cc39b7b --- /dev/null +++ b/common/service-utils/src/main/java/cn/bunny/common/service/exception/GlobalExceptionHandler.java @@ -0,0 +1,130 @@ +package cn.bunny.common.service.exception; + + +import cn.bunny.common.service.context.BaseContext; +import cn.bunny.dao.pojo.result.Result; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.support.DefaultMessageSourceResolvable; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import java.nio.file.AccessDeniedException; +import java.sql.SQLIntegrityConstraintViolationException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +@RestControllerAdvice +@Slf4j +public class GlobalExceptionHandler { + // 自定义异常信息 + @ExceptionHandler(BunnyException.class) + @ResponseBody + public Result exceptionHandler(BunnyException exception) { + Integer code = exception.getCode() != null ? exception.getCode() : 500; + return Result.error(null, code, exception.getMessage()); + } + + // 运行时异常信息 + @ExceptionHandler(RuntimeException.class) + @ResponseBody + public Result exceptionHandler(RuntimeException exception) { + String message = exception.getMessage(); + + // 解析异常 + String jsonParseError = "JSON parse error (.*)"; + Matcher jsonParseErrorMatcher = Pattern.compile(jsonParseError).matcher(message); + if (jsonParseErrorMatcher.find()) { + return Result.error(null, 500, "JSON解析异常 " + jsonParseErrorMatcher.group(1)); + } + + // 数据过大 + String dataTooLongError = "Data too long for column (.*?) at row 1"; + Matcher dataTooLongErrorMatcher = Pattern.compile(dataTooLongError).matcher(message); + if (dataTooLongErrorMatcher.find()) { + return Result.error(null, 500, dataTooLongErrorMatcher.group(1) + " 字段数据过大"); + } + + // 主键冲突 + String primaryKeyError = "Duplicate entry '(.*?)' for key .*"; + Matcher primaryKeyErrorMatcher = Pattern.compile(primaryKeyError).matcher(message); + if (primaryKeyErrorMatcher.find()) { + return Result.error(null, 500, "[" + primaryKeyErrorMatcher.group(1) + "]已存在"); + } + + log.error("GlobalExceptionHandler===>运行时异常信息:{}", message); + exception.printStackTrace(); + return Result.error(null, 500, "服务器异常"); + } + + // 捕获系统异常 + @ExceptionHandler(Exception.class) + @ResponseBody + public Result error(Exception exception) { + log.error("捕获系统异常:{}", exception.getMessage()); + log.error("GlobalExceptionHandler===>系统异常信息:{}", (Object) exception.getStackTrace()); + + // 错误消息 + String message = exception.getMessage(); + + // 匹配到内容 + String patternString = "Request method '(\\w+)' is not supported"; + Matcher matcher = Pattern.compile(patternString).matcher(message); + if (matcher.find()) return Result.error(null, 500, "请求方法错误,不是 " + matcher.group(1) + "类型请求"); + + // 请求API不存在 + String noStaticResource = "No static resource (.*)\\."; + Matcher noStaticResourceMatcher = Pattern.compile(noStaticResource).matcher(message); + if (noStaticResourceMatcher.find()) + return Result.error(null, 500, "请求API不存在 " + noStaticResourceMatcher.group(1)); + + // 返回错误内容 + return Result.error(null, 500, "系统异常"); + } + + // 表单验证字段 + @ExceptionHandler(MethodArgumentNotValidException.class) + public Result handleValidationExceptions(MethodArgumentNotValidException ex) { + log.error("表单验证失败,用户Id:{}", BaseContext.getUserId()); + String errorMessage = ex.getBindingResult().getFieldErrors().stream() + .map(DefaultMessageSourceResolvable::getDefaultMessage) + .collect(Collectors.joining(", ")); + return Result.error(null, 201, errorMessage); + } + + // 特定异常处理 + @ExceptionHandler(ArithmeticException.class) + @ResponseBody + public Result error(ArithmeticException exception) { + log.error("GlobalExceptionHandler===>特定异常信息:{}", exception.getMessage()); + + return Result.error(null, 500, exception.getMessage()); + } + + // spring security异常 + @ExceptionHandler(AccessDeniedException.class) + @ResponseBody + public Result error(AccessDeniedException exception) throws AccessDeniedException { + log.error("GlobalExceptionHandler===>spring security异常:{}", exception.getMessage()); + + return Result.error(ResultCodeEnum.SERVICE_ERROR); + } + + // 处理SQL异常 + @ExceptionHandler(SQLIntegrityConstraintViolationException.class) + @ResponseBody + public Result exceptionHandler(SQLIntegrityConstraintViolationException exception) { + log.error("GlobalExceptionHandler===>处理SQL异常:{}", exception.getMessage()); + + String message = exception.getMessage(); + if (message.contains("Duplicate entry")) { + // 错误信息 + return Result.error(ResultCodeEnum.USER_IS_EMPTY); + } else { + return Result.error(ResultCodeEnum.UNKNOWN_EXCEPTION); + } + } +} diff --git a/common/service-utils/src/main/java/cn/bunny/common/service/utils/EmptyUtil.java b/common/service-utils/src/main/java/cn/bunny/common/service/utils/EmptyUtil.java new file mode 100644 index 0000000..9cbfe0c --- /dev/null +++ b/common/service-utils/src/main/java/cn/bunny/common/service/utils/EmptyUtil.java @@ -0,0 +1,21 @@ +package cn.bunny.common.service.utils; + +import cn.bunny.common.service.exception.BunnyException; +import lombok.extern.slf4j.Slf4j; +import org.springframework.util.StringUtils; + +@Slf4j +public class EmptyUtil { + /** + * 是否为空 + * + * @param value 判断值 + * @param message 错误消息 + */ + public static void isEmpty(Object value, String message) { + if (value == null || !StringUtils.hasText(value.toString())) { + log.error("为空对象错误:{},{}", value, message); + throw new BunnyException(message); + } + } +} diff --git a/common/service-utils/src/main/java/cn/bunny/common/service/utils/FileUtil.java b/common/service-utils/src/main/java/cn/bunny/common/service/utils/FileUtil.java new file mode 100644 index 0000000..3daf5cd --- /dev/null +++ b/common/service-utils/src/main/java/cn/bunny/common/service/utils/FileUtil.java @@ -0,0 +1,31 @@ +package cn.bunny.common.service.utils; + +import org.springframework.stereotype.Component; + +@Component +public class FileUtil { + /** + * * 获取文件大小字符串 + */ + public static String getSize(Long fileSize) { + double fileSizeInKB = fileSize / 1024.00; + double fileSizeInMB = fileSizeInKB / 1024; + double fileSizeInGB = fileSizeInMB / 1024; + + String size; + if (fileSizeInGB >= 1) { + fileSizeInGB = Double.parseDouble(String.format("%.2f", fileSizeInGB)); + size = fileSizeInGB + "GB"; + } else if (fileSizeInMB >= 1) { + fileSizeInMB = Double.parseDouble(String.format("%.2f", fileSizeInMB)); + size = fileSizeInMB + "MB"; + } else if (fileSizeInKB >= 1) { + fileSizeInKB = Double.parseDouble(String.format("%.2f", fileSizeInKB)); + size = fileSizeInKB + "KB"; + } else { + size = fileSize + "B"; + } + + return size; + } +} diff --git a/common/service-utils/src/main/java/cn/bunny/common/service/utils/HttpUtil.java b/common/service-utils/src/main/java/cn/bunny/common/service/utils/HttpUtil.java new file mode 100644 index 0000000..bfb9b51 --- /dev/null +++ b/common/service-utils/src/main/java/cn/bunny/common/service/utils/HttpUtil.java @@ -0,0 +1,206 @@ +package cn.bunny.common.service.utils; + +import org.apache.commons.lang3.StringUtils; +import org.apache.http.HttpResponse; +import org.apache.http.NameValuePair; +import org.apache.http.client.HttpClient; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.conn.ClientConnectionManager; +import org.apache.http.conn.scheme.Scheme; +import org.apache.http.conn.scheme.SchemeRegistry; +import org.apache.http.conn.ssl.SSLSocketFactory; +import org.apache.http.entity.ByteArrayEntity; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.message.BasicNameValuePair; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class HttpUtil { + public static HttpResponse doGet(String host, String path, String method, Map headers, Map querys) throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpGet request = new HttpGet(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + return httpClient.execute(request); + } + + public static HttpResponse doPost(String host, String path, String method, Map headers, Map querys, Map bodys) throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPost request = new HttpPost(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (bodys != null) { + List nameValuePairList = new ArrayList(); + + for (String key : bodys.keySet()) { + nameValuePairList.add(new BasicNameValuePair(key, bodys.get(key))); + } + UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(nameValuePairList, "utf-8"); + formEntity.setContentType("application/x-www-form-urlencoded; charset=UTF-8"); + request.setEntity(formEntity); + } + + return httpClient.execute(request); + } + + + public static HttpResponse doPost(String host, String path, String method, Map headers, Map querys, String body) throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPost request = new HttpPost(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (StringUtils.isNotBlank(body)) { + request.setEntity(new StringEntity(body, "utf-8")); + } + + return httpClient.execute(request); + } + + + public static HttpResponse doPost(String host, String path, String method, Map headers, Map querys, byte[] body) throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPost request = new HttpPost(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (body != null) { + request.setEntity(new ByteArrayEntity(body)); + } + + return httpClient.execute(request); + } + + + public static HttpResponse doPut(String host, String path, String method, Map headers, Map querys, String body) throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPut request = new HttpPut(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (StringUtils.isNotBlank(body)) { + request.setEntity(new StringEntity(body, "utf-8")); + } + + return httpClient.execute(request); + } + + + public static HttpResponse doPut(String host, String path, String method, Map headers, Map querys, byte[] body) throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPut request = new HttpPut(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (body != null) { + request.setEntity(new ByteArrayEntity(body)); + } + + return httpClient.execute(request); + } + + + public static HttpResponse doDelete(String host, String path, String method, Map headers, Map querys) throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpDelete request = new HttpDelete(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + return httpClient.execute(request); + } + + private static String buildUrl(String host, String path, Map querys) throws UnsupportedEncodingException { + StringBuilder sbUrl = new StringBuilder(); + sbUrl.append(host); + if (!StringUtils.isBlank(path)) { + sbUrl.append(path); + } + if (null != querys) { + StringBuilder sbQuery = new StringBuilder(); + for (Map.Entry query : querys.entrySet()) { + if (!sbQuery.isEmpty()) { + sbQuery.append("&"); + } + if (StringUtils.isBlank(query.getKey()) && !StringUtils.isBlank(query.getValue())) { + sbQuery.append(query.getValue()); + } + if (!StringUtils.isBlank(query.getKey())) { + sbQuery.append(query.getKey()); + if (!StringUtils.isBlank(query.getValue())) { + sbQuery.append("="); + sbQuery.append(URLEncoder.encode(query.getValue(), StandardCharsets.UTF_8)); + } + } + } + if (!sbQuery.isEmpty()) { + sbUrl.append("?").append(sbQuery); + } + } + + return sbUrl.toString(); + } + + private static HttpClient wrapClient(String host) { + HttpClient httpClient = new DefaultHttpClient(); + if (host.startsWith("https://")) { + sslClient(httpClient); + } + + return httpClient; + } + + private static void sslClient(HttpClient httpClient) { + try { + SSLContext ctx = SSLContext.getInstance("TLS"); + X509TrustManager tm = new X509TrustManager() { + public X509Certificate[] getAcceptedIssuers() { + return null; + } + + public void checkClientTrusted(X509Certificate[] xcs, String str) { + } + + public void checkServerTrusted(X509Certificate[] xcs, String str) { + } + }; + ctx.init(null, new TrustManager[]{tm}, null); + SSLSocketFactory ssf = new SSLSocketFactory(ctx); + ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); + ClientConnectionManager ccm = httpClient.getConnectionManager(); + SchemeRegistry registry = ccm.getSchemeRegistry(); + registry.register(new Scheme("https", 443, ssf)); + } catch (Exception ex) { + throw new RuntimeException(); + } + } +} \ No newline at end of file diff --git a/common/service-utils/src/main/java/cn/bunny/common/service/utils/JwtHelper.java b/common/service-utils/src/main/java/cn/bunny/common/service/utils/JwtHelper.java new file mode 100644 index 0000000..efca21b --- /dev/null +++ b/common/service-utils/src/main/java/cn/bunny/common/service/utils/JwtHelper.java @@ -0,0 +1,352 @@ +package cn.bunny.common.service.utils; + +import cn.bunny.common.service.exception.BunnyException; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import io.jsonwebtoken.*; +import io.micrometer.common.lang.Nullable; +import org.springframework.util.StringUtils; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class JwtHelper { + // 时间 按天 计算 + private static final long tokenExpiration = 24 * 60 * 60 * 1000; + // JWT 的 秘钥 + private static final String tokenSignKey = "Bunny-Java-Template"; + // 默认主题 + private static final String subject = "Bunny"; + // 默认时间 + private static final Date time = new Date(System.currentTimeMillis() + tokenExpiration * 7); + + /** + * 使用默认主题,默认时间,默认秘钥,创建自定义集合token + * + * @param map 集合 + * @return token + */ + public static String createTokenWithMap(Map map) { + return Jwts.builder() + .setSubject(subject) + .setExpiration(time) + .signWith(SignatureAlgorithm.HS256, tokenSignKey) + .setClaims(map) + .setId(UUID.randomUUID().toString()) + .compressWith(CompressionCodecs.GZIP).compact(); + } + + /** + * 使用默认主题,默认秘钥,自定义时间,创建集合形式token + * + * @param map 集合 + * @param time 过期时间 + * @return token + */ + public static String createTokenWithMap(Map map, Date time) { + return Jwts.builder() + .setSubject(subject) + .signWith(SignatureAlgorithm.HS256, tokenSignKey) + .setExpiration(time) + .setClaims(map) + .setId(UUID.randomUUID().toString()) + .compressWith(CompressionCodecs.GZIP).compact(); + } + + /** + * 使用默认主题,默认秘钥,自定义时间,创建集合形式token + * + * @param map 集合 + * @param day 过期时间 + * @return token + */ + public static String createTokenWithMap(Map map, Integer day) { + return Jwts.builder() + .setSubject(subject) + .signWith(SignatureAlgorithm.HS256, tokenSignKey) + .setExpiration(new Date(System.currentTimeMillis() + tokenExpiration * day)) + .setClaims(map) + .setId(UUID.randomUUID().toString()) + .compressWith(CompressionCodecs.GZIP).compact(); + } + + /** + * 使用默认主题,默认秘钥,自定义key,创建集合形式token + * + * @param map 集合 + * @param tokenSignKey 自定义key + * @return token + */ + public static String createTokenWithMap(Map map, String tokenSignKey) { + return Jwts.builder() + .setSubject(subject) + .setExpiration(time) + .signWith(SignatureAlgorithm.HS256, tokenSignKey) + .setClaims(map) + .setId(UUID.randomUUID().toString()) + .compressWith(CompressionCodecs.GZIP).compact(); + } + + /** + * 使用自定义主题,自定义时间,创建集合形式token + * + * @param map 集合 + * @param subject 主题 + * @param time 过期时间 + * @return token + */ + public static String createTokenWithMap(Map map, String subject, Date time) { + return Jwts.builder() + .setSubject(subject) + .setExpiration(time) + .setClaims(map) + .setId(UUID.randomUUID().toString()) + .signWith(SignatureAlgorithm.HS256, tokenSignKey) + .compressWith(CompressionCodecs.GZIP) + .compact(); + } + + /** + * 创建集合形式token + * + * @param map 集合 + * @param subject 主题 + * @param tokenSignKey 过期时间 + * @return token + */ + public static String createTokenWithMap(Map map, String subject, String tokenSignKey) { + return Jwts.builder() + .setSubject(subject) + .setExpiration(time) + .signWith(SignatureAlgorithm.HS256, tokenSignKey) + .setClaims(map) + .setId(UUID.randomUUID().toString()) + .compressWith(CompressionCodecs.GZIP).compact(); + } + + /** + * 创建集合形式token + * + * @param map 集合 + * @param tokenSignKey 主题 + * @param time 过期时间 + * @return token + */ + public static String createTokenWithMap(Map map, String tokenSignKey, Integer time) { + return Jwts.builder() + .setSubject(subject) + .setExpiration(new Date(System.currentTimeMillis() + tokenExpiration * time)) + .setClaims(map) + .setId(UUID.randomUUID().toString()) + .signWith(SignatureAlgorithm.HS256, tokenSignKey) + .compressWith(CompressionCodecs.GZIP) + .compact(); + } + + /** + * 创建集合形式token + * + * @param map 集合 + * @param subject 主题 + * @param day 过期时间 + * @return token + */ + public static String createTokenWithMap(Map map, String subject, String tokenSignKey, Integer day) { + return Jwts.builder() + .setSubject(subject) + .setExpiration(new Date(System.currentTimeMillis() + tokenExpiration * day)) + .setClaims(map) + .setId(UUID.randomUUID().toString()) + .signWith(SignatureAlgorithm.HS256, tokenSignKey) + .compressWith(CompressionCodecs.GZIP) + .compact(); + } + + /** + * 创建集合形式token + * + * @param map 集合 + * @param subject 主题 + * @param time 过期时间 + * @return token + */ + public static String createTokenWithMap(Map map, String subject, String tokenSignKey, Date time) { + return Jwts.builder() + .setSubject(subject) + .setExpiration(time) + .setClaims(map) + .setId(UUID.randomUUID().toString()) + .signWith(SignatureAlgorithm.HS256, tokenSignKey) + .compressWith(CompressionCodecs.GZIP) + .compact(); + } + + /** + * 根据用户名和ID创建token + * + * @param userId 用户ID + * @param username 用户名 + * @param day 过期时间 + * @return token值 + */ + public static String createToken(Long userId, String username, Integer day) { + return Jwts.builder() + .setSubject(subject) + .setExpiration(new Date(System.currentTimeMillis() + tokenExpiration * day)) + .claim("userId", userId) + .claim("username", username) + .setId(UUID.randomUUID().toString()) + .signWith(SignatureAlgorithm.HS256, tokenSignKey) + .compressWith(CompressionCodecs.GZIP) + .compact(); + } + + /** + * 使用token获取map集合,使用默认秘钥 + * + * @param token token + * @return map集合 + */ + public static Map getMapByToken(String token) { + try { + if (!StringUtils.hasText(token)) throw new BunnyException(ResultCodeEnum.TOKEN_PARSING_FAILED); + Claims claims = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token).getBody(); + + // 将 body 值转为map + return new HashMap<>(claims); + + } catch (Exception exception) { + throw new BunnyException(ResultCodeEnum.TOKEN_PARSING_FAILED); + } + } + + /** + * 使用token获取map集合 + * + * @param token token + * @param signKey 秘钥 + * @return map集合 + */ + public static Map getMapByToken(String token, String signKey) { + try { + if (!StringUtils.hasText(token)) throw new BunnyException(ResultCodeEnum.TOKEN_PARSING_FAILED); + Jws claimsJws = Jwts.parser().setSigningKey(signKey).parseClaimsJws(token); + Claims body = claimsJws.getBody(); + // 将 body 值转为map + return new HashMap<>(body); + + } catch (Exception exception) { + throw new BunnyException(ResultCodeEnum.TOKEN_PARSING_FAILED); + } + } + + /** + * 根据token获取主题 + * + * @param token token + * @return 主题 + */ + public static String getSubjectByToken(String token) { + return getSubjectByTokenHandler(token, tokenSignKey); + } + + @Nullable + private static String getSubjectByTokenHandler(String token, String tokenSignKey) { + try { + if (!StringUtils.hasText(token)) throw new BunnyException(ResultCodeEnum.TOKEN_PARSING_FAILED); + Jws claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token); + Claims body = claimsJws.getBody(); + + return body.getSubject(); + + } catch (Exception exception) { + throw new BunnyException(ResultCodeEnum.TOKEN_PARSING_FAILED); + } + } + + /** + * 根据token获取主题 + * + * @param token token + * @return 主题 + */ + public static String getSubjectByToken(String token, String tokenSignKey) { + return getSubjectByTokenHandler(token, tokenSignKey); + } + + /** + * 根据token获取用户ID + * + * @param token token + * @return 用户ID + */ + public static Long getUserId(String token) { + try { + if (!StringUtils.hasText(token)) throw new BunnyException(ResultCodeEnum.TOKEN_PARSING_FAILED); + + Jws claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token); + Claims claims = claimsJws.getBody(); + + return Long.valueOf(String.valueOf(claims.get("userId"))); + } catch (Exception exception) { + throw new BunnyException(ResultCodeEnum.TOKEN_PARSING_FAILED); + } + } + + /** + * 根据token获取用户名 + * + * @param token token + * @return 用户名 + */ + public static String getUsername(String token) { + try { + if (!StringUtils.hasText(token)) return ""; + + Jws claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token); + Claims claims = claimsJws.getBody(); + return (String) claims.get("username"); + } catch (Exception exception) { + throw new BunnyException(ResultCodeEnum.TOKEN_PARSING_FAILED); + } + } + + /** + * 判断token是否过期 + * + * @param token token + * @return 是否过期 + */ + public static boolean isExpired(String token) { + return isExpiredUtil(token, tokenSignKey); + } + + /** + * 判断token是否过期 + * + * @param token token + * @return 是否过期 + */ + public static boolean isExpired(String token, String tokenSignKey) { + return isExpiredUtil(token, tokenSignKey); + } + + /** + * 判断是否过期 + * + * @param token token + * @param tokenSignKey key值 + * @return 是否过期 + */ + private static boolean isExpiredUtil(String token, String tokenSignKey) { + try { + Jws claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token); + Date expiration = claimsJws.getBody().getExpiration(); + + return expiration != null && expiration.before(new Date()); + } catch (Exception exception) { + return true; + } + } +} \ No newline at end of file diff --git a/common/service-utils/src/main/java/cn/bunny/common/service/utils/ResponseHandlerUtil.java b/common/service-utils/src/main/java/cn/bunny/common/service/utils/ResponseHandlerUtil.java new file mode 100644 index 0000000..8bf9c91 --- /dev/null +++ b/common/service-utils/src/main/java/cn/bunny/common/service/utils/ResponseHandlerUtil.java @@ -0,0 +1,12 @@ +package cn.bunny.common.service.utils; + +import cn.bunny.dao.pojo.result.Result; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import jakarta.servlet.http.HttpServletResponse; + +public class ResponseHandlerUtil { + public static boolean loginAuthHandler(HttpServletResponse response, ResultCodeEnum loginAuth) { + ResponseUtil.out(response, Result.error(loginAuth)); + return false; + } +} diff --git a/common/service-utils/src/main/java/cn/bunny/common/service/utils/ResponseUtil.java b/common/service-utils/src/main/java/cn/bunny/common/service/utils/ResponseUtil.java new file mode 100644 index 0000000..99a8d2e --- /dev/null +++ b/common/service-utils/src/main/java/cn/bunny/common/service/utils/ResponseUtil.java @@ -0,0 +1,26 @@ +package cn.bunny.common.service.utils; + +import cn.bunny.dao.pojo.result.Result; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.http.HttpStatus; + +import java.io.IOException; + +public class ResponseUtil { + + public static void out(HttpServletResponse response, Result result) { + ObjectMapper mapper = new ObjectMapper(); + + // 注册JavaTimeModule模块 + mapper.registerModule(new JavaTimeModule()); + response.setContentType("application/json;charset=UTF-8"); + response.setStatus(HttpStatus.OK.value()); + try { + mapper.writeValue(response.getWriter(), result); + } catch (IOException e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/common/service-utils/src/main/java/cn/bunny/common/service/utils/ip/IpEntity.java b/common/service-utils/src/main/java/cn/bunny/common/service/utils/ip/IpEntity.java new file mode 100644 index 0000000..44e3afa --- /dev/null +++ b/common/service-utils/src/main/java/cn/bunny/common/service/utils/ip/IpEntity.java @@ -0,0 +1,21 @@ +package cn.bunny.common.service.utils.ip; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@ApiModel(value = "IpEntity对象", description = "用户IP相关信息") +public class IpEntity { + @ApiModelProperty("原始地址") + private String ipAddr; + + @ApiModelProperty("IP归属地") + private String ipRegion; +} diff --git a/common/service-utils/src/main/java/cn/bunny/common/service/utils/ip/IpUtil.java b/common/service-utils/src/main/java/cn/bunny/common/service/utils/ip/IpUtil.java new file mode 100644 index 0000000..95d8d8c --- /dev/null +++ b/common/service-utils/src/main/java/cn/bunny/common/service/utils/ip/IpUtil.java @@ -0,0 +1,133 @@ +package cn.bunny.common.service.utils.ip; + +import jakarta.annotation.PostConstruct; +import jakarta.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import org.lionsoul.ip2region.xdb.Searcher; +import org.springframework.core.io.ClassPathResource; +import org.springframework.util.FileCopyUtils; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import java.io.InputStream; +import java.net.InetAddress; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +@Slf4j +public class IpUtil { + private static Searcher searcher; + + /** + * 判断是否为合法 IP + */ + public static boolean checkIp(String ipAddress) { + String ip = "([1-9]|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}"; + Pattern pattern = Pattern.compile(ip); + Matcher matcher = pattern.matcher(ipAddress); + return matcher.matches(); + } + + /** + * 在服务启动时,将 ip2region 加载到内存中 + */ + @PostConstruct + private static void initIp2Region() { + try { + InputStream inputStream = new ClassPathResource("/ipdb/ip2region.xdb").getInputStream(); + byte[] bytes = FileCopyUtils.copyToByteArray(inputStream); + searcher = Searcher.newWithBuffer(bytes); + } catch (Exception exception) { + log.error("ip转换错误消息:{}", exception.getMessage()); + log.error("ip转换错误栈:{}", (Object) exception.getStackTrace()); + } + } + + /** + * 获取 ip 所属地址 + * + * @param ip ip + */ + public static String getIpRegion(String ip) { + if (ip.equals("0:0:0:0:0:0:0:1")) ip = "127.0.0.1"; + boolean isIp = checkIp(ip); + if (isIp) { + initIp2Region(); + try { + // searchIpInfo 的数据格式: 国家|区域|省份|城市|ISP + String searchIpInfo = searcher.search(ip); + String[] splitIpInfo = searchIpInfo.split("\\|"); + if (splitIpInfo.length > 0) { + if ("中国".equals(splitIpInfo[0])) { + // 国内属地返回省份和地区 + return splitIpInfo[2] + "," + splitIpInfo[3] + " " + splitIpInfo[4]; + } else if ("0".equals(splitIpInfo[0])) { + if ("内网IP".equals(splitIpInfo[4])) { + // 内网 IP + return splitIpInfo[4]; + } else { + return ""; + } + } else { + // 国外属地返回国家 + return splitIpInfo[0]; + } + } + } catch (Exception exception) { + log.error("获取 ip 所属地址消息:{}", exception.getMessage()); + log.error("获取 ip 所属地址:{}", (Object) exception.getStackTrace()); + } + return ""; + } else { + throw new IllegalArgumentException("非法的IP地址"); + } + } + + /** + * * 获取当前用户登录IP地址 + * + * @return IP地址 + */ + public static IpEntity getCurrentUserIpAddress() { + ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + + // 判断IP地址归属地 + String remoteAddr = requestAttributes != null ? getIpAddr(requestAttributes.getRequest()) : "0:0:0:0:0:0:0:1"; + String ipRegion = IpUtil.getIpRegion(remoteAddr); + + // 转成环回地址 + remoteAddr = remoteAddr.equals("0:0:0:0:0:0:0:1") ? "127.0.0.1" : remoteAddr; + return IpEntity.builder().ipAddr(remoteAddr).ipRegion(ipRegion).build(); + } + + /** + * * 获取IP地址 + * + * @param request 请求头 + */ + public static String getIpAddr(HttpServletRequest request) { + String ipAddress; + try { + ipAddress = request.getHeader("x-forwarded-for"); + if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) { + ipAddress = request.getHeader("Proxy-Client-IP"); + } + if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) { + ipAddress = request.getHeader("WL-Proxy-Client-IP"); + } + if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) { + ipAddress = request.getRemoteAddr(); + if (ipAddress.equals("127.0.0.1")) ipAddress = InetAddress.getLocalHost().getHostAddress(); + } + // 对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割 + if (ipAddress != null && ipAddress.length() > 15) { + if (ipAddress.indexOf(",") > 0) { + ipAddress = ipAddress.substring(0, ipAddress.indexOf(",")); + } + } + } catch (Exception e) { + ipAddress = null; + } + return ipAddress; + } +} diff --git a/common/service-utils/src/main/java/cn/bunny/common/service/utils/mail/MailSenderUtil.java b/common/service-utils/src/main/java/cn/bunny/common/service/utils/mail/MailSenderUtil.java new file mode 100644 index 0000000..5b8690f --- /dev/null +++ b/common/service-utils/src/main/java/cn/bunny/common/service/utils/mail/MailSenderUtil.java @@ -0,0 +1,70 @@ +package cn.bunny.common.service.utils.mail; + +import cn.bunny.dao.pojo.common.EmailSend; +import cn.bunny.dao.pojo.common.EmailSendInit; +import jakarta.mail.MessagingException; +import jakarta.mail.internet.MimeMessage; +import org.springframework.mail.javamail.JavaMailSenderImpl; +import org.springframework.mail.javamail.MimeMessageHelper; +import org.springframework.web.multipart.MultipartFile; + +import java.util.Objects; + +public class MailSenderUtil { + + /** + * * 邮件发送初始化 + * + * @param emailSendInit 邮件发送初始化 + */ + public static JavaMailSenderImpl senderUtil(EmailSendInit emailSendInit) { + JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl(); + javaMailSender.setHost(emailSendInit.getHost()); + javaMailSender.setPort(emailSendInit.getPort()); + javaMailSender.setUsername(emailSendInit.getUsername()); + javaMailSender.setPassword(emailSendInit.getPassword()); + javaMailSender.setProtocol(emailSendInit.getProtocol()); + javaMailSender.setDefaultEncoding("UTF-8"); + + return javaMailSender; + } + + /** + * * 发送邮件 + * + * @param emailSendInit 邮件发送初始化 + * @param emailSend 邮件发送表单 + */ + public static void sendEmail(EmailSendInit emailSendInit, EmailSend emailSend) throws MessagingException { + // 发送邮件初始化 + JavaMailSenderImpl javaMailSender = senderUtil(emailSendInit); + MimeMessage message = javaMailSender.createMimeMessage(); + MimeMessageHelper helper = new MimeMessageHelper(message, true); + + // 设置发件人 + helper.setFrom(emailSendInit.getUsername()); + + // 设置群发内容 + helper.setTo(emailSend.getSendTo().toArray(new String[0])); + + // 设置主题 + helper.setSubject(emailSend.getSubject()); + + // 设置发送文本 + helper.setText(emailSend.getText(), emailSend.isRichText()); + + // 设置抄送 + helper.setCc(emailSend.getCcParam().toArray(new String[0])); + + // 设置附件 + MultipartFile[] files = emailSend.getFiles(); + if (files != null) { + for (MultipartFile file : files) { + helper.addAttachment(Objects.requireNonNull(file.getOriginalFilename()), file); + } + } + + // 发送邮件 + javaMailSender.send(message); + } +} diff --git a/common/service-utils/src/main/java/cn/bunny/common/service/utils/mail/template-propties b/common/service-utils/src/main/java/cn/bunny/common/service/utils/mail/template-propties new file mode 100644 index 0000000..cc51c94 --- /dev/null +++ b/common/service-utils/src/main/java/cn/bunny/common/service/utils/mail/template-propties @@ -0,0 +1,23 @@ +Configuration example + +mail: + host: smtp.qq.com # 邮箱地址 + port: 465 # 邮箱端口号 + username: xxx@qq.com # 设置发送邮箱 + password: xx # 如果是纯数字要加引号 + default-encoding: UTF-8 # 设置编码格式 + protocol: smtps + properties: + mail: + debug: true # 是否开启debug模式发送邮件 + smtp: + auth: true + connectionTimeout: 5000 # 设置连接延迟 + timeout: 5000 # 延迟时间 + writeTimeout: 5000 # 写入邮箱延迟 + allow8BitMime: true + sendPartial: true + ssl: + enabled: true # 是否开启SSL连接 + socketFactory: + class: javax.net.ssl.SSLSocketFactory # 必要设置!!! \ No newline at end of file diff --git a/common/service-utils/src/main/java/cn/bunny/common/service/utils/minio/MinioProperties.java b/common/service-utils/src/main/java/cn/bunny/common/service/utils/minio/MinioProperties.java new file mode 100644 index 0000000..2f659be --- /dev/null +++ b/common/service-utils/src/main/java/cn/bunny/common/service/utils/minio/MinioProperties.java @@ -0,0 +1,26 @@ +package cn.bunny.common.service.utils.minio; + +import io.minio.MinioClient; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ConfigurationProperties(prefix = "bunny.minio") +@ConditionalOnProperty(name = "bunny.minio.bucket-name")// 当属性有值时这个配置才生效 +@Data +@Slf4j +public class MinioProperties { + private String endpointUrl; + private String accessKey; + private String secretKey; + private String bucketName; + + @Bean + public MinioClient minioClient() { + return MinioClient.builder().endpoint(endpointUrl).credentials(accessKey, secretKey).build(); + } +} diff --git a/common/service-utils/src/main/java/cn/bunny/common/service/utils/minio/MinioUtil.java b/common/service-utils/src/main/java/cn/bunny/common/service/utils/minio/MinioUtil.java new file mode 100644 index 0000000..12fe945 --- /dev/null +++ b/common/service-utils/src/main/java/cn/bunny/common/service/utils/minio/MinioUtil.java @@ -0,0 +1,176 @@ +package cn.bunny.common.service.utils.minio; + +import cn.bunny.common.service.exception.BunnyException; +import cn.bunny.dao.pojo.common.MinioFilePath; +import cn.bunny.dao.pojo.constant.MinioConstant; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import io.minio.*; +import io.minio.messages.DeleteError; +import io.minio.messages.DeleteObject; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.io.InputStream; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.List; +import java.util.UUID; + +/** + * Minio操作工具类 简化操作步骤 + * By:Bunny0212 + */ +@Component +@Slf4j +public class MinioUtil { + @Autowired + private MinioProperties properties; + + @Autowired + private MinioClient minioClient; + + /** + * 获取Minio文件路径 + */ + public static MinioFilePath initUploadFileReturnMinioFilePath(String buckName, String minioPreType, MultipartFile file) { + String uuid = UUID.randomUUID().toString(); + // 定义日期时间格式 + LocalDateTime currentDateTime = LocalDateTime.now(); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM-dd"); + String extension = ""; + + // 原始文件名 + String filename = file.getOriginalFilename(); + if (StringUtils.hasText(filename) && filename.contains(".")) { + extension = "." + filename.substring(filename.lastIndexOf(".") + 1); + } + + // UUID防止重名 + String uuidFilename = uuid + extension; + + // 拼接时间+UUID文件名 + String timeUuidFilename = currentDateTime.format(formatter) + "/" + uuidFilename;// 加上时间路径 + + // 上传根文件夹+拼接时间+UUID文件名 + String filepath = MinioConstant.getType(minioPreType) + timeUuidFilename; + + // 桶名称+上传根文件夹+拼接时间+UUID文件名 + String buckNameFilepath = "/" + buckName + MinioConstant.getType(minioPreType) + timeUuidFilename; + + // 设置及Minio基础信息 + MinioFilePath minioFIlePath = new MinioFilePath(); + minioFIlePath.setFilename(filename); + minioFIlePath.setUuidFilename(uuidFilename); + minioFIlePath.setTimeUuidFilename(timeUuidFilename); + minioFIlePath.setFilepath(filepath); + minioFIlePath.setBucketNameFilepath(buckNameFilepath); + + return minioFIlePath; + } + + /** + * * 上传文件并返回处理信息 + */ + public MinioFilePath uploadObjectReturnFilePath(MultipartFile file, String minioPreType) throws IOException { + if (file == null) return null; + String bucketName = properties.getBucketName(); + + // 上传对象 + try { + MinioFilePath minioFile = initUploadFileReturnMinioFilePath(bucketName, minioPreType, file); + + minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(minioFile.getFilepath()).stream(file.getInputStream(), file.getSize(), -1).build()); + + return minioFile; + } catch (Exception exception) { + throw new BunnyException(ResultCodeEnum.UPDATE_ERROR); + } + } + + /** + * 获取默认bucket文件,并返回字节数组 + * + * @param objectName 对象名称 + * @return 文件流对象 + */ + public byte[] getBucketObjectByte(String objectName) { + String bucketName = properties.getBucketName(); + + try { + GetObjectResponse getObjectResponse = minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(objectName).build()); + + return getObjectResponse.readAllBytes(); + } catch (Exception exception) { + exception.printStackTrace(); + } + throw new BunnyException(ResultCodeEnum.GET_BUCKET_EXCEPTION); + } + + /** + * 获取Minio全路径名,Object带有桶名称 + * + * @param objectName 对象名称 + * @return 全路径 + */ + public String getObjectNameFullPath(String objectName) { + String url = properties.getEndpointUrl(); + + return url + objectName; + } + + /** + * 上传文件 + * + * @param bucketName 桶名称 + * @param filename 文件名 + * @param inputStream 输入流 + * @param size 大小 + */ + public void putObject(String bucketName, String filename, InputStream inputStream, Long size) { + try { + minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(filename).stream(inputStream, size, -1).build()); + } catch (Exception exception) { + log.error("上传文件失败:{}", (Object) exception.getStackTrace()); + throw new BunnyException(ResultCodeEnum.UPDATE_ERROR); + } + } + + /** + * * 删除目标文件 + * + * @param list 对象文件列表 + */ + public void removeObjects(List list) { + try { + String bucketName = properties.getBucketName(); + List objectList = list.stream().map(DeleteObject::new).toList(); + + Iterable> results = minioClient.removeObjects(RemoveObjectsArgs.builder().bucket(bucketName).objects(objectList).build()); + for (Result result : results) { + DeleteError error = result.get(); + throw new BunnyException("Error in deleting object " + error.objectName() + "; " + error.message()); + } + } catch (Exception exception) { + exception.printStackTrace(); + } + } + + /** + * * 更新文件 + * + * @param bucketName 桶名称 + * @param filepath 文件路径 + * @param file 文件 + */ + public void updateFile(String bucketName, String filepath, MultipartFile file) { + try { + putObject(bucketName, filepath, file.getInputStream(), file.getSize()); + } catch (IOException e) { + throw new BunnyException(e.getMessage()); + } + } +} diff --git a/dao/pom.xml b/dao/pom.xml new file mode 100644 index 0000000..a142267 --- /dev/null +++ b/dao/pom.xml @@ -0,0 +1,48 @@ + + 4.0.0 + + cn.bunny + financial-admin-server + 0.0.1-SNAPSHOT + + + dao + jar + + model + https://maven.apache.org + + + UTF-8 + + + + + + org.projectlombok + lombok + + + + com.baomidou + mybatis-plus-spring-boot3-starter + + + + com.github.xiaoymin + knife4j-openapi3-jakarta-spring-boot-starter + + + + com.alibaba.fastjson2 + fastjson2 + + + + io.swagger + swagger-annotations + 1.6.14 + + + diff --git a/dao/src/main/java/cn/bunny/dao/common/entity/BaseEntity.java b/dao/src/main/java/cn/bunny/dao/common/entity/BaseEntity.java new file mode 100644 index 0000000..b557de8 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/common/entity/BaseEntity.java @@ -0,0 +1,48 @@ +package cn.bunny.dao.common.entity; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +@Data +@Schema(name = "BaseEntity", title = "基础信息字段", description = "基础信息字段") +public class BaseEntity implements Serializable { + + @Schema(name = "id", title = "唯一标识") + @TableId(value = "id", type = IdType.ASSIGN_ID) + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + @Schema(name = "createTime", title = "创建时间") + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + @Schema(name = "updateTime", title = "更新时间") + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + @Schema(name = "createUser", title = "创建用户") + @TableField(fill = FieldFill.INSERT) + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JsonSerialize(using = ToStringSerializer.class) + private Long createUser; + + @Schema(name = "updateUser", title = "操作用户") + @TableField(fill = FieldFill.INSERT_UPDATE) + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JsonSerialize(using = ToStringSerializer.class) + private Long updateUser; + + @Schema(name = "isDeleted", title = "是否被删除") + @TableLogic + private Boolean isDeleted; + +} + diff --git a/dao/src/main/java/cn/bunny/dao/common/entity/BaseUserEntity.java b/dao/src/main/java/cn/bunny/dao/common/entity/BaseUserEntity.java new file mode 100644 index 0000000..4adf13f --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/common/entity/BaseUserEntity.java @@ -0,0 +1,18 @@ +package cn.bunny.dao.common.entity; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@EqualsAndHashCode(callSuper = true) +@Data +@Schema(name = "BaseUserEntity", title = "基础信息字段包含用户信息", description = "基础信息字段包含用户信息") +public class BaseUserEntity extends BaseEntity { + + @Schema(name = "username", title = "用户名") + private String createUsername; + + @Schema(name = "nickname", title = "昵称") + private String updateUsername; + +} diff --git a/dao/src/main/java/cn/bunny/dao/common/vo/BaseUserVo.java b/dao/src/main/java/cn/bunny/dao/common/vo/BaseUserVo.java new file mode 100644 index 0000000..572aa7a --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/common/vo/BaseUserVo.java @@ -0,0 +1,18 @@ +package cn.bunny.dao.common.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@EqualsAndHashCode(callSuper = true) +@Data +@Schema(name = "BaseVo", title = "基础返回对象内容包含用户信息", description = "基础返回对象内容包含用户信息") +public class BaseUserVo extends BaseVo { + + @Schema(name = "username", title = "用户名") + private String createUsername; + + @Schema(name = "nickname", title = "昵称") + private String updateUsername; + +} diff --git a/dao/src/main/java/cn/bunny/dao/common/vo/BaseVo.java b/dao/src/main/java/cn/bunny/dao/common/vo/BaseVo.java new file mode 100644 index 0000000..7214f16 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/common/vo/BaseVo.java @@ -0,0 +1,49 @@ +package cn.bunny.dao.common.vo; + +import com.alibaba.fastjson2.annotation.JSONField; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +@Data +@Schema(name = "BaseVo", title = "基础返回对象内容", description = "基础返回对象内容") +public class BaseVo implements Serializable { + + @Schema(name = "id", title = "主键") + @JsonProperty("id") + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JSONField(serializeUsing = ToStringSerializer.class) + private Long id; + + @Schema(name = "updateTime", title = "更新时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonSerialize(using = LocalDateTimeSerializer.class) + @JsonDeserialize(using = LocalDateTimeDeserializer.class) + private LocalDateTime updateTime; + + @Schema(name = "createTime", title = "发布时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonSerialize(using = LocalDateTimeSerializer.class) + @JsonDeserialize(using = LocalDateTimeDeserializer.class) + private LocalDateTime createTime; + + @Schema(name = "createUser", title = "创建用户") + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JSONField(serializeUsing = ToStringSerializer.class) + private Long createUser; + + @Schema(name = "updateUser", title = "操作用户") + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JSONField(serializeUsing = ToStringSerializer.class) + private Long updateUser; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/common/vo/TreeSelectVo.java b/dao/src/main/java/cn/bunny/dao/common/vo/TreeSelectVo.java new file mode 100644 index 0000000..e41029e --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/common/vo/TreeSelectVo.java @@ -0,0 +1,42 @@ +package cn.bunny.dao.common.vo; + +import com.alibaba.fastjson2.annotation.JSONField; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.List; + +@Data +@Schema(name = "TreeSelectList对象", title = "树形结构数据", description = "树形结构数据") +public class TreeSelectVo { + + @Schema(name = "id", title = "主键") + @JsonProperty("id") + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JSONField(serializeUsing = ToStringSerializer.class) + private Long id; + + @Schema(name = "value", title = "值内容") + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JSONField(serializeUsing = ToStringSerializer.class) + private Object value; + + @Schema(name = "key", title = "key内容") + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JSONField(serializeUsing = ToStringSerializer.class) + private Object key; + + @Schema(name = "label", title = "显示内容") + private String label; + + @Schema(name = "parentId", title = "父级id") + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JSONField(serializeUsing = ToStringSerializer.class) + private Long parentId; + + @Schema(name = "children", title = "子级内容") + private List children; +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/dto/financial/bill/BillAddDto.java b/dao/src/main/java/cn/bunny/dao/dto/financial/bill/BillAddDto.java new file mode 100644 index 0000000..9845972 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/financial/bill/BillAddDto.java @@ -0,0 +1,46 @@ +package cn.bunny.dao.dto.financial.bill; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "BillAddDto对象", title = "账单信息添加内容", description = "账单信息添加内容") +public class BillAddDto { + + @Schema(name = "username", title = "类型:1 - 收入,-1 - 支出") + @NotNull(message = "类型不能为空") + @Min(value = -1, message = "类型格式不正确") + @Max(value = 1, message = "类型格式不正确") + private Byte type; + + @Schema(name = "amount", title = "金额") + @NotNull(message = "金额不能为空") + @Min(value = 0, message = "金额格式不正确") + private BigDecimal amount; + + @Schema(name = "description", title = "描述") + private String description; + + @Schema(name = "transactionDate", title = "交易日期") + @NotNull(message = "交易日期不能为空") + @JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime transactionDate; + + @Schema(name = "categoryId", title = "类别id") + @NotNull(message = "类别id不能为空") + private Long categoryId; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/dto/financial/bill/BillDto.java b/dao/src/main/java/cn/bunny/dao/dto/financial/bill/BillDto.java new file mode 100644 index 0000000..d673531 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/financial/bill/BillDto.java @@ -0,0 +1,33 @@ +package cn.bunny.dao.dto.financial.bill; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDate; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "BillDto对象", title = "账单信息查询内容", description = "账单信息查询内容") +public class BillDto { + + @Schema(name = "username", title = "类型:1 - 收入,-1 - 支出") + private Byte type; + + @Schema(name = "description", title = "描述") + private String description; + + @Schema(name = "startDate", title = "开始交易日期") + @JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd") + private LocalDate startDate; + + @Schema(name = "endDate", title = "结束交易日期") + @JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd") + private LocalDate endDate; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/dto/financial/bill/BillUpdateDto.java b/dao/src/main/java/cn/bunny/dao/dto/financial/bill/BillUpdateDto.java new file mode 100644 index 0000000..f848bcf --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/financial/bill/BillUpdateDto.java @@ -0,0 +1,41 @@ +package cn.bunny.dao.dto.financial.bill; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "BillUpdateDto对象", title = "账单信息更新内容", description = "账单信息更新内容") +public class BillUpdateDto { + + @Schema(name = "id", title = "主键") + @NotNull(message = "id不能为空") + private Long id; + + @Schema(name = "username", title = "类型:1 - 收入,-1 - 支出") + private Byte type; + + @Schema(name = "amount", title = "金额") + private BigDecimal amount; + + @Schema(name = "description", title = "描述") + private String description; + + @Schema(name = "transactionDate", title = "交易日期") + @JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime transactionDate; + + @Schema(name = "categoryId", title = "类别id") + private Long categoryId; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/dto/financial/category/CategoryUserAddDto.java b/dao/src/main/java/cn/bunny/dao/dto/financial/category/CategoryUserAddDto.java new file mode 100644 index 0000000..2611bac --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/financial/category/CategoryUserAddDto.java @@ -0,0 +1,24 @@ +package cn.bunny.dao.dto.financial.category; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "CategoryUserAddDto对象", title = "分类信息添加", description = "分类信息添加") +public class CategoryUserAddDto { + + @Schema(name = "categoryName", title = "分类名称") + @NotNull(message = "分类名称不能为空") + @NotBlank(message = "分类名称不能为空") + private String categoryName; + +} + diff --git a/dao/src/main/java/cn/bunny/dao/dto/financial/category/CategoryUserDto.java b/dao/src/main/java/cn/bunny/dao/dto/financial/category/CategoryUserDto.java new file mode 100644 index 0000000..04f2fc2 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/financial/category/CategoryUserDto.java @@ -0,0 +1,30 @@ +package cn.bunny.dao.dto.financial.category; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "CategoryDto对象", title = "分类信息查询", description = "分类信息查询") +public class CategoryUserDto { + + @Schema(name = "categoryName", title = "分类名称") + private String categoryName; + + @Schema(name = "isBuiltin", title = "是否内置字段") + private Boolean isBuiltin; + +} + + + + + + + + diff --git a/dao/src/main/java/cn/bunny/dao/dto/financial/category/CategoryUserUpdateDto.java b/dao/src/main/java/cn/bunny/dao/dto/financial/category/CategoryUserUpdateDto.java new file mode 100644 index 0000000..60f5c9b --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/financial/category/CategoryUserUpdateDto.java @@ -0,0 +1,27 @@ +package cn.bunny.dao.dto.financial.category; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "CategoryUpdateDto对象", title = "分类信息添加", description = "分类信息添加") +public class CategoryUserUpdateDto { + + @Schema(name = "id", title = "主键") + @NotNull(message = "id不能为空") + private Long id; + + @Schema(name = "categoryName", title = "分类名称") + @NotNull(message = "分类名称不能为空") + @NotBlank(message = "分类名称不能为空") + private String categoryName; + +} diff --git a/dao/src/main/java/cn/bunny/dao/dto/i18n/I18nAddDto.java b/dao/src/main/java/cn/bunny/dao/dto/i18n/I18nAddDto.java new file mode 100644 index 0000000..0dba62c --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/i18n/I18nAddDto.java @@ -0,0 +1,34 @@ +package cn.bunny.dao.dto.i18n; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "I18nAddDto对象", title = "多语言添加", description = "多语言添加") +public class I18nAddDto { + + @Schema(name = "keyName", title = "多语言key") + @NotBlank(message = "多语言key不能为空") + @NotNull(message = "多语言key不能为空") + private String keyName; + + @Schema(name = "translation", title = "多语言翻译名称") + @NotBlank(message = "多语言翻译名称不能为空") + @NotNull(message = "多语言翻译名称不能为空") + private String translation; + + @Schema(name = "typeName", title = "多语言类型名称") + @NotBlank(message = "多语言类型名称不能为空") + @NotNull(message = "多语言类型名称不能为空") + private String typeName; + +} + diff --git a/dao/src/main/java/cn/bunny/dao/dto/i18n/I18nDto.java b/dao/src/main/java/cn/bunny/dao/dto/i18n/I18nDto.java new file mode 100644 index 0000000..f10a44f --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/i18n/I18nDto.java @@ -0,0 +1,26 @@ +package cn.bunny.dao.dto.i18n; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "I18nDto对象", title = "多语言分页查询", description = "多语言分页查询") +public class I18nDto { + + @Schema(name = "keyName", title = "多语言key") + private String keyName; + + @Schema(name = "translation", title = "多语言翻译名称") + private String translation; + + @Schema(name = "typeName", title = "多语言类型名称") + private String typeName; + +} + diff --git a/dao/src/main/java/cn/bunny/dao/dto/i18n/I18nTypeAddDto.java b/dao/src/main/java/cn/bunny/dao/dto/i18n/I18nTypeAddDto.java new file mode 100644 index 0000000..d0e0f68 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/i18n/I18nTypeAddDto.java @@ -0,0 +1,32 @@ +package cn.bunny.dao.dto.i18n; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "I18nTypeAddDto对象", title = "多语言类型添加", description = "多语言类型添加内容") +public class I18nTypeAddDto { + + @Schema(name = "typeName", title = "多语言类型(比如zh,en)") + @NotBlank(message = "多语言类型不能为空") + @NotNull(message = "多语言类型不能为空") + private String typeName; + + @Schema(name = "summary", title = "名称解释(比如中文,英文)") + @NotNull(message = "名称解释不能为空") + private String summary; + + @Schema(name = "isDefault", title = "是否为默认") + private Boolean isDefault = false; + +} + + diff --git a/dao/src/main/java/cn/bunny/dao/dto/i18n/I18nTypeDto.java b/dao/src/main/java/cn/bunny/dao/dto/i18n/I18nTypeDto.java new file mode 100644 index 0000000..a0915df --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/i18n/I18nTypeDto.java @@ -0,0 +1,22 @@ +package cn.bunny.dao.dto.i18n; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "I18nTypeDto对象", title = "多语言类型", description = "多语言类型") +public class I18nTypeDto { + + @Schema(name = "typeName", title = "多语言类型(比如zh,en)") + private String typeName; + + @Schema(name = "summary", title = "名称解释(比如中文,英文)") + private String summary; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/dto/i18n/I18nTypeUpdateDto.java b/dao/src/main/java/cn/bunny/dao/dto/i18n/I18nTypeUpdateDto.java new file mode 100644 index 0000000..7e53a24 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/i18n/I18nTypeUpdateDto.java @@ -0,0 +1,35 @@ +package cn.bunny.dao.dto.i18n; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "I18nTypeUpdateDto对象", title = "多语言类型更新", description = "多语言类型更新内容") +public class I18nTypeUpdateDto { + + @Schema(name = "id", title = "主键") + @NotNull(message = "id不能为空") + private Long id; + + @Schema(name = "typeName", title = "多语言类型(比如zh,en)") + @NotBlank(message = "多语言类型不能为空") + @NotNull(message = "多语言类型不能为空") + private String typeName; + + @Schema(name = "summary", title = "名称解释(比如中文,英文)") + @NotBlank(message = "名称解释不能为空") + @NotNull(message = "名称解释不能为空") + private String summary; + + @Schema(name = "isDefault", title = "是否为默认") + private Boolean isDefault = false; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/dto/i18n/I18nUpdateDto.java b/dao/src/main/java/cn/bunny/dao/dto/i18n/I18nUpdateDto.java new file mode 100644 index 0000000..096fe2a --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/i18n/I18nUpdateDto.java @@ -0,0 +1,36 @@ +package cn.bunny.dao.dto.i18n; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "I18nUpdateDto对象", title = "多语言更新", description = "多语言更新") +public class I18nUpdateDto { + + @Schema(name = "id", title = "主键") + @NotNull(message = "id不能为空") + private Long id; + + @Schema(name = "keyName", title = "多语言key") + @NotBlank(message = "多语言key不能为空") + @NotNull(message = "多语言key不能为空") + private String keyName; + + @Schema(name = "translation", title = "多语言翻译名称") + @NotBlank(message = "多语言翻译名称不能为空") + @NotNull(message = "多语言翻译名称不能为空") + private String translation; + + + @Schema(name = "typeId", title = "多语言类型id") + private Long typeId; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/dto/log/ScheduleExecuteLogDto.java b/dao/src/main/java/cn/bunny/dao/dto/log/ScheduleExecuteLogDto.java new file mode 100644 index 0000000..5c1a144 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/log/ScheduleExecuteLogDto.java @@ -0,0 +1,31 @@ +package cn.bunny.dao.dto.log; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "QuartzExecuteLogDto对象", title = "调度任务执行日志分页查询", description = "调度任务执行日志分页查询") +public class ScheduleExecuteLogDto { + + @Schema(name = "jobName", title = "任务名称") + private String jobName; + + @Schema(name = "jobGroup", title = "任务分组") + private String jobGroup; + + @Schema(name = "jobClassName", title = "执行任务类名") + private String jobClassName; + + @Schema(name = "cronExpression", title = "执行任务core表达式") + private String cronExpression; + + @Schema(name = "triggerName", title = "触发器名称") + private String triggerName; + +} diff --git a/dao/src/main/java/cn/bunny/dao/dto/log/UserLoginLogDto.java b/dao/src/main/java/cn/bunny/dao/dto/log/UserLoginLogDto.java new file mode 100644 index 0000000..638d9c8 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/log/UserLoginLogDto.java @@ -0,0 +1,41 @@ +package cn.bunny.dao.dto.log; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "UserLoginLogDto对象", title = "用户登录日志分页查询", description = "用户登录日志分页查询") +public class UserLoginLogDto { + + @Schema(name = "userId", title = "用户Id") + private Long userId; + + @Schema(name = "username", title = "用户名") + private String username; + + @Schema(name = "token", title = "登录token") + private String token; + + @Schema(name = "ipAddress", title = "登录Ip") + private String ipAddress; + + @Schema(name = "ipRegion", title = "登录Ip归属地") + private String ipRegion; + + @Schema(name = "userAgent", title = "登录时代理") + private String userAgent; + + @Schema(name = "type", title = "操作类型") + private String type; + + @Schema(name = "xRequestedWith", title = "标识客户端是否是通过Ajax发送请求的") + private String xRequestedWith; + +} + diff --git a/dao/src/main/java/cn/bunny/dao/dto/log/UserLoginLogUpdateDto.java b/dao/src/main/java/cn/bunny/dao/dto/log/UserLoginLogUpdateDto.java new file mode 100644 index 0000000..3b0f001 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/log/UserLoginLogUpdateDto.java @@ -0,0 +1,40 @@ +package cn.bunny.dao.dto.log; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "UserLoginLogDto对象", title = "用户登录日志分页查询", description = "用户登录日志分页查询") +public class UserLoginLogUpdateDto { + + @Schema(name = "userId", title = "用户Id") + private Long userId; + + @Schema(name = "username", title = "用户名") + private String username; + + @Schema(name = "token", title = "登录token") + private String token; + + @Schema(name = "ipAddress", title = "登录Ip") + private String ipAddress; + + @Schema(name = "ipRegion", title = "登录Ip归属地") + private String ipRegion; + + @Schema(name = "userAgent", title = "登录时代理") + private String userAgent; + + @Schema(name = "type", title = "操作类型") + private String type; + + @Schema(name = "xRequestedWith", title = "标识客户端是否是通过Ajax发送请求的") + private String xRequestedWith; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/dto/quartz/SchedulersOperationDto.java b/dao/src/main/java/cn/bunny/dao/dto/quartz/SchedulersOperationDto.java new file mode 100644 index 0000000..9801d7b --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/quartz/SchedulersOperationDto.java @@ -0,0 +1,28 @@ +package cn.bunny.dao.dto.quartz; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "SchedulersOperationDto对象", title = "Schedulers公共操作表单", description = "Schedulers公共操作表单") +public class SchedulersOperationDto { + + @Schema(name = "jobName", title = "任务名称") + @NotBlank(message = "任务名称不能为空") + @NotNull(message = "任务名称不能为空") + private String jobName; + + @Schema(name = "jobGroup", title = "任务分组") + @NotBlank(message = "任务分组不能为空") + @NotNull(message = "任务分组不能为空") + private String jobGroup; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/dto/quartz/group/SchedulersGroupAddDto.java b/dao/src/main/java/cn/bunny/dao/dto/quartz/group/SchedulersGroupAddDto.java new file mode 100644 index 0000000..b225963 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/quartz/group/SchedulersGroupAddDto.java @@ -0,0 +1,26 @@ +package cn.bunny.dao.dto.quartz.group; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "SchedulersGroupAddDto对象", title = "添加任务调度分组", description = "添加任务调度分组") +public class SchedulersGroupAddDto { + + @Schema(name = "groupName", title = "分组名称") + @NotBlank(message = "分组名称不能为空") + @NotNull(message = "分组名称不能为空") + private String groupName; + + @Schema(name = "description", title = "分组详情") + private String description; + +} diff --git a/dao/src/main/java/cn/bunny/dao/dto/quartz/group/SchedulersGroupDto.java b/dao/src/main/java/cn/bunny/dao/dto/quartz/group/SchedulersGroupDto.java new file mode 100644 index 0000000..dc36c78 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/quartz/group/SchedulersGroupDto.java @@ -0,0 +1,24 @@ +package cn.bunny.dao.dto.quartz.group; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "SchedulersGroupDto对象", title = "分页查询任务调度分组", description = "分页查询任务调度分组") +public class SchedulersGroupDto { + + @Schema(name = "groupName", title = "分组名称") + private String groupName; + + @Schema(name = "description", title = "分组详情") + private String description; + +} + + diff --git a/dao/src/main/java/cn/bunny/dao/dto/quartz/group/SchedulersGroupUpdateDto.java b/dao/src/main/java/cn/bunny/dao/dto/quartz/group/SchedulersGroupUpdateDto.java new file mode 100644 index 0000000..725a5ed --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/quartz/group/SchedulersGroupUpdateDto.java @@ -0,0 +1,30 @@ +package cn.bunny.dao.dto.quartz.group; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "SchedulersGroupUpdateDto对象", title = "更新任务调度分组", description = "更新任务调度分组") +public class SchedulersGroupUpdateDto { + + @Schema(name = "id", title = "主键") + @NotNull(message = "id不能为空") + private Long id; + + @Schema(name = "groupName", title = "分组名称") + @NotBlank(message = "分组名称不能为空") + @NotNull(message = "分组名称不能为空") + private String groupName; + + @Schema(name = "description", title = "分组详情") + private String description; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/dto/quartz/schedule/SchedulersAddDto.java b/dao/src/main/java/cn/bunny/dao/dto/quartz/schedule/SchedulersAddDto.java new file mode 100644 index 0000000..85eb52e --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/quartz/schedule/SchedulersAddDto.java @@ -0,0 +1,44 @@ +package cn.bunny.dao.dto.quartz.schedule; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "SchedulersAddDto对象", title = "Schedulers添加表单", description = "Schedulers添加表单") +public class SchedulersAddDto { + + @Schema(name = "jobName", title = "任务名称") + @NotBlank(message = "任务名称不能为空") + @NotNull(message = "任务名称不能为空") + private String jobName; + + @Schema(name = "jobGroup", title = "任务分组") + @NotBlank(message = "任务分组不能为空") + @NotNull(message = "任务分组不能为空") + private String jobGroup; + + @Schema(name = "description", title = "任务详情") + private String description; + + @Schema(name = "jobClassName", title = "任务类名称") + @NotBlank(message = "corn表达式不能为空") + @NotNull(message = "corn表达式不能为空") + private String jobClassName; + + @Schema(name = "cronExpression", title = "corn表达式") + @NotBlank(message = "corn表达式不能为空") + @NotNull(message = "corn表达式不能为空") + private String cronExpression; + +} + + + diff --git a/dao/src/main/java/cn/bunny/dao/dto/quartz/schedule/SchedulersDto.java b/dao/src/main/java/cn/bunny/dao/dto/quartz/schedule/SchedulersDto.java new file mode 100644 index 0000000..3c517ad --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/quartz/schedule/SchedulersDto.java @@ -0,0 +1,40 @@ +package cn.bunny.dao.dto.quartz.schedule; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "SchedulersDto对象", title = "Schedulers查询表单", description = "Schedulers查询表单") +public class SchedulersDto { + + @Schema(name = "jobName", title = "任务名称") + private String jobName; + + @Schema(name = "jobGroup", title = "任务分组") + private String jobGroup; + + @Schema(name = "description", title = "任务详情") + private String description; + + @Schema(name = "jobClassName", title = "任务类名称") + @NotNull(message = "corn表达式不能为空") + private String jobClassName; + + @Schema(name = "triggerName", title = "触发器名称") + private String triggerName; + + @Schema(name = "triggerState", title = "triggerState触发器状态") + private String triggerState; + + @Schema(name = "jobMethodName", title = "执行方法") + private String jobMethodName; + +} + diff --git a/dao/src/main/java/cn/bunny/dao/dto/quartz/schedule/SchedulersUpdateDto.java b/dao/src/main/java/cn/bunny/dao/dto/quartz/schedule/SchedulersUpdateDto.java new file mode 100644 index 0000000..2ebb82e --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/quartz/schedule/SchedulersUpdateDto.java @@ -0,0 +1,48 @@ +package cn.bunny.dao.dto.quartz.schedule; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "SchedulersUpdateDto对象", title = "Schedulers更新表单", description = "Schedulers更新表单") +public class SchedulersUpdateDto { + + @Schema(name = "jobName", title = "任务名称") + @NotBlank(message = "任务名称不能为空") + @NotNull(message = "任务名称不能为空") + private String jobName; + + @Schema(name = "jobGroup", title = "任务分组") + @NotBlank(message = "任务分组不能为空") + @NotNull(message = "任务分组不能为空") + private String jobGroup; + + @Schema(name = "description", title = "任务详情") + @NotBlank(message = "任务详情不能为空") + @NotNull(message = "任务详情不能为空") + private String description; + + @Schema(name = "jobClassName", title = "任务类名称") + @NotBlank(message = "corn表达式不能为空") + @NotNull(message = "corn表达式不能为空") + private String jobClassName; + + @Schema(name = "cronExpression", title = "corn表达式") + @NotBlank(message = "corn表达式不能为空") + @NotNull(message = "corn表达式不能为空") + private String cronExpression; + + @Schema(name = "jobMethodName", title = "执行方法") + @NotBlank(message = "执行方法不能为空") + @NotNull(message = "执行方法不能为空") + private String jobMethodName; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/configuration/WebConfigurationDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/configuration/WebConfigurationDto.java new file mode 100644 index 0000000..84e2f70 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/configuration/WebConfigurationDto.java @@ -0,0 +1,132 @@ +package cn.bunny.dao.dto.system.configuration; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +@Getter +@Setter +@Accessors(chain = true) +@Schema(name = "WebConfiguration对象", title = "前端配置选项", description = "前端配置选项") +public class WebConfigurationDto { + + @Schema(name = "Version", description = "应用程序的版本") + @NotBlank(message = "应用程序的版本不能为空") + @NotNull(message = "应用程序的版本不能为空") + private String version; + + @Schema(name = "Title", description = "应用程序的标题") + @NotBlank(message = "应用程序的标题不能为空") + @NotNull(message = "应用程序的标题不能为空") + private String title; + + @Schema(name = "Copyright", description = "版权信息") + @NotBlank(message = "版权信息不能为空") + @NotNull(message = "版权信息不能为空") + private String copyright; + + @Schema(name = "FixedHeader", description = "头部是否固定") + @NotNull(message = "头部是否固定不能为空") + private boolean fixedHeader; + + @Schema(name = "HiddenSideBar", description = "侧边栏是否隐藏") + @NotNull(message = "侧边栏是否隐藏不能为空") + private boolean hiddenSideBar; + + @Schema(name = "MultiTagsCache", description = "是否缓存多个标签") + @NotNull(message = "是否缓存多个标签不能为空") + private boolean multiTagsCache; + + @Schema(name = "KeepAlive", description = "是否持久化") + @NotNull(message = "持久化不能为空") + private boolean keepAlive; + + @Schema(name = "Locale", description = "语言类型") + @NotBlank(message = "语言类型不能为空") + @NotNull(message = "语言类型不能为空") + private String locale; + + @Schema(name = "Layout", description = "应用程序的布局") + @NotBlank(message = "应用程序的布局不能为空") + @NotNull(message = "应用程序的布局不能为空") + private String layout; + + @Schema(name = "Theme", description = "应用程序的主题") + @NotBlank(message = "管理者不能为空") + @NotNull(message = "管理者不能为空") + private String theme; + + @Schema(name = "DarkMode", description = "是否启用深色模式") + @NotNull(message = "darkMode不能为空") + private boolean darkMode; + + @Schema(name = "OverallStyle", description = "应用程序的整体样式") + @NotBlank(message = "整体样式不能为空") + @NotNull(message = "整体样式不能为空") + private String overallStyle; + + @Schema(name = "Grey", description = "是否启用灰色模式") + @NotNull(message = "是否启用灰色模式不能为空") + private boolean grey; + + @Schema(name = "Weak", description = "色弱模式") + @NotNull(message = "色弱模式不能为空") + private boolean weak; + + @Schema(name = "HideTabs", description = "是否隐藏选项卡") + @NotNull(message = "是否隐藏选项卡不能为空") + private boolean hideTabs; + + @Schema(name = "HideFooter", description = "是否隐藏页脚") + @NotNull(message = "是否隐藏页脚不能为空") + private boolean hideFooter; + + @Schema(name = "Stretch", description = "是否拉伸显示") + @NotNull(message = "是否拉伸不能为空") + private boolean stretch; + + @Schema(name = "SidebarStatus", description = "侧边栏的状态") + @NotNull(message = "侧边栏的状态不能为空") + private boolean sidebarStatus; + + @Schema(name = "EpThemeColor", description = "主题颜色") + @NotNull(message = "主题颜色不能为空") + private String epThemeColor; + + @Schema(name = "ShowLogo", description = "是否显示logo") + @NotNull(message = "是否显示logo不能为空") + private boolean showLogo; + + @Schema(name = "ShowModel", description = "要显示的模型") + @NotBlank(message = "showModel不能为空") + @NotNull(message = "showModel不能为空") + private String showModel; + + @Schema(name = "MenuArrowIconNoTransition", description = "菜单箭头图标是否没有过渡效果") + @NotNull(message = "过渡效果不能为空") + private boolean menuArrowIconNoTransition; + + @Schema(name = "CachingAsyncRoutes", description = "是否缓存异步路由") + @NotNull(message = "缓存异步路由不能为空") + private boolean cachingAsyncRoutes; + + @Schema(name = "TooltipEffect", description = "工具提示的效果") + @NotBlank(message = "工具提示不能为空") + @NotNull(message = "工具提示不能为空") + private String tooltipEffect; + + @Schema(name = "ResponsiveStorageNameSpace", description = "响应式存储的命名空间") + @NotBlank(message = "响应式存储的命名空间不能为空") + @NotNull(message = "响应式存储的命名空间不能为空") + private String responsiveStorageNameSpace; + + @Schema(name = "MenuSearchHistory", description = "菜单搜索历史") + @NotNull(message = "菜单搜索历史不能为空") + @Min(value = 1, message = "菜单搜索历史必须大于等于1") + private int menuSearchHistory; + +} diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/configuration/category/CategoryAddDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/configuration/category/CategoryAddDto.java new file mode 100644 index 0000000..ac1b537 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/configuration/category/CategoryAddDto.java @@ -0,0 +1,30 @@ +package cn.bunny.dao.dto.system.configuration.category; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "CategoryAddDto对象", title = "分类信息添加", description = "分类信息添加") +public class CategoryAddDto { + + @Schema(name = "userId", title = "绑定的用户id") + private Long userId; + + @Schema(name = "categoryName", title = "分类名称") + @NotNull(message = "分类名称不能为空") + @NotBlank(message = "分类名称不能为空") + private String categoryName; + + @Schema(name = "isBuiltin", title = "是否内置字段") + @NotNull(message = "内置字段不能为空") + private Boolean isBuiltin; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/configuration/category/CategoryDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/configuration/category/CategoryDto.java new file mode 100644 index 0000000..58722e7 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/configuration/category/CategoryDto.java @@ -0,0 +1,25 @@ +package cn.bunny.dao.dto.system.configuration.category; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "CategoryDto对象", title = "分类信息查询", description = "分类信息查询") +public class CategoryDto { + + @Schema(name = "userId", title = "绑定的用户id") + private Long userId; + + @Schema(name = "categoryName", title = "分类名称") + private String categoryName; + + @Schema(name = "isBuiltin", title = "是否内置字段") + private Boolean isBuiltin; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/configuration/category/CategoryUpdateDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/configuration/category/CategoryUpdateDto.java new file mode 100644 index 0000000..2122481 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/configuration/category/CategoryUpdateDto.java @@ -0,0 +1,34 @@ +package cn.bunny.dao.dto.system.configuration.category; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "CategoryUpdateDto对象", title = "分类信息添加", description = "分类信息添加") +public class CategoryUpdateDto { + + @Schema(name = "id", title = "主键") + @NotNull(message = "id不能为空") + private Long id; + + @Schema(name = "userId", title = "绑定的用户id") + private Long userId; + + @Schema(name = "categoryName", title = "分类名称") + @NotNull(message = "分类名称不能为空") + @NotBlank(message = "分类名称不能为空") + private String categoryName; + + @Schema(name = "isBuiltin", title = "是否内置字段") + @NotNull(message = "内置字段不能为空") + private Boolean isBuiltin; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/dept/DeptAddDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/dept/DeptAddDto.java new file mode 100644 index 0000000..fc38671 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/dept/DeptAddDto.java @@ -0,0 +1,38 @@ +package cn.bunny.dao.dto.system.dept; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "DeptAddDto对象", title = "部门", description = "部门管理") +public class DeptAddDto { + + @Schema(name = "parentId", title = "父级id") + private String parentId; + + @Schema(name = "managerId", title = "管理者") + @NotNull(message = "管理者不能为空") + @NotEmpty(message = "管理者不能为空") + private List manager; + + @Schema(name = "deptName", title = "部门名称") + @NotBlank(message = "部门名称不能为空") + @NotNull(message = "部门名称不能为空") + private String deptName; + + @Schema(name = "summary", title = "部门简介") + private String summary; + +} + diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/dept/DeptDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/dept/DeptDto.java new file mode 100644 index 0000000..809421c --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/dept/DeptDto.java @@ -0,0 +1,23 @@ +package cn.bunny.dao.dto.system.dept; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "DeptDto对象", title = "部门", description = "部门管理") +public class DeptDto { + + @Schema(name = "deptName", title = "部门名称") + private String deptName; + + @Schema(name = "summary", title = "部门简介") + private String summary; + +} + diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/dept/DeptUpdateDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/dept/DeptUpdateDto.java new file mode 100644 index 0000000..ad3de2e --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/dept/DeptUpdateDto.java @@ -0,0 +1,42 @@ +package cn.bunny.dao.dto.system.dept; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "DeptUpdateDto对象", title = "部门", description = "部门管理") +public class DeptUpdateDto { + + @Schema(name = "id", title = "主键") + @NotNull(message = "id不能为空") + private Long id; + + @Schema(name = "parentId", title = "父级id") + private Long parentId; + + @Schema(name = "managerId", title = "管理者") + @NotNull(message = "管理者不能为空") + @NotEmpty(message = "管理者不能为空") + private List manager; + + @Schema(name = "deptName", title = "部门名称") + @NotBlank(message = "部门名称不能为空") + @NotNull(message = "部门名称不能为空") + private String deptName; + + @Schema(name = "summary", title = "部门简介") + private String summary; + +} + diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/email/template/EmailTemplateAddDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/email/template/EmailTemplateAddDto.java new file mode 100644 index 0000000..1c7ba6a --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/email/template/EmailTemplateAddDto.java @@ -0,0 +1,39 @@ +package cn.bunny.dao.dto.system.email.template; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "EmailTemplateAddDto对象", title = "邮箱模板请求内容", description = "邮箱模板请求内容") +public class EmailTemplateAddDto { + + @Schema(name = "templateName", title = "模板名称") + @NotBlank(message = "模板名称不能为空") + @NotNull(message = "模板名称不能为空") + private String templateName; + + @Schema(name = "emailUser", title = "配置邮件用户") + @NotNull(message = "配置邮件用户不能为空") + private Long emailUser; + + @Schema(name = "subject", title = "主题") + @NotBlank(message = "主题不能为空") + @NotNull(message = "主题不能为空") + private String subject; + + @Schema(name = "body", title = "邮件内容") + @NotBlank(message = "邮件内容不能为空") + @NotNull(message = "邮件内容不能为空") + private String body; + + @Schema(name = "type", title = "邮件类型") + private String type; +} diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/email/template/EmailTemplateDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/email/template/EmailTemplateDto.java new file mode 100644 index 0000000..0ae196a --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/email/template/EmailTemplateDto.java @@ -0,0 +1,28 @@ +package cn.bunny.dao.dto.system.email.template; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "EmailTemplateDto", title = "邮箱模板请求内容", description = "邮箱模板请求内容") +public class EmailTemplateDto { + + @Schema(name = "templateName", title = "模板名称") + private String templateName; + + @Schema(name = "subject", title = "主题") + private String subject; + + @Schema(name = "body", title = "邮件内容") + private String body; + + @Schema(name = "type", title = "邮件类型") + private String type; +} + diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/email/template/EmailTemplateUpdateDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/email/template/EmailTemplateUpdateDto.java new file mode 100644 index 0000000..0985fd9 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/email/template/EmailTemplateUpdateDto.java @@ -0,0 +1,43 @@ +package cn.bunny.dao.dto.system.email.template; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "EmailTemplateUpdateDto对象", title = "邮箱模板请求内容", description = "邮箱模板请求内容") +public class EmailTemplateUpdateDto { + + @Schema(name = "id", title = "主键") + @NotNull(message = "id不能为空") + private Long id; + + @Schema(name = "templateName", title = "模板名称") + @NotBlank(message = "模板名称不能为空") + @NotNull(message = "模板名称不能为空") + private String templateName; + + @Schema(name = "emailUser", title = "配置邮件用户") + @NotNull(message = "配置邮件用户不能为空") + private Long emailUser; + + @Schema(name = "subject", title = "主题") + @NotBlank(message = "主题不能为空") + @NotNull(message = "主题不能为空") + private String subject; + + @Schema(name = "body", title = "邮件内容") + @NotBlank(message = "邮件内容不能为空") + @NotNull(message = "邮件内容不能为空") + private String body; + + @Schema(name = "type", title = "邮件类型") + private String type; +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/email/user/EmailUserUpdateStatusDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/email/user/EmailUserUpdateStatusDto.java new file mode 100644 index 0000000..c5b2cd9 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/email/user/EmailUserUpdateStatusDto.java @@ -0,0 +1,24 @@ +package cn.bunny.dao.dto.system.email.user; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "EmailUserUpdateStatusDto对象", title = "邮箱用户更新状态", description = "邮箱用户更新状态表单") +public class EmailUserUpdateStatusDto { + + @Schema(name = "id", title = "主键") + @NotNull(message = "id不能为空") + private Long id; + + @Schema(name = "isDefault", title = "是否为默认邮件") + private Boolean isDefault; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/email/user/EmailUsersAddDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/email/user/EmailUsersAddDto.java new file mode 100644 index 0000000..e555967 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/email/user/EmailUsersAddDto.java @@ -0,0 +1,43 @@ +package cn.bunny.dao.dto.system.email.user; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "EmailUsersAddDto对象", title = "邮箱用户发送配置", description = "邮箱用户发送配置管理") +public class EmailUsersAddDto { + + @Schema(name = "email", title = "邮箱") + @NotBlank(message = "邮箱不能为空") + @NotNull(message = "邮箱不能为空") + private String email; + + @Schema(name = "password", title = "密码") + @NotBlank(message = "密码不能为空") + @NotNull(message = "密码不能为空") + private String password; + + @Schema(name = "host", title = "Host地址") + @NotBlank(message = "Host地址不能为空") + @NotNull(message = "Host地址不能为空") + private String host; + + @Schema(name = "port", title = "端口号") + @NotNull(message = "端口号不能为空") + private Integer port; + + @Schema(name = "smtpAgreement", title = "邮箱协议") + private String smtpAgreement; + + @Schema(name = "isDefault", title = "是否为默认邮件") + private Boolean isDefault = false; + +} diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/email/user/EmailUsersDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/email/user/EmailUsersDto.java new file mode 100644 index 0000000..db194e8 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/email/user/EmailUsersDto.java @@ -0,0 +1,30 @@ +package cn.bunny.dao.dto.system.email.user; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "EmailUsersDto对象", title = "邮箱用户发送配置", description = "邮箱用户发送配置管理") +public class EmailUsersDto { + + @Schema(name = "email", title = "邮箱") + private String email; + + @Schema(name = "host", title = "Host地址") + private String host; + + @Schema(name = "port", title = "端口号") + private Integer port; + + @Schema(name = "smtpAgreement", title = "邮箱协议") + private String smtpAgreement; + +} + + diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/email/user/EmailUsersUpdateDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/email/user/EmailUsersUpdateDto.java new file mode 100644 index 0000000..771e7be --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/email/user/EmailUsersUpdateDto.java @@ -0,0 +1,49 @@ +package cn.bunny.dao.dto.system.email.user; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "EmailUsersUpdateDto对象", title = "邮箱用户发送配置", description = "邮箱用户发送配置管理") +public class EmailUsersUpdateDto { + + @Schema(name = "id", title = "主键") + @NotNull(message = "id不能为空") + private Long id; + + @Schema(name = "email", title = "邮箱") + @NotBlank(message = "邮箱不能为空") + @NotNull(message = "邮箱不能为空") + private String email; + + @Schema(name = "password", title = "密码") + @NotBlank(message = "密码不能为空") + @NotNull(message = "密码不能为空") + private String password; + + @Schema(name = "host", title = "Host地址") + @NotBlank(message = "Host地址不能为空") + @NotNull(message = "Host地址不能为空") + private String host; + + @Schema(name = "port", title = "端口号") + @NotNull(message = "端口号不能为空") + private Integer port; + + @Schema(name = "smtpAgreement", title = "邮箱协议") + private String smtpAgreement; + + @Schema(name = "isDefault", title = "是否为默认邮件") + private Boolean isDefault; + +} + + diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/files/FileUploadDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/files/FileUploadDto.java new file mode 100644 index 0000000..254655e --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/files/FileUploadDto.java @@ -0,0 +1,28 @@ +package cn.bunny.dao.dto.system.files; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.web.multipart.MultipartFile; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "FileUploadDto对象", title = "文件上传", description = "文件上传管理") +public class FileUploadDto { + + @Schema(name = "file", title = "文件") + @NotNull(message = "文件不能为空") + private MultipartFile file; + + @Schema(name = "type", title = "文件类型") + @NotBlank(message = "文件类型不能为空") + @NotNull(message = "文件类型不能为空") + private String type; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/files/FilesAddDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/files/FilesAddDto.java new file mode 100644 index 0000000..faf3393 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/files/FilesAddDto.java @@ -0,0 +1,37 @@ +package cn.bunny.dao.dto.system.files; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "FilesAddDto对象", title = "文件", description = "文件管理") +public class FilesAddDto { + + @Schema(name = "filepath", title = "文件在服务器上的存储路径") + @NotBlank(message = "存储路径不能为空") + @NotNull(message = "存储路径不能为空") + private String filepath; + + @Schema(name = "downloadCount", title = "下载数量") + @Min(value = 0L, message = "最小值为0") + private Integer downloadCount = 0; + + @Schema(name = "files", title = "文件") + @NotEmpty(message = "文件不能为空") + @NotNull(message = "文件不能为空") + private List files; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/files/FilesDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/files/FilesDto.java new file mode 100644 index 0000000..d9bd98e --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/files/FilesDto.java @@ -0,0 +1,28 @@ +package cn.bunny.dao.dto.system.files; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "FilesDto对象", title = "文件", description = "文件管理") +public class FilesDto { + + @Schema(name = "filename", title = "文件的名称") + private String filename; + + @Schema(name = "filepath", title = "文件在服务器上的存储路径") + private String filepath; + + @Schema(name = "fileType", title = "文件的MIME类型") + private String fileType; + + @Schema(name = "downloadCount", title = "下载数量") + private Integer downloadCount; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/files/FilesUpdateDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/files/FilesUpdateDto.java new file mode 100644 index 0000000..a703882 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/files/FilesUpdateDto.java @@ -0,0 +1,41 @@ +package cn.bunny.dao.dto.system.files; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.web.multipart.MultipartFile; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "FilesUpdateDto对象", title = "文件", description = "文件管理") +public class FilesUpdateDto { + + @Schema(name = "id", title = "主键") + @NotNull(message = "id不能为空") + private Long id; + + @Schema(name = "filename", title = "文件的名称") + @NotBlank(message = "文件的名称不能为空") + @NotNull(message = "文件的名称不能为空") + private String filename; + + @Schema(name = "fileType", title = "文件的MIME类型") + @NotBlank(message = "文件类型不能为空") + @NotNull(message = "文件类型不能为空") + private String fileType; + + @Schema(name = "downloadCount", title = "下载数量") + @Min(value = 0L, message = "最小值为0") + private Integer downloadCount; + + @Schema(name = "file", title = "文件") + private MultipartFile files; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/menuIcon/MenuIconAddDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/menuIcon/MenuIconAddDto.java new file mode 100644 index 0000000..5522de9 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/menuIcon/MenuIconAddDto.java @@ -0,0 +1,29 @@ +package cn.bunny.dao.dto.system.menuIcon; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "MenuIconAddDto对象", title = "系统菜单图标", description = "系统菜单图标管理") +public class MenuIconAddDto { + + @Schema(name = "iconCode", title = "icon类名") + @NotBlank(message = "iconCode不能为空") + @NotNull(message = "iconCode不能为空") + private String iconCode; + + @Schema(name = "iconName", title = "icon 名称") + @NotBlank(message = "icon 名称不能为空") + @NotNull(message = "icon 名称不能为空") + private String iconName; + +} + diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/menuIcon/MenuIconDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/menuIcon/MenuIconDto.java new file mode 100644 index 0000000..e93510e --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/menuIcon/MenuIconDto.java @@ -0,0 +1,23 @@ +package cn.bunny.dao.dto.system.menuIcon; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "MenuIconDto对象", title = "系统菜单图标", description = "系统菜单图标管理") +public class MenuIconDto { + + @Schema(name = "iconCode", title = "icon类名") + private String iconCode; + + @Schema(name = "iconName", title = "icon 名称") + private String iconName; + +} + diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/menuIcon/MenuIconUpdateDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/menuIcon/MenuIconUpdateDto.java new file mode 100644 index 0000000..6839266 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/menuIcon/MenuIconUpdateDto.java @@ -0,0 +1,32 @@ +package cn.bunny.dao.dto.system.menuIcon; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "MenuIconUpdateDto对象", title = "系统菜单图标", description = "系统菜单图标管理") +public class MenuIconUpdateDto { + + @Schema(name = "id", title = "主键") + @NotNull(message = "id不能为空") + private Long id; + + @Schema(name = "iconCode", title = "icon类名") + @NotBlank(message = "iconCode不能为空") + @NotNull(message = "iconCode不能为空") + private String iconCode; + + @Schema(name = "iconName", title = "icon 名称") + @NotBlank(message = "icon 名称不能为空") + @NotNull(message = "icon 名称不能为空") + private String iconName; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/message/MessageAddDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/message/MessageAddDto.java new file mode 100644 index 0000000..7dc7e0b --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/message/MessageAddDto.java @@ -0,0 +1,62 @@ +package cn.bunny.dao.dto.system.message; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "MessageAddDto对象", title = "添加系统消息", description = "添加系统消息") +public class MessageAddDto { + + @Schema(name = "title", title = "消息标题") + @NotNull(message = "消息标题 不能为空") + @NotBlank(message = "消息标题 不能为空") + private String title; + + @Schema(name = "receivedUserIds", title = "接收人用户ID") + private List receivedUserIds; + + @Schema(name = "sendUserId", title = "发送人用户ID") + private Long sendUserId; + + @Schema(name = "messageTypeId", title = "消息类型") + @NotNull(message = "消息类型 不能为空") + private Long messageTypeId; + + @Schema(name = "cover", title = "封面") + private String cover; + + @Schema(name = "summary", title = "消息简介") + @NotBlank(message = "消息简介 不能为空") + @NotNull(message = "消息简介 不能为空") + private String summary; + + @Schema(name = "content", title = "消息内容") + @NotBlank(message = "消息内容 不能为空") + @NotNull(message = "消息内容 不能为空") + private String content; + + @Schema(name = "editorType", title = "编辑器类型") + @NotBlank(message = "编辑器类型 不能为空") + @NotNull(message = "编辑器类型 不能为空") + private String editorType; + + @Schema(name = "status", title = "0:未读 1:已读") + private Boolean status = false; + + @Schema(name = "level", title = "消息等级") + private String level; + + @Schema(name = "extra", title = "消息等级详情") + private String extra; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/message/MessageDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/message/MessageDto.java new file mode 100644 index 0000000..68f46b0 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/message/MessageDto.java @@ -0,0 +1,34 @@ +package cn.bunny.dao.dto.system.message; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "MessageDto对象", title = "消息查询", description = "消息查询") +public class MessageDto { + + @Schema(name = "title", title = "消息标题") + private String title; + + @Schema(name = "sendNickname", title = "发送人用户昵称") + private String sendNickname; + + @Schema(name = "messageType", title = "消息类型") + private String messageType; + + @Schema(name = "level", title = "消息等级") + private String level; + + @Schema(name = "extra", title = "消息等级详情") + private String extra; + + @Schema(name = "editorType", title = "编辑器类型") + private String editorType; + +} diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/message/MessageReceivedDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/message/MessageReceivedDto.java new file mode 100644 index 0000000..52d5069 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/message/MessageReceivedDto.java @@ -0,0 +1,39 @@ +package cn.bunny.dao.dto.system.message; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "MessageReceivedDto对象", title = "用户消息查询", description = "用户消息查询") +public class MessageReceivedDto { + + @Schema(name = "title", title = "消息标题") + private String title; + + @Schema(name = "sendNickname", title = "发送人用户昵称") + private String sendNickname; + + @Schema(name = "messageType", title = "消息类型") + private String messageType; + + @Schema(name = "level", title = "消息等级") + private String level; + + @Schema(name = "extra", title = "消息等级详情") + private String extra; + + @Schema(name = "status", title = "0:未读 1:已读") + private Boolean status; + + @Schema(name = "editorType", title = "编辑器类型") + private String editorType; + +} + + diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/message/MessageReceivedUpdateDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/message/MessageReceivedUpdateDto.java new file mode 100644 index 0000000..24a9474 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/message/MessageReceivedUpdateDto.java @@ -0,0 +1,24 @@ +package cn.bunny.dao.dto.system.message; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "MessageReceivedDto对象", title = "用户消息查询", description = "用户消息查询") +public class MessageReceivedUpdateDto { + + @Schema(name = "ids", title = "消息接受id") + private List ids; + + @Schema(name = "status", title = "0:未读 1:已读") + private Boolean status; + +} diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/message/MessageTypeAddDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/message/MessageTypeAddDto.java new file mode 100644 index 0000000..ce144d0 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/message/MessageTypeAddDto.java @@ -0,0 +1,34 @@ +package cn.bunny.dao.dto.system.message; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "MessageTypeAddDto对象", title = "系统消息类型", description = "系统消息类型") +public class MessageTypeAddDto { + + @Schema(name = "messageName", title = "消息名称") + @NotBlank(message = "消息名称 不能为空") + @NotNull(message = "消息名称 不能为空") + private String messageName; + + @Schema(name = "messageType", title = "sys:系统消息,user用户消息") + @NotBlank(message = "消息类型 不能为空") + @NotNull(message = "消息类型 不能为空") + private String messageType; + + @Schema(name = "summary", title = "消息备注") + private String summary; + + @Schema(name = "status", title = "消息类型") + private Boolean status = true; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/message/MessageTypeDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/message/MessageTypeDto.java new file mode 100644 index 0000000..806728e --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/message/MessageTypeDto.java @@ -0,0 +1,30 @@ +package cn.bunny.dao.dto.system.message; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "MessageType对象", title = "系统消息类型", description = "系统消息类型") +public class MessageTypeDto { + + @Schema(name = "status", title = "1:启用 0:禁用") + private Boolean status; + + @Schema(name = "messageName", title = "消息名称") + private String messageName; + + @Schema(name = "messageType", title = "sys:系统消息,user用户消息") + private String messageType; + + @Schema(name = "summary", title = "消息备注") + private String summary; + +} + + diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/message/MessageTypeUpdateDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/message/MessageTypeUpdateDto.java new file mode 100644 index 0000000..974a52d --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/message/MessageTypeUpdateDto.java @@ -0,0 +1,33 @@ +package cn.bunny.dao.dto.system.message; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "MessageTypeUpdateDto对象", title = "系统消息类型", description = "系统消息类型") +public class MessageTypeUpdateDto { + + @Schema(name = "id", title = "主键") + @NotNull(message = "id不能为空") + private Long id; + + @Schema(name = "status", title = "1:启用 0:禁用") + private Boolean status; + + @Schema(name = "messageName", title = "消息名称") + private String messageName; + + @Schema(name = "messageType", title = "sys:系统消息,user用户消息") + private String messageType; + + @Schema(name = "summary", title = "消息备注") + private String summary; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/message/MessageUpdateDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/message/MessageUpdateDto.java new file mode 100644 index 0000000..31aa445 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/message/MessageUpdateDto.java @@ -0,0 +1,65 @@ +package cn.bunny.dao.dto.system.message; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "MessageUpdateDto对象", title = "系统消息", description = "系统消息") +public class MessageUpdateDto { + + @Schema(name = "id", title = "主键") + @NotNull(message = "id不能为空") + private Long id; + + @Schema(name = "title", title = "消息标题") + @NotNull(message = "消息标题 不能为空") + @NotBlank(message = "消息标题 不能为空") + private String title; + + @Schema(name = "receivedUserIds", title = "接收人用户ID列表") + private List receivedUserIds; + + @Schema(name = "sendUserId", title = "发送人用户ID") + @NotNull(message = "发送人用户ID 不能为空") + private Long sendUserId; + + @Schema(name = "messageTypeId", title = "消息类型") + @NotNull(message = "消息类型 不能为空") + private Long messageTypeId; + + @Schema(name = "cover", title = "封面") + private String cover; + + @Schema(name = "summary", title = "消息简介") + @NotBlank(message = "消息简介 不能为空") + @NotNull(message = "消息简介 不能为空") + private String summary; + + @Schema(name = "content", title = "消息内容") + @NotBlank(message = "消息内容 不能为空") + @NotNull(message = "消息内容 不能为空") + private String content; + + @Schema(name = "editorType", title = "编辑器类型") + @NotBlank(message = "编辑器类型 不能为空") + @NotNull(message = "编辑器类型 不能为空") + private String editorType; + + @Schema(name = "level", title = "消息等级") + private String level; + + @Schema(name = "extra", title = "消息等级详情") + private String extra; + +} + diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/message/MessageUserDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/message/MessageUserDto.java new file mode 100644 index 0000000..eac5747 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/message/MessageUserDto.java @@ -0,0 +1,25 @@ +package cn.bunny.dao.dto.system.message; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "MessageUserDto对象", title = "用户消息查询内容", description = "用户消息查询内容") +public class MessageUserDto { + + @Schema(name = "title", title = "消息标题") + private String title; + + @Schema(name = "messageType", title = "消息类型") + private String messageType; + + @Schema(name = "status", title = "0:未读 1:已读") + private Boolean status; + +} diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/rolePower/AssignPowersToRoleDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/rolePower/AssignPowersToRoleDto.java new file mode 100644 index 0000000..bb5f75f --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/rolePower/AssignPowersToRoleDto.java @@ -0,0 +1,29 @@ +package cn.bunny.dao.dto.system.rolePower; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "AssignPowersToRoleDto对象", title = "为角色分配权限表单", description = "为角色分配权限") +public class AssignPowersToRoleDto { + + @Schema(name = "roleIds", title = "角色id") + @NotNull(message = "角色id不能为空") + private Long roleId; + + @Schema(name = "powerIds", title = "权限id列表") + @NotNull(message = "权限id列表不能为空") + @NotEmpty(message = "权限id列表不能为空") + private List powerIds; + +} diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/rolePower/power/PowerAddDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/rolePower/power/PowerAddDto.java new file mode 100644 index 0000000..bc41978 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/rolePower/power/PowerAddDto.java @@ -0,0 +1,38 @@ +package cn.bunny.dao.dto.system.rolePower.power; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "PowerAddDto对象", title = "权限", description = "权限管理") +public class PowerAddDto { + + @Schema(name = "id", title = "主键") + private Long id; + + @Schema(name = "parentId", title = "父级id") + private Long parentId; + + @Schema(name = "parentId", title = "权限编码") + @NotBlank(message = "权限编码 不能为空") + @NotNull(message = "权限编码 不能为空") + private String powerCode; + + @Schema(name = "powerName", title = "权限名称") + @NotBlank(message = "权限名称 不能为空") + @NotNull(message = "权限名称 不能为空") + private String powerName; + + @Schema(name = "requestUrl", title = "请求路径") + private String requestUrl; + +} + diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/rolePower/power/PowerDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/rolePower/power/PowerDto.java new file mode 100644 index 0000000..c05d3d4 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/rolePower/power/PowerDto.java @@ -0,0 +1,26 @@ +package cn.bunny.dao.dto.system.rolePower.power; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "PowerDto对象", title = "权限", description = "权限管理") +public class PowerDto { + + @Schema(name = "parentId", title = "权限编码") + private String powerCode; + + @Schema(name = "powerName", title = "权限名称") + private String powerName; + + @Schema(name = "requestUrl", title = "请求路径") + private String requestUrl; + +} + diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/rolePower/power/PowerUpdateBatchByParentIdDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/rolePower/power/PowerUpdateBatchByParentIdDto.java new file mode 100644 index 0000000..ff0603b --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/rolePower/power/PowerUpdateBatchByParentIdDto.java @@ -0,0 +1,29 @@ +package cn.bunny.dao.dto.system.rolePower.power; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "PowerUpdateBatchByParentIdDto对象", title = "批量修改权限", description = "批量修改权限表单") +public class PowerUpdateBatchByParentIdDto { + + @Schema(name = "id", title = "主键") + @NotNull(message = "id不能为空") + @NotEmpty(message = "id不能为空") + private List ids; + + @Schema(name = "parentId", title = "父级id") + @NotNull(message = "父级不能为空") + private Long parentId; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/rolePower/power/PowerUpdateDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/rolePower/power/PowerUpdateDto.java new file mode 100644 index 0000000..1d79e32 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/rolePower/power/PowerUpdateDto.java @@ -0,0 +1,38 @@ +package cn.bunny.dao.dto.system.rolePower.power; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "PowerUpdateDto对象", title = "权限", description = "权限管理") +public class PowerUpdateDto { + + @Schema(name = "id", title = "主键") + @NotNull(message = "id不能为空") + private Long id; + + @Schema(name = "parentId", title = "父级id") + private Long parentId; + + @Schema(name = "parentId", title = "权限编码") + @NotBlank(message = "权限编码 不能为空") + @NotNull(message = "权限编码 不能为空") + private String powerCode; + + @Schema(name = "powerName", title = "权限名称") + @NotBlank(message = "权限名称 不能为空") + @NotNull(message = "权限名称 不能为空") + private String powerName; + + @Schema(name = "requestUrl", title = "请求路径") + private String requestUrl; + +} diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/rolePower/role/RoleAddDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/rolePower/role/RoleAddDto.java new file mode 100644 index 0000000..9587cfb --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/rolePower/role/RoleAddDto.java @@ -0,0 +1,30 @@ +package cn.bunny.dao.dto.system.rolePower.role; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "RoleAddDto对象", title = "角色", description = "角色管理") +public class RoleAddDto { + + @Schema(name = "roleCode", title = "角色代码") + @NotBlank(message = "roleCode 不能为空") + @NotNull(message = "roleCode 不能为空") + private String roleCode; + + @Schema(name = "description", title = "描述") + @NotBlank(message = "description 不能为空") + @NotNull(message = "description 不能为空") + private String description; + +} + + diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/rolePower/role/RoleDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/rolePower/role/RoleDto.java new file mode 100644 index 0000000..fd90f49 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/rolePower/role/RoleDto.java @@ -0,0 +1,23 @@ +package cn.bunny.dao.dto.system.rolePower.role; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "RoleDto对象", title = "角色", description = "角色管理") +public class RoleDto { + + @Schema(name = "roleCode", title = "角色代码") + private String roleCode; + + @Schema(name = "description", title = "描述") + private String description; + +} + diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/rolePower/role/RoleUpdateDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/rolePower/role/RoleUpdateDto.java new file mode 100644 index 0000000..0724733 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/rolePower/role/RoleUpdateDto.java @@ -0,0 +1,32 @@ +package cn.bunny.dao.dto.system.rolePower.role; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "RoleUpdateDto对象", title = "角色", description = "角色管理") +public class RoleUpdateDto { + + @Schema(name = "id", title = "主键") + @NotNull(message = "id不能为空") + private Long id; + + @Schema(name = "roleCode", title = "角色代码") + @NotBlank(message = "roleCode 不能为空") + @NotNull(message = "roleCode 不能为空") + private String roleCode; + + @Schema(name = "description", title = "描述") + @NotBlank(message = "description 不能为空") + @NotNull(message = "description 不能为空") + private String description; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/router/AssignRolesToRoutersDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/router/AssignRolesToRoutersDto.java new file mode 100644 index 0000000..8becf99 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/router/AssignRolesToRoutersDto.java @@ -0,0 +1,30 @@ +package cn.bunny.dao.dto.system.router; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "AssignRolesToRoutersDto对象", title = "路由分配角色", description = "路由分配角色") +public class AssignRolesToRoutersDto { + + @Schema(name = "routerId", title = "路由id") + @NotNull(message = "路由id不能为空") + @NotEmpty(message = "路由id不能为空") + private List routerIds; + + @Schema(name = "roleIds", title = "角色id列表") + @NotNull(message = "角色id列表不能为空") + @NotEmpty(message = "角色id列表不能为空") + private List roleIds; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/router/RouterAddDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/router/RouterAddDto.java new file mode 100644 index 0000000..d144c76 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/router/RouterAddDto.java @@ -0,0 +1,62 @@ +package cn.bunny.dao.dto.system.router; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "RouterManageDto对象", title = "路由添加表单", description = "路由添加表单") +public class RouterAddDto { + + @Schema(name = "menuType", title = "菜单类型") + @NotNull(message = "菜单类型不能为空") + private Integer menuType; + + @Schema(name = "parentId", title = "父级id") + private Long parentId; + + @Schema(name = "title", title = "路由title") + @NotNull(message = "菜单名称不能为空") + @NotBlank(message = "菜单名称不能为空") + private String title; + + @Schema(name = "routeName", title = "路由名称") + @JsonProperty("name") + @NotBlank(message = "路由名称不能为空") + @NotNull(message = "路由名称不能为空") + private String routeName; + + @Schema(name = "path", title = "在项目中路径") + @NotBlank(message = "路由路径不能为空") + @NotNull(message = "路由路径不能为空") + private String path; + + @Schema(name = "component", title = "组件位置") + private String component; + + @Schema(name = "routerRank", title = "等级") + @JsonProperty("rank") + @NotNull(message = "菜单排序不能为空") + @Max(value = 999, message = "不能超过999") + private Integer routerRank = 99; + + @Schema(name = "icon", title = "图标") + private String icon; + + @Schema(name = "frameSrc", title = "frame路径") + private String frameSrc; + + @Schema(name = "visible", title = "是否显示") + private Boolean visible = false; + +} + diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/router/RouterManageDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/router/RouterManageDto.java new file mode 100644 index 0000000..d5ed675 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/router/RouterManageDto.java @@ -0,0 +1,21 @@ +package cn.bunny.dao.dto.system.router; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "RouterManageDto对象", title = "路由查询表单", description = "路由查询表单") +public class RouterManageDto { + + @Schema(name = "title", title = "路由标题") + private String title; + + @Schema(name = "visible", title = "是否显示") + private Boolean visible; +} diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/router/RouterUpdateByIdWithRankDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/router/RouterUpdateByIdWithRankDto.java new file mode 100644 index 0000000..4f74282 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/router/RouterUpdateByIdWithRankDto.java @@ -0,0 +1,26 @@ +package cn.bunny.dao.dto.system.router; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "RouterUpdateByIdWithRankDto对象", title = "根据菜单Id更新菜单排序", description = "根据菜单Id更新菜单排序") +public class RouterUpdateByIdWithRankDto { + + @Schema(name = "id", title = "唯一标识") + @NotNull(message = "id不能为空") + private Long id; + + @Schema(name = "routerRank", title = "等级") + @JsonProperty("rank") + private Integer routerRank; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/router/RouterUpdateDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/router/RouterUpdateDto.java new file mode 100644 index 0000000..e2c9133 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/router/RouterUpdateDto.java @@ -0,0 +1,64 @@ +package cn.bunny.dao.dto.system.router; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "RouterManageDto对象", title = "路由更新表单", description = "路由更新表单") +public class RouterUpdateDto { + + @Schema(name = "id", title = "唯一标识") + @NotNull(message = "id不能为空") + private Long id; + + @Schema(name = "menuType", title = "菜单类型") + @NotNull(message = "菜单类型不能为空") + private Integer menuType; + + @Schema(name = "parentId", title = "父级id") + private Long parentId; + + @Schema(name = "title", title = "路由title") + @NotBlank(message = "菜单名称不能为空") + @NotNull(message = "菜单名称不能为空") + private String title; + + @Schema(name = "routeName", title = "路由名称") + @JsonProperty("name") + @NotBlank(message = "路由名称不能为空") + @NotNull(message = "路由名称不能为空") + private String routeName; + + @Schema(name = "path", title = "在项目中路径") + @NotBlank(message = "路由路径不能为空") + @NotNull(message = "路由路径不能为空") + private String path; + + @Schema(name = "component", title = "组件位置") + private String component; + + @Schema(name = "routerRank", title = "等级") + @JsonProperty("rank") + @Max(value = 999, message = "不能超过999") + private Integer routerRank; + + @Schema(name = "icon", title = "图标") + private String icon; + + @Schema(name = "frameSrc", title = "frame路径") + private String frameSrc; + + @Schema(name = "visible", title = "是否显示") + private Boolean visible; +} + diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/user/AdminUserAddDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/user/AdminUserAddDto.java new file mode 100644 index 0000000..baf15f1 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/user/AdminUserAddDto.java @@ -0,0 +1,59 @@ +package cn.bunny.dao.dto.system.user; + +import cn.bunny.dao.pojo.constant.UserConstant; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "AdminUserAddDto对象", title = "用户", description = "用户管理") +public class AdminUserAddDto { + + @Schema(name = "username", title = "用户名") + @NotBlank(message = "用户名不能为空") + @NotNull(message = "用户名不能为空") + private String username; + + @Schema(name = "nickname", title = "昵称") + @NotBlank(message = "昵称不能为空") + @NotNull(message = "昵称不能为空") + private String nickname; + + @Schema(name = "email", title = "邮箱") + @NotBlank(message = "邮箱不能为空") + @NotNull(message = "邮箱不能为空") + private String email; + + @Schema(name = "phone", title = "手机号") + private String phone; + + @Schema(name = "password", title = "密码") + @NotBlank(message = "密码不能为空") + @NotNull(message = "密码不能为空") + private String password = "123456"; + + @Schema(name = "avatar", title = "头像") + private String avatar; + + @Schema(name = "sex", title = "性别", description = "0:女 1:男") + private Byte sex = 1; + + @Schema(name = "summary", title = "个人描述") + private String summary = UserConstant.PERSON_DESCRIPTION; + + @Schema(name = "deptId", title = "部门") + @NotNull(message = "部门不能为空") + private Long deptId; + + @Schema(name = "status", title = "状态", description = "1:禁用 0:正常") + private Boolean status = false; + +} + diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/user/AdminUserDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/user/AdminUserDto.java new file mode 100644 index 0000000..6f86af9 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/user/AdminUserDto.java @@ -0,0 +1,42 @@ +package cn.bunny.dao.dto.system.user; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "AdminUserAddDto对象", title = "用户", description = "用户管理") +public class AdminUserDto { + + @Schema(name = "username", title = "用户名") + private String username; + + @Schema(name = "nickname", title = "昵称") + private String nickname; + + @Schema(name = "email", title = "邮箱") + private String email; + + @Schema(name = "phone", title = "手机号") + private String phone; + + @Schema(name = "sex", title = "性别", description = "0:女 1:男") + private Byte sex; + + @Schema(name = "summary", title = "个人描述") + private String summary; + + @Schema(name = "status", title = "状态", description = "1:禁用 0:正常") + private Boolean status; + + @Schema(name = "deptId", title = "部门") + private List deptIds; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/user/AdminUserUpdateByLocalUserDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/user/AdminUserUpdateByLocalUserDto.java new file mode 100644 index 0000000..09349bc --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/user/AdminUserUpdateByLocalUserDto.java @@ -0,0 +1,41 @@ +package cn.bunny.dao.dto.system.user; + +import cn.bunny.dao.pojo.constant.UserConstant; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "AdminUserUpdateByLocalUserDto对象", title = "更新本地用户信息", description = "更新本地用户信息") +public class AdminUserUpdateByLocalUserDto { + + @Schema(name = "nickname", title = "昵称") + @NotBlank(message = "昵称不能为空") + @NotNull(message = "昵称不能为空") + private String nickname; + + @Schema(name = "email", title = "邮箱") + @NotBlank(message = "邮箱不能为空") + @NotNull(message = "邮箱不能为空") + private String email; + + @Schema(name = "avatar", title = "头像") + private String avatar = UserConstant.USER_AVATAR; + + @Schema(name = "phone", title = "手机号") + private String phone; + + @Schema(name = "sex", title = "性别", description = "0:女 1:男") + private Byte sex = 1; + + @Schema(name = "summary", title = "个人描述") + private String summary = UserConstant.PERSON_DESCRIPTION; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/user/AdminUserUpdateDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/user/AdminUserUpdateDto.java new file mode 100644 index 0000000..f749ba4 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/user/AdminUserUpdateDto.java @@ -0,0 +1,54 @@ +package cn.bunny.dao.dto.system.user; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "AdminUserUpdateDto对象", title = "用户", description = "用户管理") +public class AdminUserUpdateDto { + + @Schema(name = "id", title = "主键") + @NotNull(message = "id不能为空") + private Long id; + + @Schema(name = "username", title = "用户名") + @NotBlank(message = "用户名不能为空") + @NotNull(message = "用户名不能为空") + private String username; + + @Schema(name = "nickname", title = "昵称") + @NotBlank(message = "昵称不能为空") + @NotNull(message = "昵称不能为空") + private String nickname; + + @Schema(name = "email", title = "邮箱") + @NotBlank(message = "邮箱不能为空") + @NotNull(message = "邮箱不能为空") + private String email; + + @Schema(name = "phone", title = "手机号") + private String phone; + + @Schema(name = "sex", title = "性别", description = "0:女 1:男") + private Byte sex; + + @Schema(name = "summary", title = "个人描述") + private String summary; + + @Schema(name = "deptId", title = "部门") + @NotNull(message = "部门不能为空") + private Long deptId; + + @Schema(name = "status", title = "状态", description = "1:禁用 0:正常") + private Boolean status; + +} + diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/user/AdminUserUpdateUserStatusDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/user/AdminUserUpdateUserStatusDto.java new file mode 100644 index 0000000..f6f273a --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/user/AdminUserUpdateUserStatusDto.java @@ -0,0 +1,25 @@ +package cn.bunny.dao.dto.system.user; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "UserUpdateWithPasswordDto对象", title = "管理员用户修改密码", description = "管理员用户修改密码") +public class AdminUserUpdateUserStatusDto { + + @Schema(name = "userId", title = "用户ID") + @NotNull(message = "用户ID不能为空") + private Long userId; + + @Schema(name = "status", title = "用户状态") + @NotNull(message = "用户状态不能为空") + private Boolean status; + +} diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/user/AdminUserUpdateWithPasswordDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/user/AdminUserUpdateWithPasswordDto.java new file mode 100644 index 0000000..8c9792a --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/user/AdminUserUpdateWithPasswordDto.java @@ -0,0 +1,28 @@ +package cn.bunny.dao.dto.system.user; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "UserUpdateWithPasswordDto对象", title = "管理员用户修改密码", description = "管理员用户修改密码") +public class AdminUserUpdateWithPasswordDto { + + @Schema(name = "userId", title = "用户ID") + @NotNull(message = "用户ID不能为空") + private Long userId; + + @Schema(name = "password", title = "用户密码") + @NotBlank(message = "密码不能为空") + @NotNull(message = "密码不能为空") + private String password; + +} + diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/user/AssignRolesToUsersDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/user/AssignRolesToUsersDto.java new file mode 100644 index 0000000..c1ac49d --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/user/AssignRolesToUsersDto.java @@ -0,0 +1,25 @@ +package cn.bunny.dao.dto.system.user; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "AssignRolesToUsersDto对象", title = "用户分配角色", description = "用户分配角色") +public class AssignRolesToUsersDto { + + @Schema(name = "userId", title = "用户id") + private Long userId; + + @Schema(name = "roleIds", title = "角色id列表") + private List roleIds; + +} + diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/user/LoginDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/user/LoginDto.java new file mode 100644 index 0000000..0dd6f1d --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/user/LoginDto.java @@ -0,0 +1,42 @@ +package cn.bunny.dao.dto.system.user; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Pattern; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "LoginDto", title = "登录表单内容", description = "登录表单内容") +public class LoginDto { + + @Schema(name = "username", title = "用户名") + @NotBlank(message = "用户名不能为空") + @NotNull(message = "用户名不能为空") + private String username; + + @Schema(name = "password", title = "密码") + @NotBlank(message = "密码不能为空") + @NotNull(message = "密码不能为空") + @Pattern(regexp = "^(?![0-9]+$)(?![a-z]+$)(?![A-Z]+$)(?!([^(0-9a-zA-Z)]|[()])+$)(?!^.*[\\u4E00-\\u9FA5].*$)([^(0-9a-zA-Z)]|[()]|[a-z]|[A-Z]|[0-9]){8,18}$", message = "密码格式应为8-18位数字、字母、符号的任意两种组合") + private String password; + + @Schema(name = "emailCode", title = "邮箱验证码") + @NotBlank(message = "邮箱验证码不能为空") + @NotNull(message = "邮箱验证码不能为空") + private String emailCode; + + @Schema(name = "type", title = "登录类型") + @NotBlank(message = "登录类型不能为空") + @NotNull(message = "登录类型能为空") + private String type; + + @Schema(name = "readMeDay", title = "记住我的天数") + private Long readMeDay = 1L; +} diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/user/RefreshTokenDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/user/RefreshTokenDto.java new file mode 100644 index 0000000..b558940 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/user/RefreshTokenDto.java @@ -0,0 +1,25 @@ +package cn.bunny.dao.dto.system.user; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "RefreshTokenDto对象", title = "登录成功返回内容", description = "登录成功返回内容") +public class RefreshTokenDto { + @Schema(name = "refreshToken", title = "请求刷新token") + @NotBlank(message = "请求刷新token不能为空") + @NotNull(message = "请求刷新token不能为空") + private String refreshToken; + + @Schema(name = "readMeDay", title = "记住我天数") + private long readMeDay = 1; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/dto/system/user/UserUpdateWithAvatarDto.java b/dao/src/main/java/cn/bunny/dao/dto/system/user/UserUpdateWithAvatarDto.java new file mode 100644 index 0000000..39e1e23 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/system/user/UserUpdateWithAvatarDto.java @@ -0,0 +1,26 @@ +package cn.bunny.dao.dto.system.user; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.web.multipart.MultipartFile; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "UserUpdateWithAvatarDto对象", title = "管理员用户修改头像", description = "管理员用户修改头像") +public class UserUpdateWithAvatarDto { + + @Schema(name = "userId", title = "用户ID") + @NotNull(message = "用户ID不能为空") + private Long userId; + + @Schema(name = "avatar", title = "用户头像") + @NotNull(message = "用户头像不能为空") + private MultipartFile avatar; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/entity/configuration/WebConfiguration.java b/dao/src/main/java/cn/bunny/dao/entity/configuration/WebConfiguration.java new file mode 100644 index 0000000..95db1de --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/entity/configuration/WebConfiguration.java @@ -0,0 +1,148 @@ +package cn.bunny.dao.entity.configuration; + +import com.alibaba.fastjson2.annotation.JSONField; +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "WebConfiguration对象", title = "前端配置文件", description = "前端配置文件") +public class WebConfiguration { + + @Schema(name = "Version", description = "应用程序的版本") + @JSONField(name = "Version") + @JsonProperty("Version") + private String version; + + @Schema(name = "Title", description = "应用程序的标题") + @JSONField(name = "Title") + @JsonProperty("Title") + private String title; + + @Schema(name = "Copyright", description = "版权信息") + @JSONField(name = "Copyright") + @JsonProperty("Copyright") + private String copyright; + + @Schema(name = "FixedHeader", description = "头部是否固定") + @JSONField(name = "FixedHeader") + @JsonProperty("FixedHeader") + private boolean fixedHeader; + + @Schema(name = "HiddenSideBar", description = "侧边栏是否隐藏") + @JSONField(name = "HiddenSideBar") + @JsonProperty("HiddenSideBar") + private boolean hiddenSideBar; + + @Schema(name = "MultiTagsCache", description = "是否缓存多个标签") + @JSONField(name = "MultiTagsCache") + @JsonProperty("MultiTagsCache") + private boolean multiTagsCache; + + @Schema(name = "KeepAlive", description = "是否持久化") + @JSONField(name = "KeepAlive") + @JsonProperty("KeepAlive") + private boolean keepAlive; + + @Schema(name = "Locale", description = "语言类型") + @JSONField(name = "Locale") + @JsonProperty("Locale") + private String locale; + + @Schema(name = "Layout", description = "应用程序的布局") + @JSONField(name = "Layout") + @JsonProperty("Layout") + private String layout; + + @Schema(name = "Theme", description = "应用程序的主题") + @JSONField(name = "Theme") + @JsonProperty("Theme") + private String theme; + + @Schema(name = "DarkMode", description = "是否启用深色模式") + @JSONField(name = "DarkMode") + @JsonProperty("DarkMode") + private boolean darkMode; + + @Schema(name = "OverallStyle", description = "应用程序的整体样式") + @JSONField(name = "OverallStyle") + @JsonProperty("OverallStyle") + private String overallStyle; + + @Schema(name = "Grey", description = "是否启用灰色模式") + @JSONField(name = "Grey") + @JsonProperty("Grey") + private boolean grey; + + @Schema(name = "Weak", description = "色弱模式") + @JSONField(name = "Weak") + @JsonProperty("Weak") + private boolean weak; + + @Schema(name = "HideTabs", description = "是否隐藏选项卡") + @JSONField(name = "HideTabs") + @JsonProperty("HideTabs") + private boolean hideTabs; + + @Schema(name = "HideFooter", description = "是否隐藏页脚") + @JSONField(name = "HideFooter") + @JsonProperty("HideFooter") + private boolean hideFooter; + + @Schema(name = "Stretch", description = "是否拉伸显示") + @JSONField(name = "Stretch") + @JsonProperty("Stretch") + private boolean stretch; + + @Schema(name = "SidebarStatus", description = "侧边栏的状态") + @JSONField(name = "SidebarStatus") + @JsonProperty("SidebarStatus") + private boolean sidebarStatus; + + @Schema(name = "EpThemeColor", description = "主题颜色") + @JSONField(name = "EpThemeColor") + @JsonProperty("EpThemeColor") + private String epThemeColor; + + @Schema(name = "ShowLogo", description = "是否显示logo") + @JSONField(name = "ShowLogo") + @JsonProperty("ShowLogo") + private boolean showLogo; + + @Schema(name = "ShowModel", description = "要显示的模型") + @JSONField(name = "ShowModel") + @JsonProperty("ShowModel") + private String showModel; + + @Schema(name = "MenuArrowIconNoTransition", description = "菜单箭头图标是否没有过渡效果") + @JSONField(name = "MenuArrowIconNoTransition") + @JsonProperty("MenuArrowIconNoTransition") + private boolean menuArrowIconNoTransition; + + @Schema(name = "CachingAsyncRoutes", description = "是否缓存异步路由") + @JSONField(name = "CachingAsyncRoutes") + @JsonProperty("CachingAsyncRoutes") + private boolean cachingAsyncRoutes; + + @Schema(name = "TooltipEffect", description = "工具提示的效果") + @JSONField(name = "TooltipEffect") + @JsonProperty("TooltipEffect") + private String tooltipEffect; + + @Schema(name = "ResponsiveStorageNameSpace", description = "响应式存储的命名空间") + @JSONField(name = "ResponsiveStorageNameSpace") + @JsonProperty("ResponsiveStorageNameSpace") + private String responsiveStorageNameSpace; + + @Schema(name = "MenuSearchHistory", description = "菜单搜索历史") + @JSONField(name = "MenuSearchHistory") + @JsonProperty("MenuSearchHistory") + private int menuSearchHistory; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/entity/financial/Bill.java b/dao/src/main/java/cn/bunny/dao/entity/financial/Bill.java new file mode 100644 index 0000000..7d43d91 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/entity/financial/Bill.java @@ -0,0 +1,46 @@ +package cn.bunny.dao.entity.financial; + +import cn.bunny.dao.common.entity.BaseEntity; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + *

+ * 账单信息 + *

+ * + * @author Bunny + * @since 2024-11-07 + */ +@Getter +@Setter +@Accessors(chain = true) +@TableName("t_bill") +@Schema(name = "Bill对象", title = "账单信息", description = "账单信息") +public class Bill extends BaseEntity { + + @Schema(name = "username", title = "类型:1 - 收入,-1 - 支出") + private Byte type; + + @Schema(name = "amount", title = "金额") + private BigDecimal amount; + + @Schema(name = "description", title = "描述") + private String description; + + @Schema(name = "transactionDate", title = "交易日期") + private LocalDateTime transactionDate; + + @Schema(name = "categoryId", title = "类别id") + private Long categoryId; + +} + + + diff --git a/dao/src/main/java/cn/bunny/dao/entity/financial/Category.java b/dao/src/main/java/cn/bunny/dao/entity/financial/Category.java new file mode 100644 index 0000000..495df45 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/entity/financial/Category.java @@ -0,0 +1,35 @@ +package cn.bunny.dao.entity.financial; + +import cn.bunny.dao.common.entity.BaseEntity; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +/** + *

+ * 分类信息 + *

+ * + * @author Bunny + * @since 2024-11-08 + */ +@Getter +@Setter +@Accessors(chain = true) +@TableName("t_category") +@Schema(name = "Category对象", title = "分类信息", description = "分类信息") +public class Category extends BaseEntity { + + @Schema(name = "userId", title = "绑定的用户id") + private Long userId; + + @Schema(name = "categoryName", title = "分类名称") + private String categoryName; + + @Schema(name = "isBuiltin", title = "是否内置字段") + private Boolean isBuiltin; + +} + diff --git a/dao/src/main/java/cn/bunny/dao/entity/i18n/I18n.java b/dao/src/main/java/cn/bunny/dao/entity/i18n/I18n.java new file mode 100644 index 0000000..8e2618d --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/entity/i18n/I18n.java @@ -0,0 +1,34 @@ +package cn.bunny.dao.entity.i18n; + +import cn.bunny.dao.common.entity.BaseEntity; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +/** + *

+ * 多语言表 + *

+ * + * @author Bunny + * @since 2024-09-28 + */ +@Getter +@Setter +@Accessors(chain = true) +@TableName("sys_i18n") +@Schema(name = "I18n对象", title = "多语言", description = "多语言管理") +public class I18n extends BaseEntity { + + @Schema(name = "keyName", title = "多语言key") + private String keyName; + + @Schema(name = "translation", title = "多语言翻译名称") + private String translation; + + @Schema(name = "typeName", title = "多语言类型id") + private String typeName; + +} diff --git a/dao/src/main/java/cn/bunny/dao/entity/i18n/I18nType.java b/dao/src/main/java/cn/bunny/dao/entity/i18n/I18nType.java new file mode 100644 index 0000000..ae799a8 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/entity/i18n/I18nType.java @@ -0,0 +1,34 @@ +package cn.bunny.dao.entity.i18n; + +import cn.bunny.dao.common.entity.BaseEntity; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +/** + *

+ * 多语言类型表 + *

+ * + * @author Bunny + * @since 2024-09-28 + */ +@Getter +@Setter +@Accessors(chain = true) +@TableName("sys_i18n_type") +@Schema(name = "I18nType对象", title = "多语言类型表", description = "多语言类型表") +public class I18nType extends BaseEntity { + + @Schema(name = "typeName", title = "多语言类型(比如zh,en)") + private String typeName; + + @Schema(name = "summary", title = "名称解释(比如中文,英文)") + private String summary; + + @Schema(name = "isDefault", title = "是否为默认") + private Boolean isDefault; + +} diff --git a/dao/src/main/java/cn/bunny/dao/entity/log/ScheduleExecuteLog.java b/dao/src/main/java/cn/bunny/dao/entity/log/ScheduleExecuteLog.java new file mode 100644 index 0000000..1c6b13b --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/entity/log/ScheduleExecuteLog.java @@ -0,0 +1,48 @@ +package cn.bunny.dao.entity.log; + +import cn.bunny.dao.common.entity.BaseEntity; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +/** + *

+ * 调度任务执行日志 + *

+ * + * @author Bunny + * @since 2024-10-18 + */ +@Getter +@Setter +@Accessors(chain = true) +@TableName("log_quartz_execute") +@Schema(name = "QuartzExecuteLog对象", title = "调度任务执行日志", description = "调度任务执行日志") +public class ScheduleExecuteLog extends BaseEntity { + + @Schema(name = "jobName", title = "任务名称") + private String jobName; + + @Schema(name = "jobGroup", title = "任务分组") + private String jobGroup; + + @Schema(name = "jobClassName", title = "执行任务类名") + private String jobClassName; + + @Schema(name = "cronExpression", title = "执行任务core表达式") + private String cronExpression; + + @Schema(name = "triggerName", title = "触发器名称") + private String triggerName; + + @Schema(name = "executeResult", title = "执行结果") + private String executeResult; + + @Schema(name = "duration", title = "执行时间") + private Long duration; + +} + + diff --git a/dao/src/main/java/cn/bunny/dao/entity/log/ScheduleExecuteLogJson.java b/dao/src/main/java/cn/bunny/dao/entity/log/ScheduleExecuteLogJson.java new file mode 100644 index 0000000..d521931 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/entity/log/ScheduleExecuteLogJson.java @@ -0,0 +1,32 @@ +package cn.bunny.dao.entity.log; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.Map; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "QuartzExecuteLog对象", title = "执行任务的日志", description = "执行任务的日志") +public class ScheduleExecuteLogJson { + + @Schema(name = "result", title = "执行结果") + private String result; + + @Schema(name = "status", title = "执行状态") + private String status; + + @Schema(name = "message", title = "执行消息") + private String message; + + @Schema(name = "operationTime", title = "操作时间") + private String operationTime; + + @Schema(name = "executeParams", title = "执行任务参数") + private Map executeParams; +} diff --git a/dao/src/main/java/cn/bunny/dao/entity/log/UserLoginLog.java b/dao/src/main/java/cn/bunny/dao/entity/log/UserLoginLog.java new file mode 100644 index 0000000..72ec509 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/entity/log/UserLoginLog.java @@ -0,0 +1,49 @@ +package cn.bunny.dao.entity.log; + +import cn.bunny.dao.common.entity.BaseEntity; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +/** + *

+ * 用户登录日志 + *

+ * + * @author Bunny + * @since 2024-10-19 + */ +@Getter +@Setter +@Accessors(chain = true) +@TableName("log_user_login") +@Schema(name = "UserLogin对象", title = "用户登录日志", description = "用户登录日志") +public class UserLoginLog extends BaseEntity { + + @Schema(name = "userId", title = "用户Id") + private Long userId; + + @Schema(name = "username", title = "用户名") + private String username; + + @Schema(name = "token", title = "登录token") + private String token; + + @Schema(name = "ipAddress", title = "登录Ip") + private String ipAddress; + + @Schema(name = "ipRegion", title = "登录Ip归属地") + private String ipRegion; + + @Schema(name = "userAgent", title = "登录时代理") + private String userAgent; + + @Schema(name = "type", title = "操作类型") + private String type; + + @Schema(name = "xRequestedWith", title = "标识客户端是否是通过Ajax发送请求的") + private String xRequestedWith; + +} diff --git a/dao/src/main/java/cn/bunny/dao/entity/quartz/Schedulers.java b/dao/src/main/java/cn/bunny/dao/entity/quartz/Schedulers.java new file mode 100644 index 0000000..994d4e2 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/entity/quartz/Schedulers.java @@ -0,0 +1,47 @@ +package cn.bunny.dao.entity.quartz; + +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + *

+ * VIEW + *

+ * + * @author Bunny + * @since 2024-10-14 + */ +@Getter +@Setter +@Accessors(chain = true) +@TableName("view_qrtz_schedulers") +@Schema(name = "Schedulers对象", title = "Schedulers视图", description = "Schedulers视图") +public class Schedulers implements Serializable { + + @Schema(name = "jobName", title = "任务名称") + private String jobName; + + @Schema(name = "jobGroup", title = "任务分组") + private String jobGroup; + + @Schema(name = "description", title = "任务详情") + private String description; + + @Schema(name = "jobClassName", title = "任务类名称") + private String jobClassName; + + @Schema(name = "cronExpression", title = "corn表达式") + private String cronExpression; + + @Schema(name = "triggerName", title = "触发器名称") + private String triggerName; + + @Schema(name = "triggerState", title = "triggerState触发器状态") + private String triggerState; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/entity/quartz/SchedulersGroup.java b/dao/src/main/java/cn/bunny/dao/entity/quartz/SchedulersGroup.java new file mode 100644 index 0000000..b5a078d --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/entity/quartz/SchedulersGroup.java @@ -0,0 +1,32 @@ +package cn.bunny.dao.entity.quartz; + +import cn.bunny.dao.common.entity.BaseEntity; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +/** + *

+ * 任务调度分组表 + *

+ * + * @author Bunny + * @since 2024-10-15 + */ +@Getter +@Setter +@Accessors(chain = true) +@TableName("qrtz_schedulers_group") +@Schema(name = "SchedulersGroup对象", title = "任务调度分组", description = "任务调度分组") +public class SchedulersGroup extends BaseEntity { + + @Schema(name = "groupName", title = "分组名称") + private String groupName; + + @Schema(name = "description", title = "分组详情") + private String description; + +} + diff --git a/dao/src/main/java/cn/bunny/dao/entity/system/AdminUser.java b/dao/src/main/java/cn/bunny/dao/entity/system/AdminUser.java new file mode 100644 index 0000000..89e3f1b --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/entity/system/AdminUser.java @@ -0,0 +1,59 @@ +package cn.bunny.dao.entity.system; + +import cn.bunny.dao.common.entity.BaseEntity; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + *

+ * 管理员用户信息 + *

+ * + * @author Bunny + * @since 2024-06-26 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@Accessors(chain = true) +@TableName("sys_user") +@Schema(name = "AdminUser对象", title = "用户信息", description = "用户信息") +public class AdminUser extends BaseEntity { + + @Schema(name = "username", title = "用户名") + private String username; + + @Schema(name = "nickname", title = "昵称") + private String nickname; + + @Schema(name = "email", title = "邮箱") + private String email; + + @Schema(name = "phone", title = "手机号") + private String phone; + + @Schema(name = "password", title = "密码") + private String password; + + @Schema(name = "avatar", title = "头像") + private String avatar; + + @Schema(name = "sex", title = "性别", description = "0:女 1:男") + private Byte sex; + + @Schema(name = "summary", title = "个人描述") + private String summary; + + @Schema(name = "ipAddress", title = "登录Ip") + private String ipAddress; + + @Schema(name = "ipRegion", title = "登录Ip归属地") + private String ipRegion; + + @Schema(name = "status", title = "状态", description = "1:禁用 0:正常") + private Boolean status; + +} + diff --git a/dao/src/main/java/cn/bunny/dao/entity/system/Dept.java b/dao/src/main/java/cn/bunny/dao/entity/system/Dept.java new file mode 100644 index 0000000..903fde5 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/entity/system/Dept.java @@ -0,0 +1,38 @@ +package cn.bunny.dao.entity.system; + +import cn.bunny.dao.common.entity.BaseEntity; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +/** + *

+ * 部门表 + *

+ * + * @author Bunny + * @since 2024-10-04 + */ +@Getter +@Setter +@Accessors(chain = true) +@TableName("sys_dept") +@Schema(name = "Dept对象", title = "部门", description = "部门管理") +public class Dept extends BaseEntity { + + @Schema(name = "parentId", title = "父级id") + private String parentId; + + @Schema(name = "manager", title = "管理者") + private String manager; + + @Schema(name = "deptName", title = "部门名称") + private String deptName; + + @Schema(name = "summary", title = "部门简介") + private String summary; + +} + diff --git a/dao/src/main/java/cn/bunny/dao/entity/system/EmailTemplate.java b/dao/src/main/java/cn/bunny/dao/entity/system/EmailTemplate.java new file mode 100644 index 0000000..0397d98 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/entity/system/EmailTemplate.java @@ -0,0 +1,43 @@ +package cn.bunny.dao.entity.system; + +import cn.bunny.dao.common.entity.BaseEntity; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + *

+ * + *

+ * + * @author Bunny + * @since 2024-05-19 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@Accessors(chain = true) +@TableName("sys_email_template") +@Schema(name = "EmailTemplate对象", title = "邮件模板表", description = "邮件模板表") +public class EmailTemplate extends BaseEntity { + + @Schema(name = "templateName", title = "模板名称") + private String templateName; + + @Schema(name = "emailUser", title = "模板名称") + private Long emailUser; + + @Schema(name = "subject", title = "主题") + private String subject; + + @Schema(name = "body", title = "邮件内容") + private String body; + + @Schema(name = "type", title = "邮件类型") + private String type; + + @Schema(name = "isDefault", title = "是否默认") + private Boolean isDefault; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/entity/system/EmailUsers.java b/dao/src/main/java/cn/bunny/dao/entity/system/EmailUsers.java new file mode 100644 index 0000000..c3820aa --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/entity/system/EmailUsers.java @@ -0,0 +1,45 @@ +package cn.bunny.dao.entity.system; + +import cn.bunny.dao.common.entity.BaseEntity; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + *

+ * 邮箱发送表 + *

+ * + * @author Bunny + * @since 2024-05-17 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@Accessors(chain = true) +@TableName("sys_email_users") +@Schema(name = "EmailUsers对象", title = "邮箱用户发送配置", description = "邮箱用户发送配置管理") +public class EmailUsers extends BaseEntity { + + @Schema(name = "email", title = "邮箱") + private String email; + + @Schema(name = "password", title = "密码") + private String password; + + @Schema(name = "host", title = "Host地址") + private String host; + + @Schema(name = "port", title = "端口号") + private Integer port; + + @Schema(name = "smtpAgreement", title = "邮箱协议") + private String smtpAgreement; + + @Schema(name = "isDefault", title = "是否为默认邮件") + private Boolean isDefault; + +} + + diff --git a/dao/src/main/java/cn/bunny/dao/entity/system/Files.java b/dao/src/main/java/cn/bunny/dao/entity/system/Files.java new file mode 100644 index 0000000..f242ee7 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/entity/system/Files.java @@ -0,0 +1,40 @@ +package cn.bunny.dao.entity.system; + +import cn.bunny.dao.common.entity.BaseEntity; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +/** + *

+ * 系统文件表 + *

+ * + * @author Bunny + * @since 2024-10-04 + */ +@Getter +@Setter +@Accessors(chain = true) +@TableName("sys_files") +@Schema(name = "Files对象", title = "系统文件表", description = "系统文件管理") +public class Files extends BaseEntity { + + @Schema(name = "filename", title = "文件的名称") + private String filename; + + @Schema(name = "filepath", title = "文件在服务器上的存储路径") + private String filepath; + + @Schema(name = "fileSize", title = "文件的大小,以字节为单位") + private Long fileSize; + + @Schema(name = "fileType", title = "文件的MIME类型") + private String fileType; + + @Schema(name = "downloadCount", title = "下载数量") + private Integer downloadCount; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/entity/system/MenuIcon.java b/dao/src/main/java/cn/bunny/dao/entity/system/MenuIcon.java new file mode 100644 index 0000000..f742dbf --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/entity/system/MenuIcon.java @@ -0,0 +1,24 @@ +package cn.bunny.dao.entity.system; + +import cn.bunny.dao.common.entity.BaseEntity; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +@EqualsAndHashCode(callSuper = true) +@Data +@Accessors(chain = true) +@TableName("sys_menu_icon") +@Schema(name = "MenuIcon对象", title = "系统菜单图标", description = "系统菜单图标") +public class MenuIcon extends BaseEntity { + + @Schema(name = "iconCode", title = "icon类名") + private String iconCode; + + @Schema(name = "iconName", title = "icon 名称") + private String iconName; + +} + diff --git a/dao/src/main/java/cn/bunny/dao/entity/system/Message.java b/dao/src/main/java/cn/bunny/dao/entity/system/Message.java new file mode 100644 index 0000000..6164a69 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/entity/system/Message.java @@ -0,0 +1,54 @@ +package cn.bunny.dao.entity.system; + +import cn.bunny.dao.common.entity.BaseEntity; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +/** + *

+ * 系统消息 + *

+ * + * @author Bunny + * @since 2024-10-30 + */ +@Getter +@Setter +@Accessors(chain = true) +@TableName("sys_message") +@Schema(name = "Message对象", title = "系统消息", description = "系统消息") +public class Message extends BaseEntity { + + @Schema(name = "title", title = "消息标题") + private String title; + + @Schema(name = "sendUserId", title = "发送人用户ID") + private Long sendUserId; + + @Schema(name = "messageType", title = "sys:系统消息,user用户消息") + private String messageType; + + @Schema(name = "cover", title = "封面") + private String cover; + + @Schema(name = "summary", title = "消息简介") + private String summary; + + @Schema(name = "content", title = "消息内容") + private String content; + + @Schema(name = "editorType", title = "编辑器类型") + private String editorType; + + @Schema(name = "level", title = "消息等级") + private String level; + + @Schema(name = "extra", title = "消息等级详情") + private String extra; + +} + + diff --git a/dao/src/main/java/cn/bunny/dao/entity/system/MessageReceived.java b/dao/src/main/java/cn/bunny/dao/entity/system/MessageReceived.java new file mode 100644 index 0000000..5e830bc --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/entity/system/MessageReceived.java @@ -0,0 +1,34 @@ +package cn.bunny.dao.entity.system; + +import cn.bunny.dao.common.entity.BaseEntity; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +/** + *

+ * + *

+ * + * @author Bunny + * @since 2024-10-31 + */ +@Getter +@Setter +@Accessors(chain = true) +@TableName("sys_message_received") +@Schema(name = "MessageReceived对象", title = "系统消息接受用户", description = "系统消息接受用户") +public class MessageReceived extends BaseEntity { + + @Schema(name = "receivedUserId", title = "接受者id") + private Long receivedUserId; + + @Schema(name = "messageId", title = "消息ID") + private Long messageId; + + @Schema(name = "status", title = "0:未读 1:已读") + private Boolean status; + +} diff --git a/dao/src/main/java/cn/bunny/dao/entity/system/MessageType.java b/dao/src/main/java/cn/bunny/dao/entity/system/MessageType.java new file mode 100644 index 0000000..056116a --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/entity/system/MessageType.java @@ -0,0 +1,38 @@ +package cn.bunny.dao.entity.system; + +import cn.bunny.dao.common.entity.BaseEntity; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +/** + *

+ * 系统消息类型 + *

+ * + * @author Bunny + * @since 2024-10-30 + */ +@Getter +@Setter +@Accessors(chain = true) +@TableName("sys_message_type") +@Schema(name = "MessageType对象", title = "系统消息类型", description = "系统消息类型") +public class MessageType extends BaseEntity { + + @Schema(name = "messageName", title = "消息名称") + private String messageName; + + @Schema(name = "messageType", title = "sys:系统消息,user用户消息") + private String messageType; + + @Schema(name = "summary", title = "消息备注") + private String summary; + + @Schema(name = "status", title = "0:启用 1:禁用") + private Boolean status; + +} + diff --git a/dao/src/main/java/cn/bunny/dao/entity/system/Power.java b/dao/src/main/java/cn/bunny/dao/entity/system/Power.java new file mode 100644 index 0000000..7bdf3eb --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/entity/system/Power.java @@ -0,0 +1,28 @@ +package cn.bunny.dao.entity.system; + +import cn.bunny.dao.common.entity.BaseEntity; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@TableName("sys_power") +@Schema(name = "Power对象", title = "权限", description = "权限") +public class Power extends BaseEntity { + + @Schema(name = "parentId", title = "父级id") + private Long parentId; + + @Schema(name = "parentId", title = "权限编码") + private String powerCode; + + @Schema(name = "powerName", title = "权限名称") + private String powerName; + + @Schema(name = "requestUrl", title = "请求路径") + private String requestUrl; + +} + diff --git a/dao/src/main/java/cn/bunny/dao/entity/system/Role.java b/dao/src/main/java/cn/bunny/dao/entity/system/Role.java new file mode 100644 index 0000000..0da330a --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/entity/system/Role.java @@ -0,0 +1,24 @@ +package cn.bunny.dao.entity.system; + +import cn.bunny.dao.common.entity.BaseEntity; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +@Getter +@Setter +@Accessors(chain = true) +@TableName("sys_role") +@Schema(name = "Role对象", title = "角色", description = "角色") +public class Role extends BaseEntity { + + @Schema(name = "roleCode", title = "角色代码") + private String roleCode; + + @Schema(name = "description", title = "描述") + private String description; + +} + diff --git a/dao/src/main/java/cn/bunny/dao/entity/system/RolePower.java b/dao/src/main/java/cn/bunny/dao/entity/system/RolePower.java new file mode 100644 index 0000000..05e9005 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/entity/system/RolePower.java @@ -0,0 +1,25 @@ +package cn.bunny.dao.entity.system; + +import cn.bunny.dao.common.entity.BaseEntity; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +@Setter +@Getter +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +@TableName("sys_role_power") +@Schema(name = "RolePower对象", title = "角色权限关系", description = "角色权限关系") +public class RolePower extends BaseEntity { + + @Schema(name = "roleId", title = "角色id") + private Long roleId; + + @Schema(name = "powerId", title = "权限id") + private Long powerId; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/entity/system/Router.java b/dao/src/main/java/cn/bunny/dao/entity/system/Router.java new file mode 100644 index 0000000..c0525ef --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/entity/system/Router.java @@ -0,0 +1,55 @@ +package cn.bunny.dao.entity.system; + +import cn.bunny.dao.common.entity.BaseEntity; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +/** + *

+ * 系统菜单表 + *

+ * + * @author Bunny + * @since 2024-09-29 + */ +@Getter +@Setter +@Accessors(chain = true) +@TableName("sys_router") +@Schema(name = "Router对象", title = "系统菜单表", description = "系统菜单表") +public class Router extends BaseEntity { + + @Schema(name = "parentId", title = "父级id") + private Long parentId; + + @Schema(name = "path", title = "在项目中路径") + private String path; + + @Schema(name = "component", title = "组件位置") + private String component; + + @Schema(name = "frameSrc", title = "frame路径") + private String frameSrc; + + @Schema(name = "routeName", title = "路由名称") + private String routeName; + + @Schema(name = "title", title = "路由title") + private String title; + + @Schema(name = "menuType", title = "菜单类型") + private Integer menuType; + + @Schema(name = "icon", title = "图标") + private String icon; + + @Schema(name = "routerRank", title = "等级") + private Integer routerRank; + + @Schema(name = "visible", title = "是否显示") + private Boolean visible; + +} diff --git a/dao/src/main/java/cn/bunny/dao/entity/system/RouterRole.java b/dao/src/main/java/cn/bunny/dao/entity/system/RouterRole.java new file mode 100644 index 0000000..53fb062 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/entity/system/RouterRole.java @@ -0,0 +1,22 @@ +package cn.bunny.dao.entity.system; + +import cn.bunny.dao.common.entity.BaseEntity; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +@Getter +@Setter +@Accessors(chain = true) +@TableName("sys_router_role") +@Schema(name = "RouterRole对象", title = "路由角色关系", description = "路由角色关系") +public class RouterRole extends BaseEntity { + + @Schema(name = "routerId", title = "路由ID") + private Long routerId; + + @Schema(name = "roleId", title = "角色ID") + private Long roleId; +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/entity/system/SystemLog.java b/dao/src/main/java/cn/bunny/dao/entity/system/SystemLog.java new file mode 100644 index 0000000..f56b6ab --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/entity/system/SystemLog.java @@ -0,0 +1,55 @@ +package cn.bunny.dao.entity.system; + +import cn.bunny.dao.common.entity.BaseEntity; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +/** + *

+ * 系统日志表 + *

+ * + * @author Bunny + * @since 2024-05-31 + */ +@Getter +@Setter +@Accessors(chain = true) +@TableName("system_log") +@Schema(name = "SystemLog对象", title = "系统日志表", description = "系统日志表") +public class SystemLog extends BaseEntity { + + @Schema(name = "classPath", title = "所在类路径") + private String classPath; + + @Schema(name = "methodName", title = "执行方法名称") + private String methodName; + + @Schema(name = "args", title = "入参内容") + private String args; + + @Schema(name = "result", title = "返回参数") + private String result; + + @Schema(name = "errorStack", title = "报错堆栈") + private String errorStack; + + @Schema(name = "errorMessage", title = "报错") + private String errorMessage; + + @Schema(name = "email", title = "邮箱") + private String email; + + @Schema(name = "nickname", title = "用户名") + private String nickname; + + @Schema(name = "token", title = "当前用户token") + private String token; + + @Schema(name = "ipAddress", title = "当前用户IP地址") + private String ipAddress; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/entity/system/UserDept.java b/dao/src/main/java/cn/bunny/dao/entity/system/UserDept.java new file mode 100644 index 0000000..a1d4c62 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/entity/system/UserDept.java @@ -0,0 +1,31 @@ +package cn.bunny.dao.entity.system; + +import cn.bunny.dao.common.entity.BaseEntity; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +/** + *

+ * 部门用户关系表 + *

+ * + * @author Bunny + * @since 2024-10-04 + */ +@Getter +@Setter +@Accessors(chain = true) +@TableName("sys_user_dept") +@Schema(name = "UserDept对象", title = "部门用户关系表", description = "部门用户关系管理") +public class UserDept extends BaseEntity { + + @Schema(name = "userId", title = "用户id") + private Long userId; + + @Schema(name = "deptId", title = "部门id") + private Long deptId; + +} diff --git a/dao/src/main/java/cn/bunny/dao/entity/system/UserRole.java b/dao/src/main/java/cn/bunny/dao/entity/system/UserRole.java new file mode 100644 index 0000000..08f7150 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/entity/system/UserRole.java @@ -0,0 +1,23 @@ +package cn.bunny.dao.entity.system; + +import cn.bunny.dao.common.entity.BaseEntity; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +@Getter +@Setter +@Accessors(chain = true) +@TableName("sys_user_role") +@Schema(name = "UserRole对象", title = "用户角色关系", description = "用户角色关系") +public class UserRole extends BaseEntity { + + @Schema(name = "userId", title = "用户id") + private Long userId; + + @Schema(name = "roleId", title = "角色id") + private Long roleId; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/pojo/common/EmailSend.java b/dao/src/main/java/cn/bunny/dao/pojo/common/EmailSend.java new file mode 100644 index 0000000..8fd3da5 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/pojo/common/EmailSend.java @@ -0,0 +1,49 @@ +package cn.bunny.dao.pojo.common; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.web.multipart.MultipartFile; + +import java.util.ArrayList; +import java.util.List; + +/** + * 邮件发送对象 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Schema(name = "EmailSend", title = "邮件发送表单", description = "邮件发送表单") +public class EmailSend { + + @Schema(name = "sendTo", title = "收件人") + @NotBlank(message = "收件人机不能为空") + @NotNull(message = "收件人不能为空") + private List sendTo; + + @Schema(name = "subject", title = "发送主题") + @NotBlank(message = "发送主题不能为空") + @NotNull(message = "发送主题不能为空") + private String subject; + + @Schema(name = "isRichText", title = "是否为富文本") + private boolean isRichText = true; + + @Schema(name = "message", title = "发送内容") + @NotBlank(message = "发送内容不能为空") + @NotNull(message = "发送内容不能为空") + private String text; + + @Schema(name = "ccParam", title = "抄送人") + private List ccParam = new ArrayList<>(); + + @Schema(name = "file", title = "发送的文件") + private MultipartFile[] files; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/pojo/common/EmailSendInit.java b/dao/src/main/java/cn/bunny/dao/pojo/common/EmailSendInit.java new file mode 100644 index 0000000..d25bd58 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/pojo/common/EmailSendInit.java @@ -0,0 +1,43 @@ +package cn.bunny.dao.pojo.common; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 邮箱发送初始化参数 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Schema(name = "EmailSendInit", title = "邮件发送初始化", description = "邮件发送初始化") +public class EmailSendInit { + + @Schema(name = "port", title = "端口") + @NotNull(message = "端口不能为空") + private Integer port; + + @Schema(name = "host", title = "主机") + @NotBlank(message = "主机不能为空") + @NotNull(message = "主机不能为空") + private String host; + + @Schema(name = "protocol", description = "协议") + private String protocol = "smtps"; + + @Schema(name = "username", title = "用户名") + @NotBlank(message = "用户名不能为空") + @NotNull(message = "用户名不能为空") + private String username; + + @Schema(name = "password", title = "密码") + @NotBlank(message = "密码不能为空") + @NotNull(message = "密码不能为空") + private String password; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/pojo/common/MinioFilePath.java b/dao/src/main/java/cn/bunny/dao/pojo/common/MinioFilePath.java new file mode 100644 index 0000000..87e7d0b --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/pojo/common/MinioFilePath.java @@ -0,0 +1,18 @@ +package cn.bunny.dao.pojo.common; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class MinioFilePath { + private String filename; + private String uuidFilename; + private String timeUuidFilename; + private String filepath; + private String bucketNameFilepath; +} diff --git a/dao/src/main/java/cn/bunny/dao/pojo/constant/LocalDateTimeConstant.java b/dao/src/main/java/cn/bunny/dao/pojo/constant/LocalDateTimeConstant.java new file mode 100644 index 0000000..5ce334d --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/pojo/constant/LocalDateTimeConstant.java @@ -0,0 +1,11 @@ +package cn.bunny.dao.pojo.constant; + +import lombok.Data; + +@Data +public class LocalDateTimeConstant { + public static final String YYYY_MM_DD = "yyyy-MM-dd"; + public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss"; + public static final String YYYY_MM_DD_HH_MM_SS_SLASH = "yyyy/MM/dd HH:mm:ss"; + public static final String YYYY_MM_DD_HH_MM_SS_UNDERLINE = "yyyy_MM_dd_HH_mm_ss_SSS"; +} diff --git a/dao/src/main/java/cn/bunny/dao/pojo/constant/MinioConstant.java b/dao/src/main/java/cn/bunny/dao/pojo/constant/MinioConstant.java new file mode 100644 index 0000000..4fff73a --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/pojo/constant/MinioConstant.java @@ -0,0 +1,35 @@ +package cn.bunny.dao.pojo.constant; + +import lombok.Data; + +import java.util.HashMap; +import java.util.Map; + +@Data +public class MinioConstant { + public static final String favicon = "favicon"; + public static final String avatar = "avatar"; + public static final String message = "message"; + public static final String carousel = "carousel"; + public static final String feedback = "feedback"; + public static final String backup = "backup"; + public static final Map typeMap = new HashMap<>(); + + static { + typeMap.put(favicon, "/favicon/"); + typeMap.put(avatar, "/avatar/"); + typeMap.put(message, "/message/"); + typeMap.put(carousel, "/carousel/"); + typeMap.put(feedback, "/feedback/"); + typeMap.put(backup, "/backup/"); + typeMap.put("images", "/images/"); + typeMap.put("video", "/video/"); + typeMap.put("default", "/default/"); + } + + public static String getType(String type) { + String value = typeMap.get(type); + if (value != null) return value; + throw new RuntimeException("上传类型错误或缺失"); + } +} diff --git a/dao/src/main/java/cn/bunny/dao/pojo/constant/RedisUserConstant.java b/dao/src/main/java/cn/bunny/dao/pojo/constant/RedisUserConstant.java new file mode 100644 index 0000000..5451ead --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/pojo/constant/RedisUserConstant.java @@ -0,0 +1,27 @@ +package cn.bunny.dao.pojo.constant; + +import lombok.Data; + +/** + * Redis用户前缀设置 + */ +@Data +public class RedisUserConstant { + // 过期时间 + public static final Long REDIS_EXPIRATION_TIME = 7L;// 7 天/分钟 Redis过期 + public static final Integer Cookie_EXPIRATION_TIME = 5 * 60 * 60;// cookies 过期时间 5 分钟 + + private static final String ADMIN_LOGIN_INFO_PREFIX = "admin::login_info::"; + private static final String ADMIN_EMAIL_CODE_PREFIX = "admin::email_code::"; + private static final String USER_LOGIN_INFO_PREFIX = "user::login_info::"; + private static final String USER_EMAIL_CODE_PREFIX = "user::email_code::"; + + public static String getAdminLoginInfoPrefix(String adminUser) { + return ADMIN_LOGIN_INFO_PREFIX + adminUser; + } + + public static String getAdminUserEmailCodePrefix(String adminUser) { + return ADMIN_EMAIL_CODE_PREFIX + adminUser; + } + +} diff --git a/dao/src/main/java/cn/bunny/dao/pojo/constant/UserConstant.java b/dao/src/main/java/cn/bunny/dao/pojo/constant/UserConstant.java new file mode 100644 index 0000000..2fe60d0 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/pojo/constant/UserConstant.java @@ -0,0 +1,10 @@ +package cn.bunny.dao.pojo.constant; + +import lombok.Data; + +@Data +public class UserConstant { + public static final String USER_AVATAR = "https://thirdwx.qlogo.cn/mmopen/vi_32/DYAIOgq83eoj0hHXhgJNOTSOFsS4uZs8x1ConecaVOB8eIl115xmJZcT4oCicvia7wMEufibKtTLqiaJeanU2Lpg3w/132"; + public static final String PERSON_DESCRIPTION = "这个人很懒没有介绍..."; + public static final Long CATEGORY_COUNT = 50L; +} diff --git a/dao/src/main/java/cn/bunny/dao/pojo/enums/EmailTemplateEnums.java b/dao/src/main/java/cn/bunny/dao/pojo/enums/EmailTemplateEnums.java new file mode 100644 index 0000000..e97f71e --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/pojo/enums/EmailTemplateEnums.java @@ -0,0 +1,21 @@ +package cn.bunny.dao.pojo.enums; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; + +@Getter +@Schema(description = "Email Template Types") +public enum EmailTemplateEnums { + VERIFICATION_CODE("verification_code", "邮箱验证码发送"), + NOTIFICATION("notification", "通知型邮件"), + WARNING("warning", "警告型邮件"), + ; + + private final String type; + private final String summary; + + EmailTemplateEnums(String type, String summary) { + this.type = type; + this.summary = summary; + } +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/pojo/enums/JobEnums.java b/dao/src/main/java/cn/bunny/dao/pojo/enums/JobEnums.java new file mode 100644 index 0000000..94c3259 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/pojo/enums/JobEnums.java @@ -0,0 +1,20 @@ +package cn.bunny.dao.pojo.enums; + +import lombok.Getter; + +@Getter +public enum JobEnums { + FINISH("finish", "完成"), + UNFINISHED("unfinished", "未完成"), + RUNNING("running", "正在运行"), + ERROR("error", "错误"), + ; + + private final String type; + private final String summary; + + JobEnums(String type, String summary) { + this.type = type; + this.summary = summary; + } +} diff --git a/dao/src/main/java/cn/bunny/dao/pojo/result/PageResult.java b/dao/src/main/java/cn/bunny/dao/pojo/result/PageResult.java new file mode 100644 index 0000000..aed48e4 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/pojo/result/PageResult.java @@ -0,0 +1,34 @@ +package cn.bunny.dao.pojo.result; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.List; + +/** + * 封装分页查询结果 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "PageResult 对象", title = "分页返回结果", description = "分页返回结果") +public class PageResult implements Serializable { + + @Schema(name = "pageNo", title = "当前页") + private Long pageNo; + + @Schema(name = "pageSize", title = "每页记录数") + private Long pageSize; + + @Schema(name = "total", title = "总记录数") + private Long total; + + @Schema(name = "list", title = "当前页数据集合") + private List list; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/pojo/result/Result.java b/dao/src/main/java/cn/bunny/dao/pojo/result/Result.java new file mode 100644 index 0000000..d941e7c --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/pojo/result/Result.java @@ -0,0 +1,173 @@ +package cn.bunny.dao.pojo.result; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class Result { + // 状态码 + private Integer code; + // 返回消息 + private String message; + // 返回数据 + private T data; + + /** + * * 自定义返回体 + * + * @param data 返回体 + * @return Result + */ + protected static Result build(T data) { + Result result = new Result<>(); + result.setData(data); + return result; + } + + /** + * * 自定义返回体,使用ResultCodeEnum构建 + * + * @param body 返回体 + * @param codeEnum 返回状态码 + * @return Result + */ + public static Result build(T body, ResultCodeEnum codeEnum) { + Result result = build(body); + result.setCode(codeEnum.getCode()); + result.setMessage(codeEnum.getMessage()); + return result; + } + + /** + * * 自定义返回体 + * + * @param body 返回体 + * @param code 返回状态码 + * @param message 返回消息 + * @return Result + */ + public static Result build(T body, Integer code, String message) { + Result result = build(body); + result.setCode(code); + result.setMessage(message); + result.setData(null); + return result; + } + + /** + * * 操作成功 + * + * @return Result + */ + public static Result success() { + return success(null, ResultCodeEnum.SUCCESS); + } + + /** + * * 操作成功 + * + * @param data baseCategory1List + */ + public static Result success(T data) { + return build(data, ResultCodeEnum.SUCCESS); + } + + /** + * * 操作成功-状态码 + * + * @param codeEnum 状态码 + */ + public static Result success(ResultCodeEnum codeEnum) { + return success(null, codeEnum); + } + + /** + * * 操作成功-自定义返回数据和状态码 + * + * @param data 返回体 + * @param codeEnum 状态码 + */ + public static Result success(T data, ResultCodeEnum codeEnum) { + return build(data, codeEnum); + } + + /** + * * 操作失败-自定义返回数据和状态码 + * + * @param data 返回体 + * @param message 错误信息 + */ + public static Result success(T data, String message) { + return build(data, 200, message); + } + + /** + * * 操作失败-自定义返回数据和状态码 + * + * @param data 返回体 + * @param code 状态码 + * @param message 错误信息 + */ + public static Result success(T data, Integer code, String message) { + return build(data, code, message); + } + + /** + * * 操作失败 + */ + public static Result error() { + return Result.build(null); + } + + /** + * * 操作失败-自定义返回数据 + * + * @param data 返回体 + */ + public static Result error(T data) { + return build(data, ResultCodeEnum.FAIL); + } + + /** + * * 操作失败-状态码 + * + * @param codeEnum 状态码 + */ + public static Result error(ResultCodeEnum codeEnum) { + return build(null, codeEnum); + } + + /** + * * 操作失败-自定义返回数据和状态码 + * + * @param data 返回体 + * @param codeEnum 状态码 + */ + public static Result error(T data, ResultCodeEnum codeEnum) { + return build(data, codeEnum); + } + + /** + * * 操作失败-自定义返回数据和状态码 + * + * @param data 返回体 + * @param code 状态码 + * @param message 错误信息 + */ + public static Result error(T data, Integer code, String message) { + return build(data, code, message); + } + + /** + * * 操作失败-自定义返回数据和状态码 + * + * @param data 返回体 + * @param message 错误信息 + */ + public static Result error(T data, String message) { + return build(null, 500, message); + } +} diff --git a/dao/src/main/java/cn/bunny/dao/pojo/result/ResultCodeEnum.java b/dao/src/main/java/cn/bunny/dao/pojo/result/ResultCodeEnum.java new file mode 100644 index 0000000..a70cc3c --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/pojo/result/ResultCodeEnum.java @@ -0,0 +1,91 @@ +package cn.bunny.dao.pojo.result; + +import lombok.Getter; + +/** + * 统一返回结果状态信息类 + */ +@Getter +public enum ResultCodeEnum { + // 成功操作 200 + SUCCESS(200, "操作成功"), + ADD_SUCCESS(200, "添加成功"), + UPDATE_SUCCESS(200, "修改成功"), + DELETE_SUCCESS(200, "删除成功"), + SORT_SUCCESS(200, "排序成功"), + SUCCESS_UPLOAD(200, "上传成功"), + SUCCESS_LOGOUT(200, "退出成功"), + LOGOUT_SUCCESS(200, "退出成功"), + EMAIL_CODE_REFRESH(200, "邮箱验证码已刷新"), + EMAIL_CODE_SEND_SUCCESS(200, "邮箱验证码已发送"), + + // 验证错误 201 + USERNAME_OR_PASSWORD_NOT_EMPTY(201, "用户名或密码不能为空"), + EMAIL_CODE_NOT_EMPTY(201, "邮箱验证码不能为空"), + SEND_EMAIL_CODE_NOT_EMPTY(201, "请先发送邮箱验证码"), + EMAIL_CODE_NOT_MATCHING(201, "邮箱验证码不匹配"), + LOGIN_ERROR(201, "账号或密码错误"), + LOGIN_ERROR_USERNAME_PASSWORD_NOT_EMPTY(201, "登录信息不能为空"), + GET_BUCKET_EXCEPTION(201, "获取文件信息失败"), + SEND_MAIL_CODE_ERROR(201, "邮件发送失败"), + EMAIL_CODE_EMPTY(201, "邮箱验证码过期或不存在"), + EMAIL_EXIST(201, "邮箱已存在"), + REQUEST_IS_EMPTY(201, "请求数据为空"), + DATA_TOO_LARGE(201, "请求数据为空"), + UPDATE_NEW_PASSWORD_SAME_AS_OLD_PASSWORD(201, "新密码与密码相同"), + + // 数据相关 206 + ILLEGAL_REQUEST(206, "非法请求"), + REPEAT_SUBMIT(206, "重复提交"), + DATA_ERROR(206, "数据异常"), + EMAIL_USER_TEMPLATE_IS_EMPTY(206, "邮件模板为空"), + EMAIL_TEMPLATE_IS_EMPTY(206, "邮件模板为空"), + EMAIL_USER_IS_EMPTY(206, "关联邮件用户配置为空"), + DATA_EXIST(206, "数据已存在"), + DATA_NOT_EXIST(206, "数据不存在"), + ALREADY_USER_EXCEPTION(206, "用户已存在"), + USER_IS_EMPTY(206, "用户不存在"), + FILE_NOT_EXIST(206, "文件不存在"), + NEW_PASSWORD_SAME_OLD_PASSWORD(206, "新密码不能和旧密码相同"), + MISSING_TEMPLATE_FILES(206, "缺少模板文件"), + THE_MAXIMUM_BAR_CODE(206, "最大条码为50"), + + // 身份过期 208 + LOGIN_AUTH(208, "请先登陆"), + AUTHENTICATION_EXPIRED(208, "身份验证过期"), + SESSION_EXPIRATION(208, "会话过期"), + + // 209 + THE_SAME_USER_HAS_LOGGED_IN(209, "相同用户已登录"), + + // 提示错误 + URL_ENCODE_ERROR(216, "URL编码失败"), + ILLEGAL_CALLBACK_REQUEST_ERROR(217, "非法回调请求"), + FETCH_USERINFO_ERROR(219, "获取用户信息失败"), + ILLEGAL_DATA_REQUEST(219, "非法数据请求"), + CLASS_NOT_FOUND(219, "类名不存在"), + ADMIN_ROLE_CAN_NOT_DELETED(219, "无法删除admin角色"), + + // 无权访问 403 + FAIL_REQUEST_NOT_AUTH(403, "用户未认证"), + FAIL_NO_ACCESS_DENIED(403, "无权访问"), + FAIL_NO_ACCESS_DENIED_USER_OFFLINE(403, "用户强制下线"), + LOGGED_IN_FROM_ANOTHER_DEVICE(403, "没有权限访问"), + TOKEN_PARSING_FAILED(403, "token解析失败"), + FAIL_NO_ACCESS_DENIED_USER_LOCKED(403, "该账户已封禁"), + + // 系统错误 500 + UNKNOWN_EXCEPTION(500, "服务异常"), + SERVICE_ERROR(500, "服务异常"), + UPDATE_ERROR(500, "上传文件失败"), + FAIL(500, "失败"), + ; + + private final Integer code; + private final String message; + + ResultCodeEnum(Integer code, String message) { + this.code = code; + this.message = message; + } +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/view/ViewRolePower.java b/dao/src/main/java/cn/bunny/dao/view/ViewRolePower.java new file mode 100644 index 0000000..c599277 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/view/ViewRolePower.java @@ -0,0 +1,37 @@ +package cn.bunny.dao.view; + +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +@Setter +@Getter +@Accessors(chain = true) +@TableName("sys_role_power") +@Schema(name = "ViewRolePower对象", title = "角色权限关系视图", description = "角色权限关系视图") +public class ViewRolePower { + + @Schema(name = "roleId", title = "角色ID") + private Long roleId; + + @Schema(name = "roleCode", title = "角色代码") + private String roleCode; + + @Schema(name = "description", title = "描述") + private String description; + + @Schema(name = "parentId", title = "父级id") + private Long parentId; + + @Schema(name = "parentId", title = "权限编码") + private String powerCode; + + @Schema(name = "powerName", title = "权限名称") + private String powerName; + + @Schema(name = "requestUrl", title = "请求路径") + private String requestUrl; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/view/ViewRouterRole.java b/dao/src/main/java/cn/bunny/dao/view/ViewRouterRole.java new file mode 100644 index 0000000..62ea93e --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/view/ViewRouterRole.java @@ -0,0 +1,58 @@ +package cn.bunny.dao.view; + +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +@Getter +@Setter +@Accessors(chain = true) +@TableName("sys_router_role") +@Schema(name = "RouterRoleViewRouterRole象", title = "路由角色关系视图", description = "路由角色关系视图") +public class ViewRouterRole { + + @Schema(name = "routerId", title = "路由ID") + private Long routerId; + + @Schema(name = "parentId", title = "父级id") + private Long parentId; + + @Schema(name = "path", title = "在项目中路径") + private String path; + + @Schema(name = "component", title = "组件位置") + private String component; + + @Schema(name = "frameSrc", title = "frame路径") + private String frameSrc; + + @Schema(name = "routeName", title = "路由名称") + private String routeName; + + @Schema(name = "title", title = "路由title") + private String title; + + @Schema(name = "menuType", title = "菜单类型") + private Integer menuType; + + @Schema(name = "icon", title = "图标") + private String icon; + + @Schema(name = "routerRank", title = "等级") + private Integer routerRank; + + @Schema(name = "visible", title = "是否显示") + private Boolean visible; + + @Schema(name = "roleId", title = "角色ID") + private Long roleId; + + @Schema(name = "roleCode", title = "角色代码") + private String roleCode; + + @Schema(name = "description", title = "描述") + private String description; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/view/ViewUserDept.java b/dao/src/main/java/cn/bunny/dao/view/ViewUserDept.java new file mode 100644 index 0000000..244546f --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/view/ViewUserDept.java @@ -0,0 +1,60 @@ +package cn.bunny.dao.view; + +import cn.bunny.dao.common.entity.BaseUserEntity; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + *

+ * 管理员用户信息 + *

+ * + * @author Bunny + * @since 2024-06-26 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@Accessors(chain = true) +@TableName("sys_user") +@Schema(name = "AdminUserAndDept对象", title = "用户信息和部门Id", description = "用户信息和部门Id") +public class ViewUserDept extends BaseUserEntity { + + @Schema(name = "username", title = "用户名") + private String username; + + @Schema(name = "nickname", title = "昵称") + private String nickname; + + @Schema(name = "email", title = "邮箱") + private String email; + + @Schema(name = "phone", title = "手机号") + private String phone; + + @Schema(name = "password", title = "密码") + private String password; + + @Schema(name = "avatar", title = "头像") + private String avatar; + + @Schema(name = "sex", title = "性别", description = "0:女 1:男") + private Byte sex; + + @Schema(name = "summary", title = "个人描述") + private String summary; + + @Schema(name = "ipAddress", title = "登录Ip") + private String ipAddress; + + @Schema(name = "ipRegion", title = "登录Ip归属地") + private String ipRegion; + + @Schema(name = "status", title = "状态", description = "1:禁用 0:正常") + private Boolean status; + + @Schema(name = "deptId", title = "部门") + private Long deptId; +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/vo/configuration/CategoryVo.java b/dao/src/main/java/cn/bunny/dao/vo/configuration/CategoryVo.java new file mode 100644 index 0000000..a33f4a1 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/vo/configuration/CategoryVo.java @@ -0,0 +1,32 @@ +package cn.bunny.dao.vo.configuration; + +import cn.bunny.dao.common.vo.BaseUserVo; +import com.alibaba.fastjson2.annotation.JSONField; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "CategoryUserVo对象", title = "分类信息查询", description = "分类信息查询") +public class CategoryVo extends BaseUserVo { + + @Schema(name = "userId", title = "绑定的用户id") + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JSONField(serializeUsing = ToStringSerializer.class) + private Long userId; + + @Schema(name = "username", title = "绑定的用户名") + private String username; + + @Schema(name = "categoryName", title = "分类名称") + private String categoryName; + + @Schema(name = "isBuiltin", title = "是否内置字段") + private Boolean isBuiltin; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/vo/configuration/WebConfigurationVo.java b/dao/src/main/java/cn/bunny/dao/vo/configuration/WebConfigurationVo.java new file mode 100644 index 0000000..287c131 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/vo/configuration/WebConfigurationVo.java @@ -0,0 +1,121 @@ +package cn.bunny.dao.vo.configuration; + +import com.alibaba.fastjson2.annotation.JSONField; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "WebConfigurationVo对象", title = "前端配置获取返回结果", description = "前端配置获取返回结果") +public class WebConfigurationVo { + + @Schema(name = "Version", description = "应用程序的版本") + @JSONField(name = "Version") + private String version; + + @Schema(name = "Title", description = "应用程序的标题") + @JSONField(name = "Title") + private String title; + + @Schema(name = "Copyright", description = "版权信息") + @JSONField(name = "Copyright") + private String copyright; + + @Schema(name = "FixedHeader", description = "头部是否固定") + @JSONField(name = "FixedHeader") + private boolean fixedHeader; + + @Schema(name = "HiddenSideBar", description = "侧边栏是否隐藏") + @JSONField(name = "HiddenSideBar") + private boolean hiddenSideBar; + + @Schema(name = "MultiTagsCache", description = "是否缓存多个标签") + @JSONField(name = "MultiTagsCache") + private boolean multiTagsCache; + + @Schema(name = "KeepAlive", description = "是否持久化") + @JSONField(name = "KeepAlive") + private boolean keepAlive; + + @Schema(name = "Locale", description = "语言类型") + @JSONField(name = "Locale") + private String locale; + + @Schema(name = "Layout", description = "应用程序的布局") + @JSONField(name = "Layout") + private String layout; + + @Schema(name = "Theme", description = "应用程序的主题") + @JSONField(name = "Theme") + private String theme; + + @Schema(name = "DarkMode", description = "是否启用深色模式") + @JSONField(name = "DarkMode") + private boolean darkMode; + + @Schema(name = "OverallStyle", description = "应用程序的整体样式") + @JSONField(name = "OverallStyle") + private String overallStyle; + + @Schema(name = "Grey", description = "是否启用灰色模式") + @JSONField(name = "Grey") + private boolean grey; + + @Schema(name = "Weak", description = "色弱模式") + @JSONField(name = "Weak") + private boolean weak; + + @Schema(name = "HideTabs", description = "是否隐藏选项卡") + @JSONField(name = "HideTabs") + private boolean hideTabs; + + @Schema(name = "HideFooter", description = "是否隐藏页脚") + @JSONField(name = "HideFooter") + private boolean hideFooter; + + @Schema(name = "Stretch", description = "是否拉伸显示") + @JSONField(name = "Stretch") + private boolean stretch; + + @Schema(name = "SidebarStatus", description = "侧边栏的状态") + @JSONField(name = "SidebarStatus") + private boolean sidebarStatus; + + @Schema(name = "EpThemeColor", description = "主题颜色") + @JSONField(name = "EpThemeColor") + private String epThemeColor; + + @Schema(name = "ShowLogo", description = "是否显示logo") + @JSONField(name = "ShowLogo") + private boolean showLogo; + + @Schema(name = "ShowModel", description = "要显示的模型") + @JSONField(name = "ShowModel") + private String showModel; + + @Schema(name = "MenuArrowIconNoTransition", description = "菜单箭头图标是否没有过渡效果") + @JSONField(name = "MenuArrowIconNoTransition") + private boolean menuArrowIconNoTransition; + + @Schema(name = "CachingAsyncRoutes", description = "是否缓存异步路由") + @JSONField(name = "CachingAsyncRoutes") + private boolean cachingAsyncRoutes; + + @Schema(name = "TooltipEffect", description = "工具提示的效果") + @JSONField(name = "TooltipEffect") + private String tooltipEffect; + + @Schema(name = "ResponsiveStorageNameSpace", description = "响应式存储的命名空间") + @JSONField(name = "ResponsiveStorageNameSpace") + private String responsiveStorageNameSpace; + + @Schema(name = "MenuSearchHistory", description = "菜单搜索历史") + @JSONField(name = "MenuSearchHistory") + private int menuSearchHistory; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/vo/financial/BillVo.java b/dao/src/main/java/cn/bunny/dao/vo/financial/BillVo.java new file mode 100644 index 0000000..1f149d6 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/vo/financial/BillVo.java @@ -0,0 +1,48 @@ +package cn.bunny.dao.vo.financial; + +import cn.bunny.dao.common.vo.BaseVo; +import com.alibaba.fastjson2.annotation.JSONField; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "BillVo对象", title = "账单信息返回内容", description = "账单信息返回内容") +public class BillVo extends BaseVo { + + @Schema(name = "username", title = "类型:1 - 收入,-1 - 支出") + private Byte type; + + @Schema(name = "amount", title = "金额") + private BigDecimal amount; + + @Schema(name = "description", title = "描述") + private String description; + + @Schema(name = "transactionDate", title = "交易日期") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonSerialize(using = LocalDateTimeSerializer.class) + @JsonDeserialize(using = LocalDateTimeDeserializer.class) + private LocalDateTime transactionDate; + + @Schema(name = "categoryId", title = "分类Id") + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JSONField(serializeUsing = ToStringSerializer.class) + private String categoryId; + + @Schema(name = "categoryName", title = "类别分类") + private String categoryName; + +} diff --git a/dao/src/main/java/cn/bunny/dao/vo/financial/CategoryUserVo.java b/dao/src/main/java/cn/bunny/dao/vo/financial/CategoryUserVo.java new file mode 100644 index 0000000..a41850f --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/vo/financial/CategoryUserVo.java @@ -0,0 +1,21 @@ +package cn.bunny.dao.vo.financial; + +import cn.bunny.dao.common.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "CategoryUserVo对象", title = "分类信息查询", description = "分类信息查询") +public class CategoryUserVo extends BaseVo { + + @Schema(name = "categoryName", title = "分类名称") + private String categoryName; + + @Schema(name = "isBuiltin", title = "是否内置字段") + private Boolean isBuiltin; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/vo/i18n/I18nTypeVo.java b/dao/src/main/java/cn/bunny/dao/vo/i18n/I18nTypeVo.java new file mode 100644 index 0000000..872f9b8 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/vo/i18n/I18nTypeVo.java @@ -0,0 +1,26 @@ +package cn.bunny.dao.vo.i18n; + +import cn.bunny.dao.common.vo.BaseUserVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "I18nVo对象", title = "多语言返回内容", description = "多语言返回内容") +public class I18nTypeVo extends BaseUserVo { + + @Schema(name = "typeName", title = "多语言类型(比如zh,en)") + private String typeName; + + @Schema(name = "summary", title = "名称解释(比如中文,英文)") + private String summary; + + @Schema(name = "isDefault", title = "是否为默认") + private Boolean isDefault; + +} + + diff --git a/dao/src/main/java/cn/bunny/dao/vo/i18n/I18nVo.java b/dao/src/main/java/cn/bunny/dao/vo/i18n/I18nVo.java new file mode 100644 index 0000000..4d102bd --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/vo/i18n/I18nVo.java @@ -0,0 +1,26 @@ +package cn.bunny.dao.vo.i18n; + +import cn.bunny.dao.common.vo.BaseUserVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "I18nVo对象", title = "多语言返回内容", description = "多语言返回内容") +public class I18nVo extends BaseUserVo { + + @Schema(name = "keyName", title = "多语言key") + private String keyName; + + @Schema(name = "translation", title = "多语言翻译名称") + private String translation; + + @Schema(name = "typeName", title = "多语言类型id") + private String typeName; + +} + + diff --git a/dao/src/main/java/cn/bunny/dao/vo/log/QuartzExecuteLogVo.java b/dao/src/main/java/cn/bunny/dao/vo/log/QuartzExecuteLogVo.java new file mode 100644 index 0000000..ef3e9e5 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/vo/log/QuartzExecuteLogVo.java @@ -0,0 +1,36 @@ +package cn.bunny.dao.vo.log; + +import cn.bunny.dao.common.vo.BaseUserVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "QuartzExecuteLogVo对象", title = "调度任务执行日志返回对象", description = "调度任务执行日志返回对象") +public class QuartzExecuteLogVo extends BaseUserVo { + + @Schema(name = "jobName", title = "任务名称") + private String jobName; + + @Schema(name = "jobGroup", title = "任务分组") + private String jobGroup; + + @Schema(name = "jobClassName", title = "执行任务类名") + private String jobClassName; + + @Schema(name = "cronExpression", title = "执行任务core表达式") + private String cronExpression; + + @Schema(name = "triggerName", title = "触发器名称") + private String triggerName; + + @Schema(name = "executeResult", title = "执行结果") + private String executeResult; + + @Schema(name = "duration", title = "执行时间") + private Integer duration; + +} diff --git a/dao/src/main/java/cn/bunny/dao/vo/log/UserLoginLogLocalVo.java b/dao/src/main/java/cn/bunny/dao/vo/log/UserLoginLogLocalVo.java new file mode 100644 index 0000000..2afde05 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/vo/log/UserLoginLogLocalVo.java @@ -0,0 +1,41 @@ +package cn.bunny.dao.vo.log; + +import cn.bunny.dao.common.vo.BaseVo; +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "UserLoginLogLocalVo对象", title = "用户登录日志", description = "用户登录日志") +public class UserLoginLogLocalVo extends BaseVo { + + @Schema(name = "userId", title = "用户Id") + private Long userId; + + @Schema(name = "username", title = "用户名") + private String username; + + @Schema(name = "token", title = "登录token") + private String token; + + @Schema(name = "ipAddress", title = "登录Ip") + private String ipAddress; + + @Schema(name = "ipRegion", title = "登录Ip归属地") + private String ipRegion; + + @Schema(name = "userAgent", title = "登录时代理") + private String userAgent; + + @Schema(name = "type", title = "操作类型") + private String type; + + @Schema(name = "xRequestedWith", title = "标识客户端是否是通过Ajax发送请求的") + @JsonProperty("xRequestedWith") + private String xRequestedWith; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/vo/log/UserLoginLogVo.java b/dao/src/main/java/cn/bunny/dao/vo/log/UserLoginLogVo.java new file mode 100644 index 0000000..02171ee --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/vo/log/UserLoginLogVo.java @@ -0,0 +1,41 @@ +package cn.bunny.dao.vo.log; + +import cn.bunny.dao.common.vo.BaseUserVo; +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "UserLoginLogVo对象", title = "用户登录日志", description = "用户登录日志") +public class UserLoginLogVo extends BaseUserVo { + + @Schema(name = "userId", title = "用户Id") + private Long userId; + + @Schema(name = "username", title = "用户名") + private String username; + + @Schema(name = "token", title = "登录token") + private String token; + + @Schema(name = "ipAddress", title = "登录Ip") + private String ipAddress; + + @Schema(name = "ipRegion", title = "登录Ip归属地") + private String ipRegion; + + @Schema(name = "userAgent", title = "登录时代理") + private String userAgent; + + @Schema(name = "type", title = "操作类型") + private String type; + + @Schema(name = "xRequestedWith", title = "标识客户端是否是通过Ajax发送请求的") + @JsonProperty("xRequestedWith") + private String xRequestedWith; + +} diff --git a/dao/src/main/java/cn/bunny/dao/vo/quartz/SchedulersGroupVo.java b/dao/src/main/java/cn/bunny/dao/vo/quartz/SchedulersGroupVo.java new file mode 100644 index 0000000..e07f4cc --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/vo/quartz/SchedulersGroupVo.java @@ -0,0 +1,21 @@ +package cn.bunny.dao.vo.quartz; + +import cn.bunny.dao.common.vo.BaseUserVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "SchedulersGroupVo", title = "任务调度分组返回对象", description = "任务调度分组返回对象") +public class SchedulersGroupVo extends BaseUserVo { + + @Schema(name = "groupName", title = "分组名称") + private String groupName; + + @Schema(name = "description", title = "分组详情") + private String description; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/vo/quartz/SchedulersVo.java b/dao/src/main/java/cn/bunny/dao/vo/quartz/SchedulersVo.java new file mode 100644 index 0000000..6110b36 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/vo/quartz/SchedulersVo.java @@ -0,0 +1,39 @@ +package cn.bunny.dao.vo.quartz; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "SchedulersVo对象", title = "Schedulers返回内容", description = "Schedulers返回内容") +public class SchedulersVo { + + @Schema(name = "jobName", title = "任务名称") + private String jobName; + + @Schema(name = "jobGroup", title = "任务分组") + private String jobGroup; + + @Schema(name = "description", title = "任务详情") + private String description; + + @Schema(name = "jobClassName", title = "任务类名称") + @NotNull(message = "corn表达式不能为空") + private String jobClassName; + + @Schema(name = "triggerName", title = "触发器名称") + private String triggerName; + + @Schema(name = "triggerState", title = "triggerState触发器状态") + private String triggerState; + + @Schema(name = "cronExpression", title = "corn表达式") + private String cronExpression; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/vo/system/DeptVo.java b/dao/src/main/java/cn/bunny/dao/vo/system/DeptVo.java new file mode 100644 index 0000000..deb00f6 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/vo/system/DeptVo.java @@ -0,0 +1,27 @@ +package cn.bunny.dao.vo.system; + +import cn.bunny.dao.common.vo.BaseUserVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "DeptVo对象", title = "部门", description = "部门管理") +public class DeptVo extends BaseUserVo { + + @Schema(name = "parentId", title = "父级id") + private String parentId; + + @Schema(name = "manager", title = "管理者") + private String manager; + + @Schema(name = "deptName", title = "部门名称") + private String deptName; + + @Schema(name = "summary", title = "部门简介") + private String summary; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/vo/system/MenuIconVo.java b/dao/src/main/java/cn/bunny/dao/vo/system/MenuIconVo.java new file mode 100644 index 0000000..0c7994c --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/vo/system/MenuIconVo.java @@ -0,0 +1,21 @@ +package cn.bunny.dao.vo.system; + +import cn.bunny.dao.common.vo.BaseUserVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "MenuIconVo对象", title = "系统菜单图标", description = "系统菜单图标") +public class MenuIconVo extends BaseUserVo { + + @Schema(name = "iconCode", title = "icon类名") + private String iconCode; + + @Schema(name = "iconName", title = "icon 名称") + private String iconName; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/vo/system/configuration/WebConfigurationVo.java b/dao/src/main/java/cn/bunny/dao/vo/system/configuration/WebConfigurationVo.java new file mode 100644 index 0000000..8ddc1b5 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/vo/system/configuration/WebConfigurationVo.java @@ -0,0 +1,121 @@ +package cn.bunny.dao.vo.system.configuration; + +import com.alibaba.fastjson2.annotation.JSONField; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "WebConfigurationVo对象", title = "前端配置选项", description = "前端配置选项") +public class WebConfigurationVo { + + @Schema(name = "Version", description = "应用程序的版本") + @JSONField(format = "Version") + private String version; + + @Schema(name = "Title", description = "应用程序的标题") + @JSONField(format = "Title") + private String title; + + @Schema(name = "Copyright", description = "版权信息") + @JSONField(format = "Copyright") + private String copyright; + + @Schema(name = "FixedHeader", description = "头部是否固定") + @JSONField(format = "FixedHeader") + private boolean fixedHeader; + + @Schema(name = "HiddenSideBar", description = "侧边栏是否隐藏") + @JSONField(format = "FixedHeader") + private boolean hiddenSideBar; + + @Schema(name = "MultiTagsCache", description = "是否缓存多个标签") + @JSONField(format = "FixedHeader") + private boolean multiTagsCache; + + @Schema(name = "KeepAlive", description = "是否持久化") + @JSONField(format = "FixedHeader") + private boolean keepAlive; + + @Schema(name = "Locale", description = "语言类型") + @JSONField(format = "Locale") + private String locale; + + @Schema(name = "Layout", description = "应用程序的布局") + @JSONField(name = "Layout") + private String layout; + + @Schema(name = "Theme", description = "应用程序的主题") + @JSONField(format = "FixedHeader") + private String theme; + + @Schema(name = "DarkMode", description = "是否启用深色模式") + @JSONField(format = "FixedHeader") + private boolean darkMode; + + @Schema(name = "OverallStyle", description = "应用程序的整体样式") + @JSONField(format = "FixedHeader") + private String overallStyle; + + @Schema(name = "Grey", description = "是否启用灰色模式") + @JSONField(format = "FixedHeader") + private boolean grey; + + @Schema(name = "Weak", description = "色弱模式") + @JSONField(format = "FixedHeader") + private boolean weak; + + @Schema(name = "HideTabs", description = "是否隐藏选项卡") + @JSONField(format = "HideTabs") + private boolean hideTabs; + + @Schema(name = "HideFooter", description = "是否隐藏页脚") + @JSONField(format = "HideFooter") + private boolean hideFooter; + + @Schema(name = "Stretch", description = "是否拉伸显示") + @JSONField(format = "Stretch") + private boolean stretch; + + @Schema(name = "SidebarStatus", description = "侧边栏的状态") + @JSONField(format = "SidebarStatus") + private boolean sidebarStatus; + + @Schema(name = "EpThemeColor", description = "主题颜色") + @JSONField(format = "EpThemeColor") + private String epThemeColor; + + @Schema(name = "ShowLogo", description = "是否显示logo") + @JSONField(format = "ShowLogo") + private boolean showLogo; + + @Schema(name = "ShowModel", description = "要显示的模型") + @JSONField(format = "ShowModel") + private String showModel; + + @Schema(name = "MenuArrowIconNoTransition", description = "菜单箭头图标是否没有过渡效果") + @JSONField(format = "MenuArrowIconNoTransition") + private boolean menuArrowIconNoTransition; + + @Schema(name = "CachingAsyncRoutes", description = "是否缓存异步路由") + @JSONField(format = "CachingAsyncRoutes") + private boolean cachingAsyncRoutes; + + @Schema(name = "TooltipEffect", description = "工具提示的效果") + @JSONField(format = "TooltipEffect") + private String tooltipEffect; + + @Schema(name = "ResponsiveStorageNameSpace", description = "响应式存储的命名空间") + @JSONField(format = "ResponsiveStorageNameSpace") + private String responsiveStorageNameSpace; + + @Schema(name = "MenuSearchHistory", description = "菜单搜索历史") + @JSONField(format = "MenuSearchHistory") + private int menuSearchHistory; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/vo/system/email/EmailTemplateVo.java b/dao/src/main/java/cn/bunny/dao/vo/system/email/EmailTemplateVo.java new file mode 100644 index 0000000..6f59fa8 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/vo/system/email/EmailTemplateVo.java @@ -0,0 +1,41 @@ +package cn.bunny.dao.vo.system.email; + +import cn.bunny.dao.common.vo.BaseUserVo; +import com.alibaba.fastjson2.annotation.JSONField; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "EmailTemplateVo对象", title = "邮箱模板返回内容", description = "邮箱模板返回内容") +public class EmailTemplateVo extends BaseUserVo { + + @Schema(name = "templateName", title = "模板名称") + private String templateName; + + @Schema(name = "emailUser", title = "配置邮件用户") + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JSONField(serializeUsing = ToStringSerializer.class) + private Long emailUser; + + @Schema(name = "emailUsername", title = "邮箱账户") + private String emailUsername; + + @Schema(name = "subject", title = "主题") + private String subject; + + @Schema(name = "body", title = "邮件内容") + private String body; + + @Schema(name = "type", title = "邮件类型") + private String type; + + @Schema(name = "isDefault", title = "是否默认") + private Boolean isDefault; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/vo/system/email/EmailUsersVo.java b/dao/src/main/java/cn/bunny/dao/vo/system/email/EmailUsersVo.java new file mode 100644 index 0000000..bd647dc --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/vo/system/email/EmailUsersVo.java @@ -0,0 +1,33 @@ +package cn.bunny.dao.vo.system.email; + +import cn.bunny.dao.common.vo.BaseUserVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "EmailUsersVo对象", title = "邮箱用户发送配置", description = "邮箱用户发送配置管理") +public class EmailUsersVo extends BaseUserVo { + + @Schema(name = "email", title = "邮箱") + private String email; + + @Schema(name = "password", title = "密码") + private String password; + + @Schema(name = "host", title = "Host地址") + private String host; + + @Schema(name = "port", title = "端口号") + private Integer port; + + @Schema(name = "smtpAgreement", title = "邮箱协议") + private String smtpAgreement; + + @Schema(name = "isDefault", title = "是否为默认邮件") + private Boolean isDefault; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/vo/system/files/FileInfoVo.java b/dao/src/main/java/cn/bunny/dao/vo/system/files/FileInfoVo.java new file mode 100644 index 0000000..4a31b19 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/vo/system/files/FileInfoVo.java @@ -0,0 +1,36 @@ +package cn.bunny.dao.vo.system.files; + +import cn.bunny.dao.common.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +/** + * 返回文件信息 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "FileInfoVo对象", title = "管理端返回文件信息", description = "管理端返回文件信息") +public class FileInfoVo extends BaseVo { + + @Schema(name = "url", title = "文件的路径") + private String url; + + @Schema(name = "filename", title = "文件的名称") + private String filename; + + @Schema(name = "filepath", title = "文件在服务器上的存储路径") + private String filepath; + + @Schema(name = "fileSize", title = "文件的大小,以字节为单位") + private Long fileSize; + + @Schema(name = "size", title = "文件大小") + private String size; + + @Schema(name = "fileType", title = "文件的MIME类型") + private String fileType; + +} diff --git a/dao/src/main/java/cn/bunny/dao/vo/system/files/FilesVo.java b/dao/src/main/java/cn/bunny/dao/vo/system/files/FilesVo.java new file mode 100644 index 0000000..449d05c --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/vo/system/files/FilesVo.java @@ -0,0 +1,30 @@ +package cn.bunny.dao.vo.system.files; + +import cn.bunny.dao.common.vo.BaseUserVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "FilesVo对象", title = "系统文件", description = "管理端系统文件返回信息") +public class FilesVo extends BaseUserVo { + + @Schema(name = "filename", title = "文件的名称") + private String filename; + + @Schema(name = "filepath", title = "文件在服务器上的存储路径") + private String filepath; + + @Schema(name = "fileSize", title = "文件的大小,以字节为单位") + private Long fileSize; + + @Schema(name = "fileType", title = "文件的MIME类型") + private String fileType; + + @Schema(name = "downloadCount", title = "下载数量") + private Integer downloadCount; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/vo/system/message/MessageDetailVo.java b/dao/src/main/java/cn/bunny/dao/vo/system/message/MessageDetailVo.java new file mode 100644 index 0000000..4a97c9e --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/vo/system/message/MessageDetailVo.java @@ -0,0 +1,45 @@ +package cn.bunny.dao.vo.system.message; + +import cn.bunny.dao.common.vo.BaseUserVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "MessageDetailVo对象", title = "系统消息详情返回内容", description = "系统消息详情返回内容") +public class MessageDetailVo extends BaseUserVo { + + @Schema(name = "title", title = "消息标题") + private String title; + + @Schema(name = "sendUserId", title = "发送人用户ID") + private Long sendUserId; + + @Schema(name = "messageType", title = "sys:系统消息,user用户消息") + private String messageType; + + @Schema(name = "cover", title = "封面") + private String cover; + + @Schema(name = "summary", title = "消息简介") + private String summary; + + @Schema(name = "content", title = "消息内容") + private String content; + + @Schema(name = "editorType", title = "编辑器类型") + private String editorType; + + @Schema(name = "level", title = "消息等级") + private String level; + + @Schema(name = "extra", title = "消息等级详情") + private String extra; + + @Schema(name = "sendNickname", title = "发送人昵称") + private String sendNickname; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/vo/system/message/MessageReceivedWithMessageVo.java b/dao/src/main/java/cn/bunny/dao/vo/system/message/MessageReceivedWithMessageVo.java new file mode 100644 index 0000000..5a3b9f6 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/vo/system/message/MessageReceivedWithMessageVo.java @@ -0,0 +1,76 @@ +package cn.bunny.dao.vo.system.message; + +import cn.bunny.dao.common.vo.BaseUserVo; +import com.alibaba.fastjson2.annotation.JSONField; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "MessageReceivedWithMessageVo对象", title = "消息内容和消息接受", description = "消息内容和消息接受") +public class MessageReceivedWithMessageVo extends BaseUserVo { + + @Schema(name = "id", title = "消息接受id") + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JSONField(serializeUsing = ToStringSerializer.class) + private Long id; + + @Schema(name = "messageId", title = "消息id") + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JSONField(serializeUsing = ToStringSerializer.class) + private Long messageId; + + @Schema(name = "receivedUserId", title = "接收人用户ID") + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JSONField(serializeUsing = ToStringSerializer.class) + private String receivedUserId; + + @Schema(name = "receivedUserNickname", title = "接收人用户昵称") + private String receivedUserNickname; + + @Schema(name = "messageTypeId", title = "消息类型id") + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JSONField(serializeUsing = ToStringSerializer.class) + private String messageTypeId; + + @Schema(name = "messageType", title = "消息类型") + private String messageType; + + @Schema(name = "title", title = "消息标题") + private String title; + + @Schema(name = "sendUserId", title = "发送人用户ID") + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JSONField(serializeUsing = ToStringSerializer.class) + private Long sendUserId; + + @Schema(name = "sendNickname", title = "发送人昵称") + private String sendNickname; + + @Schema(name = "cover", title = "封面") + private String cover; + + @Schema(name = "summary", title = "消息简介") + private String summary; + + @Schema(name = "content", title = "消息内容") + private String content; + + @Schema(name = "editorType", title = "编辑器类型") + private String editorType; + + @Schema(name = "status", title = "0:未读 1:已读") + private Boolean status; + + @Schema(name = "level", title = "消息等级") + private String level; + + @Schema(name = "extra", title = "消息等级详情") + private String extra; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/vo/system/message/MessageReceivedWithUserVo.java b/dao/src/main/java/cn/bunny/dao/vo/system/message/MessageReceivedWithUserVo.java new file mode 100644 index 0000000..4f888cb --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/vo/system/message/MessageReceivedWithUserVo.java @@ -0,0 +1,35 @@ +package cn.bunny.dao.vo.system.message; + +import com.alibaba.fastjson2.annotation.JSONField; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "MessageReceivedWithUser对象", title = "用户消息接受", description = "用户消息接受") +public class MessageReceivedWithUserVo { + + @Schema(name = "receivedUserId", title = "接受者id") + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JSONField(serializeUsing = ToStringSerializer.class) + private Long receivedUserId; + + @Schema(name = "messageId", title = "消息ID") + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JSONField(serializeUsing = ToStringSerializer.class) + private Long messageId; + + @Schema(name = "username", title = "用户名") + private String username; + + @Schema(name = "nickname", title = "昵称") + private String nickname; + +} diff --git a/dao/src/main/java/cn/bunny/dao/vo/system/message/MessageTypeVo.java b/dao/src/main/java/cn/bunny/dao/vo/system/message/MessageTypeVo.java new file mode 100644 index 0000000..bcd697b --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/vo/system/message/MessageTypeVo.java @@ -0,0 +1,27 @@ +package cn.bunny.dao.vo.system.message; + +import cn.bunny.dao.common.vo.BaseUserVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "MessageTypeVo对象", title = "系统消息类型", description = "系统消息类型") +public class MessageTypeVo extends BaseUserVo { + + @Schema(name = "messageName", title = "消息名称") + private String messageName; + + @Schema(name = "messageType", title = "sys:系统消息,user用户消息") + private String messageType; + + @Schema(name = "summary", title = "消息备注") + private String summary; + + @Schema(name = "status", title = "消息状态") + private Boolean status; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/vo/system/message/MessageUserVo.java b/dao/src/main/java/cn/bunny/dao/vo/system/message/MessageUserVo.java new file mode 100644 index 0000000..b7a2f9c --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/vo/system/message/MessageUserVo.java @@ -0,0 +1,63 @@ +package cn.bunny.dao.vo.system.message; + +import cn.bunny.dao.common.vo.BaseVo; +import com.alibaba.fastjson2.annotation.JSONField; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +import java.time.LocalDateTime; + +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "MessageVo对象", title = "系统消息返回内容", description = "系统消息返回内容") +public class MessageUserVo extends BaseVo { + + @Schema(name = "id", title = "消息messageId") + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JSONField(serializeUsing = ToStringSerializer.class) + private Long id; + + @Schema(name = "messageReceivedId", title = "用户消息表id") + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JSONField(serializeUsing = ToStringSerializer.class) + private Long messageReceivedId; + + @Schema(name = "title", title = "消息标题") + private String title; + + @Schema(name = "messageType", title = "消息类型") + private String messageType; + + @Schema(name = "cover", title = "封面") + private String cover; + + @Schema(name = "summary", title = "消息简介") + private String summary; + + @Schema(name = "level", title = "消息等级") + private String level; + + @Schema(name = "extra", title = "消息等级详情") + private String extra; + + @Schema(name = "status", title = "消息状态") + private Boolean status; + + @Schema(name = "updateTime", title = "更新时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonSerialize(using = LocalDateTimeSerializer.class) + @JsonDeserialize(using = LocalDateTimeDeserializer.class) + @JsonProperty("acceptanceTime") + private LocalDateTime updateTime; + +} diff --git a/dao/src/main/java/cn/bunny/dao/vo/system/message/MessageVo.java b/dao/src/main/java/cn/bunny/dao/vo/system/message/MessageVo.java new file mode 100644 index 0000000..98aa8ea --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/vo/system/message/MessageVo.java @@ -0,0 +1,68 @@ +package cn.bunny.dao.vo.system.message; + +import cn.bunny.dao.common.vo.BaseUserVo; +import com.alibaba.fastjson2.annotation.JSONField; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +import java.util.List; + +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "MessageVo对象", title = "系统消息返回内容", description = "系统消息返回内容") +public class MessageVo extends BaseUserVo { + + @Schema(name = "receivedUserId", title = "接收人用户ID") + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JSONField(serializeUsing = ToStringSerializer.class) + private List receivedUserId; + + @Schema(name = "receivedUserNickname", title = "接收人用户昵称") + private List receivedUserNickname; + + @Schema(name = "title", title = "消息标题") + private String title; + + @Schema(name = "sendUserId", title = "发送人用户ID") + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JSONField(serializeUsing = ToStringSerializer.class) + private Long sendUserId; + + @Schema(name = "sendNickname", title = "发送人昵称") + private String sendNickname; + + @Schema(name = "messageTypeId", title = "消息类型id") + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JSONField(serializeUsing = ToStringSerializer.class) + private String messageTypeId; + + @Schema(name = "messageType", title = "sys:系统消息,user用户消息") + private String messageType; + + @Schema(name = "cover", title = "封面") + private String cover; + + @Schema(name = "summary", title = "消息简介") + private String summary; + + @Schema(name = "content", title = "消息内容") + private String content; + + @Schema(name = "editorType", title = "编辑器类型") + private String editorType; + + @Schema(name = "level", title = "消息等级") + private String level; + + @Schema(name = "extra", title = "消息等级详情") + private String extra; + +} + + + diff --git a/dao/src/main/java/cn/bunny/dao/vo/system/rolePower/PowerVo.java b/dao/src/main/java/cn/bunny/dao/vo/system/rolePower/PowerVo.java new file mode 100644 index 0000000..663df35 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/vo/system/rolePower/PowerVo.java @@ -0,0 +1,37 @@ +package cn.bunny.dao.vo.system.rolePower; + +import cn.bunny.dao.common.vo.BaseUserVo; +import com.alibaba.fastjson2.annotation.JSONField; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +import java.util.List; + +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "PowerVo对象", title = "权限", description = "权限管理") +public class PowerVo extends BaseUserVo { + + @Schema(name = "parentId", title = "父级id") + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JSONField(serializeUsing = ToStringSerializer.class) + private Long parentId; + + @Schema(name = "parentId", title = "权限编码") + private String powerCode; + + @Schema(name = "powerName", title = "权限名称") + private String powerName; + + @Schema(name = "requestUrl", title = "请求路径") + private String requestUrl; + + @Schema(name = "children", title = "子级") + private List children; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/vo/system/rolePower/RoleVo.java b/dao/src/main/java/cn/bunny/dao/vo/system/rolePower/RoleVo.java new file mode 100644 index 0000000..dfbeb09 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/vo/system/rolePower/RoleVo.java @@ -0,0 +1,23 @@ +package cn.bunny.dao.vo.system.rolePower; + +import cn.bunny.dao.common.vo.BaseUserVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "RoleVo对象", title = "角色", description = "角色管理") +public class RoleVo extends BaseUserVo { + + @Schema(name = "roleCode", title = "角色代码") + private String roleCode; + + @Schema(name = "description", title = "描述") + private String description; + +} + + diff --git a/dao/src/main/java/cn/bunny/dao/vo/system/router/RouterManageVo.java b/dao/src/main/java/cn/bunny/dao/vo/system/router/RouterManageVo.java new file mode 100644 index 0000000..ee47ee9 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/vo/system/router/RouterManageVo.java @@ -0,0 +1,61 @@ +package cn.bunny.dao.vo.system.router; + +import cn.bunny.dao.common.vo.BaseUserVo; +import com.alibaba.fastjson2.annotation.JSONField; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import jakarta.validation.constraints.NotBlank; +import lombok.*; + +import java.util.List; + +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@ApiModel(value = "RouterControllerVo对象", description = "路由管理端返回对象") +public class RouterManageVo extends BaseUserVo { + + @ApiModelProperty("父级id") + @JsonProperty("parentId") + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JSONField(serializeUsing = ToStringSerializer.class) + private Long parentId; + + @ApiModelProperty("在项目中路径") + private String path; + + @ApiModelProperty("组件位置") + private String component; + + @ApiModelProperty("frame路径") + private String frameSrc; + + @ApiModelProperty("路由名称") + @NotBlank(message = "路由名称不能为空") + @JsonProperty("name") + private String routeName; + + @ApiModelProperty("路由title") + private String title; + + @ApiModelProperty("菜单类型") + private Integer menuType; + + @ApiModelProperty("图标") + private String icon; + + @ApiModelProperty("等级") + @JsonProperty("rank") + private Integer routerRank; + + @ApiModelProperty("是否显示") + private Boolean visible; + + @ApiModelProperty("子路由") + private List children; +} diff --git a/dao/src/main/java/cn/bunny/dao/vo/system/router/RouterMeta.java b/dao/src/main/java/cn/bunny/dao/vo/system/router/RouterMeta.java new file mode 100644 index 0000000..f21e63e --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/vo/system/router/RouterMeta.java @@ -0,0 +1,37 @@ +package cn.bunny.dao.vo.system.router; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@ApiModel(value = "UserRouterMetaVo对象", description = "系统属性内容") +public class RouterMeta { + + @ApiModelProperty(value = "图标") + private String icon; + + @ApiModelProperty(value = "标题") + private String title; + + @ApiModelProperty(value = "排序权重") + private Integer rank; + + @ApiModelProperty(value = "角色列表") + private List roles; + + @ApiModelProperty(value = "权限列表") + private List auths; + + @ApiModelProperty("frame路径") + private String frameSrc; + +} diff --git a/dao/src/main/java/cn/bunny/dao/vo/system/router/UserRouterVo.java b/dao/src/main/java/cn/bunny/dao/vo/system/router/UserRouterVo.java new file mode 100644 index 0000000..c473a31 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/vo/system/router/UserRouterVo.java @@ -0,0 +1,61 @@ +package cn.bunny.dao.vo.system.router; + +import com.alibaba.fastjson2.annotation.JSONField; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@ApiModel(value = "UserRouterVo对象", description = "系统菜单表") +public class UserRouterVo { + + @Schema(name = "id", title = "主键") + @JsonProperty("id") + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JSONField(serializeUsing = ToStringSerializer.class) + private Long id; + + @ApiModelProperty("菜单类型") + private Integer menuType; + + @ApiModelProperty("父级id") + @JsonProperty("parentId") + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JSONField(serializeUsing = ToStringSerializer.class) + private Long parentId; + + @ApiModelProperty("菜单名称") + private String title; + + @ApiModelProperty("路由名称") + @JsonProperty("name") + private String routeName; + + @ApiModelProperty("在项目中路径") + private String path; + + @ApiModelProperty("组件位置") + private String component; + + @ApiModelProperty("等级") + @JsonProperty("rank") + private Integer routerRank; + + @ApiModelProperty("路由Meta") + private RouterMeta meta; + + @ApiModelProperty("子路由") + private List children; +} diff --git a/dao/src/main/java/cn/bunny/dao/vo/system/user/AdminUserVo.java b/dao/src/main/java/cn/bunny/dao/vo/system/user/AdminUserVo.java new file mode 100644 index 0000000..f884fca --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/vo/system/user/AdminUserVo.java @@ -0,0 +1,52 @@ +package cn.bunny.dao.vo.system.user; + +import cn.bunny.dao.common.vo.BaseUserVo; +import com.alibaba.fastjson2.annotation.JSONField; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "AdminUserVo对象", title = "用户信息", description = "用户信息") +public class AdminUserVo extends BaseUserVo { + + @Schema(name = "username", title = "用户名") + private String username; + + @Schema(name = "nickname", title = "昵称") + private String nickname; + + @Schema(name = "email", title = "邮箱") + private String email; + + @Schema(name = "phone", title = "手机号") + private String phone; + + @Schema(name = "avatar", title = "头像") + private String avatar; + + @Schema(name = "sex", title = "性别", description = "0:女 1:男") + private Byte sex; + + @Schema(name = "summary", title = "个人描述") + private String summary; + + @Schema(name = "ipAddress", title = "登录Ip") + private String ipAddress; + + @Schema(name = "ipRegion", title = "登录Ip归属地") + private String ipRegion; + + @Schema(name = "deptId", title = "部门") + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JSONField(serializeUsing = ToStringSerializer.class) + private Long deptId; + + @Schema(name = "status", title = "状态", description = "1:禁用 0:正常") + private Boolean status; +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/vo/system/user/LoginVo.java b/dao/src/main/java/cn/bunny/dao/vo/system/user/LoginVo.java new file mode 100644 index 0000000..e81fc5e --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/vo/system/user/LoginVo.java @@ -0,0 +1,72 @@ +package cn.bunny.dao.vo.system.user; + +import cn.bunny.dao.common.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +import java.util.ArrayList; +import java.util.List; + +/** + * 用户登录返回内容 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "LoginVo对象", title = "登录成功返回内容", description = "登录成功返回内容") +public class LoginVo extends BaseVo { + + @Schema(name = "nickname", title = "昵称") + private String nickname; + + @Schema(name = "username", title = "用户名") + private String username; + + @Schema(name = "email", title = "邮箱") + private String email; + + @Schema(name = "phone", title = "手机号") + private String phone; + + @Schema(name = "password", title = "密码") + private String password; + + @Schema(name = "avatar", title = "头像") + private String avatar; + + @Schema(name = "sex", title = "0:女 1:男") + private Byte sex; + + @Schema(name = "personDescription", title = "个人描述") + private String personDescription; + + @Schema(name = "ipAddress", title = "登录Ip") + private String ipAddress; + + @Schema(name = "ipRegion", title = "登录Ip归属地") + private String ipRegion; + + @Schema(name = "status", title = "1:禁用 0:正常") + private Boolean status; + + @Schema(name = "token", title = "令牌") + private String token; + + @Schema(name = "refreshToken", title = "刷新token") + private String refreshToken; + + @Schema(name = "expires", title = "过期时间") + private String expires; + + @Schema(name = "roleList", title = "角色列表") + private List roles = new ArrayList<>(); + + @Schema(name = "powerList", title = "权限列表") + private List permissions = new ArrayList<>(); + + @Schema(name = "readMeDay", title = "记住我多久") + private Long readMeDay; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/vo/system/user/RefreshTokenVo.java b/dao/src/main/java/cn/bunny/dao/vo/system/user/RefreshTokenVo.java new file mode 100644 index 0000000..2171aa7 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/vo/system/user/RefreshTokenVo.java @@ -0,0 +1,22 @@ +package cn.bunny.dao.vo.system.user; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.NoArgsConstructor; + +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "RefreshTokenVo 对象", title = "刷新token返回内容", description = "刷新token返回内容") +public class RefreshTokenVo { + + @Schema(name = "accessToken", title = "访问令牌") + private String accessToken; + + @Schema(name = "refreshToken", title = "刷新token") + private String refreshToken; + + @Schema(name = "expires", title = "过期时间") + private String expires; +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/vo/system/user/SearchUserinfoVo.java b/dao/src/main/java/cn/bunny/dao/vo/system/user/SearchUserinfoVo.java new file mode 100644 index 0000000..52a7c8b --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/vo/system/user/SearchUserinfoVo.java @@ -0,0 +1,38 @@ +package cn.bunny.dao.vo.system.user; + +import com.alibaba.fastjson2.annotation.JSONField; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "AdminUserVo对象", title = "用户信息", description = "用户信息") +public class SearchUserinfoVo { + + @Schema(name = "id", title = "主键") + @JsonProperty("id") + @JsonFormat(shape = JsonFormat.Shape.STRING) + @JSONField(serializeUsing = ToStringSerializer.class) + private Long id; + + @Schema(name = "username", title = "用户名") + private String username; + + @Schema(name = "nickname", title = "昵称") + private String nickname; + + @Schema(name = "email", title = "邮箱") + private String email; + + @Schema(name = "phone", title = "手机号") + private String phone; + +} diff --git a/dao/src/main/java/cn/bunny/dao/vo/system/user/UserVo.java b/dao/src/main/java/cn/bunny/dao/vo/system/user/UserVo.java new file mode 100644 index 0000000..cfe7a3a --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/vo/system/user/UserVo.java @@ -0,0 +1,39 @@ +package cn.bunny.dao.vo.system.user; + +import cn.bunny.dao.common.vo.BaseVo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +@Data +@EqualsAndHashCode(callSuper = true) +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "LoginVo对象", title = "登录成功返回内容", description = "登录成功返回内容") +public class UserVo extends BaseVo { + + @Schema(name = "nickname", title = "昵称") + private String nickname; + + @Schema(name = "username", title = "用户名") + private String username; + + @Schema(name = "email", title = "邮箱") + private String email; + + @Schema(name = "phone", title = "手机号") + private String phone; + + @Schema(name = "avatar", title = "头像") + private String avatar; + + @Schema(name = "sex", title = "0:女 1:男") + private Byte sex; + + @Schema(name = "personDescription", title = "个人描述") + private String summary; + + @Schema(name = "status", title = "1:禁用 0:正常") + private Boolean status; + +} diff --git a/dao/src/main/java/cn/bunny/dao/vo/system/user/ValidateCodeVo.java b/dao/src/main/java/cn/bunny/dao/vo/system/user/ValidateCodeVo.java new file mode 100644 index 0000000..9e93e15 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/vo/system/user/ValidateCodeVo.java @@ -0,0 +1,20 @@ +package cn.bunny.dao.vo.system.user; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Schema(description = "验证码响应结果实体类") +public class ValidateCodeVo { + @Schema(description = "验证码key") + private String codeKey; + + @Schema(description = "验证码value") + private String codeValue; +} \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..5917148 --- /dev/null +++ b/pom.xml @@ -0,0 +1,184 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.2.3 + + + cn.bunny + financial-admin-server + 0.0.1-SNAPSHOT + pom + financial-admin-server + financial-admin-server + + + common + dao + service + + + + 17 + 17 + 17 + 3.8.1 + 3.5.6 + 8.0.30 + 4.5.0 + 2.0.47 + 8.5.9 + 1.18.32 + 0.9.1 + 2.10.1 + 1.9.21 + 6.1.0 + 2.2 + 3.1 + 5.1.0 + 4.3.1 + 2.12.3 + 2.3.2 + + + + + + junit + junit + ${junit.version} + + + + org.apache.velocity + velocity-engine-core + ${velocity.version} + + + org.apache.velocity.tools + velocity-tools-generic + ${velocity-tools.version} + + + + com.baomidou + mybatis-plus-spring-boot3-starter + ${mybatis-plus.version} + + + + mysql + mysql-connector-java + ${mysql.version} + + + + com.zaxxer + HikariCP + ${HikariCP.version} + + + + com.baomidou + dynamic-datasource-spring-boot3-starter + ${dynamic.datasource.version} + + + + com.github.xiaoymin + knife4j-openapi3-jakarta-spring-boot-starter + ${knife4j.version} + + + + com.alibaba.fastjson2 + fastjson2 + ${fastjson2.version} + + + + io.minio + minio + ${minio.version} + + + + org.projectlombok + lombok + ${lombok.version} + + + + cn.hutool + hutool-all + 5.8.27 + + + + io.jsonwebtoken + jjwt + ${jwt.version} + + + + org.aspectj + aspectjrt + ${aspectj} + + + + org.aspectj + aspectjweaver + ${aspectj} + + + joda-time + joda-time + ${jodatime.version} + + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-dataType.version} + + + + org.quartz-scheduler + quartz + ${quartz-scheduler.version} + + + + + + + + dev + + dev + + + true + + + + + test + + test + + + + + prod + + prod + + + + + diff --git a/service/pom.xml b/service/pom.xml new file mode 100644 index 0000000..c32eb8d --- /dev/null +++ b/service/pom.xml @@ -0,0 +1,110 @@ + + 4.0.0 + + cn.bunny + financial-admin-server + 0.0.1-SNAPSHOT + + + service + jar + service + https://maven.apache.org + + + UTF-8 + + + + + cn.bunny + service-utils + 0.0.1-SNAPSHOT + + + + org.springframework.boot + spring-boot-starter-security + + + + org.springframework.security + spring-security-test + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-actuator + 3.2.3 + + + + junit + junit + 3.8.1 + + + + org.springframework.boot + spring-boot-starter-test + + + + org.aspectj + aspectjrt + + + org.aspectj + aspectjweaver + + + + org.springframework.boot + spring-boot-starter-websocket + + + + org.quartz-scheduler + quartz + + + com.mchange + c3p0 + 0.9.5.5 + + + + org.springframework + spring-context-support + 6.1.6 + + + + com.alibaba + easyexcel + 4.0.2 + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + + diff --git a/service/src/Dockerfile b/service/src/Dockerfile new file mode 100644 index 0000000..0039cda --- /dev/null +++ b/service/src/Dockerfile @@ -0,0 +1,35 @@ +FROM openjdk:24-ea-17-jdk-oraclelinux9 +MAINTAINER server + +#系统编码 +ENV LANG=C.UTF-8 LC_ALL=C.UTF-8 + +# 设置时区,构建镜像时执行的命令 +RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime +RUN echo "Asia/Shanghai" > /etc/timezone + +# 设定工作目录 +WORKDIR /home/server + +# 复制jar包 +COPY target/*.jar /home/server/app.jar + +# 程序内部挂在目录 +VOLUME /usr/bin/docker +VOLUME ["/var/run/docker.sock"] +VOLUME /etc/docker/daemon.json +VOLUME ["/www/root/backup"] +VOLUME ["/www/root/server"] + +# 启动容器时的进程 +ENTRYPOINT ["java","-jar","/home/server/app.jar"] + +#暴露 8000 端口 +EXPOSE 8000 + +# 生产环境 +# mvn clean package -Pprod -DskipTests + +# 测试环境 +# mvn clean package -Ptest -DskipTests + diff --git a/service/src/main/java/cn/bunny/services/ServiceApplication.java b/service/src/main/java/cn/bunny/services/ServiceApplication.java new file mode 100644 index 0000000..32c058e --- /dev/null +++ b/service/src/main/java/cn/bunny/services/ServiceApplication.java @@ -0,0 +1,23 @@ +package cn.bunny.services; + +import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +@MapperScan("cn.bunny.services.mapper") +@ComponentScan("cn.bunny") +@EnableScheduling +@EnableCaching +@EnableTransactionManagement +@Slf4j +@SpringBootApplication +public class ServiceApplication { + public static void main(String[] args) { + SpringApplication.run(ServiceApplication.class, args); + } +} diff --git a/service/src/main/java/cn/bunny/services/aop/AnnotationScanner.java b/service/src/main/java/cn/bunny/services/aop/AnnotationScanner.java new file mode 100644 index 0000000..84ad11a --- /dev/null +++ b/service/src/main/java/cn/bunny/services/aop/AnnotationScanner.java @@ -0,0 +1,43 @@ +package cn.bunny.services.aop; + +import cn.bunny.common.service.exception.BunnyException; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; +import org.springframework.core.type.filter.AnnotationTypeFilter; +import org.springframework.stereotype.Component; + +import java.lang.annotation.Annotation; +import java.util.HashSet; +import java.util.Set; + +/** + * * 扫描指定目录下所有类 + */ +@Component +public class AnnotationScanner { + + @SuppressWarnings("unchecked") + public Set> getClassesWithAnnotation(Class annotation) { + // 设置是否延迟初始化 + ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false); + // 只需要带有 Annotation 注解类的内容 + scanner.addIncludeFilter(new AnnotationTypeFilter((Class) annotation)); + + // 扫描到的内容,排除重复的内容 + Set> classes = new HashSet<>(); + + // 只要 cn.bunny.services 包下面的全部内容 + for (BeanDefinition bd : scanner.findCandidateComponents("cn.bunny.services")) { + try { + // 通过反射加载类,并将类名转换为 Class 对象 + Class clazz = Class.forName(bd.getBeanClassName()); + classes.add(clazz); + } catch (ClassNotFoundException e) { + throw new BunnyException(ResultCodeEnum.CLASS_NOT_FOUND); + } + } + + return classes; + } +} \ No newline at end of file diff --git a/service/src/main/java/cn/bunny/services/aop/JobExecuteAop.java b/service/src/main/java/cn/bunny/services/aop/JobExecuteAop.java new file mode 100644 index 0000000..65e9da3 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/aop/JobExecuteAop.java @@ -0,0 +1,108 @@ +package cn.bunny.services.aop; + +import cn.bunny.dao.entity.log.ScheduleExecuteLog; +import cn.bunny.dao.entity.log.ScheduleExecuteLogJson; +import cn.bunny.dao.pojo.constant.LocalDateTimeConstant; +import cn.bunny.dao.pojo.enums.JobEnums; +import cn.bunny.services.mapper.schedule.ScheduleExecuteLogMapper; +import com.alibaba.fastjson2.JSON; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.quartz.Job; +import org.quartz.JobExecutionContext; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.time.Duration; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Map; + +@Aspect +@Component +public class JobExecuteAop { + + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(LocalDateTimeConstant.YYYY_MM_DD_HH_MM_SS); + + @Autowired + private ScheduleExecuteLogMapper scheduleExecuteLogMapper; + + @Around(value = "pointCut()") + public Object aroundMethod(ProceedingJoinPoint joinPoint) { + Object result; + Object[] args = joinPoint.getArgs(); + JobExecutionContext context = (JobExecutionContext) args[0]; + + // 存储到任务调度日志中 + ScheduleExecuteLog executeLog = new ScheduleExecuteLog(); + ScheduleExecuteLogJson executeLogJson = new ScheduleExecuteLogJson(); + + // 格式化时间 + LocalDateTime startLocalDateTime = LocalDateTime.now(); + String startExecuteTIme = startLocalDateTime.format(dateTimeFormatter); + + // 获取上下文map集合 + Map jobDataMap = context.getJobDetail().getJobDataMap().getWrappedMap(); + String jobName = String.valueOf(jobDataMap.get("jobName")); + String jobGroup = String.valueOf(jobDataMap.get("jobGroup")); + String cronExpression = String.valueOf(jobDataMap.get("cronExpression")); + String triggerName = String.valueOf(jobDataMap.get("triggerName")); + Class jobClass = context.getJobDetail().getJobClass(); + + try { + // 开始执行 + executeLog.setJobName(jobName); + executeLog.setJobGroup(jobGroup); + executeLog.setJobClassName(jobClass.getName()); + executeLog.setCronExpression(cronExpression); + executeLog.setTriggerName(triggerName); + // 设置状态结果 + executeLogJson.setResult(JobEnums.UNFINISHED.getType()); + executeLogJson.setStatus(JobEnums.RUNNING.getType()); + executeLogJson.setMessage(JobEnums.RUNNING.getSummary()); + executeLogJson.setOperationTime(startExecuteTIme); + executeLogJson.setExecuteParams(jobDataMap); + executeLog.setExecuteResult(JSON.toJSONString(executeLogJson)); + scheduleExecuteLogMapper.insert(executeLog); + + // 执行... + result = joinPoint.proceed(); + + // 设置执行结果-执行任务的日志 + executeLogJson.setResult(JobEnums.FINISH.getType()); + executeLogJson.setStatus(JobEnums.FINISH.getType()); + executeLogJson.setMessage(JobEnums.FINISH.getSummary()); + setEndExecuteLog(executeLogJson, executeLog, startLocalDateTime); + } catch (Throwable e) { + // 设置执行结果-执行任务的日志 + executeLogJson.setResult(JobEnums.ERROR.getType()); + executeLogJson.setStatus(JobEnums.ERROR.getType()); + executeLogJson.setMessage(e.getMessage()); + setEndExecuteLog(executeLogJson, executeLog, startLocalDateTime); + throw new RuntimeException(e); + } + + return result; + } + + /** + * 设置结束日志存储 + */ + private void setEndExecuteLog(ScheduleExecuteLogJson executeLogJson, ScheduleExecuteLog executeLog, LocalDateTime startLocalDateTime) { + LocalDateTime endLocalDateTime = LocalDateTime.now(); + String endExecuteTime = endLocalDateTime.format(dateTimeFormatter); + executeLogJson.setOperationTime(endExecuteTime); + // 设置状态结果 + executeLog.setId(null); + executeLog.setExecuteResult(JSON.toJSONString(executeLogJson)); + executeLog.setDuration(Duration.between(startLocalDateTime, endLocalDateTime).toSeconds()); + scheduleExecuteLogMapper.insert(executeLog); + } + + @Pointcut("execution(* cn.bunny.services.quartz.*.execute(..))") + public void pointCut() { + } + +} diff --git a/service/src/main/java/cn/bunny/services/aop/annotation/QuartzSchedulers.java b/service/src/main/java/cn/bunny/services/aop/annotation/QuartzSchedulers.java new file mode 100644 index 0000000..42bbdab --- /dev/null +++ b/service/src/main/java/cn/bunny/services/aop/annotation/QuartzSchedulers.java @@ -0,0 +1,18 @@ +package cn.bunny.services.aop.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface QuartzSchedulers { + String value() default ""; + + // 类型 + String type(); + + // 详情 + String description(); +} diff --git a/service/src/main/java/cn/bunny/services/controller/configuration/CategoryController.java b/service/src/main/java/cn/bunny/services/controller/configuration/CategoryController.java new file mode 100644 index 0000000..9408f2f --- /dev/null +++ b/service/src/main/java/cn/bunny/services/controller/configuration/CategoryController.java @@ -0,0 +1,72 @@ +package cn.bunny.services.controller.configuration; + +import cn.bunny.dao.dto.system.configuration.category.CategoryAddDto; +import cn.bunny.dao.dto.system.configuration.category.CategoryDto; +import cn.bunny.dao.dto.system.configuration.category.CategoryUpdateDto; +import cn.bunny.dao.entity.financial.Category; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.pojo.result.Result; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.configuration.CategoryVo; +import cn.bunny.services.service.configuration.CategoryService; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Mono; + +import java.util.List; + +/** + *

+ * 分类信息表 前端控制器 + *

+ * + * @author Bunny + * @since 2024-11-08 10:29:58 + */ +@Tag(name = "分类信息", description = "分类信息相关接口") +@RestController +@RequestMapping("admin/category") +public class CategoryController { + + @Autowired + private CategoryService categoryService; + + @Operation(summary = "分页查询分类信息", description = "分页查询分类信息") + @GetMapping("getCategoryList/{page}/{limit}") + public Mono>> getCategoryList( + @Parameter(name = "page", description = "当前页", required = true) + @PathVariable("page") Integer page, + @Parameter(name = "limit", description = "每页记录数", required = true) + @PathVariable("limit") Integer limit, + CategoryDto dto) { + Page pageParams = new Page<>(page, limit); + PageResult pageResult = categoryService.getCategoryList(pageParams, dto); + return Mono.just(Result.success(pageResult)); + } + + @Operation(summary = "添加分类信息", description = "添加分类信息") + @PostMapping("addCategory") + public Mono> addCategory(@Valid @RequestBody CategoryAddDto dto) { + categoryService.addCategory(dto); + return Mono.just(Result.success(ResultCodeEnum.ADD_SUCCESS)); + } + + @Operation(summary = "更新分类信息", description = "更新分类信息") + @PutMapping("updateCategory") + public Mono> updateCategory(@Valid @RequestBody CategoryUpdateDto dto) { + categoryService.updateCategory(dto); + return Mono.just(Result.success(ResultCodeEnum.UPDATE_SUCCESS)); + } + + @Operation(summary = "删除分类信息", description = "删除分类信息") + @DeleteMapping("deleteCategory") + public Mono> deleteCategory(@RequestBody List ids) { + categoryService.deleteCategory(ids); + return Mono.just(Result.success(ResultCodeEnum.DELETE_SUCCESS)); + } +} diff --git a/service/src/main/java/cn/bunny/services/controller/configuration/ConfigurationController.java b/service/src/main/java/cn/bunny/services/controller/configuration/ConfigurationController.java new file mode 100644 index 0000000..6323187 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/controller/configuration/ConfigurationController.java @@ -0,0 +1,47 @@ +package cn.bunny.services.controller.configuration; + +import cn.bunny.dao.dto.system.configuration.WebConfigurationDto; +import cn.bunny.dao.entity.configuration.WebConfiguration; +import cn.bunny.dao.pojo.result.Result; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.configuration.WebConfigurationVo; +import cn.bunny.services.service.configuration.ConfigurationService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import lombok.SneakyThrows; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Mono; + +@Tag(name = "系统配置", description = "系统配置相关接口") +@RestController +@RequestMapping("/admin/config") +public class ConfigurationController { + + @Autowired + private ConfigurationService configurationService; + + @SneakyThrows + @Operation(summary = "读取web配置文件", description = "读取web配置文件") + @GetMapping("noAuth/webConfig") + public WebConfiguration webConfig() { + return configurationService.webConfig(); + } + + @SneakyThrows + @Operation(summary = "获取修改web配置文件", description = "获取修改web配置文件") + @GetMapping("getWebConfig") + public Mono> getWebConfig() { + WebConfigurationVo webConfiguration = configurationService.getWebConfig(); + return Mono.just(Result.success(webConfiguration)); + } + + @Operation(summary = "更新web配置文件", description = "更新web配置文件") + @PutMapping("updateWebConfiguration") + public Mono> updateWebConfiguration(@Valid @RequestBody WebConfigurationDto dto) { + configurationService.updateWebConfiguration(dto); + return Mono.just(Result.success(ResultCodeEnum.UPDATE_SUCCESS)); + } + +} diff --git a/service/src/main/java/cn/bunny/services/controller/configuration/MenuIconController.java b/service/src/main/java/cn/bunny/services/controller/configuration/MenuIconController.java new file mode 100644 index 0000000..9a04a17 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/controller/configuration/MenuIconController.java @@ -0,0 +1,79 @@ +package cn.bunny.services.controller.configuration; + +import cn.bunny.dao.dto.system.menuIcon.MenuIconAddDto; +import cn.bunny.dao.dto.system.menuIcon.MenuIconDto; +import cn.bunny.dao.dto.system.menuIcon.MenuIconUpdateDto; +import cn.bunny.dao.entity.system.MenuIcon; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.pojo.result.Result; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.system.MenuIconVo; +import cn.bunny.services.service.configuration.MenuIconService; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Mono; + +import java.util.List; + +/** + *

+ * 系统菜单图标表 前端控制器 + *

+ * + * @author Bunny + * @since 2024-10-02 12:18:29 + */ +@Tag(name = "系统菜单图标", description = "系统菜单图标相关接口") +@RestController +@RequestMapping("admin/menuIcon") +public class MenuIconController { + + @Autowired + private MenuIconService menuIconService; + + @Operation(summary = "分页查询系统菜单图标", description = "分页查询系统菜单图标") + @GetMapping("getMenuIconList/{page}/{limit}") + public Mono>> getMenuIconList( + @Parameter(name = "page", description = "当前页", required = true) + @PathVariable("page") Integer page, + @Parameter(name = "limit", description = "每页记录数", required = true) + @PathVariable("limit") Integer limit, + MenuIconDto dto) { + Page pageParams = new Page<>(page, limit); + PageResult pageResult = menuIconService.getMenuIconList(pageParams, dto); + return Mono.just(Result.success(pageResult)); + } + + @Operation(summary = "获取查询图标名称列", description = "获取查询图标名称列") + @GetMapping("noManage/getIconNameList") + public Mono>> getIconNameList(String iconName) { + List voList = menuIconService.getIconNameList(iconName); + return Mono.just(Result.success(voList)); + } + + @Operation(summary = "添加系统菜单图标", description = "添加系统菜单图标") + @PostMapping("addMenuIcon") + public Mono> addMenuIcon(@Valid @RequestBody MenuIconAddDto dto) { + menuIconService.addMenuIcon(dto); + return Mono.just(Result.success(ResultCodeEnum.ADD_SUCCESS)); + } + + @Operation(summary = "更新系统菜单图标", description = "更新系统菜单图标") + @PutMapping("updateMenuIcon") + public Mono> updateMenuIcon(@Valid @RequestBody MenuIconUpdateDto dto) { + menuIconService.updateMenuIcon(dto); + return Mono.just(Result.success(ResultCodeEnum.UPDATE_SUCCESS)); + } + + @Operation(summary = "删除系统菜单图标", description = "删除系统菜单图标") + @DeleteMapping("deleteMenuIcon") + public Mono> deleteMenuIcon(@RequestBody List ids) { + menuIconService.deleteMenuIcon(ids); + return Mono.just(Result.success(ResultCodeEnum.DELETE_SUCCESS)); + } +} diff --git a/service/src/main/java/cn/bunny/services/controller/email/EmailTemplateController.java b/service/src/main/java/cn/bunny/services/controller/email/EmailTemplateController.java new file mode 100644 index 0000000..f80ded7 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/controller/email/EmailTemplateController.java @@ -0,0 +1,80 @@ +package cn.bunny.services.controller.email; + +import cn.bunny.dao.dto.system.email.template.EmailTemplateAddDto; +import cn.bunny.dao.dto.system.email.template.EmailTemplateDto; +import cn.bunny.dao.dto.system.email.template.EmailTemplateUpdateDto; +import cn.bunny.dao.entity.system.EmailTemplate; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.pojo.result.Result; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.system.email.EmailTemplateVo; +import cn.bunny.services.service.email.EmailTemplateService; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Mono; + +import java.util.List; +import java.util.Map; + +/** + *

+ * 邮件模板 前端控制器 + *

+ * + * @author Bunny + * @since 2024-10-10 21:24:08 + */ +@Tag(name = "邮件模板", description = "邮件模板相关接口") +@RestController +@RequestMapping("admin/emailTemplate") +public class EmailTemplateController { + + @Autowired + private EmailTemplateService emailTemplateService; + + @Operation(summary = "分页查询邮件模板", description = "分页查询邮件模板") + @GetMapping("getEmailTemplateList/{page}/{limit}") + public Mono>> getEmailTemplateList( + @Parameter(name = "page", description = "当前页", required = true) + @PathVariable("page") Integer page, + @Parameter(name = "limit", description = "每页记录数", required = true) + @PathVariable("limit") Integer limit, + EmailTemplateDto dto) { + Page pageParams = new Page<>(page, limit); + PageResult pageResult = emailTemplateService.getEmailTemplateList(pageParams, dto); + return Mono.just(Result.success(pageResult)); + } + + @Operation(summary = "获取邮件模板类型字段", description = "获取邮件模板类型字段") + @GetMapping("getEmailTypes") + public Mono>>> getEmailTypes() { + List> list = emailTemplateService.getEmailTypes(); + return Mono.just(Result.success(list)); + } + + @Operation(summary = "添加邮件模板", description = "添加邮件模板") + @PostMapping("addEmailTemplate") + public Mono> addEmailTemplate(@Valid @RequestBody EmailTemplateAddDto dto) { + emailTemplateService.addEmailTemplate(dto); + return Mono.just(Result.success(ResultCodeEnum.ADD_SUCCESS)); + } + + @Operation(summary = "更新邮件模板", description = "更新邮件模板") + @PutMapping("updateEmailTemplate") + public Mono> updateEmailTemplate(@Valid @RequestBody EmailTemplateUpdateDto dto) { + emailTemplateService.updateEmailTemplate(dto); + return Mono.just(Result.success(ResultCodeEnum.UPDATE_SUCCESS)); + } + + @Operation(summary = "删除邮件模板", description = "删除邮件模板") + @DeleteMapping("deleteEmailTemplate") + public Mono> deleteEmailTemplate(@RequestBody List ids) { + emailTemplateService.deleteEmailTemplate(ids); + return Mono.just(Result.success(ResultCodeEnum.DELETE_SUCCESS)); + } +} diff --git a/service/src/main/java/cn/bunny/services/controller/email/EmailUsersController.java b/service/src/main/java/cn/bunny/services/controller/email/EmailUsersController.java new file mode 100644 index 0000000..1478d16 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/controller/email/EmailUsersController.java @@ -0,0 +1,88 @@ +package cn.bunny.services.controller.email; + +import cn.bunny.dao.dto.system.email.user.EmailUserUpdateStatusDto; +import cn.bunny.dao.dto.system.email.user.EmailUsersAddDto; +import cn.bunny.dao.dto.system.email.user.EmailUsersDto; +import cn.bunny.dao.dto.system.email.user.EmailUsersUpdateDto; +import cn.bunny.dao.entity.system.EmailUsers; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.pojo.result.Result; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.system.email.EmailUsersVo; +import cn.bunny.services.service.email.EmailUsersService; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Mono; + +import java.util.List; +import java.util.Map; + +/** + *

+ * 邮箱用户发送配置 前端控制器 + *

+ * + * @author Bunny + * @since 2024-10-10 15:19:22 + */ +@Tag(name = "邮箱用户发送配置", description = "邮箱用户发送配置相关接口") +@RestController +@RequestMapping("admin/emailUsers") +public class EmailUsersController { + + @Autowired + private EmailUsersService emailUsersService; + + @Operation(summary = "分页查询邮箱用户发送配置", description = "分页查询邮箱用户发送配置") + @GetMapping("getEmailUsersList/{page}/{limit}") + public Mono>> getEmailUsersList( + @Parameter(name = "page", description = "当前页", required = true) + @PathVariable("page") Integer page, + @Parameter(name = "limit", description = "每页记录数", required = true) + @PathVariable("limit") Integer limit, + EmailUsersDto dto) { + Page pageParams = new Page<>(page, limit); + PageResult pageResult = emailUsersService.getEmailUsersList(pageParams, dto); + return Mono.just(Result.success(pageResult)); + } + + @Operation(summary = "获取所有邮箱配置用户", description = "获取所有邮箱配置用户") + @GetMapping("noManage/getAllMailboxConfigurationUsers") + public Mono>>> getAllMailboxConfigurationUsers() { + List> list = emailUsersService.getAllMailboxConfigurationUsers(); + return Mono.just(Result.success(list)); + } + + @Operation(summary = "添加邮箱用户发送配置", description = "添加邮箱用户发送配置") + @PostMapping("addEmailUsers") + public Mono> addEmailUsers(@Valid @RequestBody EmailUsersAddDto dto) { + emailUsersService.addEmailUsers(dto); + return Mono.just(Result.success(ResultCodeEnum.ADD_SUCCESS)); + } + + @Operation(summary = "更新邮箱用户发送配置", description = "更新邮箱用户发送配置") + @PutMapping("updateEmailUsers") + public Mono> updateEmailUsers(@Valid @RequestBody EmailUsersUpdateDto dto) { + emailUsersService.updateEmailUsers(dto); + return Mono.just(Result.success(ResultCodeEnum.UPDATE_SUCCESS)); + } + + @Operation(summary = "更新邮箱用户状态", description = "更新邮箱用户状态") + @PutMapping("updateEmailUserStatus") + public Result updateEmailUserStatus(@Valid @RequestBody EmailUserUpdateStatusDto dto) { + emailUsersService.updateEmailUserStatus(dto); + return Result.success(ResultCodeEnum.UPDATE_SUCCESS); + } + + @Operation(summary = "删除邮箱用户", description = "删除邮箱用户") + @DeleteMapping("deleteEmailUsers") + public Mono> deleteEmailUsers(@RequestBody List ids) { + emailUsersService.deleteEmailUsers(ids); + return Mono.just(Result.success(ResultCodeEnum.DELETE_SUCCESS)); + } +} diff --git a/service/src/main/java/cn/bunny/services/controller/financial/BillController.java b/service/src/main/java/cn/bunny/services/controller/financial/BillController.java new file mode 100644 index 0000000..4e30759 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/controller/financial/BillController.java @@ -0,0 +1,72 @@ +package cn.bunny.services.controller.financial; + +import cn.bunny.dao.dto.financial.bill.BillAddDto; +import cn.bunny.dao.dto.financial.bill.BillDto; +import cn.bunny.dao.dto.financial.bill.BillUpdateDto; +import cn.bunny.dao.entity.financial.Bill; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.pojo.result.Result; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.financial.BillVo; +import cn.bunny.services.service.financial.BillService; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Mono; + +import java.util.List; + +/** + *

+ * 账单信息表 前端控制器 + *

+ * + * @author Bunny + * @since 2024-11-07 16:49:19 + */ +@Tag(name = "账单信息", description = "账单信息相关接口") +@RestController +@RequestMapping("admin/bill") +public class BillController { + + @Autowired + private BillService billService; + + @Operation(summary = "分页查询账单信息", description = "分页查询账单信息") + @GetMapping("noManage/getBillList/{page}/{limit}") + public Mono>> getBillList( + @Parameter(name = "page", description = "当前页", required = true) + @PathVariable("page") Integer page, + @Parameter(name = "limit", description = "每页记录数", required = true) + @PathVariable("limit") Integer limit, + BillDto dto) { + Page pageParams = new Page<>(page, limit); + PageResult pageResult = billService.getBillList(pageParams, dto); + return Mono.just(Result.success(pageResult)); + } + + @Operation(summary = "添加账单信息", description = "添加账单信息") + @PostMapping("noManage/addBill") + public Mono> addBill(@Valid @RequestBody BillAddDto dto) { + billService.addBill(dto); + return Mono.just(Result.success(ResultCodeEnum.ADD_SUCCESS)); + } + + @Operation(summary = "更新账单信息", description = "更新账单信息") + @PutMapping("noManage/updateBill") + public Mono> updateBill(@Valid @RequestBody BillUpdateDto dto) { + billService.updateBill(dto); + return Mono.just(Result.success(ResultCodeEnum.UPDATE_SUCCESS)); + } + + @Operation(summary = "删除账单信息", description = "删除账单信息") + @DeleteMapping("noManage/deleteBill") + public Mono> deleteBill(@RequestBody List ids) { + billService.deleteBill(ids); + return Mono.just(Result.success(ResultCodeEnum.DELETE_SUCCESS)); + } +} diff --git a/service/src/main/java/cn/bunny/services/controller/financial/CategoryUserController.java b/service/src/main/java/cn/bunny/services/controller/financial/CategoryUserController.java new file mode 100644 index 0000000..4029a48 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/controller/financial/CategoryUserController.java @@ -0,0 +1,79 @@ +package cn.bunny.services.controller.financial; + +import cn.bunny.dao.dto.financial.category.CategoryUserAddDto; +import cn.bunny.dao.dto.financial.category.CategoryUserDto; +import cn.bunny.dao.dto.financial.category.CategoryUserUpdateDto; +import cn.bunny.dao.entity.financial.Category; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.pojo.result.Result; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.financial.CategoryUserVo; +import cn.bunny.services.service.financial.CategoryUserService; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Mono; + +import java.util.List; + +/** + *

+ * 分类信息表 前端控制器 + *

+ * + * @author Bunny + * @since 2024-11-08 10:00:09 + */ +@Tag(name = "分类信息", description = "分类信息相关接口") +@RestController +@RequestMapping("admin/categoryUser") +public class CategoryUserController { + + @Autowired + private CategoryUserService categoryUserService; + + @Operation(summary = "用户分类分页查询分类信息", description = "用户分类分页查询分类信息") + @GetMapping("noManage/getCategoryUserList/{page}/{limit}") + public Mono>> getCategoryUserList( + @Parameter(name = "page", description = "当前页", required = true) + @PathVariable("page") Integer page, + @Parameter(name = "limit", description = "每页记录数", required = true) + @PathVariable("limit") Integer limit, + CategoryUserDto dto) { + Page pageParams = new Page<>(page, limit); + PageResult pageResult = categoryUserService.getCategoryUserList(pageParams, dto); + return Mono.just(Result.success(pageResult)); + } + + @Operation(summary = "查询当前用户下所有的分类", description = "查询当前用户下所有的分类") + @GetMapping("noManage/getCategoryUserAllList") + public Mono>> getCategoryUserAllList() { + List voList = categoryUserService.getCategoryUserAllList(); + return Mono.just(Result.success(voList)); + } + + @Operation(summary = "用戶分类添加分类信息", description = "用戶分类添加分类信息") + @PostMapping("noManage/addCategoryUser") + public Mono> addCategoryUser(@Valid @RequestBody CategoryUserAddDto dto) { + categoryUserService.addCategoryUser(dto); + return Mono.just(Result.success(ResultCodeEnum.ADD_SUCCESS)); + } + + @Operation(summary = "用户分类更新分类信息", description = "用户分类更新分类信息") + @PutMapping("noManage/updateCategoryUser") + public Mono> updateCategoryUser(@Valid @RequestBody CategoryUserUpdateDto dto) { + categoryUserService.updateCategoryUser(dto); + return Mono.just(Result.success(ResultCodeEnum.UPDATE_SUCCESS)); + } + + @Operation(summary = "用户分类删除分类信息", description = "用户分类删除分类信息") + @DeleteMapping("noManage/deleteCategoryUser") + public Mono> deleteCategoryUser(@RequestBody List ids) { + categoryUserService.deleteCategoryUser(ids); + return Mono.just(Result.success(ResultCodeEnum.DELETE_SUCCESS)); + } +} diff --git a/service/src/main/java/cn/bunny/services/controller/i18n/I18nController.java b/service/src/main/java/cn/bunny/services/controller/i18n/I18nController.java new file mode 100644 index 0000000..12a0ffe --- /dev/null +++ b/service/src/main/java/cn/bunny/services/controller/i18n/I18nController.java @@ -0,0 +1,80 @@ +package cn.bunny.services.controller.i18n; + +import cn.bunny.dao.dto.i18n.I18nAddDto; +import cn.bunny.dao.dto.i18n.I18nDto; +import cn.bunny.dao.dto.i18n.I18nUpdateDto; +import cn.bunny.dao.entity.i18n.I18n; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.pojo.result.Result; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.i18n.I18nVo; +import cn.bunny.services.service.i18n.I18nService; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Mono; + +import java.util.List; +import java.util.Map; + +/** + *

+ * 多语言 前端控制器 + *

+ * + * @author Bunny + * @since 2024-09-28 + */ +@Tag(name = "多语言", description = "多语言相关接口") +@RestController +@RequestMapping("admin/i18n") +public class I18nController { + + @Autowired + private I18nService i18nService; + + @Operation(summary = "获取多语言内容", description = "获取多语言内容") + @GetMapping("getI18n") + public Mono>> getI18n() { + Map vo = i18nService.getI18n(); + return Mono.just(Result.success(vo)); + } + + @Operation(summary = "获取管理多语言列", description = "获取管理多语言列") + @GetMapping("getI18nList/{page}/{limit}") + public Mono>> getI18nList( + @Parameter(name = "page", description = "当前页", required = true) + @PathVariable("page") Integer page, + @Parameter(name = "limit", description = "每页记录数", required = true) + @PathVariable("limit") Integer limit, + I18nDto dto) { + Page pageParams = new Page<>(page, limit); + PageResult vo = i18nService.getI18nList(pageParams, dto); + return Mono.just(Result.success(vo)); + } + + @Operation(summary = "添加多语言", description = "添加多语言") + @PostMapping("addI18n") + public Mono> addI18n(@Valid @RequestBody I18nAddDto dto) { + i18nService.addI18n(dto); + return Mono.just(Result.success(ResultCodeEnum.ADD_SUCCESS)); + } + + @Operation(summary = "更新多语言", description = "更新多语言") + @PutMapping("updateI18n") + public Mono> updateI18n(@Valid @RequestBody I18nUpdateDto dto) { + i18nService.updateI18n(dto); + return Mono.just(Result.success(ResultCodeEnum.UPDATE_SUCCESS)); + } + + @Operation(summary = "删除多语言", description = "删除多语言") + @DeleteMapping("deleteI18n") + public Mono> deleteI18n(@RequestBody List ids) { + i18nService.deleteI18n(ids); + return Mono.just(Result.success(ResultCodeEnum.DELETE_SUCCESS)); + } +} diff --git a/service/src/main/java/cn/bunny/services/controller/i18n/I18nTypeController.java b/service/src/main/java/cn/bunny/services/controller/i18n/I18nTypeController.java new file mode 100644 index 0000000..dbed39c --- /dev/null +++ b/service/src/main/java/cn/bunny/services/controller/i18n/I18nTypeController.java @@ -0,0 +1,62 @@ +package cn.bunny.services.controller.i18n; + +import cn.bunny.dao.dto.i18n.I18nTypeAddDto; +import cn.bunny.dao.dto.i18n.I18nTypeDto; +import cn.bunny.dao.dto.i18n.I18nTypeUpdateDto; +import cn.bunny.dao.pojo.result.Result; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.i18n.I18nTypeVo; +import cn.bunny.services.service.i18n.I18nTypeService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Mono; + +import java.util.List; + +/** + *

+ * 多语言类型 前端控制器 + *

+ * + * @author Bunny + * @since 2024-09-28 + */ +@Tag(name = "多语言类型", description = "多语言类型相关接口") +@RestController +@RequestMapping("admin/i18nType") +public class I18nTypeController { + + @Autowired + private I18nTypeService i18nTypeService; + + @Operation(summary = "获取多语言类型", description = "获取多语言类型") + @GetMapping("/noAuth/getI18nTypeList") + public Mono>> getI18nTypeList(I18nTypeDto dto) { + List voList = i18nTypeService.getI18nTypeList(dto); + return Mono.just(Result.success(voList)); + } + + @Operation(summary = "添加多语言类型", description = "添加多语言类型") + @PostMapping("addI18nType") + public Mono> addI18nType(@Valid @RequestBody I18nTypeAddDto dto) { + i18nTypeService.addI18nType(dto); + return Mono.just(Result.success(ResultCodeEnum.ADD_SUCCESS)); + } + + @Operation(summary = "更新多语言类型", description = "更新多语言类型") + @PutMapping("updateI18nType") + public Mono> updateI18nType(@Valid @RequestBody I18nTypeUpdateDto dto) { + i18nTypeService.updateI18nType(dto); + return Mono.just(Result.success(ResultCodeEnum.UPDATE_SUCCESS)); + } + + @Operation(summary = "删除多语言类型", description = "删除多语言类型") + @DeleteMapping("deleteI18nType") + public Mono> deleteI18nType(@RequestBody List ids) { + i18nTypeService.deleteI18nType(ids); + return Mono.just(Result.success(ResultCodeEnum.DELETE_SUCCESS)); + } +} diff --git a/service/src/main/java/cn/bunny/services/controller/message/MessageController.java b/service/src/main/java/cn/bunny/services/controller/message/MessageController.java new file mode 100644 index 0000000..05cabd6 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/controller/message/MessageController.java @@ -0,0 +1,88 @@ +package cn.bunny.services.controller.message; + +import cn.bunny.dao.dto.system.message.MessageAddDto; +import cn.bunny.dao.dto.system.message.MessageDto; +import cn.bunny.dao.dto.system.message.MessageUpdateDto; +import cn.bunny.dao.entity.system.Message; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.pojo.result.Result; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.system.message.MessageDetailVo; +import cn.bunny.dao.vo.system.message.MessageReceivedWithUserVo; +import cn.bunny.dao.vo.system.message.MessageVo; +import cn.bunny.services.service.message.MessageService; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Mono; + +import java.util.List; + +/** + *

+ * 系统消息表 前端控制器 + *

+ * + * @author Bunny + * @since 2024-10-30 15:19:56 + */ +@Tag(name = "系统消息", description = "系统消息相关接口") +@RestController +@RequestMapping("admin/message") +public class MessageController { + + @Autowired + private MessageService messageService; + + @Operation(summary = "分页查询发送消息", description = "分页查询发送消息") + @GetMapping("getMessageList/{page}/{limit}") + public Mono>> getMessageList( + @Parameter(name = "page", description = "当前页", required = true) + @PathVariable("page") Integer page, + @Parameter(name = "limit", description = "每页记录数", required = true) + @PathVariable("limit") Integer limit, + MessageDto dto) { + Page pageParams = new Page<>(page, limit); + PageResult pageResult = messageService.getMessageList(pageParams, dto); + return Mono.just(Result.success(pageResult)); + } + + @Operation(summary = "根据消息id查询消息详情", description = "根据消息id查询消息详情") + @GetMapping("noManage/getMessageDetailById") + public Mono> getMessageDetailById(Long id) { + MessageDetailVo vo = messageService.getMessageDetailById(id); + return Mono.just(Result.success(vo)); + } + + @Operation(summary = "根据消息id获取接收人信息", description = "根据消息id获取接收人信息") + @GetMapping("noManage/getReceivedUserinfoByMessageId") + public Mono>> getReceivedUserinfoByMessageId(Long messageId) { + List voList = messageService.getReceivedUserinfoByMessageId(messageId); + return Mono.just(Result.success(voList)); + } + + @Operation(summary = "添加系统消息", description = "添加系统消息") + @PostMapping("addMessage") + public Mono> addMessage(@Valid @RequestBody MessageAddDto dto) { + messageService.addMessage(dto); + return Mono.just(Result.success(ResultCodeEnum.ADD_SUCCESS)); + } + + @Operation(summary = "更新系统消息", description = "更新系统消息") + @PutMapping("updateMessage") + public Mono> updateMessage(@Valid @RequestBody MessageUpdateDto dto) { + messageService.updateMessage(dto); + return Mono.just(Result.success(ResultCodeEnum.UPDATE_SUCCESS)); + } + + @Operation(summary = "删除系统消息", description = "删除系统消息") + @DeleteMapping("deleteMessage") + public Mono> deleteMessage(@RequestBody List ids) { + messageService.deleteMessage(ids); + return Mono.just(Result.success(ResultCodeEnum.DELETE_SUCCESS)); + } +} diff --git a/service/src/main/java/cn/bunny/services/controller/message/MessageReceivedController.java b/service/src/main/java/cn/bunny/services/controller/message/MessageReceivedController.java new file mode 100644 index 0000000..9ff46a1 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/controller/message/MessageReceivedController.java @@ -0,0 +1,93 @@ +package cn.bunny.services.controller.message; + +import cn.bunny.dao.dto.system.message.MessageReceivedDto; +import cn.bunny.dao.dto.system.message.MessageReceivedUpdateDto; +import cn.bunny.dao.dto.system.message.MessageUserDto; +import cn.bunny.dao.entity.system.Message; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.pojo.result.Result; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.system.message.MessageReceivedWithMessageVo; +import cn.bunny.dao.vo.system.message.MessageUserVo; +import cn.bunny.services.service.message.MessageReceivedService; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Mono; + +import java.util.List; + +/** + *

+ * 前端控制器 + *

+ * + * @author Bunny + * @since 2024-10-31 + */ +@Tag(name = "消息接收(用户消息)", description = "消息接收(用户消息)相关接口") +@RestController +@RequestMapping("/admin/messageReceived") +public class MessageReceivedController { + + @Autowired + private MessageReceivedService messageReceivedService; + + @Operation(summary = "管理员分页查询用户消息", description = "管理员分页查询用户消息") + @GetMapping("getMessageReceivedList/{page}/{limit}") + public Mono>> getMessageReceivedList( + @Parameter(name = "page", description = "当前页", required = true) + @PathVariable("page") Integer page, + @Parameter(name = "limit", description = "每页记录数", required = true) + @PathVariable("limit") Integer limit, + MessageReceivedDto dto) { + Page pageParams = new Page<>(page, limit); + PageResult pageResult = messageReceivedService.getMessageReceivedList(pageParams, dto); + return Mono.just(Result.success(pageResult)); + } + + @Operation(summary = "管理员将用户消息标为已读", description = "管理员将用户消息标为已读") + @PutMapping("updateMarkMessageReceived") + public Mono> updateMarkMessageReceived(@Valid @RequestBody MessageReceivedUpdateDto dto) { + messageReceivedService.updateMarkMessageReceived(dto); + return Mono.just(Result.success()); + } + + @Operation(summary = "管理删除用户消息", description = "管理删除用户消息") + @DeleteMapping("deleteMessageReceivedByIds") + public Mono> deleteMessageReceivedByIds(@RequestBody List ids) { + messageReceivedService.deleteMessageReceivedByIds(ids); + return Mono.just(Result.success(ResultCodeEnum.DELETE_SUCCESS)); + } + + @Operation(summary = "分页查询用户消息", description = "分页查询用户消息") + @GetMapping("noManage/getUserMessageList/{page}/{limit}") + public Mono>> getUserMessageList( + @Parameter(name = "page", description = "当前页", required = true) + @PathVariable("page") Integer page, + @Parameter(name = "limit", description = "每页记录数", required = true) + @PathVariable("limit") Integer limit, + MessageUserDto dto) { + Page pageParams = new Page<>(page, limit); + PageResult pageResult = messageReceivedService.getUserMessageList(pageParams, dto); + return Mono.just(Result.success(pageResult)); + } + + @Operation(summary = "用户将消息标为已读", description = "用户将消息标为已读") + @PutMapping("noManage/userMarkAsRead") + public Mono> userMarkAsRead(@Valid @RequestBody List ids) { + messageReceivedService.userMarkAsRead(ids); + return Mono.just(Result.success(ResultCodeEnum.UPDATE_SUCCESS)); + } + + @Operation(summary = "用户删除消息", description = "用户删除消息") + @DeleteMapping("noManage/deleteUserMessageByIds") + public Mono> deleteUserMessageByIds(@RequestBody List ids) { + messageReceivedService.deleteUserMessageByIds(ids); + return Mono.just(Result.success(ResultCodeEnum.DELETE_SUCCESS)); + } +} diff --git a/service/src/main/java/cn/bunny/services/controller/message/MessageTypeController.java b/service/src/main/java/cn/bunny/services/controller/message/MessageTypeController.java new file mode 100644 index 0000000..440a360 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/controller/message/MessageTypeController.java @@ -0,0 +1,79 @@ +package cn.bunny.services.controller.message; + +import cn.bunny.dao.dto.system.message.MessageTypeAddDto; +import cn.bunny.dao.dto.system.message.MessageTypeDto; +import cn.bunny.dao.dto.system.message.MessageTypeUpdateDto; +import cn.bunny.dao.entity.system.MessageType; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.pojo.result.Result; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.system.message.MessageTypeVo; +import cn.bunny.services.service.message.MessageTypeService; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Mono; + +import java.util.List; + +/** + *

+ * 系统消息类型表 前端控制器 + *

+ * + * @author Bunny + * @since 2024-10-30 13:19:33 + */ +@Tag(name = "系统消息类型", description = "系统消息类型相关接口") +@RestController +@RequestMapping("admin/messageType") +public class MessageTypeController { + + @Autowired + private MessageTypeService messageTypeService; + + @Operation(summary = "分页查询系统消息类型", description = "分页查询系统消息类型") + @GetMapping("getMessageTypeList/{page}/{limit}") + public Mono>> getMessageTypeList( + @Parameter(name = "page", description = "当前页", required = true) + @PathVariable("page") Integer page, + @Parameter(name = "limit", description = "每页记录数", required = true) + @PathVariable("limit") Integer limit, + MessageTypeDto dto) { + Page pageParams = new Page<>(page, limit); + PageResult pageResult = messageTypeService.getMessageTypeList(pageParams, dto); + return Mono.just(Result.success(pageResult)); + } + + @Operation(summary = "获取所有消息类型", description = "获取所有消息类型") + @GetMapping("noManage/getAllMessageTypes") + public Mono>> getNoManageMessageTypes() { + List voList = messageTypeService.getNoManageMessageTypes(); + return Mono.just(Result.success(voList)); + } + + @Operation(summary = "添加系统消息类型", description = "添加系统消息类型") + @PostMapping("addMessageType") + public Mono> addMessageType(@Valid @RequestBody MessageTypeAddDto dto) { + messageTypeService.addMessageType(dto); + return Mono.just(Result.success(ResultCodeEnum.ADD_SUCCESS)); + } + + @Operation(summary = "更新系统消息类型", description = "更新系统消息类型") + @PutMapping("updateMessageType") + public Mono> updateMessageType(@Valid @RequestBody MessageTypeUpdateDto dto) { + messageTypeService.updateMessageType(dto); + return Mono.just(Result.success(ResultCodeEnum.UPDATE_SUCCESS)); + } + + @Operation(summary = "删除系统消息类型", description = "删除系统消息类型") + @DeleteMapping("deleteMessageType") + public Mono> deleteMessageType(@RequestBody List ids) { + messageTypeService.deleteMessageType(ids); + return Mono.just(Result.success(ResultCodeEnum.DELETE_SUCCESS)); + } +} diff --git a/service/src/main/java/cn/bunny/services/controller/schedule/ScheduleExecuteLogController.java b/service/src/main/java/cn/bunny/services/controller/schedule/ScheduleExecuteLogController.java new file mode 100644 index 0000000..3d83ae0 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/controller/schedule/ScheduleExecuteLogController.java @@ -0,0 +1,55 @@ +package cn.bunny.services.controller.schedule; + +import cn.bunny.dao.dto.log.ScheduleExecuteLogDto; +import cn.bunny.dao.entity.log.ScheduleExecuteLog; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.pojo.result.Result; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.log.QuartzExecuteLogVo; +import cn.bunny.services.service.schedule.ScheduleExecuteLogService; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Mono; + +import java.util.List; + +/** + *

+ * 调度任务执行日志表 前端控制器 + *

+ * + * @author Bunny + * @since 2024-10-18 12:56:39 + */ +@Tag(name = "调度任务执行日志", description = "调度任务执行日志相关接口") +@RestController +@RequestMapping("admin/quartzExecuteLog") +public class ScheduleExecuteLogController { + + @Autowired + private ScheduleExecuteLogService scheduleExecuteLogService; + + @Operation(summary = "分页查询调度任务执行日志", description = "分页查询调度任务执行日志") + @GetMapping("getQuartzExecuteLogList/{page}/{limit}") + public Mono>> getQuartzExecuteLogList( + @Parameter(name = "page", description = "当前页", required = true) + @PathVariable("page") Integer page, + @Parameter(name = "limit", description = "每页记录数", required = true) + @PathVariable("limit") Integer limit, + ScheduleExecuteLogDto dto) { + Page pageParams = new Page<>(page, limit); + PageResult pageResult = scheduleExecuteLogService.getQuartzExecuteLogList(pageParams, dto); + return Mono.just(Result.success(pageResult)); + } + + @Operation(summary = "删除调度任务执行日志", description = "删除调度任务执行日志") + @DeleteMapping("deleteQuartzExecuteLog") + public Mono> deleteQuartzExecuteLog(@RequestBody List ids) { + scheduleExecuteLogService.deleteQuartzExecuteLog(ids); + return Mono.just(Result.success(ResultCodeEnum.DELETE_SUCCESS)); + } +} diff --git a/service/src/main/java/cn/bunny/services/controller/schedule/SchedulersController.java b/service/src/main/java/cn/bunny/services/controller/schedule/SchedulersController.java new file mode 100644 index 0000000..f504c79 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/controller/schedule/SchedulersController.java @@ -0,0 +1,87 @@ +package cn.bunny.services.controller.schedule; + +import cn.bunny.dao.dto.quartz.SchedulersOperationDto; +import cn.bunny.dao.dto.quartz.schedule.SchedulersAddDto; +import cn.bunny.dao.dto.quartz.schedule.SchedulersDto; +import cn.bunny.dao.entity.quartz.Schedulers; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.pojo.result.Result; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.quartz.SchedulersVo; +import cn.bunny.services.service.schedule.SchedulersService; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Mono; + +import java.util.List; +import java.util.Map; + +/** + *

+ * Schedulers视图 前端控制器 + *

+ * + * @author Bunny + * @since 2024-10-15 16:35:10 + */ +@Tag(name = "调度任务", description = "调度任务相关接口") +@RestController +@RequestMapping("admin/schedulers") +public class SchedulersController { + + @Autowired + private SchedulersService schedulersService; + + @Operation(summary = "分页查询视图", description = "分页查询视图") + @GetMapping("getSchedulersList/{page}/{limit}") + public Mono>> getSchedulersList( + @Parameter(name = "page", description = "当前页", required = true) + @PathVariable("page") Integer page, + @Parameter(name = "limit", description = "每页记录数", required = true) + @PathVariable("limit") Integer limit, + SchedulersDto dto) { + Page pageParams = new Page<>(page, limit); + PageResult pageResult = schedulersService.getSchedulersList(pageParams, dto); + return Mono.just(Result.success(pageResult)); + } + + @Operation(summary = "获取所有可用调度任务", description = "获取所有可用调度任务") + @GetMapping("noManage/getAllScheduleJobList") + public Mono>>> getAllScheduleJobList() { + List> mapList = schedulersService.getAllScheduleJobList(); + return Mono.just(Result.success(mapList)); + } + + @Operation(summary = "添加任务", description = "添加任务") + @PostMapping("addSchedulers") + public Mono> addSchedulers(@Valid @RequestBody SchedulersAddDto dto) { + schedulersService.addSchedulers(dto); + return Mono.just(Result.success(ResultCodeEnum.ADD_SUCCESS)); + } + + @Operation(summary = "暂停任务", description = "暂停任务") + @PutMapping("/pauseSchedulers") + public Result pause(@RequestBody SchedulersOperationDto dto) { + schedulersService.pauseScheduler(dto); + return Result.success(); + } + + @Operation(summary = "恢复任务", description = "恢复任务") + @PutMapping("/resumeSchedulers") + public Result resume(@RequestBody SchedulersOperationDto dto) { + schedulersService.resumeScheduler(dto); + return Result.success(); + } + + @Operation(summary = "删除任务", description = "删除任务") + @DeleteMapping("/deleteSchedulers") + public Mono> deleteSchedulers(@RequestBody SchedulersOperationDto dto) { + schedulersService.deleteSchedulers(dto); + return Mono.just(Result.success(ResultCodeEnum.DELETE_SUCCESS)); + } +} diff --git a/service/src/main/java/cn/bunny/services/controller/schedule/SchedulersGroupController.java b/service/src/main/java/cn/bunny/services/controller/schedule/SchedulersGroupController.java new file mode 100644 index 0000000..00308f5 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/controller/schedule/SchedulersGroupController.java @@ -0,0 +1,79 @@ +package cn.bunny.services.controller.schedule; + +import cn.bunny.dao.dto.quartz.group.SchedulersGroupAddDto; +import cn.bunny.dao.dto.quartz.group.SchedulersGroupDto; +import cn.bunny.dao.dto.quartz.group.SchedulersGroupUpdateDto; +import cn.bunny.dao.entity.quartz.SchedulersGroup; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.pojo.result.Result; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.quartz.SchedulersGroupVo; +import cn.bunny.services.service.schedule.SchedulersGroupService; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Mono; + +import java.util.List; + +/** + *

+ * 任务调度分组 前端控制器 + *

+ * + * @author Bunny + * @since 2024-10-15 20:26:32 + */ +@Tag(name = "任务调度分组", description = "任务调度分组相关接口") +@RestController +@RequestMapping("admin/schedulersGroup") +public class SchedulersGroupController { + + @Autowired + private SchedulersGroupService schedulersGroupService; + + @Operation(summary = "分页查询任务调度分组", description = "分页查询任务调度分组") + @GetMapping("getSchedulersGroupList/{page}/{limit}") + public Mono>> getSchedulersGroupList( + @Parameter(name = "page", description = "当前页", required = true) + @PathVariable("page") Integer page, + @Parameter(name = "limit", description = "每页记录数", required = true) + @PathVariable("limit") Integer limit, + SchedulersGroupDto dto) { + Page pageParams = new Page<>(page, limit); + PageResult pageResult = schedulersGroupService.getSchedulersGroupList(pageParams, dto); + return Mono.just(Result.success(pageResult)); + } + + @Operation(summary = "获取所有任务调度分组", description = "获取所有任务调度分组") + @GetMapping("getAllSchedulersGroup") + public Mono>> getAllSchedulersGroup() { + List voList = schedulersGroupService.getAllSchedulersGroup(); + return Mono.just(Result.success(voList)); + } + + @Operation(summary = "添加任务调度分组", description = "添加任务调度分组") + @PostMapping("addSchedulersGroup") + public Mono> addSchedulersGroup(@Valid @RequestBody SchedulersGroupAddDto dto) { + schedulersGroupService.addSchedulersGroup(dto); + return Mono.just(Result.success(ResultCodeEnum.ADD_SUCCESS)); + } + + @Operation(summary = "更新任务调度分组", description = "更新任务调度分组") + @PutMapping("updateSchedulersGroup") + public Mono> updateSchedulersGroup(@Valid @RequestBody SchedulersGroupUpdateDto dto) { + schedulersGroupService.updateSchedulersGroup(dto); + return Mono.just(Result.success(ResultCodeEnum.UPDATE_SUCCESS)); + } + + @Operation(summary = "删除任务调度分组", description = "删除任务调度分组") + @DeleteMapping("deleteSchedulersGroup") + public Mono> deleteSchedulersGroup(@RequestBody List ids) { + schedulersGroupService.deleteSchedulersGroup(ids); + return Mono.just(Result.success(ResultCodeEnum.DELETE_SUCCESS)); + } +} diff --git a/service/src/main/java/cn/bunny/services/controller/system/DeptController.java b/service/src/main/java/cn/bunny/services/controller/system/DeptController.java new file mode 100644 index 0000000..b108e93 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/controller/system/DeptController.java @@ -0,0 +1,79 @@ +package cn.bunny.services.controller.system; + +import cn.bunny.dao.dto.system.dept.DeptAddDto; +import cn.bunny.dao.dto.system.dept.DeptDto; +import cn.bunny.dao.dto.system.dept.DeptUpdateDto; +import cn.bunny.dao.entity.system.Dept; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.pojo.result.Result; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.system.DeptVo; +import cn.bunny.services.service.system.DeptService; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Mono; + +import java.util.List; + +/** + *

+ * 部门 前端控制器 + *

+ * + * @author Bunny + * @since 2024-10-04 10:39:08 + */ +@Tag(name = "系统部门", description = "部门相关接口") +@RestController +@RequestMapping("/admin/dept") +public class DeptController { + + @Autowired + private DeptService deptService; + + @Operation(summary = "分页查询部门", description = "分页查询部门") + @GetMapping("getDeptList/{page}/{limit}") + public Mono>> getDeptList( + @Parameter(name = "page", description = "当前页", required = true) + @PathVariable("page") Integer page, + @Parameter(name = "limit", description = "每页记录数", required = true) + @PathVariable("limit") Integer limit, + DeptDto dto) { + Page pageParams = new Page<>(page, limit); + PageResult pageResult = deptService.getDeptList(pageParams, dto); + return Mono.just(Result.success(pageResult)); + } + + @Operation(summary = "获取所有部门", description = "获取所有部门") + @GetMapping("noManage/getAllDeptList") + public Mono>> getAllDeptList() { + List voList = deptService.getAllDeptList(); + return Mono.just(Result.success(voList)); + } + + @Operation(summary = "添加部门", description = "添加部门") + @PostMapping("addDept") + public Mono> addDept(@Valid @RequestBody DeptAddDto dto) { + deptService.addDept(dto); + return Mono.just(Result.success(ResultCodeEnum.ADD_SUCCESS)); + } + + @Operation(summary = "更新部门", description = "更新部门") + @PutMapping("updateDept") + public Mono> updateDept(@Valid @RequestBody DeptUpdateDto dto) { + deptService.updateDept(dto); + return Mono.just(Result.success(ResultCodeEnum.UPDATE_SUCCESS)); + } + + @Operation(summary = "删除部门", description = "删除部门") + @DeleteMapping("deleteDept") + public Mono> deleteDept(@RequestBody List ids) { + deptService.deleteDept(ids); + return Mono.just(Result.success(ResultCodeEnum.DELETE_SUCCESS)); + } +} diff --git a/service/src/main/java/cn/bunny/services/controller/system/FilesController.java b/service/src/main/java/cn/bunny/services/controller/system/FilesController.java new file mode 100644 index 0000000..422c311 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/controller/system/FilesController.java @@ -0,0 +1,122 @@ +package cn.bunny.services.controller.system; + +import cn.bunny.dao.dto.system.files.FileUploadDto; +import cn.bunny.dao.dto.system.files.FilesAddDto; +import cn.bunny.dao.dto.system.files.FilesDto; +import cn.bunny.dao.dto.system.files.FilesUpdateDto; +import cn.bunny.dao.entity.system.Files; +import cn.bunny.dao.pojo.constant.MinioConstant; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.pojo.result.Result; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.system.files.FileInfoVo; +import cn.bunny.dao.vo.system.files.FilesVo; +import cn.bunny.services.service.system.FilesService; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Mono; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + *

+ * 系统文件表表 前端控制器 + *

+ * + * @author Bunny + * @since 2024-10-09 16:28:01 + */ +@Tag(name = "系统文件表", description = "系统文件相关接口") +@RestController +@RequestMapping("admin/files") +public class FilesController { + + @Autowired + private FilesService filesService; + + @Operation(summary = "分页查询系统文件", description = "分页查询系统文件") + @GetMapping("getFilesList/{page}/{limit}") + public Mono>> getFilesList( + @Parameter(name = "page", description = "当前页", required = true) + @PathVariable("page") Integer page, + @Parameter(name = "limit", description = "每页记录数", required = true) + @PathVariable("limit") Integer limit, + FilesDto dto) { + Page pageParams = new Page<>(page, limit); + PageResult pageResult = filesService.getFilesList(pageParams, dto); + return Mono.just(Result.success(pageResult)); + } + + @Operation(summary = "下载文件", description = "下载文件") + @GetMapping("downloadFilesByFileId/{fileId}") + public ResponseEntity downloadFilesByFileId(@PathVariable Long fileId) { + return filesService.downloadFilesByFileId(fileId); + } + + @Operation(summary = "获取所有文件类型", description = "获取所有文件类型") + @GetMapping("noManage/getAllMediaTypes") + public Mono>> getAllMediaTypes() { + Set list = filesService.getAllMediaTypes(); + return Mono.just(Result.success(list)); + } + + @Operation(summary = "获取所有文件存储基础路径", description = "获取所有文件存储基础路径") + @GetMapping("noManage/getAllFilesStoragePath") + public Mono>> getAllFilesStoragePath() { + Map typeMap = MinioConstant.typeMap; + List list = typeMap.keySet().stream().toList(); + + return Mono.just(Result.success(list)); + } + + @Operation(summary = "根据文件名下载文件", description = "根据文件名下载文件") + @GetMapping("downloadFilesByFilepath") + public ResponseEntity downloadFilesByFilepath(String filepath) { + return filesService.downloadFilesByFilepath(filepath); + } + + // // 无法做权限校验 + // @Operation(summary = "根据文件名访问resource下图片文件", description = "根据文件名访问resource下文件") + // @GetMapping("noAuth/getResourceImagesByFilename/{filename}") + // public ResponseEntity getResourceImagesByFilename(@PathVariable String filename) { + // Resource file = new ClassPathResource("static/images/" + filename); + // if (!file.exists()) throw new BunnyException(ResultCodeEnum.FILE_NOT_EXIST); + // return ResponseEntity.ok().body(file); + // } + + @Operation(summary = "更新系统文件", description = "更新系统文件") + @PutMapping("updateFiles") + public Result updateFiles(@Valid FilesUpdateDto dto) { + filesService.updateFiles(dto); + return Result.success(ResultCodeEnum.UPDATE_SUCCESS); + } + + @Operation(summary = "添加系统文件", description = "添加系统文件") + @PostMapping("addFiles") + public Mono> addFiles(@Valid FilesAddDto dto) { + filesService.addFiles(dto); + return Mono.just(Result.success(ResultCodeEnum.ADD_SUCCESS)); + } + + @Operation(summary = "上传文件", description = "上传文件") + @PostMapping("upload") + public Result upload(FileUploadDto dto) { + FileInfoVo vo = filesService.upload(dto); + return Result.success(vo, ResultCodeEnum.SUCCESS_UPLOAD); + } + + @Operation(summary = "删除系统文件", description = "删除系统文件") + @DeleteMapping("deleteFiles") + public Result deleteFiles(@RequestBody List ids) { + filesService.deleteFiles(ids); + return Result.success(ResultCodeEnum.DELETE_SUCCESS); + } +} diff --git a/service/src/main/java/cn/bunny/services/controller/system/IndexController.java b/service/src/main/java/cn/bunny/services/controller/system/IndexController.java new file mode 100644 index 0000000..0896583 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/controller/system/IndexController.java @@ -0,0 +1,38 @@ +package cn.bunny.services.controller.system; + +import cn.hutool.captcha.CaptchaUtil; +import cn.hutool.captcha.CircleCaptcha; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Tag(name = "访问首页内容", description = "访问首页内容相关接口") +@RestController +@RequestMapping("/") +public class IndexController { + + @Operation(summary = "访问首页", description = "访问首页") + @GetMapping("") + public String index() { + return "欢迎访问 Bunny Java Template,欢迎去Gitee:https://gitee.com/BunnyBoss/java_single.git"; + } + + @Operation(summary = "生成验证码", description = "生成验证码") + @GetMapping("noAuth/checkCode") + public ResponseEntity checkCode() { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.IMAGE_JPEG); + + // 生成验证码 + CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(150, 48, 4, 2); + byte[] image = captcha.getImageBytes(); + + return new ResponseEntity<>(image, headers, HttpStatus.OK); + } +} \ No newline at end of file diff --git a/service/src/main/java/cn/bunny/services/controller/system/PowerController.java b/service/src/main/java/cn/bunny/services/controller/system/PowerController.java new file mode 100644 index 0000000..7e03ff3 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/controller/system/PowerController.java @@ -0,0 +1,88 @@ +package cn.bunny.services.controller.system; + +import cn.bunny.dao.dto.system.rolePower.power.PowerAddDto; +import cn.bunny.dao.dto.system.rolePower.power.PowerDto; +import cn.bunny.dao.dto.system.rolePower.power.PowerUpdateBatchByParentIdDto; +import cn.bunny.dao.dto.system.rolePower.power.PowerUpdateDto; +import cn.bunny.dao.entity.system.Power; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.pojo.result.Result; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.system.rolePower.PowerVo; +import cn.bunny.services.service.system.PowerService; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Mono; + +import java.util.List; + +/** + *

+ * 权限 前端控制器 + *

+ * + * @author Bunny + * @since 2024-10-03 16:00:52 + */ +@Tag(name = "权限", description = "权限相关接口") +@RestController +@RequestMapping("admin/power") +public class PowerController { + + @Autowired + private PowerService powerService; + + @Operation(summary = "分页查询权限", description = "分页查询权限") + @GetMapping("getPowerList/{page}/{limit}") + public Mono>> getPowerList( + @Parameter(name = "page", description = "当前页", required = true) + @PathVariable("page") Integer page, + @Parameter(name = "limit", description = "每页记录数", required = true) + @PathVariable("limit") Integer limit, + PowerDto dto) { + Page pageParams = new Page<>(page, limit); + PageResult pageResult = powerService.getPowerList(pageParams, dto); + return Mono.just(Result.success(pageResult)); + } + + @Operation(summary = "获取所有权限", description = "获取所有权限") + @GetMapping("getAllPowers") + public Mono>> getAllPowers() { + List voList = powerService.getAllPowers(); + return Mono.just(Result.success(voList)); + } + + @Operation(summary = "添加权限", description = "添加权限") + @PostMapping("addPower") + public Result addPower(@Valid @RequestBody PowerAddDto dto) { + powerService.addPower(dto); + return Result.success(ResultCodeEnum.ADD_SUCCESS); + } + + @Operation(summary = "更新权限", description = "更新权限") + @PutMapping("updatePower") + public Mono> updatePower(@Valid @RequestBody PowerUpdateDto dto) { + powerService.updatePower(dto); + return Mono.just(Result.success(ResultCodeEnum.UPDATE_SUCCESS)); + } + + @Operation(summary = "批量修改权限父级", description = "批量修改权限父级") + @PutMapping("updateBatchByPowerWithParentId") + public Mono> updateBatchByPowerWithParentId(@RequestBody @Valid PowerUpdateBatchByParentIdDto dto) { + powerService.updateBatchByPowerWithParentId(dto); + return Mono.just(Result.success(ResultCodeEnum.UPDATE_SUCCESS)); + } + + @Operation(summary = "删除权限", description = "删除权限") + @DeleteMapping("deletePower") + public Mono> deletePower(@RequestBody List ids) { + powerService.deletePower(ids); + return Mono.just(Result.success(ResultCodeEnum.DELETE_SUCCESS)); + } + +} diff --git a/service/src/main/java/cn/bunny/services/controller/system/RoleController.java b/service/src/main/java/cn/bunny/services/controller/system/RoleController.java new file mode 100644 index 0000000..369f9c0 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/controller/system/RoleController.java @@ -0,0 +1,79 @@ +package cn.bunny.services.controller.system; + +import cn.bunny.dao.dto.system.rolePower.role.RoleAddDto; +import cn.bunny.dao.dto.system.rolePower.role.RoleDto; +import cn.bunny.dao.dto.system.rolePower.role.RoleUpdateDto; +import cn.bunny.dao.entity.system.Role; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.pojo.result.Result; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.system.rolePower.RoleVo; +import cn.bunny.services.service.system.RoleService; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Mono; + +import java.util.List; + +/** + *

+ * 角色 前端控制器 + *

+ * + * @author Bunny + * @since 2024-10-03 14:26:24 + */ +@Tag(name = "角色", description = "角色相关接口") +@RestController +@RequestMapping("admin/role") +public class RoleController { + + @Autowired + private RoleService roleService; + + @Operation(summary = "分页查询角色", description = "分页查询角色") + @GetMapping("getRoleList/{page}/{limit}") + public Mono>> getRoleList( + @Parameter(name = "page", description = "当前页", required = true) + @PathVariable("page") Integer page, + @Parameter(name = "limit", description = "每页记录数", required = true) + @PathVariable("limit") Integer limit, + RoleDto dto) { + Page pageParams = new Page<>(page, limit); + PageResult pageResult = roleService.getRoleList(pageParams, dto); + return Mono.just(Result.success(pageResult)); + } + + @Operation(summary = "获取所有角色", description = "获取所有角色") + @GetMapping("noManage/getAllRoles") + public Mono>> getAllRoles() { + List roleVoList = roleService.getAllRoles(); + return Mono.just(Result.success(roleVoList)); + } + + @Operation(summary = "添加角色", description = "添加角色") + @PostMapping("addRole") + public Mono> addRole(@Valid @RequestBody RoleAddDto dto) { + roleService.addRole(dto); + return Mono.just(Result.success(ResultCodeEnum.ADD_SUCCESS)); + } + + @Operation(summary = "更新角色", description = "更新角色") + @PutMapping("updateRole") + public Mono> updateRole(@Valid @RequestBody RoleUpdateDto dto) { + roleService.updateRole(dto); + return Mono.just(Result.success(ResultCodeEnum.UPDATE_SUCCESS)); + } + + @Operation(summary = "删除角色", description = "删除角色") + @DeleteMapping("deleteRole") + public Mono> deleteRole(@RequestBody List ids) { + roleService.deleteRole(ids); + return Mono.just(Result.success(ResultCodeEnum.DELETE_SUCCESS)); + } +} diff --git a/service/src/main/java/cn/bunny/services/controller/system/RolePowerController.java b/service/src/main/java/cn/bunny/services/controller/system/RolePowerController.java new file mode 100644 index 0000000..ecacb32 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/controller/system/RolePowerController.java @@ -0,0 +1,44 @@ +package cn.bunny.services.controller.system; + +import cn.bunny.dao.dto.system.rolePower.AssignPowersToRoleDto; +import cn.bunny.dao.pojo.result.Result; +import cn.bunny.services.service.system.RolePowerService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Mono; + +import java.util.List; + +/** + *

+ * 前端控制器 + *

+ * + * @author Bunny + * @since 2024-09-26 + */ +@Tag(name = "角色和权限", description = "角色和权限相关接口") +@RestController +@RequestMapping("admin/rolePower") +public class RolePowerController { + + @Autowired + private RolePowerService rolePowerService; + + @Operation(summary = "根据角色id获取权限内容", description = "根据角色id获取权限内容") + @GetMapping("noManage/getPowerListByRoleId") + public Mono>> getPowerListByRoleId(Long id) { + List voList = rolePowerService.getPowerListByRoleId(id); + return Mono.just(Result.success(voList)); + } + + @Operation(summary = "为角色分配权限", description = "为角色分配权限") + @PostMapping("assignPowersToRole") + public Result assignPowersToRole(@Valid @RequestBody AssignPowersToRoleDto dto) { + rolePowerService.assignPowersToRole(dto); + return Result.success(); + } +} diff --git a/service/src/main/java/cn/bunny/services/controller/system/RouterController.java b/service/src/main/java/cn/bunny/services/controller/system/RouterController.java new file mode 100644 index 0000000..6efd444 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/controller/system/RouterController.java @@ -0,0 +1,97 @@ +package cn.bunny.services.controller.system; + +import cn.bunny.dao.dto.system.router.RouterAddDto; +import cn.bunny.dao.dto.system.router.RouterManageDto; +import cn.bunny.dao.dto.system.router.RouterUpdateByIdWithRankDto; +import cn.bunny.dao.dto.system.router.RouterUpdateDto; +import cn.bunny.dao.entity.system.Router; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.pojo.result.Result; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.system.router.RouterManageVo; +import cn.bunny.dao.vo.system.router.UserRouterVo; +import cn.bunny.services.service.system.RouterService; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Mono; + +import java.util.List; + +/** + *

+ * 系统菜单 前端控制器 + *

+ * + * @author Bunny + * @since 2024-09-26 + */ +@Tag(name = "系统路由", description = "系统路由相关接口") +@RestController +@RequestMapping("admin/router") +public class RouterController { + + @Autowired + private RouterService routerService; + + @Operation(summary = "获取用户菜单", description = "获取用户菜单") + @GetMapping("noManage/getRouterAsync") + public Mono>> getRouterAsync() { + List voList = routerService.getRouterAsync(); + return Mono.just(Result.success(voList)); + } + + @Operation(summary = "分页管理菜单列", description = "分页管理菜单列") + @GetMapping("getMenusList/{page}/{limit}") + public Mono>> getMenusByPage( + @Parameter(name = "page", description = "当前页", required = true) + @PathVariable("page") Integer page, + @Parameter(name = "limit", description = "每页记录数", required = true) + @PathVariable("limit") Integer limit, + RouterManageDto dto) { + Page pageParams = new Page<>(page, limit); + PageResult voPageResult = routerService.getMenusByPage(pageParams, dto); + + return Mono.just(Result.success(voPageResult)); + } + + @Operation(summary = "分页查询管理菜单列表", description = "分页查询管理菜单列表") + @GetMapping("getMenusList") + public Mono>> getMenusList(RouterManageDto dto) { + List voPageResult = routerService.getMenusList(dto); + + return Mono.just(Result.success(voPageResult)); + } + + @Operation(summary = "添加路由菜单", description = "添加路由菜单") + @PostMapping("addMenu") + public Mono> addMenu(@Valid @RequestBody RouterAddDto dto) { + routerService.addMenu(dto); + return Mono.just(Result.success(ResultCodeEnum.ADD_SUCCESS)); + } + + @Operation(summary = "更新路由菜单", description = "更新路由菜单") + @PutMapping("updateMenu") + public Mono> updateMenu(@Valid @RequestBody RouterUpdateDto dto) { + routerService.updateMenu(dto); + return Mono.just(Result.success(ResultCodeEnum.UPDATE_SUCCESS)); + } + + @Operation(summary = "快速更新菜单排序", description = "快速更新菜单排序") + @PutMapping("updateMenuByIdWithRank") + public Mono> updateMenuByIdWithRank(@Valid @RequestBody RouterUpdateByIdWithRankDto dto) { + routerService.updateMenuByIdWithRank(dto); + return Mono.just(Result.success(ResultCodeEnum.UPDATE_SUCCESS)); + } + + @Operation(summary = "删除路由菜单", description = "删除路由菜单") + @DeleteMapping("deletedMenuByIds") + public Mono> deletedMenuByIds(@RequestBody List ids) { + routerService.deletedMenuByIds(ids); + return Mono.just(Result.success(ResultCodeEnum.DELETE_SUCCESS)); + } +} diff --git a/service/src/main/java/cn/bunny/services/controller/system/RouterRoleController.java b/service/src/main/java/cn/bunny/services/controller/system/RouterRoleController.java new file mode 100644 index 0000000..35f0564 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/controller/system/RouterRoleController.java @@ -0,0 +1,57 @@ +package cn.bunny.services.controller.system; + +import cn.bunny.dao.dto.system.router.AssignRolesToRoutersDto; +import cn.bunny.dao.pojo.result.Result; +import cn.bunny.services.service.system.RouterRoleService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Mono; + +import java.util.List; + +/** + *

+ * 前端控制器 + *

+ * + * @author Bunny + * @since 2024-09-26 + */ +@Tag(name = "路由和角色", description = "路由和角色相关接口") +@RestController +@RequestMapping("admin/routerRole") +public class RouterRoleController { + + @Autowired + private RouterRoleService routerRoleService; + + @Operation(summary = "根据菜单id获取所有角色", description = "根据菜单id获取所有角色") + @GetMapping("getRoleListByRouterId") + public Mono>> getRoleListByRouterId(Long routerId) { + List roleListByRouterId = routerRoleService.getRoleListByRouterId(routerId); + return Mono.just(Result.success(roleListByRouterId)); + } + + @Operation(summary = "为菜单分配角色", description = "为菜单分配角色") + @PostMapping("assignRolesToRouter") + public Mono> assignRolesToRouter(@RequestBody AssignRolesToRoutersDto dto) { + routerRoleService.assignRolesToRouter(dto); + return Mono.just(Result.success()); + } + + @Operation(summary = "批量为菜单添加角色", description = "批量为菜单添加角色") + @PostMapping("assignAddBatchRolesToRouter") + public Mono> assignAddBatchRolesToRouter(@RequestBody AssignRolesToRoutersDto dto) { + routerRoleService.assignAddBatchRolesToRouter(dto); + return Mono.just(Result.success()); + } + + @Operation(summary = "清除选中菜单所有角色", description = "清除选中菜单所有角色") + @DeleteMapping("clearAllRolesSelect") + public Mono> clearAllRolesSelect(@RequestBody List routerIds) { + routerRoleService.clearAllRolesSelect(routerIds); + return Mono.just(Result.success()); + } +} diff --git a/service/src/main/java/cn/bunny/services/controller/system/UserController.java b/service/src/main/java/cn/bunny/services/controller/system/UserController.java new file mode 100644 index 0000000..8fdabaa --- /dev/null +++ b/service/src/main/java/cn/bunny/services/controller/system/UserController.java @@ -0,0 +1,147 @@ +package cn.bunny.services.controller.system; + +import cn.bunny.dao.dto.system.user.*; +import cn.bunny.dao.entity.system.AdminUser; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.pojo.result.Result; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.system.user.*; +import cn.bunny.services.service.system.UserService; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Mono; + +import java.util.List; + + +@Tag(name = "用户信息", description = "用户信息相关接口") +@RestController +@RequestMapping("/admin/user") +public class UserController { + + @Autowired + private UserService userService; + + @Operation(summary = "分页查询用户信息", description = "分页查询用户信息") + @GetMapping("getAdminUserList/{page}/{limit}") + public Mono>> getAdminUserList( + @Parameter(name = "page", description = "当前页", required = true) + @PathVariable("page") Integer page, + @Parameter(name = "limit", description = "每页记录数", required = true) + @PathVariable("limit") Integer limit, + AdminUserDto dto) { + Page pageParams = new Page<>(page, limit); + PageResult pageResult = userService.getAdminUserList(pageParams, dto); + return Mono.just(Result.success(pageResult)); + } + + @Operation(summary = "获取本地登录用户信息", description = "获取用户信息从Redis中获取") + @GetMapping("noManage/getUserinfo") + public Mono> getUserinfo() { + LoginVo vo = userService.getUserinfo(); + return Mono.just(Result.success(vo)); + } + + @Operation(summary = "获取用户信息", description = "根据用户ID获取用户信息,不包含Redis中的信息") + @GetMapping("getUserinfoById") + public Mono> getUserinfoById(Long id) { + UserVo vo = userService.getUserinfoById(id); + return Mono.just(Result.success(vo)); + } + + @Operation(summary = "多条件查询用户", description = "多条件查询用户") + @GetMapping("noManage/queryUser") + public Mono>> queryUser(String keyword) { + List voList = userService.queryUser(keyword); + return Mono.just(Result.success(voList)); + } + + @Operation(summary = "更新用户信息", description = "更新用户信息,需要更新Redis中的内容") + @PutMapping("updateAdminUser") + public Result updateAdminUser(@Valid @RequestBody AdminUserUpdateDto dto) { + userService.updateAdminUser(dto); + return Result.success(ResultCodeEnum.UPDATE_SUCCESS); + } + + @Operation(summary = "更新本地用户信息", description = "更新本地用户信息,需要更新Redis中的内容") + @PutMapping("noManage/updateAdminUserByLocalUser") + public Result updateAdminUserByLocalUser(@Valid @RequestBody AdminUserUpdateByLocalUserDto dto) { + userService.updateAdminUserByLocalUser(dto); + return Result.success(ResultCodeEnum.UPDATE_SUCCESS); + } + + @Operation(summary = "更新本地用户密码", description = "更新本地用户密码") + @PutMapping("noManage/updateUserPasswordByLocalUser") + public Result updateUserPasswordByLocalUser(String password) { + userService.updateUserPasswordByLocalUser(password); + return Result.success(ResultCodeEnum.UPDATE_SUCCESS); + } + + @Operation(summary = "管理员修改用户密码", description = "管理员修改管理员用户密码") + @PutMapping("updateUserPasswordByAdmin") + public Result updateUserPasswordByAdmin(@Valid @RequestBody AdminUserUpdateWithPasswordDto dto) { + userService.updateUserPasswordByAdmin(dto); + return Result.success(ResultCodeEnum.UPDATE_SUCCESS); + } + + @Operation(summary = "修改用户状态", description = "管理员修改用户状态") + @PutMapping("updateUserStatusByAdmin") + public Result updateUserStatusByAdmin(@Valid @RequestBody AdminUserUpdateUserStatusDto dto) { + userService.updateUserStatusByAdmin(dto); + return Result.success(ResultCodeEnum.UPDATE_SUCCESS); + } + + @Operation(summary = "修改用户头像", description = "管理员修改用户头像") + @PutMapping("uploadAvatarByAdmin") + public Result uploadAvatarByAdmin(@Valid UserUpdateWithAvatarDto dto) { + userService.uploadAvatarByAdmin(dto); + return Result.success(ResultCodeEnum.UPDATE_SUCCESS); + } + + @Operation(summary = "强制退出", description = "强制退出") + @PutMapping("forcedOffline") + public Result forcedOffline(@RequestBody Long id) { + userService.forcedOffline(id); + return Result.success(); + } + + @Operation(summary = "登录发送邮件验证码", description = "登录发送邮件验证码") + @PostMapping("noAuth/sendLoginEmail") + public Result sendLoginEmail(String email) { + userService.sendLoginEmail(email); + return Result.success(ResultCodeEnum.EMAIL_CODE_SEND_SUCCESS); + } + + @Operation(summary = "刷新token", description = "刷新用户token") + @PostMapping("noManage/refreshToken") + public Result refreshToken(@Valid @RequestBody RefreshTokenDto dto) { + RefreshTokenVo vo = userService.refreshToken(dto); + return Result.success(vo); + } + + @Operation(summary = "添加用户信息", description = "添加用户信息") + @PostMapping("addAdminUser") + public Result addAdminUser(@Valid @RequestBody AdminUserAddDto dto) { + userService.addAdminUser(dto); + return Result.success(ResultCodeEnum.ADD_SUCCESS); + } + + @Operation(summary = "退出登录", description = "退出登录") + @PostMapping("noManage/logout") + public Result logout() { + userService.logout(); + return Result.success(ResultCodeEnum.LOGOUT_SUCCESS); + } + + @Operation(summary = "删除用户", description = "删除用户") + @DeleteMapping("deleteAdminUser") + public Mono> deleteAdminUser(@RequestBody List ids) { + userService.deleteAdminUser(ids); + return Mono.just(Result.success(ResultCodeEnum.DELETE_SUCCESS)); + } +} \ No newline at end of file diff --git a/service/src/main/java/cn/bunny/services/controller/system/UserLoginLogController.java b/service/src/main/java/cn/bunny/services/controller/system/UserLoginLogController.java new file mode 100644 index 0000000..ff24d46 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/controller/system/UserLoginLogController.java @@ -0,0 +1,68 @@ +package cn.bunny.services.controller.system; + +import cn.bunny.dao.dto.log.UserLoginLogDto; +import cn.bunny.dao.entity.log.UserLoginLog; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.pojo.result.Result; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.log.UserLoginLogLocalVo; +import cn.bunny.dao.vo.log.UserLoginLogVo; +import cn.bunny.services.service.system.UserLoginLogService; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Mono; + +import java.util.List; + +/** + *

+ * 用户登录日志表 前端控制器 + *

+ * + * @author Bunny + * @since 2024-10-19 01:01:01 + */ +@Tag(name = "用户登录日志", description = "用户登录日志相关接口") +@RestController +@RequestMapping("admin/userLoginLog") +public class UserLoginLogController { + + @Autowired + private UserLoginLogService userLoginLogService; + + @Operation(summary = "分页查询用户登录日志", description = "分页查询用户登录日志") + @GetMapping("getUserLoginLogList/{page}/{limit}") + public Mono>> getUserLoginLogList( + @Parameter(name = "page", description = "当前页", required = true) + @PathVariable("page") Integer page, + @Parameter(name = "limit", description = "每页记录数", required = true) + @PathVariable("limit") Integer limit, + UserLoginLogDto dto) { + Page pageParams = new Page<>(page, limit); + PageResult pageResult = userLoginLogService.getUserLoginLogList(pageParams, dto); + return Mono.just(Result.success(pageResult)); + } + + @Operation(summary = "获取本地用户登录日志", description = "获取本地用户登录日志") + @GetMapping("noManage/getUserLoginLogListByLocalUser/{page}/{limit}") + public Mono>> getUserLoginLogListByLocalUser( + @Parameter(name = "page", description = "当前页", required = true) + @PathVariable("page") Integer page, + @Parameter(name = "limit", description = "每页记录数", required = true) + @PathVariable("limit") Integer limit) { + Page pageParams = new Page<>(page, limit); + PageResult voPageResult = userLoginLogService.getUserLoginLogListByLocalUser(pageParams); + return Mono.just(Result.success(voPageResult)); + } + + @Operation(summary = "删除用户登录日志", description = "删除用户登录日志") + @DeleteMapping("deleteUserLoginLog") + public Mono> deleteUserLoginLog(@RequestBody List ids) { + userLoginLogService.deleteUserLoginLog(ids); + return Mono.just(Result.success(ResultCodeEnum.DELETE_SUCCESS)); + } +} diff --git a/service/src/main/java/cn/bunny/services/controller/system/UserRoleController.java b/service/src/main/java/cn/bunny/services/controller/system/UserRoleController.java new file mode 100644 index 0000000..274617d --- /dev/null +++ b/service/src/main/java/cn/bunny/services/controller/system/UserRoleController.java @@ -0,0 +1,43 @@ +package cn.bunny.services.controller.system; + +import cn.bunny.dao.dto.system.user.AssignRolesToUsersDto; +import cn.bunny.dao.pojo.result.Result; +import cn.bunny.services.service.system.UserRoleService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Mono; + +import java.util.List; + +/** + *

+ * 前端控制器 + *

+ * + * @author Bunny + * @since 2024-09-26 + */ +@Tag(name = "用户和角色", description = "用户和角色相关接口") +@RestController +@RequestMapping("admin/userRole") +public class UserRoleController { + + @Autowired + private UserRoleService userRoleService; + + @Operation(summary = "根据用户id获取角色列", description = "根据用户id获取角色列") + @GetMapping("getRoleListByUserId") + public Mono>> getRoleListByUserId(Long userId) { + List roleVoList = userRoleService.getRoleListByUserId(userId); + return Mono.just(Result.success(roleVoList)); + } + + @Operation(summary = "为用户分配角色", description = "为用户分配角色") + @PostMapping("assignRolesToUsers") + public Mono> assignRolesToUsers(@RequestBody AssignRolesToUsersDto dto) { + userRoleService.assignRolesToUsers(dto); + return Mono.just(Result.success()); + } +} diff --git a/service/src/main/java/cn/bunny/services/factory/EmailFactory.java b/service/src/main/java/cn/bunny/services/factory/EmailFactory.java new file mode 100644 index 0000000..2410570 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/factory/EmailFactory.java @@ -0,0 +1,95 @@ +package cn.bunny.services.factory; + +import cn.bunny.common.service.exception.BunnyException; +import cn.bunny.common.service.utils.mail.MailSenderUtil; +import cn.bunny.dao.entity.system.EmailTemplate; +import cn.bunny.dao.entity.system.EmailUsers; +import cn.bunny.dao.pojo.common.EmailSend; +import cn.bunny.dao.pojo.common.EmailSendInit; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.services.mapper.email.EmailTemplateMapper; +import cn.bunny.services.mapper.email.EmailUsersMapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import jakarta.mail.MessagingException; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; + +@Component +public class EmailFactory { + + @Autowired + private EmailTemplateMapper emailTemplateMapper; + + @Autowired + private EmailUsersMapper emailUsersMapper; + + /** + * * 发送邮件模板 + * 根据已存在的邮件模板发送邮件 + */ + public void sendEmailTemplate(String email, EmailTemplate emailTemplate, HashMap params) { + // 判断邮件模板是否为空 + if (emailTemplate == null) throw new BunnyException(ResultCodeEnum.EMAIL_TEMPLATE_IS_EMPTY); + + // 查询配置发送邮箱,如果没有配置发件者邮箱改用用户列表中默认的,如果默认的也为空则报错 + Long emailUser = emailTemplate.getEmailUser(); + EmailUsers emailUsers; + if (emailUser == null) { + emailUsers = emailUsersMapper.selectOne(Wrappers.lambdaQuery().eq(EmailUsers::getIsDefault, true)); + if (emailUsers == null) throw new BunnyException(ResultCodeEnum.EMAIL_USER_IS_EMPTY); + } else { + emailUsers = emailUsersMapper.selectOne(Wrappers.lambdaQuery().eq(EmailUsers::getId, emailUser)); + } + + // 查询发件者信息 + EmailSendInit emailSendInit = new EmailSendInit(); + BeanUtils.copyProperties(emailUsers, emailSendInit); + emailSendInit.setUsername(emailUsers.getEmail()); + emailSendInit.setProtocol(emailUsers.getSmtpAgreement()); + + // 邮件发送模板 + EmailSend emailSend = new EmailSend(); + emailSend.setSubject(emailTemplate.getSubject()); + emailSend.setSendTo(List.of(email)); + emailSend.setRichText(true); + + // 替换模板中字符串 + final String[] modifiedTemplate = {emailTemplate.getBody()}; + params.forEach((key, value) -> modifiedTemplate[0] = modifiedTemplate[0].replaceAll(key, String.valueOf(value))); + + // 发送邮件 + try { + emailSend.setText(modifiedTemplate[0]); + MailSenderUtil.sendEmail(emailSendInit, emailSend); + } catch (MessagingException e) { + throw new BunnyException(ResultCodeEnum.SEND_MAIL_CODE_ERROR); + } + } + + /** + * * 发送邮件模板 + * 根据邮件模板发送邮件 + */ + public void sendEmailTemplate(String email, Long emailTemplateId, HashMap params) { + EmailTemplate emailTemplate = emailTemplateMapper.selectOne(Wrappers.lambdaQuery().eq(EmailTemplate::getId, emailTemplateId)); + sendEmailTemplate(email, emailTemplate, params); + } + + /** + * 判断邮箱是否添加 + * + * @param isDefault 邮箱是否为默认 + */ + public void updateEmailUserDefault(Boolean isDefault) { + EmailUsers emailUsers = new EmailUsers(); + // 判断状态,如果是默认将所有的内容都设为false + if (isDefault) { + emailUsers.setIsDefault(false); + emailUsersMapper.update(emailUsers, Wrappers.lambdaUpdate().eq(EmailUsers::getIsDefault, true)); + } + } +} \ No newline at end of file diff --git a/service/src/main/java/cn/bunny/services/factory/PowerFactory.java b/service/src/main/java/cn/bunny/services/factory/PowerFactory.java new file mode 100644 index 0000000..48719c8 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/factory/PowerFactory.java @@ -0,0 +1,25 @@ +package cn.bunny.services.factory; + +import cn.bunny.dao.vo.system.rolePower.PowerVo; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component +public class PowerFactory { + + + /** + * * 构建权限树形结构 + * + * @param id 节点ID + * @param powerVoList 节点列表 + * @return 树形列表 + */ + public List handlePowerVoChildren(Long id, List powerVoList) { + return powerVoList.stream() + .filter(powerVo -> powerVo.getParentId().equals(id)) + .peek(powerVo -> powerVo.setChildren(handlePowerVoChildren(powerVo.getId(), powerVoList))) + .toList(); + } +} diff --git a/service/src/main/java/cn/bunny/services/factory/RoleFactory.java b/service/src/main/java/cn/bunny/services/factory/RoleFactory.java new file mode 100644 index 0000000..96cf6fa --- /dev/null +++ b/service/src/main/java/cn/bunny/services/factory/RoleFactory.java @@ -0,0 +1,44 @@ +package cn.bunny.services.factory; + +import cn.bunny.dao.entity.system.AdminUser; +import cn.bunny.dao.pojo.constant.RedisUserConstant; +import cn.bunny.services.mapper.system.UserMapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component +public class RoleFactory { + + @Autowired + private RedisTemplate redisTemplate; + + @Autowired + private UserMapper userMapper; + + @Autowired + private UserFactory userFactory; + + /** + * 批量更新Redis中用户信息 + * + * @param userIds 用户Id列表 + */ + public void updateUserRedisInfo(List userIds) { + // 根据Id查找所有用户 + List adminUsers = userMapper.selectList(Wrappers.lambdaQuery().in(AdminUser::getId, userIds)); + + // 用户为空时不更新Redis的key + if (adminUsers.isEmpty()) return; + + // 更新Redis中用户信息 + adminUsers.stream().filter(user -> { + String adminLoginInfoPrefix = RedisUserConstant.getAdminLoginInfoPrefix(user.getUsername()); + Object object = redisTemplate.opsForValue().get(adminLoginInfoPrefix); + return object != null; + }).forEach(user -> userFactory.buildUserVo(user, RedisUserConstant.REDIS_EXPIRATION_TIME)); + } +} diff --git a/service/src/main/java/cn/bunny/services/factory/RouterServiceFactory.java b/service/src/main/java/cn/bunny/services/factory/RouterServiceFactory.java new file mode 100644 index 0000000..e5b5b97 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/factory/RouterServiceFactory.java @@ -0,0 +1,31 @@ +package cn.bunny.services.factory; + +import cn.bunny.dao.vo.system.router.UserRouterVo; +import org.jetbrains.annotations.NotNull; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; + +@Component +public class RouterServiceFactory { + + /** + * * 递归调用设置子路由 + * + * @param id 主键 + * @param routerVoList 返回VO列表 + * @return 返回路由列表 + */ + public List handleGetChildrenWIthRouter(Long id, @NotNull List routerVoList) { + List list = new ArrayList<>(); + for (UserRouterVo routerVo : routerVoList) { + if (routerVo.getParentId().equals(id)) { + routerVo.setChildren(handleGetChildrenWIthRouter(routerVo.getId(), routerVoList)); + list.add(routerVo); + } + } + + return list; + } +} diff --git a/service/src/main/java/cn/bunny/services/factory/UserFactory.java b/service/src/main/java/cn/bunny/services/factory/UserFactory.java new file mode 100644 index 0000000..cead780 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/factory/UserFactory.java @@ -0,0 +1,237 @@ +package cn.bunny.services.factory; + +import cn.bunny.common.service.utils.JwtHelper; +import cn.bunny.common.service.utils.ip.IpUtil; +import cn.bunny.common.service.utils.minio.MinioUtil; +import cn.bunny.dao.entity.log.UserLoginLog; +import cn.bunny.dao.entity.system.AdminUser; +import cn.bunny.dao.entity.system.Power; +import cn.bunny.dao.entity.system.Role; +import cn.bunny.dao.pojo.constant.LocalDateTimeConstant; +import cn.bunny.dao.pojo.constant.RedisUserConstant; +import cn.bunny.dao.pojo.constant.UserConstant; +import cn.bunny.dao.vo.system.user.LoginVo; +import cn.bunny.services.mapper.system.PowerMapper; +import cn.bunny.services.mapper.system.RoleMapper; +import cn.bunny.services.mapper.system.UserLoginLogMapper; +import cn.bunny.services.mapper.system.UserMapper; +import cn.bunny.services.security.custom.CustomCheckIsAdmin; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.StringUtils; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +@Component +public class UserFactory { + @Autowired + private PowerMapper powerMapper; + + @Autowired + private RoleMapper roleMapper; + + @Autowired + private UserMapper userMapper; + + @Autowired + private UserLoginLogMapper userLoginLogMapper; + + @Autowired + private RedisTemplate redisTemplate; + + @Autowired + private MinioUtil minioUtil; + + @Transactional + public LoginVo buildLoginUserVo(AdminUser user, long readMeDay) { + Long userId = user.getId(); + String email = user.getEmail(); + String username = user.getUsername(); + + // 使用用户名创建token + String token = JwtHelper.createToken(userId, username, (int) readMeDay); + + // 获取IP地址并更新用户登录信息 + String ipAddr = IpUtil.getCurrentUserIpAddress().getIpAddr(); + String ipRegion = IpUtil.getCurrentUserIpAddress().getIpRegion(); + + // 设置用户IP地址,并更新用户信息 + AdminUser updateUser = new AdminUser(); + updateUser.setId(userId); + updateUser.setIpAddress(ipAddr); + updateUser.setIpRegion(ipRegion); + userMapper.updateById(updateUser); + + // 将用户登录保存在用户登录日志表中 + userLoginLogMapper.insert(setUserLoginLog(user, token, ipAddr, ipRegion, "login")); + + // 设置用户返回信息 + LoginVo loginVo = setLoginVo(user, token, readMeDay, ipAddr, ipRegion); + + // 将信息保存在Redis中,一定要确保用户名是唯一的 + redisTemplate.opsForValue().set(RedisUserConstant.getAdminLoginInfoPrefix(username), loginVo, readMeDay, TimeUnit.DAYS); + + // 将Redis中验证码删除 + redisTemplate.delete(RedisUserConstant.getAdminUserEmailCodePrefix(email)); + + return loginVo; + } + + /** + * * 构建用户返回对象LoginVo + * + * @param user 用户对象 + * @param readMeDay 记住我时间 + */ + public void buildUserVo(AdminUser user, long readMeDay) { + Long userId = user.getId(); + String username = user.getUsername(); + + // 使用用户名创建token + String token = JwtHelper.createToken(userId, username, (int) readMeDay); + + // 设置用户返回信息 + LoginVo loginVo = setLoginVo(user, token, readMeDay, user.getIpAddress(), user.getIpRegion()); + + // 将信息保存在Redis中,一定要确保用户名是唯一的 + redisTemplate.opsForValue().set(RedisUserConstant.getAdminLoginInfoPrefix(username), loginVo, readMeDay, TimeUnit.DAYS); + } + + + /** + * * 设置更新用户设置内容 + */ + public LoginVo setLoginVo(AdminUser user, String token, long readMeDay, String ipAddr, String ipRegion) { + Long userId = user.getId(); + + // 判断用户是否有头像,如果没有头像设置默认头像,并且用户头像不能和默认头像相同 + String avatar = checkGetUserAvatar(user.getAvatar()); + + // 查找用户橘色 + List roles = new ArrayList<>(roleMapper.selectListByUserId(userId).stream().map(Role::getRoleCode).toList()); + List permissions = new ArrayList<>(); + + // 判断是否是 admin 如果是admin 赋予所有权限 + boolean isAdmin = CustomCheckIsAdmin.checkAdmin(roles, permissions, user); + if (!isAdmin) { + permissions = powerMapper.selectListByUserId(userId).stream().map(Power::getPowerCode).toList(); + } + + // 计算过期时间,并格式化返回 + LocalDateTime localDateTime = LocalDateTime.now(); + LocalDateTime plusDay = localDateTime.plusDays(readMeDay); + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(LocalDateTimeConstant.YYYY_MM_DD_HH_MM_SS_SLASH); + String expires = plusDay.format(dateTimeFormatter); + + // 构建返回对象,设置用户需要内容 + LoginVo loginVo = new LoginVo(); + BeanUtils.copyProperties(user, loginVo); + loginVo.setNickname(user.getNickname()); + loginVo.setAvatar(avatar); + loginVo.setToken(token); + loginVo.setRefreshToken(token); + loginVo.setIpAddress(ipAddr); + loginVo.setIpRegion(ipRegion); + loginVo.setRoles(roles); + loginVo.setPermissions(permissions); + loginVo.setUpdateUser(userId); + loginVo.setPersonDescription(user.getSummary()); + loginVo.setExpires(expires); + loginVo.setReadMeDay(readMeDay); + + return loginVo; + } + + /** + * 检查用户头像是否合规 + * + * @param avatar 头像字符串 + * @return 整理好的头像内容 + */ + public String checkPostUserAvatar(String avatar) { + // 如果用户没有头像或者用户头像和默认头像相同,返回默认头像 + String userAvatar = UserConstant.USER_AVATAR; + if (!StringUtils.hasText(avatar) || avatar.equals(userAvatar)) return userAvatar; + + // 替换前端发送的host前缀,将其删除,只保留路径名称 + String regex = "^https?://.*?/(.*)"; + Pattern pattern = Pattern.compile(regex); + Matcher matcher = pattern.matcher(avatar); + + // 如果没有匹配 + if (!matcher.matches()) return avatar; + + // 匹配后返回内容 + return "/" + matcher.group(1); + } + + /** + * 检查用户头像是否合规 + * + * @param avatar 头像字符串 + * @return 整理好的头像内容 + */ + public String checkGetUserAvatar(String avatar) { + // 如果用户没有头像或者用户头像和默认头像相同,返回默认头像 + String userAvatar = UserConstant.USER_AVATAR; + if (!StringUtils.hasText(avatar) || avatar.equals(userAvatar)) return userAvatar; + + // 替换前端发送的host前缀,将其删除,只保留路径名称 + String regex = "^https?://.*?/(.*)"; + Pattern pattern = Pattern.compile(regex); + Matcher matcher = pattern.matcher(avatar); + + // 如果没有匹配 + if (matcher.matches()) return avatar; + + // 匹配后返回内容 + return minioUtil.getObjectNameFullPath(avatar); + } + + + /** + * * 设置用户登录日志内容 + */ + public UserLoginLog setUserLoginLog(AdminUser user, String token, String ipAddr, String ipRegion, String type) { + Long userId = user.getId(); + + UserLoginLog userLoginLog = new UserLoginLog(); + userLoginLog.setUsername(user.getUsername()); + userLoginLog.setUserId(userId); + userLoginLog.setIpAddress(ipAddr); + userLoginLog.setIpRegion(ipRegion); + userLoginLog.setToken(token); + userLoginLog.setType(type); + userLoginLog.setCreateUser(userId); + userLoginLog.setUpdateUser(userId); + userLoginLog.setCreateTime(LocalDateTime.now()); + userLoginLog.setUpdateTime(LocalDateTime.now()); + + // 当前请求request + ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + if (requestAttributes == null) return userLoginLog; + HttpServletRequest request = requestAttributes.getRequest(); + + // 获取User-Agent + String userAgent = request.getHeader("User-Agent"); + userLoginLog.setUserAgent(userAgent); + + // 获取X-Requested-With + String xRequestedWith = request.getHeader("X-Requested-With"); + userLoginLog.setXRequestedWith(xRequestedWith); + + return userLoginLog; + } +} \ No newline at end of file diff --git a/service/src/main/java/cn/bunny/services/factory/UserLoginLogFactory.java b/service/src/main/java/cn/bunny/services/factory/UserLoginLogFactory.java new file mode 100644 index 0000000..baded06 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/factory/UserLoginLogFactory.java @@ -0,0 +1,34 @@ +package cn.bunny.services.factory; + +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.vo.log.UserLoginLogVo; +import com.baomidou.mybatisplus.core.metadata.IPage; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component +public class UserLoginLogFactory { + + /** + * 用户登录日志分页查询通用方法 + * + * @param page 分页结果 + * @return 分页用户登录日志 + */ + public PageResult getUserLoginLogVoPageResult(IPage page) { + List voList = page.getRecords().stream().map(userLoginLog -> { + UserLoginLogVo userLoginLogVo = new UserLoginLogVo(); + BeanUtils.copyProperties(userLoginLog, userLoginLogVo); + return userLoginLogVo; + }).toList(); + + return PageResult.builder() + .list(voList) + .pageNo(page.getCurrent()) + .pageSize(page.getSize()) + .total(page.getTotal()) + .build(); + } +} diff --git a/service/src/main/java/cn/bunny/services/mapper/configuration/CategoryMapper.java b/service/src/main/java/cn/bunny/services/mapper/configuration/CategoryMapper.java new file mode 100644 index 0000000..30f0162 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/mapper/configuration/CategoryMapper.java @@ -0,0 +1,40 @@ +package cn.bunny.services.mapper.configuration; + +import cn.bunny.dao.dto.system.configuration.category.CategoryDto; +import cn.bunny.dao.entity.financial.Category; +import cn.bunny.dao.vo.configuration.CategoryVo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 分类信息 Mapper 接口 + *

+ * + * @author Bunny + * @since 2024-11-08 10:29:58 + */ +@Mapper +public interface CategoryMapper extends BaseMapper { + + /** + * * 分页查询分类信息内容 + * + * @param pageParams 分类信息分页参数 + * @param dto 分类信息查询表单 + * @return 分类信息分页结果 + */ + IPage selectListByPage(@Param("page") Page pageParams, @Param("dto") CategoryDto dto); + + /** + * 物理删除分类信息 + * + * @param ids 删除 id 列表 + */ + void deleteBatchIdsWithPhysics(List ids); +} diff --git a/service/src/main/java/cn/bunny/services/mapper/configuration/MenuIconMapper.java b/service/src/main/java/cn/bunny/services/mapper/configuration/MenuIconMapper.java new file mode 100644 index 0000000..6cf5c50 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/mapper/configuration/MenuIconMapper.java @@ -0,0 +1,40 @@ +package cn.bunny.services.mapper.configuration; + +import cn.bunny.dao.dto.system.menuIcon.MenuIconDto; +import cn.bunny.dao.entity.system.MenuIcon; +import cn.bunny.dao.vo.system.MenuIconVo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 系统菜单图标 Mapper 接口 + *

+ * + * @author Bunny + * @since 2024-10-02 12:18:29 + */ +@Mapper +public interface MenuIconMapper extends BaseMapper { + + /** + * * 分页查询系统菜单图标内容 + * + * @param pageParams 系统菜单图标分页参数 + * @param dto 系统菜单图标查询表单 + * @return 系统菜单图标分页结果 + */ + IPage selectListByPage(@Param("page") Page pageParams, @Param("dto") MenuIconDto dto); + + /** + * 物理删除系统菜单图标 + * + * @param ids 删除 id 列表 + */ + void deleteBatchIdsWithPhysics(List ids); +} diff --git a/service/src/main/java/cn/bunny/services/mapper/email/EmailTemplateMapper.java b/service/src/main/java/cn/bunny/services/mapper/email/EmailTemplateMapper.java new file mode 100644 index 0000000..0e6b477 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/mapper/email/EmailTemplateMapper.java @@ -0,0 +1,40 @@ +package cn.bunny.services.mapper.email; + +import cn.bunny.dao.dto.system.email.template.EmailTemplateDto; +import cn.bunny.dao.entity.system.EmailTemplate; +import cn.bunny.dao.vo.system.email.EmailTemplateVo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 邮件模板表 Mapper 接口 + *

+ * + * @author Bunny + * @since 2024-10-10 21:24:08 + */ +@Mapper +public interface EmailTemplateMapper extends BaseMapper { + + /** + * * 分页查询邮件模板表内容 + * + * @param pageParams 邮件模板表分页参数 + * @param dto 邮件模板表查询表单 + * @return 邮件模板表分页结果 + */ + IPage selectListByPage(@Param("page") Page pageParams, @Param("dto") EmailTemplateDto dto); + + /** + * 物理删除邮件模板表 + * + * @param ids 删除 id 列表 + */ + void deleteBatchIdsWithPhysics(List ids); +} diff --git a/service/src/main/java/cn/bunny/services/mapper/email/EmailUsersMapper.java b/service/src/main/java/cn/bunny/services/mapper/email/EmailUsersMapper.java new file mode 100644 index 0000000..7aa92a9 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/mapper/email/EmailUsersMapper.java @@ -0,0 +1,40 @@ +package cn.bunny.services.mapper.email; + +import cn.bunny.dao.dto.system.email.user.EmailUsersDto; +import cn.bunny.dao.entity.system.EmailUsers; +import cn.bunny.dao.vo.system.email.EmailUsersVo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 邮箱用户发送配置 Mapper 接口 + *

+ * + * @author Bunny + * @since 2024-10-10 15:19:22 + */ +@Mapper +public interface EmailUsersMapper extends BaseMapper { + + /** + * * 分页查询邮箱用户发送配置内容 + * + * @param pageParams 邮箱用户发送配置分页参数 + * @param dto 邮箱用户发送配置查询表单 + * @return 邮箱用户发送配置分页结果 + */ + IPage selectListByPage(@Param("page") Page pageParams, @Param("dto") EmailUsersDto dto); + + /** + * 物理删除邮箱用户发送配置 + * + * @param ids 删除 id 列表 + */ + void deleteBatchIdsWithPhysics(List ids); +} diff --git a/service/src/main/java/cn/bunny/services/mapper/financial/BillMapper.java b/service/src/main/java/cn/bunny/services/mapper/financial/BillMapper.java new file mode 100644 index 0000000..628ab2f --- /dev/null +++ b/service/src/main/java/cn/bunny/services/mapper/financial/BillMapper.java @@ -0,0 +1,40 @@ +package cn.bunny.services.mapper.financial; + +import cn.bunny.dao.dto.financial.bill.BillDto; +import cn.bunny.dao.entity.financial.Bill; +import cn.bunny.dao.vo.financial.BillVo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 账单信息 Mapper 接口 + *

+ * + * @author Bunny + * @since 2024-11-07 16:49:19 + */ +@Mapper +public interface BillMapper extends BaseMapper { + + /** + * * 分页查询账单信息内容 + * + * @param pageParams 账单信息分页参数 + * @param dto 账单信息查询表单 + * @return 账单信息分页结果 + */ + IPage selectListByPage(@Param("page") Page pageParams, @Param("dto") BillDto dto, @Param("userId") Long userId); + + /** + * 物理删除账单信息 + * + * @param ids 删除 id 列表 + */ + void deleteBatchIdsWithPhysics(List ids); +} diff --git a/service/src/main/java/cn/bunny/services/mapper/financial/CategoryUserMapper.java b/service/src/main/java/cn/bunny/services/mapper/financial/CategoryUserMapper.java new file mode 100644 index 0000000..bf0e83b --- /dev/null +++ b/service/src/main/java/cn/bunny/services/mapper/financial/CategoryUserMapper.java @@ -0,0 +1,40 @@ +package cn.bunny.services.mapper.financial; + +import cn.bunny.dao.dto.financial.category.CategoryUserDto; +import cn.bunny.dao.entity.financial.Category; +import cn.bunny.dao.vo.financial.CategoryUserVo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 分类信息 Mapper 接口 + *

+ * + * @author Bunny + * @since 2024-11-08 10:00:09 + */ +@Mapper +public interface CategoryUserMapper extends BaseMapper { + + /** + * * 分页查询分类信息内容 + * + * @param pageParams 分类信息分页参数 + * @param dto 分类信息查询表单 + * @return 分类信息分页结果 + */ + IPage selectListByPage(@Param("page") Page pageParams, @Param("dto") CategoryUserDto dto, @Param("userId") Long userId); + + /** + * 物理删除分类信息 + * + * @param ids 删除 id 列表 + */ + void deleteBatchIdsWithPhysics(List ids); +} diff --git a/service/src/main/java/cn/bunny/services/mapper/i18n/I18nMapper.java b/service/src/main/java/cn/bunny/services/mapper/i18n/I18nMapper.java new file mode 100644 index 0000000..1b19e71 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/mapper/i18n/I18nMapper.java @@ -0,0 +1,40 @@ +package cn.bunny.services.mapper.i18n; + +import cn.bunny.dao.dto.i18n.I18nDto; +import cn.bunny.dao.entity.i18n.I18n; +import cn.bunny.dao.vo.i18n.I18nVo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 多语言表 Mapper 接口 + *

+ * + * @author Bunny + * @since 2024-09-28 + */ +@Mapper +public interface I18nMapper extends BaseMapper { + + /** + * * 分页查询多语言内容 + * + * @param pageParams 分页想去 + * @param dto 路由查询表单 + * @return 分页结果 + */ + IPage selectListByPage(@Param("page") Page pageParams, @Param("dto") I18nDto dto); + + /** + * 物理删除多语言 + * + * @param ids 删除 id 列表 + */ + void deleteBatchIdsWithPhysics(List ids); +} diff --git a/service/src/main/java/cn/bunny/services/mapper/i18n/I18nTypeMapper.java b/service/src/main/java/cn/bunny/services/mapper/i18n/I18nTypeMapper.java new file mode 100644 index 0000000..7fa10f3 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/mapper/i18n/I18nTypeMapper.java @@ -0,0 +1,36 @@ +package cn.bunny.services.mapper.i18n; + +import cn.bunny.dao.dto.i18n.I18nTypeDto; +import cn.bunny.dao.entity.i18n.I18nType; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 多语言类型表 Mapper 接口 + *

+ * + * @author Bunny + * @since 2024-09-28 + */ +@Mapper +public interface I18nTypeMapper extends BaseMapper { + + /** + * 物理删除多语言类型 + * + * @param ids 删除 id 列表 + */ + void deleteBatchIdsWithPhysics(List ids); + + /** + * 多语言类型查询 + * + * @param dto 多语言类型查询 + * @return 多语言类型列表 + */ + List selectListByPage(@Param("dto") I18nTypeDto dto); +} diff --git a/service/src/main/java/cn/bunny/services/mapper/message/MessageMapper.java b/service/src/main/java/cn/bunny/services/mapper/message/MessageMapper.java new file mode 100644 index 0000000..837b592 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/mapper/message/MessageMapper.java @@ -0,0 +1,57 @@ +package cn.bunny.services.mapper.message; + +import cn.bunny.dao.dto.system.message.MessageDto; +import cn.bunny.dao.entity.system.Message; +import cn.bunny.dao.vo.system.message.MessageDetailVo; +import cn.bunny.dao.vo.system.message.MessageReceivedWithMessageVo; +import cn.bunny.dao.vo.system.message.MessageReceivedWithUserVo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + *

+ * 系统消息 Mapper 接口 + *

+ * + * @author Bunny + * @since 2024-10-30 15:19:56 + */ +@Mapper +public interface MessageMapper extends BaseMapper { + + /** + * 根据消息id查询消息详情 + * + * @param id 消息id + * @return 消息返回对象 + */ + MessageDetailVo selectMessageVoById(Long id); + + /** + * 根据消息id获取接收人信息 + * + * @param messageId 消息id + * @return 消息接收人用户名等信息 + */ + List selectUserinfoListByMessageId(Long messageId); + + /** + * 物理删除系统消息 + * + * @param ids 删除 id 列表 + */ + void deleteBatchIdsWithPhysics(List ids); + + /** + * 分页查询发送消息 + * + * @param pageParams 分页参数 + * @param dto 查询表单 + * @return 系统消息返回列表 + */ + IPage selectListByPage(Page pageParams, MessageDto dto); +} diff --git a/service/src/main/java/cn/bunny/services/mapper/message/MessageReceivedMapper.java b/service/src/main/java/cn/bunny/services/mapper/message/MessageReceivedMapper.java new file mode 100644 index 0000000..1c752af --- /dev/null +++ b/service/src/main/java/cn/bunny/services/mapper/message/MessageReceivedMapper.java @@ -0,0 +1,59 @@ +package cn.bunny.services.mapper.message; + +import cn.bunny.dao.dto.system.message.MessageReceivedDto; +import cn.bunny.dao.dto.system.message.MessageUserDto; +import cn.bunny.dao.entity.system.Message; +import cn.bunny.dao.entity.system.MessageReceived; +import cn.bunny.dao.vo.system.message.MessageReceivedWithMessageVo; +import cn.bunny.dao.vo.system.message.MessageUserVo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author Bunny + * @since 2024-10-31 + */ +@Mapper +public interface MessageReceivedMapper extends BaseMapper { + + /** + * * 用户消息接收管理分页查询 + * + * @param pageParams 系统消息分页参数 + * @param dto 系统消息查询表单 + * @return 系统消息分页结果 + */ + IPage selectListByMessageReceivedPage(@Param("page") Page pageParams, @Param("dto") MessageReceivedDto dto); + + /** + * 根据id批量删除 + * + * @param ids 主键ids + */ + void deleteBatchIdsWithPhysics(List ids); + + /** + * 根据消息所有包含匹配当前消息Id的列表 + * + * @param pageParams 系统消息分页参数 + * @param dto 系统消息查询表单 + * @return 系统消息分页结果 + */ + IPage selectListByUserMessagePage(@Param("page") Page pageParams, @Param("dto") MessageUserDto dto, @Param("userId") Long userId); + + /** + * 根据消息Id物理删除 + * + * @param ids 消息id + */ + void deleteBatchIdsByMessageIdsWithPhysics(List ids); +} diff --git a/service/src/main/java/cn/bunny/services/mapper/message/MessageTypeMapper.java b/service/src/main/java/cn/bunny/services/mapper/message/MessageTypeMapper.java new file mode 100644 index 0000000..4e7b752 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/mapper/message/MessageTypeMapper.java @@ -0,0 +1,40 @@ +package cn.bunny.services.mapper.message; + +import cn.bunny.dao.dto.system.message.MessageTypeDto; +import cn.bunny.dao.entity.system.MessageType; +import cn.bunny.dao.vo.system.message.MessageTypeVo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 系统消息类型 Mapper 接口 + *

+ * + * @author Bunny + * @since 2024-10-30 13:19:33 + */ +@Mapper +public interface MessageTypeMapper extends BaseMapper { + + /** + * * 分页查询系统消息类型内容 + * + * @param pageParams 系统消息类型分页参数 + * @param dto 系统消息类型查询表单 + * @return 系统消息类型分页结果 + */ + IPage selectListByPage(@Param("page") Page pageParams, @Param("dto") MessageTypeDto dto); + + /** + * 物理删除系统消息类型 + * + * @param ids 删除 id 列表 + */ + void deleteBatchIdsWithPhysics(List ids); +} diff --git a/service/src/main/java/cn/bunny/services/mapper/schedule/ScheduleExecuteLogMapper.java b/service/src/main/java/cn/bunny/services/mapper/schedule/ScheduleExecuteLogMapper.java new file mode 100644 index 0000000..11de5b0 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/mapper/schedule/ScheduleExecuteLogMapper.java @@ -0,0 +1,40 @@ +package cn.bunny.services.mapper.schedule; + +import cn.bunny.dao.dto.log.ScheduleExecuteLogDto; +import cn.bunny.dao.entity.log.ScheduleExecuteLog; +import cn.bunny.dao.vo.log.QuartzExecuteLogVo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 调度任务执行日志 Mapper 接口 + *

+ * + * @author Bunny + * @since 2024-10-18 12:56:39 + */ +@Mapper +public interface ScheduleExecuteLogMapper extends BaseMapper { + + /** + * * 分页查询调度任务执行日志内容 + * + * @param pageParams 调度任务执行日志分页参数 + * @param dto 调度任务执行日志查询表单 + * @return 调度任务执行日志分页结果 + */ + IPage selectListByPage(@Param("page") Page pageParams, @Param("dto") ScheduleExecuteLogDto dto); + + /** + * 物理删除调度任务执行日志 + * + * @param ids 删除 id 列表 + */ + void deleteBatchIdsWithPhysics(List ids); +} diff --git a/service/src/main/java/cn/bunny/services/mapper/schedule/SchedulersGroupMapper.java b/service/src/main/java/cn/bunny/services/mapper/schedule/SchedulersGroupMapper.java new file mode 100644 index 0000000..31017e6 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/mapper/schedule/SchedulersGroupMapper.java @@ -0,0 +1,40 @@ +package cn.bunny.services.mapper.schedule; + +import cn.bunny.dao.dto.quartz.group.SchedulersGroupDto; +import cn.bunny.dao.entity.quartz.SchedulersGroup; +import cn.bunny.dao.vo.quartz.SchedulersGroupVo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 任务调度分组 Mapper 接口 + *

+ * + * @author Bunny + * @since 2024-10-15 20:26:32 + */ +@Mapper +public interface SchedulersGroupMapper extends BaseMapper { + + /** + * * 分页查询任务调度分组内容 + * + * @param pageParams 任务调度分组分页参数 + * @param dto 任务调度分组查询表单 + * @return 任务调度分组分页结果 + */ + IPage selectListByPage(@Param("page") Page pageParams, @Param("dto") SchedulersGroupDto dto); + + /** + * 物理删除任务调度分组 + * + * @param ids 删除 id 列表 + */ + void deleteBatchIdsWithPhysics(List ids); +} diff --git a/service/src/main/java/cn/bunny/services/mapper/schedule/SchedulersMapper.java b/service/src/main/java/cn/bunny/services/mapper/schedule/SchedulersMapper.java new file mode 100644 index 0000000..2346778 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/mapper/schedule/SchedulersMapper.java @@ -0,0 +1,30 @@ +package cn.bunny.services.mapper.schedule; + +import cn.bunny.dao.dto.quartz.schedule.SchedulersDto; +import cn.bunny.dao.entity.quartz.Schedulers; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * Schedulers视图 Mapper 接口 + *

+ * + * @author Bunny + * @since 2024-10-15 16:35:10 + */ +@Mapper +public interface SchedulersMapper extends BaseMapper { + + /** + * * 分页查询Schedulers视图内容 + * + * @param pageParams Schedulers视图分页参数 + * @param dto Schedulers视图查询表单 + * @return Schedulers视图分页结果 + */ + IPage selectListByPage(@Param("page") Page pageParams, @Param("dto") SchedulersDto dto); +} diff --git a/service/src/main/java/cn/bunny/services/mapper/system/DeptMapper.java b/service/src/main/java/cn/bunny/services/mapper/system/DeptMapper.java new file mode 100644 index 0000000..04d4ae5 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/mapper/system/DeptMapper.java @@ -0,0 +1,40 @@ +package cn.bunny.services.mapper.system; + +import cn.bunny.dao.dto.system.dept.DeptDto; +import cn.bunny.dao.entity.system.Dept; +import cn.bunny.dao.vo.system.DeptVo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 部门 Mapper 接口 + *

+ * + * @author Bunny + * @since 2024-10-04 10:39:08 + */ +@Mapper +public interface DeptMapper extends BaseMapper { + + /** + * * 分页查询部门内容 + * + * @param pageParams 部门分页参数 + * @param dto 部门查询表单 + * @return 部门分页结果 + */ + IPage selectListByPage(@Param("page") Page pageParams, @Param("dto") DeptDto dto); + + /** + * 物理删除部门 + * + * @param ids 删除 id 列表 + */ + void deleteBatchIdsWithPhysics(List ids); +} diff --git a/service/src/main/java/cn/bunny/services/mapper/system/FilesMapper.java b/service/src/main/java/cn/bunny/services/mapper/system/FilesMapper.java new file mode 100644 index 0000000..316d2c3 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/mapper/system/FilesMapper.java @@ -0,0 +1,40 @@ +package cn.bunny.services.mapper.system; + +import cn.bunny.dao.dto.system.files.FilesDto; +import cn.bunny.dao.entity.system.Files; +import cn.bunny.dao.vo.system.files.FilesVo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 系统文件表 Mapper 接口 + *

+ * + * @author Bunny + * @since 2024-10-09 16:28:01 + */ +@Mapper +public interface FilesMapper extends BaseMapper { + + /** + * * 分页查询系统文件表内容 + * + * @param pageParams 系统文件表分页参数 + * @param dto 系统文件表查询表单 + * @return 系统文件表分页结果 + */ + IPage selectListByPage(@Param("page") Page pageParams, @Param("dto") FilesDto dto); + + /** + * 物理删除系统文件表 + * + * @param ids 删除 id 列表 + */ + void deleteBatchIdsWithPhysics(List ids); +} diff --git a/service/src/main/java/cn/bunny/services/mapper/system/PowerMapper.java b/service/src/main/java/cn/bunny/services/mapper/system/PowerMapper.java new file mode 100644 index 0000000..8caaa06 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/mapper/system/PowerMapper.java @@ -0,0 +1,50 @@ +package cn.bunny.services.mapper.system; + +import cn.bunny.dao.dto.system.rolePower.power.PowerDto; +import cn.bunny.dao.entity.system.Power; +import cn.bunny.dao.vo.system.rolePower.PowerVo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +/** + *

+ * 权限 Mapper 接口 + *

+ * + * @author Bunny + * @since 2024-10-03 16:00:52 + */ +@Mapper +public interface PowerMapper extends BaseMapper { + + /** + * * 分页查询权限内容 + * + * @param pageParams 权限分页参数 + * @param dto 权限查询表单 + * @return 权限分页结果 + */ + IPage selectListByPage(@Param("page") Page pageParams, @Param("dto") PowerDto dto); + + /** + * 物理删除权限 + * + * @param ids 删除 id 列表 + */ + void deleteBatchIdsWithPhysics(List ids); + + /** + * * 根据用户id查询当前用户所有权限 + * + * @param userId 用户id + */ + @NotNull + List selectListByUserId(long userId); + +} diff --git a/service/src/main/java/cn/bunny/services/mapper/system/RoleMapper.java b/service/src/main/java/cn/bunny/services/mapper/system/RoleMapper.java new file mode 100644 index 0000000..7af905f --- /dev/null +++ b/service/src/main/java/cn/bunny/services/mapper/system/RoleMapper.java @@ -0,0 +1,57 @@ +package cn.bunny.services.mapper.system; + +import cn.bunny.dao.dto.system.rolePower.role.RoleDto; +import cn.bunny.dao.entity.system.Role; +import cn.bunny.dao.vo.system.rolePower.RoleVo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +/** + *

+ * 角色 Mapper 接口 + *

+ * + * @author Bunny + * @since 2024-10-03 14:26:24 + */ +@Mapper +public interface RoleMapper extends BaseMapper { + + /** + * * 分页查询角色内容 + * + * @param pageParams 角色分页参数 + * @param dto 角色查询表单 + * @return 角色分页结果 + */ + IPage selectListByPage(@Param("page") Page pageParams, @Param("dto") RoleDto dto); + + /** + * 物理删除角色 + * + * @param ids 删除 id 列表 + */ + void deleteBatchIdsWithPhysics(List ids); + + /** + * * 根据用户id查询当前用户所有角色 + * + * @param userId 用户id + */ + @NotNull + List selectListByUserId(long userId); + + /** + * * 根据用户Id列表查询用户角色 + * + * @param ids 用户Id列表 + * @return 角色列表 + */ + List selectListByUserIds(List ids); +} diff --git a/service/src/main/java/cn/bunny/services/mapper/system/RolePowerMapper.java b/service/src/main/java/cn/bunny/services/mapper/system/RolePowerMapper.java new file mode 100644 index 0000000..31f7342 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/mapper/system/RolePowerMapper.java @@ -0,0 +1,49 @@ +package cn.bunny.services.mapper.system; + +import cn.bunny.dao.entity.system.RolePower; +import cn.bunny.dao.view.ViewRolePower; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author Bunny + * @since 2024-09-26 + */ +@Mapper +public interface RolePowerMapper extends BaseMapper { + + /** + * * 根据权限id列表删除角色权限相关 + * + * @param powerIds 权限id列表 + */ + void deleteBatchPowerIdsWithPhysics(List powerIds); + + /** + * * 根据角色id删除角色权限 + * + * @param roleIds 角色 + */ + void deleteBatchRoleIdsWithPhysics(List roleIds); + + /** + * * 根据角色id获取权限内容 + * + * @param roleId 角色id + * @return 已选择的权限列表 + */ + List selectPowerListByRoleId(Long roleId); + + /** + * 查看所有角色关联的权限 + * + * @return 角色权限关系视图 + */ + List viewRolePowerWithAll(); +} diff --git a/service/src/main/java/cn/bunny/services/mapper/system/RouterMapper.java b/service/src/main/java/cn/bunny/services/mapper/system/RouterMapper.java new file mode 100644 index 0000000..3c07bbb --- /dev/null +++ b/service/src/main/java/cn/bunny/services/mapper/system/RouterMapper.java @@ -0,0 +1,65 @@ +package cn.bunny.services.mapper.system; + + +import cn.bunny.dao.dto.system.router.RouterManageDto; +import cn.bunny.dao.entity.system.Router; +import cn.bunny.dao.vo.system.router.RouterManageVo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author Bunny + * @since 2024-09-27 + */ +@Mapper +public interface RouterMapper extends BaseMapper { + + /** + * * 根据用户id查找路由内容 + * + * @param userId 用户id + * @return 路由列表 + */ + List selectListByUserId(Long userId); + + /** + * * 递归查询所有父级Id,直到查询到父级Id为0 + * + * @param ids id列表 + * @return 路由列表 + */ + List selectParentListByRouterId(List ids); + + /** + * * 管理菜单列表 + * + * @param pageParams 分页想去 + * @param dto 路由查询表单 + * @return 分页结果 + */ + IPage selectListByPage(@Param("page") Page pageParams, @Param("dto") RouterManageDto dto); + + /** + * * 管理菜单列表不分页 + * + * @param dto 路由查询表单 + * @return 分页结果 + */ + List selectAllList(@Param("dto") RouterManageDto dto); + + /** + * * 物理删除路由菜单 + * + * @param ids 删除id列表 + */ + void deleteBatchIdsWithPhysics(List ids); +} diff --git a/service/src/main/java/cn/bunny/services/mapper/system/RouterRoleMapper.java b/service/src/main/java/cn/bunny/services/mapper/system/RouterRoleMapper.java new file mode 100644 index 0000000..0079ccc --- /dev/null +++ b/service/src/main/java/cn/bunny/services/mapper/system/RouterRoleMapper.java @@ -0,0 +1,48 @@ +package cn.bunny.services.mapper.system; + +import cn.bunny.dao.entity.system.RouterRole; +import cn.bunny.dao.view.ViewRouterRole; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author Bunny + * @since 2024-09-26 + */ +@Mapper +public interface RouterRoleMapper extends BaseMapper { + + /** + * 根据路由id删除所有角色和路由信息 + * + * @param routerIds 路由id + */ + void deleteBatchIdsByRouterIdsWithPhysics(List routerIds); + + /** + * * 根据角色id列表删除角色和路由相关 + * + * @param roleIds 角色id列表 + */ + void deleteBatchIdsByRoleIdsWithPhysics(List roleIds); + + /** + * 查看所有路由关联角色 + * + * @return 路由角色关系视图列表 + */ + List viewRouterRolesWithAll(); + + /** + * 根据Id列表物理删除路由角色关系表 + * + * @param ids 路由角色关系表ids + */ + void deleteBatchIdsWithPhysics(List ids); +} diff --git a/service/src/main/java/cn/bunny/services/mapper/system/UserDeptMapper.java b/service/src/main/java/cn/bunny/services/mapper/system/UserDeptMapper.java new file mode 100644 index 0000000..dab9d3f --- /dev/null +++ b/service/src/main/java/cn/bunny/services/mapper/system/UserDeptMapper.java @@ -0,0 +1,33 @@ +package cn.bunny.services.mapper.system; + +import cn.bunny.dao.entity.system.UserDept; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + *

+ * 部门用户关系表 Mapper 接口 + *

+ * + * @author Bunny + * @since 2024-10-04 + */ +@Mapper +public interface UserDeptMapper extends BaseMapper { + + /** + * * 根据部门id删除部门用户 + * + * @param deptIds 部门id列表 + */ + void deleteBatchIdsByDeptIdWithPhysics(List deptIds); + + /** + * * 根据用户id删除用户部门 + * + * @param userIds 用户id列表 + */ + void deleteBatchIdsByUserIdWithPhysics(List userIds); +} diff --git a/service/src/main/java/cn/bunny/services/mapper/system/UserLoginLogMapper.java b/service/src/main/java/cn/bunny/services/mapper/system/UserLoginLogMapper.java new file mode 100644 index 0000000..45fb616 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/mapper/system/UserLoginLogMapper.java @@ -0,0 +1,48 @@ +package cn.bunny.services.mapper.system; + +import cn.bunny.dao.dto.log.UserLoginLogDto; +import cn.bunny.dao.entity.log.UserLoginLog; +import cn.bunny.dao.vo.log.UserLoginLogVo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 用户登录日志 Mapper 接口 + *

+ * + * @author Bunny + * @since 2024-10-19 01:01:01 + */ +@Mapper +public interface UserLoginLogMapper extends BaseMapper { + + /** + * * 分页查询用户登录日志内容 + * + * @param pageParams 用户登录日志分页参数 + * @param dto 用户登录日志查询表单 + * @return 用户登录日志分页结果 + */ + IPage selectListByPage(@Param("page") Page pageParams, @Param("dto") UserLoginLogDto dto); + + /** + * 物理删除用户登录日志 + * + * @param ids 删除 id 列表 + */ + void deleteBatchIdsWithPhysics(List ids); + + /** + * * 分页查询根据用户Id用户登录日志内容 + * + * @param pageParams 分页查询内容 + * @return 用户登录日志返回列表 + */ + IPage selectListByPageWithLocalUser(Page pageParams, Long id); +} diff --git a/service/src/main/java/cn/bunny/services/mapper/system/UserMapper.java b/service/src/main/java/cn/bunny/services/mapper/system/UserMapper.java new file mode 100644 index 0000000..4cfb0dd --- /dev/null +++ b/service/src/main/java/cn/bunny/services/mapper/system/UserMapper.java @@ -0,0 +1,48 @@ +package cn.bunny.services.mapper.system; + +import cn.bunny.dao.dto.system.user.AdminUserDto; +import cn.bunny.dao.entity.system.AdminUser; +import cn.bunny.dao.view.ViewUserDept; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * 用户信息 Mapper 接口 + *

+ * + * @author Bunny + * @since 2024-09-26 + */ +@Mapper +public interface UserMapper extends BaseMapper { + + /** + * * 分页查询用户信息内容 + * + * @param pageParams 用户信息分页参数 + * @param dto 用户信息查询表单 + * @return 用户信息分页结果 + */ + IPage selectListByPage(@Param("page") Page pageParams, @Param("dto") AdminUserDto dto); + + /** + * 物理删除用户信息 + * + * @param ids 删除 id 列表 + */ + void deleteBatchIdsWithPhysics(List ids); + + /** + * * 查询用户 + * + * @param keyword 查询关键字 + * @return 用户信息列表 + */ + List queryUser(String keyword); +} diff --git a/service/src/main/java/cn/bunny/services/mapper/system/UserRoleMapper.java b/service/src/main/java/cn/bunny/services/mapper/system/UserRoleMapper.java new file mode 100644 index 0000000..6424b70 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/mapper/system/UserRoleMapper.java @@ -0,0 +1,34 @@ +package cn.bunny.services.mapper.system; + +import cn.bunny.dao.entity.system.UserRole; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author Bunny + * @since 2024-09-26 + */ +@Mapper +public interface UserRoleMapper extends BaseMapper { + + /** + * * 删除这个用户id下所有的角色信息 + * + * @param userIds 用户id + */ + void deleteBatchIdsByUserIdsWithPhysics(List userIds); + + /** + * * 根据角色id删除用户和角色 + * + * @param roleIds 角色id列表 + */ + void deleteBatchIdsByRoleIdsWithPhysics(List roleIds); + +} diff --git a/service/src/main/java/cn/bunny/services/quartz/DatabaseBackupJob.java b/service/src/main/java/cn/bunny/services/quartz/DatabaseBackupJob.java new file mode 100644 index 0000000..7b478bb --- /dev/null +++ b/service/src/main/java/cn/bunny/services/quartz/DatabaseBackupJob.java @@ -0,0 +1,74 @@ +package cn.bunny.services.quartz; + +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.quartz.Job; +import org.quartz.JobDataMap; +import org.quartz.JobExecutionContext; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Map; +import java.util.concurrent.TimeUnit; + + +@Slf4j +// @QuartzSchedulers(type = "backup", description = "数据库备份(仅限本地docker中MySQL)") +@Component +public class DatabaseBackupJob implements Job { + + @Value("${bunny.backPath}") + private String backPath; + + @SneakyThrows + @Override + public void execute(JobExecutionContext context) { + // 读取资源目录下脚本文件并写入到主机中 + try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream("static/backup.sh")) { + if (inputStream == null) return; + byte[] bytes = inputStream.readAllBytes(); + Files.write(Path.of(backPath + "/backup.sh"), bytes); + } + + // 执行脚本 + System.setProperty("TERM", "xterm"); + ProcessBuilder processBuilder = new ProcessBuilder("sh", backPath + "/backup.sh"); + processBuilder.redirectErrorStream(true); + Process process = processBuilder.start(); + + // 执行命令 + ProcessHandle handle = process.toHandle(); + + // 执行任务的pid + long pid = handle.pid(); + + // 执行任务系统信息 + JobDataMap jobDataMap = context.getJobDetail().getJobDataMap(); + Map environment = processBuilder.environment(); + String info = handle.info().toString(); + jobDataMap.put("pid", pid); + jobDataMap.put("systemInfo", info); + jobDataMap.put("environment", environment); + + // 进程是否结束 + if (process.waitFor(5, TimeUnit.MINUTES)) { + int waitedFor = process.waitFor(); + jobDataMap.put("existCode", waitedFor); + } else process.destroyForcibly(); + + // 执行后读取内容 + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + String line; + StringBuilder stringBuilder = new StringBuilder(); + while ((line = reader.readLine()) != null) { + stringBuilder.append(line); + System.out.println(line); + } + jobDataMap.put("output", stringBuilder.toString()); + } +} diff --git a/service/src/main/java/cn/bunny/services/quartz/JobHello.java b/service/src/main/java/cn/bunny/services/quartz/JobHello.java new file mode 100644 index 0000000..6d008d1 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/quartz/JobHello.java @@ -0,0 +1,16 @@ +package cn.bunny.services.quartz; + +import cn.bunny.services.aop.annotation.QuartzSchedulers; +import lombok.extern.slf4j.Slf4j; +import org.quartz.Job; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; + +@Slf4j +@QuartzSchedulers(type = "test", description = "JobHello任务内容") +public class JobHello implements Job { + @Override + public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { + System.out.print("执行任务--JobHello。。。。。。。。。"); + } +} diff --git a/service/src/main/java/cn/bunny/services/quartz/JobHello2.java b/service/src/main/java/cn/bunny/services/quartz/JobHello2.java new file mode 100644 index 0000000..521a264 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/quartz/JobHello2.java @@ -0,0 +1,16 @@ +package cn.bunny.services.quartz; + +import cn.bunny.services.aop.annotation.QuartzSchedulers; +import lombok.extern.slf4j.Slf4j; +import org.quartz.Job; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; + +@Slf4j +@QuartzSchedulers(type = "test", description = "Demo的类JobHello2") +public class JobHello2 implements Job { + @Override + public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { + System.out.print("执行任务--JobHello2。。。。。。。。。"); + } +} diff --git a/service/src/main/java/cn/bunny/services/quartz/MailingJob.java b/service/src/main/java/cn/bunny/services/quartz/MailingJob.java new file mode 100644 index 0000000..d316a26 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/quartz/MailingJob.java @@ -0,0 +1,15 @@ +package cn.bunny.services.quartz; + +import cn.bunny.services.aop.annotation.QuartzSchedulers; +import cn.bunny.services.factory.EmailFactory; +import org.quartz.Job; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; + +@QuartzSchedulers(type = "email", description = "定时邮件任务") +public class MailingJob implements Job { + @Override + public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { + EmailFactory emailFactory = new EmailFactory(); + } +} diff --git a/service/src/main/java/cn/bunny/services/security/config/WebSecurityConfig.java b/service/src/main/java/cn/bunny/services/security/config/WebSecurityConfig.java new file mode 100644 index 0000000..ec247a8 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/security/config/WebSecurityConfig.java @@ -0,0 +1,80 @@ +package cn.bunny.services.security.config; + +import cn.bunny.services.security.custom.CustomPasswordEncoder; +import cn.bunny.services.security.filter.TokenLoginFilterService; +import cn.bunny.services.security.handelr.SecurityAccessDeniedHandler; +import cn.bunny.services.security.handelr.SecurityAuthenticationEntryPoint; +import cn.bunny.services.security.service.CustomUserDetailsService; +import cn.bunny.services.security.service.impl.CustomAuthorizationManagerServiceImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; +import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.security.web.util.matcher.RegexRequestMatcher; + +@Configuration +@EnableWebSecurity +@EnableMethodSecurity +public class WebSecurityConfig { + @Autowired + private RedisTemplate redisTemplate; + + @Autowired + private CustomUserDetailsService customUserDetailsService; + + @Autowired + private CustomPasswordEncoder customPasswordEncoder; + + @Autowired + private CustomAuthorizationManagerServiceImpl customAuthorizationManagerService; + + @Autowired + private AuthenticationConfiguration authenticationConfiguration; + + @Bean + public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception { + String[] annotations = { + "/", "/ws/**", + "/*/*/noAuth/**", "/*/noAuth/**", "/noAuth/**", + "/media.ico", "/favicon.ico", "*.html", "/webjars/**", "/v3/api-docs/**", "swagger-ui/**", + "/error", "/*/i18n/getI18n", + }; + httpSecurity + // 前端段分离不需要---禁用明文验证 + .httpBasic(AbstractHttpConfigurer::disable) + // 前端段分离不需要---禁用默认登录页 + .formLogin(AbstractHttpConfigurer::disable) + // 前端段分离不需要---禁用退出页 + .logout(AbstractHttpConfigurer::disable) + // 前端段分离不需要---csrf攻击 + .csrf(AbstractHttpConfigurer::disable) + // 跨域访问权限,如果需要可以关闭后自己配置跨域访问 + .cors(AbstractHttpConfigurer::disable) + // 前后端分离不需要---因为是无状态的 + .sessionManagement(AbstractHttpConfigurer::disable) + // 前后端分离不需要---记住我 + .rememberMe(AbstractHttpConfigurer::disable) + .authorizeHttpRequests(authorize -> authorize.requestMatchers(annotations).permitAll() + .requestMatchers(RegexRequestMatcher.regexMatcher(".*\\.(css|js)$")).permitAll() + .anyRequest().access(customAuthorizationManagerService)) + .exceptionHandling(exception -> { + // 请求未授权接口 + exception.authenticationEntryPoint(new SecurityAuthenticationEntryPoint()); + // 没有权限访问 + exception.accessDeniedHandler(new SecurityAccessDeniedHandler()); + }) + // 登录验证过滤器 + .addFilterBefore(new TokenLoginFilterService(authenticationConfiguration, redisTemplate, customUserDetailsService), UsernamePasswordAuthenticationFilter.class) + // 自定义密码加密器和用户登录 + .passwordManagement(customPasswordEncoder).userDetailsService(customUserDetailsService); + + return httpSecurity.build(); + } +} diff --git a/service/src/main/java/cn/bunny/services/security/custom/CustomCheckIsAdmin.java b/service/src/main/java/cn/bunny/services/security/custom/CustomCheckIsAdmin.java new file mode 100644 index 0000000..4650302 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/security/custom/CustomCheckIsAdmin.java @@ -0,0 +1,51 @@ +package cn.bunny.services.security.custom; + +import cn.bunny.common.service.context.BaseContext; +import cn.bunny.dao.entity.system.AdminUser; + +import java.util.List; + +/** + * 检查是否是管理员 + */ +public class CustomCheckIsAdmin { + + /** + * 判断是否是管理员 + * + * @param roleList 角色代码列表 + * @return 是否是管理员 + */ + public static boolean checkAdmin(List roleList) { + // 判断是否是超级管理员 + if (BaseContext.getUserId().equals(1L)) return true; + + // 判断是否是 admin + return roleList.stream().anyMatch(role -> role.equals("admin")); + } + + /** + * 判断是否是管理员 + * + * @param roleList 角色代码列表 + * @param permissions 权限列表 + * @param adminUser 用户信息 + * @return 是否是管理员 + */ + public static boolean checkAdmin(List roleList, List permissions, AdminUser adminUser) { + // 判断是否是超级管理员 + boolean isIdAdmin = adminUser.getId().equals(1L); + boolean isAdmin = roleList.stream().anyMatch(role -> role.equals("admin")); + + // 判断是否是 admin + if (isIdAdmin || isAdmin) { + roleList.add("admin"); + permissions.add("*"); + permissions.add("*::*"); + permissions.add("*::*::*"); + return true; + } + + return false; + } +} diff --git a/service/src/main/java/cn/bunny/services/security/custom/CustomPasswordEncoder.java b/service/src/main/java/cn/bunny/services/security/custom/CustomPasswordEncoder.java new file mode 100644 index 0000000..0dd6069 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/security/custom/CustomPasswordEncoder.java @@ -0,0 +1,28 @@ +package cn.bunny.services.security.custom; + +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.Customizer; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configurers.PasswordManagementConfigurer; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.util.DigestUtils; + +/** + * 自定义密码加密比对 + */ +@Configuration +public class CustomPasswordEncoder implements PasswordEncoder, Customizer> { + @Override + public String encode(CharSequence rawPassword) { + return DigestUtils.md5DigestAsHex(rawPassword.toString().getBytes()); + } + + @Override + public boolean matches(CharSequence rawPassword, String encodedPassword) { + return encodedPassword.matches(DigestUtils.md5DigestAsHex(rawPassword.toString().getBytes())); + } + + @Override + public void customize(PasswordManagementConfigurer httpSecurityPasswordManagementConfigurer) { + } +} diff --git a/service/src/main/java/cn/bunny/services/security/custom/CustomUser.java b/service/src/main/java/cn/bunny/services/security/custom/CustomUser.java new file mode 100644 index 0000000..5ac7e96 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/security/custom/CustomUser.java @@ -0,0 +1,23 @@ +package cn.bunny.services.security.custom; + +import cn.bunny.dao.entity.system.AdminUser; +import lombok.Getter; +import lombok.Setter; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.User; + +import java.util.Collection; + +/** + * 重写自带的User + */ +@Getter +@Setter +public class CustomUser extends User { + private AdminUser user; + + public CustomUser(AdminUser user, Collection authorities) { + super(user.getUsername(), user.getPassword(), authorities); + this.user = user; + } +} \ No newline at end of file diff --git a/service/src/main/java/cn/bunny/services/security/filter/TokenLoginFilterService.java b/service/src/main/java/cn/bunny/services/security/filter/TokenLoginFilterService.java new file mode 100644 index 0000000..82812eb --- /dev/null +++ b/service/src/main/java/cn/bunny/services/security/filter/TokenLoginFilterService.java @@ -0,0 +1,128 @@ +package cn.bunny.services.security.filter; + + +import cn.bunny.dao.dto.system.user.LoginDto; +import cn.bunny.dao.pojo.constant.RedisUserConstant; +import cn.bunny.dao.pojo.result.Result; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.system.user.LoginVo; +import cn.bunny.services.security.handelr.SecurityAuthenticationFailureHandler; +import cn.bunny.services.security.handelr.SecurityAuthenticationSuccessHandler; +import cn.bunny.services.security.service.CustomUserDetailsService; +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.FilterChain; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.http.HttpMethod; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.util.StringUtils; + +import java.io.IOException; + +import static cn.bunny.common.service.utils.ResponseUtil.out; + +/** + * * UsernamePasswordAuthenticationFilter + * * 也可以在这里添加验证码、短信等的验证 + * 由于SpringSecurity的登录只能是表单形式 并且用户名密码需要时username、password,可以通过继承 UsernamePasswordAuthenticationFilter 获取登录请求的参数 + * 再去设置到 UsernamePasswordAuthenticationToken 中 来改变请求传参方式、参数名等 或者也可以在登录的时候加入其他参数等等 + */ +public class TokenLoginFilterService extends UsernamePasswordAuthenticationFilter { + + private final RedisTemplate redisTemplate; + private final CustomUserDetailsService customUserDetailsService; + private LoginDto loginDto; + + public TokenLoginFilterService(AuthenticationConfiguration authenticationConfiguration, RedisTemplate redisTemplate, CustomUserDetailsService customUserDetailsService) throws Exception { + this.setAuthenticationSuccessHandler(new SecurityAuthenticationSuccessHandler()); + this.setAuthenticationFailureHandler(new SecurityAuthenticationFailureHandler()); + this.setPostOnly(false); + this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/admin/login", HttpMethod.POST.name())); + this.setAuthenticationManager(authenticationConfiguration.getAuthenticationManager()); + this.redisTemplate = redisTemplate; + this.customUserDetailsService = customUserDetailsService; + } + + /** + * * 自定义验证 + * 判断邮箱验证码是否正确 + */ + @Override + public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) { + ObjectMapper objectMapper = new ObjectMapper(); + try { + loginDto = objectMapper.readValue(request.getInputStream(), LoginDto.class); + + // type不能为空 + String type = loginDto.getType(); + if (!StringUtils.hasText(type)) { + out(response, Result.error(ResultCodeEnum.REQUEST_IS_EMPTY)); + return null; + } + + String emailCode = loginDto.getEmailCode(); + String username = loginDto.getUsername(); + String password = loginDto.getPassword(); + + // 如果有邮箱验证码,表示是邮箱登录 + if (type.equals("email")) { + emailCode = emailCode.toLowerCase(); + Object redisEmailCode = redisTemplate.opsForValue().get(RedisUserConstant.getAdminUserEmailCodePrefix(username)); + if (redisEmailCode == null) { + out(response, Result.error(ResultCodeEnum.EMAIL_CODE_EMPTY)); + return null; + } + + // 判断用户邮箱验证码是否和Redis中发送的验证码 + if (!emailCode.equals(redisEmailCode.toString().toLowerCase())) { + out(response, Result.error(ResultCodeEnum.EMAIL_CODE_NOT_MATCHING)); + return null; + } + } + + Authentication authenticationToken = new UsernamePasswordAuthenticationToken(username, password); + return getAuthenticationManager().authenticate(authenticationToken); + } catch (IOException e) { + out(response, Result.error(ResultCodeEnum.ILLEGAL_DATA_REQUEST)); + return null; + } + } + + /** + * 验证成功 + */ + @Override + protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication auth) { + // 获取登录返回信息 + LoginVo loginVo = customUserDetailsService.login(loginDto, response); + if (loginVo == null) return; + + // 判断用户是否禁用 + if (loginVo.getStatus()) { + out(response, Result.error(ResultCodeEnum.FAIL_NO_ACCESS_DENIED_USER_LOCKED)); + return; + } + + out(response, Result.success(loginVo)); + } + + /** + * 验证失败 + */ + @Override + protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) { + String password = loginDto.getPassword(); + String username = loginDto.getUsername(); + + if (!StringUtils.hasText(password) || !StringUtils.hasText(username)) + out(response, Result.error(ResultCodeEnum.USERNAME_OR_PASSWORD_NOT_EMPTY)); + else + out(response, Result.error(null, ResultCodeEnum.LOGIN_ERROR)); + } +} \ No newline at end of file diff --git a/service/src/main/java/cn/bunny/services/security/handelr/SecurityAccessDeniedHandler.java b/service/src/main/java/cn/bunny/services/security/handelr/SecurityAccessDeniedHandler.java new file mode 100644 index 0000000..10ab63c --- /dev/null +++ b/service/src/main/java/cn/bunny/services/security/handelr/SecurityAccessDeniedHandler.java @@ -0,0 +1,26 @@ +package cn.bunny.services.security.handelr; + +import cn.bunny.dao.pojo.result.Result; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import com.alibaba.fastjson2.JSON; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.SneakyThrows; +import org.springframework.security.access.AccessDeniedException; + +/** + * 没有权限访问 + */ +public class SecurityAccessDeniedHandler implements org.springframework.security.web.access.AccessDeniedHandler { + @SneakyThrows + @Override + public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) { + Result result = Result.error(ResultCodeEnum.FAIL_NO_ACCESS_DENIED); + + Object json = JSON.toJSON(result); + + // 返回响应 + response.setContentType("application/json;charset=UTF-8"); + response.getWriter().println(json); + } +} diff --git a/service/src/main/java/cn/bunny/services/security/handelr/SecurityAuthenticationEntryPoint.java b/service/src/main/java/cn/bunny/services/security/handelr/SecurityAuthenticationEntryPoint.java new file mode 100644 index 0000000..b45d885 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/security/handelr/SecurityAuthenticationEntryPoint.java @@ -0,0 +1,35 @@ +package cn.bunny.services.security.handelr; + +import cn.bunny.common.service.utils.ResponseUtil; +import cn.bunny.dao.pojo.result.Result; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.AuthenticationEntryPoint; + +/** + * 请求未认证接口 + */ +@Slf4j +public class SecurityAuthenticationEntryPoint implements AuthenticationEntryPoint { + @Override + public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) { + String token = request.getHeader("token"); + String message = authException.getMessage(); + // 创建结果对象 + Result result; + + if (token == null) { + result = Result.error(ResultCodeEnum.LOGIN_AUTH); + log.info("请求未登录接口:{},用户id:{}", message, null); + } else { + result = Result.error(ResultCodeEnum.LOGGED_IN_FROM_ANOTHER_DEVICE); + log.info("请求未授权接口:{},用户id:{}", message, token); + } + + // 返回响应 + ResponseUtil.out(response, result); + } +} diff --git a/service/src/main/java/cn/bunny/services/security/handelr/SecurityAuthenticationFailureHandler.java b/service/src/main/java/cn/bunny/services/security/handelr/SecurityAuthenticationFailureHandler.java new file mode 100644 index 0000000..98ad1cc --- /dev/null +++ b/service/src/main/java/cn/bunny/services/security/handelr/SecurityAuthenticationFailureHandler.java @@ -0,0 +1,25 @@ +package cn.bunny.services.security.handelr; + +import cn.bunny.dao.pojo.result.Result; +import com.alibaba.fastjson2.JSON; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.security.core.AuthenticationException; + +import java.io.IOException; + +public class SecurityAuthenticationFailureHandler implements org.springframework.security.web.authentication.AuthenticationFailureHandler { + @Override + public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException { + // 错误消息 + String localizedMessage = exception.getLocalizedMessage(); + Result result = Result.error(localizedMessage); + + // 转成JSON + Object json = JSON.toJSON(result); + + // 返回响应 + response.setContentType("application/json;charset=UTF-8"); + response.getWriter().println(json); + } +} diff --git a/service/src/main/java/cn/bunny/services/security/handelr/SecurityAuthenticationSuccessHandler.java b/service/src/main/java/cn/bunny/services/security/handelr/SecurityAuthenticationSuccessHandler.java new file mode 100644 index 0000000..f40dfac --- /dev/null +++ b/service/src/main/java/cn/bunny/services/security/handelr/SecurityAuthenticationSuccessHandler.java @@ -0,0 +1,26 @@ +package cn.bunny.services.security.handelr; + +import cn.bunny.dao.pojo.result.Result; +import com.alibaba.fastjson2.JSON; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.security.core.Authentication; +import org.springframework.security.web.authentication.AuthenticationSuccessHandler; + +import java.io.IOException; + +/** + * 登录成功 + */ +public class SecurityAuthenticationSuccessHandler implements AuthenticationSuccessHandler { + @Override + public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException { + // 获取用户身份信息 + Object principal = authentication.getPrincipal(); + Result result = Result.success(principal); + + // 返回 + response.setContentType("application/json;charset=UTF-8"); + response.getWriter().println(JSON.toJSON(result)); + } +} diff --git a/service/src/main/java/cn/bunny/services/security/service/CustomUserDetailsService.java b/service/src/main/java/cn/bunny/services/security/service/CustomUserDetailsService.java new file mode 100644 index 0000000..af8f6d0 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/security/service/CustomUserDetailsService.java @@ -0,0 +1,24 @@ +package cn.bunny.services.security.service; + +import cn.bunny.dao.dto.system.user.LoginDto; +import cn.bunny.dao.vo.system.user.LoginVo; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; + +public interface CustomUserDetailsService extends UserDetailsService { + /** + * 根据用户名获取用户对象(获取不到直接抛异常) + */ + @Override + UserDetails loadUserByUsername(String username) throws UsernameNotFoundException; + + /** + * 前台用户登录接口 + * + * @param loginDto 登录参数 + * @return 登录后结果返回 + */ + LoginVo login(LoginDto loginDto, HttpServletResponse response); +} diff --git a/service/src/main/java/cn/bunny/services/security/service/impl/CustomAuthorizationManagerServiceImpl.java b/service/src/main/java/cn/bunny/services/security/service/impl/CustomAuthorizationManagerServiceImpl.java new file mode 100644 index 0000000..f1769ff --- /dev/null +++ b/service/src/main/java/cn/bunny/services/security/service/impl/CustomAuthorizationManagerServiceImpl.java @@ -0,0 +1,126 @@ +package cn.bunny.services.security.service.impl; + +import cn.bunny.common.service.context.BaseContext; +import cn.bunny.common.service.utils.JwtHelper; +import cn.bunny.dao.entity.system.Power; +import cn.bunny.dao.entity.system.Role; +import cn.bunny.dao.pojo.constant.RedisUserConstant; +import cn.bunny.dao.vo.system.user.LoginVo; +import cn.bunny.services.mapper.system.PowerMapper; +import cn.bunny.services.mapper.system.RoleMapper; +import cn.bunny.services.security.custom.CustomCheckIsAdmin; +import com.alibaba.fastjson2.JSON; +import jakarta.servlet.http.HttpServletRequest; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.security.authorization.AuthorizationDecision; +import org.springframework.security.authorization.AuthorizationManager; +import org.springframework.security.core.Authentication; +import org.springframework.security.web.access.intercept.RequestAuthorizationContext; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Objects; +import java.util.function.Supplier; + + +/** + * 自定义权限判断 + * 判断用户有哪些权限 + */ +@Component +@Slf4j +public class CustomAuthorizationManagerServiceImpl implements AuthorizationManager { + + @Autowired + private PowerMapper powerMapper; + + @Autowired + private RoleMapper roleMapper; + + @Autowired + private RedisTemplate redisTemplate; + + @SneakyThrows + @Override + public AuthorizationDecision check(Supplier authentication, RequestAuthorizationContext context) { + // 用户的token和用户id、请求Url + HttpServletRequest request = context.getRequest(); + + // 判断是否有 token + String token = request.getHeader("token"); + if (token == null) { + return new AuthorizationDecision(false); + } + + // 判断 token 是否过期 + if (JwtHelper.isExpired(token)) { + return new AuthorizationDecision(false); + } + + // 解析JWT中的用户名 + String username = JwtHelper.getUsername(token); + Long userId = JwtHelper.getUserId(token); + + // 查找 Redis + Object loginVoObject = redisTemplate.opsForValue().get(RedisUserConstant.getAdminLoginInfoPrefix(username)); + LoginVo loginVo = JSON.parseObject(JSON.toJSONString(loginVoObject), LoginVo.class); + + // 登录信息为空 + if (loginVo == null) { + return new AuthorizationDecision(false); + } + + // 判断用户是否禁用 + if (loginVo.getStatus()) { + return new AuthorizationDecision(false); + } + + // 设置用户信息 + BaseContext.setUsername(username); + BaseContext.setUserId(userId); + BaseContext.setLoginVo(loginVo); + + // 校验权限 + return new AuthorizationDecision(hasAuth(request)); + } + + /** + * 查询用户所属的角色信息 + * + * @param request 请求url地址 + */ + private Boolean hasAuth(HttpServletRequest request) { + // 根据用户ID查询角色数据 + Long userId = BaseContext.getUserId(); + List roleList = roleMapper.selectListByUserId(userId); + + // 角色代码 + List roleCodeList = roleList.stream().map(Role::getRoleCode).toList(); + + // 判断是否是管理员用户 + boolean checkedAdmin = CustomCheckIsAdmin.checkAdmin(roleCodeList); + if (checkedAdmin) return true; + + // 判断请求地址是否是 noManage 不需要被验证的 + String requestURI = request.getRequestURI(); + if (requestURI.contains("noManage")) return true; + + // 根据角色列表查询权限信息 + List powerList = powerMapper.selectListByUserId(userId); + + // 判断是否与请求路径匹配 + return powerList.stream().map(Power::getRequestUrl) + .filter(Objects::nonNull) + .anyMatch(requestUrl -> { + if ((requestUrl.contains("/*") || requestUrl.contains("/**"))) { + return new AntPathRequestMatcher(requestUrl).matches(request); + } else { + return requestURI.matches(requestUrl); + } + }); + } +} diff --git a/service/src/main/java/cn/bunny/services/security/service/impl/CustomUserDetailsServiceImpl.java b/service/src/main/java/cn/bunny/services/security/service/impl/CustomUserDetailsServiceImpl.java new file mode 100644 index 0000000..bfcd702 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/security/service/impl/CustomUserDetailsServiceImpl.java @@ -0,0 +1,85 @@ +package cn.bunny.services.security.service.impl; + +import cn.bunny.common.service.exception.BunnyException; +import cn.bunny.dao.dto.system.user.LoginDto; +import cn.bunny.dao.entity.system.AdminUser; +import cn.bunny.dao.pojo.result.Result; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.system.user.LoginVo; +import cn.bunny.services.factory.UserFactory; +import cn.bunny.services.mapper.system.UserMapper; +import cn.bunny.services.security.custom.CustomUser; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Component; +import org.springframework.util.DigestUtils; + +import static cn.bunny.common.service.utils.ResponseUtil.out; + +@Component +public class CustomUserDetailsServiceImpl implements cn.bunny.services.security.service.CustomUserDetailsService { + + @Autowired + private UserMapper userMapper; + + @Autowired + private UserFactory userFactory; + + /** + * 根据用户名获取用户对象(获取不到直接抛异常) + * + * @param username 用户名 + */ + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + // 查询用户相关内容 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper() + .eq(AdminUser::getEmail, username) + .or() + .eq(AdminUser::getUsername, username); + + // 根据邮箱查询用户名 + AdminUser adminUser = userMapper.selectOne(queryWrapper); + if (adminUser == null) throw new UsernameNotFoundException(ResultCodeEnum.USER_IS_EMPTY.getMessage()); + + return new CustomUser(adminUser, AuthorityUtils.createAuthorityList()); + } + + /** + * 前台用户登录接口 + * + * @param loginDto 登录参数 + * @return 登录后结果返回 + */ + @Override + public LoginVo login(LoginDto loginDto, HttpServletResponse response) { + String username = loginDto.getUsername(); + String password = loginDto.getPassword(); + Long readMeDay = loginDto.getReadMeDay(); + + // 查询用户相关内容 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + if (loginDto.getType().equals("email")) { + queryWrapper.eq(AdminUser::getEmail, username); + } else { + queryWrapper.eq(AdminUser::getUsername, username); + } + AdminUser user = userMapper.selectOne(queryWrapper); + + // 判断用户是否为空 + if (user == null) { + out(response, Result.error(ResultCodeEnum.LOGIN_ERROR)); + return null; + } + + // 对登录密码进行md5加密判断,是否与数据库中一致 + String md5Password = DigestUtils.md5DigestAsHex(password.getBytes()); + if (!user.getPassword().equals(md5Password)) throw new BunnyException(ResultCodeEnum.LOGIN_ERROR); + + return userFactory.buildLoginUserVo(user, readMeDay); + } +} diff --git a/service/src/main/java/cn/bunny/services/service/configuration/CategoryService.java b/service/src/main/java/cn/bunny/services/service/configuration/CategoryService.java new file mode 100644 index 0000000..9abe2c7 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/configuration/CategoryService.java @@ -0,0 +1,52 @@ +package cn.bunny.services.service.configuration; + +import cn.bunny.dao.dto.system.configuration.category.CategoryAddDto; +import cn.bunny.dao.dto.system.configuration.category.CategoryDto; +import cn.bunny.dao.dto.system.configuration.category.CategoryUpdateDto; +import cn.bunny.dao.entity.financial.Category; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.vo.configuration.CategoryVo; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import jakarta.validation.Valid; + +import java.util.List; + +/** + *

+ * 分类信息 服务类 + *

+ * + * @author Bunny + * @since 2024-11-08 10:29:58 + */ +public interface CategoryService extends IService { + + /** + * * 获取分类信息列表 + * + * @return 分类信息返回列表 + */ + PageResult getCategoryList(Page pageParams, CategoryDto dto); + + /** + * * 添加分类信息 + * + * @param dto 添加表单 + */ + void addCategory(@Valid CategoryAddDto dto); + + /** + * * 更新分类信息 + * + * @param dto 更新表单 + */ + void updateCategory(@Valid CategoryUpdateDto dto); + + /** + * * 删除|批量删除分类信息类型 + * + * @param ids 删除id列表 + */ + void deleteCategory(List ids); +} diff --git a/service/src/main/java/cn/bunny/services/service/configuration/ConfigurationService.java b/service/src/main/java/cn/bunny/services/service/configuration/ConfigurationService.java new file mode 100644 index 0000000..d53feac --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/configuration/ConfigurationService.java @@ -0,0 +1,29 @@ +package cn.bunny.services.service.configuration; + +import cn.bunny.dao.dto.system.configuration.WebConfigurationDto; +import cn.bunny.dao.entity.configuration.WebConfiguration; +import cn.bunny.dao.vo.configuration.WebConfigurationVo; + +public interface ConfigurationService { + + /** + * * 更新web配置 + * + * @param dto 前端配置选项 + */ + void updateWebConfiguration(WebConfigurationDto dto); + + /** + * 读取web配置文件 + * + * @return 前端配置文件 + */ + WebConfiguration webConfig(); + + /** + * 获取修改web配置文件 + * + * @return 要修改前端配置文件 + */ + WebConfigurationVo getWebConfig(); +} \ No newline at end of file diff --git a/service/src/main/java/cn/bunny/services/service/configuration/MenuIconService.java b/service/src/main/java/cn/bunny/services/service/configuration/MenuIconService.java new file mode 100644 index 0000000..3aec565 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/configuration/MenuIconService.java @@ -0,0 +1,60 @@ +package cn.bunny.services.service.configuration; + +import cn.bunny.dao.dto.system.menuIcon.MenuIconAddDto; +import cn.bunny.dao.dto.system.menuIcon.MenuIconDto; +import cn.bunny.dao.dto.system.menuIcon.MenuIconUpdateDto; +import cn.bunny.dao.entity.system.MenuIcon; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.vo.system.MenuIconVo; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import jakarta.validation.Valid; + +import java.util.List; + +/** + *

+ * 系统菜单图标 服务类 + *

+ * + * @author Bunny + * @since 2024-10-02 12:18:29 + */ +public interface MenuIconService extends IService { + + /** + * * 获取系统菜单图标列表 + * + * @return 系统菜单图标返回列表 + */ + PageResult getMenuIconList(Page pageParams, MenuIconDto dto); + + /** + * * 添加系统菜单图标 + * + * @param dto 添加表单 + */ + void addMenuIcon(@Valid MenuIconAddDto dto); + + /** + * * 更新系统菜单图标 + * + * @param dto 更新表单 + */ + void updateMenuIcon(@Valid MenuIconUpdateDto dto); + + /** + * * 删除|批量删除系统菜单图标类型 + * + * @param ids 删除id列表 + */ + void deleteMenuIcon(List ids); + + /** + * * 获取查询图标名称列表 + * + * @param iconName 查询图标名称 + * @return 图标返回列表 + */ + List getIconNameList(String iconName); +} diff --git a/service/src/main/java/cn/bunny/services/service/configuration/impl/CategoryServiceImpl.java b/service/src/main/java/cn/bunny/services/service/configuration/impl/CategoryServiceImpl.java new file mode 100644 index 0000000..4a6dcca --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/configuration/impl/CategoryServiceImpl.java @@ -0,0 +1,89 @@ +package cn.bunny.services.service.configuration.impl; + +import cn.bunny.common.service.context.BaseContext; +import cn.bunny.dao.dto.system.configuration.category.CategoryAddDto; +import cn.bunny.dao.dto.system.configuration.category.CategoryDto; +import cn.bunny.dao.dto.system.configuration.category.CategoryUpdateDto; +import cn.bunny.dao.entity.financial.Category; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.vo.configuration.CategoryVo; +import cn.bunny.services.mapper.configuration.CategoryMapper; +import cn.bunny.services.service.configuration.CategoryService; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import jakarta.validation.Valid; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 分类信息 服务实现类 + *

+ * + * @author Bunny + * @since 2024-11-08 10:29:58 + */ +@Service +public class CategoryServiceImpl extends ServiceImpl implements CategoryService { + + /** + * * 分类信息 服务实现类 + * + * @param pageParams 分类信息分页查询page对象 + * @param dto 分类信息分页查询对象 + * @return 查询分页分类信息返回对象 + */ + @Override + public PageResult getCategoryList(Page pageParams, CategoryDto dto) { + IPage page = baseMapper.selectListByPage(pageParams, dto); + + return PageResult.builder() + .list(page.getRecords()) + .pageNo(page.getCurrent()) + .pageSize(page.getSize()) + .total(page.getTotal()) + .build(); + } + + /** + * 添加分类信息 + * + * @param dto 分类信息添加 + */ + @Override + public void addCategory(@Valid CategoryAddDto dto) { + // 保存数据 + Category category = new Category(); + BeanUtils.copyProperties(dto, category); + + // 如果内置的id为空设置为当前用户的id + category.setUserId(category.getUserId() == null ? BaseContext.getUserId() : dto.getUserId()); + save(category); + } + + /** + * 更新分类信息 + * + * @param dto 分类信息更新 + */ + @Override + public void updateCategory(@Valid CategoryUpdateDto dto) { + // 更新内容 + Category category = new Category(); + BeanUtils.copyProperties(dto, category); + updateById(category); + } + + /** + * 删除|批量删除分类信息 + * + * @param ids 删除id列表 + */ + @Override + public void deleteCategory(List ids) { + baseMapper.deleteBatchIdsWithPhysics(ids); + } +} diff --git a/service/src/main/java/cn/bunny/services/service/configuration/impl/ConfigurationServiceImpl.java b/service/src/main/java/cn/bunny/services/service/configuration/impl/ConfigurationServiceImpl.java new file mode 100644 index 0000000..2dda29e --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/configuration/impl/ConfigurationServiceImpl.java @@ -0,0 +1,104 @@ +package cn.bunny.services.service.configuration.impl; + +import cn.bunny.common.service.exception.BunnyException; +import cn.bunny.dao.dto.system.configuration.WebConfigurationDto; +import cn.bunny.dao.entity.configuration.WebConfiguration; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.configuration.WebConfigurationVo; +import cn.bunny.services.service.configuration.ConfigurationService; +import com.alibaba.fastjson2.JSON; +import org.jetbrains.annotations.NotNull; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; + +@Service +public class ConfigurationServiceImpl implements ConfigurationService { + + @Value("${bunny.bashPath}") + private String bashPath; + + private static @NotNull String getWebConfigString(InputStream inputStream, Path templatePath) throws IOException { + if (inputStream == null) throw new BunnyException(ResultCodeEnum.MISSING_TEMPLATE_FILES); + + // 判断web模板文件是否存在,不存在进行复制 + boolean exists = Files.exists(templatePath); + if (!exists) Files.copy(inputStream, templatePath); + + // 将读取文件返回 + byte[] bytes = Files.readAllBytes(templatePath); + return new String(bytes); + } + + /** + * * 更新web配置 + * + * @param dto 前端配置选项 + */ + @Override + @CacheEvict(cacheNames = "webConfig", key = "'platformConfig'", beforeInvocation = true, cacheManager = "cacheManagerWithMouth") + public void updateWebConfiguration(WebConfigurationDto dto) { + try { + // 系统模板文件位置 + Path templatePath = Path.of(bashPath + "/platform-config.json"); + + // 提交表单转换 + WebConfiguration webConfiguration = new WebConfiguration(); + BeanUtils.copyProperties(dto, webConfiguration); + + // 将表单转成存储的类型 + WebConfigurationVo webConfigurationVo = new WebConfigurationVo(); + BeanUtils.copyProperties(webConfiguration, webConfigurationVo); + + // 将文件写入 + String jsonString = JSON.toJSONString(webConfigurationVo); + Files.writeString(templatePath, jsonString); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + /** + * 读取web配置文件 + * + * @return 前端配置文件 + */ + @Override + @Cacheable(cacheNames = "webConfig", key = "'platformConfig'", cacheManager = "cacheManagerWithMouth") + public WebConfiguration webConfig() { + // 系统模板文件位置 + Path templatePath = Path.of(bashPath + "/platform-config.json"); + + try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream("static/platform-config.json")) { + String string = getWebConfigString(inputStream, templatePath); + return JSON.parseObject(string, WebConfiguration.class); + } catch (IOException exception) { + throw new BunnyException(exception.getMessage()); + } + } + + /** + * 获取修改web配置文件 + * + * @return 要修改前端配置文件 + */ + @Override + public WebConfigurationVo getWebConfig() { + // 系统模板文件位置 + Path templatePath = Path.of(bashPath + "/platform-config.json"); + + try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream("static/platform-config.json")) { + String string = getWebConfigString(inputStream, templatePath); + return JSON.parseObject(string, WebConfigurationVo.class); + } catch (IOException exception) { + throw new BunnyException(exception.getMessage()); + } + } +} diff --git a/service/src/main/java/cn/bunny/services/service/configuration/impl/MenuIconServiceImpl.java b/service/src/main/java/cn/bunny/services/service/configuration/impl/MenuIconServiceImpl.java new file mode 100644 index 0000000..a5a2cf5 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/configuration/impl/MenuIconServiceImpl.java @@ -0,0 +1,112 @@ +package cn.bunny.services.service.configuration.impl; + +import cn.bunny.common.service.exception.BunnyException; +import cn.bunny.dao.dto.system.menuIcon.MenuIconAddDto; +import cn.bunny.dao.dto.system.menuIcon.MenuIconDto; +import cn.bunny.dao.dto.system.menuIcon.MenuIconUpdateDto; +import cn.bunny.dao.entity.system.MenuIcon; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.system.MenuIconVo; +import cn.bunny.services.mapper.configuration.MenuIconMapper; +import cn.bunny.services.service.configuration.MenuIconService; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import jakarta.validation.Valid; +import org.springframework.beans.BeanUtils; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.stream.Collectors; + +/** + *

+ * 系统菜单图标 服务实现类 + *

+ * + * @author Bunny + * @since 2024-10-02 12:18:29 + */ +@Service +@Transactional +public class MenuIconServiceImpl extends ServiceImpl implements MenuIconService { + + /** + * * 系统菜单图标 服务实现类 + * + * @param pageParams 系统菜单图标分页查询page对象 + * @param dto 系统菜单图标分页查询对象 + * @return 查询分页系统菜单图标返回对象 + */ + @Override + public PageResult getMenuIconList(Page pageParams, MenuIconDto dto) { + // 分页查询菜单图标 + IPage page = baseMapper.selectListByPage(pageParams, dto); + return PageResult.builder() + .list(page.getRecords()) + .pageNo(page.getCurrent()) + .pageSize(page.getSize()) + .total(page.getTotal()) + .build(); + } + + /** + * * 获取查询图标名称列表 + * + * @param iconName 查询图标名称 + * @return 图标返回列表 + */ + @Override + public List getIconNameList(String iconName) { + return list(Wrappers.lambdaQuery().like(MenuIcon::getIconName, iconName)) + .stream().collect(Collectors.toMap(MenuIcon::getIconName, menuIcon -> { + MenuIconVo menuIconVo = new MenuIconVo(); + BeanUtils.copyProperties(menuIcon, menuIconVo); + return menuIconVo; + }, (existing, replacement) -> existing)).values().stream().toList(); + } + + /** + * 添加系统菜单图标 + * + * @param dto 系统菜单图标添加 + */ + @Override + @CacheEvict(cacheNames = "menuIcon", key = "'menuIconList'", beforeInvocation = true) + public void addMenuIcon(MenuIconAddDto dto) { + MenuIcon menuIcon = new MenuIcon(); + BeanUtils.copyProperties(dto, menuIcon); + save(menuIcon); + } + + /** + * 更新系统菜单图标 + * + * @param dto 系统菜单图标更新 + */ + @Override + @CacheEvict(cacheNames = "menuIcon", key = "'menuIconList'", beforeInvocation = true) + public void updateMenuIcon(@Valid MenuIconUpdateDto dto) { + MenuIcon menuIcon = new MenuIcon(); + BeanUtils.copyProperties(dto, menuIcon); + updateById(menuIcon); + } + + /** + * 删除|批量删除系统菜单图标 + * + * @param ids 删除id列表 + */ + @Override + @CacheEvict(cacheNames = "menuIcon", key = "'menuIconList'", beforeInvocation = true) + public void deleteMenuIcon(List ids) { + // 判断数据请求是否为空 + if (ids.isEmpty()) throw new BunnyException(ResultCodeEnum.REQUEST_IS_EMPTY); + + baseMapper.deleteBatchIdsWithPhysics(ids); + } +} diff --git a/service/src/main/java/cn/bunny/services/service/email/EmailTemplateService.java b/service/src/main/java/cn/bunny/services/service/email/EmailTemplateService.java new file mode 100644 index 0000000..425dd0b --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/email/EmailTemplateService.java @@ -0,0 +1,60 @@ +package cn.bunny.services.service.email; + +import cn.bunny.dao.dto.system.email.template.EmailTemplateAddDto; +import cn.bunny.dao.dto.system.email.template.EmailTemplateDto; +import cn.bunny.dao.dto.system.email.template.EmailTemplateUpdateDto; +import cn.bunny.dao.entity.system.EmailTemplate; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.vo.system.email.EmailTemplateVo; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import jakarta.validation.Valid; + +import java.util.List; +import java.util.Map; + +/** + *

+ * 邮件模板表 服务类 + *

+ * + * @author Bunny + * @since 2024-10-10 21:24:08 + */ +public interface EmailTemplateService extends IService { + + /** + * * 获取邮件模板表列表 + * + * @return 邮件模板表返回列表 + */ + PageResult getEmailTemplateList(Page pageParams, EmailTemplateDto dto); + + /** + * * 添加邮件模板表 + * + * @param dto 添加表单 + */ + void addEmailTemplate(@Valid EmailTemplateAddDto dto); + + /** + * * 更新邮件模板表 + * + * @param dto 更新表单 + */ + void updateEmailTemplate(@Valid EmailTemplateUpdateDto dto); + + /** + * * 删除|批量删除邮件模板表类型 + * + * @param ids 删除id列表 + */ + void deleteEmailTemplate(List ids); + + /** + * * 获取模板类型字段 + * + * @return 枚举字段列表 + */ + List> getEmailTypes(); +} diff --git a/service/src/main/java/cn/bunny/services/service/email/EmailUsersService.java b/service/src/main/java/cn/bunny/services/service/email/EmailUsersService.java new file mode 100644 index 0000000..87a1e01 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/email/EmailUsersService.java @@ -0,0 +1,69 @@ +package cn.bunny.services.service.email; + +import cn.bunny.dao.dto.system.email.user.EmailUserUpdateStatusDto; +import cn.bunny.dao.dto.system.email.user.EmailUsersAddDto; +import cn.bunny.dao.dto.system.email.user.EmailUsersDto; +import cn.bunny.dao.dto.system.email.user.EmailUsersUpdateDto; +import cn.bunny.dao.entity.system.EmailUsers; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.vo.system.email.EmailUsersVo; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import jakarta.validation.Valid; + +import java.util.List; +import java.util.Map; + +/** + *

+ * 邮箱用户发送配置 服务类 + *

+ * + * @author Bunny + * @since 2024-10-10 15:19:22 + */ +public interface EmailUsersService extends IService { + + /** + * * 获取邮箱用户发送配置列表 + * + * @return 邮箱用户发送配置返回列表 + */ + PageResult getEmailUsersList(Page pageParams, EmailUsersDto dto); + + /** + * * 添加邮箱用户发送配置 + * + * @param dto 添加表单 + */ + void addEmailUsers(@Valid EmailUsersAddDto dto); + + /** + * * 更新邮箱用户发送配置 + * + * @param dto 更新表单 + */ + void updateEmailUsers(@Valid EmailUsersUpdateDto dto); + + /** + * * 删除|批量删除邮箱用户发送配置类型 + * + * @param ids 删除id列表 + */ + void deleteEmailUsers(List ids); + + /** + * * 更新邮箱用户状态 + * + * @param dto 邮箱用户更新状态表单 + */ + void updateEmailUserStatus(EmailUserUpdateStatusDto dto); + + /** + * * 获取所有邮箱配置用户 + * + * @return 邮件用户列表 + */ + List> getAllMailboxConfigurationUsers(); + +} diff --git a/service/src/main/java/cn/bunny/services/service/email/impl/EmailTemplateServiceImpl.java b/service/src/main/java/cn/bunny/services/service/email/impl/EmailTemplateServiceImpl.java new file mode 100644 index 0000000..abbe244 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/email/impl/EmailTemplateServiceImpl.java @@ -0,0 +1,114 @@ +package cn.bunny.services.service.email.impl; + +import cn.bunny.common.service.exception.BunnyException; +import cn.bunny.dao.dto.system.email.template.EmailTemplateAddDto; +import cn.bunny.dao.dto.system.email.template.EmailTemplateDto; +import cn.bunny.dao.dto.system.email.template.EmailTemplateUpdateDto; +import cn.bunny.dao.entity.system.EmailTemplate; +import cn.bunny.dao.pojo.enums.EmailTemplateEnums; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.system.email.EmailTemplateVo; +import cn.bunny.services.mapper.email.EmailTemplateMapper; +import cn.bunny.services.service.email.EmailTemplateService; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import jakarta.validation.Valid; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + *

+ * 邮件模板表 服务实现类 + *

+ * + * @author Bunny + * @since 2024-10-10 21:24:08 + */ +@Service +public class EmailTemplateServiceImpl extends ServiceImpl implements EmailTemplateService { + + /** + * * 邮件模板表 服务实现类 + * + * @param pageParams 邮件模板表分页查询page对象 + * @param dto 邮件模板表分页查询对象 + * @return 查询分页邮件模板表返回对象 + */ + @Override + public PageResult getEmailTemplateList(Page pageParams, EmailTemplateDto dto) { + IPage page = baseMapper.selectListByPage(pageParams, dto); + + return PageResult.builder() + .list(page.getRecords()) + .pageNo(page.getCurrent()) + .pageSize(page.getSize()) + .total(page.getTotal()) + .build(); + } + + /** + * 添加邮件模板表 + * + * @param dto 邮件模板表添加 + */ + @Override + public void addEmailTemplate(@Valid EmailTemplateAddDto dto) { + // 保存数据 + EmailTemplate emailTemplate = new EmailTemplate(); + BeanUtils.copyProperties(dto, emailTemplate); + save(emailTemplate); + } + + /** + * 更新邮件模板表 + * + * @param dto 邮件模板表更新 + */ + @Override + public void updateEmailTemplate(@Valid EmailTemplateUpdateDto dto) { + // 查询是否有这个模板 + List emailTemplateList = list(Wrappers.lambdaQuery().eq(EmailTemplate::getId, dto.getId())); + if (emailTemplateList.isEmpty()) throw new BunnyException(ResultCodeEnum.DATA_NOT_EXIST); + + // 更新内容 + EmailTemplate emailTemplate = new EmailTemplate(); + BeanUtils.copyProperties(dto, emailTemplate); + updateById(emailTemplate); + } + + /** + * 删除|批量删除邮件模板表 + * + * @param ids 删除id列表 + */ + @Override + public void deleteEmailTemplate(List ids) { + // 判断数据请求是否为空 + if (ids.isEmpty()) throw new BunnyException(ResultCodeEnum.REQUEST_IS_EMPTY); + + baseMapper.deleteBatchIdsWithPhysics(ids); + } + + /** + * * 获取模板类型字段 + * + * @return 枚举字段列表 + */ + @Override + public List> getEmailTypes() { + return Arrays.stream(EmailTemplateEnums.values()).map(emailTemplateEnums -> { + Map map = new HashMap<>(); + map.put("key", emailTemplateEnums.getSummary()); + map.put("value", emailTemplateEnums.getType()); + return map; + }).toList(); + } +} diff --git a/service/src/main/java/cn/bunny/services/service/email/impl/EmailUsersServiceImpl.java b/service/src/main/java/cn/bunny/services/service/email/impl/EmailUsersServiceImpl.java new file mode 100644 index 0000000..9cd8cdd --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/email/impl/EmailUsersServiceImpl.java @@ -0,0 +1,137 @@ +package cn.bunny.services.service.email.impl; + +import cn.bunny.common.service.exception.BunnyException; +import cn.bunny.dao.dto.system.email.user.EmailUserUpdateStatusDto; +import cn.bunny.dao.dto.system.email.user.EmailUsersAddDto; +import cn.bunny.dao.dto.system.email.user.EmailUsersDto; +import cn.bunny.dao.dto.system.email.user.EmailUsersUpdateDto; +import cn.bunny.dao.entity.system.EmailUsers; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.system.email.EmailUsersVo; +import cn.bunny.services.factory.EmailFactory; +import cn.bunny.services.mapper.email.EmailUsersMapper; +import cn.bunny.services.service.email.EmailUsersService; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import jakarta.validation.Valid; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + *

+ * 邮箱用户发送配置 服务实现类 + *

+ * + * @author Bunny + * @since 2024-10-10 15:19:22 + */ +@Service +@Transactional +public class EmailUsersServiceImpl extends ServiceImpl implements EmailUsersService { + + @Autowired + private EmailFactory emailFactory; + + /** + * * 邮箱用户发送配置 服务实现类 + * + * @param pageParams 邮箱用户发送配置分页查询page对象 + * @param dto 邮箱用户发送配置分页查询对象 + * @return 查询分页邮箱用户发送配置返回对象 + */ + @Override + public PageResult getEmailUsersList(Page pageParams, EmailUsersDto dto) { + IPage page = baseMapper.selectListByPage(pageParams, dto); + + return PageResult.builder() + .list(page.getRecords()) + .pageNo(page.getCurrent()) + .pageSize(page.getSize()) + .total(page.getTotal()) + .build(); + } + + /** + * 添加邮箱用户发送配置 + * + * @param dto 邮箱用户发送配置添加 + */ + @Override + public void addEmailUsers(EmailUsersAddDto dto) { + // 更新邮箱默认状态 + emailFactory.updateEmailUserDefault(dto.getIsDefault()); + + // 保存数据 + EmailUsers emailUsers = new EmailUsers(); + BeanUtils.copyProperties(dto, emailUsers); + save(emailUsers); + } + + + /** + * 更新邮箱用户发送配置 + * + * @param dto 邮箱用户发送配置更新 + */ + @Override + public void updateEmailUsers(@Valid EmailUsersUpdateDto dto) { + // 更新邮箱默认状态 + emailFactory.updateEmailUserDefault(dto.getIsDefault()); + + // 更新内容 + EmailUsers emailUsers = new EmailUsers(); + BeanUtils.copyProperties(dto, emailUsers); + updateById(emailUsers); + } + + /** + * 删除|批量删除邮箱用户发送配置 + * + * @param ids 删除id列表 + */ + @Override + public void deleteEmailUsers(List ids) { + // 判断数据请求是否为空 + if (ids.isEmpty()) throw new BunnyException(ResultCodeEnum.REQUEST_IS_EMPTY); + + baseMapper.deleteBatchIdsWithPhysics(ids); + } + + /** + * * 更新邮箱用户状态 + * + * @param dto 邮箱用户更新状态表单 + */ + @Override + public void updateEmailUserStatus(EmailUserUpdateStatusDto dto) { + // 更新邮箱默认状态 + emailFactory.updateEmailUserDefault(dto.getIsDefault()); + + EmailUsers emailUsers = new EmailUsers(); + BeanUtils.copyProperties(dto, emailUsers); + updateById(emailUsers); + } + + /** + * * 获取所有邮箱配置用户 + * + * @return 邮件用户列表 + */ + @Override + public List> getAllMailboxConfigurationUsers() { + return list().stream().map(emailUsers -> { + Map map = new HashMap<>(); + map.put("key", emailUsers.getEmail()); + map.put("value", emailUsers.getId().toString()); + return map; + }).toList(); + } +} diff --git a/service/src/main/java/cn/bunny/services/service/financial/BillService.java b/service/src/main/java/cn/bunny/services/service/financial/BillService.java new file mode 100644 index 0000000..39ca436 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/financial/BillService.java @@ -0,0 +1,52 @@ +package cn.bunny.services.service.financial; + +import cn.bunny.dao.dto.financial.bill.BillAddDto; +import cn.bunny.dao.dto.financial.bill.BillDto; +import cn.bunny.dao.dto.financial.bill.BillUpdateDto; +import cn.bunny.dao.entity.financial.Bill; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.vo.financial.BillVo; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import jakarta.validation.Valid; + +import java.util.List; + +/** + *

+ * 账单信息 服务类 + *

+ * + * @author Bunny + * @since 2024-11-07 16:49:19 + */ +public interface BillService extends IService { + + /** + * * 获取账单信息列表 + * + * @return 账单信息返回列表 + */ + PageResult getBillList(Page pageParams, BillDto dto); + + /** + * * 添加账单信息 + * + * @param dto 添加表单 + */ + void addBill(@Valid BillAddDto dto); + + /** + * * 更新账单信息 + * + * @param dto 更新表单 + */ + void updateBill(@Valid BillUpdateDto dto); + + /** + * * 删除|批量删除账单信息类型 + * + * @param ids 删除id列表 + */ + void deleteBill(List ids); +} diff --git a/service/src/main/java/cn/bunny/services/service/financial/CategoryUserService.java b/service/src/main/java/cn/bunny/services/service/financial/CategoryUserService.java new file mode 100644 index 0000000..3178d82 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/financial/CategoryUserService.java @@ -0,0 +1,59 @@ +package cn.bunny.services.service.financial; + +import cn.bunny.dao.dto.financial.category.CategoryUserAddDto; +import cn.bunny.dao.dto.financial.category.CategoryUserDto; +import cn.bunny.dao.dto.financial.category.CategoryUserUpdateDto; +import cn.bunny.dao.entity.financial.Category; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.vo.financial.CategoryUserVo; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import jakarta.validation.Valid; + +import java.util.List; + +/** + *

+ * 分类信息 服务类 + *

+ * + * @author Bunny + * @since 2024-11-08 10:00:09 + */ +public interface CategoryUserService extends IService { + + /** + * * 用户分类分页查询分类信息 + * + * @return 分类信息返回列表 + */ + PageResult getCategoryUserList(Page pageParams, CategoryUserDto dto); + + /** + * * 用戶分类添加分类信息 + * + * @param dto 添加表单 + */ + void addCategoryUser(@Valid CategoryUserAddDto dto); + + /** + * * 用户分类更新分类信息 + * + * @param dto 更新表单 + */ + void updateCategoryUser(@Valid CategoryUserUpdateDto dto); + + /** + * * 用户分类删除分类信息|批量删除分类信息类型 + * + * @param ids 删除id列表 + */ + void deleteCategoryUser(List ids); + + /** + * 查询当前用户下所有的分类 + * + * @return 当前用户分类返回列表 + */ + List getCategoryUserAllList(); +} diff --git a/service/src/main/java/cn/bunny/services/service/financial/impl/BillServiceImpl.java b/service/src/main/java/cn/bunny/services/service/financial/impl/BillServiceImpl.java new file mode 100644 index 0000000..5942536 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/financial/impl/BillServiceImpl.java @@ -0,0 +1,90 @@ +package cn.bunny.services.service.financial.impl; + +import cn.bunny.common.service.context.BaseContext; +import cn.bunny.dao.dto.financial.bill.BillAddDto; +import cn.bunny.dao.dto.financial.bill.BillDto; +import cn.bunny.dao.dto.financial.bill.BillUpdateDto; +import cn.bunny.dao.entity.financial.Bill; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.vo.financial.BillVo; +import cn.bunny.services.mapper.financial.BillMapper; +import cn.bunny.services.service.financial.BillService; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import jakarta.validation.Valid; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 账单信息 服务实现类 + *

+ * + * @author Bunny + * @since 2024-11-07 16:49:19 + */ +@Service +public class BillServiceImpl extends ServiceImpl implements BillService { + + /** + * * 账单信息 服务实现类 + * + * @param pageParams 账单信息分页查询page对象 + * @param dto 账单信息分页查询对象 + * @return 查询分页账单信息返回对象 + */ + @Override + public PageResult getBillList(Page pageParams, BillDto dto) { + // 需要根据当前用户去查询 + Long userId = BaseContext.getUserId(); + + // 判断创建用户的Id是否和当前请求的用户id是否相同 + IPage page = baseMapper.selectListByPage(pageParams, dto, userId); + + return PageResult.builder() + .list(page.getRecords()) + .pageNo(page.getCurrent()) + .pageSize(page.getSize()) + .total(page.getTotal()) + .build(); + } + + /** + * 添加账单信息 + * + * @param dto 账单信息添加 + */ + @Override + public void addBill(@Valid BillAddDto dto) { + // 保存数据 + Bill bill = new Bill(); + BeanUtils.copyProperties(dto, bill); + save(bill); + } + + /** + * 更新账单信息 + * + * @param dto 账单信息更新 + */ + @Override + public void updateBill(@Valid BillUpdateDto dto) { + // 更新内容 + Bill bill = new Bill(); + BeanUtils.copyProperties(dto, bill); + updateById(bill); + } + + /** + * 删除|批量删除账单信息 + * + * @param ids 删除id列表 + */ + @Override + public void deleteBill(List ids) { + baseMapper.deleteBatchIdsWithPhysics(ids); + } +} diff --git a/service/src/main/java/cn/bunny/services/service/financial/impl/CategoryUserServiceImpl.java b/service/src/main/java/cn/bunny/services/service/financial/impl/CategoryUserServiceImpl.java new file mode 100644 index 0000000..01807ce --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/financial/impl/CategoryUserServiceImpl.java @@ -0,0 +1,125 @@ +package cn.bunny.services.service.financial.impl; + +import cn.bunny.common.service.context.BaseContext; +import cn.bunny.common.service.exception.BunnyException; +import cn.bunny.dao.dto.financial.category.CategoryUserAddDto; +import cn.bunny.dao.dto.financial.category.CategoryUserDto; +import cn.bunny.dao.dto.financial.category.CategoryUserUpdateDto; +import cn.bunny.dao.entity.financial.Category; +import cn.bunny.dao.pojo.constant.UserConstant; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.financial.CategoryUserVo; +import cn.bunny.services.mapper.financial.CategoryUserMapper; +import cn.bunny.services.service.financial.CategoryUserService; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import jakarta.validation.Valid; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 分类信息 服务实现类 + *

+ * + * @author Bunny + * @since 2024-11-08 10:00:09 + */ +@Service +public class CategoryUserServiceImpl extends ServiceImpl implements CategoryUserService { + + /** + * * 用户分类分页查询分类信息 服务实现类 + * + * @param pageParams 分类信息分页查询page对象 + * @param dto 分类信息分页查询对象 + * @return 查询分页分类信息返回对象 + */ + @Override + public PageResult getCategoryUserList(Page pageParams, CategoryUserDto dto) { + IPage page = baseMapper.selectListByPage(pageParams, dto, BaseContext.getUserId()); + + return PageResult.builder() + .list(page.getRecords()) + .pageNo(page.getCurrent()) + .pageSize(page.getSize()) + .total(page.getTotal()) + .build(); + } + + /** + * 用戶分类添加分类信息 + * + * @param dto 分类信息添加 + */ + @Override + public void addCategoryUser(@Valid CategoryUserAddDto dto) { + // 查询当前用户添加了多少条 + if (count(Wrappers.lambdaQuery().eq(Category::getIsBuiltin, false)) >= UserConstant.CATEGORY_COUNT) { + throw new BunnyException(ResultCodeEnum.THE_MAXIMUM_BAR_CODE); + } + + // 保存数据 + Category categoryUser = new Category(); + BeanUtils.copyProperties(dto, categoryUser); + + // 设置当前用户Id + categoryUser.setUserId(BaseContext.getUserId()); + save(categoryUser); + } + + /** + * 用户分类更新分类信息 + * + * @param dto 分类信息更新 + */ + @Override + public void updateCategoryUser(@Valid CategoryUserUpdateDto dto) { + Long userId = BaseContext.getUserId(); + String categoryName = dto.getCategoryName(); + + // 判断用户修改的当前内容是否和系统内置的信息一致 + Category category = getOne(Wrappers.lambdaQuery().eq(Category::getId, dto.getId())); + Long categoryUserId = category.getUserId(); + String categoryCategoryName = category.getCategoryName(); + + if (!categoryUserId.equals(userId) || !categoryCategoryName.equals(categoryName)) { + throw new BunnyException(ResultCodeEnum.ILLEGAL_DATA_REQUEST); + } + + // 更新内容 + Category categoryUser = new Category(); + BeanUtils.copyProperties(dto, categoryUser); + updateById(categoryUser); + } + + /** + * 用户分类删除|批量删除分类信息 + * + * @param ids 删除id列表 + */ + @Override + public void deleteCategoryUser(List ids) { + baseMapper.deleteBatchIdsWithPhysics(ids); + } + + /** + * 查询当前用户下所有的分类 + * + * @return 当前用户分类返回列表 + */ + @Override + public List getCategoryUserAllList() { + return list(Wrappers.lambdaQuery().eq(Category::getUserId, BaseContext.getUserId())) + .stream().map(category -> { + CategoryUserVo categoryUserVo = new CategoryUserVo(); + BeanUtils.copyProperties(category, categoryUserVo); + return categoryUserVo; + }).toList(); + } +} diff --git a/service/src/main/java/cn/bunny/services/service/i18n/I18nService.java b/service/src/main/java/cn/bunny/services/service/i18n/I18nService.java new file mode 100644 index 0000000..a49967e --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/i18n/I18nService.java @@ -0,0 +1,60 @@ +package cn.bunny.services.service.i18n; + +import cn.bunny.dao.dto.i18n.I18nAddDto; +import cn.bunny.dao.dto.i18n.I18nDto; +import cn.bunny.dao.dto.i18n.I18nUpdateDto; +import cn.bunny.dao.entity.i18n.I18n; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.vo.i18n.I18nVo; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import jakarta.validation.Valid; + +import java.util.HashMap; +import java.util.List; + +/** + *

+ * 多语言表 服务类 + *

+ * + * @author Bunny + * @since 2024-09-28 + */ +public interface I18nService extends IService { + + /** + * * 获取多语言内容 + * + * @return 多语言返回内容 + */ + HashMap getI18n(); + + /** + * * 获取管理多语言列表 + * + * @return 多语言返回列表 + */ + PageResult getI18nList(Page pageParams, I18nDto dto); + + /** + * * 添加多语言 + * + * @param dto 添加表单 + */ + void addI18n(@Valid I18nAddDto dto); + + /** + * * 更新多语言 + * + * @param dto 更新表单 + */ + void updateI18n(@Valid I18nUpdateDto dto); + + /** + * * 删除多语言类型 + * + * @param ids 删除id列表 + */ + void deleteI18n(List ids); +} diff --git a/service/src/main/java/cn/bunny/services/service/i18n/I18nTypeService.java b/service/src/main/java/cn/bunny/services/service/i18n/I18nTypeService.java new file mode 100644 index 0000000..07c1e19 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/i18n/I18nTypeService.java @@ -0,0 +1,49 @@ +package cn.bunny.services.service.i18n; + +import cn.bunny.dao.dto.i18n.I18nTypeAddDto; +import cn.bunny.dao.dto.i18n.I18nTypeDto; +import cn.bunny.dao.dto.i18n.I18nTypeUpdateDto; +import cn.bunny.dao.entity.i18n.I18nType; +import cn.bunny.dao.vo.i18n.I18nTypeVo; +import com.baomidou.mybatisplus.extension.service.IService; + +import java.util.List; + +/** + *

+ * 多语言类型表 服务类 + *

+ * + * @author Bunny + * @since 2024-09-28 + */ +public interface I18nTypeService extends IService { + + /** + * 获取多语言类型 + * + * @return 多语言类型列表 + */ + List getI18nTypeList(I18nTypeDto dto); + + /** + * 添加多语言类型 + * + * @param dto 多语言类型添加 + */ + void addI18nType(I18nTypeAddDto dto); + + /** + * 更新多语言类型 + * + * @param dto 多语言类型更新 + */ + void updateI18nType(I18nTypeUpdateDto dto); + + /** + * 删除多语言类型 + * + * @param ids 删除id列表 + */ + void deleteI18nType(List ids); +} diff --git a/service/src/main/java/cn/bunny/services/service/i18n/impl/I18nServiceImpl.java b/service/src/main/java/cn/bunny/services/service/i18n/impl/I18nServiceImpl.java new file mode 100644 index 0000000..b8172af --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/i18n/impl/I18nServiceImpl.java @@ -0,0 +1,143 @@ +package cn.bunny.services.service.i18n.impl; + +import cn.bunny.common.service.exception.BunnyException; +import cn.bunny.dao.dto.i18n.I18nAddDto; +import cn.bunny.dao.dto.i18n.I18nDto; +import cn.bunny.dao.dto.i18n.I18nUpdateDto; +import cn.bunny.dao.entity.i18n.I18n; +import cn.bunny.dao.entity.i18n.I18nType; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.i18n.I18nVo; +import cn.bunny.services.mapper.i18n.I18nMapper; +import cn.bunny.services.mapper.i18n.I18nTypeMapper; +import cn.bunny.services.service.i18n.I18nService; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import jakarta.validation.Valid; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + *

+ * 多语言表 服务实现类 + *

+ * + * @author Bunny + * @since 2024-09-28 + */ +@Service +@Transactional +public class I18nServiceImpl extends ServiceImpl implements I18nService { + + @Autowired + private I18nTypeMapper i18nTypeMapper; + + /** + * * 获取多语言内容 + * + * @return 多语言返回内容 + */ + @Override + @Cacheable(cacheNames = "i18n", key = "'i18n'", cacheManager = "cacheManagerWithMouth") + public HashMap getI18n() { + // 查找默认语言内容 + I18nType i18nType = i18nTypeMapper.selectOne(Wrappers.lambdaQuery().eq(I18nType::getIsDefault, true)); + List i18nList = list(); + + // 整理集合 + Map> map = i18nList.stream() + .collect(Collectors.groupingBy( + I18n::getTypeName, + Collectors.toMap(I18n::getKeyName, I18n::getTranslation))); + + // 返回集合 + HashMap hashMap = new HashMap<>(map); + hashMap.put("local", Objects.requireNonNull(i18nType.getTypeName(), "zh")); + return hashMap; + } + + /** + * * 获取管理多语言列表 + * + * @return 多语言返回列表 + */ + @Override + public PageResult getI18nList(Page pageParams, I18nDto dto) { + IPage page = baseMapper.selectListByPage(pageParams, dto); + + return PageResult.builder() + .list(page.getRecords()) + .pageSize(page.getSize()) + .pageNo(page.getCurrent()) + .total(page.getTotal()) + .build(); + } + + /** + * * 添加多语言 + * + * @param dto 添加表单 + */ + @Override + @CacheEvict(cacheNames = "i18n", key = "'i18n'", beforeInvocation = true) + public void addI18n(@Valid I18nAddDto dto) { + String keyName = dto.getKeyName(); + String typeName = dto.getTypeName(); + + // 查询数据是否存在 + List i18nList = list(Wrappers.lambdaQuery().eq(I18n::getKeyName, keyName).eq(I18n::getTypeName, typeName)); + if (!i18nList.isEmpty()) throw new BunnyException(ResultCodeEnum.DATA_EXIST); + + // 保存内容 + I18n i18n = new I18n(); + BeanUtils.copyProperties(dto, i18n); + save(i18n); + } + + /** + * * 更新多语言 + * + * @param dto 更新表单 + */ + @Override + @CacheEvict(cacheNames = "i18n", key = "'i18n'", beforeInvocation = true) + public void updateI18n(@Valid I18nUpdateDto dto) { + Long id = dto.getId(); + + // 查询数据是否存在 + List i18nList = list(Wrappers.lambdaQuery().eq(I18n::getId, id)); + if (i18nList.isEmpty()) throw new BunnyException(ResultCodeEnum.DATA_NOT_EXIST); + + // 保存内容 + I18n i18n = new I18n(); + BeanUtils.copyProperties(dto, i18n); + updateById(i18n); + } + + /** + * * 删除多语言类型 + * + * @param ids 删除id列表 + */ + @Override + @CacheEvict(cacheNames = "i18n", key = "'i18n'", beforeInvocation = true) + public void deleteI18n(List ids) { + // 判断数据请求是否为空 + if (ids.isEmpty()) throw new BunnyException(ResultCodeEnum.REQUEST_IS_EMPTY); + + baseMapper.deleteBatchIdsWithPhysics(ids); + } +} diff --git a/service/src/main/java/cn/bunny/services/service/i18n/impl/I18nTypeServiceImpl.java b/service/src/main/java/cn/bunny/services/service/i18n/impl/I18nTypeServiceImpl.java new file mode 100644 index 0000000..7385cb9 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/i18n/impl/I18nTypeServiceImpl.java @@ -0,0 +1,119 @@ +package cn.bunny.services.service.i18n.impl; + +import cn.bunny.common.service.exception.BunnyException; +import cn.bunny.dao.dto.i18n.I18nTypeAddDto; +import cn.bunny.dao.dto.i18n.I18nTypeDto; +import cn.bunny.dao.dto.i18n.I18nTypeUpdateDto; +import cn.bunny.dao.entity.i18n.I18nType; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.i18n.I18nTypeVo; +import cn.bunny.services.mapper.i18n.I18nTypeMapper; +import cn.bunny.services.service.i18n.I18nTypeService; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.beans.BeanUtils; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +/** + *

+ * 多语言类型表 服务实现类 + *

+ * + * @author Bunny + * @since 2024-09-28 + */ +@Service +@Transactional +public class I18nTypeServiceImpl extends ServiceImpl implements I18nTypeService { + + /** + * 获取多语言类型 + * + * @return 多语言类型列表 + */ + @Override + @Cacheable(cacheNames = "i18n", key = "'i18nType'", cacheManager = "cacheManagerWithMouth") + public List getI18nTypeList(I18nTypeDto dto) { + List i18nTypeList = baseMapper.selectListByPage(dto); + return i18nTypeList.stream().map(i18nType -> { + I18nTypeVo i18nTypeVo = new I18nTypeVo(); + BeanUtils.copyProperties(i18nType, i18nTypeVo); + return i18nTypeVo; + }).toList(); + } + + /** + * 添加多语言类型 + * + * @param dto 多语言类型添加 + */ + @Override + @CacheEvict(cacheNames = "i18n", key = "'i18nType'", beforeInvocation = true) + public void addI18nType(I18nTypeAddDto dto) { + String typeName = dto.getTypeName(); + Boolean isDefault = dto.getIsDefault(); + I18nType i18nType = new I18nType(); + + // 查询添加的数据是否之前添加过 + List i18nTypeList = list(Wrappers.lambdaQuery().eq(I18nType::getTypeName, typeName)); + if (!i18nTypeList.isEmpty()) throw new BunnyException(ResultCodeEnum.DATA_EXIST); + + // 如果是默认,将其它内容设为false + if (isDefault) { + i18nType.setIsDefault(false); + update(i18nType, Wrappers.lambdaUpdate().eq(I18nType::getIsDefault, true)); + } + + // 保存数据 + i18nType = new I18nType(); + BeanUtils.copyProperties(dto, i18nType); + save(i18nType); + } + + /** + * 更新多语言类型 + * + * @param dto 多语言类型更新 + */ + @Override + @CacheEvict(cacheNames = "i18n", key = "'i18nType'", beforeInvocation = true) + public void updateI18nType(I18nTypeUpdateDto dto) { + Long id = dto.getId(); + Boolean isDefault = dto.getIsDefault(); + I18nType i18nType = new I18nType(); + + // 查询更新的内容是否存在 + List i18nTypeList = list(Wrappers.lambdaQuery().eq(I18nType::getId, id)); + if (i18nTypeList.isEmpty()) throw new BunnyException(ResultCodeEnum.DATA_NOT_EXIST); + + // 如果是默认,将其它内容设为false + if (isDefault) { + i18nType.setIsDefault(false); + update(i18nType, Wrappers.lambdaUpdate().eq(I18nType::getIsDefault, true)); + } + + // 更新内容 + i18nType = new I18nType(); + BeanUtils.copyProperties(dto, i18nType); + updateById(i18nType); + } + + /** + * 删除多语言类型 + * + * @param ids 删除id列表 + */ + @Override + @CacheEvict(cacheNames = "i18n", key = "'i18nType'", beforeInvocation = true) + public void deleteI18nType(List ids) { + // 判断数据请求是否为空 + if (ids.isEmpty()) throw new BunnyException(ResultCodeEnum.REQUEST_IS_EMPTY); + + baseMapper.deleteBatchIdsWithPhysics(ids); + } +} diff --git a/service/src/main/java/cn/bunny/services/service/message/MessageReceivedService.java b/service/src/main/java/cn/bunny/services/service/message/MessageReceivedService.java new file mode 100644 index 0000000..fb9c1e5 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/message/MessageReceivedService.java @@ -0,0 +1,70 @@ +package cn.bunny.services.service.message; + +import cn.bunny.dao.dto.system.message.MessageReceivedDto; +import cn.bunny.dao.dto.system.message.MessageReceivedUpdateDto; +import cn.bunny.dao.dto.system.message.MessageUserDto; +import cn.bunny.dao.entity.system.Message; +import cn.bunny.dao.entity.system.MessageReceived; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.vo.system.message.MessageReceivedWithMessageVo; +import cn.bunny.dao.vo.system.message.MessageUserVo; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import jakarta.validation.Valid; + +import java.util.List; + +/** + *

+ * 服务类 + *

+ * + * @author Bunny + * @since 2024-10-31 + */ +public interface MessageReceivedService extends IService { + + /** + * 管理员管理用户消息接收分页查询 + * + * @return 系统消息返回列表 + */ + PageResult getMessageReceivedList(Page pageParams, MessageReceivedDto dto); + + /** + * 管理员将用户接受消息标为已读 + * + * @param dto 用户消息表单 + */ + void updateMarkMessageReceived(@Valid MessageReceivedUpdateDto dto); + + /** + * 管理删除用户接受的消息 + * + * @param ids 用户消息Id列表 + */ + void deleteMessageReceivedByIds(List ids); + + /** + * 分页查询用户消息 + * + * @param pageParams 系统消息返回列表 + * @param dto 查询表单 + * @return 分页结果 + */ + PageResult getUserMessageList(Page pageParams, MessageUserDto dto); + + /** + * 用户将消息标为已读 + * + * @param ids 消息id列表 + */ + void userMarkAsRead(List ids); + + /** + * 用户删除消息 + * + * @param ids 消息Id列表 + */ + void deleteUserMessageByIds(List ids); +} diff --git a/service/src/main/java/cn/bunny/services/service/message/MessageService.java b/service/src/main/java/cn/bunny/services/service/message/MessageService.java new file mode 100644 index 0000000..95e416e --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/message/MessageService.java @@ -0,0 +1,72 @@ +package cn.bunny.services.service.message; + +import cn.bunny.dao.dto.system.message.MessageAddDto; +import cn.bunny.dao.dto.system.message.MessageDto; +import cn.bunny.dao.dto.system.message.MessageUpdateDto; +import cn.bunny.dao.entity.system.Message; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.vo.system.message.MessageDetailVo; +import cn.bunny.dao.vo.system.message.MessageReceivedWithUserVo; +import cn.bunny.dao.vo.system.message.MessageVo; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import jakarta.validation.Valid; + +import java.util.List; + +/** + *

+ * 系统消息 服务类 + *

+ * + * @author Bunny + * @since 2024-10-30 15:19:56 + */ +public interface MessageService extends IService { + + /** + * 根据消息id获取接收人信息 + * + * @param messageId 消息id + * @return 消息接收人用户名等信息 + */ + List getReceivedUserinfoByMessageId(Long messageId); + + /** + * 根据消息id查询消息详情 + * + * @param id 消息id + * @return 消息详情 + */ + MessageDetailVo getMessageDetailById(Long id); + + /** + * * 添加系统消息 + * + * @param dto 添加表单 + */ + void addMessage(@Valid MessageAddDto dto); + + /** + * * 更新系统消息 + * + * @param dto 更新表单 + */ + void updateMessage(@Valid MessageUpdateDto dto); + + /** + * * 删除|批量删除系统消息类型 + * + * @param ids 删除id列表 + */ + void deleteMessage(List ids); + + /** + * 分页查询发送消息 + * + * @param pageParams 分页参数 + * @param dto 查询表单 + * @return 系统消息返回列表 + */ + PageResult getMessageList(Page pageParams, MessageDto dto); +} diff --git a/service/src/main/java/cn/bunny/services/service/message/MessageTypeService.java b/service/src/main/java/cn/bunny/services/service/message/MessageTypeService.java new file mode 100644 index 0000000..8030606 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/message/MessageTypeService.java @@ -0,0 +1,59 @@ +package cn.bunny.services.service.message; + +import cn.bunny.dao.dto.system.message.MessageTypeAddDto; +import cn.bunny.dao.dto.system.message.MessageTypeDto; +import cn.bunny.dao.dto.system.message.MessageTypeUpdateDto; +import cn.bunny.dao.entity.system.MessageType; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.vo.system.message.MessageTypeVo; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import jakarta.validation.Valid; + +import java.util.List; + +/** + *

+ * 系统消息类型 服务类 + *

+ * + * @author Bunny + * @since 2024-10-30 13:19:33 + */ +public interface MessageTypeService extends IService { + + /** + * * 获取系统消息类型列表 + * + * @return 系统消息类型返回列表 + */ + PageResult getMessageTypeList(Page pageParams, MessageTypeDto dto); + + /** + * * 添加系统消息类型 + * + * @param dto 添加表单 + */ + void addMessageType(@Valid MessageTypeAddDto dto); + + /** + * * 更新系统消息类型 + * + * @param dto 更新表单 + */ + void updateMessageType(@Valid MessageTypeUpdateDto dto); + + /** + * * 删除|批量删除系统消息类型类型 + * + * @param ids 删除id列表 + */ + void deleteMessageType(List ids); + + /** + * 获取所有消息类型 + * + * @return 系统消息类型列表 + */ + List getNoManageMessageTypes(); +} diff --git a/service/src/main/java/cn/bunny/services/service/message/impl/MessageReceivedServiceImpl.java b/service/src/main/java/cn/bunny/services/service/message/impl/MessageReceivedServiceImpl.java new file mode 100644 index 0000000..2878b43 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/message/impl/MessageReceivedServiceImpl.java @@ -0,0 +1,175 @@ +package cn.bunny.services.service.message.impl; + +import cn.bunny.common.service.context.BaseContext; +import cn.bunny.common.service.exception.BunnyException; +import cn.bunny.dao.dto.system.message.MessageReceivedDto; +import cn.bunny.dao.dto.system.message.MessageReceivedUpdateDto; +import cn.bunny.dao.dto.system.message.MessageUserDto; +import cn.bunny.dao.entity.system.Message; +import cn.bunny.dao.entity.system.MessageReceived; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.system.message.MessageReceivedWithMessageVo; +import cn.bunny.dao.vo.system.message.MessageUserVo; +import cn.bunny.services.factory.UserFactory; +import cn.bunny.services.mapper.message.MessageReceivedMapper; +import cn.bunny.services.service.message.MessageReceivedService; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import jakarta.validation.Valid; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +/** + *

+ * 服务实现类 + *

+ * + * @author Bunny + * @since 2024-10-31 + */ +@Service +@Transactional +public class MessageReceivedServiceImpl extends ServiceImpl implements MessageReceivedService { + + @Autowired + private UserFactory userFactory; + + /** + * 管理员管理用户消息接收分页查询 + * + * @param pageParams 系统消息分页查询page对象 + * @param dto 系统消息分页查询对象 + * @return 查询分页系统消息返回对象 + */ + @Override + public PageResult getMessageReceivedList(Page pageParams, MessageReceivedDto dto) { + // 分页查询消息数据 + IPage page = baseMapper.selectListByMessageReceivedPage(pageParams, dto); + List voList = page.getRecords().stream().map(messageVo -> { + MessageReceivedWithMessageVo vo = new MessageReceivedWithMessageVo(); + BeanUtils.copyProperties(messageVo, vo); + + // 设置封面返回内容 + String cover = vo.getCover(); + cover = userFactory.checkGetUserAvatar(cover); + vo.setCover(cover); + return vo; + }).toList(); + return PageResult.builder().list(voList).pageNo(page.getCurrent()) + .pageSize(page.getSize()).total(page.getTotal()) + .build(); + } + + /** + * 管理员将用户接受消息标为已读 + * + * @param dto 用户消息表单 + */ + @Override + public void updateMarkMessageReceived(@Valid MessageReceivedUpdateDto dto) { + List messageReceivedList = dto.getIds().stream().map(id -> { + MessageReceived messageReceived = new MessageReceived(); + messageReceived.setId(id); + messageReceived.setStatus(dto.getStatus()); + return messageReceived; + }).toList(); + updateBatchById(messageReceivedList); + } + + /** + * 管理删除用户接受的消息 + * + * @param ids 用户消息Id列表 + */ + @Override + public void deleteMessageReceivedByIds(List ids) { + baseMapper.deleteBatchIdsWithPhysics(ids); + } + + /** + * 分页查询用户消息 + * 查询用户消息关系表,找到当前用户所有的消息 + * 拿到用户消息关系表中数据只要MessageId + * 根据MessageId分页查询消息表 + * + * @param pageParams 系统消息返回列表 + * @param dto 用户消息查询内容 + * @return 分页结果 + */ + @Override + public PageResult getUserMessageList(Page pageParams, MessageUserDto dto) { + // 根据消息所有包含匹配当前消息Id的列表 + IPage page = baseMapper.selectListByUserMessagePage(pageParams, dto, BaseContext.getUserId()); + List voList = page.getRecords().stream().map(messageVo -> { + MessageUserVo vo = new MessageUserVo(); + BeanUtils.copyProperties(messageVo, vo); + + // 设置封面返回内容 + String cover = vo.getCover(); + cover = userFactory.checkGetUserAvatar(cover); + vo.setCover(cover); + return vo; + }).toList(); + + return PageResult.builder().list(voList).pageNo(page.getCurrent()) + .pageSize(page.getSize()).total(page.getTotal()) + .build(); + } + + /** + * 用户将消息标为已读 + * 将消息表中满足id条件全部标为已读 + * + * @param ids 消息id列表 + */ + @Override + public void userMarkAsRead(List ids) { + // 判断ids是否为空 + if (ids.isEmpty()) { + throw new BunnyException(ResultCodeEnum.REQUEST_IS_EMPTY); + } + + // 更新表中消息状态 + List messageList = ids.stream().map(id -> { + MessageReceived messageReceived = new MessageReceived(); + messageReceived.setId(id); + messageReceived.setStatus(true); + return messageReceived; + }).toList(); + + updateBatchById(messageList); + } + + /** + * 用户删除消息 + * + * @param ids 消息Id列表 + */ + @Override + public void deleteUserMessageByIds(List ids) { + // 判断ids是否为空 + if (ids.isEmpty()) { + throw new BunnyException(ResultCodeEnum.REQUEST_IS_EMPTY); + } + + // 判断删除的是否是自己的消息 + List messageReceivedList = list(Wrappers.lambdaQuery().in(MessageReceived::getReceivedUserId, ids)); + messageReceivedList.forEach(messageReceived -> { + if (!messageReceived.getReceivedUserId().equals(BaseContext.getUserId())) { + throw new BunnyException(ResultCodeEnum.ILLEGAL_DATA_REQUEST); + } + }); + + // 根据当前用户id删除消息接受表中数据 + baseMapper.deleteBatchIds(ids); + // baseMapper.deleteBatchIdsWithPhysics(ids); + } + +} diff --git a/service/src/main/java/cn/bunny/services/service/message/impl/MessageServiceImpl.java b/service/src/main/java/cn/bunny/services/service/message/impl/MessageServiceImpl.java new file mode 100644 index 0000000..921a248 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/message/impl/MessageServiceImpl.java @@ -0,0 +1,241 @@ +package cn.bunny.services.service.message.impl; + +import cn.bunny.common.service.context.BaseContext; +import cn.bunny.common.service.exception.BunnyException; +import cn.bunny.dao.common.entity.BaseEntity; +import cn.bunny.dao.dto.system.message.MessageAddDto; +import cn.bunny.dao.dto.system.message.MessageDto; +import cn.bunny.dao.dto.system.message.MessageUpdateDto; +import cn.bunny.dao.entity.system.Message; +import cn.bunny.dao.entity.system.MessageReceived; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.system.message.MessageDetailVo; +import cn.bunny.dao.vo.system.message.MessageReceivedWithMessageVo; +import cn.bunny.dao.vo.system.message.MessageReceivedWithUserVo; +import cn.bunny.dao.vo.system.message.MessageVo; +import cn.bunny.services.factory.UserFactory; +import cn.bunny.services.mapper.message.MessageMapper; +import cn.bunny.services.mapper.message.MessageReceivedMapper; +import cn.bunny.services.mapper.system.UserMapper; +import cn.bunny.services.service.message.MessageReceivedService; +import cn.bunny.services.service.message.MessageService; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import jakarta.validation.Valid; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + *

+ * 系统消息 服务实现类 + *

+ * + * @author Bunny + * @since 2024-10-30 15:19:56 + */ +@Service +@Transactional +public class MessageServiceImpl extends ServiceImpl implements MessageService { + + @Autowired + private UserFactory userFactory; + + @Autowired + private MessageReceivedMapper messageReceivedMapper; + + @Autowired + private UserMapper userMapper; + + @Autowired + private MessageReceivedService messageReceivedService; + + /** + * 分页查询发送消息 + * + * @param pageParams 分页参数 + * @param dto 查询表单 + * @return 系统消息返回列表 + */ + @Override + public PageResult getMessageList(Page pageParams, MessageDto dto) { + IPage page = baseMapper.selectListByPage(pageParams, dto); + List records = page.getRecords(); + + // 接受人昵称 + Map> receivedUserNicknameMap = records.stream() + .collect(Collectors.groupingBy( + MessageReceivedWithMessageVo::getId, + Collectors.mapping(MessageReceivedWithMessageVo::getReceivedUserNickname, Collectors.toList()))); + + // 接收人id + Map> receivedUserIdMap = records.stream() + .collect(Collectors.groupingBy( + MessageReceivedWithMessageVo::getId, + Collectors.mapping(messageWithMessageReceivedVo -> messageWithMessageReceivedVo.getId().toString(), Collectors.toList()))); + + List voList = records.stream() + .map(messageWithMessageReceivedVo -> { + MessageVo messageVo = new MessageVo(); + BeanUtils.copyProperties(messageWithMessageReceivedVo, messageVo); + messageVo.setReceivedUserNickname(receivedUserNicknameMap.get(messageWithMessageReceivedVo.getId())); + messageVo.setReceivedUserId(receivedUserIdMap.get(messageWithMessageReceivedVo.getId())); + return messageVo; + }).distinct().toList(); + + return PageResult.builder().list(voList).pageNo(page.getCurrent()) + .pageSize(page.getSize()).total(page.getTotal()) + .build(); + } + + /** + * 根据消息id查询消息详情 + * 请求消息内容后标为已读 + * + * @param id 消息id + * @return 消息详情 + */ + @Override + public MessageDetailVo getMessageDetailById(Long id) { + // 将消息设为已读 + MessageReceived messageReceived = new MessageReceived(); + messageReceived.setReceivedUserId(BaseContext.getUserId()); + messageReceived.setMessageId(id); + messageReceived.setStatus(true); + + // 更新满足条件的消息用户表 + LambdaUpdateWrapper wrapper = Wrappers.lambdaUpdate() + .eq(MessageReceived::getMessageId, id) + .eq(MessageReceived::getReceivedUserId, BaseContext.getUserId()); + messageReceivedMapper.update(messageReceived, wrapper); + + // 返回详情内容给前端 + return baseMapper.selectMessageVoById(id); + } + + /** + * 根据消息id获取接收人信息 + * + * @param messageId 消息id + * @return 消息接收人用户名等信息 + */ + @Override + public List getReceivedUserinfoByMessageId(Long messageId) { + if (messageId == null) { + throw new BunnyException(ResultCodeEnum.REQUEST_IS_EMPTY); + } + return baseMapper.selectUserinfoListByMessageId(messageId); + } + + /** + * 添加系统消息 + * 判断发送消息的接收人是否为空,如果为空默认是所有用户都是接受者 + * 之后要将消息的接受者要保存在,消息接收表中,在这之前是没有消息id的 + * 先要保存消息内容,之后获取到保存消息的id + * 将消息的id和接收者的id构建成map插入到消息接收表中 + * + * @param dto 系统消息添加 + */ + @Override + public void addMessage(@Valid MessageAddDto dto) { + // 如果发送人为空设置当前登录的人的ID + if (dto.getSendUserId() == null) dto.setSendUserId(BaseContext.getUserId()); + + // 设置封面返回内容 + String cover = dto.getCover(); + dto.setCover(userFactory.checkGetUserAvatar(cover)); + + // 先保存消息数据,之后拿到保存消息的id + Message message = new Message(); + BeanUtils.copyProperties(dto, message); + message.setMessageType(dto.getMessageTypeId().toString()); + save(message); + + // 如果接收人为空默认接收全部人 + List receivedUserIds = dto.getReceivedUserIds(); + if (receivedUserIds.isEmpty()) { + receivedUserIds = userMapper.selectList(null).stream().map(BaseEntity::getId).toList(); + } + + // 从之前保存的消息中获取消息id,保存到消息接收表中 + List receivedList = receivedUserIds.stream().map(id -> { + MessageReceived messageReceived = new MessageReceived(); + messageReceived.setMessageId(message.getId()); + messageReceived.setReceivedUserId(id); + messageReceived.setStatus(false); + return messageReceived; + }).toList(); + + messageReceivedService.saveBatch(receivedList); + } + + + /** + * 更新系统消息 + * + * @param dto 系统消息更新 + */ + @Override + public void updateMessage(@Valid MessageUpdateDto dto) { + // 如果发送人为空设置当前登录的人的ID + Long sendUserId = dto.getSendUserId(); + if (sendUserId == null) dto.setSendUserId(BaseContext.getUserId()); + + // 如果接收人为空默认接收全部人 + List receivedUserIds = dto.getReceivedUserIds(); + if (receivedUserIds.isEmpty()) { + receivedUserIds = userMapper.selectList(null).stream().map(BaseEntity::getId).toList(); + } + + // 设置封面返回内容 + String cover = dto.getCover(); + dto.setCover(userFactory.checkGetUserAvatar(cover)); + + // 更新内容 + Message message = new Message(); + BeanUtils.copyProperties(dto, message); + message.setMessageType(dto.getMessageTypeId().toString()); + baseMapper.updateById(message); + + // 保存消息和用户之间关联数据 + List receivedList = receivedUserIds.stream().map(id -> { + MessageReceived messageReceived = new MessageReceived(); + messageReceived.setMessageId(dto.getId()); + messageReceived.setReceivedUserId(id); + return messageReceived; + }).toList(); + + // 删除这个消息id下所有用户消息关系内容 + messageReceivedMapper.deleteBatchIdsByMessageIdsWithPhysics(List.of(dto.getId())); + + // 插入接收者和消息表 + messageReceivedService.saveBatch(receivedList); + } + + /** + * 删除|批量删除系统消息 + * 删除消息表中的数据,还要删除消息接收表中的消息 + * 消息接收表根据消息id进行删除 + * + * @param ids 删除id列表 + */ + @Override + public void deleteMessage(List ids) { + // 根据消息id删除 + // removeBatchByIds(ids); + baseMapper.deleteBatchIdsWithPhysics(ids); + + // 根据消息Id物理删除用户消息表 + // messageReceivedMapper.deleteBatchIds(ids); + messageReceivedMapper.deleteBatchIdsByMessageIdsWithPhysics(ids); + } +} diff --git a/service/src/main/java/cn/bunny/services/service/message/impl/MessageTypeServiceImpl.java b/service/src/main/java/cn/bunny/services/service/message/impl/MessageTypeServiceImpl.java new file mode 100644 index 0000000..5038f07 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/message/impl/MessageTypeServiceImpl.java @@ -0,0 +1,100 @@ +package cn.bunny.services.service.message.impl; + +import cn.bunny.dao.dto.system.message.MessageTypeAddDto; +import cn.bunny.dao.dto.system.message.MessageTypeDto; +import cn.bunny.dao.dto.system.message.MessageTypeUpdateDto; +import cn.bunny.dao.entity.system.MessageType; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.vo.system.message.MessageTypeVo; +import cn.bunny.services.mapper.message.MessageTypeMapper; +import cn.bunny.services.service.message.MessageTypeService; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import jakarta.validation.Valid; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 系统消息类型 服务实现类 + *

+ * + * @author Bunny + * @since 2024-10-30 13:19:33 + */ +@Service +public class MessageTypeServiceImpl extends ServiceImpl implements MessageTypeService { + + /** + * * 系统消息类型 服务实现类 + * + * @param pageParams 系统消息类型分页查询page对象 + * @param dto 系统消息类型分页查询对象 + * @return 查询分页系统消息类型返回对象 + */ + @Override + public PageResult getMessageTypeList(Page pageParams, MessageTypeDto dto) { + IPage page = baseMapper.selectListByPage(pageParams, dto); + + return PageResult.builder() + .list(page.getRecords()) + .pageNo(page.getCurrent()) + .pageSize(page.getSize()) + .total(page.getTotal()) + .build(); + } + + /** + * 添加系统消息类型 + * + * @param dto 系统消息类型添加 + */ + @Override + public void addMessageType(@Valid MessageTypeAddDto dto) { + // 保存数据 + MessageType messageType = new MessageType(); + BeanUtils.copyProperties(dto, messageType); + save(messageType); + } + + /** + * 更新系统消息类型 + * + * @param dto 系统消息类型更新 + */ + @Override + public void updateMessageType(@Valid MessageTypeUpdateDto dto) { + // 更新内容 + MessageType messageType = new MessageType(); + BeanUtils.copyProperties(dto, messageType); + updateById(messageType); + } + + /** + * 删除|批量删除系统消息类型 + * + * @param ids 删除id列表 + */ + @Override + public void deleteMessageType(List ids) { + baseMapper.deleteBatchIdsWithPhysics(ids); + } + + /** + * 获取所有消息类型 + * + * @return 系统消息类型列表 + */ + @Override + public List getNoManageMessageTypes() { + return list(Wrappers.lambdaQuery().eq(MessageType::getStatus, true)).stream().map(messageType -> { + MessageTypeVo messageTypeVo = new MessageTypeVo(); + BeanUtils.copyProperties(messageType, messageTypeVo); + return messageTypeVo; + }).toList(); + } +} diff --git a/service/src/main/java/cn/bunny/services/service/schedule/ScheduleExecuteLogService.java b/service/src/main/java/cn/bunny/services/service/schedule/ScheduleExecuteLogService.java new file mode 100644 index 0000000..212730e --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/schedule/ScheduleExecuteLogService.java @@ -0,0 +1,35 @@ +package cn.bunny.services.service.schedule; + +import cn.bunny.dao.dto.log.ScheduleExecuteLogDto; +import cn.bunny.dao.entity.log.ScheduleExecuteLog; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.vo.log.QuartzExecuteLogVo; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; + +import java.util.List; + +/** + *

+ * 调度任务执行日志 服务类 + *

+ * + * @author Bunny + * @since 2024-10-18 12:56:39 + */ +public interface ScheduleExecuteLogService extends IService { + + /** + * * 获取调度任务执行日志列表 + * + * @return 调度任务执行日志返回列表 + */ + PageResult getQuartzExecuteLogList(Page pageParams, ScheduleExecuteLogDto dto); + + /** + * * 删除|批量删除调度任务执行日志类型 + * + * @param ids 删除id列表 + */ + void deleteQuartzExecuteLog(List ids); +} diff --git a/service/src/main/java/cn/bunny/services/service/schedule/SchedulersGroupService.java b/service/src/main/java/cn/bunny/services/service/schedule/SchedulersGroupService.java new file mode 100644 index 0000000..bcc66b6 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/schedule/SchedulersGroupService.java @@ -0,0 +1,59 @@ +package cn.bunny.services.service.schedule; + +import cn.bunny.dao.dto.quartz.group.SchedulersGroupAddDto; +import cn.bunny.dao.dto.quartz.group.SchedulersGroupDto; +import cn.bunny.dao.dto.quartz.group.SchedulersGroupUpdateDto; +import cn.bunny.dao.entity.quartz.SchedulersGroup; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.vo.quartz.SchedulersGroupVo; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import jakarta.validation.Valid; + +import java.util.List; + +/** + *

+ * 任务调度分组 服务类 + *

+ * + * @author Bunny + * @since 2024-10-15 20:26:32 + */ +public interface SchedulersGroupService extends IService { + + /** + * * 获取任务调度分组列表 + * + * @return 任务调度分组返回列表 + */ + PageResult getSchedulersGroupList(Page pageParams, SchedulersGroupDto dto); + + /** + * * 添加任务调度分组 + * + * @param dto 添加表单 + */ + void addSchedulersGroup(@Valid SchedulersGroupAddDto dto); + + /** + * * 更新任务调度分组 + * + * @param dto 更新表单 + */ + void updateSchedulersGroup(@Valid SchedulersGroupUpdateDto dto); + + /** + * * 删除|批量删除任务调度分组类型 + * + * @param ids 删除id列表 + */ + void deleteSchedulersGroup(List ids); + + /** + * * 获取所有任务调度分组 + * + * @return 获取所有任务分组 + */ + List getAllSchedulersGroup(); +} diff --git a/service/src/main/java/cn/bunny/services/service/schedule/SchedulersService.java b/service/src/main/java/cn/bunny/services/service/schedule/SchedulersService.java new file mode 100644 index 0000000..663a415 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/schedule/SchedulersService.java @@ -0,0 +1,67 @@ +package cn.bunny.services.service.schedule; + +import cn.bunny.dao.dto.quartz.SchedulersOperationDto; +import cn.bunny.dao.dto.quartz.schedule.SchedulersAddDto; +import cn.bunny.dao.dto.quartz.schedule.SchedulersDto; +import cn.bunny.dao.entity.quartz.Schedulers; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.vo.quartz.SchedulersVo; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import jakarta.validation.Valid; + +import java.util.List; +import java.util.Map; + +/** + *

+ * Schedulers视图 服务类 + *

+ * + * @author Bunny + * @since 2024-10-15 16:35:10 + */ +public interface SchedulersService extends IService { + + /** + * * 获取Schedulers视图列表 + * + * @return Schedulers视图返回列表 + */ + PageResult getSchedulersList(Page pageParams, SchedulersDto dto); + + /** + * * 添加Schedulers视图 + * + * @param dto 添加表单 + */ + void addSchedulers(@Valid SchedulersAddDto dto); + + /** + * * 暂停Schedulers任务 + * + * @param dto Schedulers公共操作表单 + */ + void pauseScheduler(SchedulersOperationDto dto); + + /** + * * 恢复Schedulers任务 + * + * @param dto Schedulers公共操作表单 + */ + void resumeScheduler(SchedulersOperationDto dto); + + /** + * * 移出Schedulers任务 + * + * @param dto Schedulers公共操作表单 + */ + void deleteSchedulers(SchedulersOperationDto dto); + + /** + * * 获取所有可用调度任务 + * + * @return 所有调度任务内容 + */ + List> getAllScheduleJobList(); +} diff --git a/service/src/main/java/cn/bunny/services/service/schedule/impl/ScheduleExecuteLogServiceImpl.java b/service/src/main/java/cn/bunny/services/service/schedule/impl/ScheduleExecuteLogServiceImpl.java new file mode 100644 index 0000000..40a138b --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/schedule/impl/ScheduleExecuteLogServiceImpl.java @@ -0,0 +1,55 @@ +package cn.bunny.services.service.schedule.impl; + +import cn.bunny.dao.dto.log.ScheduleExecuteLogDto; +import cn.bunny.dao.entity.log.ScheduleExecuteLog; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.vo.log.QuartzExecuteLogVo; +import cn.bunny.services.mapper.schedule.ScheduleExecuteLogMapper; +import cn.bunny.services.service.schedule.ScheduleExecuteLogService; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 调度任务执行日志 服务实现类 + *

+ * + * @author Bunny + * @since 2024-10-18 12:56:39 + */ +@Service +public class ScheduleExecuteLogServiceImpl extends ServiceImpl implements ScheduleExecuteLogService { + + /** + * * 调度任务执行日志 服务实现类 + * + * @param pageParams 调度任务执行日志分页查询page对象 + * @param dto 调度任务执行日志分页查询对象 + * @return 查询分页调度任务执行日志返回对象 + */ + @Override + public PageResult getQuartzExecuteLogList(Page pageParams, ScheduleExecuteLogDto dto) { + IPage page = baseMapper.selectListByPage(pageParams, dto); + + return PageResult.builder() + .list(page.getRecords()) + .pageNo(page.getCurrent()) + .pageSize(page.getSize()) + .total(page.getTotal()) + .build(); + } + + /** + * 删除|批量删除调度任务执行日志 + * + * @param ids 删除id列表 + */ + @Override + public void deleteQuartzExecuteLog(List ids) { + baseMapper.deleteBatchIdsWithPhysics(ids); + } +} diff --git a/service/src/main/java/cn/bunny/services/service/schedule/impl/SchedulersGroupServiceImpl.java b/service/src/main/java/cn/bunny/services/service/schedule/impl/SchedulersGroupServiceImpl.java new file mode 100644 index 0000000..678515c --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/schedule/impl/SchedulersGroupServiceImpl.java @@ -0,0 +1,105 @@ +package cn.bunny.services.service.schedule.impl; + +import cn.bunny.dao.dto.quartz.group.SchedulersGroupAddDto; +import cn.bunny.dao.dto.quartz.group.SchedulersGroupDto; +import cn.bunny.dao.dto.quartz.group.SchedulersGroupUpdateDto; +import cn.bunny.dao.entity.quartz.SchedulersGroup; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.vo.quartz.SchedulersGroupVo; +import cn.bunny.services.mapper.schedule.SchedulersGroupMapper; +import cn.bunny.services.service.schedule.SchedulersGroupService; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import jakarta.validation.Valid; +import org.springframework.beans.BeanUtils; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 任务调度分组 服务实现类 + *

+ * + * @author Bunny + * @since 2024-10-15 20:26:32 + */ +@Service +public class SchedulersGroupServiceImpl extends ServiceImpl implements SchedulersGroupService { + + /** + * * 任务调度分组 服务实现类 + * + * @param pageParams 任务调度分组分页查询page对象 + * @param dto 任务调度分组分页查询对象 + * @return 查询分页任务调度分组返回对象 + */ + @Override + public PageResult getSchedulersGroupList(Page pageParams, SchedulersGroupDto dto) { + IPage page = baseMapper.selectListByPage(pageParams, dto); + + return PageResult.builder() + .list(page.getRecords()) + .pageNo(page.getCurrent()) + .pageSize(page.getSize()) + .total(page.getTotal()) + .build(); + } + + /** + * * 获取所有任务调度分组 + * + * @return 获取所有任务分组 + */ + @Override + @Cacheable(cacheNames = "schedulers", key = "'allSchedulersGroup'", cacheManager = "cacheManagerWithMouth") + public List getAllSchedulersGroup() { + return list().stream().map(schedulersGroup -> { + SchedulersGroupVo schedulersGroupVo = new SchedulersGroupVo(); + BeanUtils.copyProperties(schedulersGroup, schedulersGroupVo); + return schedulersGroupVo; + }).toList(); + } + + /** + * 添加任务调度分组 + * + * @param dto 任务调度分组添加 + */ + @Override + @CacheEvict(cacheNames = "schedulers", key = "'allSchedulersGroup'", beforeInvocation = true) + public void addSchedulersGroup(@Valid SchedulersGroupAddDto dto) { + // 保存数据 + SchedulersGroup schedulersGroup = new SchedulersGroup(); + BeanUtils.copyProperties(dto, schedulersGroup); + save(schedulersGroup); + } + + /** + * 更新任务调度分组 + * + * @param dto 任务调度分组更新 + */ + @Override + @CacheEvict(cacheNames = "schedulers", key = "'allSchedulersGroup'", beforeInvocation = true) + public void updateSchedulersGroup(@Valid SchedulersGroupUpdateDto dto) { + // 更新内容 + SchedulersGroup schedulersGroup = new SchedulersGroup(); + BeanUtils.copyProperties(dto, schedulersGroup); + updateById(schedulersGroup); + } + + /** + * 删除|批量删除任务调度分组 + * + * @param ids 删除id列表 + */ + @Override + @CacheEvict(cacheNames = "schedulers", key = "'allSchedulersGroup'", beforeInvocation = true) + public void deleteSchedulersGroup(List ids) { + baseMapper.deleteBatchIdsWithPhysics(ids); + } +} diff --git a/service/src/main/java/cn/bunny/services/service/schedule/impl/SchedulersServiceImpl.java b/service/src/main/java/cn/bunny/services/service/schedule/impl/SchedulersServiceImpl.java new file mode 100644 index 0000000..d118ba9 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/schedule/impl/SchedulersServiceImpl.java @@ -0,0 +1,190 @@ +package cn.bunny.services.service.schedule.impl; + +import cn.bunny.common.service.exception.BunnyException; +import cn.bunny.dao.dto.quartz.SchedulersOperationDto; +import cn.bunny.dao.dto.quartz.schedule.SchedulersAddDto; +import cn.bunny.dao.dto.quartz.schedule.SchedulersDto; +import cn.bunny.dao.entity.quartz.Schedulers; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.vo.quartz.SchedulersVo; +import cn.bunny.services.aop.AnnotationScanner; +import cn.bunny.services.aop.annotation.QuartzSchedulers; +import cn.bunny.services.mapper.schedule.SchedulersMapper; +import cn.bunny.services.service.schedule.SchedulersService; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import jakarta.validation.Valid; +import org.quartz.*; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + *

+ * Schedulers视图 服务实现类 + *

+ * + * @author Bunny + * @since 2024-10-15 16:35:10 + */ +@Service +public class SchedulersServiceImpl extends ServiceImpl implements SchedulersService { + + @Autowired + private Scheduler scheduler; + + @Autowired + private AnnotationScanner annotationScanner; + + /** + * * Schedulers视图 服务实现类 + * + * @param pageParams Schedulers视图分页查询page对象 + * @param dto Schedulers视图分页查询对象 + * @return 查询分页Schedulers视图返回对象 + */ + @Override + public PageResult getSchedulersList(Page pageParams, SchedulersDto dto) { + IPage page = baseMapper.selectListByPage(pageParams, dto); + + List voList = page.getRecords().stream().map(schedulers -> { + SchedulersVo schedulersVo = new SchedulersVo(); + BeanUtils.copyProperties(schedulers, schedulersVo); + return schedulersVo; + }).toList(); + + return PageResult.builder() + .list(voList) + .pageNo(page.getCurrent()) + .pageSize(page.getSize()) + .total(page.getTotal()) + .build(); + } + + /** + * * 获取所有可用调度任务 + * + * @return 所有调度任务内容 + */ + @Override + public List> getAllScheduleJobList() { + Set> classesWithAnnotation = annotationScanner.getClassesWithAnnotation(QuartzSchedulers.class); + return classesWithAnnotation.stream().map(cls -> { + Map hashMap = new HashMap<>(); + + // 调度器引用路径 + String classReference = cls.getName(); + // 调度器详情 + String description = cls.getAnnotation(QuartzSchedulers.class).description(); + // 调度器类型 + String type = cls.getAnnotation(QuartzSchedulers.class).type(); + + hashMap.put("value", classReference); + hashMap.put("label", description); + hashMap.put("type", type); + return hashMap; + }).toList(); + } + + /** + * 添加Schedulers视图 + * + * @param dto Schedulers视图添加 + */ + @SuppressWarnings("unchecked") + @Override + public void addSchedulers(@Valid SchedulersAddDto dto) { + String jobName = dto.getJobName(); + String jobGroup = dto.getJobGroup(); + String cronExpression = dto.getCronExpression(); + + try { + // 动态创建Class对象 + Class className = Class.forName(dto.getJobClassName()); + + // 获取无参构造函数 + className.getConstructor().newInstance(); + + // 创建任务 + JobDetail jobDetail = JobBuilder.newJob((Class) className) + .withIdentity(jobName, jobGroup) + .withDescription(dto.getDescription()) + .build(); + + // 执行任务 + CronTrigger trigger = TriggerBuilder.newTrigger() + .withIdentity(jobName, jobGroup) + .withDescription(dto.getDescription()) + .startNow() + .withSchedule(CronScheduleBuilder.cronSchedule(cronExpression)) + .build(); + + // 设置任务map值 + JobDataMap jobDataMap = jobDetail.getJobDataMap(); + jobDataMap.put("jobName", jobName); + jobDataMap.put("jobGroup", jobGroup); + jobDataMap.put("cronExpression", cronExpression); + jobDataMap.put("triggerName", trigger.getKey().getName()); + + scheduler.scheduleJob(jobDetail, trigger); + } catch (Exception exception) { + throw new BunnyException(exception.getMessage()); + } + } + + /** + * * 暂停Schedulers任务 + * + * @param dto Schedulers公共操作表单 + */ + @Override + public void pauseScheduler(SchedulersOperationDto dto) { + try { + JobKey key = new JobKey(dto.getJobName(), dto.getJobGroup()); + scheduler.pauseJob(key); + } catch (SchedulerException exception) { + throw new BunnyException(exception.getMessage()); + } + } + + /** + * * 恢复Schedulers任务 + * + * @param dto Schedulers公共操作表单 + */ + @Override + public void resumeScheduler(SchedulersOperationDto dto) { + try { + JobKey key = new JobKey(dto.getJobName(), dto.getJobGroup()); + scheduler.resumeJob(key); + } catch (SchedulerException exception) { + throw new BunnyException(exception.getMessage()); + } + } + + /** + * * 移出Schedulers任务 + * + * @param dto Schedulers公共操作表单 + */ + @Override + public void deleteSchedulers(SchedulersOperationDto dto) { + try { + String jobGroup = dto.getJobGroup(); + String jobName = dto.getJobName(); + + TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup); + scheduler.pauseTrigger(triggerKey); + scheduler.unscheduleJob(triggerKey); + scheduler.deleteJob(JobKey.jobKey(jobName, jobGroup)); + } catch (SchedulerException exception) { + throw new BunnyException(exception.getMessage()); + } + } +} diff --git a/service/src/main/java/cn/bunny/services/service/system/DeptService.java b/service/src/main/java/cn/bunny/services/service/system/DeptService.java new file mode 100644 index 0000000..cb1125c --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/system/DeptService.java @@ -0,0 +1,59 @@ +package cn.bunny.services.service.system; + +import cn.bunny.dao.dto.system.dept.DeptAddDto; +import cn.bunny.dao.dto.system.dept.DeptDto; +import cn.bunny.dao.dto.system.dept.DeptUpdateDto; +import cn.bunny.dao.entity.system.Dept; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.vo.system.DeptVo; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import jakarta.validation.Valid; + +import java.util.List; + +/** + *

+ * 部门 服务类 + *

+ * + * @author Bunny + * @since 2024-10-04 10:39:08 + */ +public interface DeptService extends IService { + + /** + * * 获取部门列表 + * + * @return 部门返回列表 + */ + PageResult getDeptList(Page pageParams, DeptDto dto); + + /** + * * 添加部门 + * + * @param dto 添加表单 + */ + void addDept(@Valid DeptAddDto dto); + + /** + * * 更新部门 + * + * @param dto 更新表单 + */ + void updateDept(@Valid DeptUpdateDto dto); + + /** + * * 删除|批量删除部门类型 + * + * @param ids 删除id列表 + */ + void deleteDept(List ids); + + /** + * * 获取所有部门 + * + * @return 所有部门列表 + */ + List getAllDeptList(); +} diff --git a/service/src/main/java/cn/bunny/services/service/system/FilesService.java b/service/src/main/java/cn/bunny/services/service/system/FilesService.java new file mode 100644 index 0000000..809628b --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/system/FilesService.java @@ -0,0 +1,87 @@ +package cn.bunny.services.service.system; + +import cn.bunny.dao.dto.system.files.FileUploadDto; +import cn.bunny.dao.dto.system.files.FilesAddDto; +import cn.bunny.dao.dto.system.files.FilesDto; +import cn.bunny.dao.dto.system.files.FilesUpdateDto; +import cn.bunny.dao.entity.system.Files; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.vo.system.files.FileInfoVo; +import cn.bunny.dao.vo.system.files.FilesVo; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import jakarta.validation.Valid; +import org.springframework.http.ResponseEntity; + +import java.util.List; +import java.util.Set; + +/** + *

+ * 系统文件表 服务类 + *

+ * + * @author Bunny + * @since 2024-10-09 16:28:01 + */ +public interface FilesService extends IService { + + /** + * * 获取系统文件表列表 + * + * @return 系统文件表返回列表 + */ + PageResult getFilesList(Page pageParams, FilesDto dto); + + /** + * * 添加系统文件表 + * + * @param dto 添加表单 + */ + void addFiles(@Valid FilesAddDto dto); + + /** + * * 更新系统文件表 + * + * @param dto 更新表单 + */ + void updateFiles(@Valid FilesUpdateDto dto); + + /** + * * 上传文件 + * + * @param dto 文件上传 + * @return 管理端返回文件信息 + */ + FileInfoVo upload(FileUploadDto dto); + + /** + * * 删除|批量删除系统文件表类型 + * + * @param ids 删除id列表 + */ + void deleteFiles(List ids); + + /** + * * 下载文件 + * + * @param fileId 文件id + * @return 文件字节数组 + */ + ResponseEntity downloadFilesByFileId(Long fileId); + + /** + * * 下载文件 + * + * @param filepath 文件路径 + * @return 文件字节数组 + */ + ResponseEntity downloadFilesByFilepath(String filepath); + + /** + * * 获取所有文件类型 + * + * @return 媒体文件类型列表 + */ + Set getAllMediaTypes(); +} diff --git a/service/src/main/java/cn/bunny/services/service/system/PowerService.java b/service/src/main/java/cn/bunny/services/service/system/PowerService.java new file mode 100644 index 0000000..71d4b98 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/system/PowerService.java @@ -0,0 +1,67 @@ +package cn.bunny.services.service.system; + +import cn.bunny.dao.dto.system.rolePower.power.PowerAddDto; +import cn.bunny.dao.dto.system.rolePower.power.PowerDto; +import cn.bunny.dao.dto.system.rolePower.power.PowerUpdateBatchByParentIdDto; +import cn.bunny.dao.dto.system.rolePower.power.PowerUpdateDto; +import cn.bunny.dao.entity.system.Power; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.vo.system.rolePower.PowerVo; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import jakarta.validation.Valid; + +import java.util.List; + +/** + *

+ * 权限 服务类 + *

+ * + * @author Bunny + * @since 2024-10-03 16:00:52 + */ +public interface PowerService extends IService { + + /** + * * 获取权限列表 + * + * @return 权限返回列表 + */ + PageResult getPowerList(Page pageParams, PowerDto dto); + + /** + * * 添加权限 + * + * @param dto 添加表单 + */ + void addPower(@Valid PowerAddDto dto); + + /** + * * 更新权限 + * + * @param dto 更新表单 + */ + void updatePower(@Valid PowerUpdateDto dto); + + /** + * * 删除|批量删除权限类型 + * + * @param ids 删除id列表 + */ + void deletePower(List ids); + + /** + * * 获取所有权限 + * + * @return 所有权限列表 + */ + List getAllPowers(); + + /** + * * 批量修改权限父级 + * + * @param dto 批量修改权限表单 + */ + void updateBatchByPowerWithParentId(PowerUpdateBatchByParentIdDto dto); +} diff --git a/service/src/main/java/cn/bunny/services/service/system/RolePowerService.java b/service/src/main/java/cn/bunny/services/service/system/RolePowerService.java new file mode 100644 index 0000000..9f05c6a --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/system/RolePowerService.java @@ -0,0 +1,34 @@ +package cn.bunny.services.service.system; + +import cn.bunny.dao.dto.system.rolePower.AssignPowersToRoleDto; +import cn.bunny.dao.entity.system.RolePower; +import com.baomidou.mybatisplus.extension.service.IService; +import jakarta.validation.Valid; + +import java.util.List; + +/** + *

+ * 服务类 + *

+ * + * @author Bunny + * @since 2024-09-26 + */ +public interface RolePowerService extends IService { + + /** + * * 根据角色id获取权限内容 + * + * @param id 角色id + * @return 已选择的权限列表 + */ + List getPowerListByRoleId(Long id); + + /** + * * 为角色分配权限 + * + * @param powerIds 权限id + */ + void assignPowersToRole(@Valid AssignPowersToRoleDto powerIds); +} diff --git a/service/src/main/java/cn/bunny/services/service/system/RoleService.java b/service/src/main/java/cn/bunny/services/service/system/RoleService.java new file mode 100644 index 0000000..c473fee --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/system/RoleService.java @@ -0,0 +1,59 @@ +package cn.bunny.services.service.system; + +import cn.bunny.dao.dto.system.rolePower.role.RoleAddDto; +import cn.bunny.dao.dto.system.rolePower.role.RoleDto; +import cn.bunny.dao.dto.system.rolePower.role.RoleUpdateDto; +import cn.bunny.dao.entity.system.Role; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.vo.system.rolePower.RoleVo; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import jakarta.validation.Valid; + +import java.util.List; + +/** + *

+ * 角色 服务类 + *

+ * + * @author Bunny + * @since 2024-10-03 14:26:24 + */ +public interface RoleService extends IService { + + /** + * * 获取角色列表 + * + * @return 角色返回列表 + */ + PageResult getRoleList(Page pageParams, RoleDto dto); + + /** + * * 添加角色 + * + * @param dto 添加表单 + */ + void addRole(@Valid RoleAddDto dto); + + /** + * * 更新角色 + * + * @param dto 更新表单 + */ + void updateRole(@Valid RoleUpdateDto dto); + + /** + * * 删除|批量删除角色类型 + * + * @param ids 删除id列表 + */ + void deleteRole(List ids); + + /** + * * 获取所有角色 + * + * @return 所有角色列表 + */ + List getAllRoles(); +} diff --git a/service/src/main/java/cn/bunny/services/service/system/RouterRoleService.java b/service/src/main/java/cn/bunny/services/service/system/RouterRoleService.java new file mode 100644 index 0000000..0d6569c --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/system/RouterRoleService.java @@ -0,0 +1,47 @@ +package cn.bunny.services.service.system; + +import cn.bunny.dao.dto.system.router.AssignRolesToRoutersDto; +import cn.bunny.dao.entity.system.RouterRole; +import com.baomidou.mybatisplus.extension.service.IService; + +import java.util.List; + +/** + *

+ * 服务类 + *

+ * + * @author Bunny + * @since 2024-09-26 + */ +public interface RouterRoleService extends IService { + + /** + * * 根据路由id获取所有角色 + * + * @param routerId 路由id + * @return 角色列表 + */ + List getRoleListByRouterId(Long routerId); + + /** + * * 为菜单分配角色 + * + * @param dto 路由分配角色 + */ + void assignRolesToRouter(AssignRolesToRoutersDto dto); + + /** + * 清除选中菜单所有角色 + * + * @param routerIds 路由id + */ + void clearAllRolesSelect(List routerIds); + + /** + * 批量为菜单添加角色 + * + * @param dto 路由分配角色 + */ + void assignAddBatchRolesToRouter(AssignRolesToRoutersDto dto); +} diff --git a/service/src/main/java/cn/bunny/services/service/system/RouterService.java b/service/src/main/java/cn/bunny/services/service/system/RouterService.java new file mode 100644 index 0000000..1f16cd0 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/system/RouterService.java @@ -0,0 +1,76 @@ +package cn.bunny.services.service.system; + +import cn.bunny.dao.dto.system.router.RouterAddDto; +import cn.bunny.dao.dto.system.router.RouterManageDto; +import cn.bunny.dao.dto.system.router.RouterUpdateByIdWithRankDto; +import cn.bunny.dao.dto.system.router.RouterUpdateDto; +import cn.bunny.dao.entity.system.Router; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.vo.system.router.RouterManageVo; +import cn.bunny.dao.vo.system.router.UserRouterVo; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import jakarta.validation.Valid; + +import java.util.List; + +/** + *

+ * 服务类 + *

+ * + * @author Bunny + * @since 2024-09-27 + */ +public interface RouterService extends IService { + /** + * * 获取路由内容 + * + * @return 路遇列表 + */ + List getRouterAsync(); + + /** + * * 管理菜单列表 + * + * @param pageParams 分页想去 + * @param dto 路由查询表单 + * @return 系统菜单表分页 + */ + PageResult getMenusByPage(Page pageParams, RouterManageDto dto); + + /** + * * 管理菜单列表 + * + * @return 系统菜单表 + */ + List getMenusList(RouterManageDto dto); + + /** + * * 添加路由菜单 + * + * @param dto 添加菜单表单 + */ + void addMenu(@Valid RouterAddDto dto); + + /** + * * 更新路由菜单 + * + * @param dto 更新表单 + */ + void updateMenu(@Valid RouterUpdateDto dto); + + /** + * * 删除路由菜单 + * + * @param ids 删除id列表 + */ + void deletedMenuByIds(List ids); + + /** + * * 快速更新菜单排序 + * + * @param dto 根据菜单Id更新菜单排序 + */ + void updateMenuByIdWithRank(RouterUpdateByIdWithRankDto dto); +} diff --git a/service/src/main/java/cn/bunny/services/service/system/UserDeptService.java b/service/src/main/java/cn/bunny/services/service/system/UserDeptService.java new file mode 100644 index 0000000..7f26018 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/system/UserDeptService.java @@ -0,0 +1,16 @@ +package cn.bunny.services.service.system; + +import cn.bunny.dao.entity.system.UserDept; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 部门用户关系表 服务类 + *

+ * + * @author Bunny + * @since 2024-10-04 + */ +public interface UserDeptService extends IService { + +} diff --git a/service/src/main/java/cn/bunny/services/service/system/UserLoginLogService.java b/service/src/main/java/cn/bunny/services/service/system/UserLoginLogService.java new file mode 100644 index 0000000..d7bd053 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/system/UserLoginLogService.java @@ -0,0 +1,44 @@ +package cn.bunny.services.service.system; + +import cn.bunny.dao.dto.log.UserLoginLogDto; +import cn.bunny.dao.entity.log.UserLoginLog; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.vo.log.UserLoginLogLocalVo; +import cn.bunny.dao.vo.log.UserLoginLogVo; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; + +import java.util.List; + +/** + *

+ * 用户登录日志 服务类 + *

+ * + * @author Bunny + * @since 2024-10-19 01:01:01 + */ +public interface UserLoginLogService extends IService { + + /** + * * 获取用户登录日志列表 + * + * @return 用户登录日志返回列表 + */ + PageResult getUserLoginLogList(Page pageParams, UserLoginLogDto dto); + + /** + * * 删除|批量删除用户登录日志类型 + * + * @param ids 删除id列表 + */ + void deleteUserLoginLog(List ids); + + /** + * * 获取本地用户登录日志 + * + * @param pageParams 分页查询内容 + * @return 用户登录日志返回列表 + */ + PageResult getUserLoginLogListByLocalUser(Page pageParams); +} diff --git a/service/src/main/java/cn/bunny/services/service/system/UserRoleService.java b/service/src/main/java/cn/bunny/services/service/system/UserRoleService.java new file mode 100644 index 0000000..d2e1018 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/system/UserRoleService.java @@ -0,0 +1,33 @@ +package cn.bunny.services.service.system; + +import cn.bunny.dao.dto.system.user.AssignRolesToUsersDto; +import cn.bunny.dao.entity.system.UserRole; +import com.baomidou.mybatisplus.extension.service.IService; + +import java.util.List; + +/** + *

+ * 服务类 + *

+ * + * @author Bunny + * @since 2024-09-26 + */ +public interface UserRoleService extends IService { + + /** + * * 为用户分配角色 + * + * @param dto 用户分配角色 + */ + void assignRolesToUsers(AssignRolesToUsersDto dto); + + /** + * * 根据用户id获取角色列表 + * + * @param userId 用户id + * @return 角色列表 + */ + List getRoleListByUserId(Long userId); +} diff --git a/service/src/main/java/cn/bunny/services/service/system/UserService.java b/service/src/main/java/cn/bunny/services/service/system/UserService.java new file mode 100644 index 0000000..65f94e1 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/system/UserService.java @@ -0,0 +1,137 @@ +package cn.bunny.services.service.system; + +import cn.bunny.dao.dto.system.user.*; +import cn.bunny.dao.entity.system.AdminUser; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.vo.system.user.*; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import jakarta.validation.Valid; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +/** + *

+ * 用户信息 服务类 + *

+ * + * @author Bunny + * @since 2024-09-26 + */ +public interface UserService extends IService { + + /** + * * 获取用户信息列表 + * + * @return 用户信息返回列表 + */ + PageResult getAdminUserList(Page pageParams, AdminUserDto dto); + + /** + * * 添加用户信息 + * + * @param dto 添加表单 + */ + void addAdminUser(@Valid AdminUserAddDto dto); + + /** + * * 更新用户信息 + * + * @param dto 更新表单 + */ + void updateAdminUser(@Valid AdminUserUpdateDto dto); + + /** + * * 删除|批量删除用户信息类型 + * + * @param ids 删除id列表 + */ + void deleteAdminUser(List ids); + + /** + * 登录发送邮件验证码 + * + * @param email 邮箱 + */ + void sendLoginEmail(@NotNull String email); + + /** + * 刷新用户token + * + * @param dto 请求token + * @return 刷新token返回内容 + */ + @NotNull + RefreshTokenVo refreshToken(@NotNull RefreshTokenDto dto); + + /** + * * 退出登录 + */ + void logout(); + + /** + * * 获取用户信息 + * + * @param id 用户id + * @return 用户信息 + */ + UserVo getUserinfoById(Long id); + + /** + * * 管理员修改管理员用户密码 + * + * @param dto 管理员用户修改密码 + */ + void updateUserPasswordByAdmin(AdminUserUpdateWithPasswordDto dto); + + /** + * * 管理员上传用户头像 + * + * @param dto 管理员用户修改头像 + */ + void uploadAvatarByAdmin(UserUpdateWithAvatarDto dto); + + /** + * * 强制退出 + * + * @param id 用户id + */ + void forcedOffline(Long id); + + /** + * * 查询用户 + * + * @param keyword 查询用户信息关键字 + * @return 用户信息列表 + */ + List queryUser(String keyword); + + /** + * * 修改用户状态 + * + * @param dto 管理员用户修改密码 + */ + void updateUserStatusByAdmin(AdminUserUpdateUserStatusDto dto); + + /** + * * 获取本地登录用户信息 + * + * @return 用户信息 + */ + LoginVo getUserinfo(); + + /** + * * 更新本地用户信息 + * + * @param dto 用户信息 + */ + void updateAdminUserByLocalUser(AdminUserUpdateByLocalUserDto dto); + + /** + * * 更新本地用户密码 + * + * @param password 更新本地用户密码 + */ + void updateUserPasswordByLocalUser(@Valid String password); +} diff --git a/service/src/main/java/cn/bunny/services/service/system/impl/DeptServiceImpl.java b/service/src/main/java/cn/bunny/services/service/system/impl/DeptServiceImpl.java new file mode 100644 index 0000000..7def05c --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/system/impl/DeptServiceImpl.java @@ -0,0 +1,133 @@ +package cn.bunny.services.service.system.impl; + +import cn.bunny.common.service.exception.BunnyException; +import cn.bunny.dao.dto.system.dept.DeptAddDto; +import cn.bunny.dao.dto.system.dept.DeptDto; +import cn.bunny.dao.dto.system.dept.DeptUpdateDto; +import cn.bunny.dao.entity.system.Dept; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.system.DeptVo; +import cn.bunny.services.mapper.system.DeptMapper; +import cn.bunny.services.mapper.system.UserDeptMapper; +import cn.bunny.services.service.system.DeptService; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.stream.Collectors; + +/** + *

+ * 部门 服务实现类 + *

+ * + * @author Bunny + * @since 2024-10-04 10:39:08 + */ +@Service +@Transactional +public class DeptServiceImpl extends ServiceImpl implements DeptService { + + @Autowired + private UserDeptMapper userDeptMapper; + + /** + * * 部门 服务实现类 + * + * @param pageParams 部门分页查询page对象 + * @param dto 部门分页查询对象 + * @return 查询分页部门返回对象 + */ + @Override + public PageResult getDeptList(Page pageParams, DeptDto dto) { + IPage page = baseMapper.selectListByPage(pageParams, dto); + + return PageResult.builder() + .list(page.getRecords()) + .pageNo(page.getCurrent()) + .pageSize(page.getSize()) + .total(page.getTotal()) + .build(); + } + + /** + * * 获取所有部门 + * + * @return 所有部门列表 + */ + @Override + @Cacheable(cacheNames = "dept", key = "'allDept'", cacheManager = "cacheManagerWithMouth") + public List getAllDeptList() { + return list().stream().map(dept -> { + DeptVo deptVo = new DeptVo(); + BeanUtils.copyProperties(dept, deptVo); + return deptVo; + }).toList(); + } + + /** + * 添加部门 + * + * @param dto 部门添加 + */ + @Override + @CacheEvict(cacheNames = "dept", key = "'allDept'", beforeInvocation = true) + public void addDept(DeptAddDto dto) { + // 整理管理者人员 + String mangerList = dto.getManager().stream().map(String::trim).collect(Collectors.joining(",")); + + // 保存数据 + Dept dept = new Dept(); + BeanUtils.copyProperties(dto, dept); + dept.setManager(mangerList); + + save(dept); + } + + /** + * 更新部门 + * + * @param dto 部门更新 + */ + @Override + @CacheEvict(cacheNames = "dept", key = "'allDept'", beforeInvocation = true) + public void updateDept(DeptUpdateDto dto) { + if (dto.getId().equals(dto.getParentId())) throw new BunnyException(ResultCodeEnum.ILLEGAL_DATA_REQUEST); + + // 将管理员用户逗号分隔 + String mangerList = dto.getManager().stream().map(String::trim).collect(Collectors.joining(",")); + + // 更新内容 + Dept dept = new Dept(); + BeanUtils.copyProperties(dto, dept); + dept.setManager(mangerList); + + updateById(dept); + } + + /** + * 删除|批量删除部门 + * + * @param ids 删除id列表 + */ + @Override + @CacheEvict(cacheNames = "dept", key = "'allDept'", beforeInvocation = true) + public void deleteDept(List ids) { + // 判断数据请求是否为空 + if (ids.isEmpty()) throw new BunnyException(ResultCodeEnum.REQUEST_IS_EMPTY); + + // 删除当前部门 + baseMapper.deleteBatchIdsWithPhysics(ids); + + // 删除用户部门关联 + userDeptMapper.deleteBatchIdsByDeptIdWithPhysics(ids); + } +} diff --git a/service/src/main/java/cn/bunny/services/service/system/impl/FilesServiceImpl.java b/service/src/main/java/cn/bunny/services/service/system/impl/FilesServiceImpl.java new file mode 100644 index 0000000..c55491b --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/system/impl/FilesServiceImpl.java @@ -0,0 +1,292 @@ +package cn.bunny.services.service.system.impl; + +import cn.bunny.common.service.context.BaseContext; +import cn.bunny.common.service.exception.BunnyException; +import cn.bunny.common.service.utils.FileUtil; +import cn.bunny.common.service.utils.minio.MinioProperties; +import cn.bunny.common.service.utils.minio.MinioUtil; +import cn.bunny.dao.dto.system.files.FileUploadDto; +import cn.bunny.dao.dto.system.files.FilesAddDto; +import cn.bunny.dao.dto.system.files.FilesDto; +import cn.bunny.dao.dto.system.files.FilesUpdateDto; +import cn.bunny.dao.entity.system.Files; +import cn.bunny.dao.pojo.common.MinioFilePath; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.system.files.FileInfoVo; +import cn.bunny.dao.vo.system.files.FilesVo; +import cn.bunny.services.mapper.system.FilesMapper; +import cn.bunny.services.service.system.FilesService; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import jakarta.validation.Valid; +import lombok.SneakyThrows; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + *

+ * 系统文件表 服务实现类 + *

+ * + * @author Bunny + * @since 2024-10-09 16:28:01 + */ +@Service +@Transactional +public class FilesServiceImpl extends ServiceImpl implements FilesService { + + @Value("${spring.servlet.multipart.max-file-size}") + private String maxFileSize; + + @Autowired + private MinioProperties properties; + + @Autowired + private MinioUtil minioUtil; + + @Autowired + private FilesMapper filesMapper; + + /** + * * 系统文件表 服务实现类 + * + * @param pageParams 系统文件表分页查询page对象 + * @param dto 系统文件表分页查询对象 + * @return 查询分页系统文件表返回对象 + */ + @Override + public PageResult getFilesList(Page pageParams, FilesDto dto) { + IPage page = baseMapper.selectListByPage(pageParams, dto); + + return PageResult.builder() + .list(page.getRecords()) + .pageNo(page.getCurrent()) + .pageSize(page.getSize()) + .total(page.getTotal()) + .build(); + } + + /** + * 添加系统文件表 + * + * @param dto 系统文件表添加 + */ + @Override + public void addFiles(FilesAddDto dto) { + List list = dto.getFiles().stream().map(file -> { + try { + MinioFilePath minioFilePath = minioUtil.uploadObjectReturnFilePath(file, dto.getFilepath()); + + Files files = new Files(); + files.setFileType(file.getContentType()); + files.setFileSize(file.getSize()); + files.setFilepath("/" + properties.getBucketName() + minioFilePath.getFilepath()); + files.setFilename(minioFilePath.getFilename()); + files.setDownloadCount(dto.getDownloadCount()); + return files; + } catch (IOException e) { + throw new BunnyException(e.getMessage()); + } + }).toList(); + + // 保存数据 + saveBatch(list); + } + + /** + * 更新系统文件表 + * + * @param dto 系统文件表更新 + */ + @Override + public void updateFiles(@Valid FilesUpdateDto dto) { + Long id = dto.getId(); + MultipartFile file = dto.getFiles(); + Files files = getOne(Wrappers.lambdaQuery().eq(Files::getId, id)); + + if (file != null) { + // 文件路径 + String filePath = files.getFilepath().replace("/" + properties.getBucketName() + "/", ""); + minioUtil.updateFile(properties.getBucketName(), filePath, file); + + // 设置文件信息 + files.setFileSize(file.getSize()); + files.setFileType(file.getContentType()); + } + + // 更新内容 + files = new Files(); + BeanUtils.copyProperties(dto, files); + updateById(files); + } + + /** + * * 上传文件 + * + * @param dto 文件上传 + * @return 管理端返回文件信息 + */ + @SneakyThrows + @Override + public FileInfoVo upload(FileUploadDto dto) { + // 上传的文件 + MultipartFile file = dto.getFile(); + // 上传文件类型 + String type = dto.getType(); + // 管理员Id + Long userId = BaseContext.getUserId(); + // 文件大小 + long fileSize = file.getSize(); + // 文件类型 + String contentType = file.getContentType(); + // 文件名 + String filename = file.getOriginalFilename(); + + // 上传文件 + MinioFilePath minioFIlePath = minioUtil.uploadObjectReturnFilePath(file, type); + String bucketNameFilepath = minioFIlePath.getBucketNameFilepath(); + + // 盘读研数据是否过大 + String mb = maxFileSize.replace("MB", ""); + if (fileSize / 1024 / 1024 > Long.parseLong(mb)) throw new BunnyException(ResultCodeEnum.DATA_TOO_LARGE); + + // 插入文件信息 + Files adminFiles = new Files(); + adminFiles.setFileSize(fileSize); + adminFiles.setFileType(contentType); + adminFiles.setFilename(filename); + adminFiles.setFilepath(bucketNameFilepath); + adminFiles.setCreateUser(userId); + filesMapper.insert(adminFiles); + + // 返回信息内容化 + return FileInfoVo.builder() + .size(FileUtil.getSize(fileSize)) + .filepath(bucketNameFilepath) + .fileSize(fileSize) + .fileType(contentType) + .filename(filename) + .url(minioUtil.getObjectNameFullPath(bucketNameFilepath)) + .build(); + } + + /** + * 删除|批量删除系统文件表 + * + * @param ids 删除id列表 + */ + @Override + public void deleteFiles(List ids) { + if (ids.isEmpty()) throw new BunnyException(ResultCodeEnum.REQUEST_IS_EMPTY); + + // 查询文件路径 + List list = list(Wrappers.lambdaQuery().in(Files::getId, ids)).stream() + .map(files -> { + String filepath = files.getFilepath(); + int end = filepath.indexOf("/", 1); + return filepath.substring(end + 1); + }).toList(); + + // 删除目标文件 + minioUtil.removeObjects(list); + + // 删除数据库内容 + baseMapper.deleteBatchIdsWithPhysics(ids); + } + + /** + * * 下载文件 + * + * @param fileId 文件id + * @return 文件字节数组 + */ + @Override + public ResponseEntity downloadFilesByFileId(Long fileId) { + // 查询数据库文件信息 + Files files = getOne(Wrappers.lambdaQuery().eq(Files::getId, fileId)); + + // 判断文件是否存在 + if (files == null) throw new BunnyException(ResultCodeEnum.FILE_NOT_EXIST); + + // 从Minio获取文件 + String filepath = files.getFilepath(); + int end = filepath.indexOf("/", 1); + filepath = filepath.substring(end + 1); + byte[] bytes = minioUtil.getBucketObjectByte(filepath); + + // 设置响应头 + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); + headers.setContentDispositionFormData("attachment", files.getFilename()); + + return new ResponseEntity<>(bytes, headers, HttpStatus.OK); + } + + /** + * * 下载文件 + * + * @param filepath 文件路径 + * @return 文件字节数组 + */ + @Override + public ResponseEntity downloadFilesByFilepath(String filepath) { + // 截取文件路径 + int start = filepath.indexOf("/", 1); + filepath = filepath.substring(start + 1); + byte[] bytes = minioUtil.getBucketObjectByte(filepath); + + // 设置文件名称 + int end = filepath.lastIndexOf("/"); + String filename = filepath.substring(end + 1); + + // 设置响应头 + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); + headers.setContentDispositionFormData("attachment", filename); + + return new ResponseEntity<>(bytes, headers, HttpStatus.OK); + } + + /** + * * 获取所有文件类型 + * + * @return 媒体文件类型列表 + */ + @Override + public Set getAllMediaTypes() { + Set valueList = new HashSet<>(); + Class mediaTypeClass = MediaType.class; + + try { + for (Field declaredField : mediaTypeClass.getDeclaredFields()) { + // 获取字段属性值 + declaredField.setAccessible(true); + String value = declaredField.get(null).toString(); + + if (value.matches("\\w+/.*")) { + valueList.add(value); + } + } + return valueList; + } catch (Exception exception) { + return Set.of(); + } + } +} diff --git a/service/src/main/java/cn/bunny/services/service/system/impl/PowerServiceImpl.java b/service/src/main/java/cn/bunny/services/service/system/impl/PowerServiceImpl.java new file mode 100644 index 0000000..8b250e2 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/system/impl/PowerServiceImpl.java @@ -0,0 +1,156 @@ +package cn.bunny.services.service.system.impl; + +import cn.bunny.common.service.exception.BunnyException; +import cn.bunny.dao.dto.system.rolePower.power.PowerAddDto; +import cn.bunny.dao.dto.system.rolePower.power.PowerDto; +import cn.bunny.dao.dto.system.rolePower.power.PowerUpdateBatchByParentIdDto; +import cn.bunny.dao.dto.system.rolePower.power.PowerUpdateDto; +import cn.bunny.dao.entity.system.Power; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.system.rolePower.PowerVo; +import cn.bunny.services.mapper.system.PowerMapper; +import cn.bunny.services.mapper.system.RolePowerMapper; +import cn.bunny.services.service.system.PowerService; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import jakarta.validation.Valid; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +/** + *

+ * 权限 服务实现类 + *

+ * + * @author Bunny + * @since 2024-10-03 16:00:52 + */ +@Service +@Transactional +public class PowerServiceImpl extends ServiceImpl implements PowerService { + + @Autowired + private RolePowerMapper rolePowerMapper; + + /** + * * 权限 服务实现类 + * + * @param pageParams 权限分页查询page对象 + * @param dto 权限分页查询对象 + * @return 查询分页权限返回对象 + */ + @Override + public PageResult getPowerList(Page pageParams, PowerDto dto) { + IPage page = baseMapper.selectListByPage(pageParams, dto); + + return PageResult.builder() + .list(page.getRecords()) + .pageNo(page.getCurrent()) + .pageSize(page.getSize()) + .total(page.getTotal()) + .build(); + } + + /** + * * 获取所有权限 + * + * @return 所有权限列表 + */ + @Override + @Cacheable(cacheNames = "power", key = "'allPower'", cacheManager = "cacheManagerWithMouth") + public List getAllPowers() { + List powerList = list(); + return powerList.stream().map(power -> { + PowerVo powerVo = new PowerVo(); + BeanUtils.copyProperties(power, powerVo); + return powerVo; + }).toList(); + } + + /** + * 添加权限 + * + * @param dto 权限添加 + */ + @Override + @CacheEvict(cacheNames = "power", key = "'allPower'", beforeInvocation = true) + public void addPower(@Valid PowerAddDto dto) { + // 添加权限时确保权限码和请求地址是唯一的 + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(Power::getPowerCode, dto.getPowerCode()) + .or() + .eq(Power::getRequestUrl, dto.getRequestUrl()); + List powerList = list(wrapper); + if (!powerList.isEmpty()) throw new BunnyException(ResultCodeEnum.DATA_EXIST); + + // 保存数据 + Power power = new Power(); + BeanUtils.copyProperties(dto, power); + save(power); + } + + /** + * 更新权限 + * + * @param dto 权限更新 + */ + @Override + @CacheEvict(cacheNames = "power", key = "'allPower'", beforeInvocation = true) + public void updatePower(@Valid PowerUpdateDto dto) { + Long id = dto.getId(); + List powerList = list(Wrappers.lambdaQuery().eq(Power::getId, id)); + if (powerList.isEmpty()) throw new BunnyException(ResultCodeEnum.DATA_NOT_EXIST); + if (dto.getId().equals(dto.getParentId())) throw new BunnyException(ResultCodeEnum.ILLEGAL_DATA_REQUEST); + + // 更新内容 + Power power = new Power(); + BeanUtils.copyProperties(dto, power); + updateById(power); + } + + /** + * 删除|批量删除权限 + * + * @param ids 删除id列表 + */ + @Override + @CacheEvict(cacheNames = "power", key = "'allPower'", beforeInvocation = true) + public void deletePower(List ids) { + // 判断数据请求是否为空 + if (ids.isEmpty()) throw new BunnyException(ResultCodeEnum.REQUEST_IS_EMPTY); + + // 删除权限 + baseMapper.deleteBatchIdsWithPhysics(ids); + + // 删除角色部门相关 + rolePowerMapper.deleteBatchPowerIdsWithPhysics(ids); + } + + /** + * * 批量修改权限父级 + * + * @param dto 批量修改权限表单 + */ + @Override + @CacheEvict(cacheNames = "power", key = "'allPower'", beforeInvocation = true) + public void updateBatchByPowerWithParentId(PowerUpdateBatchByParentIdDto dto) { + List powerList = dto.getIds().stream().map(id -> { + Power power = new Power(); + power.setId(id); + power.setParentId(dto.getParentId()); + return power; + }).toList(); + + updateBatchById(powerList); + } +} diff --git a/service/src/main/java/cn/bunny/services/service/system/impl/RolePowerServiceImpl.java b/service/src/main/java/cn/bunny/services/service/system/impl/RolePowerServiceImpl.java new file mode 100644 index 0000000..81d384e --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/system/impl/RolePowerServiceImpl.java @@ -0,0 +1,88 @@ +package cn.bunny.services.service.system.impl; + +import cn.bunny.dao.dto.system.rolePower.AssignPowersToRoleDto; +import cn.bunny.dao.entity.system.AdminUser; +import cn.bunny.dao.entity.system.RolePower; +import cn.bunny.dao.entity.system.UserRole; +import cn.bunny.services.factory.RoleFactory; +import cn.bunny.services.mapper.system.RolePowerMapper; +import cn.bunny.services.mapper.system.UserMapper; +import cn.bunny.services.mapper.system.UserRoleMapper; +import cn.bunny.services.service.system.RolePowerService; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +/** + *

+ * 服务实现类 + *

+ * + * @author Bunny + * @since 2024-09-26 + */ +@Service +@Transactional +public class RolePowerServiceImpl extends ServiceImpl implements RolePowerService { + + @Autowired + private UserMapper userMapper; + + @Autowired + private RoleFactory roleFactory; + @Autowired + private UserRoleMapper userRoleMapper; + + /** + * * 根据角色id获取权限内容 + * + * @param id 角色id + * @return 已选择的权限列表 + */ + @Override + public List getPowerListByRoleId(Long id) { + List rolePowerList = baseMapper.selectPowerListByRoleId(id); + return rolePowerList.stream().map(rolePower -> rolePower.getPowerId().toString()).toList(); + } + + /** + * * 为角色分配权限 + * + * @param dto 为角色分配权限表单 + */ + @Override + public void assignPowersToRole(AssignPowersToRoleDto dto) { + List powerIds = dto.getPowerIds(); + Long roleId = dto.getRoleId(); + + // 删除这个角色下所有权限 + baseMapper.deleteBatchRoleIdsWithPhysics(List.of(roleId)); + + // 保存分配数据 + List rolePowerList = powerIds.stream().map(powerId -> { + RolePower rolePower = new RolePower(); + rolePower.setRoleId(roleId); + rolePower.setPowerId(powerId); + return rolePower; + }).toList(); + saveBatch(rolePowerList); + + // 找到所有和当前更新角色相同的用户 + List roleIds = userRoleMapper.selectList(Wrappers.lambdaQuery().eq(UserRole::getRoleId, roleId)) + .stream().map(UserRole::getUserId).toList(); + + // 根据Id查找所有用户 + List adminUsers = userMapper.selectList(Wrappers.lambdaQuery().in(!roleIds.isEmpty(), AdminUser::getId, roleIds)); + + // 用户为空时不更新Redis的key + if (adminUsers.isEmpty()) return; + + // 更新Redis中用户信息 + List userIds = adminUsers.stream().map(AdminUser::getId).toList(); + roleFactory.updateUserRedisInfo(userIds); + } +} diff --git a/service/src/main/java/cn/bunny/services/service/system/impl/RoleServiceImpl.java b/service/src/main/java/cn/bunny/services/service/system/impl/RoleServiceImpl.java new file mode 100644 index 0000000..fa8955b --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/system/impl/RoleServiceImpl.java @@ -0,0 +1,148 @@ +package cn.bunny.services.service.system.impl; + +import cn.bunny.common.service.exception.BunnyException; +import cn.bunny.dao.dto.system.rolePower.role.RoleAddDto; +import cn.bunny.dao.dto.system.rolePower.role.RoleDto; +import cn.bunny.dao.dto.system.rolePower.role.RoleUpdateDto; +import cn.bunny.dao.entity.system.Role; +import cn.bunny.dao.entity.system.UserRole; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.system.rolePower.RoleVo; +import cn.bunny.services.factory.RoleFactory; +import cn.bunny.services.mapper.system.RoleMapper; +import cn.bunny.services.mapper.system.RolePowerMapper; +import cn.bunny.services.mapper.system.RouterRoleMapper; +import cn.bunny.services.mapper.system.UserRoleMapper; +import cn.bunny.services.service.system.RoleService; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import jakarta.validation.Valid; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 角色 服务实现类 + *

+ * + * @author Bunny + * @since 2024-10-03 14:26:24 + */ +@Service +public class RoleServiceImpl extends ServiceImpl implements RoleService { + + @Autowired + private UserRoleMapper userRoleMapper; + + @Autowired + private RolePowerMapper rolePowerMapper; + + @Autowired + private RouterRoleMapper routerRoleMapper; + + @Autowired + private RoleFactory roleFactory; + + /** + * * 角色 服务实现类 + * + * @param pageParams 角色分页查询page对象 + * @param dto 角色分页查询对象 + * @return 查询分页角色返回对象 + */ + @Override + public PageResult getRoleList(Page pageParams, RoleDto dto) { + IPage page = baseMapper.selectListByPage(pageParams, dto); + + return PageResult.builder() + .list(page.getRecords()) + .pageNo(page.getCurrent()) + .pageSize(page.getSize()) + .total(page.getTotal()) + .build(); + } + + /** + * * 获取所有角色 + * + * @return 所有角色列表 + */ + @Override + @Cacheable(cacheNames = "role", key = "'allRole'", cacheManager = "cacheManagerWithMouth") + public List getAllRoles() { + return list().stream().map(role -> { + RoleVo roleVo = new RoleVo(); + BeanUtils.copyProperties(role, roleVo); + return roleVo; + }).toList(); + } + + /** + * 添加角色 + * + * @param dto 角色添加 + */ + @Override + @CacheEvict(cacheNames = "role", key = "'allRole'", beforeInvocation = true) + public void addRole(@Valid RoleAddDto dto) { + Role role = new Role(); + BeanUtils.copyProperties(dto, role); + save(role); + } + + /** + * 更新角色 + * + * @param dto 角色更新 + */ + @Override + @CacheEvict(cacheNames = "role", key = "'allRole'", beforeInvocation = true) + public void updateRole(@Valid RoleUpdateDto dto) { + // 查询更新的角色是否存在 + List roleList = list(Wrappers.lambdaQuery().eq(Role::getId, dto.getId())); + if (roleList.isEmpty()) throw new BunnyException(ResultCodeEnum.DATA_NOT_EXIST); + + // 更新内容 + Role role = new Role(); + BeanUtils.copyProperties(dto, role); + updateById(role); + + // 找到所有和当前更新角色相同的用户,并更新Redis中用户信息 + List userIds = userRoleMapper.selectList(Wrappers.lambdaQuery().eq(UserRole::getRoleId, dto.getId())) + .stream().map(UserRole::getUserId).toList(); + roleFactory.updateUserRedisInfo(userIds); + } + + + /** + * 删除|批量删除角色 + * + * @param ids 删除id列表 + */ + @Override + @CacheEvict(cacheNames = "role", key = "'allRole'", beforeInvocation = true) + public void deleteRole(List ids) { + // 判断数据请求是否为空 + if (ids.isEmpty()) throw new BunnyException(ResultCodeEnum.REQUEST_IS_EMPTY); + + // 删除角色 + baseMapper.deleteBatchIdsWithPhysics(ids); + + // 删除角色权限相关 + rolePowerMapper.deleteBatchRoleIdsWithPhysics(ids); + + // 删除角色和用户相关 + userRoleMapper.deleteBatchIdsByRoleIdsWithPhysics(ids); + + // 删除角色和路由相关 + routerRoleMapper.deleteBatchIdsByRoleIdsWithPhysics(ids); + } +} diff --git a/service/src/main/java/cn/bunny/services/service/system/impl/RouterRoleServiceImpl.java b/service/src/main/java/cn/bunny/services/service/system/impl/RouterRoleServiceImpl.java new file mode 100644 index 0000000..2f2cc94 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/system/impl/RouterRoleServiceImpl.java @@ -0,0 +1,121 @@ +package cn.bunny.services.service.system.impl; + +import cn.bunny.common.service.exception.BunnyException; +import cn.bunny.dao.dto.system.router.AssignRolesToRoutersDto; +import cn.bunny.dao.entity.system.RouterRole; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.services.mapper.system.RouterRoleMapper; +import cn.bunny.services.service.system.RouterRoleService; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; + +/** + *

+ * 服务实现类 + *

+ * + * @author Bunny + * @since 2024-09-26 + */ +@Service +@Transactional +public class RouterRoleServiceImpl extends ServiceImpl implements RouterRoleService { + + /** + * * 根据路由id获取所有角色 + * + * @param routerId 路由id + * @return 角色列表 + */ + @Override + public List getRoleListByRouterId(Long routerId) { + return list(Wrappers.lambdaQuery().eq(RouterRole::getRouterId, routerId)).stream() + .map(routerRole -> routerRole.getRoleId().toString()).toList(); + } + + /** + * * 为菜单分配角色 + * + * @param dto 路由分配角色 + */ + @Override + public void assignRolesToRouter(AssignRolesToRoutersDto dto) { + List routerIds = dto.getRouterIds(); + List roleIds = dto.getRoleIds(); + + // 删除这个路由下所有已经分配好的角色内容 + baseMapper.deleteBatchIdsByRouterIdsWithPhysics(routerIds); + + // 保存分配好的角色信息 + List roleList = new ArrayList<>(); + for (Long roleId : roleIds) { + List list = routerIds.stream().map(routerId -> { + RouterRole routerRole = new RouterRole(); + routerRole.setRouterId(routerId); + routerRole.setRoleId(roleId); + return routerRole; + }).toList(); + + roleList.addAll(list); + } + + saveBatch(roleList); + } + + /** + * 清除选中菜单所有角色 + * + * @param routerIds 路由id + */ + @Override + public void clearAllRolesSelect(List routerIds) { + if (routerIds.isEmpty()) { + throw new BunnyException(ResultCodeEnum.REQUEST_IS_EMPTY); + } + baseMapper.deleteBatchIdsByRouterIdsWithPhysics(routerIds); + } + + /** + * 批量为菜单添加角色 + * 查询所有满足角色id列表的路由 + * 将满足条件的路由提取出routerId列表 + * 并删除所有routerIds + * + * @param dto 路由分配角色 + */ + @Override + public void assignAddBatchRolesToRouter(AssignRolesToRoutersDto dto) { + // 查询所有满足角色id和路由Id相关 + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.in(RouterRole::getRoleId, dto.getRoleIds()) + .and(qw -> qw.in(RouterRole::getRouterId, dto.getRouterIds())); + List routerRoleList = list(wrapper); + + // 根据Id列表物理删除路由角色关系表 + List ids = routerRoleList.stream().map(RouterRole::getId).toList(); + if (!ids.isEmpty()) { + baseMapper.deleteBatchIdsWithPhysics(ids); + } + + // 保存分配好的角色信息 + List roleList = new ArrayList<>(); + for (Long roleId : dto.getRoleIds()) { + List list = dto.getRouterIds().stream().map(routerId -> { + RouterRole routerRole = new RouterRole(); + routerRole.setRouterId(routerId); + routerRole.setRoleId(roleId); + return routerRole; + }).toList(); + + roleList.addAll(list); + } + + saveBatch(roleList); + } +} diff --git a/service/src/main/java/cn/bunny/services/service/system/impl/RouterServiceImpl.java b/service/src/main/java/cn/bunny/services/service/system/impl/RouterServiceImpl.java new file mode 100644 index 0000000..1856b96 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/system/impl/RouterServiceImpl.java @@ -0,0 +1,267 @@ +package cn.bunny.services.service.system.impl; + +import cn.bunny.common.service.context.BaseContext; +import cn.bunny.common.service.exception.BunnyException; +import cn.bunny.dao.dto.system.router.RouterAddDto; +import cn.bunny.dao.dto.system.router.RouterManageDto; +import cn.bunny.dao.dto.system.router.RouterUpdateByIdWithRankDto; +import cn.bunny.dao.dto.system.router.RouterUpdateDto; +import cn.bunny.dao.entity.system.Role; +import cn.bunny.dao.entity.system.Router; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.view.ViewRolePower; +import cn.bunny.dao.view.ViewRouterRole; +import cn.bunny.dao.vo.system.router.RouterManageVo; +import cn.bunny.dao.vo.system.router.RouterMeta; +import cn.bunny.dao.vo.system.router.UserRouterVo; +import cn.bunny.services.factory.RouterServiceFactory; +import cn.bunny.services.mapper.system.RoleMapper; +import cn.bunny.services.mapper.system.RolePowerMapper; +import cn.bunny.services.mapper.system.RouterMapper; +import cn.bunny.services.mapper.system.RouterRoleMapper; +import cn.bunny.services.security.custom.CustomCheckIsAdmin; +import cn.bunny.services.service.system.RouterService; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import java.util.stream.Collectors; + +/** + *

+ * 服务实现类 + *

+ * + * @author Bunny + * @since 2024-09-27 + */ +@Service +@Transactional +public class RouterServiceImpl extends ServiceImpl implements RouterService { + @Autowired + private RouterServiceFactory routerServiceFactory; + + @Autowired + private RoleMapper roleMapper; + + @Autowired + private RouterRoleMapper routerRoleMapper; + + @Autowired + private RolePowerMapper rolePowerMapper; + + /** + * * 获取路由内容 + * + * @return 路遇列表 + */ + @Override + public List getRouterAsync() { + // 根据用户ID查询角色数据 + Long userId = BaseContext.getUserId(); + + // 查询角色信息 + List roleList; + List userRoleCodeList; + if (userId.equals(1L)) { + userRoleCodeList = List.of("admin"); + } else { + roleList = roleMapper.selectListByUserId(userId); + userRoleCodeList = roleList.stream().map(Role::getRoleCode).toList(); + } + + // 如果没有分配角色直接返回空数组 + if (userRoleCodeList.isEmpty()) return new ArrayList<>(); + + // 返回路由列表 + List list = new ArrayList<>(); + + // 查询用户角色,判断是否是管理员角色 + boolean isAdmin = CustomCheckIsAdmin.checkAdmin(userRoleCodeList); + + // 查询路由和角色对应关系 + List routerRoleList = routerRoleMapper.viewRouterRolesWithAll(); + Map> routerIdWithRoleCodeMap = routerRoleList.stream() + .collect(Collectors.groupingBy( + ViewRouterRole::getRouterId, + Collectors.mapping(ViewRouterRole::getRoleCode, Collectors.toUnmodifiableList()) + )); + + // 角色和权限对应关系 + List rolePowerList = rolePowerMapper.viewRolePowerWithAll(); + Map> roleCodeWithPowerCodeMap = rolePowerList.stream() + .collect(Collectors.groupingBy( + ViewRolePower::getRoleCode, + Collectors.mapping(ViewRolePower::getPowerCode, Collectors.toUnmodifiableSet()) + )); + + // 查询所有路由内容 + List routerList = list(); + + // 构建返回路由列表 + List routerVoList = routerList.stream() + .sorted(Comparator.comparing(Router::getRouterRank)) + .filter(Router::getVisible) + .map(router -> { + // 角色码列表 + List roleCodeList; + + // 权限码列表 + List powerCodeList; + + // 判断是否是admin + if (isAdmin) { + roleCodeList = userRoleCodeList; + powerCodeList = List.of("*", "*::*", "*::*::*"); + } else { + roleCodeList = routerIdWithRoleCodeMap.getOrDefault(router.getId(), Collections.emptyList()); + powerCodeList = roleCodeList.stream() + .map(roleCodeWithPowerCodeMap::get) + .filter(Objects::nonNull) + .flatMap(Set::stream) + .collect(Collectors.toUnmodifiableSet()) + .stream().toList(); + } + + // 复制对象 + UserRouterVo routerVo = new UserRouterVo(); + BeanUtils.copyProperties(router, routerVo); + + // 设置 + RouterMeta meta = RouterMeta.builder() + .frameSrc(router.getFrameSrc()) + .rank(router.getRouterRank()) + .icon(router.getIcon()) + .title(router.getTitle()) + .roles(roleCodeList) + .auths(powerCodeList) + .build(); + + routerVo.setMeta(meta); + return routerVo; + }).distinct().toList(); + + // 构建树形结构 + routerVoList.forEach(routerVo -> { + if (routerVo.getParentId() == 0) { + routerVo.setChildren(routerServiceFactory.handleGetChildrenWIthRouter(routerVo.getId(), routerVoList)); + list.add(routerVo); + } + }); + + return list; + } + + /** + * * 管理菜单列表 + * + * @param pageParams 分页想去 + * @param dto 路由查询表单 + * @return 系统菜单表分页 + */ + @Override + public PageResult getMenusByPage(Page pageParams, RouterManageDto dto) { + IPage page = baseMapper.selectListByPage(pageParams, dto); + + // 构建返回对象 + List voList = page.getRecords().stream() + .sorted(Comparator.comparing(RouterManageVo::getRouterRank)) + .toList(); + + return PageResult.builder() + .list(voList) + .pageNo(page.getCurrent()) + .pageSize(page.getSize()) + .total(page.getTotal()) + .build(); + } + + /** + * * 管理菜单列表 + * + * @return 系统菜单表 + */ + @Override + public List getMenusList(RouterManageDto dto) { + List list = baseMapper.selectAllList(dto); + return list.stream() + .sorted(Comparator.comparing(RouterManageVo::getRouterRank)) + .toList(); + } + + /** + * * 添加路由菜单 + * + * @param dto 添加菜单表单 + */ + @Override + public void addMenu(RouterAddDto dto) { + // 添加路由 + Router router = new Router(); + BeanUtils.copyProperties(dto, router); + + save(router); + } + + /** + * * 更新路由菜单 + * + * @param dto 更新表单 + */ + @Override + public void updateMenu(RouterUpdateDto dto) { + // 如果设置的不是外部页面 + if (!dto.getMenuType().equals(2)) dto.setFrameSrc(""); + + Router router = new Router(); + BeanUtils.copyProperties(dto, router); + updateById(router); + } + + /** + * * 删除路由菜单 + * + * @param ids 删除id列表 + */ + @Override + public void deletedMenuByIds(List ids) { + // 判断数据请求是否为空 + if (ids.isEmpty()) throw new BunnyException(ResultCodeEnum.REQUEST_IS_EMPTY); + + // 查找子级菜单,一起删除 + List longList = list(Wrappers.lambdaQuery().in(Router::getParentId, ids)).stream().map(Router::getId).toList(); + ids.addAll(longList); + + // 逻辑删除 + removeBatchByIds(ids); + + // // 物理删除 + // baseMapper.deleteBatchIdsWithPhysics(ids); + } + + /** + * * 快速更新菜单排序 + * + * @param dto 根据菜单Id更新菜单排序 + */ + @Override + public void updateMenuByIdWithRank(RouterUpdateByIdWithRankDto dto) { + Router router = getOne(Wrappers.lambdaQuery().eq(Router::getId, dto.getId())); + + // 判断更新数据是否存在 + if (router == null) throw new BunnyException(ResultCodeEnum.DATA_NOT_EXIST); + + // 更新排序 + router = new Router(); + router.setId(dto.getId()); + router.setRouterRank(dto.getRouterRank()); + updateById(router); + } +} diff --git a/service/src/main/java/cn/bunny/services/service/system/impl/UserDeptServiceImpl.java b/service/src/main/java/cn/bunny/services/service/system/impl/UserDeptServiceImpl.java new file mode 100644 index 0000000..8a686b2 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/system/impl/UserDeptServiceImpl.java @@ -0,0 +1,20 @@ +package cn.bunny.services.service.system.impl; + +import cn.bunny.dao.entity.system.UserDept; +import cn.bunny.services.mapper.system.UserDeptMapper; +import cn.bunny.services.service.system.UserDeptService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 部门用户关系表 服务实现类 + *

+ * + * @author Bunny + * @since 2024-10-04 + */ +@Service +public class UserDeptServiceImpl extends ServiceImpl implements UserDeptService { + +} diff --git a/service/src/main/java/cn/bunny/services/service/system/impl/UserLoginLogServiceImpl.java b/service/src/main/java/cn/bunny/services/service/system/impl/UserLoginLogServiceImpl.java new file mode 100644 index 0000000..0cc2bde --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/system/impl/UserLoginLogServiceImpl.java @@ -0,0 +1,89 @@ +package cn.bunny.services.service.system.impl; + +import cn.bunny.common.service.context.BaseContext; +import cn.bunny.dao.dto.log.UserLoginLogDto; +import cn.bunny.dao.entity.log.UserLoginLog; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.vo.log.UserLoginLogLocalVo; +import cn.bunny.dao.vo.log.UserLoginLogVo; +import cn.bunny.services.factory.UserLoginLogFactory; +import cn.bunny.services.mapper.system.UserLoginLogMapper; +import cn.bunny.services.service.system.UserLoginLogService; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +/** + *

+ * 用户登录日志 服务实现类 + *

+ * + * @author Bunny + * @since 2024-10-19 01:01:01 + */ +@Service +@Transactional +public class UserLoginLogServiceImpl extends ServiceImpl implements UserLoginLogService { + + @Autowired + private UserLoginLogFactory factory; + + /** + * * 用户登录日志 服务实现类 + * + * @param pageParams 用户登录日志分页查询page对象 + * @param dto 用户登录日志分页查询对象 + * @return 查询分页用户登录日志返回对象 + */ + @Override + public PageResult getUserLoginLogList(Page pageParams, UserLoginLogDto dto) { + IPage page = baseMapper.selectListByPage(pageParams, dto); + + return factory.getUserLoginLogVoPageResult(page); + } + + /** + * 删除|批量删除用户登录日志 + * + * @param ids 删除id列表 + */ + @Override + public void deleteUserLoginLog(List ids) { + // // 逻辑删除 + // removeBatchByIds(ids); + + // 物理删除 + baseMapper.deleteBatchIdsWithPhysics(ids); + } + + /** + * * 获取本地用户登录日志 + * + * @param pageParams 分页查询内容 + * @return 用户登录日志返回列表 + */ + @Override + public PageResult getUserLoginLogListByLocalUser(Page pageParams) { + Long userId = BaseContext.getUserId(); + IPage page = baseMapper.selectListByPageWithLocalUser(pageParams, userId); + + List voList = page.getRecords().stream().map(userLoginLog -> { + UserLoginLogLocalVo userLoginLogVo = new UserLoginLogLocalVo(); + BeanUtils.copyProperties(userLoginLog, userLoginLogVo); + return userLoginLogVo; + }).toList(); + + return PageResult.builder() + .list(voList) + .pageNo(page.getCurrent()) + .pageSize(page.getSize()) + .total(page.getTotal()) + .build(); + } +} diff --git a/service/src/main/java/cn/bunny/services/service/system/impl/UserRoleServiceImpl.java b/service/src/main/java/cn/bunny/services/service/system/impl/UserRoleServiceImpl.java new file mode 100644 index 0000000..a958f9d --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/system/impl/UserRoleServiceImpl.java @@ -0,0 +1,100 @@ +package cn.bunny.services.service.system.impl; + +import cn.bunny.common.service.context.BaseContext; +import cn.bunny.common.service.exception.BunnyException; +import cn.bunny.dao.dto.system.user.AssignRolesToUsersDto; +import cn.bunny.dao.entity.system.AdminUser; +import cn.bunny.dao.entity.system.UserRole; +import cn.bunny.dao.pojo.constant.RedisUserConstant; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.system.user.LoginVo; +import cn.bunny.services.factory.UserFactory; +import cn.bunny.services.mapper.system.UserMapper; +import cn.bunny.services.mapper.system.UserRoleMapper; +import cn.bunny.services.service.system.UserRoleService; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.concurrent.TimeUnit; + +/** + *

+ * 服务实现类 + *

+ * + * @author Bunny + * @since 2024-09-26 + */ +@Service +@Transactional +public class UserRoleServiceImpl extends ServiceImpl implements UserRoleService { + + @Autowired + private UserRoleMapper userRoleMapper; + + @Autowired + private UserFactory userFactory; + + @Autowired + private UserMapper userMapper; + + @Autowired + private RedisTemplate redisTemplate; + + /** + * * 根据用户id获取角色列表 + * + * @param userId 用户id + * @return 角色列表 + */ + @Override + public List getRoleListByUserId(Long userId) { + if (userId == null) throw new BunnyException(ResultCodeEnum.REQUEST_IS_EMPTY); + + List userRoles = userRoleMapper.selectList(Wrappers.lambdaQuery().eq(UserRole::getUserId, userId)); + return userRoles.stream().map(userRole -> userRole.getRoleId().toString()).toList(); + } + + /** + * * 为用户分配角色 + * + * @param dto 用户分配角色 + */ + @Override + public void assignRolesToUsers(AssignRolesToUsersDto dto) { + Long userId = dto.getUserId(); + List roleIds = dto.getRoleIds(); + + // 查询当前用户 + AdminUser adminUser = userMapper.selectOne(Wrappers.lambdaQuery().eq(AdminUser::getId, userId)); + if (adminUser == null) { + throw new BunnyException(ResultCodeEnum.USER_IS_EMPTY); + } + + // 删除这个用户下所有已经分配好的角色内容 + baseMapper.deleteBatchIdsByUserIdsWithPhysics(List.of(userId)); + + // 保存分配好的角色信息 + List roleList = roleIds.stream().map(roleId -> { + UserRole userRole = new UserRole(); + userRole.setUserId(userId); + userRole.setRoleId(roleId); + return userRole; + }).toList(); + saveBatch(roleList); + + // 获取记住我时间 + LoginVo loginVo = BaseContext.getLoginVo(); + Long readMeDay = loginVo != null ? loginVo.getReadMeDay() : RedisUserConstant.REDIS_EXPIRATION_TIME; + + // 重新设置Redis中的用户存储信息vo对象 + String username = adminUser.getUsername(); + loginVo = userFactory.buildLoginUserVo(adminUser, readMeDay); + redisTemplate.opsForValue().set(RedisUserConstant.getAdminLoginInfoPrefix(username), loginVo, readMeDay, TimeUnit.DAYS); + } +} diff --git a/service/src/main/java/cn/bunny/services/service/system/impl/UserServiceImpl.java b/service/src/main/java/cn/bunny/services/service/system/impl/UserServiceImpl.java new file mode 100644 index 0000000..74b958b --- /dev/null +++ b/service/src/main/java/cn/bunny/services/service/system/impl/UserServiceImpl.java @@ -0,0 +1,522 @@ +package cn.bunny.services.service.system.impl; + +import cn.bunny.common.service.context.BaseContext; +import cn.bunny.common.service.exception.BunnyException; +import cn.bunny.common.service.utils.JwtHelper; +import cn.bunny.common.service.utils.ip.IpUtil; +import cn.bunny.dao.dto.system.files.FileUploadDto; +import cn.bunny.dao.dto.system.user.*; +import cn.bunny.dao.entity.log.UserLoginLog; +import cn.bunny.dao.entity.system.AdminUser; +import cn.bunny.dao.entity.system.EmailTemplate; +import cn.bunny.dao.entity.system.Role; +import cn.bunny.dao.entity.system.UserDept; +import cn.bunny.dao.pojo.constant.MinioConstant; +import cn.bunny.dao.pojo.constant.RedisUserConstant; +import cn.bunny.dao.pojo.enums.EmailTemplateEnums; +import cn.bunny.dao.pojo.result.PageResult; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.view.ViewUserDept; +import cn.bunny.dao.vo.system.files.FileInfoVo; +import cn.bunny.dao.vo.system.user.*; +import cn.bunny.services.factory.EmailFactory; +import cn.bunny.services.factory.UserFactory; +import cn.bunny.services.mapper.email.EmailTemplateMapper; +import cn.bunny.services.mapper.system.*; +import cn.bunny.services.service.system.FilesService; +import cn.bunny.services.service.system.UserService; +import cn.hutool.captcha.CaptchaUtil; +import cn.hutool.captcha.CircleCaptcha; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import jakarta.validation.Valid; +import lombok.SneakyThrows; +import org.jetbrains.annotations.NotNull; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.DigestUtils; +import org.springframework.util.StringUtils; +import org.springframework.web.multipart.MultipartFile; + +import java.util.HashMap; +import java.util.List; +import java.util.concurrent.TimeUnit; + + +/** + * 用户信息 服务实现类 + * + * @author Bunny + * @since 2024-09-26 + */ +@Service +@Transactional +public class UserServiceImpl extends ServiceImpl implements UserService { + + @Autowired + private UserFactory userFactory; + + @Autowired + private EmailFactory emailFactory; + + @Autowired + private RedisTemplate redisTemplate; + + @Autowired + private FilesService filesService; + + @Autowired + private UserDeptMapper userDeptMapper; + + @Autowired + private UserRoleMapper userRoleMapper; + + @Autowired + private UserLoginLogMapper userLoginLogMapper; + + @Autowired + private EmailTemplateMapper emailTemplateMapper; + + @Autowired + private RoleMapper roleMapper; + + /** + * 登录发送邮件验证码 + * + * @param email 邮箱 + */ + @Override + public void sendLoginEmail(@NotNull String email) { + // 查询验证码邮件模板 + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(EmailTemplate::getIsDefault, true); + lambdaQueryWrapper.eq(EmailTemplate::getType, EmailTemplateEnums.VERIFICATION_CODE.getType()); + EmailTemplate emailTemplate = emailTemplateMapper.selectOne(lambdaQueryWrapper); + + // 生成验证码 + CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(150, 48, 4, 2); + String emailCode = captcha.getCode(); + + // 需要替换模板内容 + HashMap hashMap = new HashMap<>(); + hashMap.put("#title#", "BunnyAdmin"); + hashMap.put("#verifyCode#", emailCode); + hashMap.put("#expires#", 15); + hashMap.put("#sendEmailUser#", emailTemplate.getEmailUser()); + hashMap.put("#companyName#", "BunnyAdmin"); + + // 发送邮件 + emailFactory.sendEmailTemplate(email, emailTemplate, hashMap); + + // 在Redis中存储验证码 + redisTemplate.opsForValue().set(RedisUserConstant.getAdminUserEmailCodePrefix(email), emailCode, RedisUserConstant.REDIS_EXPIRATION_TIME, TimeUnit.MINUTES); + } + + /** + * 刷新用户token + * + * @param dto 请求token + * @return 刷新token返回内容 + */ + @NotNull + @Override + public RefreshTokenVo refreshToken(@NotNull RefreshTokenDto dto) { + Long userId = JwtHelper.getUserId(dto.getRefreshToken()); + AdminUser adminUser = getOne(Wrappers.lambdaQuery().eq(AdminUser::getId, userId)); + + if (adminUser == null) throw new BunnyException(ResultCodeEnum.FAIL_REQUEST_NOT_AUTH); + if (adminUser.getStatus()) throw new BunnyException(ResultCodeEnum.FAIL_NO_ACCESS_DENIED_USER_LOCKED); + + LoginVo buildUserVo = userFactory.buildLoginUserVo(adminUser, dto.getReadMeDay()); + RefreshTokenVo refreshTokenVo = new RefreshTokenVo(); + BeanUtils.copyProperties(buildUserVo, refreshTokenVo); + + return refreshTokenVo; + } + + /** + * 退出登录 + */ + @Override + public void logout() { + // 获取上下文对象中的用户ID和用户token + LoginVo loginVo = BaseContext.getLoginVo(); + String token = loginVo.getToken(); + Long userId = BaseContext.getUserId(); + + // 获取IP地址 + String ipAddr = IpUtil.getCurrentUserIpAddress().getIpAddr(); + String ipRegion = IpUtil.getCurrentUserIpAddress().getIpRegion(); + + // 查询用户信息 + AdminUser adminUser = getOne(Wrappers.lambdaQuery().eq(AdminUser::getId, userId)); + UserLoginLog userLoginLog = userFactory.setUserLoginLog(adminUser, token, ipAddr, ipRegion, "logout"); + userLoginLogMapper.insert(userLoginLog); + + // 删除Redis中用户信息 + redisTemplate.delete(RedisUserConstant.getAdminLoginInfoPrefix(adminUser.getUsername())); + } + + /** + * * 获取用户信息 + * + * @param id 用户id + * @return 用户信息 + */ + @Override + public UserVo getUserinfoById(Long id) { + // 判断请求Id是否为空 + if (id == null) throw new BunnyException(ResultCodeEnum.REQUEST_IS_EMPTY); + AdminUser user = getById(id); + + // 用户是否存在 + if (user == null) throw new BunnyException(ResultCodeEnum.DATA_NOT_EXIST); + + // 用户头像 + String avatar = user.getAvatar(); + UserVo userVo = new UserVo(); + BeanUtils.copyProperties(user, userVo); + + userVo.setAvatar(userFactory.checkGetUserAvatar(avatar)); + return userVo; + } + + /** + * * 管理员修改管理员用户密码 + * + * @param dto 管理员用户修改密码 + */ + @Override + public void updateUserPasswordByAdmin(AdminUserUpdateWithPasswordDto dto) { + Long userId = dto.getUserId(); + String password = dto.getPassword(); + + // 对密码加密 + String md5Password = DigestUtils.md5DigestAsHex(password.getBytes()); + AdminUser adminUser = getOne(Wrappers.lambdaQuery().eq(AdminUser::getId, userId)); + + // 判断是否存在这个用户 + if (adminUser == null) throw new BunnyException(ResultCodeEnum.USER_IS_EMPTY); + + // 判断新密码是否与旧密码相同 + if (adminUser.getPassword().equals(md5Password)) + throw new BunnyException(ResultCodeEnum.UPDATE_NEW_PASSWORD_SAME_AS_OLD_PASSWORD); + + // 更新用户密码 + adminUser = new AdminUser(); + adminUser.setPassword(md5Password); + adminUser.setId(userId); + updateById(adminUser); + + // 删除Redis中登录用户信息 + redisTemplate.delete(RedisUserConstant.getAdminLoginInfoPrefix(adminUser.getUsername())); + } + + /** + * * 管理员上传用户头像 + * + * @param dto 管理员用户修改头像 + */ + @SneakyThrows + @Override + public void uploadAvatarByAdmin(UserUpdateWithAvatarDto dto) { + MultipartFile avatar = dto.getAvatar(); + Long userId = dto.getUserId(); + + // 判断是否存在这个用户 + AdminUser user = getOne(Wrappers.lambdaQuery().eq(AdminUser::getId, userId)); + if (user == null) throw new BunnyException(ResultCodeEnum.USER_IS_EMPTY); + + // 上传头像 + FileUploadDto uploadDto = FileUploadDto.builder().file(avatar).type(MinioConstant.avatar).build(); + FileInfoVo fileInfoVo = filesService.upload(uploadDto); + + // 更新用户 + AdminUser adminUser = new AdminUser(); + adminUser.setId(userId); + adminUser.setAvatar(fileInfoVo.getFilepath()); + updateById(adminUser); + + // 重新生成用户信息到Redis中 + user.setAvatar(adminUser.getAvatar()); + userFactory.buildUserVo(user, RedisUserConstant.REDIS_EXPIRATION_TIME); + } + + /** + * * 强制退出 + * + * @param id 用户id + */ + @Override + public void forcedOffline(Long id) { + if (id == null) throw new BunnyException(ResultCodeEnum.REQUEST_IS_EMPTY); + + // 根据id查询用户登录前缀 + AdminUser adminUser = getOne(Wrappers.lambdaQuery().eq(AdminUser::getId, id)); + String adminLoginInfoPrefix = RedisUserConstant.getAdminLoginInfoPrefix(adminUser.getUsername()); + + // 将用户登录保存在用户登录日志表中 + UserLoginLog userLoginLog = new UserLoginLog(); + userLoginLog.setUserId(adminUser.getId()); + userLoginLog.setIpAddress(adminUser.getIpAddress()); + userLoginLog.setIpRegion(adminUser.getIpRegion()); + userLoginLog.setToken(null); + userLoginLog.setType("forcedOffline"); + userLoginLogMapper.insert(userLoginLog); + + // 删除Redis中用户信息 + redisTemplate.delete(adminLoginInfoPrefix); + } + + /** + * * 查询用户 + * + * @param keyword 查询用户信息关键字 + * @return 用户信息列表 + */ + @Override + public List queryUser(String keyword) { + if (!StringUtils.hasText(keyword)) { + return list(Page.of(1, 20), Wrappers.lambdaQuery().eq(AdminUser::getStatus, false)).stream().map(adminUser -> { + SearchUserinfoVo adminUserVo = new SearchUserinfoVo(); + BeanUtils.copyProperties(adminUser, adminUserVo); + return adminUserVo; + }).toList(); + } + + List list = baseMapper.queryUser(keyword); + return list.stream().map(adminUser -> { + SearchUserinfoVo adminUserVo = new SearchUserinfoVo(); + BeanUtils.copyProperties(adminUser, adminUserVo); + return adminUserVo; + }).toList(); + } + + /** + * * 修改用户状态 + * + * @param dto 管理员用户修改状态 + */ + @Override + public void updateUserStatusByAdmin(AdminUserUpdateUserStatusDto dto) { + Long userId = dto.getUserId(); + + // 更新用户Id + AdminUser adminUser = new AdminUser(); + adminUser.setId(userId); + adminUser.setStatus(dto.getStatus()); + updateById(adminUser); + + // 如果是锁定用户删除Redis中内容 + if (dto.getStatus()) { + adminUser = getOne(Wrappers.lambdaQuery().eq(AdminUser::getId, userId)); + redisTemplate.delete(RedisUserConstant.getAdminLoginInfoPrefix(adminUser.getUsername())); + } + } + + /** + * * 获取本地登录用户信息 + * + * @return 用户信息 + */ + @Override + public LoginVo getUserinfo() { + return BaseContext.getLoginVo(); + } + + /** + * * 更新本地用户信息 + * + * @param dto 用户信息 + */ + @Override + public void updateAdminUserByLocalUser(AdminUserUpdateByLocalUserDto dto) { + Long userId = BaseContext.getUserId(); + + // 判断是否存在这个用户 + AdminUser user = getOne(Wrappers.lambdaQuery().eq(AdminUser::getId, userId)); + if (user == null) throw new BunnyException(ResultCodeEnum.USER_IS_EMPTY); + + // 检查用户头像 + dto.setAvatar(userFactory.checkPostUserAvatar(dto.getAvatar())); + + // 更新用户 + AdminUser adminUser = new AdminUser(); + adminUser.setId(userId); + BeanUtils.copyProperties(dto, adminUser); + updateById(adminUser); + + // 重新生成用户信息到Redis中 + BeanUtils.copyProperties(dto, user); + userFactory.buildUserVo(user, RedisUserConstant.REDIS_EXPIRATION_TIME); + } + + /** + * * 更新本地用户密码 + * + * @param password 更新本地用户密码 + */ + @Override + public void updateUserPasswordByLocalUser(@Valid String password) { + // 根据当前用户查询用户信息 + Long userId = BaseContext.getUserId(); + AdminUser adminUser = getOne(Wrappers.lambdaQuery().eq(AdminUser::getId, userId)); + + // 判断用户是否存在 + if (adminUser == null) throw new BunnyException(ResultCodeEnum.USER_IS_EMPTY); + + // 数据库中的密码 + String dbPassword = adminUser.getPassword(); + password = DigestUtils.md5DigestAsHex(password.getBytes()); + + // 判断数据库中密码是否和更新用户密码相同 + if (dbPassword.equals(password)) throw new BunnyException(ResultCodeEnum.NEW_PASSWORD_SAME_OLD_PASSWORD); + + // 更新用户密码 + adminUser = new AdminUser(); + adminUser.setId(userId); + adminUser.setPassword(password); + updateById(adminUser); + + // 删除Redis中登录用户信息 + redisTemplate.delete(RedisUserConstant.getAdminLoginInfoPrefix(adminUser.getUsername())); + } + + /** + * * 用户信息 服务实现类 + * + * @param pageParams 用户信息分页查询page对象 + * @param dto 用户信息分页查询对象 + * @return 查询分页用户信息返回对象 + */ + @Override + public PageResult getAdminUserList(Page pageParams, AdminUserDto dto) { + IPage page = baseMapper.selectListByPage(pageParams, dto); + + List voList = page.getRecords().stream() + .map(adminUser -> { + // 如果存在用户头像,则设置用户头像 + String avatar = userFactory.checkGetUserAvatar(adminUser.getAvatar()); + + AdminUserVo adminUserVo = new AdminUserVo(); + BeanUtils.copyProperties(adminUser, adminUserVo); + adminUserVo.setAvatar(avatar); + return adminUserVo; + }) + .filter(adminUserVo -> !adminUserVo.getId().equals(1L)) + .toList(); + + return PageResult.builder() + .list(voList) + .pageNo(page.getCurrent()) + .pageSize(page.getSize()) + .total(page.getTotal()) + .build(); + } + + /** + * * 添加用户信息 + * 需要确认用户名-username是唯一的 + * 需要确认邮箱-email是唯一的 + * + * @param dto 用户信息添加 + */ + @Override + public void addAdminUser(@Valid AdminUserAddDto dto) { + // 对密码加密 + String md5Password = DigestUtils.md5DigestAsHex(dto.getPassword().getBytes()); + + // 保存数据 + AdminUser adminUser = new AdminUser(); + BeanUtils.copyProperties(dto, adminUser); + adminUser.setPassword(md5Password); + save(adminUser); + + // 插入用户部门关系表 + Long userId = adminUser.getId(); + Long deptId = dto.getDeptId(); + UserDept userDept = new UserDept(); + userDept.setDeptId(deptId); + userDept.setUserId(userId); + + // 插入分配后的用户内容 + userDeptMapper.insert(userDept); + } + + /** + * 更新用户信息 + * 如果更新了用户名需要用户重新登录,因为Redis中的key已经被删除 + * + * @param dto 用户信息更新 + */ + @Override + public void updateAdminUser(AdminUserUpdateDto dto) { + // 部门Id + Long deptId = dto.getDeptId(); + Long userId = dto.getId(); + + // 判断更新内容是否存在 + AdminUser adminUser = getOne(Wrappers.lambdaQuery().eq(AdminUser::getId, userId)); + if (adminUser == null) throw new BunnyException(ResultCodeEnum.DATA_NOT_EXIST); + + // 如果更新了用户名,删除之前的用户数据 + if (!dto.getUsername().equals(adminUser.getUsername())) { + String adminLoginInfoPrefix = RedisUserConstant.getAdminLoginInfoPrefix(adminUser.getUsername()); + redisTemplate.delete(adminLoginInfoPrefix); + } + + // 更新用户 + adminUser = new AdminUser(); + BeanUtils.copyProperties(dto, adminUser); + updateById(adminUser); + + // 更新用户部门 + UserDept userDept = new UserDept(); + userDept.setDeptId(deptId); + userDept.setUserId(userId); + + // 删除这个用户部门关系下所有 + userDeptMapper.deleteBatchIdsByUserIdWithPhysics(List.of(userId)); + + // 插入分配后的用户内容 + userDeptMapper.insert(userDept); + + // 重新生成用户信息到Redis中 + BeanUtils.copyProperties(dto, adminUser); + userFactory.buildUserVo(adminUser, RedisUserConstant.REDIS_EXPIRATION_TIME); + } + + /** + * 删除|批量删除用户信息 + * + * @param ids 删除id列表 + */ + @Override + public void deleteAdminUser(List ids) { + // 判断数据请求是否为空 + if (ids.isEmpty()) throw new BunnyException(ResultCodeEnum.REQUEST_IS_EMPTY); + + // 根据用户Id列表查询用户角色 + List list = roleMapper.selectListByUserIds(ids); + List roleList = list.stream().filter(role -> role.getRoleCode().equals("admin") || ids.contains(1L)).toList(); + if (!roleList.isEmpty()) throw new BunnyException(ResultCodeEnum.ADMIN_ROLE_CAN_NOT_DELETED); + + // 逻辑删除 + removeBatchByIds(ids); + + // 物理删除用户 + // baseMapper.deleteBatchIdsWithPhysics(ids); + + // 删除部门相关 + userDeptMapper.deleteBatchIdsByUserIdWithPhysics(ids); + + // 删除用户角色相关 + userRoleMapper.deleteBatchIdsByUserIdsWithPhysics(ids); + } +} diff --git a/service/src/main/resources/application-dev.yml b/service/src/main/resources/application-dev.yml new file mode 100644 index 0000000..1c7049a --- /dev/null +++ b/service/src/main/resources/application-dev.yml @@ -0,0 +1,60 @@ +server: + port: 7070 + +logging: + level: + cn.bunny.service.mapper: info + cn.bunny.service.controller: info + cn.bunny.service.service: info + root: info + pattern: + dateformat: HH:mm:ss:SSS + file: + path: "logs/${spring.application.name}" + +#mybatis-plus: +# configuration: +# map-underscore-to-camel-case: true +# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 查看日志 + +bunny: + master: + host: 192.168.3.98 + port: 3304 + database: family_financial + username: root + password: "02120212" + + redis: + host: 192.168.3.98 + port: 6379 + database: 6 + password: "123456" + + minio: + endpointUrl: "http://192.168.3.98:9000" + accessKey: bunny + secretKey: "02120212" + bucket-name: financial + #bunny: + # master: + # host: rm-bp12z6hlv46vi6g8mro.mysql.rds.aliyuncs.com + # port: 3306 + # database: family_financial + # username: family_financial_prod + # password: 0212family_financial + # + # redis: + # host: 47.120.65.66 + # port: 6379 + # database: 6 + # password: "02120212" + # + # minio: + # endpointUrl: "http://116.196.101.14:9000" + # accessKey: bunny + # secretKey: "02120212" + # bucket-name: financial + + backPath: "D:\\MyData\\backup" + bashPath: "D:\\MyData" diff --git a/service/src/main/resources/application-prod.yml b/service/src/main/resources/application-prod.yml new file mode 100644 index 0000000..d61b822 --- /dev/null +++ b/service/src/main/resources/application-prod.yml @@ -0,0 +1,46 @@ +server: + port: 8000 + +#mybatis-plus: +# configuration: +# map-underscore-to-camel-case: true +# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 查看日志 + +logging: + level: + cn.bunny.service.mapper: warn + cn.bunny.service.controller: warn + cn.bunny.service.service: warn + root: warn + pattern: + dateformat: HH:mm:ss:SSS + file: + path: "logs/${spring.application.name}" + +# 线上禁用文档 +knife4j: + enable: true + production: true + +bunny: + master: + host: rm-bp12z6hlv46vi6g8mro.mysql.rds.aliyuncs.com + port: 3306 + database: family_financial + username: family_financial_prod + password: 0212family_financial + + redis: + host: 47.120.65.66 + port: 6379 + database: 6 + password: "02120212" + + minio: + endpointUrl: "http://116.196.101.14:9000" + accessKey: bunny + secretKey: "02120212" + bucket-name: financial + + backPath: "/www/root/backup" + bashPath: "/www/root/server" \ No newline at end of file diff --git a/service/src/main/resources/application-test.yml b/service/src/main/resources/application-test.yml new file mode 100644 index 0000000..adc954b --- /dev/null +++ b/service/src/main/resources/application-test.yml @@ -0,0 +1,65 @@ +server: + port: 7070 + +#mybatis-plus: +# configuration: +# map-underscore-to-camel-case: true +# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 查看日志 + +logging: + level: + cn.bunny.service.mapper: warn + cn.bunny.service.controller: warn + cn.bunny.service.service: warn + root: warn + pattern: + dateformat: HH:mm:ss:SSS + file: + path: "logs/${spring.application.name}" + +# 线上禁用文档 +knife4j: + enable: true + production: true + +# rabbitmq: +# host: ${bunny.rabbitmq.host} +# port: ${bunny.rabbitmq.port} +# username: ${bunny.rabbitmq.username} +# password: ${bunny.rabbitmq.password} +# virtual-host: ${bunny.rabbitmq.virtual-host} +# publisher-confirm-type: correlated # 交换机确认 +# publisher-returns: true # 队列确认 +# listener: +# simple: +# acknowledge-mode: manual # 手动处理消息 +# connection-timeout: 1s # 设置MQ连接超时时间 +# template: +# retry: +# enabled: true # 失败重试 +# initial-interval: 1000ms # 失败后初始时间 +# multiplier: 1 # 失败后下次等待时长倍数 initial-interval * multiplier +# max-attempts: 3 # 最大重试次数 + +bunny: + master: + host: rm-bp12z6hlv46vi6g8mro.mysql.rds.aliyuncs.com + port: 3306 + database: family_financial + username: family_financial_prod + password: 0212family_financial + + redis: + host: 47.120.65.66 + port: 6379 + database: 6 + password: "02120212" + + minio: + endpointUrl: "http://116.196.101.14:9000" + accessKey: bunny + secretKey: "02120212" + bucket-name: financial + + backPath: "D:\\MyData\\backup" + bashPath: "D:\\MyData" \ No newline at end of file diff --git a/service/src/main/resources/application.yml b/service/src/main/resources/application.yml new file mode 100644 index 0000000..9922645 --- /dev/null +++ b/service/src/main/resources/application.yml @@ -0,0 +1,101 @@ +spring: + profiles: + active: @profiles.active@ + application: + name: bunny-service + servlet: + multipart: + max-file-size: 6MB + + datasource: + type: com.zaxxer.hikari.HikariDataSource + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://${bunny.master.host}:${bunny.master.port}/${bunny.master.database}?serverTimezone=GMT%2B8&useSSL=false&characterEncoding=utf-8&allowPublicKeyRetrieval=true + username: ${bunny.master.username} + password: ${bunny.master.password} + # dynamic: + # primary: master #设置默认的数据源或者数据源组,默认值即为master + # strict: false #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源 + # grace-destroy: false #是否优雅关闭数据源,默认为false,设置为true时,关闭数据源时如果数据源中还存在活跃连接,至多等待10s后强制关闭 + # datasource: + # master: + # type: com.zaxxer.hikari.HikariDataSource + # driver-class-name: com.mysql.cj.jdbc.Driver + # url: jdbc:mysql://${bunny.master.host}:${bunny.master.port}/${bunny.master.database}?serverTimezone=GMT%2B8&useSSL=false&characterEncoding=utf-8&allowPublicKeyRetrieval=true + # username: ${bunny.master.username} + # password: ${bunny.master.password} + # aop: + # enabled: true + + data: + redis: + host: ${bunny.redis.host} + port: ${bunny.redis.port} + database: ${bunny.redis.database} + password: ${bunny.redis.password} + lettuce: + pool: + max-active: 20 #最大连接数 + max-wait: -1 #最大阻塞等待时间(负数表示没限制) + max-idle: 5 #最大空闲 + min-idle: 0 #最小空闲 + + quartz: + job-store-type: jdbc + jdbc: + initialize-schema: never + auto-startup: true + wait-for-jobs-to-complete-on-shutdown: true + overwrite-existing-jobs: false + scheduler-name: quartzScheduler + properties: + org: + quartz: + scheduler: + # 默认 + instanceName: quartzScheduler + # 如果使用集群,instanceId必须唯一,设置成AUTO + instanceId: AUTO + jobStore: + # 存储方式使用JobStoreTX 也就是数据库 LocalDataSourceJobStore + class: org.springframework.scheduling.quartz.LocalDataSourceJobStore + driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate + # 表名前缀 + tablePrefix: QRTZ_ + useProperties: false + misfireThreshold: 5000 + threadPool: + class: org.quartz.simpl.SimpleThreadPool + threadCount: 20 + threadPriority: 5 + threadsInheritContextClassLoaderOfInitializingThread: true + + jackson: + date-format: yyyy-MM-dd HH:mm:ss + time-zone: GMT+8 + +mybatis-plus: + mapper-locations: classpath:mapper/**/*.xml + global-config: + db-config: + logic-delete-field: isDeleted + configuration: + map-underscore-to-camel-case: true + +management: + endpoints: + web: + exposure: + include: "*" + base-path: /admin/actuator + info: + env: + enabled: true + java: + enabled: true + os: + enabled: true + + endpoint: + health: + show-details: always \ No newline at end of file diff --git a/service/src/main/resources/banner.txt b/service/src/main/resources/banner.txt new file mode 100644 index 0000000..d964e56 --- /dev/null +++ b/service/src/main/resources/banner.txt @@ -0,0 +1,6 @@ +__________ ____. +\______ \__ __ ____ ____ ___.__. | |____ ___ _______ + | | _/ | \/ \ / < | | | \__ \\ \/ /\__ \ + | | \ | / | \ | \___ | /\__| |/ __ \\ / / __ \_ + |______ /____/|___| /___| / ____| \________(____ /\_/ (____ / + \/ \/ \/\/ \/ \/ \ No newline at end of file diff --git a/service/src/main/resources/ipdb/ip2region.xdb b/service/src/main/resources/ipdb/ip2region.xdb new file mode 100644 index 0000000..7052c05 Binary files /dev/null and b/service/src/main/resources/ipdb/ip2region.xdb differ diff --git a/service/src/main/resources/logback.xml b/service/src/main/resources/logback.xml new file mode 100644 index 0000000..cf2e85e --- /dev/null +++ b/service/src/main/resources/logback.xml @@ -0,0 +1,68 @@ + + + logback + + + + + + + + + + + + INFO + + + %cyan([%thread]) %yellow(%-5level) %green(%logger{100}).%boldRed(%method)-%boldMagenta(%line)- %blue(%msg%n) + ${ENCODING} + + + + + + /www/root/server/logs/${datetime}/financial-server.log + true + + %date{yyyy-MM-dd HH:mm:ss} [%-5level] %thread %file:%line %logger %msg%n + ${ENCODING} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/service/src/main/resources/mapper/configuration/CategoryMapper.xml b/service/src/main/resources/mapper/configuration/CategoryMapper.xml new file mode 100644 index 0000000..32a4b4b --- /dev/null +++ b/service/src/main/resources/mapper/configuration/CategoryMapper.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + id, create_time, update_time, create_user, update_user, is_deleted, user_id, category_name, is_builtin + + + + + + + + delete + from t_category + where id in + + #{id} + + + + diff --git a/service/src/main/resources/mapper/configuration/MenuIconMapper.xml b/service/src/main/resources/mapper/configuration/MenuIconMapper.xml new file mode 100644 index 0000000..6249595 --- /dev/null +++ b/service/src/main/resources/mapper/configuration/MenuIconMapper.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + id, create_time, update_time, create_user, update_user, is_deleted, icon_name, icon_code + + + + + + + + delete + from sys_menu_icon + where id in + + #{id} + + + + diff --git a/service/src/main/resources/mapper/email/EmailTemplateMapper.xml b/service/src/main/resources/mapper/email/EmailTemplateMapper.xml new file mode 100644 index 0000000..bec054c --- /dev/null +++ b/service/src/main/resources/mapper/email/EmailTemplateMapper.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + id, create_time, update_time, create_user, update_user, is_deleted, template_name, email_user, subject, body, type, is_default + + + + + + + + delete + from sys_email_template + where id in + + #{id} + + + + diff --git a/service/src/main/resources/mapper/email/EmailUsersMapper.xml b/service/src/main/resources/mapper/email/EmailUsersMapper.xml new file mode 100644 index 0000000..7aa2ba3 --- /dev/null +++ b/service/src/main/resources/mapper/email/EmailUsersMapper.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + id, create_time, update_time, create_user, update_user, is_deleted, email, password, host, port, smtp_agreement, is_default + + + + + + + + delete + from sys_email_users + where id in + + #{id} + + + + diff --git a/service/src/main/resources/mapper/financial/BillMapper.xml b/service/src/main/resources/mapper/financial/BillMapper.xml new file mode 100644 index 0000000..7342d66 --- /dev/null +++ b/service/src/main/resources/mapper/financial/BillMapper.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + id, create_time, update_time, create_user, update_user, is_deleted, type, amount, description, transaction_date, category_id + + + + + + + + delete + from t_bill + where id in + + #{id} + + + + diff --git a/service/src/main/resources/mapper/financial/CategoryUserMapper.xml b/service/src/main/resources/mapper/financial/CategoryUserMapper.xml new file mode 100644 index 0000000..de5aae3 --- /dev/null +++ b/service/src/main/resources/mapper/financial/CategoryUserMapper.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + id, create_time, update_time, create_user, update_user, is_deleted, user_id, category_name, is_builtin + + + + + + + + delete + from t_category + where id in + + #{id} + + + + diff --git a/service/src/main/resources/mapper/i18n/I18nMapper.xml b/service/src/main/resources/mapper/i18n/I18nMapper.xml new file mode 100644 index 0000000..ac0a27c --- /dev/null +++ b/service/src/main/resources/mapper/i18n/I18nMapper.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + id, key_name, translation, type_name, create_user, update_user, update_time, create_time, is_deleted + + + + + delete + from sys_i18n + where id in + + #{id} + + + + + + + diff --git a/service/src/main/resources/mapper/i18n/I18nTypeMapper.xml b/service/src/main/resources/mapper/i18n/I18nTypeMapper.xml new file mode 100644 index 0000000..d8b882d --- /dev/null +++ b/service/src/main/resources/mapper/i18n/I18nTypeMapper.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + id, type_name, summary, create_user, update_user, update_time, create_time, is_deleted,is_default + + + + + delete + from sys_i18n_type + where id in + + #{id} + + + + + + + diff --git a/service/src/main/resources/mapper/message/MessageMapper.xml b/service/src/main/resources/mapper/message/MessageMapper.xml new file mode 100644 index 0000000..395dea4 --- /dev/null +++ b/service/src/main/resources/mapper/message/MessageMapper.xml @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + id, create_time, update_time, create_user, update_user, is_deleted, title, send_user_id, message_type, content, cover, summary, editor_type, level,extra + + + + + + + + + + + delete + from sys_message + where is_deleted=0 and id in + + #{id} + + + + + + + diff --git a/service/src/main/resources/mapper/message/MessageReceivedMapper.xml b/service/src/main/resources/mapper/message/MessageReceivedMapper.xml new file mode 100644 index 0000000..426a11b --- /dev/null +++ b/service/src/main/resources/mapper/message/MessageReceivedMapper.xml @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + id, received_user_id, message_id + + + + + + + + delete + from sys_message_received + where id in + + #{id} + + + + + + delete + from sys_message_received + where message_id in + + #{id} + + + + + + + diff --git a/service/src/main/resources/mapper/message/MessageTypeMapper.xml b/service/src/main/resources/mapper/message/MessageTypeMapper.xml new file mode 100644 index 0000000..c8b7aab --- /dev/null +++ b/service/src/main/resources/mapper/message/MessageTypeMapper.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + id, create_time, update_time, create_user, update_user, is_deleted, message_name, message_type, summary, status + + + + + + + + delete + from sys_message_type + where id in + + #{id} + + + + diff --git a/service/src/main/resources/mapper/schedule/ScheduleExecuteLogMapper.xml b/service/src/main/resources/mapper/schedule/ScheduleExecuteLogMapper.xml new file mode 100644 index 0000000..40ba81b --- /dev/null +++ b/service/src/main/resources/mapper/schedule/ScheduleExecuteLogMapper.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + id, create_time, update_time, create_user, update_user, is_deleted, job_name, job_group, job_class_name, cron_expression, trigger_name, execute_result, duration + + + + + + + + delete + from log_quartz_execute + where id in + + #{id} + + + + diff --git a/service/src/main/resources/mapper/schedule/SchedulersGroupMapper.xml b/service/src/main/resources/mapper/schedule/SchedulersGroupMapper.xml new file mode 100644 index 0000000..2aad41f --- /dev/null +++ b/service/src/main/resources/mapper/schedule/SchedulersGroupMapper.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + id, create_time, update_time, create_user, update_user, is_deleted, group_name, description + + + + + + + + delete + from qrtz_schedulers_group + where id in + + #{id} + + + + diff --git a/service/src/main/resources/mapper/schedule/SchedulersMapper.xml b/service/src/main/resources/mapper/schedule/SchedulersMapper.xml new file mode 100644 index 0000000..7358d07 --- /dev/null +++ b/service/src/main/resources/mapper/schedule/SchedulersMapper.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + job_name, job_group, description, job_class_name, cron_expression, trigger_name, trigger_state + + + + + diff --git a/service/src/main/resources/mapper/system/DeptMapper.xml b/service/src/main/resources/mapper/system/DeptMapper.xml new file mode 100644 index 0000000..4f85ac5 --- /dev/null +++ b/service/src/main/resources/mapper/system/DeptMapper.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + id, create_time, update_time, create_user, update_user, is_deleted, parent_id, manager, dept_name, summary + + + + + + + + delete + from sys_dept + where id in + + #{id} + + + + diff --git a/service/src/main/resources/mapper/system/FilesMapper.xml b/service/src/main/resources/mapper/system/FilesMapper.xml new file mode 100644 index 0000000..029a496 --- /dev/null +++ b/service/src/main/resources/mapper/system/FilesMapper.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + id, create_time, update_time, create_user, update_user, is_deleted, filename, filepath, file_size, file_type, download_count + + + + + + + + delete + from sys_files + where id in + + #{id} + + + + diff --git a/service/src/main/resources/mapper/system/PowerMapper.xml b/service/src/main/resources/mapper/system/PowerMapper.xml new file mode 100644 index 0000000..f096654 --- /dev/null +++ b/service/src/main/resources/mapper/system/PowerMapper.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + id, create_time, update_time, create_user, update_user, is_deleted, parent_id, power_code, power_name, request_url + + + + + + + + delete + from sys_power + where id in + + #{id} + + + + + + diff --git a/service/src/main/resources/mapper/system/RoleMapper.xml b/service/src/main/resources/mapper/system/RoleMapper.xml new file mode 100644 index 0000000..1430707 --- /dev/null +++ b/service/src/main/resources/mapper/system/RoleMapper.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + id, create_time, update_time, create_user, update_user, is_deleted, role_code, description + + + + + + + + delete + from sys_role + where id in + + #{id} + + + + + + + + + + diff --git a/service/src/main/resources/mapper/system/RolePowerMapper.xml b/service/src/main/resources/mapper/system/RolePowerMapper.xml new file mode 100644 index 0000000..9cc5076 --- /dev/null +++ b/service/src/main/resources/mapper/system/RolePowerMapper.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + id, role_id, power_id, create_time, update_time, create_user, update_user, is_deleted + + + + + delete + from sys_role_power + where power_id in + + #{id} + + + + + + delete + from sys_role_power + where role_id in + + #{id} + + + + + + + + + + diff --git a/service/src/main/resources/mapper/system/RouterMapper.xml b/service/src/main/resources/mapper/system/RouterMapper.xml new file mode 100644 index 0000000..b17a7e4 --- /dev/null +++ b/service/src/main/resources/mapper/system/RouterMapper.xml @@ -0,0 +1,107 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + id, parent_id, path, component, frame_src, route_name, title, menu_type, icon, router_rank, visible, create_user, update_user, update_time, create_time, is_deleted + + + + + delete + from sys_router + where id in + + #{id} + + + + + + + + + + + + + + + diff --git a/service/src/main/resources/mapper/system/RouterRoleMapper.xml b/service/src/main/resources/mapper/system/RouterRoleMapper.xml new file mode 100644 index 0000000..c2c5f6e --- /dev/null +++ b/service/src/main/resources/mapper/system/RouterRoleMapper.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + id, router_id, role_id, create_user, update_time, update_user, create_time, is_deleted + + + + + delete + from sys_router_role + where router_id in + + #{id} + + + + + + delete + from sys_router_role + where role_id in + + #{id} + + + + + + delete + from sys_router_role + where id in + + #{id} + + + + + + + diff --git a/service/src/main/resources/mapper/system/UserDeptMapper.xml b/service/src/main/resources/mapper/system/UserDeptMapper.xml new file mode 100644 index 0000000..48f4043 --- /dev/null +++ b/service/src/main/resources/mapper/system/UserDeptMapper.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + id, user_id, dept_id, create_time, update_time, create_user, update_user, is_deleted + + + + + delete + from sys_user_dept + where dept_id in + + #{id} + + + + + + delete + from sys_user_dept + where user_id in + + #{id} + + + + diff --git a/service/src/main/resources/mapper/system/UserLoginLogMapper.xml b/service/src/main/resources/mapper/system/UserLoginLogMapper.xml new file mode 100644 index 0000000..2532cfe --- /dev/null +++ b/service/src/main/resources/mapper/system/UserLoginLogMapper.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + id, create_time, update_time, create_user, update_user, is_deleted, user_id, username, token, ip_address, ip_region, user_agent, type, x_requested_with + + + + + + + + + + + delete + from log_user_login + where id in + + #{id} + + + + diff --git a/service/src/main/resources/mapper/system/UserMapper.xml b/service/src/main/resources/mapper/system/UserMapper.xml new file mode 100644 index 0000000..ac10216 --- /dev/null +++ b/service/src/main/resources/mapper/system/UserMapper.xml @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + id, username, nickname, email, phone, password, avatar, sex, summary, ip_address, ip_region, status, create_user, create_time, update_time, update_user, is_deleted + + + + + + + + + + + delete + from sys_user + where id in + + #{id} + + + + diff --git a/service/src/main/resources/mapper/system/UserRoleMapper.xml b/service/src/main/resources/mapper/system/UserRoleMapper.xml new file mode 100644 index 0000000..bc4625b --- /dev/null +++ b/service/src/main/resources/mapper/system/UserRoleMapper.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + id, user_id, role_id, create_time, update_time, create_user, update_user, is_deleted + + + + + delete + from sys_user_role + where user_id in + + #{id} + + + + + + delete + from sys_user_role + where role_id in + + #{id} + + + + diff --git a/service/src/main/resources/static/backup.sh b/service/src/main/resources/static/backup.sh new file mode 100644 index 0000000..4b0bfb9 --- /dev/null +++ b/service/src/main/resources/static/backup.sh @@ -0,0 +1,15 @@ +#!/bin/bash +# 设置备份文件存放目录 +backup_dir="/home/backup/" +# 获取当前时间并格式化为 yyyy_MM_dd_HH_mm_ss_SSS 格式 +timestamp=$(date +"%Y_%m_%d_%H_%M_%S_%3N") +# 设置数据库用户名、密码和数据库名 +db_user="root" +db_pass="02120212" +db_name="auth_admin" +# 设置备份文件名 +backup_file="${backup_dir}backup_${db_name}_${timestamp}.sql" +# 执行备份命令 +docker exec -i slave_3304 bash -c "mysqldump -u ${db_user} -p${db_pass} ${db_name} > ${backup_file}" +# 输出备份文件路径 +echo "Backup completed: ${backup_file}" \ No newline at end of file diff --git a/service/src/main/resources/static/error/500.html b/service/src/main/resources/static/error/500.html new file mode 100644 index 0000000..6071bf4 --- /dev/null +++ b/service/src/main/resources/static/error/500.html @@ -0,0 +1,64 @@ + + + + + 500 - 服务器错误 + + + + +
+

:'(

+

服务器开小差啦!管理员正在修理中...

+

还请阁下静候站点恢复~

+
+ + \ No newline at end of file diff --git a/service/src/main/resources/static/favicon.ico b/service/src/main/resources/static/favicon.ico new file mode 100644 index 0000000..385f8a6 Binary files /dev/null and b/service/src/main/resources/static/favicon.ico differ diff --git a/service/src/main/resources/static/platform-config.json b/service/src/main/resources/static/platform-config.json new file mode 100644 index 0000000..d31a494 --- /dev/null +++ b/service/src/main/resources/static/platform-config.json @@ -0,0 +1,28 @@ +{ + "Version": "5.8.0", + "Title": "BunnyAdmin", + "Copyright": "Copyright © 2020-present", + "FixedHeader": true, + "HiddenSideBar": false, + "MultiTagsCache": false, + "KeepAlive": true, + "Locale": "zh", + "Layout": "vertical", + "Theme": "light", + "DarkMode": false, + "OverallStyle": "light", + "Grey": false, + "Weak": false, + "HideTabs": false, + "HideFooter": false, + "Stretch": false, + "SidebarStatus": true, + "EpThemeColor": "#409EFF", + "ShowLogo": true, + "ShowModel": "smart", + "MenuArrowIconNoTransition": false, + "CachingAsyncRoutes": false, + "TooltipEffect": "light", + "ResponsiveStorageNameSpace": "responsive-", + "MenuSearchHistory": 6 +}