commit de9157143a44ff098c1c097aa3abbe4c26dbb4c6 Author: horizons <1490493387@qq.com> Date: Mon Oct 24 07:50:54 2022 +0800 feat: 全量提交 diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..e0934da4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +# Created by .ignore support plugin (hsz.mobi) +### Example sysUserDetails template template +### Example sysUserDetails template + +# IntelliJ project files +.idea +*.iml +out +gen +target +*.log +logs \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..145dbd66 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,18 @@ +# SpringBoot单体应用部署Dockerfile +FROM openjdk:17-jdk-alpine + +RUN apk --update --no-cache add tini +ENTRYPOINT ["tini"] + +# /tmp 目录就会在运行时自动挂载为匿名卷,任何向 /tmp 中写入的信息都不会记录进容器存储层 +VOLUME /tmp + +ADD target/youlai-boot.jar app.jar + +CMD java \ + -Djava.security.egd=file:/dev/./urandom \ + -jar /app.jar + +EXPOSE 8989 +# 时区修改 +RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \&& echo 'Asia/Shanghai' >/etc/timezone \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 00000000..b7a3e2a9 --- /dev/null +++ b/pom.xml @@ -0,0 +1,172 @@ + + + 4.0.0 + + com.youlai + youlai-boot + 1.0.0 + SpringBoot 单体应用 + + + org.springframework.boot + spring-boot-starter-parent + 2.7.3 + + + + + 17 + 17 + + 1.18.24 + 5.7.21 + + 8.0.19 + 1.2.4 + 3.5.2 + + 3.0.2 + + 2.7.3 + + 1.5.2.Final + + 2.3.0 + + 0.11.5 + + 3.0.5 + + + + + + org.projectlombok + lombok + ${lombok.version} + + + + cn.hutool + hutool-all + ${hutool.version} + + + + com.baomidou + mybatis-plus-boot-starter + ${mybatis-plus.version} + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-security + + + + org.springframework.boot + spring-boot-starter-data-redis + + + + org.apache.commons + commons-pool2 + + + + mysql + mysql-connector-java + ${mysql.version} + + + + com.alibaba + druid-spring-boot-starter + ${druid.version} + + + + + com.github.xiaoymin + knife4j-spring-boot-starter + ${knife4j.version} + + + + org.mapstruct + mapstruct + ${mapstruct.version} + + + + org.mapstruct + mapstruct-processor + ${mapstruct.version} + + + + com.xuxueli + xxl-job-core + ${xxl-job.version} + + + + io.jsonwebtoken + jjwt-api + ${jjwt.version} + + + io.jsonwebtoken + jjwt-impl + ${jjwt.version} + runtime + + + + io.jsonwebtoken + jjwt-jackson + ${jjwt.version} + runtime + + + + com.alibaba + easyexcel + ${easyexcel.version} + + + + org.springframework.boot + spring-boot-starter-validation + + + + + + ${project.artifactId} + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.10.1 + + 17 + 17 + + + + + \ No newline at end of file diff --git a/sql/youlai_boot.sql b/sql/youlai_boot.sql new file mode 100644 index 00000000..2406563c --- /dev/null +++ b/sql/youlai_boot.sql @@ -0,0 +1,245 @@ +/* +* youlai_boot 权限系统数据库(MySQL8.x) +*/ + +-- ---------------------------- +-- 1. 创建数据库 +-- ---------------------------- +CREATE DATABASE IF NOT EXISTS youlai_boot DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_general_ci; + + +-- ---------------------------- +-- 2. 创建表 +-- ---------------------------- +use youlai_boot; + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for sys_dept +-- ---------------------------- +DROP TABLE IF EXISTS `sys_dept`; +CREATE TABLE `sys_dept` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '部门名称', + `parent_id` bigint NULL DEFAULT 0 COMMENT '父节点id', + `tree_path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '父节点id路径', + `sort` int NULL DEFAULT 0 COMMENT '显示顺序', + `status` tinyint NULL DEFAULT 1 COMMENT '状态(1:正常;0:禁用)', + `deleted` tinyint NULL DEFAULT 0 COMMENT '逻辑删除标识(1:已删除;0:未删除)', + `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间', + `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 150 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '部门表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sys_dept +-- ---------------------------- +INSERT INTO `sys_dept` VALUES (1, '有来技术', 0, '0', 1, 1, 0, NULL, NULL); +INSERT INTO `sys_dept` VALUES (2, '研发部门', 1, '0,1', 1, 1, 0, NULL, '2022-04-19 12:46:37'); +INSERT INTO `sys_dept` VALUES (3, '测试部门', 1, '0,1', 1, 1, 0, NULL, '2022-04-19 12:46:37'); + +-- ---------------------------- +-- Table structure for sys_dict_item +-- ---------------------------- +DROP TABLE IF EXISTS `sys_dict_item`; +CREATE TABLE `sys_dict_item` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', + `type_code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '字典类型编码', + `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '字典项名称', + `value` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '字典项值', + `sort` int NULL DEFAULT 0 COMMENT '排序', + `status` tinyint NULL DEFAULT 0 COMMENT '状态(1:正常;0:禁用)', + `defaulted` tinyint NULL DEFAULT 0 COMMENT '是否默认(1:是;0:否)', + `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '备注', + `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间', + `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 65 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '字典数据表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sys_dict_item +-- ---------------------------- +INSERT INTO `sys_dict_item` VALUES (1, 'gender', '男', '1', 1, 1, 0, NULL, '2019-05-05 13:07:52', '2022-06-12 23:20:39'); +INSERT INTO `sys_dict_item` VALUES (2, 'gender', '女', '2', 2, 1, 0, NULL, '2019-04-19 11:33:00', '2019-07-02 14:23:05'); +INSERT INTO `sys_dict_item` VALUES (3, 'gender', '未知', '0', 1, 1, 0, NULL, '2020-10-17 08:09:31', '2020-10-17 08:09:31'); + +-- ---------------------------- +-- Table structure for sys_dict_type +-- ---------------------------- +DROP TABLE IF EXISTS `sys_dict_type`; +CREATE TABLE `sys_dict_type` ( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键 ', + `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '类型名称', + `code` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '类型编码', + `status` tinyint(1) NULL DEFAULT 0 COMMENT '状态(0:正常;1:禁用)', + `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间', + `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `type_code`(`code`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 79 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '字典类型表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sys_dict_type +-- ---------------------------- +INSERT INTO `sys_dict_type` VALUES (1, '性别', 'gender', 1, NULL, '2019-12-06 19:03:32', '2022-06-12 16:21:28'); + +-- ---------------------------- +-- Table structure for sys_menu +-- ---------------------------- +DROP TABLE IF EXISTS `sys_menu`; +CREATE TABLE `sys_menu` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `parent_id` bigint NOT NULL COMMENT '父菜单ID', + `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '菜单名称', + `type` tinyint NULL DEFAULT NULL COMMENT '菜单类型(1:菜单;2:目录;3:外链;4:按钮)', + `path` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '路由路径(浏览器地址栏路径)', + `component` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '组件路径(vue页面完整路径,省略.vue后缀)', + `perm` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '权限标识', + `visible` tinyint(1) NOT NULL DEFAULT 1 COMMENT '显示状态(1-显示;0-隐藏)', + `sort` int NULL DEFAULT 0 COMMENT '排序', + `icon` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '菜单图标', + `redirect_url` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '外链路径', + `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间', + `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 31 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '菜单管理' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sys_menu +-- ---------------------------- +INSERT INTO `sys_menu` VALUES (1, 0, '系统管理', 2, '/system', 'Layout', NULL, 1, 1, 'system', '/system/user', '2021-08-28 09:12:21', '2021-08-28 09:12:21'); +INSERT INTO `sys_menu` VALUES (2, 1, '用户管理', 1, 'user', 'system/user/index', NULL, 1, 1, 'user', NULL, '2021-08-28 09:12:21', '2021-08-28 09:12:21'); +INSERT INTO `sys_menu` VALUES (3, 1, '角色管理', 1, 'role', 'system/role/index', NULL, 1, 2, 'role', NULL, '2021-08-28 09:12:21', '2021-08-28 09:12:21'); +INSERT INTO `sys_menu` VALUES (4, 1, '菜单管理', 1, 'cmenu', 'system/menu/index', NULL, 1, 3, 'menu', NULL, '2021-08-28 09:12:21', '2021-08-28 09:12:21'); +INSERT INTO `sys_menu` VALUES (5, 1, '部门管理', 1, 'dept', 'system/dept/index', NULL, 1, 4, 'tree', NULL, '2021-08-28 09:12:21', '2021-08-28 09:12:21'); +INSERT INTO `sys_menu` VALUES (6, 1, '字典管理', 1, 'dict', 'system/dict/index', NULL, 1, 5, 'dict', NULL, '2021-08-28 09:12:21', '2021-08-28 09:12:21'); +INSERT INTO `sys_menu` VALUES (20, 0, '多级菜单', 2, '/multi-level-menu', 'Layout', NULL, 1, 7, 'nested', '/nested/level1/level2', '2022-02-16 23:11:00', '2022-02-16 23:11:00'); +INSERT INTO `sys_menu` VALUES (21, 20, '菜单一级', 2, 'nested_level1_index', 'nested/level1/index', NULL, 1, 1, '', '/nested/level1/level2', '2022-02-16 23:13:38', '2022-02-16 23:13:38'); +INSERT INTO `sys_menu` VALUES (22, 21, '菜单二级', 2, 'nested_level1_level2_index', 'nested/level1/level2/index', NULL, 1, 1, '', '/nested/level1/level2/level3', '2022-02-16 23:14:23', '2022-02-16 23:14:23'); +INSERT INTO `sys_menu` VALUES (23, 22, '菜单三级-1', 1, 'nested_level1_level2_level3_index1', 'nested/level1/level2/level3/index1', NULL, 1, 1, '', '', '2022-02-16 23:14:51', '2022-02-16 23:14:51'); +INSERT INTO `sys_menu` VALUES (24, 22, '菜单三级-2', 1, 'nested_level1_level2_level3_index2', 'nested/level1/level2/level3/index2', NULL, 1, 2, '', '', '2022-02-16 23:15:08', '2022-02-16 23:15:08'); +INSERT INTO `sys_menu` VALUES (26, 0, '外部链接', 2, '/external-link', 'Layout', NULL, 1, 9, 'link', 'noredirect', '2022-02-17 22:51:20', '2022-02-17 22:51:20'); +INSERT INTO `sys_menu` VALUES (30, 26, 'document', 3, 'https://www.cnblogs.com/haoxianrui/', '', NULL, 1, 1, 'link', '', '2022-02-18 00:01:40', '2022-02-18 00:01:40'); +INSERT INTO `sys_menu` VALUES (31, 2, '用户新增', 4, '', NULL, 'sys:user:add', 1, 1, '', '', '2022-10-23 11:04:08', '2022-10-23 11:04:11'); +INSERT INTO `sys_menu` VALUES (32, 2, '用户编辑', 4, '', NULL, 'sys:user:edit', 1, 2, '', '', '2022-10-23 11:04:08', '2022-10-23 11:04:11'); +INSERT INTO `sys_menu` VALUES (33, 2, '用户删除', 4, '', NULL, 'sys:user:delete', 1, 3, '', '', '2022-10-23 11:04:08', '2022-10-23 11:04:11'); + +-- ---------------------------- +-- Table structure for sys_role +-- ---------------------------- +DROP TABLE IF EXISTS `sys_role`; +CREATE TABLE `sys_role` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '角色名称', + `code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '角色编码', + `sort` int NULL DEFAULT NULL COMMENT '显示顺序', + `status` tinyint(1) NULL DEFAULT 1 COMMENT '角色状态(1-正常;0-停用)', + `deleted` tinyint(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除标识(0-未删除;1-已删除)', + `create_time` datetime NULL DEFAULT NULL COMMENT '更新时间', + `update_time` datetime NULL DEFAULT NULL COMMENT '创建时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `name`(`name`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 110 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '角色表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sys_role +-- ---------------------------- +INSERT INTO `sys_role` VALUES (1, '超级管理员', 'ROOT', 1, 1, 0, '2021-05-21 14:56:51', '2018-12-23 16:00:00'); +INSERT INTO `sys_role` VALUES (2, '系统管理员', 'ADMIN', 2, 1, 0, '2021-03-25 12:39:54', NULL); +INSERT INTO `sys_role` VALUES (3, '访问游客', 'GUEST', 3, 1, 0, '2021-05-26 15:49:05', '2019-05-05 16:00:00'); +INSERT INTO `sys_role` VALUES (4, '开发', 'DEVELOP', 4, 1, 0, '2022-09-10 13:51:08', '2022-09-10 13:51:08'); +INSERT INTO `sys_role` VALUES (5, '测试', 'TEST', 5, 1, 0, '2022-09-10 15:00:51', '2022-09-10 15:00:51'); + +-- ---------------------------- +-- Table structure for sys_role_menu +-- ---------------------------- +DROP TABLE IF EXISTS `sys_role_menu`; +CREATE TABLE `sys_role_menu` ( + `role_id` bigint NOT NULL COMMENT '角色ID', + `menu_id` bigint NOT NULL COMMENT '菜单ID' +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '角色和菜单关联表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sys_role_menu +-- ---------------------------- +INSERT INTO `sys_role_menu` VALUES (2, 1); +INSERT INTO `sys_role_menu` VALUES (2, 2); +INSERT INTO `sys_role_menu` VALUES (2, 3); +INSERT INTO `sys_role_menu` VALUES (2, 4); +INSERT INTO `sys_role_menu` VALUES (2, 5); +INSERT INTO `sys_role_menu` VALUES (2, 6); +INSERT INTO `sys_role_menu` VALUES (2, 11); +INSERT INTO `sys_role_menu` VALUES (2, 12); +INSERT INTO `sys_role_menu` VALUES (2, 19); +INSERT INTO `sys_role_menu` VALUES (2, 18); +INSERT INTO `sys_role_menu` VALUES (2, 17); +INSERT INTO `sys_role_menu` VALUES (2, 13); +INSERT INTO `sys_role_menu` VALUES (2, 14); +INSERT INTO `sys_role_menu` VALUES (2, 15); +INSERT INTO `sys_role_menu` VALUES (2, 16); +INSERT INTO `sys_role_menu` VALUES (2, 9); +INSERT INTO `sys_role_menu` VALUES (2, 10); +INSERT INTO `sys_role_menu` VALUES (2, 37); +INSERT INTO `sys_role_menu` VALUES (2, 20); +INSERT INTO `sys_role_menu` VALUES (2, 21); +INSERT INTO `sys_role_menu` VALUES (2, 22); +INSERT INTO `sys_role_menu` VALUES (2, 23); +INSERT INTO `sys_role_menu` VALUES (2, 24); +INSERT INTO `sys_role_menu` VALUES (2, 32); +INSERT INTO `sys_role_menu` VALUES (2, 33); +INSERT INTO `sys_role_menu` VALUES (2, 39); +INSERT INTO `sys_role_menu` VALUES (2, 34); +INSERT INTO `sys_role_menu` VALUES (2, 26); +INSERT INTO `sys_role_menu` VALUES (2, 30); +INSERT INTO `sys_role_menu` VALUES (2, 31); + +-- ---------------------------- +-- Table structure for sys_user +-- ---------------------------- +DROP TABLE IF EXISTS `sys_user`; +CREATE TABLE `sys_user` ( + `id` int NOT NULL AUTO_INCREMENT, + `username` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用户名', + `nickname` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '昵称', + `gender` tinyint(1) NULL DEFAULT 1 COMMENT '性别((1:男;2:女))', + `password` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '密码', + `dept_id` int NULL DEFAULT NULL COMMENT '部门ID', + `avatar` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '用户头像', + `mobile` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '联系方式', + `status` tinyint(1) NULL DEFAULT 1 COMMENT '用户状态((1:正常;0:禁用))', + `email` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用户邮箱', + `deleted` tinyint(1) NULL DEFAULT 0 COMMENT '逻辑删除标识(0:未删除;1:已删除)', + `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间', + `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `login_name`(`username`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 260 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户信息表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sys_user +-- ---------------------------- +INSERT INTO `sys_user` VALUES (1, 'root', '有来技术', 0, '$2a$10$xVWsNOhHrCxh5UbpCE7/HuJ.PAOKcYAqRxD2CO2nVnJS.IAXkr5aq', NULL, 'https://s2.loli.net/2022/04/07/gw1L2Z5sPtS8GIl.gif', '17621590365', 1, 'youlaitech@163.com', 0, NULL, NULL); +INSERT INTO `sys_user` VALUES (2, 'admin', '系统管理员', 1, '$2a$10$xVWsNOhHrCxh5UbpCE7/HuJ.PAOKcYAqRxD2CO2nVnJS.IAXkr5aq', 2, 'https://s2.loli.net/2022/04/07/gw1L2Z5sPtS8GIl.gif', '17621210366', 1, '', 0, '2019-10-10 13:41:22', '2022-07-31 12:39:30'); +INSERT INTO `sys_user` VALUES (3, 'test', '测试小用户', 1, '$2a$10$MPJkNw.hKT/fZOgwYP8q9eu/rFJJDsNov697AmdkHNJkpjIpVSw2q', 3, 'https://s2.loli.net/2022/04/07/gw1L2Z5sPtS8GIl.gif', '17621210366', 1, 'youlaitech@163.com', 1, '2021-06-05 01:31:29', '2021-06-05 01:31:29'); + +-- ---------------------------- +-- Table structure for sys_user_role +-- ---------------------------- +DROP TABLE IF EXISTS `sys_user_role`; +CREATE TABLE `sys_user_role` ( + `user_id` bigint NOT NULL COMMENT '用户ID', + `role_id` bigint NOT NULL COMMENT '角色ID', + PRIMARY KEY (`user_id`, `role_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户和角色关联表' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of sys_user_role +-- ---------------------------- +INSERT INTO `sys_user_role` VALUES (1, 1); +INSERT INTO `sys_user_role` VALUES (2, 2); +INSERT INTO `sys_user_role` VALUES (3, 3); + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/src/main/java/com/youlai/system/SystemApplication.java b/src/main/java/com/youlai/system/SystemApplication.java new file mode 100644 index 00000000..f72c404e --- /dev/null +++ b/src/main/java/com/youlai/system/SystemApplication.java @@ -0,0 +1,13 @@ +package com.youlai.system; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SystemApplication { + + public static void main(String[] args) { + SpringApplication.run(SystemApplication.class, args); + } + +} diff --git a/src/main/java/com/youlai/system/common/base/BaseEntity.java b/src/main/java/com/youlai/system/common/base/BaseEntity.java new file mode 100644 index 00000000..fea13d45 --- /dev/null +++ b/src/main/java/com/youlai/system/common/base/BaseEntity.java @@ -0,0 +1,25 @@ +package com.youlai.system.common.base; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +@Data +public class BaseEntity implements Serializable { + private static final long serialVersionUID = 1L; + + @TableField(fill = FieldFill.INSERT) + @JsonInclude(value = JsonInclude.Include.NON_NULL) + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime createTime; + + @TableField(fill = FieldFill.INSERT_UPDATE) + @JsonInclude(value = JsonInclude.Include.NON_NULL) + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime updateTime; +} diff --git a/src/main/java/com/youlai/system/common/base/BasePageQuery.java b/src/main/java/com/youlai/system/common/base/BasePageQuery.java new file mode 100644 index 00000000..620ed156 --- /dev/null +++ b/src/main/java/com/youlai/system/common/base/BasePageQuery.java @@ -0,0 +1,22 @@ +package com.youlai.system.common.base; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 基础分页请求对象 + * + * @author haoxr + * @date 2021/2/28 + */ +@Data +@ApiModel +public class BasePageQuery { + + @ApiModelProperty(value = "页码", example = "1") + private int pageNum = 1; + + @ApiModelProperty(value = "每页记录数", example = "10") + private int pageSize = 10; +} diff --git a/src/main/java/com/youlai/system/common/base/BaseVO.java b/src/main/java/com/youlai/system/common/base/BaseVO.java new file mode 100644 index 00000000..d8c6e35a --- /dev/null +++ b/src/main/java/com/youlai/system/common/base/BaseVO.java @@ -0,0 +1,19 @@ +package com.youlai.system.common.base; + +import lombok.Data; +import lombok.ToString; + +import java.io.Serializable; + +/** + * 视图对象基类 + * + * @author haoxr + * @date 2022/10/22 + */ +@Data +@ToString +public class BaseVO implements Serializable { + + private static final long serialVersionUID = 1L; +} diff --git a/src/main/java/com/youlai/system/common/base/IBaseEnum.java b/src/main/java/com/youlai/system/common/base/IBaseEnum.java new file mode 100644 index 00000000..96df02b4 --- /dev/null +++ b/src/main/java/com/youlai/system/common/base/IBaseEnum.java @@ -0,0 +1,88 @@ +package com.youlai.system.common.base; + + +import cn.hutool.core.util.ObjectUtil; + +import java.util.EnumSet; +import java.util.Objects; + +/** + * 枚举通用接口 + * + * @author haoxr + * @date 2022/3/27 12:06 + */ +public interface IBaseEnum { + + T getValue(); + + String getLabel(); + + /** + * 根据值获取枚举 + * + * @param value + * @param clazz + * @param 枚举 + * @return + */ + static & IBaseEnum> E getEnumByValue(Object value, Class clazz) { + Objects.requireNonNull(value); + EnumSet allEnums = EnumSet.allOf(clazz); // 获取类型下的所有枚举 + E matchEnum = allEnums.stream() + .filter(e -> ObjectUtil.equal(e.getValue(), value)) + .findFirst() + .orElse(null); + return matchEnum; + } + + /** + * 根据文本标签获取值 + * + * @param value + * @param clazz + * @param + * @return + */ + static & IBaseEnum> String getLabelByValue(Object value, Class clazz) { + Objects.requireNonNull(value); + EnumSet allEnums = EnumSet.allOf(clazz); // 获取类型下的所有枚举 + E matchEnum = allEnums.stream() + .filter(e -> ObjectUtil.equal(e.getValue(), value)) + .findFirst() + .orElse(null); + + String label = null; + if (matchEnum != null) { + label = matchEnum.getLabel(); + } + return label; + } + + + /** + * 根据文本标签获取值 + * + * @param label + * @param clazz + * @param + * @return + */ + static & IBaseEnum> Object getValueByLabel(String label, Class clazz) { + Objects.requireNonNull(label); + EnumSet allEnums = EnumSet.allOf(clazz); // 获取类型下的所有枚举 + String finalLabel = label; + E matchEnum = allEnums.stream() + .filter(e -> ObjectUtil.equal(e.getLabel(), finalLabel)) + .findFirst() + .orElse(null); + + Object value = null; + if (matchEnum != null) { + value = matchEnum.getValue(); + } + return value; + } + + +} diff --git a/src/main/java/com/youlai/system/common/constant/SecurityConstants.java b/src/main/java/com/youlai/system/common/constant/SecurityConstants.java new file mode 100644 index 00000000..83be708a --- /dev/null +++ b/src/main/java/com/youlai/system/common/constant/SecurityConstants.java @@ -0,0 +1,18 @@ +package com.youlai.system.common.constant; + +/** + * Security常量 + * + * @author haoxr + * @date 2022/10/22 + */ +public interface SecurityConstants { + + /** + * 授权角色的前缀 + *

