完成对Redis的构建及邮件登陆的操作,晚上功能组建,进行补丁修正
This commit is contained in:
parent
4690a28ab0
commit
d1415e89bb
37
.gitignore
vendored
37
.gitignore
vendored
|
@ -1,37 +0,0 @@
|
||||||
HELP.md
|
|
||||||
target/
|
|
||||||
!.mvn/wrapper/maven-wrapper.jar
|
|
||||||
!**/src/main/**/target/
|
|
||||||
!**/src/test/**/target/
|
|
||||||
|
|
||||||
### STS ###
|
|
||||||
.apt_generated
|
|
||||||
.classpath
|
|
||||||
.factorypath
|
|
||||||
.project
|
|
||||||
.settings
|
|
||||||
.springBeans
|
|
||||||
.sts4-cache
|
|
||||||
|
|
||||||
### IntelliJ IDEA ###
|
|
||||||
.idea
|
|
||||||
*.iws
|
|
||||||
*.iml
|
|
||||||
*.ipr
|
|
||||||
|
|
||||||
### NetBeans ###
|
|
||||||
/nbproject/private/
|
|
||||||
/nbbuild/
|
|
||||||
/dist/
|
|
||||||
/nbdist/
|
|
||||||
/.nb-gradle/
|
|
||||||
build/
|
|
||||||
!**/src/main/**/build/
|
|
||||||
!**/src/test/**/build/
|
|
||||||
|
|
||||||
### VS Code ###
|
|
||||||
.vscode/
|
|
||||||
|
|
||||||
### 自定义 ###
|
|
||||||
*.pdf
|
|
||||||
/src/main/resources/application-dev.yml
|
|
BIN
.mvn/wrapper/maven-wrapper.jar
vendored
BIN
.mvn/wrapper/maven-wrapper.jar
vendored
Binary file not shown.
2
.mvn/wrapper/maven-wrapper.properties
vendored
2
.mvn/wrapper/maven-wrapper.properties
vendored
|
@ -1,2 +0,0 @@
|
||||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip
|
|
||||||
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar
|
|
|
@ -1,83 +0,0 @@
|
||||||
# OrganizeInternalOA Config表详细内容设计
|
|
||||||
|
|
||||||
<div align=right>Author: 筱锋xiao_lfeng | Version: 1.1.0</div>
|
|
||||||
|
|
||||||
## oa_config 数据表
|
|
||||||
|
|
||||||
### 数据表结构
|
|
||||||
|
|
||||||
|
|
||||||
| 序号 | 名称 | 描述 | 类型 | 键 | 为空 | 额外 | 默认值 |
|
|
||||||
| :--: | :----------: | :--------: | :-------------: | :--: | :--: | :---------------: | :---------------: |
|
|
||||||
| 1 | `id` | 主键 | bigint unsigned | PRI | NO | auto_increment | |
|
|
||||||
| 2 | `value` | 调用关键字 | varchar(50) | UNI | NO | | |
|
|
||||||
| 3 | `data` | json数据 | json | | YES | | |
|
|
||||||
| 4 | `created_at` | 创建时间 | timestamp | | NO | DEFAULT_GENERATED | CURRENT_TIMESTAMP |
|
|
||||||
| 5 | `updated_at` | 修改时间 | timestamp | | YES | | |
|
|
||||||
|
|
||||||
|
|
||||||
### 各功能内容解释
|
|
||||||
|
|
||||||
1. `id` : 主键,构建索引所用
|
|
||||||
2. `value` : 构建索引,用于索引字符串内容,方便对 `data` 的获取
|
|
||||||
3. `data` : 输出的 ‘json’ 数据(重要)
|
|
||||||
4. `created_at` : 创建时间
|
|
||||||
5. `updated_at` : 修改时间
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## 说明
|
|
||||||
|
|
||||||
> 在这张数据表中,为存储相关配置信息,例如前端需要展示的轮播图、展览业、合作厂商列表、优秀成员列表等等,为了方便开发以及后续维护不需要进行额外进行对表的设计(对于新的一个前端展示功能模块就要新建一张表,显得麻烦),故将所有的内容压缩到这张表,需要展示的内容已结构化 json 数据存储到 `data` 字段。下面是内容举例。
|
|
||||||
|
|
||||||
假设我现在有一个config表
|
|
||||||
id value data
|
|
||||||
|
|
||||||
然后我有两个前端模块要动态(可修改)展示,一个是团队信息展示,另外一个轮播图,那么我新增一行
|
|
||||||
id为主键(不管),团队成员信息定义value:organize_user_info,设计数据结构,最终结构化为json存储到 data
|
|
||||||
轮播图一样,定义value: image_index,设计数据结构存储 data
|
|
||||||
|
|
||||||
一段时间后,有新的业务要展示,例如合作厂家展示
|
|
||||||
|
|
||||||
那就在这张表新建一行数据,定义value:cooperate,然后设计数据结构 存储data
|
|
||||||
|
|
||||||
以后有新的展示业务,以此类推。
|
|
||||||
|
|
||||||
这样取对应地方数据WHERE value后取出data,直接发送前端或定时(解析后给redis)。也不用一个业务新建一张表,也没那么多数据表查找循环。
|
|
||||||
对于数据体量非巨大的应该有一定可行性。
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## 轮播图数据结构设计
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"order": string,
|
|
||||||
"data": [
|
|
||||||
{
|
|
||||||
"display_order": integer,
|
|
||||||
"image": string,
|
|
||||||
"title": string,
|
|
||||||
"description": string,
|
|
||||||
"is_active": boolean,
|
|
||||||
"created_at": timestamp,
|
|
||||||
"updated_at": timestamp,
|
|
||||||
"author": string
|
|
||||||
},
|
|
||||||
{
|
|
||||||
......
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
1. `order`: 展示顺序,可选值 [asc|desc]
|
|
||||||
2. `data`: 数据内容
|
|
||||||
1. `display_order`: 展示顺序(输入integer,自定义处理)
|
|
||||||
2. `image`: 图片地址
|
|
||||||
3. `title`: 标题
|
|
||||||
4. `description`: 描述
|
|
||||||
5. `is_active`: 是否展示 [true|false]
|
|
||||||
6. `created_at`: 创建时间
|
|
||||||
7. `updated_at`: 修改时间
|
|
||||||
8. `autohr`: 填写作者
|
|
|
@ -1,399 +0,0 @@
|
||||||
# OrganizeInternalOA 数据库设计
|
|
||||||
|
|
||||||
<div align=right>Author: 筱锋xiao_lfeng | Version: 1.1.0</div>
|
|
||||||
|
|
||||||
## 数据库设计
|
|
||||||
|
|
||||||
本数据库设计基于原有 [《数据库设计》](./数据库设计.md) 进行测试修改,进一步处理数据库结构与增加可维护性。
|
|
||||||
|
|
||||||
> 数据库所有字段均待定,后续可能会对某些字段进行删除,或者新增一些字段,尽量做成可维护的接口
|
|
||||||
>
|
|
||||||
> 所有的表之间,关联性尽量不要做的那么强,适当解耦,不然可维护性不高
|
|
||||||
|
|
||||||
另外,为保证数据库的完整性,对数据库适当位置加以外键约束,若后续需要进行维护删除表等操作,可删除外键约束后操作。
|
|
||||||
|
|
||||||
使用数据库系统 `Mysql8`
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## 建表准备
|
|
||||||
|
|
||||||
总建表语句在 /mysql/[organize_oa.sql](../mysql/organize_oa.sql) 下存放。**(重要:在执行导入中,请先看下面内容)**
|
|
||||||
|
|
||||||
若需要导入数据库中,请先操作数据库进入对应数据库进行操作。无需执行表导入
|
|
||||||
|
|
||||||
```mysql
|
|
||||||
USE organize_oa;
|
|
||||||
```
|
|
||||||
|
|
||||||
### 数据库、用户名和密码
|
|
||||||
|
|
||||||
> 为了保证业务后期可拓展性及充分利用 mysql 默认数据库中数据,请参考下面内容。
|
|
||||||
|
|
||||||
另外,由于各位开发者配置环境为本地环境,非测试环境。故数据库部署并非统一,避免在 `application.yml` 文件中对 `spring.datasource` 频繁修改(操作git)带来不必要的麻烦,建议开发者建数据库时,数据库名字为 `organize_oa` 。单独开设账号 `organize_oa` 密码 `123456`
|
|
||||||
|
|
||||||
```mysql
|
|
||||||
-- 数据库及用户建表语句(执行后创建 organize_oa 数据库与同名 organize_oa 用户(密码:123456)
|
|
||||||
CREATE USER 'organize_oa'@'%' IDENTIFIED WITH caching_sha2_password BY '123456';GRANT USAGE ON *.* TO 'organize_oa'@'%';ALTER USER 'organize_oa'@'%' REQUIRE NONE WITH MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0;CREATE DATABASE IF NOT EXISTS `organize_oa`;GRANT ALL PRIVILEGES ON `organize_oa`.* TO 'organize_oa'@'%';
|
|
||||||
```
|
|
||||||
|
|
||||||
application.yml 配置文件如下:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
spring:
|
|
||||||
datasource:
|
|
||||||
url: jdbc:mysql://localhost:3306
|
|
||||||
username: organize_oa
|
|
||||||
password: 123456
|
|
||||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
|
||||||
```
|
|
||||||
|
|
||||||
> 注意,url部分中,没有使用 `jdbc:mysql://localhost:3306/organize_oa` ,在 mysql 中存在默认数据库 `information_schema` 该部分可以提取出该数据库(含 organize_oa 数据库)的信息,以及可以支持同账户下多张数据表,对后期若有需要可以调整使用。
|
|
||||||
|
|
||||||
### url差别对于mapper的使用区别
|
|
||||||
|
|
||||||
在习惯使用 `jdbc:mysql://localhost:3306/organize_oa` 下,Mapper中数据库语法的描写较为简单。
|
|
||||||
|
|
||||||
```java
|
|
||||||
@Mapper
|
|
||||||
public interface UserMapper {
|
|
||||||
@Select("SELECT * FROM oa_user WHERE username = #{username}")
|
|
||||||
UserDO getUserByUsername(String username);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
若修改为 `jdbc:mysql://localhost:3306` 之后,操作数据库都需要加上数据库名字,告知 **DBMS** 使用哪一个数据库后再选择数据表
|
|
||||||
|
|
||||||
```java
|
|
||||||
@Mapper
|
|
||||||
public interface UserMapper {
|
|
||||||
@Select("SELECT * FROM organize_oa.oa_user WHERE username = #{username}")
|
|
||||||
UserDO getUserByUsername(String username);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
> 为何这样使用。
|
|
||||||
>
|
|
||||||
> 上述这样操作可以保证此服务对应一个数据库的用户,不使用 root 用户。使用 root 用户是一个很危险的事情,分出专门一个用户处理并且专门的用户中对应 `information_schema` 也有自己及名下相关的数据内容方便利用。除此之外,可以进行业务拓展。**若后期需要额外的开发要求,需要多个数据库,而不是单个数据库对应多个数据表的时候。**无需进行Mapper内繁琐代码修改(替换),只需在编写新的业务Mapper代码写入新的数据表名称即可。
|
|
||||||
|
|
||||||
```java
|
|
||||||
// 举个例子
|
|
||||||
@Mapper
|
|
||||||
public interface GeneralMapper {
|
|
||||||
@Select("SELECT * FROM organize_oa.oa_user WHERE username = #{username}")
|
|
||||||
UserDO getUserByUsername(String username);
|
|
||||||
|
|
||||||
@Select("SELECT * FROM organize_log.oa_logs WHERE id = #{id}")
|
|
||||||
LogDO getLogById(Long id);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## organize_oa 数据库设计
|
|
||||||
|
|
||||||
> 以下是关于此数据库目前结构样式图,其中箭头为外键约束。对于外键约束内容详细会在下面进行详细叙述。
|
|
||||||
|
|
||||||
```mermaid
|
|
||||||
classDiagram
|
|
||||||
direction BT
|
|
||||||
class node7 {
|
|
||||||
varchar(50) value /* 调用关键字 */
|
|
||||||
json data /* json数据 */
|
|
||||||
timestamp created_at /* 创建时间 */
|
|
||||||
timestamp updated_at /* 修改时间 */
|
|
||||||
bigint unsigned id /* 主键 */
|
|
||||||
}
|
|
||||||
class node0 {
|
|
||||||
bigint unsigned pid /* 权限父id */
|
|
||||||
varchar(100) name /* 权限名称 */
|
|
||||||
varchar(50) code /* 权限编码 */
|
|
||||||
tinyint(1) type /* 0为菜单,1为权限 */
|
|
||||||
deleted_at /* 删除时间(没有删除应当为空) */ timestamp
|
|
||||||
bigint unsigned id /* 主键 */
|
|
||||||
}
|
|
||||||
class node5 {
|
|
||||||
varchar(255) name /* 项目名称 */
|
|
||||||
varchar(255) description /* 一句话描述 */
|
|
||||||
text introduction /* 项目详细介绍 */
|
|
||||||
tinyint(1) code_open /* 代码是否开放 */
|
|
||||||
text core_code /* 核心代码内容(Markdown) */
|
|
||||||
json git /* git代码仓库内容 */
|
|
||||||
tinyint unsigned difficulty_level /* 难度等级 */
|
|
||||||
int unsigned type /* 类型 */
|
|
||||||
double reward /* 报酬 */
|
|
||||||
tinyint unsigned status /* 状态 */
|
|
||||||
bigint unsigned id /* 项目id */
|
|
||||||
}
|
|
||||||
class node2 {
|
|
||||||
varchar(50) name /* 类型名字 */
|
|
||||||
timestamp created_at /* 创建时间 */
|
|
||||||
timestamp updated_at /* 修改时间 */
|
|
||||||
int unsigned id /* 项目类型id */
|
|
||||||
}
|
|
||||||
class node3 {
|
|
||||||
varchar(20) role_name /* 角色名称 */
|
|
||||||
timestamp created_at /* 创建时间 */
|
|
||||||
timestamp updated_at /* 修改时间 */
|
|
||||||
int unsigned id /* 角色id */
|
|
||||||
}
|
|
||||||
class node1 {
|
|
||||||
bigint unsigned pid /* 权限id */
|
|
||||||
timestamp created_at /* 创建时间 */
|
|
||||||
int unsigned rid /* 角色id */
|
|
||||||
}
|
|
||||||
class node6 {
|
|
||||||
int unsigned rid /* 角色id */
|
|
||||||
timestamp createdt_at /* 创建时间 */
|
|
||||||
timestamp updated_at /* 修改时间 */
|
|
||||||
bigint unsigned uid /* 用户id */
|
|
||||||
}
|
|
||||||
class node4 {
|
|
||||||
char(10) job_id /* 工作ID */
|
|
||||||
varchar(40) username /* 用户名 */
|
|
||||||
varchar(255) password /* 密码 */
|
|
||||||
varchar(255) address /* 用户家庭地址 */
|
|
||||||
varchar(11) phone /* 电话 */
|
|
||||||
varchar(100) email /* 邮箱 */
|
|
||||||
tinyint unsigned age /* 年龄 */
|
|
||||||
varchar(50) signature /* 一句话描述自己 */
|
|
||||||
tinyint unsigned sex /* 0/1/2:保密/男/女 */
|
|
||||||
text avatar /* 头像地址 */
|
|
||||||
varchar(20) nickname /* 昵称 */
|
|
||||||
tinyint(1) enabled /* 账户是否可用 */
|
|
||||||
tinyint(1) account_no_expired /* 账户是否过期 */
|
|
||||||
tinyint(1) credentials_no_expired /* 密码是否过期 */
|
|
||||||
tinyint(1) recommend /* 账户是否被推荐 */
|
|
||||||
tinyint(1) account_no_locked /* 账户是否被锁定 */
|
|
||||||
text description /* 个人简介 */
|
|
||||||
timestamp created_at /* 创建时间 */
|
|
||||||
timestamp updated_at /* 更新时间 */
|
|
||||||
bigint unsigned id /* 主键 */
|
|
||||||
}
|
|
||||||
|
|
||||||
node0 --|> node0
|
|
||||||
node5 --|> node2
|
|
||||||
node1 --|> node0
|
|
||||||
node1 --|> node3
|
|
||||||
node6 --|> node3
|
|
||||||
node6 --|> node4
|
|
||||||
```
|
|
||||||
|
|
||||||
### oa_user 数据表
|
|
||||||
|
|
||||||
#### 说明
|
|
||||||
|
|
||||||
> 【用户表】存放本项目所有用户数据
|
|
||||||
|
|
||||||
#### 数据表字段属性
|
|
||||||
|
|
||||||
| 序号 | 名称 | 描述 | 类型 | 键 | 为空 | 额外 | 默认值 |
|
|
||||||
| :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: |
|
|
||||||
| 1 | `id` | 主键 | bigint unsigned | PRI | NO | auto_increment | |
|
|
||||||
| 2 | `job_id` | 工作ID:正则表达 "^\[STU\|TEA\|OTH\]\[0-9\]{7}" | char(10) | UNI | NO | | |
|
|
||||||
| 3 | `username` | 用户名 | varchar(40) | UNI | NO | | |
|
|
||||||
| 4 | `password` | 密码 | varchar(255) | | NO | | |
|
|
||||||
| 5 | `address` | 用户家庭地址 | varchar(255) | | NO | | |
|
|
||||||
| 6 | `phone` | 电话 | varchar(11) | UNI | NO | | |
|
|
||||||
| 7 | `email` | 邮箱 | varchar(100) | UNI | NO | | |
|
|
||||||
| 8 | `age` | 年龄 | tinyint unsigned | | NO | | |
|
|
||||||
| 9 | `signature` | 一句话描述自己 | varchar(50) | | YES | | |
|
|
||||||
| 10 | `sex` | 0/1/2:保密/男/女 | tinyint unsigned | | NO | | 0 |
|
|
||||||
| 11 | `avatar` | 头像地址 | text | | YES | | |
|
|
||||||
| 12 | `nickname` | 昵称 | varchar(20) | | YES | | |
|
|
||||||
| 13 | `enabled` | 账户是否可用 | tinyint(1) | | NO | | 1 |
|
|
||||||
| 14 | `account_no_expired` | 账户是否过期 | tinyint(1) | | NO | | 1 |
|
|
||||||
| 15 | `credentials_no_expired` | 密码是否过期 | tinyint(1) | | NO | | 0 |
|
|
||||||
| 16 | `recommend` | 账户是否被推荐 | tinyint(1) | | NO | | 0 |
|
|
||||||
| 17 | `account_no_locked` | 账户是否被锁定 | tinyint(1) | | NO | | |
|
|
||||||
| 18 | `description` | 个人简介 | text | | YES | | |
|
|
||||||
| 19 | `created_at` | 创建时间 | timestamp | | NO | DEFAULT_GENERATED | CURRENT_TIMESTAMP |
|
|
||||||
| 20 | `updated_at` | 更新时间 | timestamp | | YES | | |
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### oa_role 数据表
|
|
||||||
|
|
||||||
#### 说明
|
|
||||||
|
|
||||||
> 【角色表】包含所有的角色(目前主要为三个,学生、老师、管理员)
|
|
||||||
|
|
||||||
#### 数据表字段属性
|
|
||||||
|
|
||||||
| 序号 | 名称 | 描述 | 类型 | 键 | 为空 | 额外 | 默认值 |
|
|
||||||
| :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: |
|
|
||||||
| 1 | `id` | 角色id | int unsigned | PRI | NO | auto_increment | |
|
|
||||||
| 2 | `role_name` | 角色名称 | varchar(20) | | NO | | |
|
|
||||||
| 3 | `created_at` | 创建时间 | timestamp | | NO | DEFAULT_GENERATED | CURRENT_TIMESTAMP |
|
|
||||||
| 4 | `updated_at` | 修改时间 | timestamp | | YES | | |
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### oa_permissions 数据表
|
|
||||||
|
|
||||||
#### 说明
|
|
||||||
|
|
||||||
> 【权限表】所有的权限,具体到每一个功能
|
|
||||||
|
|
||||||
字段 `pid` 外键约束 `id` 模式(CASCADE)更新与删除
|
|
||||||
|
|
||||||
#### 数据表字段属性
|
|
||||||
|
|
||||||
| 序号 | 名称 | 描述 | 类型 | 键 | 为空 | 额外 | 默认值 |
|
|
||||||
| :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: |
|
|
||||||
| 1 | `id` | 主键 | bigint unsigned | PRI | NO | auto_increment | |
|
|
||||||
| 2 | `pid` | 权限父id | bigint unsigned | MUL | YES | | |
|
|
||||||
| 3 | `name` | 权限名称 | varchar(100) | | NO | | |
|
|
||||||
| 4 | `code` | 权限编码 | varchar(50) | | NO | | |
|
|
||||||
| 5 | `type` | 0为菜单,1为权限 | tinyint(1) | | NO | | 1 |
|
|
||||||
| 6 | `deleted_at` | 删除时间(没有删除应当为空) | timestamp | | YES | | |
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### oa_role_user 数据表
|
|
||||||
|
|
||||||
#### 说明
|
|
||||||
|
|
||||||
> 【用户角色分配表】为用户赋予默认权限属性的内容
|
|
||||||
|
|
||||||
字段 `rid` 外键约束 `oa_role.id` 模式(RESTRICT)更新与删除
|
|
||||||
|
|
||||||
字段 `uid` 外键约束 `oa_user.id` 模式(CASCADE)更新与删除
|
|
||||||
|
|
||||||
#### 数据表字段属性
|
|
||||||
|
|
||||||
| 序号 | 名称 | 描述 | 类型 | 键 | 为空 | 额外 | 默认值 |
|
|
||||||
| :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: |
|
|
||||||
| 1 | `uid` | 用户id | bigint unsigned | PRI | NO | | |
|
|
||||||
| 2 | `rid` | 角色id | int unsigned | MUL | NO | | |
|
|
||||||
| 3 | `createdt_at` | 创建时间 | timestamp | | NO | DEFAULT_GENERATED | CURRENT_TIMESTAMP |
|
|
||||||
| 4 | `updated_at` | 修改时间 | timestamp | | YES | | |
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### oa_role_permissions 数据表
|
|
||||||
|
|
||||||
#### 说明
|
|
||||||
|
|
||||||
> 【角色权限表】为角色赋予指定权限操作
|
|
||||||
|
|
||||||
字段 `rid` 外键约束 `oa_role.id` 模式(CASCADE)更新与删除
|
|
||||||
|
|
||||||
字段 `pid` 外键约束 `oa_permissions.id` 模式(CASCADE)更新与删除
|
|
||||||
|
|
||||||
#### 数据表字段属性
|
|
||||||
|
|
||||||
| 序号 | 名称 | 描述 | 类型 | 键 | 为空 | 额外 | 默认值 |
|
|
||||||
| :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: |
|
|
||||||
| 1 | `rid` | 角色id | int unsigned | PRI | NO | | |
|
|
||||||
| 2 | `pid` | 权限id | bigint unsigned | MUL | NO | | |
|
|
||||||
| 3 | `created_at` | 创建时间 | timestamp | | NO | DEFAULT_GENERATED | CURRENT_TIMESTAMP |
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### oa_project 数据表
|
|
||||||
|
|
||||||
#### 说明
|
|
||||||
|
|
||||||
> 【项目表】用于存放项目相关内容
|
|
||||||
|
|
||||||
字段 `type` 外键约束 `oa_project_type.id` 模式(CASCADE)更新,模式(RESTRICT)删除
|
|
||||||
|
|
||||||
#### 数据表字段属性
|
|
||||||
|
|
||||||
| 序号 | 名称 | 描述 | 类型 | 键 | 为空 | 额外 | 默认值 |
|
|
||||||
| :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: |
|
|
||||||
| 1 | `id` | 项目id | bigint unsigned | PRI | NO | auto_increment | |
|
|
||||||
| 2 | `name` | 项目名称 | varchar(255) | | NO | | |
|
|
||||||
| 3 | `description` | 一句话描述 | varchar(255) | | NO | | |
|
|
||||||
| 4 | `introduction` | 项目详细介绍 | text | | NO | | |
|
|
||||||
| 5 | `code_open` | 代码是否开放 | tinyint(1) | | NO | | 0 |
|
|
||||||
| 6 | `core_code` | 核心代码内容(Markdown) | text | | YES | | |
|
|
||||||
| 7 | `git` | git代码仓库内容 | json | | YES | | |
|
|
||||||
| 8 | `difficulty_level` | 难度等级 | tinyint unsigned | | NO | | 1 |
|
|
||||||
| 9 | `type` | 类型 | int unsigned | MUL | NO | | |
|
|
||||||
| 10 | `reward` | 报酬 | bigint unsigned | | YES | | |
|
|
||||||
| 11 | `status` | 状态 | tinyint unsigned | | NO | | 0 |
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### oa_project_type 数据表
|
|
||||||
|
|
||||||
#### 说明
|
|
||||||
|
|
||||||
> 【项目类型表】用于存放项目种类的种类分类表
|
|
||||||
|
|
||||||
#### 数据表字段属性
|
|
||||||
|
|
||||||
| 序号 | 名称 | 描述 | 类型 | 键 | 为空 | 额外 | 默认值 |
|
|
||||||
| :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: |
|
|
||||||
| 1 | `id` | 项目类型id | int unsigned | PRI | NO | auto_increment | |
|
|
||||||
| 2 | `name` | 类型名字 | varchar(50) | | NO | | |
|
|
||||||
| 3 | `created_at` | 创建时间 | timestamp | | NO | DEFAULT_GENERATED | CURRENT_TIMESTAMP |
|
|
||||||
| 4 | `updated_at` | 修改时间 | timestamp | | YES | | |
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### oa_project_cutting 数据表
|
|
||||||
|
|
||||||
#### 说明
|
|
||||||
|
|
||||||
> 【项目切割表】用于存放项目分割模块后的各模块内容
|
|
||||||
|
|
||||||
字段 `pid` 外键约束 `oa_project.id` 模式(CASCADE)更新与删除
|
|
||||||
|
|
||||||
#### 数据表字段属性
|
|
||||||
|
|
||||||
| 序号 | 名称 | 描述 | 类型 | 键 | 为空 | 额外 | 默认值 |
|
|
||||||
| :--: | :--------------: | :--------------: | :--------------: | :--: | :--: | :---------------: | :---------------: |
|
|
||||||
| 1 | `id` | 主键 | bigint unsigned | PRI | NO | auto_increment | |
|
|
||||||
| 2 | `pid` | 项目id | bigint unsigned | MUL | NO | | |
|
|
||||||
| 3 | `name` | 项目分割模块名字 | varchar(40) | | NO | | |
|
|
||||||
| 4 | `tag` | 模块标签 | json | | YES | | |
|
|
||||||
| 5 | `engineering` | 工程量计算 | tinyint unsigned | | NO | | 1 |
|
|
||||||
| 6 | `estimated_time` | 预估时间(小时) | int unsigned | | NO | | 3 |
|
|
||||||
| 7 | `real_time` | 实际时间 | timestamp | | YES | | |
|
|
||||||
| 8 | `created_at` | 创建时间 | timestamp | | NO | DEFAULT_GENERATED | CURRENT_TIMESTAMP |
|
|
||||||
| 9 | `updated_at` | 修改时间 | timestamp | | YES | | |
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### oa_project_user 数据表
|
|
||||||
|
|
||||||
#### 说明
|
|
||||||
|
|
||||||
> 【用户项目分配表】用于存放用户所分配到的子项目内容
|
|
||||||
|
|
||||||
字段 `uid` 外键约束 `oa_user.id` 模式(RESTRICT)更新与删除
|
|
||||||
|
|
||||||
字段 `pid` 外键约束 `oa_project_cutting.id` 模式(CASCADE)更新与删除
|
|
||||||
|
|
||||||
#### 数据表字段属性
|
|
||||||
|
|
||||||
| 序号 | 名称 | 描述 | 类型 | 键 | 为空 | 额外 | 默认值 |
|
|
||||||
| :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: |
|
|
||||||
| 1 | `id` | 主键id | bigint unsigned | PRI | NO | auto_increment | |
|
|
||||||
| 2 | `uid` | 用户id | bigint unsigned | MUL | NO | | |
|
|
||||||
| 3 | `pid` | 接到分割项目内容 | bigint unsigned | MUL | NO | | |
|
|
||||||
| 4 | `created_at` | 创建时间 | timestamp | | NO | DEFAULT_GENERATED | CURRENT_TIMESTAMP |
|
|
||||||
| 5 | `updated_at` | 修改时间 | timestamp | | YES | | |
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### oa_config 数据表
|
|
||||||
|
|
||||||
#### 说明
|
|
||||||
|
|
||||||
> 【配置表】用于相关内容的配置
|
|
||||||
|
|
||||||
**请注意,这部分内容需要有额外的定义,具体定义内容请参考 [《Config表详细内容设计》](./OrganizeInternalOA-ConfigTableConfig.md)**
|
|
||||||
|
|
||||||
#### 数据表字段属性
|
|
||||||
|
|
||||||
| 序号 | 名称 | 描述 | 类型 | 键 | 为空 | 额外 | 默认值 |
|
|
||||||
| :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: |
|
|
||||||
| 1 | `id` | 主键 | bigint unsigned | PRI | NO | auto_increment | |
|
|
||||||
| 2 | `value` | 调用关键字 | varchar(50) | UNI | NO | | |
|
|
||||||
| 3 | `data` | json数据 | json | | YES | | |
|
|
||||||
| 4 | `created_at` | 创建时间 | timestamp | | NO | DEFAULT_GENERATED | CURRENT_TIMESTAMP |
|
|
||||||
| 5 | `updated_at` | 修改时间 | timestamp | | YES | | |
|
|
|
@ -1,78 +0,0 @@
|
||||||
## 内部系统前端(管理)
|
|
||||||
|
|
||||||
PS:组件化
|
|
||||||
|
|
||||||
+ 顶部导航栏
|
|
||||||
+ 侧边栏
|
|
||||||
+ 信息管理
|
|
||||||
+ 底部信息栏
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### 顶部导航栏
|
|
||||||
|
|
||||||
+ logo
|
|
||||||
+ 用户名
|
|
||||||
+ 头像
|
|
||||||
|
|
||||||
| 可交互组件 | 事件 | 效果 |
|
|
||||||
| ----------- | ---- | -------------------------- |
|
|
||||||
| logo | 单击 | 回到首页 |
|
|
||||||
| 头像/用户名 | 单击 | 下拉菜单(可点击退出登录) |
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### 侧边栏
|
|
||||||
|
|
||||||
+ 成员信息管理
|
|
||||||
+ 角色管理
|
|
||||||
+ 权限管理
|
|
||||||
+ 轮播图管理
|
|
||||||
+ 项目信息管理
|
|
||||||
+ 团队信息管理
|
|
||||||
+ 新闻信息管理
|
|
||||||
+ 消息通知管理
|
|
||||||
+ 日报信息管理
|
|
||||||
+ 系统日志管理(待定)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### 信息管理
|
|
||||||
|
|
||||||
PS:主要对信息进行增删查改的操作
|
|
||||||
|
|
||||||
+ 新增
|
|
||||||
+ 单行输入框
|
|
||||||
+ 表格
|
|
||||||
|
|
||||||
| 可交互组件 | 事件 | 效果 |
|
|
||||||
| ----------------------- | -------------------------- | ------------------------------ |
|
|
||||||
| 新增按钮 | 点击 | 弹窗显示新增信息 |
|
|
||||||
| 单行输入框 | 获取焦点后输入要查询的信息 | 失去焦点/按下enter键后进行查询 |
|
|
||||||
| 表单展示 | - | 显示数据 |
|
|
||||||
| 表单-编辑 | 点击 | 编辑信息 |
|
|
||||||
| 表单-删除 | 点击 | 删除信息 |
|
|
||||||
| 表单-左侧复选框(优化) | 点击 | 可进行多选删除 |
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### 底部信息栏
|
|
||||||
|
|
||||||
PS:信息待定
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,72 +0,0 @@
|
||||||
## 内部系统前端(首页)
|
|
||||||
|
|
||||||
PS:组件化编写代码
|
|
||||||
|
|
||||||
首页组件划分:
|
|
||||||
|
|
||||||
+ 顶层导航栏
|
|
||||||
+ 项目推荐
|
|
||||||
+ 团队简介
|
|
||||||
+ 新闻展示
|
|
||||||
+ 领导者/优秀学员展示
|
|
||||||
+ 底部信息栏
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### 顶部导航栏
|
|
||||||
|
|
||||||
| 可交互组件 | 事件 | 效果 |
|
|
||||||
| ---------- | ---- | ---------------------------------------------- |
|
|
||||||
| logo | 单击 | 回到首页 |
|
|
||||||
| 首页 | 单击 | 回到首页 |
|
|
||||||
| 项目 | 单击 | 进入项目页 |
|
|
||||||
| 关于 | 单击 | 下拉菜单,显示(关于我们,加入我们,项目合作) |
|
|
||||||
| 关于我们 | 单击 | 进入团队信息展示页面 |
|
|
||||||
| 加入我们 | 单击 | 进入加入我们页面 |
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### 项目推荐
|
|
||||||
|
|
||||||
| 可交互组件 | 事件 | 效果 |
|
|
||||||
| ------------ | -------- | -------------------------------------- |
|
|
||||||
| 项目卡片 | 鼠标悬浮 | 显示此项目的名称,归类,状态,进入按钮 |
|
|
||||||
| 悬浮后的卡片 | 单击 | 进入对应项目详情页面 |
|
|
||||||
| 向右箭头 | 单击 | 进入项目页 |
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### 关于
|
|
||||||
|
|
||||||
| 可交互组件 | 事件 | 效果 |
|
|
||||||
| ---------- | ---- | ---------------- |
|
|
||||||
| 向右箭头 | 单击 | 进入关于我们页面 |
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### 新闻
|
|
||||||
|
|
||||||
| 可交互组件 | 事件 | 效果 |
|
|
||||||
| ------------ | -------- | -------------------- |
|
|
||||||
| 向右箭头 | 点击 | 进入新闻页 |
|
|
||||||
| 新闻卡片 | 鼠标悬浮 | 颜色突出,可点击进入 |
|
|
||||||
| 悬浮后的卡片 | 点击 | 进入此新闻详情页 |
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### 领导者展示
|
|
||||||
|
|
||||||
| 可交互组件 | 事件 | 效果 |
|
|
||||||
| ---------- | ---- | ---------------------- |
|
|
||||||
| 头像 | 单击 | 进入此成员的个人详情页 |
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### 底部信息栏
|
|
||||||
|
|
||||||
暂时未定,摆放虚假信息即可
|
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
## 内部系统后端(管理)
|
|
||||||
|
|
||||||
PS:主要是针对内部系统项目首页的各个信息进行管理(增删查改)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### 功能点
|
|
||||||
|
|
||||||
PS:主要包含对数据库信息的增删查改,以及查询全部信息
|
|
||||||
|
|
||||||
+ 成员信息管理
|
|
||||||
+ 角色管理
|
|
||||||
+ 权限管理
|
|
||||||
+ 轮播图管理
|
|
||||||
+ 项目信息管理
|
|
||||||
+ 团队信息管理
|
|
||||||
+ 新闻信息管理
|
|
||||||
+ 消息通知管理
|
|
||||||
+ 日报信息管理
|
|
||||||
+ 系统日志管理(待定)
|
|
|
@ -1,71 +0,0 @@
|
||||||
## 内部系统后端(首页)
|
|
||||||
|
|
||||||
### 功能点设计
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#### 功能点一:权限认证
|
|
||||||
|
|
||||||
★★★★★
|
|
||||||
|
|
||||||
要求如下:
|
|
||||||
|
|
||||||
+ 框架自选:Shiro/springsecurity
|
|
||||||
+ token验证
|
|
||||||
+ redis存储token
|
|
||||||
|
|
||||||
接口:
|
|
||||||
|
|
||||||
+ 登录接口login
|
|
||||||
+ 返回用户详细信息
|
|
||||||
+ 返回此用户对应的权限
|
|
||||||
+ 返回生成的token
|
|
||||||
+ 退出接口logout
|
|
||||||
+ 删除redis中的token
|
|
||||||
|
|
||||||
#### 功能点二:轮播图展示
|
|
||||||
|
|
||||||
★
|
|
||||||
|
|
||||||
接口:
|
|
||||||
|
|
||||||
+ 查询推荐的轮播图(4-6张)
|
|
||||||
+ 返回所有被推荐的轮播图数据(4-6条)
|
|
||||||
|
|
||||||
#### 功能点三:推荐项目展示
|
|
||||||
|
|
||||||
★
|
|
||||||
|
|
||||||
接口:
|
|
||||||
|
|
||||||
+ 查询推荐的项目
|
|
||||||
+ 返回所有被推荐的项目条目(6条)
|
|
||||||
|
|
||||||
#### 功能点四:团队信息推荐
|
|
||||||
|
|
||||||
★
|
|
||||||
|
|
||||||
接口:
|
|
||||||
|
|
||||||
+ 查询团队信息
|
|
||||||
+ 返回团队信息简介
|
|
||||||
|
|
||||||
#### 功能点五:最新新闻展示
|
|
||||||
|
|
||||||
★
|
|
||||||
|
|
||||||
接口:
|
|
||||||
|
|
||||||
+ 查询最新新闻
|
|
||||||
+ 返回最新新闻条目(3条)
|
|
||||||
|
|
||||||
#### 功能点六:优秀成员推荐
|
|
||||||
|
|
||||||
★
|
|
||||||
|
|
||||||
接口:
|
|
||||||
|
|
||||||
+ 查询被推荐的成员
|
|
||||||
+ 返回被推荐的成员条目(至少三条)
|
|
||||||
|
|
||||||
|
|
316
doc/数据库设计.md
316
doc/数据库设计.md
|
@ -1,316 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
### 数据库设计
|
|
||||||
|
|
||||||
PS:
|
|
||||||
|
|
||||||
+ 数据库所有字段均待定,后续可能会对某些字段进行删除,或者新增一些字段,尽量做成可维护的接口
|
|
||||||
+ 所有的表之间,关联性尽量不要做的那么强,适当解耦,不然可维护性不高
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#### 角色权限
|
|
||||||
|
|
||||||
##### user
|
|
||||||
|
|
||||||
PS:`用户表`
|
|
||||||
|
|
||||||
msg:*包含所有用户*
|
|
||||||
|
|
||||||
| 字段 | 类型 | 注释 |
|
|
||||||
| ---------------------- | -------- | -------------------------- |
|
|
||||||
| user_id | int | 用户id |
|
|
||||||
| username | varchar | 用户名 |
|
|
||||||
| password | varchar | 密码 |
|
|
||||||
| address | varchar | 地址 |
|
|
||||||
| phone | varchar | 电话 |
|
|
||||||
| email | varchar | 电子邮箱 |
|
|
||||||
| age | int | 年龄 |
|
|
||||||
| signature | varchar | 签名 |
|
|
||||||
| sex | varchar | 性别 |
|
|
||||||
| avatar | varchar | 头像 |
|
|
||||||
| nack_name | varchar | 昵称 |
|
|
||||||
| enabled | int | 账户是否可用(1可用,0) |
|
|
||||||
| account_no_expired | int | 账户是否过期(1可用,0) |
|
|
||||||
| credentials_no_expired | int | 密码是否过期(1可用,0) |
|
|
||||||
| recommend | int | 账户是否被推荐(1推荐,0) |
|
|
||||||
| account_no_locked | int | 账户是否被锁定(1可用,0) |
|
|
||||||
| create_time | datetime | 创建时间 |
|
|
||||||
| description | varchar | 个人简介 |
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
##### role
|
|
||||||
|
|
||||||
PS:`角色表`
|
|
||||||
|
|
||||||
msg:*包含所有的角色,目前有三个*
|
|
||||||
|
|
||||||
| 字段 | 类型 | 注释 |
|
|
||||||
| --------- | ------- | -------- |
|
|
||||||
| id | int | 角色id |
|
|
||||||
| role_name | varchar | 角色名称 |
|
|
||||||
| remark | varchar | 标记 |
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
##### permissions
|
|
||||||
|
|
||||||
PS:`权限表`
|
|
||||||
|
|
||||||
msg:*所有的权限,具体到每一个功能*
|
|
||||||
|
|
||||||
| 字段 | 类型 | 解释 |
|
|
||||||
| ----------- | ------- | ---------------------- |
|
|
||||||
| id | int | 权限id |
|
|
||||||
| pid | int | 权限的父id |
|
|
||||||
| name | varchar | 名称 |
|
|
||||||
| code | varchar | 编码 |
|
|
||||||
| type | int | 0为菜单,1为权限 |
|
|
||||||
| delete_flag | tinyint | 0代表未删除,1代表删除 |
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
##### role_user
|
|
||||||
|
|
||||||
PS:`角色用户表`
|
|
||||||
|
|
||||||
msg:*给用户分配角色*
|
|
||||||
|
|
||||||
| 字段 | 类型 | 解释 |
|
|
||||||
| ---- | ---- | ------ |
|
|
||||||
| uid | int | 用户id |
|
|
||||||
| rid | int | 角色id |
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
##### role_permissions
|
|
||||||
|
|
||||||
PS:`角色权限表`
|
|
||||||
|
|
||||||
msg:*每个角色对应很多权限*
|
|
||||||
|
|
||||||
| 字段 | 类型 | 解释 |
|
|
||||||
| ---- | ---- | ------ |
|
|
||||||
| rid | int | 角色id |
|
|
||||||
| pid | int | 权限id |
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#### 轮播图(可选)
|
|
||||||
|
|
||||||
msg:*主页第一部分展示内容*
|
|
||||||
|
|
||||||
##### carousel
|
|
||||||
|
|
||||||
PS:`轮播图表`
|
|
||||||
|
|
||||||
| 字段 | 类型 | 解释 |
|
|
||||||
| ------------- | -------- | -------------- |
|
|
||||||
| id | id | 轮播图id |
|
|
||||||
| image | varchar | 图片路径或字符 |
|
|
||||||
| title | varchar | 标题 |
|
|
||||||
| description | varchar | 描述 |
|
|
||||||
| display_order | int | 展示顺序 |
|
|
||||||
| is_active | int | 是否展示 |
|
|
||||||
| create_time | datetime | 创建时间 |
|
|
||||||
| update_time | datetime | 更新时间 |
|
|
||||||
| author | varchar | 作者 |
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#### 团队信息(字段暂定)
|
|
||||||
|
|
||||||
msg:团队信息展示
|
|
||||||
|
|
||||||
##### teamInfo
|
|
||||||
|
|
||||||
PS:`团队信息表`
|
|
||||||
|
|
||||||
| 字段 | 类型 | 解释 |
|
|
||||||
| ----------- | ------- | -------- |
|
|
||||||
| id | int | 团队id |
|
|
||||||
| name | varchar | 团队名称 |
|
|
||||||
| count | int | 团队人数 |
|
|
||||||
| description | text | 团队简介 |
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#### 项目(慢一点)
|
|
||||||
|
|
||||||
msg:*主要在项目展示页面*
|
|
||||||
|
|
||||||
##### project
|
|
||||||
|
|
||||||
PS:`项目内容表`
|
|
||||||
|
|
||||||
| 字段 | 类型 | 解释 |
|
|
||||||
| ---------------- | -------- | ---------------- |
|
|
||||||
| id | int | 项目id |
|
|
||||||
| project_name | varchar | 项目名称 |
|
|
||||||
| signature | varchar | 签名 |
|
|
||||||
| description | text | 描述 |
|
|
||||||
| core_code_md | varchar | 核心代码文件 |
|
|
||||||
| github_http | varchar | github的http链接 |
|
|
||||||
| github_ssh | varchar | github的ssh链接 |
|
|
||||||
| create_time | datetime | 创建时间 |
|
|
||||||
| update_time | datetime | 更新时间 |
|
|
||||||
| difficulty_level | int | 难度等级 |
|
|
||||||
| type | varchar | 类型 |
|
|
||||||
| reward | varchar | 报酬 |
|
|
||||||
| status | int | 状态 |
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
##### user_project
|
|
||||||
|
|
||||||
PS:`用户项目表`
|
|
||||||
|
|
||||||
| 字段 | 类型 | 解释 |
|
|
||||||
| ---- | ---- | ------ |
|
|
||||||
| uid | int | 用户id |
|
|
||||||
| pid | int | 项目id |
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#### 新闻
|
|
||||||
|
|
||||||
##### news
|
|
||||||
|
|
||||||
PS:`新闻内容表`
|
|
||||||
|
|
||||||
| 字段 | 类型 | 解释 |
|
|
||||||
| ----------- | -------- | ------------------ |
|
|
||||||
| id | int | id |
|
|
||||||
| title | varchar | 标题 |
|
|
||||||
| content | text | 内容 |
|
|
||||||
| create_time | datetime | 创建时间 |
|
|
||||||
| update_time | datetime | 更新时间 |
|
|
||||||
| tags | varchar | 标签(项目,通知) |
|
|
||||||
| status | int | 状态 |
|
|
||||||
| likes | int | 点赞数(后面用) |
|
|
||||||
| comments | int | 评论数(后面用) |
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
##### news_user
|
|
||||||
|
|
||||||
PS:`新闻作者表`
|
|
||||||
|
|
||||||
| 字段 | 类型 | 解释 |
|
|
||||||
| ---- | ---- | ------ |
|
|
||||||
| uid | int | 用户id |
|
|
||||||
| nid | int | 新闻id |
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#### 消息
|
|
||||||
|
|
||||||
##### message
|
|
||||||
|
|
||||||
PS:`发送消息表`
|
|
||||||
|
|
||||||
| 字段 | 类型 | 解释 |
|
|
||||||
| ----------- | -------- | ------------------ |
|
|
||||||
| id | int | 消息id |
|
|
||||||
| sender_id | int | 发送者id |
|
|
||||||
| content | text | 内容 |
|
|
||||||
| send_time | datetime | 发送时间 |
|
|
||||||
| status | int | 状态 |
|
|
||||||
| delete_flag | int | 删除标记 |
|
|
||||||
| read_time | datetime | 阅读时间 |
|
|
||||||
| tags | varchar | 标签(项目,财务) |
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
##### message_user
|
|
||||||
|
|
||||||
PS:`接收消息表`
|
|
||||||
|
|
||||||
| 字段 | 类型 | 解释 |
|
|
||||||
| ---- | ---- | ------------------ |
|
|
||||||
| mid | int | 消息id |
|
|
||||||
| uid | int | 用户id(接收者id) |
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#### 日报
|
|
||||||
|
|
||||||
##### daily
|
|
||||||
|
|
||||||
PS:`日报信息表`
|
|
||||||
|
|
||||||
| 字段 | 类型 | 解释 |
|
|
||||||
| ----------- | -------- | ---------------- |
|
|
||||||
| id | int | 日报id |
|
|
||||||
| name | datetime | 日报名称(时间) |
|
|
||||||
| content | text | 内容 |
|
|
||||||
| plan | text | 计划 |
|
|
||||||
| create_time | datetime | 创建时间 |
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
##### daily_project
|
|
||||||
|
|
||||||
PS:`日报项目表`
|
|
||||||
|
|
||||||
| 字段 | 类型 | 解释 |
|
|
||||||
| ---- | ---- | ------ |
|
|
||||||
| did | int | 日报id |
|
|
||||||
| pid | int | 项目id |
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
##### daily-user
|
|
||||||
|
|
||||||
PS:`日报用户表`
|
|
||||||
|
|
||||||
| 字段 | 类型 | 解释 |
|
|
||||||
| ---- | ---- | ------ |
|
|
||||||
| did | int | 日报id |
|
|
||||||
| uid | int | 用户id |
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,380 +0,0 @@
|
||||||
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
|
|
||||||
START TRANSACTION;
|
|
||||||
SET time_zone = "+00:00";
|
|
||||||
|
|
||||||
|
|
||||||
/*!40101 SET @OLD_CHARACTER_SET_CLIENT = @@CHARACTER_SET_CLIENT */;
|
|
||||||
/*!40101 SET @OLD_CHARACTER_SET_RESULTS = @@CHARACTER_SET_RESULTS */;
|
|
||||||
/*!40101 SET @OLD_COLLATION_CONNECTION = @@COLLATION_CONNECTION */;
|
|
||||||
/*!40101 SET NAMES utf8mb4 */;
|
|
||||||
|
|
||||||
--
|
|
||||||
-- 数据库: `organize_oa`
|
|
||||||
--
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
--
|
|
||||||
-- 表的结构 `oa_config`
|
|
||||||
--
|
|
||||||
|
|
||||||
CREATE TABLE `oa_config`
|
|
||||||
(
|
|
||||||
`id` bigint UNSIGNED NOT NULL COMMENT '主键',
|
|
||||||
`value` varchar(50) NOT NULL COMMENT '调用关键字',
|
|
||||||
`data` json DEFAULT NULL COMMENT 'json数据',
|
|
||||||
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
|
||||||
`updated_at` timestamp NULL DEFAULT NULL COMMENT '修改时间'
|
|
||||||
) ENGINE = InnoDB
|
|
||||||
DEFAULT CHARSET = utf8mb4
|
|
||||||
COLLATE = utf8mb4_0900_ai_ci COMMENT ='配置数据表';
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
--
|
|
||||||
-- 表的结构 `oa_permissions`
|
|
||||||
--
|
|
||||||
|
|
||||||
CREATE TABLE `oa_permissions`
|
|
||||||
(
|
|
||||||
`id` bigint UNSIGNED NOT NULL COMMENT '主键',
|
|
||||||
`pid` bigint UNSIGNED DEFAULT NULL COMMENT '权限父id',
|
|
||||||
`name` varchar(100) NOT NULL COMMENT '权限名称',
|
|
||||||
`code` varchar(50) NOT NULL COMMENT '权限编码',
|
|
||||||
`type` tinyint(1) NOT NULL DEFAULT '1' COMMENT '0为菜单,1为权限',
|
|
||||||
`deleted_at` timestamp NULL DEFAULT NULL COMMENT '删除时间(没有删除应当为空)'
|
|
||||||
) ENGINE = InnoDB
|
|
||||||
DEFAULT CHARSET = utf8mb4
|
|
||||||
COLLATE = utf8mb4_0900_ai_ci COMMENT ='权限表';
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
--
|
|
||||||
-- 表的结构 `oa_project`
|
|
||||||
--
|
|
||||||
|
|
||||||
CREATE TABLE `oa_project`
|
|
||||||
(
|
|
||||||
`id` bigint UNSIGNED NOT NULL COMMENT '项目id',
|
|
||||||
`name` varchar(255) NOT NULL COMMENT '项目名称',
|
|
||||||
`description` varchar(255) NOT NULL COMMENT '一句话描述',
|
|
||||||
`introduction` text NOT NULL COMMENT '项目详细介绍',
|
|
||||||
`code_open` tinyint(1) NOT NULL DEFAULT '0' COMMENT '代码是否开放',
|
|
||||||
`core_code` text COMMENT '核心代码内容(Markdown)',
|
|
||||||
`git` json DEFAULT NULL COMMENT 'git代码仓库内容',
|
|
||||||
`difficulty_level` tinyint UNSIGNED NOT NULL DEFAULT '1' COMMENT '难度等级',
|
|
||||||
`type` int UNSIGNED NOT NULL COMMENT '类型',
|
|
||||||
`reward` bigint UNSIGNED DEFAULT NULL COMMENT '报酬',
|
|
||||||
`status` tinyint UNSIGNED NOT NULL DEFAULT '0' COMMENT '状态'
|
|
||||||
) ENGINE = InnoDB
|
|
||||||
DEFAULT CHARSET = utf8mb4
|
|
||||||
COLLATE = utf8mb4_0900_ai_ci COMMENT ='项目内容表';
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
--
|
|
||||||
-- 表的结构 `oa_project_cutting`
|
|
||||||
--
|
|
||||||
|
|
||||||
CREATE TABLE `oa_project_cutting`
|
|
||||||
(
|
|
||||||
`id` bigint UNSIGNED NOT NULL COMMENT '主键',
|
|
||||||
`pid` bigint UNSIGNED NOT NULL COMMENT '项目id',
|
|
||||||
`name` varchar(40) NOT NULL COMMENT '项目分割模块名字',
|
|
||||||
`tag` json DEFAULT NULL COMMENT '模块标签',
|
|
||||||
`engineering` tinyint UNSIGNED NOT NULL DEFAULT '1' COMMENT '工程量计算',
|
|
||||||
`estimated_time` int UNSIGNED NOT NULL DEFAULT '3' COMMENT '预估时间(小时)',
|
|
||||||
`real_time` timestamp NULL DEFAULT NULL COMMENT '实际时间',
|
|
||||||
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
|
||||||
`updated_at` timestamp NULL DEFAULT NULL COMMENT '修改时间'
|
|
||||||
) ENGINE = InnoDB
|
|
||||||
DEFAULT CHARSET = utf8mb4
|
|
||||||
COLLATE = utf8mb4_0900_ai_ci COMMENT ='项目切割';
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
--
|
|
||||||
-- 表的结构 `oa_project_type`
|
|
||||||
--
|
|
||||||
|
|
||||||
CREATE TABLE `oa_project_type`
|
|
||||||
(
|
|
||||||
`id` int UNSIGNED NOT NULL COMMENT '项目类型id',
|
|
||||||
`name` varchar(50) NOT NULL COMMENT '类型名字',
|
|
||||||
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
|
||||||
`updated_at` timestamp NULL DEFAULT NULL COMMENT '修改时间'
|
|
||||||
) ENGINE = InnoDB
|
|
||||||
DEFAULT CHARSET = utf8mb4
|
|
||||||
COLLATE = utf8mb4_0900_ai_ci COMMENT ='项目类型';
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
--
|
|
||||||
-- 表的结构 `oa_project_user`
|
|
||||||
--
|
|
||||||
|
|
||||||
CREATE TABLE `oa_project_user`
|
|
||||||
(
|
|
||||||
`id` bigint UNSIGNED NOT NULL COMMENT '主键id',
|
|
||||||
`uid` bigint UNSIGNED NOT NULL COMMENT '用户id',
|
|
||||||
`pid` bigint UNSIGNED NOT NULL COMMENT '接到分割项目内容',
|
|
||||||
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
|
||||||
`updated_at` timestamp NULL DEFAULT NULL COMMENT '修改时间'
|
|
||||||
) ENGINE = InnoDB
|
|
||||||
DEFAULT CHARSET = utf8mb4
|
|
||||||
COLLATE = utf8mb4_0900_ai_ci COMMENT ='用户项目表';
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
--
|
|
||||||
-- 表的结构 `oa_role`
|
|
||||||
--
|
|
||||||
|
|
||||||
CREATE TABLE `oa_role`
|
|
||||||
(
|
|
||||||
`id` int UNSIGNED NOT NULL COMMENT '角色id',
|
|
||||||
`role_name` varchar(20) NOT NULL COMMENT '角色名称',
|
|
||||||
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
|
||||||
`updated_at` timestamp NULL DEFAULT NULL COMMENT '修改时间'
|
|
||||||
) ENGINE = InnoDB
|
|
||||||
DEFAULT CHARSET = utf8mb4
|
|
||||||
COLLATE = utf8mb4_0900_ai_ci COMMENT ='角色表';
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
--
|
|
||||||
-- 表的结构 `oa_role_permissions`
|
|
||||||
--
|
|
||||||
|
|
||||||
CREATE TABLE `oa_role_permissions`
|
|
||||||
(
|
|
||||||
`rid` int UNSIGNED NOT NULL COMMENT '角色id',
|
|
||||||
`pid` bigint UNSIGNED NOT NULL COMMENT '权限id',
|
|
||||||
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间'
|
|
||||||
) ENGINE = InnoDB
|
|
||||||
DEFAULT CHARSET = utf8mb4
|
|
||||||
COLLATE = utf8mb4_0900_ai_ci COMMENT ='角色权限表';
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
--
|
|
||||||
-- 表的结构 `oa_role_user`
|
|
||||||
--
|
|
||||||
|
|
||||||
CREATE TABLE `oa_role_user`
|
|
||||||
(
|
|
||||||
`uid` bigint UNSIGNED NOT NULL COMMENT '用户id',
|
|
||||||
`rid` int UNSIGNED NOT NULL COMMENT '角色id',
|
|
||||||
`createdt_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
|
||||||
`updated_at` timestamp NULL DEFAULT NULL COMMENT '修改时间'
|
|
||||||
) ENGINE = InnoDB
|
|
||||||
DEFAULT CHARSET = utf8mb4
|
|
||||||
COLLATE = utf8mb4_0900_ai_ci COMMENT ='角色用户表';
|
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
|
||||||
|
|
||||||
--
|
|
||||||
-- 表的结构 `oa_user`
|
|
||||||
--
|
|
||||||
|
|
||||||
CREATE TABLE `oa_user`
|
|
||||||
(
|
|
||||||
`id` bigint UNSIGNED NOT NULL COMMENT '主键',
|
|
||||||
`job_id` char(10) NOT NULL COMMENT '工作ID:正则表达 "^[STU|TEA|OTH][0-9]{7}"',
|
|
||||||
`username` varchar(40) NOT NULL COMMENT '用户名',
|
|
||||||
`password` varchar(255) NOT NULL COMMENT '密码',
|
|
||||||
`address` varchar(255) NOT NULL COMMENT '用户家庭地址',
|
|
||||||
`phone` varchar(11) NOT NULL COMMENT '电话',
|
|
||||||
`email` varchar(100) NOT NULL COMMENT '邮箱',
|
|
||||||
`age` tinyint UNSIGNED NOT NULL COMMENT '年龄',
|
|
||||||
`signature` varchar(50) DEFAULT NULL COMMENT '一句话描述自己',
|
|
||||||
`sex` tinyint UNSIGNED NOT NULL DEFAULT '0' COMMENT '0/1/2:保密/男/女',
|
|
||||||
`avatar` text COMMENT '头像地址',
|
|
||||||
`nickname` varchar(20) DEFAULT NULL COMMENT '昵称',
|
|
||||||
`enabled` tinyint(1) NOT NULL DEFAULT '1' COMMENT '账户是否可用',
|
|
||||||
`account_no_expired` tinyint(1) NOT NULL DEFAULT '1' COMMENT '账户是否过期',
|
|
||||||
`credentials_no_expired` tinyint(1) NOT NULL DEFAULT '0' COMMENT '密码是否过期',
|
|
||||||
`recommend` tinyint(1) NOT NULL DEFAULT '0' COMMENT '账户是否被推荐',
|
|
||||||
`account_no_locked` tinyint(1) NOT NULL DEFAULT '1' COMMENT '账户是否被锁定',
|
|
||||||
`description` text COMMENT '个人简介',
|
|
||||||
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
|
||||||
`updated_at` timestamp NULL DEFAULT NULL COMMENT '更新时间'
|
|
||||||
) ENGINE = InnoDB
|
|
||||||
DEFAULT CHARSET = utf8mb4
|
|
||||||
COLLATE = utf8mb4_0900_ai_ci COMMENT ='用户表';
|
|
||||||
|
|
||||||
--
|
|
||||||
-- 转储表的索引
|
|
||||||
--
|
|
||||||
|
|
||||||
--
|
|
||||||
-- 表的索引 `oa_config`
|
|
||||||
--
|
|
||||||
ALTER TABLE `oa_config`
|
|
||||||
ADD PRIMARY KEY (`id`),
|
|
||||||
ADD UNIQUE KEY `oa_config_value_uindex` (`value`);
|
|
||||||
|
|
||||||
--
|
|
||||||
-- 表的索引 `oa_permissions`
|
|
||||||
--
|
|
||||||
ALTER TABLE `oa_permissions`
|
|
||||||
ADD PRIMARY KEY (`id`),
|
|
||||||
ADD KEY `oa_permissions_oa_permissions_id_fk` (`pid`);
|
|
||||||
|
|
||||||
--
|
|
||||||
-- 表的索引 `oa_project`
|
|
||||||
--
|
|
||||||
ALTER TABLE `oa_project`
|
|
||||||
ADD PRIMARY KEY (`id`),
|
|
||||||
ADD KEY `oa_project_oa_project_type_id_fk` (`type`);
|
|
||||||
|
|
||||||
--
|
|
||||||
-- 表的索引 `oa_project_cutting`
|
|
||||||
--
|
|
||||||
ALTER TABLE `oa_project_cutting`
|
|
||||||
ADD PRIMARY KEY (`id`),
|
|
||||||
ADD KEY `oa_project_cutting_oa_project_id_fk` (`pid`);
|
|
||||||
|
|
||||||
--
|
|
||||||
-- 表的索引 `oa_project_type`
|
|
||||||
--
|
|
||||||
ALTER TABLE `oa_project_type`
|
|
||||||
ADD PRIMARY KEY (`id`);
|
|
||||||
|
|
||||||
--
|
|
||||||
-- 表的索引 `oa_project_user`
|
|
||||||
--
|
|
||||||
ALTER TABLE `oa_project_user`
|
|
||||||
ADD PRIMARY KEY (`id`),
|
|
||||||
ADD KEY `oa_project_user_oa_project_cutting_id_fk` (`pid`),
|
|
||||||
ADD KEY `oa_user_project_oa_user_id_fk` (`uid`);
|
|
||||||
|
|
||||||
--
|
|
||||||
-- 表的索引 `oa_role`
|
|
||||||
--
|
|
||||||
ALTER TABLE `oa_role`
|
|
||||||
ADD PRIMARY KEY (`id`);
|
|
||||||
|
|
||||||
--
|
|
||||||
-- 表的索引 `oa_role_permissions`
|
|
||||||
--
|
|
||||||
ALTER TABLE `oa_role_permissions`
|
|
||||||
ADD PRIMARY KEY (`rid`),
|
|
||||||
ADD KEY `oa_role_permissions_oa_permissions_id_fk` (`pid`);
|
|
||||||
|
|
||||||
--
|
|
||||||
-- 表的索引 `oa_role_user`
|
|
||||||
--
|
|
||||||
ALTER TABLE `oa_role_user`
|
|
||||||
ADD PRIMARY KEY (`uid`),
|
|
||||||
ADD KEY `oa_role_user_oa_role_id_fk` (`rid`);
|
|
||||||
|
|
||||||
--
|
|
||||||
-- 表的索引 `oa_user`
|
|
||||||
--
|
|
||||||
ALTER TABLE `oa_user`
|
|
||||||
ADD PRIMARY KEY (`id`),
|
|
||||||
ADD UNIQUE KEY `oa_user_job_id_uindex` (`job_id`),
|
|
||||||
ADD UNIQUE KEY `oa_user_email_uindex` (`email`),
|
|
||||||
ADD UNIQUE KEY `oa_user_phone_uindex` (`phone`),
|
|
||||||
ADD UNIQUE KEY `oa_user_username_uindex` (`username`);
|
|
||||||
|
|
||||||
--
|
|
||||||
-- 在导出的表使用AUTO_INCREMENT
|
|
||||||
--
|
|
||||||
|
|
||||||
--
|
|
||||||
-- 使用表AUTO_INCREMENT `oa_config`
|
|
||||||
--
|
|
||||||
ALTER TABLE `oa_config`
|
|
||||||
MODIFY `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键';
|
|
||||||
|
|
||||||
--
|
|
||||||
-- 使用表AUTO_INCREMENT `oa_permissions`
|
|
||||||
--
|
|
||||||
ALTER TABLE `oa_permissions`
|
|
||||||
MODIFY `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键';
|
|
||||||
|
|
||||||
--
|
|
||||||
-- 使用表AUTO_INCREMENT `oa_project`
|
|
||||||
--
|
|
||||||
ALTER TABLE `oa_project`
|
|
||||||
MODIFY `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '项目id';
|
|
||||||
|
|
||||||
--
|
|
||||||
-- 使用表AUTO_INCREMENT `oa_project_cutting`
|
|
||||||
--
|
|
||||||
ALTER TABLE `oa_project_cutting`
|
|
||||||
MODIFY `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键';
|
|
||||||
|
|
||||||
--
|
|
||||||
-- 使用表AUTO_INCREMENT `oa_project_type`
|
|
||||||
--
|
|
||||||
ALTER TABLE `oa_project_type`
|
|
||||||
MODIFY `id` int UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '项目类型id';
|
|
||||||
|
|
||||||
--
|
|
||||||
-- 使用表AUTO_INCREMENT `oa_project_user`
|
|
||||||
--
|
|
||||||
ALTER TABLE `oa_project_user`
|
|
||||||
MODIFY `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键id';
|
|
||||||
|
|
||||||
--
|
|
||||||
-- 使用表AUTO_INCREMENT `oa_role`
|
|
||||||
--
|
|
||||||
ALTER TABLE `oa_role`
|
|
||||||
MODIFY `id` int UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '角色id';
|
|
||||||
|
|
||||||
--
|
|
||||||
-- 使用表AUTO_INCREMENT `oa_user`
|
|
||||||
--
|
|
||||||
ALTER TABLE `oa_user`
|
|
||||||
MODIFY `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键';
|
|
||||||
|
|
||||||
--
|
|
||||||
-- 限制导出的表
|
|
||||||
--
|
|
||||||
|
|
||||||
--
|
|
||||||
-- 限制表 `oa_permissions`
|
|
||||||
--
|
|
||||||
ALTER TABLE `oa_permissions`
|
|
||||||
ADD CONSTRAINT `oa_permissions_oa_permissions_id_fk` FOREIGN KEY (`pid`) REFERENCES `oa_permissions` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
--
|
|
||||||
-- 限制表 `oa_project`
|
|
||||||
--
|
|
||||||
ALTER TABLE `oa_project`
|
|
||||||
ADD CONSTRAINT `oa_project_oa_project_type_id_fk` FOREIGN KEY (`type`) REFERENCES `oa_project_type` (`id`) ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
--
|
|
||||||
-- 限制表 `oa_project_cutting`
|
|
||||||
--
|
|
||||||
ALTER TABLE `oa_project_cutting`
|
|
||||||
ADD CONSTRAINT `oa_project_cutting_oa_project_id_fk` FOREIGN KEY (`pid`) REFERENCES `oa_project` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
--
|
|
||||||
-- 限制表 `oa_project_user`
|
|
||||||
--
|
|
||||||
ALTER TABLE `oa_project_user`
|
|
||||||
ADD CONSTRAINT `oa_project_user_oa_project_cutting_id_fk` FOREIGN KEY (`pid`) REFERENCES `oa_project_cutting` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
|
||||||
ADD CONSTRAINT `oa_user_project_oa_user_id_fk` FOREIGN KEY (`uid`) REFERENCES `oa_user` (`id`);
|
|
||||||
|
|
||||||
--
|
|
||||||
-- 限制表 `oa_role_permissions`
|
|
||||||
--
|
|
||||||
ALTER TABLE `oa_role_permissions`
|
|
||||||
ADD CONSTRAINT `oa_role_permissions_oa_permissions_id_fk` FOREIGN KEY (`pid`) REFERENCES `oa_permissions` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
|
||||||
ADD CONSTRAINT `oa_role_permissions_oa_role_id_fk` FOREIGN KEY (`rid`) REFERENCES `oa_role` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
--
|
|
||||||
-- 限制表 `oa_role_user`
|
|
||||||
--
|
|
||||||
ALTER TABLE `oa_role_user`
|
|
||||||
ADD CONSTRAINT `oa_role_user_oa_role_id_fk` FOREIGN KEY (`rid`) REFERENCES `oa_role` (`id`),
|
|
||||||
ADD CONSTRAINT `oa_role_user_oa_user_id_fk` FOREIGN KEY (`uid`) REFERENCES `oa_user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
||||||
COMMIT;
|
|
||||||
|
|
||||||
/*!40101 SET CHARACTER_SET_CLIENT = @OLD_CHARACTER_SET_CLIENT */;
|
|
||||||
/*!40101 SET CHARACTER_SET_RESULTS = @OLD_CHARACTER_SET_RESULTS */;
|
|
||||||
/*!40101 SET COLLATION_CONNECTION = @OLD_COLLATION_CONNECTION */;
|
|
146
pom.xml
146
pom.xml
|
@ -1,146 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<parent>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-parent</artifactId>
|
|
||||||
<version>2.7.14</version>
|
|
||||||
<relativePath/> <!-- lookup parent from repository -->
|
|
||||||
</parent>
|
|
||||||
<groupId>com.jsl</groupId>
|
|
||||||
<artifactId>oa</artifactId>
|
|
||||||
<version>1.1.0</version>
|
|
||||||
<name>JSL_OrganizeInternalOA</name>
|
|
||||||
<description>JSL_OrganizeInternalOA</description>
|
|
||||||
<properties>
|
|
||||||
<java.version>1.8</java.version>
|
|
||||||
</properties>
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- Lombok -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.projectlombok</groupId>
|
|
||||||
<artifactId>lombok</artifactId>
|
|
||||||
<scope>annotationProcessor</scope>
|
|
||||||
</dependency>
|
|
||||||
<!-- SpringBoot Web -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.mybatis.spring.boot</groupId>
|
|
||||||
<artifactId>mybatis-spring-boot-starter</artifactId>
|
|
||||||
<version>2.3.1</version>
|
|
||||||
</dependency>
|
|
||||||
<!-- MySQL -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.mysql</groupId>
|
|
||||||
<artifactId>mysql-connector-j</artifactId>
|
|
||||||
<scope>runtime</scope>
|
|
||||||
</dependency>
|
|
||||||
<!-- BCrypt 校验 -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.mindrot</groupId>
|
|
||||||
<artifactId>jbcrypt</artifactId>
|
|
||||||
<version>0.4</version>
|
|
||||||
</dependency>
|
|
||||||
<!-- SpringBoot Validation(校验) -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-validation</artifactId>
|
|
||||||
<version>3.1.5</version>
|
|
||||||
</dependency>
|
|
||||||
<!-- SpringBoot Aop -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-aop</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<!-- Shiro -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.shiro</groupId>
|
|
||||||
<artifactId>shiro-spring-boot-starter</artifactId>
|
|
||||||
<version>1.9.1</version>
|
|
||||||
</dependency>
|
|
||||||
<!-- Jwt Token -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.jsonwebtoken</groupId>
|
|
||||||
<artifactId>jjwt-api</artifactId>
|
|
||||||
<version>0.11.3</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.jsonwebtoken</groupId>
|
|
||||||
<artifactId>jjwt-impl</artifactId>
|
|
||||||
<version>0.11.3</version>
|
|
||||||
<scope>runtime</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.jsonwebtoken</groupId>
|
|
||||||
<artifactId>jjwt-jackson</artifactId>
|
|
||||||
<version>0.11.3</version>
|
|
||||||
<scope>runtime</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- SpringBoot Test -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.mybatis.spring.boot</groupId>
|
|
||||||
<artifactId>mybatis-spring-boot-starter-test</artifactId>
|
|
||||||
<version>2.3.1</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-test</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<!-- Redis -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>redis.clients</groupId>
|
|
||||||
<artifactId>jedis</artifactId>
|
|
||||||
<version>3.8.0</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- SpringBoot Redis -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<!-- Jetbrains -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jetbrains</groupId>
|
|
||||||
<artifactId>annotations</artifactId>
|
|
||||||
<version>24.1.0</version>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
|
||||||
<!-- SpringBoot Mail -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-mail</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<!-- Gson -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.google.code.gson</groupId>
|
|
||||||
<artifactId>gson</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<!-- SpringBoot Thymeleaf -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
|
|
||||||
</project>
|
|
|
@ -1,13 +0,0 @@
|
||||||
package com.jsl.oa;
|
|
||||||
|
|
||||||
import org.springframework.boot.SpringApplication;
|
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
|
||||||
|
|
||||||
@SpringBootApplication
|
|
||||||
public class JslOrganizeInternalOaApplication {
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
SpringApplication.run(JslOrganizeInternalOaApplication.class, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,80 +0,0 @@
|
||||||
package com.jsl.oa.aspect;
|
|
||||||
|
|
||||||
import com.jsl.oa.utils.ErrorCode;
|
|
||||||
import com.jsl.oa.utils.ResultUtil;
|
|
||||||
import org.aspectj.lang.ProceedingJoinPoint;
|
|
||||||
import org.aspectj.lang.annotation.Around;
|
|
||||||
import org.aspectj.lang.annotation.Aspect;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.web.context.request.RequestContextHolder;
|
|
||||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h1>用户控制器切面</h1>
|
|
||||||
* <hr/>
|
|
||||||
* 用于用户控制器的切面
|
|
||||||
*
|
|
||||||
* @since v1.0.0
|
|
||||||
* @version v1.0.0
|
|
||||||
* @author 筱锋xiao_lfeng
|
|
||||||
*/
|
|
||||||
@Aspect
|
|
||||||
@Component
|
|
||||||
public class UserControllerAspect {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h1>用户控制器切面</h1>
|
|
||||||
* <hr/>
|
|
||||||
* 用于用户控制器的切面
|
|
||||||
*
|
|
||||||
* @since v1.0.0
|
|
||||||
* @param pjp ProceedingJoinPoint对象
|
|
||||||
* @return {@link Object}
|
|
||||||
* @throws Throwable 异常
|
|
||||||
*/
|
|
||||||
@Around("execution(* com.jsl.oa.controllers.AuthController.*(..))")
|
|
||||||
public Object controllerAround(ProceedingJoinPoint pjp) throws Throwable {
|
|
||||||
// 获取HttpServletRequest对象
|
|
||||||
HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
|
|
||||||
|
|
||||||
// 时间戳检查
|
|
||||||
if (checkTimestamp(request)) {
|
|
||||||
// TODO: 2023/12/21 0001 后期固定业务(如:日志处理)
|
|
||||||
return pjp.proceed();
|
|
||||||
} else {
|
|
||||||
return ResultUtil.error(ErrorCode.TIMESTAMP_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h1>时间戳检查</h1>
|
|
||||||
* <hr/>
|
|
||||||
* 用于检查时间戳是否合法,合法时间范围正负5秒
|
|
||||||
*
|
|
||||||
* @since v1.0.0
|
|
||||||
* @param request HttpServletRequest对象
|
|
||||||
* @return {@link Boolean}
|
|
||||||
*/
|
|
||||||
public Boolean checkTimestamp(@NotNull HttpServletRequest request) {
|
|
||||||
// 获取请求头中的时间戳
|
|
||||||
String getTimestamp = request.getHeader("Timestamp");
|
|
||||||
// 判断是否为空
|
|
||||||
if (getTimestamp == null || getTimestamp.isEmpty()) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
if (getTimestamp.length() == 10) {
|
|
||||||
getTimestamp += "000";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 获取当前时间戳
|
|
||||||
long nowTimestamp = System.currentTimeMillis();
|
|
||||||
|
|
||||||
// 时间误差允许前后五秒钟
|
|
||||||
return nowTimestamp - Long.parseLong(getTimestamp) <= 5000 && nowTimestamp - Long.parseLong(getTimestamp) >= -5000;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
package com.jsl.oa.common.constant;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
public enum BusinessConstants {
|
|
||||||
BUSINESS_LOGIN("login:", "登陆实现");
|
|
||||||
|
|
||||||
private final String value;
|
|
||||||
private final String description;
|
|
||||||
|
|
||||||
BusinessConstants(String value, String description) {
|
|
||||||
this.value = value;
|
|
||||||
this.description = description;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
package com.jsl.oa.common.constant;
|
|
||||||
|
|
||||||
import com.jsl.oa.utils.EmailRedisUtil;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h1>Redis常量类</h1>
|
|
||||||
* <hr/>
|
|
||||||
* 用于存放Redis常量
|
|
||||||
*
|
|
||||||
* @version v1.1.0
|
|
||||||
* @since v1.1.0
|
|
||||||
* @see EmailRedisUtil
|
|
||||||
* @author 筱锋xiao_lfeng
|
|
||||||
*/
|
|
||||||
public class RedisConstant {
|
|
||||||
/*
|
|
||||||
* 类型分类
|
|
||||||
*/
|
|
||||||
public static final String TYPE_USER = "user:"; // 用户相关
|
|
||||||
public static final String TYPE_EMAIL = "mail:"; // 邮件相关
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 表分类
|
|
||||||
*/
|
|
||||||
public static final String TABLE_USER = "user:"; // 用户表
|
|
||||||
public static final String TABLE_EMAIL = "code:"; // 邮箱验证码
|
|
||||||
}
|
|
|
@ -1,106 +0,0 @@
|
||||||
package com.jsl.oa.config;
|
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import com.jsl.oa.utils.ErrorCode;
|
|
||||||
import com.jsl.oa.utils.JwtUtil;
|
|
||||||
import com.jsl.oa.utils.ResultUtil;
|
|
||||||
import org.apache.shiro.authc.ExpiredCredentialsException;
|
|
||||||
import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
|
|
||||||
|
|
||||||
import javax.servlet.ServletRequest;
|
|
||||||
import javax.servlet.ServletResponse;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h1>JWT过滤器</h1>
|
|
||||||
* <hr/>
|
|
||||||
* 用于JWT的过滤器
|
|
||||||
*
|
|
||||||
* @author 筱锋xiao_lfeng
|
|
||||||
* @version v1.1.0
|
|
||||||
* @since v1.1.0
|
|
||||||
*/
|
|
||||||
public class JwtFilter extends BasicHttpAuthenticationFilter {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h2>判断用户Token</h2>
|
|
||||||
* <hr/>
|
|
||||||
* 判断用户Token是否存在,如果存在则进行验证
|
|
||||||
*
|
|
||||||
* @param request 请求
|
|
||||||
* @param response 响应
|
|
||||||
* @param mappedValue 映射值
|
|
||||||
* @return {@link Boolean}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
|
|
||||||
// 判断是否存在Authorization Header
|
|
||||||
String token = getAuthzHeader(request);
|
|
||||||
if (token == null || token.isEmpty()) {
|
|
||||||
return false; // 未提供Token,拒绝访问
|
|
||||||
} else {
|
|
||||||
// 解析Bearer后面的令牌
|
|
||||||
token = token.replace("Bearer ", "");
|
|
||||||
System.out.println(token);
|
|
||||||
return JwtUtil.verify(token);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h2>访问被拒绝时</h2>
|
|
||||||
* <hr/>
|
|
||||||
* 当访问被拒绝时,会调用此方法
|
|
||||||
*
|
|
||||||
* @param request 请求
|
|
||||||
* @param response 响应
|
|
||||||
* @param mappedValue 映射值
|
|
||||||
* @return {@link Boolean}
|
|
||||||
* @throws Exception 异常
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected boolean onAccessDenied(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
|
|
||||||
try {
|
|
||||||
// 尝试获取Authorization Header
|
|
||||||
String token = getAuthzHeader(request);
|
|
||||||
if (token == null || token.isEmpty()) {
|
|
||||||
// 未提供Token,拒绝访问
|
|
||||||
Gson gson = new Gson();
|
|
||||||
response.setContentType("application/json;charset=UTF-8");
|
|
||||||
response.getWriter().println(gson.toJson(ResultUtil.error(ErrorCode.UNAUTHORIZED)));
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
// 解析Bearer后面的令牌
|
|
||||||
token = token.replace("Bearer ", "");
|
|
||||||
System.out.println(token);
|
|
||||||
if (JwtUtil.verify(token)) {
|
|
||||||
// Token验证通过
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
// Token验证失败,抛出异常
|
|
||||||
throw new ExpiredCredentialsException("Token已过期");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (ExpiredCredentialsException e) {
|
|
||||||
// 处理Token过期异常,返回自定义的JSON信息
|
|
||||||
Gson gson = new Gson();
|
|
||||||
response.setContentType("application/json;charset=UTF-8");
|
|
||||||
response.getWriter().println(gson.toJson(ResultUtil.error(ErrorCode.TOKEN_EXPIRED)));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h2>获取Authorization Header</h2>
|
|
||||||
* <hr/>
|
|
||||||
* 用于获取Authorization Header
|
|
||||||
*
|
|
||||||
* @param request 请求
|
|
||||||
* @return {@link String}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected String getAuthzHeader(ServletRequest request) {
|
|
||||||
HttpServletRequest httpRequest = (HttpServletRequest) request;
|
|
||||||
return httpRequest.getHeader("Authorization");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,47 +0,0 @@
|
||||||
package com.jsl.oa.config;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.mail.javamail.JavaMailSender;
|
|
||||||
import org.springframework.mail.javamail.JavaMailSenderImpl;
|
|
||||||
|
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h1>邮件配置类</h1>
|
|
||||||
* <hr/>
|
|
||||||
* 用于配置邮件发送相关信息
|
|
||||||
*
|
|
||||||
* @since v1.1.0
|
|
||||||
* @version v1.1.0
|
|
||||||
* @author 筱锋xiao_lfeng
|
|
||||||
*/
|
|
||||||
@Configuration
|
|
||||||
public class MailConfiguration {
|
|
||||||
|
|
||||||
@Value("${spring.mail.host}")
|
|
||||||
private String emailHost;
|
|
||||||
@Value("${spring.mail.username}")
|
|
||||||
private String emailUsername;
|
|
||||||
@Value("${spring.mail.password}")
|
|
||||||
private String emailPassword;
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public JavaMailSender javaMailSender() {
|
|
||||||
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
|
|
||||||
mailSender.setDefaultEncoding("UTF-8");
|
|
||||||
mailSender.setHost(emailHost);
|
|
||||||
mailSender.setPort(25); // 你的邮件服务器端口
|
|
||||||
mailSender.setUsername(emailUsername);
|
|
||||||
mailSender.setPassword(emailPassword);
|
|
||||||
|
|
||||||
Properties props = mailSender.getJavaMailProperties();
|
|
||||||
props.put("mail.transport.protocol", "smtp");
|
|
||||||
props.put("mail.smtp.auth", "true");
|
|
||||||
props.put("mail.smtp.starttls.enable", "true");
|
|
||||||
props.put("mail.debug", "true");
|
|
||||||
|
|
||||||
return mailSender;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,46 +0,0 @@
|
||||||
package com.jsl.oa.config.redis;
|
|
||||||
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
|
||||||
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
|
|
||||||
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
|
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
|
||||||
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
|
|
||||||
import org.springframework.data.redis.serializer.RedisSerializer;
|
|
||||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h1>Redis配置类</h1>
|
|
||||||
* <hr/>
|
|
||||||
* 用于配置Redis
|
|
||||||
*
|
|
||||||
* @author 筱锋xiao_lfeng
|
|
||||||
* @version v1.1.0
|
|
||||||
* @since v1.1.0
|
|
||||||
*/
|
|
||||||
@Configuration
|
|
||||||
public class RedisConfiguration {
|
|
||||||
@Bean
|
|
||||||
public JedisConnectionFactory jedisConnectionFactory() {
|
|
||||||
RedisStandaloneConfiguration config = new RedisStandaloneConfiguration("localhost");
|
|
||||||
return new JedisConnectionFactory(config);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
|
|
||||||
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
|
|
||||||
redisTemplate.setConnectionFactory(connectionFactory);
|
|
||||||
|
|
||||||
// 配置Redis编码格式
|
|
||||||
RedisSerializer<String> stringSerializer = new StringRedisSerializer();
|
|
||||||
RedisSerializer<Object> jsonSerializer = new GenericJackson2JsonRedisSerializer();
|
|
||||||
|
|
||||||
redisTemplate.setKeySerializer(stringSerializer);
|
|
||||||
redisTemplate.setValueSerializer(jsonSerializer);
|
|
||||||
redisTemplate.setHashKeySerializer(stringSerializer);
|
|
||||||
redisTemplate.setHashValueSerializer(jsonSerializer);
|
|
||||||
|
|
||||||
return redisTemplate;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,59 +0,0 @@
|
||||||
package com.jsl.oa.config.redis;
|
|
||||||
|
|
||||||
import com.jsl.oa.common.constant.BusinessConstants;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
|
||||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public abstract class RedisOperating<R> {
|
|
||||||
protected final RedisTemplate<String, R> redisTemplate;
|
|
||||||
protected final StringRedisTemplate stringRedisTemplate;
|
|
||||||
|
|
||||||
public abstract Long getExpiredAt(BusinessConstants businessConstants, String field);
|
|
||||||
public abstract Boolean delData(BusinessConstants businessConstants, String field);
|
|
||||||
public abstract R getData(BusinessConstants businessConstants, String field);
|
|
||||||
public abstract Boolean setData(BusinessConstants businessConstants, String field, R value, Integer time);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h2>获取Redis中元素过期时间</h2>
|
|
||||||
* <hr/>
|
|
||||||
* 基础方法,用于添加String元素到Redis<br/>
|
|
||||||
*
|
|
||||||
* @param key 索引
|
|
||||||
* @return 返回过期时间
|
|
||||||
*/
|
|
||||||
public Long getExpiredAt(String key) {
|
|
||||||
return redisTemplate.getExpire(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h2>基础添加String元素到Redis</h2>
|
|
||||||
* <hr/>
|
|
||||||
* 基础方法,用于添加String元素到Redis<br/>
|
|
||||||
* 默认处理时间,单位时间秒
|
|
||||||
*
|
|
||||||
* @param key 键
|
|
||||||
* @param value 值
|
|
||||||
*/
|
|
||||||
public void set(String key, String value, Integer time) {
|
|
||||||
stringRedisTemplate.opsForValue().set(key, value);
|
|
||||||
stringRedisTemplate.expire(key, time, TimeUnit.SECONDS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h2>基础添加元素到Redis</h2>
|
|
||||||
* <hr/>
|
|
||||||
* 基础方法,用于添加元素元素到Redis<br/>
|
|
||||||
* 默认处理时间,单位时间秒
|
|
||||||
*
|
|
||||||
* @param key 键
|
|
||||||
* @param value 值
|
|
||||||
*/
|
|
||||||
public void set(String key, R value, Integer time) {
|
|
||||||
redisTemplate.opsForValue().set(key, value);
|
|
||||||
redisTemplate.expire(key, time, TimeUnit.SECONDS);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,40 +0,0 @@
|
||||||
package com.jsl.oa.config.shiro;
|
|
||||||
|
|
||||||
import com.jsl.oa.services.UserService;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.apache.shiro.authc.AuthenticationException;
|
|
||||||
import org.apache.shiro.authc.AuthenticationInfo;
|
|
||||||
import org.apache.shiro.authc.AuthenticationToken;
|
|
||||||
import org.apache.shiro.authz.AuthorizationInfo;
|
|
||||||
import org.apache.shiro.realm.AuthorizingRealm;
|
|
||||||
import org.apache.shiro.subject.PrincipalCollection;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class MyRealm extends AuthorizingRealm {
|
|
||||||
|
|
||||||
private final UserService userService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 授权
|
|
||||||
*
|
|
||||||
* @return 授权信息
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected AuthorizationInfo doGetAuthorizationInfo(@NotNull PrincipalCollection principals) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 认证
|
|
||||||
*
|
|
||||||
* @param authenticationToken 令牌
|
|
||||||
* @return 认证信息
|
|
||||||
* @throws AuthenticationException 认证异常
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,56 +0,0 @@
|
||||||
package com.jsl.oa.config.shiro;
|
|
||||||
|
|
||||||
import com.jsl.oa.config.JwtFilter;
|
|
||||||
import com.jsl.oa.services.UserService;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
|
|
||||||
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
|
|
||||||
import javax.servlet.Filter;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class ShiroConfiguration {
|
|
||||||
|
|
||||||
private final UserService userService;
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
|
|
||||||
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
|
|
||||||
shiroFilterFactoryBean.setSecurityManager(securityManager);
|
|
||||||
|
|
||||||
// 配置过滤器规则
|
|
||||||
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
|
|
||||||
filterChainDefinitionMap.put("/auth/**", "anon"); // 登录接口允许匿名访问
|
|
||||||
filterChainDefinitionMap.put("/unauthorized", "anon"); // 未授权接口允许匿名访问
|
|
||||||
filterChainDefinitionMap.put("/", "anon"); // 首页允许匿名访问
|
|
||||||
filterChainDefinitionMap.put("/**/**", "jwt"); // 其他接口一律拦截(需要Token)
|
|
||||||
|
|
||||||
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
|
|
||||||
|
|
||||||
// 设置未登陆响应接口
|
|
||||||
shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");
|
|
||||||
|
|
||||||
// 添加JWT过滤器
|
|
||||||
Map<String, Filter> filters = new LinkedHashMap<>();
|
|
||||||
filters.put("jwt", new JwtFilter()); // 配置自定义的JWT过滤器
|
|
||||||
shiroFilterFactoryBean.setFilters(filters);
|
|
||||||
return shiroFilterFactoryBean;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public DefaultWebSecurityManager securityManager(MyRealm realm) {
|
|
||||||
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
|
|
||||||
securityManager.setRealm(realm);
|
|
||||||
return securityManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public MyRealm myRealm() {
|
|
||||||
return new MyRealm(userService);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,125 +0,0 @@
|
||||||
package com.jsl.oa.controllers;
|
|
||||||
|
|
||||||
import com.jsl.oa.model.voData.UserLoginVO;
|
|
||||||
import com.jsl.oa.model.voData.UserRegisterVO;
|
|
||||||
import com.jsl.oa.services.AuthService;
|
|
||||||
import com.jsl.oa.utils.BaseResponse;
|
|
||||||
import com.jsl.oa.utils.ErrorCode;
|
|
||||||
import com.jsl.oa.utils.Processing;
|
|
||||||
import com.jsl.oa.utils.ResultUtil;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.springframework.validation.BindingResult;
|
|
||||||
import org.springframework.validation.annotation.Validated;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
|
||||||
|
|
||||||
import java.text.ParseException;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h1>用户认证控制器</h1>
|
|
||||||
* <hr/>
|
|
||||||
* 用户认证控制器,包含用户注册、用户登录、用户登出接口
|
|
||||||
*
|
|
||||||
* @version v1.1.0
|
|
||||||
* @see AuthService
|
|
||||||
* @see UserRegisterVO
|
|
||||||
* @see UserLoginVO
|
|
||||||
* @see BaseResponse
|
|
||||||
* @see ErrorCode
|
|
||||||
* @see Processing
|
|
||||||
* @see ResultUtil
|
|
||||||
* @since v1.0.0
|
|
||||||
*/
|
|
||||||
@RestController
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class AuthController {
|
|
||||||
private final AuthService authService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h2>用户注册</h2>
|
|
||||||
* <hr/>
|
|
||||||
* 用户注册接口
|
|
||||||
*
|
|
||||||
* @return {@link BaseResponse}
|
|
||||||
* @author 筱锋xiao_lfeng
|
|
||||||
* @since v1.0.0
|
|
||||||
*/
|
|
||||||
@PostMapping("/auth/register")
|
|
||||||
public BaseResponse authRegister(@RequestBody @Validated UserRegisterVO userRegisterVO, @NotNull BindingResult bindingResult) throws ParseException {
|
|
||||||
// 判断是否有参数错误
|
|
||||||
if (bindingResult.hasErrors()) {
|
|
||||||
return ResultUtil.error(ErrorCode.REQUEST_BODY_ERROR, Processing.getValidatedErrorList(bindingResult));
|
|
||||||
}
|
|
||||||
return authService.authRegister(userRegisterVO);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h2>用户登录</h2>
|
|
||||||
* <hr/>
|
|
||||||
* 用户登录接口
|
|
||||||
*
|
|
||||||
* @param userLoginVO 用户登录信息
|
|
||||||
* @param bindingResult 参数校验结果
|
|
||||||
* @return {@link BaseResponse}
|
|
||||||
* @author 176yunxuan
|
|
||||||
* @since v1.0.0
|
|
||||||
*/
|
|
||||||
@GetMapping("/auth/login")
|
|
||||||
public BaseResponse authLogin(@RequestBody @Validated UserLoginVO userLoginVO, @NotNull BindingResult bindingResult) {
|
|
||||||
// 判断是否有参数错误
|
|
||||||
if (bindingResult.hasErrors()) {
|
|
||||||
return ResultUtil.error(ErrorCode.REQUEST_BODY_ERROR, Processing.getValidatedErrorList(bindingResult));
|
|
||||||
}
|
|
||||||
return authService.authLogin(userLoginVO);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h2>用户邮箱登录</h2>
|
|
||||||
* <hr/>
|
|
||||||
* 用户邮箱登录接口
|
|
||||||
*
|
|
||||||
* @param email 用户登陆邮箱
|
|
||||||
* @return {@link BaseResponse}
|
|
||||||
* @author 筱锋xiao_lfeng
|
|
||||||
* @since v1.1.0
|
|
||||||
*/
|
|
||||||
@GetMapping("/auth/login/email/code")
|
|
||||||
public BaseResponse authLoginSendEmailCode(@RequestParam String email) {
|
|
||||||
if (email != null) {
|
|
||||||
if (Pattern.matches("^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$", email)) {
|
|
||||||
return authService.authLoginSendEmailCode(email);
|
|
||||||
} else {
|
|
||||||
return ResultUtil.error(ErrorCode.PARAMETER_ERROR);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return ResultUtil.error(ErrorCode.PARAMETER_ERROR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/auth/login/email")
|
|
||||||
public BaseResponse authLoginByEmail(@RequestParam String email, @RequestParam Integer code) {
|
|
||||||
if (email != null && code != null) {
|
|
||||||
if (Pattern.matches("^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$", email)) {
|
|
||||||
return authService.authLoginByEmail(email, code);
|
|
||||||
} else {
|
|
||||||
return ResultUtil.error(ErrorCode.PARAMETER_ERROR);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return ResultUtil.error(ErrorCode.PARAMETER_ERROR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h2>用户登出</h2>
|
|
||||||
* <hr/>
|
|
||||||
* 用户登出接口
|
|
||||||
*
|
|
||||||
* @return {@link BaseResponse}
|
|
||||||
* @since v1.1.0
|
|
||||||
*/
|
|
||||||
@GetMapping("/auth/logout")
|
|
||||||
public BaseResponse authLogout() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
package com.jsl.oa.controllers;
|
|
||||||
|
|
||||||
import com.jsl.oa.services.MailService;
|
|
||||||
import com.jsl.oa.utils.BaseResponse;
|
|
||||||
import com.jsl.oa.utils.ResultUtil;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.boot.web.servlet.error.ErrorController;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class CustomController implements ErrorController {
|
|
||||||
|
|
||||||
private final MailService mailService;
|
|
||||||
|
|
||||||
@RequestMapping("/")
|
|
||||||
public BaseResponse index() {
|
|
||||||
return ResultUtil.success("欢迎使用JSL-OA系统,服务器处于正常状态");
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping("/error")
|
|
||||||
public ResponseEntity<BaseResponse> handleError() {
|
|
||||||
return ResultUtil.error("PageNotFound", 404, "请求资源不存在");
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping("/unauthorized")
|
|
||||||
public ResponseEntity<BaseResponse> handleUnauthorized() {
|
|
||||||
return ResultUtil.error("Unauthorized", 401, "未授权");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
package com.jsl.oa.controllers;
|
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class InfoController {
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
package com.jsl.oa.controllers;
|
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class PermissionController {
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
package com.jsl.oa.controllers;
|
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class ProjectController {
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
package com.jsl.oa.controllers;
|
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
|
|
||||||
public class RoleController {
|
|
||||||
}
|
|
|
@ -1,66 +0,0 @@
|
||||||
package com.jsl.oa.dao;
|
|
||||||
|
|
||||||
import com.jsl.oa.mapper.UserMapper;
|
|
||||||
import com.jsl.oa.model.doData.UserDO;
|
|
||||||
import com.jsl.oa.model.voData.UserDeleteVO;
|
|
||||||
import com.jsl.oa.model.voData.UserEditProfile;
|
|
||||||
import com.jsl.oa.model.voData.UserLockVO;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
@Component
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class UserDAO {
|
|
||||||
|
|
||||||
private final UserMapper userMapper;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h2>用户名获取用户信息</h2>
|
|
||||||
* <hr/>
|
|
||||||
* 根据用户名获取用户信息
|
|
||||||
*
|
|
||||||
* @param username 用户名
|
|
||||||
* @author 筱锋xiao_lfeng
|
|
||||||
* @return {@link UserDO}
|
|
||||||
*/
|
|
||||||
public UserDO getUserInfoByUsername(String username) {
|
|
||||||
UserDO userDO = null;
|
|
||||||
// 从 Redis 获取数据
|
|
||||||
// TODO: 10000-Redis: 从 Redis 获取数据
|
|
||||||
// 从数据库获取用户信息
|
|
||||||
if (userDO == null) {
|
|
||||||
userDO = userMapper.getUserInfoByUsername(username);
|
|
||||||
}
|
|
||||||
return userDO;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据id判断用户是否存在
|
|
||||||
* @param id
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public Boolean isExistUser(Long id){
|
|
||||||
if(userMapper.getUserById(id)==null) {
|
|
||||||
return false;
|
|
||||||
}else return true;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 用户账号删除
|
|
||||||
* @param userDeleteVO
|
|
||||||
*/
|
|
||||||
public void userDelete(UserDeleteVO userDeleteVO) {
|
|
||||||
userMapper.userDelete(userDeleteVO);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用户账号锁定
|
|
||||||
* @param userLockVO
|
|
||||||
*/
|
|
||||||
public void userLock(UserLockVO userLockVO) {
|
|
||||||
userMapper.userLock(userLockVO);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void userEditProfile(UserEditProfile userEditProfile) {
|
|
||||||
userMapper.userEditProfile(userEditProfile);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
package com.jsl.oa.exception;
|
|
||||||
|
|
||||||
import com.jsl.oa.utils.ErrorCode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h1>业务异常类</h1>
|
|
||||||
* <hr/>
|
|
||||||
* 用于处理业务异常
|
|
||||||
*
|
|
||||||
* @since v1.0.0
|
|
||||||
* @version v1.0.0
|
|
||||||
* @author 筱锋xiao_lfeng
|
|
||||||
* @see RuntimeException
|
|
||||||
*/
|
|
||||||
public class BusinessException extends RuntimeException {
|
|
||||||
|
|
||||||
public BusinessException(ErrorCode errorCode) {
|
|
||||||
super(errorCode.getOutput() + "|" + errorCode.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
package com.jsl.oa.exception;
|
|
||||||
|
|
||||||
import com.jsl.oa.utils.BaseResponse;
|
|
||||||
import com.jsl.oa.utils.ResultUtil;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.web.HttpRequestMethodNotSupportedException;
|
|
||||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
|
||||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
|
||||||
|
|
||||||
import java.sql.SQLIntegrityConstraintViolationException;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
@ControllerAdvice
|
|
||||||
public class ProcessException {
|
|
||||||
|
|
||||||
@ExceptionHandler(value = Exception.class)
|
|
||||||
public ResponseEntity<BaseResponse> businessException(@NotNull Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return ResultUtil.error("Exception", 500, "服务器异常");
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)
|
|
||||||
public ResponseEntity<BaseResponse> businessMethodNotAllowedException() {
|
|
||||||
return ResultUtil.error("MethodNotAllowed", 405, "请求方法错误");
|
|
||||||
}
|
|
||||||
|
|
||||||
@ExceptionHandler(value = SQLIntegrityConstraintViolationException.class)
|
|
||||||
public ResponseEntity<BaseResponse> businessSQLIntegrityConstraintViolationException(@NotNull SQLIntegrityConstraintViolationException e) {
|
|
||||||
if (Pattern.matches(".*Duplicate entry.*", e.getMessage())) {
|
|
||||||
return ResultUtil.error("DuplicateEntry", 400, "数据重复");
|
|
||||||
} else if (Pattern.matches(".*Cannot delete or update a parent row: a foreign key constraint fails.*", e.getMessage())) {
|
|
||||||
return ResultUtil.error("DataAssociation", 400, "数据存在关联,无法删除");
|
|
||||||
} else {
|
|
||||||
return ResultUtil.error("DatabaseError", 400, "数据库异常");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,52 +0,0 @@
|
||||||
package com.jsl.oa.mapper;
|
|
||||||
|
|
||||||
import com.jsl.oa.model.doData.UserDO;
|
|
||||||
import com.jsl.oa.model.voData.UserDeleteVO;
|
|
||||||
import com.jsl.oa.model.voData.UserEditProfile;
|
|
||||||
import com.jsl.oa.model.voData.UserLockVO;
|
|
||||||
import com.jsl.oa.model.voData.UserLoginVO;
|
|
||||||
import org.apache.ibatis.annotations.Insert;
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
|
||||||
import org.apache.ibatis.annotations.Select;
|
|
||||||
import org.apache.ibatis.annotations.Update;
|
|
||||||
|
|
||||||
@Mapper
|
|
||||||
public interface UserMapper {
|
|
||||||
|
|
||||||
@Select("SELECT * FROM organize_oa.oa_user WHERE username = #{username}")
|
|
||||||
UserDO getUserInfoByUsername(String username);
|
|
||||||
|
|
||||||
@Select("SELECT * FROM organize_oa.oa_user WHERE job_id = #{jobId}")
|
|
||||||
UserDO getUserByUserNum(String jobId);
|
|
||||||
|
|
||||||
@Insert("INSERT INTO organize_oa.oa_user " +
|
|
||||||
"(job_id, username, password, address, phone, email, age, sex) " +
|
|
||||||
"VALUES (#{jobId}, #{username}, #{password}, #{address}, #{phone}, #{email}, #{age}, #{sex})")
|
|
||||||
boolean insertUser(UserDO userDO);
|
|
||||||
|
|
||||||
@Select("SELECT password FROM organize_oa.oa_user WHERE job_id = #{jobId}")
|
|
||||||
String loginPassword(UserLoginVO userLoginVO);
|
|
||||||
|
|
||||||
@Select("SELECT * FROM organize_oa.oa_user WHERE job_id = #{jobId}")
|
|
||||||
UserDO login(UserLoginVO userLoginVO);
|
|
||||||
|
|
||||||
@Update("UPDATE organize_oa.oa_user SET enabled = 0 WHERE id = #{id} ")
|
|
||||||
void userDelete(UserDeleteVO userDeleteVO);
|
|
||||||
|
|
||||||
@Update("UPDATE organize_oa.oa_user SET account_no_locked = 1 WHERE id = #{id} ")
|
|
||||||
void userLock(UserLockVO userLockVO);
|
|
||||||
|
|
||||||
@Select("SELECT * FROM organize_oa.oa_user WHERE id = #{id}")
|
|
||||||
UserDO getUserById(Long id);
|
|
||||||
|
|
||||||
@Select("SELECT * FROM organize_oa.oa_user WHERE email = #{email}")
|
|
||||||
UserDO getUserInfoByEmail(String email);
|
|
||||||
|
|
||||||
@Select("SELECT * FROM organize_oa.oa_user WHERE phone = #{phone}")
|
|
||||||
UserDO getUserInfoByPhone(String user);
|
|
||||||
|
|
||||||
@Select("SELECT * FROM organize_oa.oa_user WHERE job_id = #{jobId}")
|
|
||||||
UserDO getUserByJobId(String user);
|
|
||||||
|
|
||||||
void userEditProfile(UserEditProfile userEditProfile);
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
package com.jsl.oa.model.doData;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.experimental.Accessors;
|
|
||||||
|
|
||||||
import java.sql.Timestamp;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h1>config 数据表</h1>
|
|
||||||
* <hr/>
|
|
||||||
* 映射 oa_config 数据表内容进入自定义实体类
|
|
||||||
*
|
|
||||||
* @author 筱锋xiao_lfeng
|
|
||||||
* @since v1.1.0
|
|
||||||
* @version v1.1.0
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@Accessors(chain = true)
|
|
||||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
|
||||||
public class ConfigDO {
|
|
||||||
private Long id;
|
|
||||||
private String value;
|
|
||||||
private String data;
|
|
||||||
private Timestamp createdAt;
|
|
||||||
private Timestamp updatedAt;
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
package com.jsl.oa.model.doData;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.experimental.Accessors;
|
|
||||||
|
|
||||||
import java.sql.Timestamp;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h1>permission 数据表</h1>
|
|
||||||
* <hr/>
|
|
||||||
* 映射 oa_permission 数据表内容进入自定义实体类
|
|
||||||
*
|
|
||||||
* @author 筱锋xiao_lfeng
|
|
||||||
* @since v1.1.0
|
|
||||||
* @version v1.1.0
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@Accessors(chain = true)
|
|
||||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
|
||||||
public class PermissionDO {
|
|
||||||
private Long id;
|
|
||||||
private Long pid;
|
|
||||||
private String name;
|
|
||||||
private String code;
|
|
||||||
private Short type;
|
|
||||||
private Timestamp deletedAt;
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
package com.jsl.oa.model.doData;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.experimental.Accessors;
|
|
||||||
|
|
||||||
import java.sql.Timestamp;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h1>project_cutting 数据表</h1>
|
|
||||||
* <hr/>
|
|
||||||
* 映射 oa_project_cutting 数据表内容进入自定义实体类
|
|
||||||
*
|
|
||||||
* @author 筱锋xiao_lfeng
|
|
||||||
* @since v1.1.0
|
|
||||||
* @version v1.1.0
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@Accessors(chain = true)
|
|
||||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
|
||||||
public class ProjectCuttingDO {
|
|
||||||
private Long id;
|
|
||||||
private Long pid;
|
|
||||||
private String name;
|
|
||||||
private String tag;
|
|
||||||
private Short engineering;
|
|
||||||
private Integer estimatedTime;
|
|
||||||
private Integer realTime;
|
|
||||||
private Timestamp createdAt;
|
|
||||||
private Timestamp updatedAt;
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
package com.jsl.oa.model.doData;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.experimental.Accessors;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h1>project 数据表</h1>
|
|
||||||
* <hr/>
|
|
||||||
* 映射 oa_project 数据表内容进入自定义实体类
|
|
||||||
*
|
|
||||||
* @author 筱锋xiao_lfeng
|
|
||||||
* @since v1.1.0
|
|
||||||
* @version v1.1.0
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@Accessors(chain = true)
|
|
||||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
|
||||||
public class ProjectDO {
|
|
||||||
private Long id;
|
|
||||||
private String name;
|
|
||||||
private String description;
|
|
||||||
private String introduction;
|
|
||||||
private Boolean codeOpen;
|
|
||||||
private String coreCode;
|
|
||||||
private String git;
|
|
||||||
private Short difficultyLevel;
|
|
||||||
private Integer type;
|
|
||||||
private Long reward;
|
|
||||||
private Short status;
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
package com.jsl.oa.model.doData;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.experimental.Accessors;
|
|
||||||
|
|
||||||
import java.sql.Timestamp;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h1>project_type 数据表</h1>
|
|
||||||
* <hr/>
|
|
||||||
* 映射 oa_project_type 数据表内容进入自定义实体类
|
|
||||||
*
|
|
||||||
* @author 筱锋xiao_lfeng
|
|
||||||
* @since v1.1.0
|
|
||||||
* @version v1.1.0
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@Accessors(chain = true)
|
|
||||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
|
||||||
public class ProjectTypeDO {
|
|
||||||
private Long id;
|
|
||||||
private String name;
|
|
||||||
private Timestamp createdAt;
|
|
||||||
private Timestamp updatedAt;
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
package com.jsl.oa.model.doData;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.experimental.Accessors;
|
|
||||||
|
|
||||||
import java.sql.Timestamp;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h1>project_user 数据表</h1>
|
|
||||||
* <hr/>
|
|
||||||
* 映射 oa_project_user 数据表内容进入自定义实体类
|
|
||||||
*
|
|
||||||
* @author 筱锋xiao_lfeng
|
|
||||||
* @since v1.1.0
|
|
||||||
* @version v1.1.0
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@Accessors(chain = true)
|
|
||||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
|
||||||
public class ProjectUserDO {
|
|
||||||
private Long id;
|
|
||||||
private Long pid;
|
|
||||||
private Long uid;
|
|
||||||
private Timestamp createdAt;
|
|
||||||
private Timestamp updatedAt;
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
package com.jsl.oa.model.doData;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.experimental.Accessors;
|
|
||||||
|
|
||||||
import java.sql.Timestamp;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h1>role 数据表</h1>
|
|
||||||
* <hr/>
|
|
||||||
* 映射 oa_role 数据表内容进入自定义实体类
|
|
||||||
*
|
|
||||||
* @author 筱锋xiao_lfeng
|
|
||||||
* @since v1.1.0
|
|
||||||
* @version v1.1.0
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@Accessors(chain = true)
|
|
||||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
|
||||||
public class RoleDO {
|
|
||||||
private Long id;
|
|
||||||
private String roleName;
|
|
||||||
private Timestamp createdAt;
|
|
||||||
private Timestamp updatedAt;
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
package com.jsl.oa.model.doData;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.experimental.Accessors;
|
|
||||||
|
|
||||||
import java.sql.Timestamp;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h1>role 数据表</h1>
|
|
||||||
* <hr/>
|
|
||||||
* 映射 oa_role 数据表内容进入自定义实体类
|
|
||||||
*
|
|
||||||
* @author 筱锋xiao_lfeng
|
|
||||||
* @since v1.1.0
|
|
||||||
* @version v1.1.0
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@Accessors(chain = true)
|
|
||||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
|
||||||
public class RolePermissionDO {
|
|
||||||
private Long rid;
|
|
||||||
private Long pid;
|
|
||||||
private Timestamp createdAt;
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
package com.jsl.oa.model.doData;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.experimental.Accessors;
|
|
||||||
|
|
||||||
import java.sql.Timestamp;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h1>project_user 数据表</h1>
|
|
||||||
* <hr/>
|
|
||||||
* 映射 oa_project_user 数据表内容进入自定义实体类
|
|
||||||
*
|
|
||||||
* @author 筱锋xiao_lfeng
|
|
||||||
* @since v1.1.0
|
|
||||||
* @version v1.1.0
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@Accessors(chain = true)
|
|
||||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
|
||||||
public class RoleUserDO {
|
|
||||||
private Long uid;
|
|
||||||
private Long rid;
|
|
||||||
private Timestamp createdAt;
|
|
||||||
private Timestamp updatedAt;
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
package com.jsl.oa.model.doData;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.experimental.Accessors;
|
|
||||||
|
|
||||||
import java.sql.Timestamp;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h1>user 数据表</h1>
|
|
||||||
* <hr/>
|
|
||||||
* 映射 oa_user 数据表内容进入自定义实体类
|
|
||||||
*
|
|
||||||
* @author 筱锋xiao_lfeng
|
|
||||||
* @version v1.1.0
|
|
||||||
* @since v1.0.0
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@Accessors(chain = true)
|
|
||||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
|
||||||
public class UserDO {
|
|
||||||
private Long id;
|
|
||||||
private String jobId;
|
|
||||||
private String username;
|
|
||||||
private String password;
|
|
||||||
private String address;
|
|
||||||
private String phone;
|
|
||||||
private String email;
|
|
||||||
private Short age;
|
|
||||||
private String signature;
|
|
||||||
private String avatar;
|
|
||||||
private String nickname;
|
|
||||||
private Short sex;
|
|
||||||
private Boolean enabled;
|
|
||||||
private Boolean accountNoExpired;
|
|
||||||
private Boolean credentialsNoExpired;
|
|
||||||
private Boolean recommend;
|
|
||||||
private Boolean accountNoLocked;
|
|
||||||
private String description;
|
|
||||||
private Timestamp createdAt;
|
|
||||||
private Timestamp updatedAt;
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
package com.jsl.oa.model.voData;
|
|
||||||
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
import javax.validation.constraints.NotNull;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
public class UserDeleteVO {
|
|
||||||
@NotNull(message = "id不能为空")
|
|
||||||
private Long id;
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
package com.jsl.oa.model.voData;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
import javax.validation.constraints.NotNull;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
public class UserLockVO {
|
|
||||||
@NotNull(message = "id不能为空")
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
package com.jsl.oa.model.voData;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
import javax.validation.constraints.NotBlank;
|
|
||||||
import javax.validation.constraints.Pattern;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h1>用户登陆自定义实体类</h1>
|
|
||||||
* <hr/>
|
|
||||||
* 用于处理用户登陆表单输入的数据
|
|
||||||
*
|
|
||||||
* @author 175yunxuan
|
|
||||||
* @version v1.0.0
|
|
||||||
* @since v1.0.0
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
public class UserLoginVO {
|
|
||||||
@Pattern(regexp = "^[0-9A-Za-z_]+$", message = "支持用户名/手机号/工号登陆")
|
|
||||||
@NotBlank(message = "用户名不能为空")
|
|
||||||
private String user;
|
|
||||||
@NotBlank(message = "密码不能为空")
|
|
||||||
private String password;
|
|
||||||
}
|
|
|
@ -1,45 +0,0 @@
|
||||||
package com.jsl.oa.model.voData;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
import javax.validation.constraints.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h1>用户注册自定义实体类</h1>
|
|
||||||
* <hr/>
|
|
||||||
* 用于处理用户注册表单输入的数据
|
|
||||||
*
|
|
||||||
* @author 筱锋xiao_lfeng
|
|
||||||
* @version v1.0.0
|
|
||||||
* @since v1.1.0
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
public class UserRegisterVO {
|
|
||||||
@NotBlank(message = "用户名不能为空")
|
|
||||||
@Pattern(regexp = "^[0-9A-Za-z_]{3,40}$", message = "用户名只能为字母、数字或下划线")
|
|
||||||
private String username;
|
|
||||||
|
|
||||||
@NotBlank(message = "密码不能为空")
|
|
||||||
private String password;
|
|
||||||
|
|
||||||
@NotBlank(message = "家乡不能为空")
|
|
||||||
private String address;
|
|
||||||
|
|
||||||
@NotBlank(message = "电话不能为空")
|
|
||||||
@Pattern(regexp = "^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\\d{8}$", message = "电话格式错误")
|
|
||||||
private String phone;
|
|
||||||
|
|
||||||
@NotBlank(message = "邮箱不能为空")
|
|
||||||
@Pattern(regexp = "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$", message = "邮箱格式错误")
|
|
||||||
private String email;
|
|
||||||
|
|
||||||
@Min(value = 0, message = "保密:0,男:1,女:2")
|
|
||||||
@Max(value = 2, message = "保密:0,男:1,女:2")
|
|
||||||
@NotNull(message = "性别不能为空")
|
|
||||||
private Short sex;
|
|
||||||
|
|
||||||
@NotNull(message = "年龄不能为空")
|
|
||||||
private Short age;
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
package com.jsl.oa.model.voData;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import lombok.experimental.Accessors;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h1>用户注册成功UserDO自定义实体类</h1>
|
|
||||||
* <hr/>
|
|
||||||
* 用于处理用户注册表单输出的数据
|
|
||||||
*
|
|
||||||
* @author 筱锋xiao_lfeng
|
|
||||||
* @version v1.1.0
|
|
||||||
* @since v1.1.0
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@Accessors(chain = true)
|
|
||||||
public class UserReturnBackVO {
|
|
||||||
private String jobId;
|
|
||||||
private String username;
|
|
||||||
private String address;
|
|
||||||
private String phone;
|
|
||||||
private String email;
|
|
||||||
private Short age;
|
|
||||||
private Short sex;
|
|
||||||
private String token;
|
|
||||||
}
|
|
|
@ -1,58 +0,0 @@
|
||||||
package com.jsl.oa.services;
|
|
||||||
|
|
||||||
import com.jsl.oa.model.voData.UserLoginVO;
|
|
||||||
import com.jsl.oa.model.voData.UserRegisterVO;
|
|
||||||
import com.jsl.oa.utils.BaseResponse;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h1>用户认证服务接口</h1>
|
|
||||||
* <hr/>
|
|
||||||
* 用户认证服务接口,包含用户注册、用户登录、用户登出接口
|
|
||||||
*
|
|
||||||
* @version v1.1.0
|
|
||||||
* @since v1.0.0
|
|
||||||
*/
|
|
||||||
public interface AuthService {
|
|
||||||
/**
|
|
||||||
* <h2>用户注册</h2>
|
|
||||||
* <hr/>
|
|
||||||
* 用户注册服务类操作
|
|
||||||
*
|
|
||||||
* @param userRegisterVO 用户注册信息
|
|
||||||
* @return {@link BaseResponse}
|
|
||||||
* @author 筱锋xiao_lfeng
|
|
||||||
*/
|
|
||||||
BaseResponse authRegister(UserRegisterVO userRegisterVO);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h2>用户登录</h2>
|
|
||||||
* <hr/>
|
|
||||||
* 用户登录服务类操作
|
|
||||||
*
|
|
||||||
* @param userLoginVO 用户登录信息
|
|
||||||
* @return {@link BaseResponse}
|
|
||||||
* @author 176yunxuan
|
|
||||||
*/
|
|
||||||
BaseResponse authLogin(UserLoginVO userLoginVO);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h2>邮箱登陆</h2>
|
|
||||||
* <hr/>
|
|
||||||
* 用户邮箱登陆服务类操作
|
|
||||||
*
|
|
||||||
* @param email 邮箱
|
|
||||||
* @param code 验证码
|
|
||||||
* @return {@link BaseResponse}
|
|
||||||
*/
|
|
||||||
BaseResponse authLoginByEmail(String email, Integer code);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h2>发送邮箱验证码</h2>
|
|
||||||
* <hr/>
|
|
||||||
* 用户邮箱登陆服务类操作
|
|
||||||
*
|
|
||||||
* @param email 邮箱
|
|
||||||
* @return {@link BaseResponse}
|
|
||||||
*/
|
|
||||||
BaseResponse authLoginSendEmailCode(String email);
|
|
||||||
}
|
|
|
@ -1,47 +0,0 @@
|
||||||
package com.jsl.oa.services;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h1>邮件服务接口</h1>
|
|
||||||
* <hr/>
|
|
||||||
* 用于发送邮件
|
|
||||||
*
|
|
||||||
* @author 筱锋xiao_lfeng
|
|
||||||
* @version v1.1.0
|
|
||||||
* @since v1.1.0
|
|
||||||
*/
|
|
||||||
public interface MailService {
|
|
||||||
/**
|
|
||||||
* <h2>发送邮件通用模板</h2>
|
|
||||||
* <hr/>
|
|
||||||
* 更为广泛的内容发送,用于发送普通文本邮件
|
|
||||||
*
|
|
||||||
* @param sendTo 收件人
|
|
||||||
* @param subject 主题
|
|
||||||
* @param text 内容
|
|
||||||
* @return 是否发送成功
|
|
||||||
*/
|
|
||||||
boolean sendMail(String sendTo, String subject, String text);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h2>发送邮件通用模板</h2>
|
|
||||||
* <hr/>
|
|
||||||
* 发送邮件通用模板,用于发送具有模板HTML邮件
|
|
||||||
*
|
|
||||||
* @param sendTo 收件人
|
|
||||||
* @param model 模板
|
|
||||||
* @return 是否发送成功
|
|
||||||
*/
|
|
||||||
boolean sendMail(String sendTo, String model);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h2>邮件登陆模块</h2>
|
|
||||||
* <hr/>
|
|
||||||
* 用于发送用户登陆邮件
|
|
||||||
*
|
|
||||||
* @param email 邮箱
|
|
||||||
* @param code 验证码
|
|
||||||
* @return 是否发送成功
|
|
||||||
*/
|
|
||||||
boolean sendMailAboutUserLogin(String email, Integer code);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,45 +0,0 @@
|
||||||
package com.jsl.oa.services;
|
|
||||||
|
|
||||||
import com.jsl.oa.model.doData.UserDO;
|
|
||||||
import com.jsl.oa.model.voData.UserDeleteVO;
|
|
||||||
import com.jsl.oa.model.voData.UserEditProfile;
|
|
||||||
import com.jsl.oa.model.voData.UserLockVO;
|
|
||||||
import com.jsl.oa.utils.BaseResponse;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h1>用户控制器接口</h1>
|
|
||||||
* <hr/>
|
|
||||||
*
|
|
||||||
* <p>该接口用于定义用户控制器的方法</p>
|
|
||||||
*
|
|
||||||
* @version 1.1.0
|
|
||||||
* @since v1.1.0
|
|
||||||
* @author 筱锋xiao_lfeng
|
|
||||||
*/
|
|
||||||
public interface UserService {
|
|
||||||
/**
|
|
||||||
* <h2>根据用户名获取用户信息</h2>
|
|
||||||
*
|
|
||||||
* <p>该方法用于根据用户名获取用户信息</p>
|
|
||||||
*
|
|
||||||
* @param username 用户名
|
|
||||||
* @return 用户信息
|
|
||||||
*/
|
|
||||||
UserDO getUserInfoByUsername(String username);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用户账号删除
|
|
||||||
* @param userDeleteVO
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
BaseResponse userDelete(UserDeleteVO userDeleteVO);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用户账号锁定
|
|
||||||
* @param userLockVO
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
BaseResponse userLock(UserLockVO userLockVO);
|
|
||||||
|
|
||||||
BaseResponse userEditProfile(UserEditProfile userEditProfile);
|
|
||||||
}
|
|
|
@ -1,161 +0,0 @@
|
||||||
package com.jsl.oa.services.impl;
|
|
||||||
|
|
||||||
import com.jsl.oa.common.constant.BusinessConstants;
|
|
||||||
import com.jsl.oa.exception.BusinessException;
|
|
||||||
import com.jsl.oa.mapper.UserMapper;
|
|
||||||
import com.jsl.oa.model.doData.UserDO;
|
|
||||||
import com.jsl.oa.model.voData.UserLoginVO;
|
|
||||||
import com.jsl.oa.model.voData.UserRegisterVO;
|
|
||||||
import com.jsl.oa.model.voData.UserReturnBackVO;
|
|
||||||
import com.jsl.oa.services.AuthService;
|
|
||||||
import com.jsl.oa.services.MailService;
|
|
||||||
import com.jsl.oa.utils.*;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.mindrot.jbcrypt.BCrypt;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h1>用户认证服务实现类</h1>
|
|
||||||
* <hr/>
|
|
||||||
* 用户认证服务实现类,包含用户注册、用户登录、用户登出接口
|
|
||||||
*
|
|
||||||
* @version v1.1.0
|
|
||||||
* @see AuthService
|
|
||||||
* @since v1.0.0
|
|
||||||
*/
|
|
||||||
@Service
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class AuthServiceImpl implements AuthService {
|
|
||||||
private final UserMapper userMapper;
|
|
||||||
private final MailService mailService;
|
|
||||||
private final EmailRedisUtil<Integer> emailRedisUtil;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BaseResponse authRegister(@NotNull UserRegisterVO userRegisterVO) {
|
|
||||||
// 检查用户说是否存在
|
|
||||||
UserDO getUserByUsername = userMapper.getUserInfoByUsername(userRegisterVO.getUsername());
|
|
||||||
// 用户名已存在
|
|
||||||
if (getUserByUsername != null) {
|
|
||||||
return ResultUtil.error(ErrorCode.USER_EXIST);
|
|
||||||
}
|
|
||||||
// 生成工号
|
|
||||||
String userNum;
|
|
||||||
do {
|
|
||||||
userNum = Processing.createJobNumber((short) 2);
|
|
||||||
} while (userMapper.getUserByUserNum(userNum) != null);
|
|
||||||
|
|
||||||
// 数据上传
|
|
||||||
UserDO userDO = new UserDO();
|
|
||||||
userDO.setJobId(userNum)
|
|
||||||
.setUsername(userRegisterVO.getUsername())
|
|
||||||
.setPassword(BCrypt.hashpw(userRegisterVO.getPassword(), BCrypt.gensalt()))
|
|
||||||
.setAddress(userRegisterVO.getAddress())
|
|
||||||
.setPhone(userRegisterVO.getPhone())
|
|
||||||
.setEmail(userRegisterVO.getEmail())
|
|
||||||
.setAge(userRegisterVO.getAge())
|
|
||||||
.setSex(userRegisterVO.getSex());
|
|
||||||
// 插入数据
|
|
||||||
if (userMapper.insertUser(userDO)) {
|
|
||||||
userDO.setPassword(null);
|
|
||||||
return ResultUtil.success("注册成功", userDO);
|
|
||||||
} else {
|
|
||||||
throw new BusinessException(ErrorCode.DATABASE_INSERT_ERROR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BaseResponse authLogin(@NotNull UserLoginVO userLoginVO) {
|
|
||||||
// 检查用户是否存在
|
|
||||||
UserDO userDO;
|
|
||||||
if (Pattern.matches("^[0-9A-Za-z_]{3,40}$", userLoginVO.getUser())) {
|
|
||||||
// 是否为用户名
|
|
||||||
userDO = userMapper.getUserInfoByUsername(userLoginVO.getUser());
|
|
||||||
} else if (Pattern.matches("^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\\d{8}$", userLoginVO.getUser())) {
|
|
||||||
// 是否为手机号
|
|
||||||
userDO = userMapper.getUserInfoByPhone(userLoginVO.getUser());
|
|
||||||
} else if (Pattern.matches("^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$", userLoginVO.getUser())) {
|
|
||||||
// 是否为邮箱
|
|
||||||
return ResultUtil.error(ErrorCode.EMAIL_LOGIN_NOT_SUPPORT);
|
|
||||||
} else {
|
|
||||||
// 工号
|
|
||||||
userDO = userMapper.getUserByJobId(userLoginVO.getUser());
|
|
||||||
}
|
|
||||||
if (userDO != null) {
|
|
||||||
// 获取用户并登陆
|
|
||||||
if (BCrypt.checkpw(userLoginVO.getPassword(), userDO.getPassword())) {
|
|
||||||
UserReturnBackVO userReturnBackVO = new UserReturnBackVO();
|
|
||||||
// 授权 Token
|
|
||||||
String token = JwtUtil.generateToken(userDO.getUsername());
|
|
||||||
userReturnBackVO.setAddress(userDO.getAddress())
|
|
||||||
.setAge(userDO.getAge())
|
|
||||||
.setEmail(userDO.getEmail())
|
|
||||||
.setJobId(userDO.getJobId())
|
|
||||||
.setPhone(userDO.getPhone())
|
|
||||||
.setSex(userDO.getSex())
|
|
||||||
.setUsername(userDO.getUsername())
|
|
||||||
.setToken(token);
|
|
||||||
return ResultUtil.success("登陆成功", userReturnBackVO);
|
|
||||||
} else {
|
|
||||||
return ResultUtil.error(ErrorCode.WRONG_PASSWORD);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return ResultUtil.error(ErrorCode.USER_NOT_EXIST);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BaseResponse authLoginByEmail(String email, Integer code) {
|
|
||||||
// 获取验证码是否有效
|
|
||||||
Integer redisCode = emailRedisUtil.getData(BusinessConstants.BUSINESS_LOGIN, email);
|
|
||||||
if (redisCode != null) {
|
|
||||||
if (redisCode.equals(code)) {
|
|
||||||
// 删除验证码
|
|
||||||
if (emailRedisUtil.delData(BusinessConstants.BUSINESS_LOGIN, email)) {
|
|
||||||
// 邮箱获取用户
|
|
||||||
UserDO userDO = userMapper.getUserInfoByEmail(email);
|
|
||||||
// 授权 Token
|
|
||||||
String token = JwtUtil.generateToken(userDO.getUsername());
|
|
||||||
UserReturnBackVO userReturnBackVO = new UserReturnBackVO();
|
|
||||||
userReturnBackVO.setAddress(userDO.getAddress())
|
|
||||||
.setAge(userDO.getAge())
|
|
||||||
.setEmail(userDO.getEmail())
|
|
||||||
.setJobId(userDO.getJobId())
|
|
||||||
.setPhone(userDO.getPhone())
|
|
||||||
.setSex(userDO.getSex())
|
|
||||||
.setUsername(userDO.getUsername())
|
|
||||||
.setToken(token);
|
|
||||||
return ResultUtil.success("登陆成功", userReturnBackVO);
|
|
||||||
} else {
|
|
||||||
return ResultUtil.error(ErrorCode.DATABASE_DELETE_ERROR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ResultUtil.error(ErrorCode.VERIFICATION_INVALID);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BaseResponse authLoginSendEmailCode(String email) {
|
|
||||||
// 获取用户信息
|
|
||||||
UserDO userDO = userMapper.getUserInfoByEmail(email);
|
|
||||||
if (userDO != null) {
|
|
||||||
// 生成验证码
|
|
||||||
Integer code = Processing.createCode();
|
|
||||||
// 存储验证码
|
|
||||||
if (emailRedisUtil.setData(BusinessConstants.BUSINESS_LOGIN, email, code, 5)) {
|
|
||||||
// 发送邮件
|
|
||||||
if (mailService.sendMailAboutUserLogin(email, code)) {
|
|
||||||
return ResultUtil.success("验证码已发送");
|
|
||||||
} else {
|
|
||||||
return ResultUtil.error(ErrorCode.EMAIL_LOGIN_NOT_SUPPORT);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return ResultUtil.error(ErrorCode.DATABASE_INSERT_ERROR);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return ResultUtil.error(ErrorCode.USER_NOT_EXIST);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,85 +0,0 @@
|
||||||
package com.jsl.oa.services.impl;
|
|
||||||
|
|
||||||
import com.jsl.oa.services.MailService;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.mail.javamail.JavaMailSender;
|
|
||||||
import org.springframework.mail.javamail.MimeMessageHelper;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.thymeleaf.TemplateEngine;
|
|
||||||
import org.thymeleaf.context.Context;
|
|
||||||
|
|
||||||
import javax.mail.MessagingException;
|
|
||||||
import javax.mail.internet.MimeMessage;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h1>邮件服务实现类</h1>
|
|
||||||
* <hr/>
|
|
||||||
* 用于发送邮件
|
|
||||||
*
|
|
||||||
* @since v1.1.0
|
|
||||||
* @version v1.1.0
|
|
||||||
* @author 筱锋xiao_lfeng
|
|
||||||
* @see MailService
|
|
||||||
* @see JavaMailSender
|
|
||||||
* @see MimeMessageHelper
|
|
||||||
*/
|
|
||||||
@Service
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class MailServiceImpl implements MailService {
|
|
||||||
private final JavaMailSender javaMailSender;
|
|
||||||
private final TemplateEngine templateEngine;
|
|
||||||
|
|
||||||
@Value("${spring.mail.username}")
|
|
||||||
private String from;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean sendMail(String sendTo, String subject, String text) {
|
|
||||||
//发送多媒体邮件
|
|
||||||
try {
|
|
||||||
MimeMessage message = javaMailSender.createMimeMessage();
|
|
||||||
|
|
||||||
MimeMessageHelper helper = new MimeMessageHelper(message, true);
|
|
||||||
helper.setFrom(from);
|
|
||||||
helper.setTo(sendTo);
|
|
||||||
helper.setSubject(subject);
|
|
||||||
helper.setText(text, true);
|
|
||||||
|
|
||||||
javaMailSender.send(message);
|
|
||||||
return true;
|
|
||||||
} catch (MessagingException e) {
|
|
||||||
//TODO: 10001-发送邮件失败处理
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean sendMail(String sendTo, String model) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean sendMailAboutUserLogin(String email, Integer code) {
|
|
||||||
// 发送邮件带HTML模块部分
|
|
||||||
try {
|
|
||||||
MimeMessage message = javaMailSender.createMimeMessage();
|
|
||||||
|
|
||||||
MimeMessageHelper mimeMessage = new MimeMessageHelper(message, true);
|
|
||||||
mimeMessage.setFrom(from);
|
|
||||||
mimeMessage.setTo(email);
|
|
||||||
mimeMessage.setSubject("用户登陆邮件");
|
|
||||||
Context context = new Context();
|
|
||||||
context.setVariable("code", code);
|
|
||||||
context.setVariable("email", email);
|
|
||||||
String emailContent = templateEngine.process("/mail/user-login.html", context);
|
|
||||||
mimeMessage.setText(emailContent, true);
|
|
||||||
|
|
||||||
javaMailSender.send(message);
|
|
||||||
return true;
|
|
||||||
} catch (MessagingException e) {
|
|
||||||
//TODO: 10001-发送邮件失败处理
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,56 +0,0 @@
|
||||||
package com.jsl.oa.services.impl;
|
|
||||||
|
|
||||||
import com.jsl.oa.dao.UserDAO;
|
|
||||||
import com.jsl.oa.model.doData.UserDO;
|
|
||||||
import com.jsl.oa.model.voData.UserDeleteVO;
|
|
||||||
import com.jsl.oa.model.voData.UserEditProfile;
|
|
||||||
import com.jsl.oa.model.voData.UserLockVO;
|
|
||||||
import com.jsl.oa.services.UserService;
|
|
||||||
import com.jsl.oa.utils.BaseResponse;
|
|
||||||
import com.jsl.oa.utils.ErrorCode;
|
|
||||||
import com.jsl.oa.utils.ResultUtil;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.mindrot.jbcrypt.BCrypt;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class UserServiceImpl implements UserService {
|
|
||||||
|
|
||||||
private final UserDAO userDAO;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public UserDO getUserInfoByUsername(String username) {
|
|
||||||
return userDAO.getUserInfoByUsername(username);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BaseResponse userDelete(UserDeleteVO userDeleteVO) {
|
|
||||||
//判断用户是否存在
|
|
||||||
if(userDAO.isExistUser(userDeleteVO.getId())) {
|
|
||||||
userDAO.userDelete(userDeleteVO);
|
|
||||||
return ResultUtil.success("删除成功");
|
|
||||||
}else return ResultUtil.error(ErrorCode.USER_NOT_EXIST);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BaseResponse userLock(@NotNull UserLockVO userLockVO) {
|
|
||||||
//判断用户是否存在
|
|
||||||
if(userDAO.isExistUser(userLockVO.getId())) {
|
|
||||||
userDAO.userLock(userLockVO);
|
|
||||||
return ResultUtil.success("锁定成功");
|
|
||||||
}else return ResultUtil.error(ErrorCode.USER_NOT_EXIST);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BaseResponse userEditProfile(@NotNull UserEditProfile userEditProfile) {
|
|
||||||
if(userDAO.isExistUser(userEditProfile.getId())) {
|
|
||||||
if(userEditProfile.getPassword()!=null){
|
|
||||||
userEditProfile.setPassword(BCrypt.hashpw(userEditProfile.getPassword(), BCrypt.gensalt()));
|
|
||||||
}
|
|
||||||
userDAO.userEditProfile(userEditProfile);
|
|
||||||
return ResultUtil.success("修改成功");
|
|
||||||
}else return ResultUtil.error(ErrorCode.USER_NOT_EXIST);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
package com.jsl.oa.utils;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
|
||||||
public class BaseResponse {
|
|
||||||
private final String output;
|
|
||||||
private final Integer code;
|
|
||||||
private final String message;
|
|
||||||
private final Object data;
|
|
||||||
|
|
||||||
public BaseResponse(String output, Integer code, String message, Object data) {
|
|
||||||
this.output = output;
|
|
||||||
this.code = code;
|
|
||||||
this.message = message;
|
|
||||||
this.data = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BaseResponse(String output, Integer code, String message) {
|
|
||||||
this.output = output;
|
|
||||||
this.code = code;
|
|
||||||
this.message = message;
|
|
||||||
this.data = null;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,92 +0,0 @@
|
||||||
package com.jsl.oa.utils;
|
|
||||||
|
|
||||||
import com.jsl.oa.common.constant.BusinessConstants;
|
|
||||||
import com.jsl.oa.common.constant.RedisConstant;
|
|
||||||
import com.jsl.oa.config.redis.RedisConfiguration;
|
|
||||||
import com.jsl.oa.config.redis.RedisOperating;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
|
||||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h1>Redis工具类</h1>
|
|
||||||
* <hr/>
|
|
||||||
* 用于操作Redis
|
|
||||||
*
|
|
||||||
* @author 筱锋xiao_lfeng
|
|
||||||
* @version v1.1.0
|
|
||||||
* @see RedisConfiguration
|
|
||||||
* @see com.jsl.oa.common.constant.RedisConstant
|
|
||||||
* @since v1.1.0
|
|
||||||
*/
|
|
||||||
@Component
|
|
||||||
public class EmailRedisUtil<R> extends RedisOperating<R> {
|
|
||||||
|
|
||||||
public EmailRedisUtil(RedisTemplate<String, R> redisTemplate, StringRedisTemplate stringRedisTemplate) {
|
|
||||||
super(redisTemplate, stringRedisTemplate);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h2>获取邮箱验证码过期时间</h2>
|
|
||||||
* <hr/>
|
|
||||||
* 用于 AuthController 中的 authLoginByEmail 方法<br/>
|
|
||||||
* 用于获取邮箱验证码过期时间
|
|
||||||
*
|
|
||||||
* @param email 邮箱
|
|
||||||
* @return 返回邮箱验证码过期时间戳
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Long getExpiredAt(@NotNull BusinessConstants businessConstants, String email) {
|
|
||||||
String key = RedisConstant.TYPE_EMAIL + RedisConstant.TABLE_EMAIL + businessConstants.getValue() + email;
|
|
||||||
return redisTemplate.getExpire(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h2>删除邮箱验证码</h2>
|
|
||||||
* <hr/>
|
|
||||||
* 用于 AuthController 中的 authLoginByEmail 方法<br/>
|
|
||||||
* 用于删除邮箱验证码
|
|
||||||
*
|
|
||||||
* @param email 邮箱
|
|
||||||
* @return 返回是否删除成功
|
|
||||||
*/
|
|
||||||
public Boolean delData(@NotNull BusinessConstants businessConstants, String email) {
|
|
||||||
String key = RedisConstant.TYPE_EMAIL + RedisConstant.TABLE_EMAIL + businessConstants.getValue() + email;
|
|
||||||
return redisTemplate.delete(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h2>获取邮箱验证码</h2>
|
|
||||||
* <hr/>
|
|
||||||
* 用于 AuthController 中的 authLoginByEmail 方法<br/>
|
|
||||||
* 用于获取邮箱验证码
|
|
||||||
*
|
|
||||||
* @param email 邮箱
|
|
||||||
* @return 返回邮箱验证码
|
|
||||||
*/
|
|
||||||
public R getData(@NotNull BusinessConstants businessConstants, String email) {
|
|
||||||
String key = RedisConstant.TYPE_EMAIL + RedisConstant.TABLE_EMAIL + businessConstants.getValue() + email;
|
|
||||||
return redisTemplate.opsForValue().get(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h2>设置邮箱验证码</h2>
|
|
||||||
* <hr/>
|
|
||||||
* 用于 AuthController 中的 authLoginByEmail 方法<br/>
|
|
||||||
* 用于设置邮箱验证码
|
|
||||||
*
|
|
||||||
* @param email 邮箱
|
|
||||||
* @param value 验证码
|
|
||||||
* @return 返回是否添加成功
|
|
||||||
*/
|
|
||||||
public Boolean setData(@NotNull BusinessConstants businessConstants, String email, R value, Integer time) {
|
|
||||||
// 处理数据
|
|
||||||
String key = RedisConstant.TYPE_EMAIL + RedisConstant.TABLE_EMAIL + businessConstants.getValue() + email;
|
|
||||||
redisTemplate.opsForValue().set(key, value);
|
|
||||||
redisTemplate.expire(key, time, TimeUnit.MINUTES);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
package com.jsl.oa.utils;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
public enum ErrorCode {
|
|
||||||
WRONG_PASSWORD("WrongPassword", 40010, "密码错误"),
|
|
||||||
PARAMETER_ERROR("ParameterError", 40011, "参数错误"),
|
|
||||||
REQUEST_BODY_ERROR("RequestBodyError", 40012, "请求体错误"),
|
|
||||||
USER_EXIST("UserExist", 40013, "用户名已存在"),
|
|
||||||
TIMESTAMP_ERROR("TimestampError", 40014, "时间戳错误"),
|
|
||||||
USER_NOT_EXIST("UserNotExist", 40015, "用户不存在"),
|
|
||||||
UNAUTHORIZED("Unauthorized", 40100, "未授权"),
|
|
||||||
TOKEN_EXPIRED("TokenExpired", 40101, "Token已过期"),
|
|
||||||
VERIFICATION_INVALID("VerificationInvalid", 40102, "验证码无效"),
|
|
||||||
EMAIL_LOGIN_NOT_SUPPORT("EmailLoginNotSupport", 40300, "请使用邮箱登陆"),
|
|
||||||
DATABASE_INSERT_ERROR("DatabaseInsertError", 50010, "数据库插入错误"),
|
|
||||||
DATABASE_UPDATE_ERROR("DatabaseUpdateError", 50011, "数据库更新错误"),
|
|
||||||
DATABASE_DELETE_ERROR("DatabaseDeleteError", 50012, "数据库删除错误");
|
|
||||||
|
|
||||||
private final String output;
|
|
||||||
private final Integer code;
|
|
||||||
private final String message;
|
|
||||||
|
|
||||||
ErrorCode(String output, Integer code, String message) {
|
|
||||||
this.output = output;
|
|
||||||
this.code = code;
|
|
||||||
this.message = message;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,49 +0,0 @@
|
||||||
package com.jsl.oa.utils;
|
|
||||||
|
|
||||||
import io.jsonwebtoken.Claims;
|
|
||||||
import io.jsonwebtoken.Jws;
|
|
||||||
import io.jsonwebtoken.Jwts;
|
|
||||||
import io.jsonwebtoken.SignatureAlgorithm;
|
|
||||||
import io.jsonwebtoken.security.Keys;
|
|
||||||
|
|
||||||
import java.security.Key;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
public class JwtUtil {
|
|
||||||
// 替换为实际的密钥,建议使用足够长的随机字符串
|
|
||||||
private static final String SECRET_KEY = "238542310128901753637022851772455105464283332917211091531086967815273100806759714250034263888525489008903447113697698540563820710887668094087054975808574632265678643370464260078072153369247242449569221118098938297741582538222826493707667477115117609126233";
|
|
||||||
|
|
||||||
// Token 有效期,这里设置为一天,可以根据实际需求调整
|
|
||||||
private static final long EXPIRATION_TIME = 86400000;
|
|
||||||
|
|
||||||
// 生成Token
|
|
||||||
public static String generateToken(String username) {
|
|
||||||
Key key = Keys.hmacShaKeyFor(SECRET_KEY.getBytes());
|
|
||||||
|
|
||||||
return Jwts.builder()
|
|
||||||
.setSubject(username)
|
|
||||||
.setExpiration(new java.util.Date(System.currentTimeMillis() + EXPIRATION_TIME))
|
|
||||||
.signWith(key, SignatureAlgorithm.HS256)
|
|
||||||
.compact();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 验证Token
|
|
||||||
public static boolean verify(String token) {
|
|
||||||
try {
|
|
||||||
Key key = Keys.hmacShaKeyFor(SECRET_KEY.getBytes());
|
|
||||||
|
|
||||||
Jws<Claims> claimsJws = Jwts.parserBuilder()
|
|
||||||
.setSigningKey(key)
|
|
||||||
.build()
|
|
||||||
.parseClaimsJws(token);
|
|
||||||
|
|
||||||
// 从JWT中获取用户名进行匹配
|
|
||||||
String tokenUsername = claimsJws.getBody().getSubject();
|
|
||||||
// 验证用户名是否匹配
|
|
||||||
return Pattern.matches("^[0-9A-Za-z_]{3,40}$", tokenUsername);
|
|
||||||
} catch (Exception e) {
|
|
||||||
// 验证失败
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,89 +0,0 @@
|
||||||
package com.jsl.oa.utils;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.springframework.validation.BindingResult;
|
|
||||||
import org.springframework.validation.ObjectError;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h1>自定义快捷工具类</h1>
|
|
||||||
* <hr/>
|
|
||||||
*
|
|
||||||
* @author 筱锋xiao_lfeng
|
|
||||||
* @since v1.0.0
|
|
||||||
* @version v1.0.0
|
|
||||||
*/
|
|
||||||
public class Processing {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h1>获取参数校验错误信息</h1>
|
|
||||||
* <hr/>
|
|
||||||
* 用于获取参数校验错误信息
|
|
||||||
*
|
|
||||||
* @since v1.0.0
|
|
||||||
* @param bindingResult 参数校验结果
|
|
||||||
* @return {@link ArrayList<String>}
|
|
||||||
*/
|
|
||||||
public static @NotNull ArrayList<String> getValidatedErrorList(BindingResult bindingResult) {
|
|
||||||
ArrayList<String> arrayList = new ArrayList<>();
|
|
||||||
for (ObjectError objectError : bindingResult.getAllErrors()) {
|
|
||||||
arrayList.add(objectError.getDefaultMessage());
|
|
||||||
}
|
|
||||||
return arrayList;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h1>生成工号</h1>
|
|
||||||
* <hr/>
|
|
||||||
* 用于生成工号,默认长度为10
|
|
||||||
*
|
|
||||||
* @since v1.0.0
|
|
||||||
* @param type 0:学生 1:教师 2:其他
|
|
||||||
* @return {@link String}
|
|
||||||
*/
|
|
||||||
public static @NotNull String createJobNumber(Short type) {
|
|
||||||
return createJobNumber(type, (short) 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <h1>生成工号</h1>
|
|
||||||
* <hr/>
|
|
||||||
* 用于生成工号
|
|
||||||
*
|
|
||||||
* @since v1.0.0
|
|
||||||
* @param type 0:学生 1:教师 2:其他
|
|
||||||
* @param size 工号长度
|
|
||||||
* @return {@link String}
|
|
||||||
*/
|
|
||||||
public static @NotNull String createJobNumber(Short type, Short size) {
|
|
||||||
StringBuilder stringBuilder = new StringBuilder();
|
|
||||||
if (type == 0) {
|
|
||||||
stringBuilder.append("STU");
|
|
||||||
} else if (type == 1) {
|
|
||||||
stringBuilder.append("TCH");
|
|
||||||
} else {
|
|
||||||
stringBuilder.append("OTH");
|
|
||||||
}
|
|
||||||
// 生成工号
|
|
||||||
Random random = new Random();
|
|
||||||
for (int i = 0; i < size-3; i++) {
|
|
||||||
stringBuilder.append(random.nextInt(10));
|
|
||||||
}
|
|
||||||
return stringBuilder.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public static @NotNull Integer createCode() {
|
|
||||||
StringBuilder stringBuilder = new StringBuilder();
|
|
||||||
// 生成验证码
|
|
||||||
Random random = new Random();
|
|
||||||
for (int i = 0; i < 6; i++) {
|
|
||||||
stringBuilder.append(random.nextInt(10));
|
|
||||||
}
|
|
||||||
return Integer.valueOf(stringBuilder.toString());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
package com.jsl.oa.utils;
|
|
||||||
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
|
|
||||||
public class ResultUtil {
|
|
||||||
|
|
||||||
public static BaseResponse success() {
|
|
||||||
return new BaseResponse("Success", 200, "操作成功", null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static BaseResponse success(String message) {
|
|
||||||
return new BaseResponse("Success", 200, message, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static BaseResponse success(Object data) {
|
|
||||||
return new BaseResponse("Success", 200, "操作成功", data);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static BaseResponse success(String message, Object data) {
|
|
||||||
return new BaseResponse("Success", 200, message, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static BaseResponse error(ErrorCode errorCode) {
|
|
||||||
return new BaseResponse(errorCode.getOutput(), errorCode.getCode(), errorCode.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static BaseResponse error(ErrorCode errorCode, Object data) {
|
|
||||||
return new BaseResponse(errorCode.getOutput(), errorCode.getCode(), errorCode.getMessage(), data);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static BaseResponse error(String output, Integer code, String message, Object data) {
|
|
||||||
return new BaseResponse(output, code, message, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ResponseEntity<BaseResponse> error(String output, Integer code, String message) {
|
|
||||||
return ResponseEntity.status(code)
|
|
||||||
.body(new BaseResponse(output, code, message));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
spring:
|
|
||||||
datasource:
|
|
||||||
url: jdbc:mysql://localhost:3306
|
|
||||||
username: organize_oa
|
|
||||||
password: 123456
|
|
||||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
|
||||||
redis:
|
|
||||||
database: 0
|
|
||||||
host: localhost
|
|
||||||
port: 6379
|
|
||||||
profiles:
|
|
||||||
active: dev
|
|
||||||
mybatis:
|
|
||||||
configuration:
|
|
||||||
map-underscore-to-camel-case: true
|
|
||||||
|
|
|
@ -1,47 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
|
||||||
<!DOCTYPE mapper
|
|
||||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|
||||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
|
||||||
|
|
||||||
<mapper namespace="com.jsl.oa.mapper.UserMapper">
|
|
||||||
<update id="userEditProfile">
|
|
||||||
update organize_oa.oa_user
|
|
||||||
<set>
|
|
||||||
<if test="username != null and username != ''">
|
|
||||||
username = #{username},
|
|
||||||
</if>
|
|
||||||
<if test="password != null and password != ''">
|
|
||||||
password = #{password},
|
|
||||||
</if>
|
|
||||||
<if test="address != null and address != ''">
|
|
||||||
address = #{address},
|
|
||||||
</if>
|
|
||||||
<if test="phone != null and phone != ''">
|
|
||||||
phone = #{phone},
|
|
||||||
</if>
|
|
||||||
<if test="email != null and email != ''">
|
|
||||||
email = #{email},
|
|
||||||
</if>
|
|
||||||
<if test="age != null and age != ''">
|
|
||||||
age = #{age},
|
|
||||||
</if>
|
|
||||||
<if test="signature != null and signature != ''">
|
|
||||||
signature = #{signature},
|
|
||||||
</if>
|
|
||||||
<if test="sex != null and sex != ''">
|
|
||||||
sex = #{sex},
|
|
||||||
</if>
|
|
||||||
<if test="avatar != null and avatar != ''">
|
|
||||||
avatar = #{avatar},
|
|
||||||
</if>
|
|
||||||
<if test="nickname != null and nickname != ''">
|
|
||||||
nickname = #{nickname},
|
|
||||||
</if>
|
|
||||||
<if test="description != null and description != ''">
|
|
||||||
description = #{description}
|
|
||||||
</if>
|
|
||||||
</set>
|
|
||||||
where id = #{id}
|
|
||||||
</update>
|
|
||||||
|
|
||||||
</mapper>
|
|
|
@ -1,90 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html xmlns:th="http://www.thymeleaf.org" lang="zh-cn">
|
|
||||||
<head>
|
|
||||||
<title>登录邮件模板</title>
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
font-family: 'Arial', sans-serif;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
background-color: #f4f4f4;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container {
|
|
||||||
width: 80%;
|
|
||||||
margin: 0 auto;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
header {
|
|
||||||
background: #ffffff;
|
|
||||||
padding: 10px 0;
|
|
||||||
box-shadow: 0 5px 5px #888888;
|
|
||||||
}
|
|
||||||
|
|
||||||
header img {
|
|
||||||
width: 100px;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main {
|
|
||||||
padding: 20px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main h2 {
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main p {
|
|
||||||
color: #555;
|
|
||||||
}
|
|
||||||
|
|
||||||
.code {
|
|
||||||
background: #4CAF50;
|
|
||||||
color: #ffffff;
|
|
||||||
padding: 10px;
|
|
||||||
text-align: center;
|
|
||||||
font-size: 24px;
|
|
||||||
margin: 20px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
footer {
|
|
||||||
background: #ffffff;
|
|
||||||
padding: 10px 0;
|
|
||||||
box-shadow: 0 -5px 5px #888888;
|
|
||||||
}
|
|
||||||
|
|
||||||
footer p {
|
|
||||||
text-align: center;
|
|
||||||
color: #888;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="container">
|
|
||||||
<header>
|
|
||||||
<!--<img src="path/to/your/logo.png" alt="Logo">-->
|
|
||||||
测试
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<div class="main">
|
|
||||||
<h2>登录您的账户</h2>
|
|
||||||
<p>
|
|
||||||
你好,<b th:text="${email}">[收件人]</b>,
|
|
||||||
<br>
|
|
||||||
使用以下验证码登录您的账户:
|
|
||||||
</p>
|
|
||||||
<div class="code" th:text="${code}">000000</div>
|
|
||||||
<p>
|
|
||||||
如果您未请求此验证码,请忽略此邮件。
|
|
||||||
<br>
|
|
||||||
感谢您使用我们的服务。
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<footer>
|
|
||||||
<p>© 2024 您的公司。保留所有权利。</p>
|
|
||||||
</footer>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,20 +0,0 @@
|
||||||
package com.jsl.oa;
|
|
||||||
|
|
||||||
import com.jsl.oa.utils.JwtUtil;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
|
||||||
|
|
||||||
@SpringBootTest
|
|
||||||
class JslOrganizeInternalOaApplicationTests {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void contextLoads() {
|
|
||||||
String token = JwtUtil.generateToken("admin");
|
|
||||||
if (JwtUtil.verify(token)) {
|
|
||||||
System.out.println("验证通过");
|
|
||||||
} else {
|
|
||||||
System.out.println("验证失败");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user