提交 08e911f1 作者: 方治民

合并分支 '3.0' 到 'beta'

3.0

查看合并请求 !16
流水线 #2013 已失败 于阶段
in 2 分 54 秒
......@@ -3,6 +3,7 @@
## 开发环境
<!-- prettier-ignore -->
- JDK 17 [版本管理工具](https://github.com/shyiko/jabba)
- NodeJS [下载](https://nodejs.org/zh-cn/)
- IDEA [下载](https://www.jetbrains.com/idea/)
......@@ -14,6 +15,7 @@
## 开始
<!-- prettier-ignore -->
- [开发规范说明](./doc/workflow.md)
- [技术栈说明](./doc/technique.md)
- 👉 [实用技巧](./doc/skill.md)
......@@ -23,10 +25,13 @@
## TODO
<!-- prettier-ignore -->
- [x] 完成项目构建,开发文档编写
- [x] [conventional-changelog](https://www.cnblogs.com/mengfangui/p/12634845.html)
- [x] 用户及权限模块(目录/菜单/按钮),预览初始化权限配置 [SQL 脚本](./basic-auth/src/main/resources/init-test-mysql.sql)
- [x] 通用文件上传模块,支持对图片/PDF/MP3/MP4 等文件进行预处理
- [x] WebSocket 模块
- [ ] 通用字典管理模块
- [x] 通用字典管理模块
- [x] 通用文件上传模块,支持对图片/PDF/MP3/MP4 等文件进行预处理
- [ ] 大文件分片上传,扩展支持本地、MinIO、阿里云 OSS、腾讯云 COS 等
- [ ] XXL-JOB 定时任务模块
- [ ] 更合理的模块拆分,更好的模块解耦
......@@ -18,7 +18,7 @@ dependencies {
// 💬 Mock/Test Env
runtimeOnly 'com.h2database:h2'
// 💬 Prod/Dev Env
runtimeOnly 'mysql:mysql-connector-java'
runtimeOnly 'com.mysql:mysql-connector-j'
runtimeOnly 'org.postgresql:postgresql'
// 本地依赖
......
......@@ -5,12 +5,14 @@ import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.data.jpa.convert.threeten.Jsr310JpaConverters;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
@EntityScan(
basePackageClasses = { Application.class, Jsr310JpaConverters.class },
basePackages = Application.BASE_PACKAGES
)
@EnableJpaAuditing
@EnableJpaRepositories(basePackages = Application.BASE_PACKAGES)
@SpringBootApplication(scanBasePackages = Application.BASE_PACKAGES)
public class Application {
......
......@@ -7,8 +7,6 @@ env:
# username: admin
password: 123456
username: postgres
ffmpeg:
path: D:\Environments\FFmpeg\bin
# ----------------------------------------------
spring:
......
/* (C) 2023 YiRing, Inc. */
package com.yiring.auth.config;
import cn.dev33.satoken.stp.StpUtil;
import com.yiring.auth.domain.user.User;
import com.yiring.auth.domain.user.UserRepository;
import java.util.Optional;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.data.domain.AuditorAware;
import org.springframework.stereotype.Component;
/**
* @author Jim
* @version 0.1
* 2023/3/3 11:43
*/
@Component
@Configurable
@RequiredArgsConstructor
public class InjectAuditorAware implements AuditorAware<String> {
final UserRepository userRepository;
@Override
public @NonNull Optional<String> getCurrentAuditor() {
String loginId = StpUtil.getLoginIdAsString();
if (loginId != null) {
Optional<User> optional = userRepository.findById(loginId);
if (optional.isPresent()) {
return Optional.of(optional.get().getId());
}
}
return Optional.empty();
}
}
......@@ -17,7 +17,6 @@ import lombok.experimental.SuperBuilder;
import org.hibernate.annotations.Comment;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.SQLDeleteAll;
import org.hibernate.annotations.Where;
/**
* 权限
......@@ -28,20 +27,18 @@ import org.hibernate.annotations.Where;
@Getter
@Setter
@EqualsAndHashCode(callSuper = false)
@SuperBuilder(toBuilder = true)
@NoArgsConstructor
@AllArgsConstructor
@FieldNameConstants
@FieldDefaults(level = AccessLevel.PRIVATE)
@SQLDelete(sql = DELETE_SQL)
@SQLDelete(sql = DELETE_SQL + BasicEntity.Where.WHERE_ID)
@SQLDeleteAll(sql = DELETE_SQL)
@Where(clause = BasicEntity.Where.EXIST)
@Entity
@Table(
name = TABLE_NAME,
indexes = {
@Index(columnList = BasicEntity.Fields.deleteTime),
@Index(columnList = BasicEntity.Fields.deleted),
@Index(columnList = Permission.Fields.type),
@Index(columnList = Permission.Fields.pid),
@Index(columnList = Permission.Fields.tree),
......
/* (C) 2022 YiRing, Inc. */
package com.yiring.auth.domain.role;
import static com.yiring.auth.domain.role.Role.DELETE_SQL;
import static com.yiring.auth.domain.role.Role.TABLE_NAME;
import com.fasterxml.jackson.annotation.JsonIgnore;
......@@ -31,20 +30,19 @@ import org.hibernate.annotations.Where;
@Getter
@Setter
@EqualsAndHashCode(callSuper = false)
@SuperBuilder(toBuilder = true)
@NoArgsConstructor
@AllArgsConstructor
@FieldNameConstants
@FieldDefaults(level = AccessLevel.PRIVATE)
@SQLDelete(sql = DELETE_SQL)
@SQLDeleteAll(sql = DELETE_SQL)
@SQLDelete(sql = Permission.DELETE_SQL + BasicEntity.Where.WHERE_ID)
@SQLDeleteAll(sql = Permission.DELETE_SQL)
@Where(clause = BasicEntity.Where.EXIST)
@Entity
@Table(
name = TABLE_NAME,
indexes = @Index(columnList = BasicEntity.Fields.deleteTime),
uniqueConstraints = { @UniqueConstraint(columnNames = { Role.Fields.uid, BasicEntity.Fields.deleteTime }) }
indexes = @Index(columnList = BasicEntity.Fields.deleted),
uniqueConstraints = { @UniqueConstraint(columnNames = { Role.Fields.uid, BasicEntity.Fields.deleted }) }
)
@Comment("系统角色")
public class Role extends BasicEntity implements Serializable {
......
......@@ -2,6 +2,7 @@
package com.yiring.auth.domain.user;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.yiring.auth.domain.permission.Permission;
import com.yiring.auth.domain.role.Role;
import com.yiring.common.domain.BasicEntity;
import jakarta.persistence.*;
......@@ -17,7 +18,6 @@ import lombok.experimental.SuperBuilder;
import org.hibernate.annotations.Comment;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.SQLDeleteAll;
import org.hibernate.annotations.Where;
/**
* 用户
......@@ -28,23 +28,21 @@ import org.hibernate.annotations.Where;
@Getter
@Setter
@EqualsAndHashCode(callSuper = false)
@SuperBuilder(toBuilder = true)
@NoArgsConstructor
@AllArgsConstructor
@FieldNameConstants
@FieldDefaults(level = AccessLevel.PRIVATE)
@SQLDelete(sql = User.DELETE_SQL)
@SQLDeleteAll(sql = User.DELETE_SQL)
@Where(clause = User.Where.EXIST)
@SQLDelete(sql = Permission.DELETE_SQL + BasicEntity.Where.WHERE_ID)
@SQLDeleteAll(sql = Permission.DELETE_SQL)
@Entity
@Table(
name = User.TABLE_NAME,
indexes = { @Index(columnList = User.Fields.enabled), @Index(columnList = BasicEntity.Fields.deleteTime) },
indexes = { @Index(columnList = User.Fields.enabled), @Index(columnList = BasicEntity.Fields.deleted) },
uniqueConstraints = {
@UniqueConstraint(columnNames = { User.Fields.username, BasicEntity.Fields.deleteTime }),
@UniqueConstraint(columnNames = { User.Fields.mobile, BasicEntity.Fields.deleteTime }),
@UniqueConstraint(columnNames = { User.Fields.email, BasicEntity.Fields.deleteTime }),
@UniqueConstraint(columnNames = { User.Fields.username, BasicEntity.Fields.deleted }),
@UniqueConstraint(columnNames = { User.Fields.mobile, BasicEntity.Fields.deleted }),
@UniqueConstraint(columnNames = { User.Fields.email, BasicEntity.Fields.deleted }),
}
)
@Comment("系统用户")
......
......@@ -168,6 +168,7 @@ public class PermissionController {
private void save(Permission entity, PermissionParam param) {
BeanUtils.copyProperties(param, entity, Permission.Fields.meta);
entity.setTree(getTreeNode(param.getPid()));
entity.setEnable(true);
permissionRepository.saveAndFlush(entity);
}
}
......@@ -65,6 +65,7 @@ public class RoleController {
}
Role entity = new Role();
entity.setEnable(true);
BeanUtils.copyProperties(param, entity);
roleRepository.saveAndFlush(entity);
return Result.ok();
......
......@@ -37,34 +37,11 @@ public class EnvConfig implements Serializable {
boolean prod;
/**
* FFmpeg 配置
*/
FFmpeg ffmpeg;
/**
* 扩展配置
*/
Extra extra;
/**
* FFmpeg 路径相关配置
*/
@Data
@FieldDefaults(level = AccessLevel.PRIVATE)
@Configuration("env.config.ffmpeg")
@ConfigurationProperties(prefix = "env.ffmpeg")
public static class FFmpeg implements Serializable {
@Serial
private static final long serialVersionUID = 972365906869473179L;
/**
* ffmpeg 路径
*/
String path;
}
/**
* 扩展环境配置变量
*/
@Data
......
......@@ -2,16 +2,20 @@
package com.yiring.common.domain;
import com.yiring.common.snowflake.SnowflakeId;
import jakarta.persistence.*;
import jakarta.persistence.EntityListeners;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.MappedSuperclass;
import java.time.LocalDateTime;
import lombok.*;
import lombok.experimental.FieldDefaults;
import lombok.experimental.FieldNameConstants;
import lombok.experimental.SuperBuilder;
import org.hibernate.annotations.Comment;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.UpdateTimestamp;
import org.hibernate.annotations.*;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
/**
......@@ -27,11 +31,13 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener;
@ToString
@NoArgsConstructor
@AllArgsConstructor
@SuperBuilder(toBuilder = true)
@FieldNameConstants
@FieldDefaults(level = AccessLevel.PRIVATE)
@SuperBuilder(toBuilder = true)
@MappedSuperclass
@FilterDef(name = "deletedFilter", parameters = @ParamDef(name = "isDeleted", type = Boolean.class))
@Filter(name = "deletedFilter", condition = "deleted = :isDeleted")
@EntityListeners(AuditingEntityListener.class)
@MappedSuperclass
public abstract class BasicEntity {
@Comment("主键")
......@@ -40,22 +46,30 @@ public abstract class BasicEntity {
@GenericGenerator(name = SnowflakeId.GENERATOR, strategy = SnowflakeId.Strategy.STRING)
String id;
@Comment("创建人")
@CreatedBy
String createBy;
@Comment("创建时间")
@Column(nullable = false)
@CreationTimestamp
@CreatedDate
LocalDateTime createTime;
@Comment("修改人")
@LastModifiedBy
String updateBy;
@Comment("最后修改时间")
@Column(nullable = false)
@UpdateTimestamp
@LastModifiedDate
LocalDateTime updateTime;
@Comment("删除时间")
LocalDateTime deleteTime;
Boolean deleted = Boolean.FALSE;
public interface Where {
String EXIST = " delete_time is null ";
String EXIST = " deleted = false ";
String DELETE_SET = " set deleted = true ";
String DELETE_SET = " set delete_time = now() where id = ? ";
String WHERE_ID = " where id = ? ";
}
}
......@@ -18,7 +18,6 @@ import lombok.experimental.SuperBuilder;
import org.hibernate.annotations.Comment;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.SQLDeleteAll;
import org.hibernate.annotations.Where;
/**
* 分类字典
......@@ -30,20 +29,18 @@ import org.hibernate.annotations.Where;
@Getter
@Setter
@EqualsAndHashCode(callSuper = false)
@SuperBuilder(toBuilder = true)
@NoArgsConstructor
@AllArgsConstructor
@FieldNameConstants
@FieldDefaults(level = AccessLevel.PRIVATE)
@SQLDelete(sql = DELETE_SQL)
@SQLDelete(sql = DELETE_SQL + BasicEntity.Where.WHERE_ID)
@SQLDeleteAll(sql = DELETE_SQL)
@Where(clause = BasicEntity.Where.EXIST)
@Entity
@Table(
name = TABLE_NAME,
indexes = {
@Index(columnList = BasicEntity.Fields.deleteTime),
@Index(columnList = BasicEntity.Fields.deleted),
@Index(columnList = Category.Fields.name),
@Index(columnList = Category.Fields.code),
}
......
/* (C) 2023 YiRing, Inc. */
package com.yiring.dict.domain;
import static com.yiring.dict.domain.Dict.DELETE_SQL;
import static com.yiring.dict.domain.Dict.TABLE_NAME;
import com.fasterxml.jackson.annotation.JsonIgnore;
......@@ -18,7 +17,6 @@ import lombok.experimental.SuperBuilder;
import org.hibernate.annotations.Comment;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.SQLDeleteAll;
import org.hibernate.annotations.Where;
/**
* 字典
......@@ -30,20 +28,18 @@ import org.hibernate.annotations.Where;
@Getter
@Setter
@EqualsAndHashCode(callSuper = false)
@SuperBuilder(toBuilder = true)
@NoArgsConstructor
@AllArgsConstructor
@FieldNameConstants
@FieldDefaults(level = AccessLevel.PRIVATE)
@SQLDelete(sql = DELETE_SQL)
@SQLDeleteAll(sql = DELETE_SQL)
@Where(clause = BasicEntity.Where.EXIST)
@SQLDelete(sql = Category.DELETE_SQL + BasicEntity.Where.WHERE_ID)
@SQLDeleteAll(sql = Category.DELETE_SQL)
@Entity
@Table(
name = TABLE_NAME,
indexes = {
@Index(columnList = BasicEntity.Fields.deleteTime),
@Index(columnList = BasicEntity.Fields.deleted),
@Index(columnList = Dict.Fields.name),
@Index(columnList = Dict.Fields.code),
}
......
/* (C) 2023 YiRing, Inc. */
package com.yiring.dict.domain;
import static com.yiring.dict.domain.DictItem.DELETE_SQL;
import static com.yiring.common.domain.BasicEntity.Where.WHERE_ID;
import static com.yiring.dict.domain.DictItem.TABLE_NAME;
import com.yiring.common.domain.BasicEntity;
......@@ -15,7 +15,6 @@ import lombok.experimental.SuperBuilder;
import org.hibernate.annotations.Comment;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.SQLDeleteAll;
import org.hibernate.annotations.Where;
/**
* 字典选项
......@@ -27,20 +26,18 @@ import org.hibernate.annotations.Where;
@Getter
@Setter
@EqualsAndHashCode(callSuper = false)
@SuperBuilder(toBuilder = true)
@NoArgsConstructor
@AllArgsConstructor
@FieldNameConstants
@FieldDefaults(level = AccessLevel.PRIVATE)
@SQLDelete(sql = DELETE_SQL)
@SQLDeleteAll(sql = DELETE_SQL)
@Where(clause = BasicEntity.Where.EXIST)
@SQLDelete(sql = Category.DELETE_SQL + WHERE_ID)
@SQLDeleteAll(sql = Category.DELETE_SQL)
@Entity
@Table(
name = TABLE_NAME,
indexes = {
@Index(columnList = BasicEntity.Fields.deleteTime),
@Index(columnList = BasicEntity.Fields.deleted),
@Index(columnList = DictItem.Fields.name),
@Index(columnList = DictItem.Fields.enable),
}
......
plugins {
id 'java'
// https://start.spring.io
id 'org.springframework.boot' version '3.0.2'
id 'org.springframework.boot' version '3.0.3'
id 'org.graalvm.buildtools.native' version '0.9.18'
// https://plugins.gradle.org/plugin/io.spring.dependency-management
id 'io.spring.dependency-management' version '1.1.0'
// https://plugins.gradle.org/plugin/com.diffplug.spotless
id "com.diffplug.spotless" version "6.13.0"
id "com.diffplug.spotless" version "6.15.0"
}
ext {
// Spotless
// https://www.npmjs.com/package/prettier
prettierVersion = '2.8.3'
prettierVersion = '2.8.4'
// https://www.npmjs.com/package/prettier-plugin-java
prettierJavaVersion = '2.0.0'
// SpringCloud
// https://start.spring.io/
springCloudVersion = '2022.0.1'
// SpringBootAdmin
// springBootAdminVersion
springBootAdminVersion = '3.0.0'
// Dependencies
// // https://mvnrepository.com/artifact/com.github.xiaoymin/knife4j-openapi3-jakarta-spring-boot-starter
// https://mvnrepository.com/artifact/com.github.xiaoymin/knife4j-openapi3-jakarta-spring-boot-starter
knife4jOpen3Version = '4.0.0'
// https://mvnrepository.com/artifact/io.swagger/swagger-annotations
swaggerAnnotationsVersion = '1.6.9'
......@@ -32,15 +32,15 @@ ext {
// https://mvnrepository.com/artifact/cn.hutool/hutool-all
hutoolVersion = '5.8.12'
// https://mvnrepository.com/artifact/com.alibaba.fastjson2/fastjson2
fastJsonVersion = '2.0.23'
fastJsonVersion = '2.0.24'
// https://mvnrepository.com/artifact/com.xuxueli/xxl-job-core
xxlJobVersion = '2.3.1'
// https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp
okhttpVersion = '4.10.0'
// https://mvnrepository.com/artifact/io.minio/minio
minioVersion = '8.5.1'
minioVersion = '8.5.2'
// https://mvnrepository.com/artifact/io.hypersistence/hypersistence-utils-hibernate-60
hibernateTypesVersion = '3.1.2'
hibernateTypesVersion = '3.2.0'
// https://mvnrepository.com/artifact/org.hibernate/hibernate-spatial
hibernateSpatialVersion = '6.1.7.Final'
// https://mvnrepository.com/artifact/org.locationtech.jts/jts-core
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论