+ * 区分角色与权限标识 + */ + String ROLE_PREFIX = "ROLE_"; + +} diff --git a/src/main/java/com/youlai/system/common/constant/SystemConstants.java b/src/main/java/com/youlai/system/common/constant/SystemConstants.java new file mode 100644 index 00000000..3e3cef44 --- /dev/null +++ b/src/main/java/com/youlai/system/common/constant/SystemConstants.java @@ -0,0 +1,26 @@ +package com.youlai.system.common.constant; + +/** + * 系统常量 + * + * @author haoxr + * @date 2022/10/22 + */ +public interface SystemConstants { + + /** + * 根节点ID + */ + Long ROOT_NODE_ID = 0l; + + + /** + * 系统默认密码 + */ + String DEFAULT_USER_PASSWORD = "123456"; + + /** + * 超级管理员角色编码 + */ + String ROOT_ROLE_CODE = "ROOT"; +} diff --git a/src/main/java/com/youlai/system/common/enums/GenderEnum.java b/src/main/java/com/youlai/system/common/enums/GenderEnum.java new file mode 100644 index 00000000..0b294975 --- /dev/null +++ b/src/main/java/com/youlai/system/common/enums/GenderEnum.java @@ -0,0 +1,27 @@ +package com.youlai.system.common.enums; + +import com.youlai.system.common.base.IBaseEnum; +import lombok.Getter; + +/** + * 性别枚举 + * + * @author haoxr + * @date 2022/10/14 + */ +public enum GenderEnum implements IBaseEnum { + + MALE(1, "男"), + FEMALE (2, "女"); + + @Getter + private Integer value; + + @Getter + private String label; + + GenderEnum(Integer value, String label) { + this.value = value; + this.label = label; + } +} diff --git a/src/main/java/com/youlai/system/common/enums/MenuTypeEnum.java b/src/main/java/com/youlai/system/common/enums/MenuTypeEnum.java new file mode 100644 index 00000000..7767ffa0 --- /dev/null +++ b/src/main/java/com/youlai/system/common/enums/MenuTypeEnum.java @@ -0,0 +1,35 @@ +package com.youlai.system.common.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.youlai.system.common.base.IBaseEnum; +import lombok.Getter; + +/** + * 菜单类型枚举 + * + * @author haoxr + * @date 2022/4/23 9:36 + */ + +public enum MenuTypeEnum implements IBaseEnum { + + NULL(0, null), + MENU(1, "菜单"), + CATALOG(2, "目录"), + EXTLINK(3, "外链"), + BUTTON(4, "按钮"); + + @Getter + @EnumValue // Mybatis-Plus 提供注解表示插入数据库时插入该值 + private Integer value; + + @Getter + // @JsonValue // 表示对枚举序列化时返回此字段 + private String label; + + MenuTypeEnum(Integer value, String label) { + this.value = value; + this.label = label; + } + +} diff --git a/src/main/java/com/youlai/system/common/enums/StatusEnum.java b/src/main/java/com/youlai/system/common/enums/StatusEnum.java new file mode 100644 index 00000000..6caa2610 --- /dev/null +++ b/src/main/java/com/youlai/system/common/enums/StatusEnum.java @@ -0,0 +1,27 @@ +package com.youlai.system.common.enums; + +import com.youlai.system.common.base.IBaseEnum; +import lombok.Getter; + +/** + * 状态枚举 + * + * @author haoxr + * @date 2022/10/14 + */ +public enum StatusEnum implements IBaseEnum { + + ENABLE(1, "启用"), + DISABLE (0, "禁用"); + + @Getter + private Integer value; + + @Getter + private String label; + + StatusEnum(Integer value, String label) { + this.value = value; + this.label = label; + } +} diff --git a/src/main/java/com/youlai/system/common/exception/BusinessException.java b/src/main/java/com/youlai/system/common/exception/BusinessException.java new file mode 100644 index 00000000..83442f31 --- /dev/null +++ b/src/main/java/com/youlai/system/common/exception/BusinessException.java @@ -0,0 +1,35 @@ +package com.youlai.system.common.exception; + +import com.youlai.system.common.result.IResultCode; +import lombok.Getter; + +/** + * 自定义业务异常 + * + * @author haoxr + * @date 2022/7/31 + */ +@Getter +public class BusinessException extends RuntimeException { + + public IResultCode resultCode; + + public BusinessException(IResultCode errorCode) { + super(errorCode.getMsg()); + this.resultCode = errorCode; + } + + public BusinessException(String message){ + super(message); + } + + public BusinessException(String message, Throwable cause){ + super(message, cause); + } + + public BusinessException(Throwable cause){ + super(cause); + } + + +} diff --git a/src/main/java/com/youlai/system/common/exception/GlobalExceptionHandler.java b/src/main/java/com/youlai/system/common/exception/GlobalExceptionHandler.java new file mode 100644 index 00000000..ed412851 --- /dev/null +++ b/src/main/java/com/youlai/system/common/exception/GlobalExceptionHandler.java @@ -0,0 +1,208 @@ +package com.youlai.system.common.exception; + +import cn.hutool.core.util.StrUtil; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.youlai.system.common.result.Result; +import com.youlai.system.common.result.ResultCode; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.TypeMismatchException; +import org.springframework.context.support.DefaultMessageSourceResolvable; +import org.springframework.http.HttpStatus; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.BindException; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.MissingServletRequestParameterException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; +import org.springframework.web.servlet.NoHandlerFoundException; + +import javax.servlet.ServletException; +import javax.validation.ConstraintViolation; +import javax.validation.ConstraintViolationException; +import java.sql.SQLSyntaxErrorException; +import java.util.concurrent.CompletionException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +/** + * 全局系统异常处理 + * 调整异常处理的HTTP状态码,丰富异常处理类型 + * + * @author hxrui + * @author Gadfly + * @date 2020-02-25 13:54 + *

+ **/ +@RestControllerAdvice +@Slf4j +public class GlobalExceptionHandler { + + @ResponseStatus(HttpStatus.BAD_REQUEST) + @ExceptionHandler(BindException.class) + public Result processException(BindException e) { + log.error("BindException:{}", e.getMessage()); + String msg = e.getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining(";")); + return Result.failed(ResultCode.PARAM_ERROR, msg); + } + + /** + * RequestParam参数的校验 + * + * @param e + * @param + * @return + */ + @ResponseStatus(HttpStatus.BAD_REQUEST) + @ExceptionHandler(ConstraintViolationException.class) + public Result processException(ConstraintViolationException e) { + log.error("ConstraintViolationException:{}", e.getMessage()); + String msg = e.getConstraintViolations().stream().map(ConstraintViolation::getMessage).collect(Collectors.joining(";")); + return Result.failed(ResultCode.PARAM_ERROR, msg); + } + + /** + * RequestBody参数的校验 + * + * @param e + * @param + * @return + */ + @ResponseStatus(HttpStatus.BAD_REQUEST) + @ExceptionHandler(MethodArgumentNotValidException.class) + public Result processException(MethodArgumentNotValidException e) { + log.error("MethodArgumentNotValidException:{}", e.getMessage()); + String msg = e.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining(";")); + return Result.failed(ResultCode.PARAM_ERROR, msg); + } + + @ResponseStatus(HttpStatus.NOT_FOUND) + @ExceptionHandler(NoHandlerFoundException.class) + public Result processException(NoHandlerFoundException e) { + log.error(e.getMessage(), e); + return Result.failed(ResultCode.RESOURCE_NOT_FOUND); + } + + /** + * MissingServletRequestParameterException + */ + @ResponseStatus(HttpStatus.BAD_REQUEST) + @ExceptionHandler(MissingServletRequestParameterException.class) + public Result processException(MissingServletRequestParameterException e) { + log.error(e.getMessage(), e); + return Result.failed(ResultCode.PARAM_IS_NULL); + } + + /** + * MethodArgumentTypeMismatchException + */ + @ResponseStatus(HttpStatus.BAD_REQUEST) + @ExceptionHandler(MethodArgumentTypeMismatchException.class) + public Result processException(MethodArgumentTypeMismatchException e) { + log.error(e.getMessage(), e); + return Result.failed(ResultCode.PARAM_ERROR, "类型错误"); + } + + /** + * ServletException + */ + @ResponseStatus(HttpStatus.BAD_REQUEST) + @ExceptionHandler(ServletException.class) + public Result processException(ServletException e) { + log.error(e.getMessage(), e); + return Result.failed(e.getMessage()); + } + + @ResponseStatus(HttpStatus.BAD_REQUEST) + @ExceptionHandler(IllegalArgumentException.class) + public Result handleIllegalArgumentException(IllegalArgumentException e) { + log.error("非法参数异常,异常原因:{}", e.getMessage(), e); + return Result.failed(e.getMessage()); + } + + @ResponseStatus(HttpStatus.BAD_REQUEST) + @ExceptionHandler(JsonProcessingException.class) + public Result handleJsonProcessingException(JsonProcessingException e) { + log.error("Json转换异常,异常原因:{}", e.getMessage(), e); + return Result.failed(e.getMessage()); + } + + /** + * HttpMessageNotReadableException + */ + @ResponseStatus(HttpStatus.BAD_REQUEST) + @ExceptionHandler(HttpMessageNotReadableException.class) + public Result processException(HttpMessageNotReadableException e) { + log.error(e.getMessage(), e); + String errorMessage = "请求体不可为空"; + Throwable cause = e.getCause(); + if (cause != null) { + errorMessage = convertMessage(cause); + } + return Result.failed(errorMessage); + } + + /** + * TypeMismatchException + */ + @ResponseStatus(HttpStatus.BAD_REQUEST) + @ExceptionHandler(TypeMismatchException.class) + public Result processException(TypeMismatchException e) { + log.error(e.getMessage(), e); + return Result.failed(e.getMessage()); + } + + @ResponseStatus(HttpStatus.FORBIDDEN) + @ExceptionHandler(SQLSyntaxErrorException.class) + public Result processSQLSyntaxErrorException(SQLSyntaxErrorException e) { + log.error(e.getMessage(), e); + String errorMsg = e.getMessage(); + if (StrUtil.isNotBlank(errorMsg) && errorMsg.contains("denied to user")) { + return Result.failed("数据库用户无操作权限,建议本地搭建数据库环境"); + } else { + return Result.failed(e.getMessage()); + } + } + + + + + @ResponseStatus(HttpStatus.BAD_REQUEST) + @ExceptionHandler(BusinessException.class) + public Result handleBizException(BusinessException e) { + log.error("业务异常,异常原因:{}", e.getMessage(), e); + if (e.getResultCode() != null) { + return Result.failed(e.getResultCode()); + } + return Result.failed(e.getMessage()); + } + + @ResponseStatus(HttpStatus.BAD_REQUEST) + @ExceptionHandler(Exception.class) + public Result handleException(Exception e) { + return Result.failed(e.getLocalizedMessage()); + } + + /** + * 传参类型错误时,用于消息转换 + * + * @param throwable 异常 + * @return 错误信息 + */ + private String convertMessage(Throwable throwable) { + String error = throwable.toString(); + String regulation = "\\[\"(.*?)\"]+"; + Pattern pattern = Pattern.compile(regulation); + Matcher matcher = pattern.matcher(error); + String group = ""; + if (matcher.find()) { + String matchString = matcher.group(); + matchString = matchString.replace("[", "").replace("]", ""); + matchString = matchString.replaceAll("\\\"", "") + "字段类型错误"; + group += matchString; + } + return group; + } +} diff --git a/src/main/java/com/youlai/system/common/model/Option.java b/src/main/java/com/youlai/system/common/model/Option.java new file mode 100644 index 00000000..5571356a --- /dev/null +++ b/src/main/java/com/youlai/system/common/model/Option.java @@ -0,0 +1,42 @@ +package com.youlai.system.common.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + * 下拉选项对象 + * + * @author haoxr + * @date 2022/1/22 + */ +@ApiModel("下拉选项对象") +@Data +@NoArgsConstructor +public class Option { + + public Option(T value, String label) { + this.value = value; + this.label = label; + } + + public Option(T value, String label, List

+ * 主要是用于对象数据 基础类型包装对象不建议用 + * https://www.jianshu.com/p/ab832f3fe81c + * + * @author Gadfly + * @since 2021-06-30 15:20 + */ +@Slf4j +@MappedJdbcTypes(value = {JdbcType.OTHER}, includeNullJdbcType = true) +public class ArrayObjectJsonTypeHandler extends BaseTypeHandler { + private static final ObjectMapper MAPPER = new ObjectMapper(); + private static final String STRING_JSON_ARRAY_EMPTY = "[]"; + + static { + // 未知字段忽略 + MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + // 不使用科学计数 + MAPPER.configure(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN, true); + // null 值不输出(节省内存) + MAPPER.setDefaultPropertyInclusion(JsonInclude.Include.NON_NULL); + } + + private final Class type; + + public ArrayObjectJsonTypeHandler(Class type) { + Objects.requireNonNull(type); + this.type = type; + } + + @Override + public void setNonNullParameter(PreparedStatement ps, int i, E[] parameter, JdbcType jdbcType) throws SQLException { + ps.setString(i, toJson(parameter)); + } + + @Override + public E[] getNullableResult(ResultSet rs, String columnName) throws SQLException { + return toObject(rs.getString(columnName), type); + } + + @Override + public E[] getNullableResult(ResultSet rs, int columnIndex) throws SQLException { + return toObject(rs.getString(columnIndex), type); + } + + @Override + public E[] getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { + return toObject(cs.getString(columnIndex), type); + } + + /** + * object 转 json + * + * @param obj 对象 + * @return String json字符串 + */ + private String toJson(E[] obj) { + if (ArrayUtils.isEmpty(obj)) { + return STRING_JSON_ARRAY_EMPTY; + } + + try { + return MAPPER.writeValueAsString(obj); + } catch (JsonProcessingException e) { + throw new RuntimeException("mybatis column to json error,obj:" + Arrays.toString(obj), e); + } + } + + /** + * 转换对象 + * + * @param json json数据 + * @param clazz 类 + * @return E + */ + private E[] toObject(String json, Class clazz) { + if (json == null) { + return null; + } + + if (!StringUtils.hasText(json)) { + return newArray(clazz); + } + + try { + return MAPPER.readValue(json, clazz); + } catch (JsonProcessingException e) { + log.error("mybatis column json to object error,json:{}", json, e); + return newArray(clazz); + } + } + + @SuppressWarnings("unchecked") + private E[] newArray(Class clazz) { + return (E[]) Array.newInstance(clazz.getComponentType(), 0); + } +} diff --git a/src/main/java/com/youlai/system/handler/IntegerArrayJsonTypeHandler.java b/src/main/java/com/youlai/system/handler/IntegerArrayJsonTypeHandler.java new file mode 100644 index 00000000..b68569fb --- /dev/null +++ b/src/main/java/com/youlai/system/handler/IntegerArrayJsonTypeHandler.java @@ -0,0 +1,24 @@ +package com.youlai.system.handler; + +import lombok.extern.slf4j.Slf4j; +import org.apache.ibatis.type.JdbcType; +import org.apache.ibatis.type.MappedJdbcTypes; +import org.apache.ibatis.type.MappedTypes; +import org.springframework.stereotype.Component; + +/** + * Integer 数组类型转换 json + * https://www.jianshu.com/p/ab832f3fe81c + * + * @author haoxr + * @since 2022/10/14 15:19 + */ +@Slf4j +@Component +@MappedTypes(value = {Integer[].class}) +@MappedJdbcTypes(value = {JdbcType.VARCHAR}, includeNullJdbcType = true) +public class IntegerArrayJsonTypeHandler extends ArrayObjectJsonTypeHandler { + public IntegerArrayJsonTypeHandler() { + super(Integer[].class); + } +} diff --git a/src/main/java/com/youlai/system/handler/LongArrayJsonTypeHandler.java b/src/main/java/com/youlai/system/handler/LongArrayJsonTypeHandler.java new file mode 100644 index 00000000..98ceac41 --- /dev/null +++ b/src/main/java/com/youlai/system/handler/LongArrayJsonTypeHandler.java @@ -0,0 +1,23 @@ +package com.youlai.system.handler; + +import lombok.extern.slf4j.Slf4j; +import org.apache.ibatis.type.JdbcType; +import org.apache.ibatis.type.MappedJdbcTypes; +import org.apache.ibatis.type.MappedTypes; +import org.springframework.stereotype.Component; + +/** + * Long 数组类型转换 json + * + * @author haoxr + * @since 2022/10/14 + */ +@Slf4j +@Component +@MappedTypes(value = {Long[].class}) +@MappedJdbcTypes(value = {JdbcType.OTHER}, includeNullJdbcType = true) +public class LongArrayJsonTypeHandler extends ArrayObjectJsonTypeHandler { + public LongArrayJsonTypeHandler() { + super(Long[].class); + } +} diff --git a/src/main/java/com/youlai/system/handler/MyMetaObjectHandler.java b/src/main/java/com/youlai/system/handler/MyMetaObjectHandler.java new file mode 100644 index 00000000..6028077d --- /dev/null +++ b/src/main/java/com/youlai/system/handler/MyMetaObjectHandler.java @@ -0,0 +1,40 @@ +package com.youlai.system.handler; + +import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; +import org.apache.ibatis.reflection.MetaObject; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; + +/** + * mybatis-plus 字段自动填充 + * + * @author haoxr + * @date 2022/10/14 + * @link https://mp.baomidou.com/guide/auto-fill-metainfo.html + */ +@Component +public class MyMetaObjectHandler implements MetaObjectHandler { + + /** + * 新增填充创建时间 + * + * @param metaObject + */ + @Override + public void insertFill(MetaObject metaObject) { + this.strictInsertFill(metaObject, "createTime", () -> LocalDateTime.now(), LocalDateTime.class); + this.strictUpdateFill(metaObject, "updateTime", () -> LocalDateTime.now(), LocalDateTime.class); + } + + /** + * 更新填充更新时间 + * + * @param metaObject + */ + @Override + public void updateFill(MetaObject metaObject) { + this.strictUpdateFill(metaObject, "updateTime", () -> LocalDateTime.now(), LocalDateTime.class); + } + +} diff --git a/src/main/java/com/youlai/system/handler/StringArrayJsonTypeHandler.java b/src/main/java/com/youlai/system/handler/StringArrayJsonTypeHandler.java new file mode 100644 index 00000000..0bb5a0b8 --- /dev/null +++ b/src/main/java/com/youlai/system/handler/StringArrayJsonTypeHandler.java @@ -0,0 +1,23 @@ +package com.youlai.system.handler; + +import lombok.extern.slf4j.Slf4j; +import org.apache.ibatis.type.JdbcType; +import org.apache.ibatis.type.MappedJdbcTypes; +import org.apache.ibatis.type.MappedTypes; +import org.springframework.stereotype.Component; + +/** + * String 数组类型转换 json + * + * @author haoxr + * @since 2022/10/14 + */ +@Slf4j +@Component +@MappedTypes(value = {String[].class}) +@MappedJdbcTypes(value = {JdbcType.OTHER}, includeNullJdbcType = true) +public class StringArrayJsonTypeHandler extends ArrayObjectJsonTypeHandler { + public StringArrayJsonTypeHandler() { + super(String[].class); + } +} diff --git a/src/main/java/com/youlai/system/listener/UserImportListener.java b/src/main/java/com/youlai/system/listener/UserImportListener.java new file mode 100644 index 00000000..f486f36c --- /dev/null +++ b/src/main/java/com/youlai/system/listener/UserImportListener.java @@ -0,0 +1,27 @@ +package com.youlai.system.listener; + +import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.event.AnalysisEventListener; +import com.youlai.system.pojo.dto.UserImportDTO; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +/** + * + * @author haoxr + * @date 2022/4/10 20:49 + */ +@Component +@Scope("prototype") +public class UserImportListener extends AnalysisEventListener { + + @Override + public void invoke(UserImportDTO.UserItem userItem, AnalysisContext analysisContext) { + + } + + @Override + public void doAfterAllAnalysed(AnalysisContext analysisContext) { + + } +} diff --git a/src/main/java/com/youlai/system/mapper/SysDeptMapper.java b/src/main/java/com/youlai/system/mapper/SysDeptMapper.java new file mode 100644 index 00000000..00a13f52 --- /dev/null +++ b/src/main/java/com/youlai/system/mapper/SysDeptMapper.java @@ -0,0 +1,19 @@ +package com.youlai.system.mapper; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.toolkit.Constants; +import com.youlai.system.pojo.entity.SysDept; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + + +@Mapper +public interface SysDeptMapper extends BaseMapper { + + // @DataPermission + @Override + List selectList(@Param(Constants.WRAPPER) Wrapper queryWrapper); +} diff --git a/src/main/java/com/youlai/system/mapper/SysDictItemMapper.java b/src/main/java/com/youlai/system/mapper/SysDictItemMapper.java new file mode 100644 index 00000000..bfa9df2f --- /dev/null +++ b/src/main/java/com/youlai/system/mapper/SysDictItemMapper.java @@ -0,0 +1,14 @@ +package com.youlai.system.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.youlai.system.pojo.entity.SysDictItem; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface SysDictItemMapper extends BaseMapper { + +} + + + + diff --git a/src/main/java/com/youlai/system/mapper/SysDictTypeMapper.java b/src/main/java/com/youlai/system/mapper/SysDictTypeMapper.java new file mode 100644 index 00000000..d4799b77 --- /dev/null +++ b/src/main/java/com/youlai/system/mapper/SysDictTypeMapper.java @@ -0,0 +1,14 @@ +package com.youlai.system.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.youlai.system.pojo.entity.SysDictType; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface SysDictTypeMapper extends BaseMapper { + +} + + + + diff --git a/src/main/java/com/youlai/system/mapper/SysMenuMapper.java b/src/main/java/com/youlai/system/mapper/SysMenuMapper.java new file mode 100644 index 00000000..10670788 --- /dev/null +++ b/src/main/java/com/youlai/system/mapper/SysMenuMapper.java @@ -0,0 +1,30 @@ +package com.youlai.system.mapper; + +/** + * 菜单持久接口层 + * + * @author haoxr + * @date 2022/1/24 + */ + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.youlai.system.pojo.entity.SysMenu; +import com.youlai.system.pojo.po.RoutePO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; +import java.util.Set; + +@Mapper +public interface SysMenuMapper extends BaseMapper { + + List listRoutes(); + + /** + * 获取角色权限集合 + * + * @param roles + * @return + */ + Set listRolePerms(Set roles); +} diff --git a/src/main/java/com/youlai/system/mapper/SysRoleMapper.java b/src/main/java/com/youlai/system/mapper/SysRoleMapper.java new file mode 100644 index 00000000..e7230f59 --- /dev/null +++ b/src/main/java/com/youlai/system/mapper/SysRoleMapper.java @@ -0,0 +1,11 @@ +package com.youlai.system.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.youlai.system.pojo.entity.SysRole; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface SysRoleMapper extends BaseMapper { + + +} diff --git a/src/main/java/com/youlai/system/mapper/SysRoleMenuMapper.java b/src/main/java/com/youlai/system/mapper/SysRoleMenuMapper.java new file mode 100644 index 00000000..ef28ace3 --- /dev/null +++ b/src/main/java/com/youlai/system/mapper/SysRoleMenuMapper.java @@ -0,0 +1,25 @@ +package com.youlai.system.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.youlai.system.pojo.entity.SysRoleMenu; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 角色菜单持久层 + * + * @author haoxr + * @date 2022/6/4 + */ +@Mapper +public interface SysRoleMenuMapper extends BaseMapper { + + /** + * 获取角色拥有的菜单ID集合 + * + * @param roleId + * @return + */ + List listMenuIdsByRoleId(Long roleId); +} diff --git a/src/main/java/com/youlai/system/mapper/SysUserMapper.java b/src/main/java/com/youlai/system/mapper/SysUserMapper.java new file mode 100644 index 00000000..ba316e56 --- /dev/null +++ b/src/main/java/com/youlai/system/mapper/SysUserMapper.java @@ -0,0 +1,56 @@ +package com.youlai.system.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.youlai.system.pojo.entity.SysUser; +import com.youlai.system.pojo.po.UserAuthInfo; +import com.youlai.system.pojo.po.UserFormPO; +import com.youlai.system.pojo.po.UserPO; +import com.youlai.system.pojo.query.UserPageQuery; +import com.youlai.system.pojo.vo.user.UserExportVO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 用户持久层 + * + * @author haoxr + * @date 2022/1/14 + */ +@Mapper +public interface SysUserMapper extends BaseMapper { + + /** + * 获取用户分页列表 + * + * @param page + * @param queryParams 查询参数 + * @return + */ + Page listUserPages(Page page, UserPageQuery queryParams); + + /** + * 获取用户表单详情 + * + * @param userId 用户ID + * @return + */ + UserFormPO getUserDetail(Long userId); + + /** + * 根据用户名获取认证信息 + * + * @param username + * @return + */ + UserAuthInfo getUserAuthInfo(String username); + + /** + * 获取导出用户列表 + * + * @param queryParams + * @return + */ + List listExportUsers(UserPageQuery queryParams); +} diff --git a/src/main/java/com/youlai/system/mapper/SysUserRoleMapper.java b/src/main/java/com/youlai/system/mapper/SysUserRoleMapper.java new file mode 100644 index 00000000..bafd2c9f --- /dev/null +++ b/src/main/java/com/youlai/system/mapper/SysUserRoleMapper.java @@ -0,0 +1,16 @@ +package com.youlai.system.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.youlai.system.pojo.entity.SysUserRole; +import org.apache.ibatis.annotations.Mapper; + +/** + * 用户角色持久层 + * + * @author haoxr + * @date 2022/1/15 + */ +@Mapper +public interface SysUserRoleMapper extends BaseMapper { + +} diff --git a/src/main/java/com/youlai/system/pojo/dto/UserImportDTO.java b/src/main/java/com/youlai/system/pojo/dto/UserImportDTO.java new file mode 100644 index 00000000..7f8da694 --- /dev/null +++ b/src/main/java/com/youlai/system/pojo/dto/UserImportDTO.java @@ -0,0 +1,58 @@ +package com.youlai.system.pojo.dto; + +import com.alibaba.excel.annotation.ExcelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; + +/** + * 用户导入对象 + * + * @author haoxr + * @date 2022/4/10 + */ +@Data +public class UserImportDTO { + + /** + * 部门ID + */ + private Long deptId; + + /** + * 角色ID + */ + private String roleIds; + + private MultipartFile file; + + /** + * 导入的用户列表 + */ + private List userList; + + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class UserItem { + + @ExcelProperty(value = "用户名") + private String username; + + @ExcelProperty(value = "用户昵称") + private String nickname; + + @ExcelProperty(value = "性别") + private String gender; + + @ExcelProperty(value = "手机号码") + private String mobile; + + @ExcelProperty(value = "邮箱") + private String email; + } + +} diff --git a/src/main/java/com/youlai/system/pojo/entity/SysDept.java b/src/main/java/com/youlai/system/pojo/entity/SysDept.java new file mode 100644 index 00000000..dc84e607 --- /dev/null +++ b/src/main/java/com/youlai/system/pojo/entity/SysDept.java @@ -0,0 +1,66 @@ +package com.youlai.system.pojo.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.util.Date; +import lombok.Data; + +/** + * 部门表 + * @TableName sys_dept + */ +@TableName(value ="sys_dept") +@Data +public class SysDept implements Serializable { + /** + * 主键 + */ + @TableId(type = IdType.AUTO) + private Long id; + + /** + * 部门名称 + */ + private String name; + + /** + * 父节点id + */ + private Long parentId; + + /** + * 父节点id路径 + */ + private String treePath; + + /** + * 显示顺序 + */ + private Integer sort; + + /** + * 状态(1:正常;0:禁用) + */ + private Integer status; + + /** + * 逻辑删除标识(1:已删除;0:未删除) + */ + private Integer deleted; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 更新时间 + */ + private Date updateTime; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/java/com/youlai/system/pojo/entity/SysDictItem.java b/src/main/java/com/youlai/system/pojo/entity/SysDictItem.java new file mode 100644 index 00000000..96f8d346 --- /dev/null +++ b/src/main/java/com/youlai/system/pojo/entity/SysDictItem.java @@ -0,0 +1,71 @@ +package com.youlai.system.pojo.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.util.Date; +import lombok.Data; + +/** + * 字典数据表 + * @TableName sys_dict_item + */ +@TableName(value ="sys_dict_item") +@Data +public class SysDictItem implements Serializable { + /** + * 主键 + */ + @TableId(type = IdType.AUTO) + private Long id; + + /** + * 字典类型编码 + */ + private String typeCode; + + /** + * 字典项名称 + */ + private String name; + + /** + * 字典项值 + */ + private String value; + + /** + * 排序 + */ + private Integer sort; + + /** + * 状态(1:正常;0:禁用) + */ + private Integer status; + + /** + * 是否默认(1:是;0:否) + */ + private Integer defaulted; + + /** + * 备注 + */ + private String remark; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 更新时间 + */ + private Date updateTime; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/java/com/youlai/system/pojo/entity/SysDictType.java b/src/main/java/com/youlai/system/pojo/entity/SysDictType.java new file mode 100644 index 00000000..2ee71d91 --- /dev/null +++ b/src/main/java/com/youlai/system/pojo/entity/SysDictType.java @@ -0,0 +1,56 @@ +package com.youlai.system.pojo.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.util.Date; +import lombok.Data; + +/** + * 字典类型表 + * @TableName sys_dict_type + */ +@TableName(value ="sys_dict_type") +@Data +public class SysDictType implements Serializable { + /** + * 主键 + */ + @TableId(type = IdType.AUTO) + private Long id; + + /** + * 类型名称 + */ + private String name; + + /** + * 类型编码 + */ + private String code; + + /** + * 状态(0:正常;1:禁用) + */ + private Integer status; + + /** + * 备注 + */ + private String remark; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 更新时间 + */ + private Date updateTime; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/java/com/youlai/system/pojo/entity/SysMenu.java b/src/main/java/com/youlai/system/pojo/entity/SysMenu.java new file mode 100644 index 00000000..4d03482c --- /dev/null +++ b/src/main/java/com/youlai/system/pojo/entity/SysMenu.java @@ -0,0 +1,76 @@ +package com.youlai.system.pojo.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.util.Date; + +import com.youlai.system.common.base.BaseEntity; +import com.youlai.system.common.enums.MenuTypeEnum; +import lombok.Data; + +/** + * 菜单表实体 + */ +@TableName(value ="sys_menu") +@Data +public class SysMenu extends BaseEntity { + /** + * + */ + @TableId(type = IdType.AUTO) + private Long id; + + /** + * 父菜单ID + */ + private Long parentId; + + /** + * 菜单名称 + */ + private String name; + + /** + * 菜单类型(1-菜单;2-目录;3-外链;4-按钮权限) + */ + private MenuTypeEnum type; + + /** + * 路由路径(浏览器地址栏路径) + */ + private String path; + + /** + * 组件路径(vue页面完整路径,省略.vue后缀) + */ + private String component; + + /** + * 权限标识 + */ + private String perm; + + /** + * 显示状态(1:显示;0:隐藏) + */ + private Integer visible; + + /** + * 排序 + */ + private Integer sort; + + /** + * 菜单图标 + */ + private String icon; + + /** + * 外链路径 + */ + private String redirectUrl; + +} \ No newline at end of file diff --git a/src/main/java/com/youlai/system/pojo/entity/SysRole.java b/src/main/java/com/youlai/system/pojo/entity/SysRole.java new file mode 100644 index 00000000..49168e7a --- /dev/null +++ b/src/main/java/com/youlai/system/pojo/entity/SysRole.java @@ -0,0 +1,61 @@ +package com.youlai.system.pojo.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.util.Date; +import lombok.Data; + +/** + * 角色表 + * @TableName sys_role + */ +@TableName(value ="sys_role") +@Data +public class SysRole implements Serializable { + /** + * + */ + @TableId(type = IdType.AUTO) + private Long id; + + /** + * 角色名称 + */ + private String name; + + /** + * 角色编码 + */ + private String code; + + /** + * 显示顺序 + */ + private Integer sort; + + /** + * 角色状态(1-正常;0-停用) + */ + private Integer status; + + /** + * 逻辑删除标识(0-未删除;1-已删除) + */ + private Integer deleted; + + /** + * 更新时间 + */ + private Date createTime; + + /** + * 创建时间 + */ + private Date updateTime; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/java/com/youlai/system/pojo/entity/SysRoleMenu.java b/src/main/java/com/youlai/system/pojo/entity/SysRoleMenu.java new file mode 100644 index 00000000..991a6178 --- /dev/null +++ b/src/main/java/com/youlai/system/pojo/entity/SysRoleMenu.java @@ -0,0 +1,30 @@ +package com.youlai.system.pojo.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Data; + +import java.io.Serializable; + +/** + * 角色和菜单关联表 + * @TableName sys_role_menu + */ +@TableName(value ="sys_role_menu") +@Data +@AllArgsConstructor +public class SysRoleMenu implements Serializable { + /** + * 角色ID + */ + private Long roleId; + + /** + * 菜单ID + */ + private Long menuId; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/java/com/youlai/system/pojo/entity/SysUser.java b/src/main/java/com/youlai/system/pojo/entity/SysUser.java new file mode 100644 index 00000000..cab05f1b --- /dev/null +++ b/src/main/java/com/youlai/system/pojo/entity/SysUser.java @@ -0,0 +1,86 @@ +package com.youlai.system.pojo.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.util.Date; +import lombok.Data; + +/** + * 用户信息表 + * @TableName sys_user + */ +@TableName(value ="sys_user") +@Data +public class SysUser implements Serializable { + /** + * + */ + @TableId(type = IdType.AUTO) + private Long id; + + /** + * 用户名 + */ + private String username; + + /** + * 昵称 + */ + private String nickname; + + /** + * 性别((1:男;2:女)) + */ + private Integer gender; + + /** + * 密码 + */ + private String password; + + /** + * 部门ID + */ + private Long deptId; + + /** + * 用户头像 + */ + private String avatar; + + /** + * 联系方式 + */ + private String mobile; + + /** + * 用户状态((1:正常;0:禁用)) + */ + private Integer status; + + /** + * 用户邮箱 + */ + private String email; + + /** + * 逻辑删除标识(0:未删除;1:已删除) + */ + private Integer deleted; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 更新时间 + */ + private Date updateTime; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/java/com/youlai/system/pojo/entity/SysUserRole.java b/src/main/java/com/youlai/system/pojo/entity/SysUserRole.java new file mode 100644 index 00000000..b8ebcbeb --- /dev/null +++ b/src/main/java/com/youlai/system/pojo/entity/SysUserRole.java @@ -0,0 +1,30 @@ +package com.youlai.system.pojo.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Data; + +import java.io.Serializable; + +/** + * 用户和角色关联表 + * @TableName sys_user_role + */ +@TableName(value ="sys_user_role") +@Data +@AllArgsConstructor +public class SysUserRole implements Serializable { + /** + * 用户ID + */ + private Long userId; + + /** + * 角色ID + */ + private Long roleId; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/java/com/youlai/system/pojo/form/DeptForm.java b/src/main/java/com/youlai/system/pojo/form/DeptForm.java new file mode 100644 index 00000000..bb160d30 --- /dev/null +++ b/src/main/java/com/youlai/system/pojo/form/DeptForm.java @@ -0,0 +1,27 @@ +package com.youlai.system.pojo.form; + +import com.youlai.system.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +@ApiModel("部门表单对象") +@Data +public class DeptForm extends BaseEntity { + + @ApiModelProperty("部门名称") + private String name; + + @ApiModelProperty("父部门ID") + @NotNull(message = "父部门ID不能为空") + private Long parentId; + + @ApiModelProperty("状态") + private Integer status; + + @ApiModelProperty("排序") + private Integer sort; + +} diff --git a/src/main/java/com/youlai/system/pojo/form/DictItemForm.java b/src/main/java/com/youlai/system/pojo/form/DictItemForm.java new file mode 100644 index 00000000..be6cd07a --- /dev/null +++ b/src/main/java/com/youlai/system/pojo/form/DictItemForm.java @@ -0,0 +1,30 @@ +package com.youlai.system.pojo.form; + + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@ApiModel("字典数据项") +@Data +public class DictItemForm { + + @ApiModelProperty("数据项ID") + private Long id; + + @ApiModelProperty("类型编码") + private String typeCode; + + @ApiModelProperty("数据项名称") + private String name; + + @ApiModelProperty("值") + private String value; + + @ApiModelProperty("状态:1->启用;0->禁用") + private Integer status; + + @ApiModelProperty("排序") + private Integer sort; + +} diff --git a/src/main/java/com/youlai/system/pojo/form/DictTypeForm.java b/src/main/java/com/youlai/system/pojo/form/DictTypeForm.java new file mode 100644 index 00000000..79e7f258 --- /dev/null +++ b/src/main/java/com/youlai/system/pojo/form/DictTypeForm.java @@ -0,0 +1,24 @@ +package com.youlai.system.pojo.form; + + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@ApiModel("字典类型") +@Data +public class DictTypeForm { + + @ApiModelProperty("字典类型ID") + private Long id; + + @ApiModelProperty("类型名称") + private String name; + + @ApiModelProperty("类型编码") + private String code; + + @ApiModelProperty("类型状态:1->启用;0->禁用") + private Integer status; + +} diff --git a/src/main/java/com/youlai/system/pojo/form/RoleForm.java b/src/main/java/com/youlai/system/pojo/form/RoleForm.java new file mode 100644 index 00000000..93c50f15 --- /dev/null +++ b/src/main/java/com/youlai/system/pojo/form/RoleForm.java @@ -0,0 +1,30 @@ +package com.youlai.system.pojo.form; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; + +@ApiModel("角色表单对象") +@Data +public class RoleForm { + + @ApiModelProperty("角色ID") + private Long id; + + @ApiModelProperty("角色名称") + @NotBlank(message = "角色名称不能为空") + private String name; + + @ApiModelProperty("角色编码") + @NotBlank(message = "角色编码不能为空") + private String code; + + @ApiModelProperty("排序") + private Integer sort; + + @ApiModelProperty("角色状态(1-正常;0-停用)") + private Integer status; + +} diff --git a/src/main/java/com/youlai/system/pojo/form/RolePermsForm.java b/src/main/java/com/youlai/system/pojo/form/RolePermsForm.java new file mode 100644 index 00000000..e259da1f --- /dev/null +++ b/src/main/java/com/youlai/system/pojo/form/RolePermsForm.java @@ -0,0 +1,31 @@ +package com.youlai.system.pojo.form; + +import lombok.Data; + +import java.util.List; + +/** + * 角色权限传输层对象 + * + * @author haoxr + * @date 2021/12/19 11:46 + */ +@Data +public class RolePermsForm { + + /** + * 菜单ID + */ + private Long menuId; + + /** + * 角色ID + */ + private Long roleId; + + /** + * 权限ID集合 + */ + private List permIds; + +} diff --git a/src/main/java/com/youlai/system/pojo/form/RoleResourceForm.java b/src/main/java/com/youlai/system/pojo/form/RoleResourceForm.java new file mode 100644 index 00000000..be1438ba --- /dev/null +++ b/src/main/java/com/youlai/system/pojo/form/RoleResourceForm.java @@ -0,0 +1,20 @@ +package com.youlai.system.pojo.form; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + + +@ApiModel("菜单资源表单") +@Data +public class RoleResourceForm { + + @ApiModelProperty("菜单ID集合") + private List menuIds; + + @ApiModelProperty("权限ID集合") + private List permIds; + +} diff --git a/src/main/java/com/youlai/system/pojo/form/UserForm.java b/src/main/java/com/youlai/system/pojo/form/UserForm.java new file mode 100644 index 00000000..bfe5889a --- /dev/null +++ b/src/main/java/com/youlai/system/pojo/form/UserForm.java @@ -0,0 +1,55 @@ +package com.youlai.system.pojo.form; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.Pattern; +import java.util.List; + +/** + * 用户表单对象 + * + * @author haoxr + * @date 2022/4/12 11:04 + */ +@ApiModel +@Data +public class UserForm { + + @ApiModelProperty("用户ID") + private Long id; + + @ApiModelProperty("用户名") + @NotBlank(message = "用户名不能为空") + private String username; + + @ApiModelProperty("昵称") + @NotBlank(message = "昵称不能为空") + private String nickname; + + @Pattern(regexp = "^1(3\\d|4[5-9]|5[0-35-9]|6[2567]|7[0-8]|8\\d|9[0-35-9])\\d{8}$", message = "{phone.valid}") + private String mobile; + + @ApiModelProperty("性别") + private Integer gender; + + @ApiModelProperty("用户头像") + private String avatar; + + @ApiModelProperty("邮箱") + private String email; + + @ApiModelProperty("用户状态(1:正常;0:禁用)") + private Integer status; + + @ApiModelProperty("部门ID") + private Long deptId; + + @ApiModelProperty("角色ID集合") + @NotEmpty(message = "用户角色不能为空") + private List roleIds; + +} diff --git a/src/main/java/com/youlai/system/pojo/po/RoutePO.java b/src/main/java/com/youlai/system/pojo/po/RoutePO.java new file mode 100644 index 00000000..70c99efc --- /dev/null +++ b/src/main/java/com/youlai/system/pojo/po/RoutePO.java @@ -0,0 +1,78 @@ +package com.youlai.system.pojo.po; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.youlai.system.common.base.BaseEntity; +import com.youlai.system.common.enums.MenuTypeEnum; +import lombok.Data; + +import java.util.List; + +/** + * 路由 + */ +@Data +public class RoutePO { + /** + * + */ + @TableId(type = IdType.AUTO) + private Long id; + + /** + * 父菜单ID + */ + private Long parentId; + + /** + * 菜单名称 + */ + private String name; + + /** + * 菜单类型(1-菜单;2-目录;3-外链;4-按钮权限) + */ + private MenuTypeEnum type; + + /** + * 路由路径(浏览器地址栏路径) + */ + private String path; + + /** + * 组件路径(vue页面完整路径,省略.vue后缀) + */ + private String component; + + /** + * 权限标识 + */ + private String perm; + + /** + * 显示状态(1:显示;0:隐藏) + */ + private Integer visible; + + /** + * 排序 + */ + private Integer sort; + + /** + * 菜单图标 + */ + private String icon; + + /** + * 外链路径 + */ + private String redirectUrl; + + /** + * 拥有路由的权限 + */ + private List roles; + +} \ No newline at end of file diff --git a/src/main/java/com/youlai/system/pojo/po/UserAuthInfo.java b/src/main/java/com/youlai/system/pojo/po/UserAuthInfo.java new file mode 100644 index 00000000..f8dcda3e --- /dev/null +++ b/src/main/java/com/youlai/system/pojo/po/UserAuthInfo.java @@ -0,0 +1,33 @@ +package com.youlai.system.pojo.po; + +import lombok.Data; + +import java.util.Set; + +/** + * 用户认证信息 + * + * @author haoxr + * @date 2022/10/22 + * + */ +@Data +public class UserAuthInfo { + + private Long userId; + + private String username; + + private String nickname; + + private Long deptId; + + private String password; + + private Integer status; + + private Set roles; + + private Set perms; + +} diff --git a/src/main/java/com/youlai/system/pojo/po/UserFormPO.java b/src/main/java/com/youlai/system/pojo/po/UserFormPO.java new file mode 100644 index 00000000..5e53f524 --- /dev/null +++ b/src/main/java/com/youlai/system/pojo/po/UserFormPO.java @@ -0,0 +1,66 @@ +package com.youlai.system.pojo.po; + +import lombok.Data; + +import java.util.List; + +/** + * user表单持久化对象 + * + * @author haoxr + * @date 2022/6/10 + */ +@Data +public class UserFormPO { + + /** + * 用户ID + */ + private Long id; + + /** + * 用户名 + */ + private String username; + + /** + * 用户昵称 + */ + private String nickname; + + /** + * 手机号 + */ + private String mobile; + + /** + * 性别(1:男;2:女) + */ + private Integer gender; + + /** + * 用户头像 + */ + private String avatar; + + /** + * 用户邮箱 + */ + private String email; + + /** + * 状态(1:启用;0:禁用) + */ + private Integer status; + + /** + * 部门ID + */ + private Long deptId; + + /** + * 角色ID集合 + */ + private List roleIds; + +} diff --git a/src/main/java/com/youlai/system/pojo/po/UserPO.java b/src/main/java/com/youlai/system/pojo/po/UserPO.java new file mode 100644 index 00000000..9e80a9b1 --- /dev/null +++ b/src/main/java/com/youlai/system/pojo/po/UserPO.java @@ -0,0 +1,72 @@ +package com.youlai.system.pojo.po; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; + +import java.util.Date; + +/** + * 用户持久化对象 + * + * @author haoxr + * @date 2022/6/10 + */ +@Data +public class UserPO { + + /** + * 用户ID + */ + private Long id; + + /** + * 账户名 + */ + private String username; + + /** + * 昵称 + */ + private String nickname; + + /** + * 手机号 + */ + private String mobile; + + /** + * 性别(1->男;2->女) + */ + private Integer gender; + + /** + * 头像URL + */ + private String avatar; + + /** + * 邮箱 + */ + private String email; + + /** + * 状态: 1->启用;0->禁用 + */ + private Integer status; + + /** + * 部门名称 + */ + private String deptName; + + /** + * 角色名称,多个使用英文逗号(,)分割 + */ + private String roleNames; + + /** + * 创建时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd") + private Date createTime; +} diff --git a/src/main/java/com/youlai/system/pojo/query/DeptQuery.java b/src/main/java/com/youlai/system/pojo/query/DeptQuery.java new file mode 100644 index 00000000..fef4c268 --- /dev/null +++ b/src/main/java/com/youlai/system/pojo/query/DeptQuery.java @@ -0,0 +1,23 @@ +package com.youlai.system.pojo.query; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 部门分页查询对象 + * + * @author haoxr + * @date 2022/6/11 + */ +@ApiModel("部门分页查询对象") +@Data +public class DeptQuery { + + @ApiModelProperty("关键字(部门名称)") + private String keywords; + + @ApiModelProperty("状态(1->正常;0->禁用)") + private Integer status; + +} diff --git a/src/main/java/com/youlai/system/pojo/query/DictItemPageQuery.java b/src/main/java/com/youlai/system/pojo/query/DictItemPageQuery.java new file mode 100644 index 00000000..a43b72ec --- /dev/null +++ b/src/main/java/com/youlai/system/pojo/query/DictItemPageQuery.java @@ -0,0 +1,18 @@ +package com.youlai.system.pojo.query; + + +import com.youlai.system.common.base.BasePageQuery; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@ApiModel("字典数据项分页查询对象") +@Data +public class DictItemPageQuery extends BasePageQuery { + + @ApiModelProperty("关键字(字典项名称)") + private String keywords; + + @ApiModelProperty("字典类型编码") + private String typeCode; +} diff --git a/src/main/java/com/youlai/system/pojo/query/DictTypePageQuery.java b/src/main/java/com/youlai/system/pojo/query/DictTypePageQuery.java new file mode 100644 index 00000000..6e6a2973 --- /dev/null +++ b/src/main/java/com/youlai/system/pojo/query/DictTypePageQuery.java @@ -0,0 +1,16 @@ +package com.youlai.system.pojo.query; + + +import com.youlai.system.common.base.BasePageQuery; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@ApiModel("字典类型分页查询对象") +@Data +public class DictTypePageQuery extends BasePageQuery { + + @ApiModelProperty("关键字(类型名称/类型编码)") + private String keywords; + +} diff --git a/src/main/java/com/youlai/system/pojo/query/PermPageQuery.java b/src/main/java/com/youlai/system/pojo/query/PermPageQuery.java new file mode 100644 index 00000000..4ad84f53 --- /dev/null +++ b/src/main/java/com/youlai/system/pojo/query/PermPageQuery.java @@ -0,0 +1,24 @@ +package com.youlai.system.pojo.query; + +import com.youlai.system.common.base.BasePageQuery; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 权限分页查询对象 + * + * @author haoxr + * @date 2022/1/14 22:22 + */ +@Data +@ApiModel +public class PermPageQuery extends BasePageQuery { + + @ApiModelProperty("权限名称") + private String name; + + @ApiModelProperty("菜单ID") + private Long menuId; + +} diff --git a/src/main/java/com/youlai/system/pojo/query/RolePageQuery.java b/src/main/java/com/youlai/system/pojo/query/RolePageQuery.java new file mode 100644 index 00000000..04c1edfb --- /dev/null +++ b/src/main/java/com/youlai/system/pojo/query/RolePageQuery.java @@ -0,0 +1,19 @@ +package com.youlai.system.pojo.query; + +import com.youlai.system.common.base.BasePageQuery; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 角色分页查询实体 + * + * @author haoxr + * @date 2022/6/3 + * + */ +@Data +public class RolePageQuery extends BasePageQuery { + + @ApiModelProperty("关键字(角色名称/角色编码)") + private String keywords; +} diff --git a/src/main/java/com/youlai/system/pojo/query/UserPageQuery.java b/src/main/java/com/youlai/system/pojo/query/UserPageQuery.java new file mode 100644 index 00000000..3dc213c2 --- /dev/null +++ b/src/main/java/com/youlai/system/pojo/query/UserPageQuery.java @@ -0,0 +1,27 @@ +package com.youlai.system.pojo.query; + +import com.youlai.system.common.base.BasePageQuery; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 用户分页查询对象 + * + * @author haoxr + * @date 2022/1/14 + */ +@ApiModel +@Data +public class UserPageQuery extends BasePageQuery { + + @ApiModelProperty("关键字(用户名/昵称/手机号)") + private String keywords; + + @ApiModelProperty("用户状态") + private Integer status; + + @ApiModelProperty("部门ID") + private Long deptId; + +} diff --git a/src/main/java/com/youlai/system/pojo/vo/dept/DeptDetailVO.java b/src/main/java/com/youlai/system/pojo/vo/dept/DeptDetailVO.java new file mode 100644 index 00000000..05cfce2c --- /dev/null +++ b/src/main/java/com/youlai/system/pojo/vo/dept/DeptDetailVO.java @@ -0,0 +1,27 @@ +package com.youlai.system.pojo.vo.dept; + +import com.youlai.system.common.base.BaseEntity; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@ApiModel("部门详情对象") +@Data +public class DeptDetailVO extends BaseEntity { + + @ApiModelProperty("部门ID(编辑必填)") + private Long id; + + @ApiModelProperty("部门名称") + private String name; + + @ApiModelProperty("父部门ID") + private Long parentId; + + @ApiModelProperty("状态") + private Integer status; + + @ApiModelProperty("排序") + private Integer sort; + +} diff --git a/src/main/java/com/youlai/system/pojo/vo/dept/DeptVO.java b/src/main/java/com/youlai/system/pojo/vo/dept/DeptVO.java new file mode 100644 index 00000000..571a8dd7 --- /dev/null +++ b/src/main/java/com/youlai/system/pojo/vo/dept/DeptVO.java @@ -0,0 +1,29 @@ +package com.youlai.system.pojo.vo.dept; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.List; + +@Data +public class DeptVO { + + private Long id; + + private Long parentId; + + private String name; + + private Integer sort; + + private Integer status; + + private List children; + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm") + private LocalDateTime createTime; + @JsonFormat(pattern = "yyyy-MM-dd HH:mm") + private LocalDateTime updateTime; + +} diff --git a/src/main/java/com/youlai/system/pojo/vo/dict/DictItemPageVO.java b/src/main/java/com/youlai/system/pojo/vo/dict/DictItemPageVO.java new file mode 100644 index 00000000..a404cfc2 --- /dev/null +++ b/src/main/java/com/youlai/system/pojo/vo/dict/DictItemPageVO.java @@ -0,0 +1,24 @@ +package com.youlai.system.pojo.vo.dict; + + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@ApiModel("字典数据项分页对象") +@Data +public class DictItemPageVO { + + @ApiModelProperty("数据项ID") + private Long id; + + @ApiModelProperty("数据项名称") + private String name; + + @ApiModelProperty("值") + private String value; + + @ApiModelProperty("类型状态:1->启用;0->禁用") + private Integer status; + +} diff --git a/src/main/java/com/youlai/system/pojo/vo/dict/DictTypePageVO.java b/src/main/java/com/youlai/system/pojo/vo/dict/DictTypePageVO.java new file mode 100644 index 00000000..220354ad --- /dev/null +++ b/src/main/java/com/youlai/system/pojo/vo/dict/DictTypePageVO.java @@ -0,0 +1,24 @@ +package com.youlai.system.pojo.vo.dict; + + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@ApiModel("字典类型") +@Data +public class DictTypePageVO { + + @ApiModelProperty("字典类型ID") + private Long id; + + @ApiModelProperty("类型名称") + private String name; + + @ApiModelProperty("类型编码") + private String code; + + @ApiModelProperty("类型状态:1->启用;0->禁用") + private Integer status; + +} diff --git a/src/main/java/com/youlai/system/pojo/vo/menu/MenuDetailVO.java b/src/main/java/com/youlai/system/pojo/vo/menu/MenuDetailVO.java new file mode 100644 index 00000000..7e76877b --- /dev/null +++ b/src/main/java/com/youlai/system/pojo/vo/menu/MenuDetailVO.java @@ -0,0 +1,30 @@ +package com.youlai.system.pojo.vo.menu; + +import lombok.Data; + +@Data +public class MenuDetailVO { + + private Long id; + + private Long parentId; + + private String name; + + private String icon; + + private String routeName; + + private String routePath; + + private String component; + + private Integer sort; + + private Integer visible; + + private String redirect; + + private Integer type; + +} diff --git a/src/main/java/com/youlai/system/pojo/vo/menu/MenuVO.java b/src/main/java/com/youlai/system/pojo/vo/menu/MenuVO.java new file mode 100644 index 00000000..0fb5b71e --- /dev/null +++ b/src/main/java/com/youlai/system/pojo/vo/menu/MenuVO.java @@ -0,0 +1,41 @@ +package com.youlai.system.pojo.vo.menu; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.youlai.system.common.enums.MenuTypeEnum; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +@ApiModel("菜单视图对象") +@Data +public class MenuVO { + + private Long id; + + private Long parentId; + + private String name; + + private String icon; + + private String routeName; + + private String routePath; + + private String component; + + private Integer sort; + + private Integer visible; + + private String redirect; + + @ApiModelProperty("菜单类型") + private MenuTypeEnum type; + + @JsonInclude(value = JsonInclude.Include.NON_NULL) + private List children; + +} diff --git a/src/main/java/com/youlai/system/pojo/vo/menu/ResourceVO.java b/src/main/java/com/youlai/system/pojo/vo/menu/ResourceVO.java new file mode 100644 index 00000000..c7c869c5 --- /dev/null +++ b/src/main/java/com/youlai/system/pojo/vo/menu/ResourceVO.java @@ -0,0 +1,26 @@ +package com.youlai.system.pojo.vo.menu; + +import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +@ApiModel("资源(菜单+权限)视图对象") +@Data +public class ResourceVO { + + @ApiModelProperty("选项的值") + private Long value; + + @ApiModelProperty("选项的标签") + private String label; + + @ApiModelProperty("子菜单") + @JsonInclude(value = JsonInclude.Include.NON_EMPTY) + private List children; + + + +} diff --git a/src/main/java/com/youlai/system/pojo/vo/menu/RouteVO.java b/src/main/java/com/youlai/system/pojo/vo/menu/RouteVO.java new file mode 100644 index 00000000..233f30f6 --- /dev/null +++ b/src/main/java/com/youlai/system/pojo/vo/menu/RouteVO.java @@ -0,0 +1,51 @@ +package com.youlai.system.pojo.vo.menu; + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.Data; + +import java.util.List; + +/** + * 菜单路由视图对象 + * + * @author haoxr + * @date 2020/11/28 + */ +@Data +@JsonInclude(JsonInclude.Include.NON_EMPTY) +public class RouteVO { + + private String path; + + private String component; + + private String redirect; + + private String name; + + private Meta meta; + + @Data + public static class Meta { + + private String title; + + private String icon; + + private Boolean hidden; + + /** + * 如果设置为 true,目录没有子节点也会显示 + */ + private Boolean alwaysShow; + + private List roles; + + /** + * 页面缓存开启状态 + */ + private Boolean keepAlive; + } + + private List children; +} diff --git a/src/main/java/com/youlai/system/pojo/vo/perm/PermPageVO.java b/src/main/java/com/youlai/system/pojo/vo/perm/PermPageVO.java new file mode 100644 index 00000000..d46ec5e2 --- /dev/null +++ b/src/main/java/com/youlai/system/pojo/vo/perm/PermPageVO.java @@ -0,0 +1,35 @@ +package com.youlai.system.pojo.vo.perm; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * 权限视图对象 + * + * @author haoxr + * @date 2021/10/30 10:54 + */ +@ApiModel("权限视图对象") +@Data +public class PermPageVO { + + @ApiModelProperty("权限ID") + private Long id; + + @ApiModelProperty("权限名称") + private String name; + + @ApiModelProperty("URL权限标识-服务名称") + private String serviceName; + + @ApiModelProperty("URL权限标识-请求标识") + private String requestMethod; + + @ApiModelProperty("URL权限标识-请求方式") + private String requestPath; + + @ApiModelProperty("按钮权限标识") + private String btnPerm; + +} diff --git a/src/main/java/com/youlai/system/pojo/vo/role/RolePageVO.java b/src/main/java/com/youlai/system/pojo/vo/role/RolePageVO.java new file mode 100644 index 00000000..c5b9123f --- /dev/null +++ b/src/main/java/com/youlai/system/pojo/vo/role/RolePageVO.java @@ -0,0 +1,34 @@ +package com.youlai.system.pojo.vo.role; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.time.LocalDateTime; + +@ApiModel("角色分页视图对象") +@Data +public class RolePageVO { + + @ApiModelProperty("角色ID") + private Long id; + + @ApiModelProperty("角色名称") + private String name; + + @ApiModelProperty("角色编码") + private String code; + + @ApiModelProperty("角色状态") + private Integer status; + + @ApiModelProperty("排序") + private Integer sort; + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime createTime; + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime updateTime; +} diff --git a/src/main/java/com/youlai/system/pojo/vo/user/UserDetailVO.java b/src/main/java/com/youlai/system/pojo/vo/user/UserDetailVO.java new file mode 100644 index 00000000..b3f2ca96 --- /dev/null +++ b/src/main/java/com/youlai/system/pojo/vo/user/UserDetailVO.java @@ -0,0 +1,49 @@ +package com.youlai.system.pojo.vo.user; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +/** + * 用户表详情视图对象 + * + * @author haoxr + * @date 2022/8/25 + */ +@ApiModel +@Data +public class UserDetailVO { + + @ApiModelProperty("用户ID") + private Long id; + + @ApiModelProperty("用户名") + private String username; + + @ApiModelProperty("昵称") + private String nickname; + + @ApiModelProperty("") + private String mobile; + + @ApiModelProperty("性别") + private Integer gender; + + @ApiModelProperty("用户头像") + private String avatar; + + @ApiModelProperty("邮箱") + private String email; + + @ApiModelProperty("用户状态(1:正常;0:禁用)") + private Integer status; + + @ApiModelProperty("部门ID") + private Long deptId; + + @ApiModelProperty("角色ID集合") + private List roleIds; + +} diff --git a/src/main/java/com/youlai/system/pojo/vo/user/UserExportVO.java b/src/main/java/com/youlai/system/pojo/vo/user/UserExportVO.java new file mode 100644 index 00000000..e112a19f --- /dev/null +++ b/src/main/java/com/youlai/system/pojo/vo/user/UserExportVO.java @@ -0,0 +1,44 @@ +package com.youlai.system.pojo.vo.user; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.format.DateTimeFormat; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 用户导出视图对象 + * + * @author haoxr + * @date 2022/4/11 8:46 + */ + +@Data +@ColumnWidth(20) +public class UserExportVO { + + @ExcelProperty(value = "用户名") + private String username; + + @ExcelProperty(value = "用户昵称") + private String nickname; + + @ExcelProperty(value = "部门") + private String deptName; + + @ExcelProperty(value = "性别") + private String gender; + + @ExcelProperty(value = "手机号码") + private String mobile; + + @ExcelProperty(value = "邮箱") + private String email; + + @ExcelProperty(value = "创建时间") + @DateTimeFormat("yyyy/MM/dd HH:mm:ss") + private LocalDateTime createTime; + + +} diff --git a/src/main/java/com/youlai/system/pojo/vo/user/UserLoginVO.java b/src/main/java/com/youlai/system/pojo/vo/user/UserLoginVO.java new file mode 100644 index 00000000..bf8d25c0 --- /dev/null +++ b/src/main/java/com/youlai/system/pojo/vo/user/UserLoginVO.java @@ -0,0 +1,35 @@ +package com.youlai.system.pojo.vo.user; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; +import java.util.Set; + +/** + * 用户登录视图对象 + * + * @author haoxr + * @date 2022/1/14 + */ +@ApiModel("当前登录用户视图对象") +@Data +public class UserLoginVO { + + @ApiModelProperty("用户ID") + private Long userId; + + @ApiModelProperty("用户昵称") + private String nickname; + + @ApiModelProperty("头像地址") + private String avatar; + + @ApiModelProperty("用户角色编码集合") + private Set roles; + + @ApiModelProperty("用户权限标识集合") + private Set perms; + +} diff --git a/src/main/java/com/youlai/system/pojo/vo/user/UserVO.java b/src/main/java/com/youlai/system/pojo/vo/user/UserVO.java new file mode 100644 index 00000000..c23f8d58 --- /dev/null +++ b/src/main/java/com/youlai/system/pojo/vo/user/UserVO.java @@ -0,0 +1,54 @@ +package com.youlai.system.pojo.vo.user; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.Date; + +/** + * 用户分页视图对象 + * + * @author haoxr + * @date 2022/1/15 9:41 + */ +@ApiModel("用户分页视图对象") +@Data +public class UserVO { + + @ApiModelProperty("用户ID") + private Long id; + + @ApiModelProperty("用户名") + private String username; + + @ApiModelProperty("用户昵称") + private String nickname; + + @ApiModelProperty("手机号") + private String mobile; + + @ApiModelProperty("性别") + private String genderLabel; + + @ApiModelProperty("用户头像地址") + private String avatar; + + @ApiModelProperty("用户邮箱") + private String email; + + @ApiModelProperty("用户状态(1:启用;0:禁用)") + private Integer status; + + @ApiModelProperty("部门名称") + private String deptName; + + @ApiModelProperty("角色名称,多个使用英文逗号(,)分割") + private String roleNames; + + @ApiModelProperty("创建时间") + @JsonFormat(pattern = "yyyy-MM-dd") + private Date createTime; + +} diff --git a/src/main/java/com/youlai/system/security/SecurityConfig.java b/src/main/java/com/youlai/system/security/SecurityConfig.java new file mode 100644 index 00000000..4aba07b1 --- /dev/null +++ b/src/main/java/com/youlai/system/security/SecurityConfig.java @@ -0,0 +1,77 @@ +package com.youlai.system.security; + +import com.youlai.system.security.jwt.JwtAuthenticationFilter; +import com.youlai.system.security.jwt.JwtTokenManager; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +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.configuration.WebSecurityCustomizer; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; + +/** + * @author haoxr + */ +@Configuration +@EnableWebSecurity +@EnableGlobalMethodSecurity(prePostEnabled = true) +public class SecurityConfig { + + private final JwtTokenManager jwtTokenManager; + + public SecurityConfig( + JwtTokenManager jwtTokenManager + ) { + this.jwtTokenManager = jwtTokenManager; + } + + + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + http + .csrf().disable() + .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) + .and() + .authorizeHttpRequests(auth -> auth.antMatchers("/**").permitAll() + .anyRequest().authenticated()); + + // disable cache + http.headers().cacheControl(); + + http.addFilterBefore(new JwtAuthenticationFilter(jwtTokenManager), UsernamePasswordAuthenticationFilter.class); + + return http.build(); + } + + @Bean + public WebSecurityCustomizer webSecurityCustomizer() { + return (web) -> web.ignoring() + .antMatchers("/api/v1/auth/login","/webjars/**", "/doc.html", "/swagger-resources/**", "/v3/api-docs"); + } + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + + /** + * 无法直接注入 AuthenticationManager + * + * @param authenticationConfiguration + * @return + * @throws Exception + */ + @Bean + public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception { + return authenticationConfiguration.getAuthenticationManager(); + } + +} diff --git a/src/main/java/com/youlai/system/security/exception/MyAccessDeniedHandler.java b/src/main/java/com/youlai/system/security/exception/MyAccessDeniedHandler.java new file mode 100644 index 00000000..e2264925 --- /dev/null +++ b/src/main/java/com/youlai/system/security/exception/MyAccessDeniedHandler.java @@ -0,0 +1,22 @@ +package com.youlai.system.security.exception; + +import com.youlai.system.common.result.ResultCode; +import com.youlai.system.util.ResponseUtils; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.web.access.AccessDeniedHandler; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * Spring Security访问异常处理器 + * + * @author haoxr + * @date 2022/10/18 + */ +public class MyAccessDeniedHandler implements AccessDeniedHandler { + @Override + public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) { + ResponseUtils.writeErrMsg(response, ResultCode.TOKEN_ACCESS_FORBIDDEN); + } +} diff --git a/src/main/java/com/youlai/system/security/exception/MyAuthenticationEntryPoint.java b/src/main/java/com/youlai/system/security/exception/MyAuthenticationEntryPoint.java new file mode 100644 index 00000000..2e57477a --- /dev/null +++ b/src/main/java/com/youlai/system/security/exception/MyAuthenticationEntryPoint.java @@ -0,0 +1,24 @@ +package com.youlai.system.security.exception; + +import com.youlai.system.common.result.ResultCode; +import com.youlai.system.util.ResponseUtils; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.AuthenticationEntryPoint; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * 认证异常处理 + * + * @author haoxr + * @date 2022/10/18 + */ +public class MyAuthenticationEntryPoint implements AuthenticationEntryPoint { + @Override + public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { + ResponseUtils.writeErrMsg(response, ResultCode.TOKEN_INVALID_OR_EXPIRED); + } +} diff --git a/src/main/java/com/youlai/system/security/jwt/JwtAuthenticationFilter.java b/src/main/java/com/youlai/system/security/jwt/JwtAuthenticationFilter.java new file mode 100644 index 00000000..6e9672d7 --- /dev/null +++ b/src/main/java/com/youlai/system/security/jwt/JwtAuthenticationFilter.java @@ -0,0 +1,57 @@ +package com.youlai.system.security.jwt; + +import cn.hutool.core.util.StrUtil; +import com.youlai.system.common.result.ResultCode; +import com.youlai.system.util.ResponseUtils; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.web.filter.OncePerRequestFilter; + +import javax.servlet.FilterChain; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * jwt auth token filter. + * + * @author haoxr + */ +public class JwtAuthenticationFilter extends OncePerRequestFilter { + + private static final String TOKEN_PREFIX = "Bearer "; + + private final JwtTokenManager tokenManager; + + public JwtAuthenticationFilter(JwtTokenManager tokenManager) { + this.tokenManager = tokenManager; + } + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) { + + String jwt = resolveToken(request); + if (StrUtil.isNotBlank(jwt) && SecurityContextHolder.getContext().getAuthentication() == null) { + try { + this.tokenManager.validateToken(jwt); + Authentication authentication = this.tokenManager.getAuthentication(jwt); + SecurityContextHolder.getContext().setAuthentication(authentication); + chain.doFilter(request, response); + }catch (Exception e){ + ResponseUtils.writeErrMsg(response, ResultCode.TOKEN_INVALID_OR_EXPIRED); + } + }else{ + ResponseUtils.writeErrMsg(response, ResultCode.TOKEN_INVALID_OR_EXPIRED); + } + } + + /** + * Get token from header. + */ + private String resolveToken(HttpServletRequest request) { + String bearerToken = request.getHeader("Authorization"); + if (StrUtil.isNotBlank(bearerToken) && bearerToken.startsWith(TOKEN_PREFIX)) { + return bearerToken.substring(TOKEN_PREFIX.length()); + } + return null; + } +} diff --git a/src/main/java/com/youlai/system/security/jwt/JwtTokenManager.java b/src/main/java/com/youlai/system/security/jwt/JwtTokenManager.java new file mode 100644 index 00000000..597ca923 --- /dev/null +++ b/src/main/java/com/youlai/system/security/jwt/JwtTokenManager.java @@ -0,0 +1,179 @@ +/* + * Copyright 1999-2021 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.youlai.system.security.jwt; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.StrUtil; +import com.youlai.system.security.userdetails.SysUserDetails; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.JwtParser; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import io.jsonwebtoken.io.Decoders; +import io.jsonwebtoken.io.DecodingException; +import io.jsonwebtoken.security.Keys; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.nio.charset.StandardCharsets; +import java.util.Date; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + + +/** + * JWT token manager. + * + * @author haoxr + * @date 2022/10/22 + */ +@Component +public class JwtTokenManager { + + /** + * secret key. + */ + @Value("${auth.token.secret_key}") + private String secretKey; + + /** + * Token validity time(seconds). + */ + @Value("${auth.token.token_validity}") + private long tokenValidity; + + /** + * secret key byte array. + */ + private byte[] secretKeyBytes; + + private JwtParser jwtParser; + + @Resource + private RedisTemplate redisTemplate; + + /** + * Create token. + * + * @param authentication auth info + * @return token + */ + public String createToken(Authentication authentication) { + + long now = System.currentTimeMillis(); + + Date validity; + + validity = new Date(now + tokenValidity * 1000L); + + Claims claims = Jwts.claims().setSubject(authentication.getName()); + SysUserDetails userDetails = (SysUserDetails) authentication.getPrincipal(); + claims.put("userId", userDetails.getUserId()); + claims.put("username", claims.getSubject()); + Set roles = userDetails.getAuthorities().stream() + .map(item -> item.getAuthority()).collect(Collectors.toSet()); + Set authorities = userDetails.getPerms(); + authorities.addAll(roles); + redisTemplate.opsForValue().set("USER_PERMS:" + userDetails.getUserId(), authorities); + return Jwts.builder().setClaims(claims).setExpiration(validity) + .signWith(SignatureAlgorithm.HS256, Keys.hmacShaKeyFor(this.getSecretKeyBytes())).compact(); + } + + /** + * Create token. + * + * @param userName auth info + * @return token + */ + public String createToken(String userName) { + + long now = System.currentTimeMillis(); + + Date validity; + + validity = new Date(now + tokenValidity * 1000L); + + Claims claims = Jwts.claims().setSubject(userName); + + return Jwts.builder().setClaims(claims).setExpiration(validity) + .signWith(SignatureAlgorithm.HS256, Keys.hmacShaKeyFor(this.getSecretKeyBytes())).compact(); + } + + /** + * Get auth Info. + * + * @param token token + * @return auth info + */ + public Authentication getAuthentication(String token) { + if (jwtParser == null) { + jwtParser = Jwts.parserBuilder().setSigningKey(this.getSecretKeyBytes()).build(); + } + Claims claims = jwtParser.parseClaimsJws(token).getBody(); + + List authorities = AuthorityUtils + .commaSeparatedStringToAuthorityList((String) claims.get("authorities")); + + SysUserDetails principal = new SysUserDetails(); + principal.setUserId(Convert.toLong(claims.get("userId"))); + principal.setUsername(Convert.toStr(claims.get("username"))); + + // 权限数据过多放置在redis + Set perms = (Set) redisTemplate.opsForValue().get("USER_PERMS:" + claims.get("userId")); + if (CollectionUtil.isNotEmpty(perms)) { + List permAuthorities = perms.stream() + .map(perm -> new SimpleGrantedAuthority(perm)) + .collect(Collectors.toList()); + authorities.addAll(permAuthorities); + } + return new UsernamePasswordAuthenticationToken(principal, "", authorities); + } + + /** + * validate token. + * + * @param token token + */ + public void validateToken(String token) { + if (jwtParser == null) { + jwtParser = Jwts.parserBuilder().setSigningKey(this.getSecretKeyBytes()).build(); + } + jwtParser.parseClaimsJws(token); + } + + public byte[] getSecretKeyBytes() { + if (secretKeyBytes == null) { + try { + secretKeyBytes = Decoders.BASE64.decode(secretKey); + } catch (DecodingException e) { + secretKeyBytes = secretKey.getBytes(StandardCharsets.UTF_8); + } + + } + return secretKeyBytes; + } + +} diff --git a/src/main/java/com/youlai/system/security/userdetails/SysUserDetails.java b/src/main/java/com/youlai/system/security/userdetails/SysUserDetails.java new file mode 100644 index 00000000..35bfee79 --- /dev/null +++ b/src/main/java/com/youlai/system/security/userdetails/SysUserDetails.java @@ -0,0 +1,99 @@ +package com.youlai.system.security.userdetails; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.youlai.system.pojo.po.UserAuthInfo; +import lombok.Data; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import java.util.Collection; +import java.util.Collections; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * Spring Security + * @author haoxr + */ +@Data +public class SysUserDetails implements UserDetails { + + private Long userId; + + private String username; + + private String password; + + private Boolean enabled; + + private Collection authorities; + + private String authorityStr; + + private Set perms; + + public SysUserDetails() { + + } + + public SysUserDetails(UserAuthInfo user) { + this.userId = user.getUserId(); + Set roles = user.getRoles(); + Set authorities; + if (CollectionUtil.isNotEmpty(roles)) { + authorities = roles.stream() + .map(role -> new SimpleGrantedAuthority("ROLE_" + role)) // 标识角色 + .collect(Collectors.toSet()); + } else { + authorities = Collections.EMPTY_SET; + } + this.authorities = authorities; + this.username = user.getUsername(); + this.password = user.getPassword(); + this.enabled = ObjectUtil.equal(user.getStatus(), 1); + this.perms=user.getPerms(); + } + + public Long getUserId() { + return this.userId; + } + + + @Override + public Collection getAuthorities() { + return this.authorities; + } + + @Override + public String getPassword() { + return this.password; + } + + @Override + public String getUsername() { + return this.username; + } + + @Override + public boolean isAccountNonExpired() { + return true; + } + + @Override + public boolean isAccountNonLocked() { + return true; + } + + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + @Override + public boolean isEnabled() { + return this.enabled; + } +} diff --git a/src/main/java/com/youlai/system/security/userdetails/SysUserDetailsServiceImpl.java b/src/main/java/com/youlai/system/security/userdetails/SysUserDetailsServiceImpl.java new file mode 100644 index 00000000..bd5f1f4c --- /dev/null +++ b/src/main/java/com/youlai/system/security/userdetails/SysUserDetailsServiceImpl.java @@ -0,0 +1,29 @@ +package com.youlai.system.security.userdetails; + +import com.youlai.system.pojo.po.UserAuthInfo; +import com.youlai.system.service.SysUserService; +import lombok.RequiredArgsConstructor; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; + +/** + * @author haoxr + */ +@Service +@RequiredArgsConstructor +public class SysUserDetailsServiceImpl implements UserDetailsService { + + private final SysUserService sysUserService; + + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + + UserAuthInfo userAuthInfo = sysUserService.getUserAuthInfo(username); + if(userAuthInfo==null){ + throw new UsernameNotFoundException(username); + } + return new SysUserDetails(userAuthInfo); + } +} diff --git a/src/main/java/com/youlai/system/service/SysDeptService.java b/src/main/java/com/youlai/system/service/SysDeptService.java new file mode 100644 index 00000000..f5fa71c0 --- /dev/null +++ b/src/main/java/com/youlai/system/service/SysDeptService.java @@ -0,0 +1,65 @@ +package com.youlai.system.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.youlai.system.common.model.Option; +import com.youlai.system.pojo.entity.SysDept; +import com.youlai.system.pojo.form.DeptForm; +import com.youlai.system.pojo.query.DeptQuery; +import com.youlai.system.pojo.vo.dept.DeptVO; + +import java.util.List; + +/** + * 部门业务接口 + * + * @author haoxr + * @date 2021/8/22 + */ +public interface SysDeptService extends IService { + /** + * 部门列表 + * + * @return + */ + List listDepartments(DeptQuery queryParams); + + /** + * 部门树形下拉选项 + * + * @return + */ + List

+ * 超级管理员忽视任何权限判断 + * + * @return + */ + public static boolean isRoot() { + Set roles = getRoles(); + + if (roles.contains(SystemConstants.ROOT_ROLE_CODE)) { + return true; + } + return false; + } + + + /** + * 是否拥有权限判断 + *

+ * 适用业务判断(接口权限判断适用Spring Security 自带注解 PreAuthorize 判断即可 ) + * + * @return + */ + public static boolean hasPerm(String perm) { + + if (isRoot()) { + return true; + } + + Set perms = getPerms(); + + boolean hasPerm = perms.stream().anyMatch(item -> PatternMatchUtils.simpleMatch(perm, item)); + return hasPerm; + } + +} diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml new file mode 100644 index 00000000..52ba7890 --- /dev/null +++ b/src/main/resources/application-dev.yml @@ -0,0 +1,45 @@ +server: + port: 8989 + +spring: + datasource: + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://www.youlai.tech:3306/youlai_boot?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&allowMultiQueries=true + username: youlai + password: 123456 + redis: + database: 6 + host: www.youlai.tech + port: 6379 + password: 123456 + timeout: 10s + lettuce: + pool: + min-idle: 0 + max-idle: 8 + max-active: 8 + max-wait: -1ms + +mybatis-plus: + global-config: + db-config: + # 主键ID类型 + id-type: none + logic-delete-field: deleted + logic-delete-value: 1 + logic-not-delete-value: 0 + configuration: + # 驼峰下划线转换 + map-underscore-to-camel-case: true + # 这个配置会将执行的sql打印出来,在开发或测试的时候可以用 + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl + +# 认证配置 +auth: + token: + secret_key: SecretKey012345678901234567890123456789012345678901234567890123456789 + # token 有效期(单位:秒) + token_validity: 18000 + + diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml new file mode 100644 index 00000000..52ba7890 --- /dev/null +++ b/src/main/resources/application-prod.yml @@ -0,0 +1,45 @@ +server: + port: 8989 + +spring: + datasource: + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://www.youlai.tech:3306/youlai_boot?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&allowMultiQueries=true + username: youlai + password: 123456 + redis: + database: 6 + host: www.youlai.tech + port: 6379 + password: 123456 + timeout: 10s + lettuce: + pool: + min-idle: 0 + max-idle: 8 + max-active: 8 + max-wait: -1ms + +mybatis-plus: + global-config: + db-config: + # 主键ID类型 + id-type: none + logic-delete-field: deleted + logic-delete-value: 1 + logic-not-delete-value: 0 + configuration: + # 驼峰下划线转换 + map-underscore-to-camel-case: true + # 这个配置会将执行的sql打印出来,在开发或测试的时候可以用 + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl + +# 认证配置 +auth: + token: + secret_key: SecretKey012345678901234567890123456789012345678901234567890123456789 + # token 有效期(单位:秒) + token_validity: 18000 + + diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 00000000..7f594dbb --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,8 @@ +spring: + application: + name: youlai-boot + profiles: + active: dev + mvc: + pathmatch: + matching-strategy: ant_path_matcher \ No newline at end of file diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml new file mode 100644 index 00000000..a7dae9aa --- /dev/null +++ b/src/main/resources/logback-spring.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + true + + + DEBUG + + + ${CONSOLE_LOG_PATTERN} + UTF-8 + + + + + + + ${LOG_HOME}/log.log + + + %d{yyyy-MM-dd HH:mm:ss.SSS} -%5level ---[%15.15thread] %-40.40logger{39} : %msg%n%n + UTF-8 + + + + ${LOG_HOME}/%d{yyyy-MM-dd}.%i.log + + 10MB + + + 15 + + + INFO + ACCEPT + DENY + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/SysDeptMapper.xml b/src/main/resources/mapper/SysDeptMapper.xml new file mode 100644 index 00000000..0ccc55ea --- /dev/null +++ b/src/main/resources/mapper/SysDeptMapper.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + id,name,parent_id, + tree_path,sort,status, + deleted,create_time,update_time + + diff --git a/src/main/resources/mapper/SysDictItemMapper.xml b/src/main/resources/mapper/SysDictItemMapper.xml new file mode 100644 index 00000000..d20ef69b --- /dev/null +++ b/src/main/resources/mapper/SysDictItemMapper.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/src/main/resources/mapper/SysDictTypeMapper.xml b/src/main/resources/mapper/SysDictTypeMapper.xml new file mode 100644 index 00000000..73c159ee --- /dev/null +++ b/src/main/resources/mapper/SysDictTypeMapper.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + id,name,code, + status,remark,create_time, + update_time + + diff --git a/src/main/resources/mapper/SysMenuMapper.xml b/src/main/resources/mapper/SysMenuMapper.xml new file mode 100644 index 00000000..d2754c90 --- /dev/null +++ b/src/main/resources/mapper/SysMenuMapper.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/mapper/SysRoleMapper.xml b/src/main/resources/mapper/SysRoleMapper.xml new file mode 100644 index 00000000..ee5ba383 --- /dev/null +++ b/src/main/resources/mapper/SysRoleMapper.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + id,name,code, + sort,status,deleted, + create_time,update_time + + diff --git a/src/main/resources/mapper/SysRoleMenuMapper.xml b/src/main/resources/mapper/SysRoleMenuMapper.xml new file mode 100644 index 00000000..732bf312 --- /dev/null +++ b/src/main/resources/mapper/SysRoleMenuMapper.xml @@ -0,0 +1,24 @@ + + + + + + + diff --git a/src/main/resources/mapper/SysUserMapper.xml b/src/main/resources/mapper/SysUserMapper.xml new file mode 100644 index 00000000..908783dd --- /dev/null +++ b/src/main/resources/mapper/SysUserMapper.xml @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/mapper/SysUserRoleMapper.xml b/src/main/resources/mapper/SysUserRoleMapper.xml new file mode 100644 index 00000000..028eb449 --- /dev/null +++ b/src/main/resources/mapper/SysUserRoleMapper.xml @@ -0,0 +1,16 @@ + + + + + + +