✨ feat: 文件功能修改(#IC68N4),代码生成器移除,需要到ReadMe文档看下地址
This commit is contained in:
parent
74850cf795
commit
42b3a6d150
|
@ -128,7 +128,6 @@ http.authorizeHttpRequests(auth -> auth
|
|||
graph TD
|
||||
|
||||
父工程 -->|主项目| auth-api
|
||||
父工程 -->|代码生成器| generator-code
|
||||
auth-api -->|启动项、控制器| service
|
||||
service -->|mapper| dao
|
||||
service -->|包含domain、配置等| auth-core
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package cn.bunny.services;
|
||||
|
||||
import org.dromara.x.file.storage.spring.EnableFileStorage;
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
@ -11,6 +12,7 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
|
|||
@MapperScan("cn.bunny.services.mapper")
|
||||
@ComponentScan("cn.bunny")
|
||||
@EnableScheduling
|
||||
@EnableFileStorage
|
||||
@EnableCaching
|
||||
@EnableTransactionManagement
|
||||
@SpringBootApplication
|
||||
|
|
|
@ -1,4 +1,38 @@
|
|||
# 生成系统需要的权限
|
||||
# 文档包含配置和一些其他说明
|
||||
|
||||
## 文件上传配置
|
||||
|
||||
如果需要其他平台,需要参考文档:https://x-file-storage.xuyanwu.cn/#/。
|
||||
|
||||
因为按照要求,删除、更新操作需要实现接口,所以目前的`FileRecorder`是实现了的,在`FileDetailService`。
|
||||
|
||||
```yaml
|
||||
# 可以配置很多但只能使用一个!!!其他平台参考官方文档
|
||||
dromara:
|
||||
x-file-storage: # 文件存储配置
|
||||
default-platform: local-plus-1 # 默认使用的存储平台
|
||||
# default-platform: minio-1 # 默认使用的存储平台
|
||||
thumbnail-suffix: ".min.jpg" # 缩略图后缀,例如【.min.jpg】【.png】
|
||||
local-plus:
|
||||
- platform: local-plus-1 # 存储平台标识
|
||||
enable-storage: true # 启用存储
|
||||
enable-access: true # 启用访问(线上请使用 Nginx 配置,效率更高)
|
||||
domain: ${dromara.local-plus.domain}
|
||||
base-path: ${dromara.local-plus.base-path}
|
||||
path-patterns: ${dromara.local-plus.path-patterns}
|
||||
storage-path: ${dromara.local-plus.storage-path}
|
||||
minio:
|
||||
- platform: minio-1 # 存储平台标识
|
||||
enable-storage: true # 启用存储
|
||||
end-point: ${dromara.minio.endpointUrl}
|
||||
domain: ${dromara.minio.endpointUrl}/${dromara.minio.bucket-name}
|
||||
bucket-name: ${dromara.minio.bucket-name}
|
||||
access-key: ${dromara.minio.accessKey}
|
||||
secret-key: ${dromara.minio.secretKey}
|
||||
base-path: ${dromara.minio.base-path}
|
||||
```
|
||||
|
||||
## 生成系统需要的权限
|
||||
|
||||
```java
|
||||
import cn.bunny.services.AuthServiceApplication;
|
||||
|
@ -77,4 +111,59 @@ public class BuildPermissionApiTest {
|
|||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## MInio权限设置
|
||||
|
||||
如果其他平台也需要,根据自己需求进行添加,不需要可以删除这个文件。
|
||||
|
||||
```java
|
||||
/**
|
||||
* 如果项目使用的是minio,创建桶的时候需要设置公开权限
|
||||
* 在这里初始化的时候会自动设置公开权限
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnProperty(name = "dromara.x-file-storage.minio.bucket-name")
|
||||
@Data
|
||||
public class MinioConfiguration {
|
||||
|
||||
/* 地址 */
|
||||
private String domain;
|
||||
/* 访问秘钥 */
|
||||
private String accessKey;
|
||||
/* 私有秘钥 */
|
||||
private String secretKey;
|
||||
/* 桶名称 */
|
||||
private String bucketName;
|
||||
|
||||
@Bean
|
||||
public MinioClient minioClient() {
|
||||
MinioClient minioClient = MinioClient.builder().endpoint(domain).credentials(accessKey, secretKey).build();
|
||||
|
||||
try {
|
||||
// 判断桶是否存在,不存在则创建,并且可以有公开访问权限
|
||||
boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
|
||||
if (!found) {
|
||||
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
|
||||
String publicPolicy = String.format("{\n" +
|
||||
" \"Version\": \"2012-10-17\",\n" +
|
||||
" \"Statement\": [\n" +
|
||||
" {\n" +
|
||||
" \"Effect\": \"Allow\",\n" +
|
||||
" \"Principal\": \"*\",\n" +
|
||||
" \"Action\": [\"s3:GetObject\"],\n" +
|
||||
" \"Resource\": [\"arn:aws:s3:::%s/*\"]\n" +
|
||||
" }\n" +
|
||||
" ]\n" +
|
||||
"}", bucketName);
|
||||
|
||||
minioClient.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucketName).config(publicPolicy).build());
|
||||
}
|
||||
} catch (Exception exception) {
|
||||
exception.getStackTrace();
|
||||
}
|
||||
|
||||
return minioClient;
|
||||
}
|
||||
}
|
||||
```
|
|
@ -1,17 +1,16 @@
|
|||
package cn.bunny.services.controller.system;
|
||||
package cn.bunny.services.controller.file;
|
||||
|
||||
import cn.bunny.services.domain.common.constant.MinioConstant;
|
||||
import cn.bunny.services.domain.common.constant.FileStorageConstant;
|
||||
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
||||
import cn.bunny.services.domain.common.model.vo.result.Result;
|
||||
import cn.bunny.services.domain.system.files.dto.FileUploadDto;
|
||||
import cn.bunny.services.domain.system.files.dto.FilesAddDto;
|
||||
import cn.bunny.services.domain.system.files.dto.FilesAddOrUpdateDto;
|
||||
import cn.bunny.services.domain.system.files.dto.FilesDto;
|
||||
import cn.bunny.services.domain.system.files.dto.FilesUpdateDto;
|
||||
import cn.bunny.services.domain.system.files.entity.Files;
|
||||
import cn.bunny.services.domain.system.files.vo.FileInfoVo;
|
||||
import cn.bunny.services.domain.system.files.vo.FilesVo;
|
||||
import cn.bunny.services.service.system.FilesService;
|
||||
import cn.bunny.services.service.file.FilesService;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
|
@ -23,7 +22,6 @@ import org.springframework.web.bind.annotation.*;
|
|||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
|
@ -56,14 +54,14 @@ public class FilesController {
|
|||
|
||||
@Operation(summary = "更新文件", description = "更新系统文件", tags = "files::update")
|
||||
@PutMapping()
|
||||
public Result<String> updateFiles(@Valid FilesUpdateDto dto) {
|
||||
public Result<String> updateFiles(@Valid FilesAddOrUpdateDto dto) {
|
||||
filesService.updateFiles(dto);
|
||||
return Result.success(ResultCodeEnum.UPDATE_SUCCESS);
|
||||
}
|
||||
|
||||
@Operation(summary = "添加文件", description = "添加系统文件", tags = "files::add")
|
||||
@PostMapping()
|
||||
public Result<Object> addFiles(@Valid FilesAddDto dto) {
|
||||
public Result<Object> addFiles(@Valid FilesAddOrUpdateDto dto) {
|
||||
filesService.addFiles(dto);
|
||||
return Result.success(ResultCodeEnum.ADD_SUCCESS);
|
||||
}
|
||||
|
@ -81,17 +79,10 @@ public class FilesController {
|
|||
return filesService.downloadFilesByFileId(fileId);
|
||||
}
|
||||
|
||||
@Operation(summary = "获取所有文件类型", description = "获取所有文件类型", tags = "files::query")
|
||||
@GetMapping("private/getMediaTypeList")
|
||||
public Result<Set<String>> getMediaTypeList() {
|
||||
Set<String> list = filesService.getMediaTypeList();
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
@Operation(summary = "获取所有文件存储基础路径", description = "获取所有文件存储基础路径", tags = "files::query")
|
||||
@GetMapping("private/getAllFilesStoragePath")
|
||||
public Result<List<String>> getAllFilesStoragePath() {
|
||||
Map<String, String> typeMap = MinioConstant.typeMap;
|
||||
Map<String, String> typeMap = FileStorageConstant.typeMap;
|
||||
List<String> list = typeMap.keySet().stream().toList();
|
||||
|
||||
return Result.success(list);
|
|
@ -0,0 +1,69 @@
|
|||
package cn.bunny.services.controller.file;
|
||||
|
||||
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||
import cn.bunny.services.domain.common.model.vo.result.PageResult;
|
||||
import cn.bunny.services.domain.common.model.vo.result.Result;
|
||||
import cn.bunny.services.domain.system.files.dto.FilesParDetailDto;
|
||||
import cn.bunny.services.domain.system.files.entity.FilesParDetail;
|
||||
import cn.bunny.services.domain.system.files.vo.FilesParDetailVo;
|
||||
import cn.bunny.services.service.file.FilesParDetailService;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 文件分片信息表,仅在手动分片上传时使用 前端控制器
|
||||
* </p>
|
||||
*
|
||||
* @author Bunny
|
||||
* @since 2025-05-08 23:01:19
|
||||
*/
|
||||
@Tag(name = "文件分片信息表,仅在手动分片上传时使用", description = "文件分片信息表,仅在手动分片上传时使用相关接口")
|
||||
@RestController
|
||||
@RequestMapping("/api/filesParDetail")
|
||||
public class FilesParDetailController {
|
||||
|
||||
@Resource
|
||||
private FilesParDetailService filesPardetailService;
|
||||
|
||||
@Operation(summary = "分页查询文件分片信息表,仅在手动分片上传时使用", description = "分页文件分片信息表,仅在手动分片上传时使用", tags = "filesParDetail::query")
|
||||
@GetMapping("{page}/{limit}")
|
||||
public Result<PageResult<FilesParDetailVo>> getFilesParDetailPage(
|
||||
@Parameter(name = "page", description = "当前页", required = true)
|
||||
@PathVariable("page") Integer page,
|
||||
@Parameter(name = "limit", description = "每页记录数", required = true)
|
||||
@PathVariable("limit") Integer limit,
|
||||
FilesParDetailDto dto) {
|
||||
Page<FilesParDetail> pageParams = new Page<>(page, limit);
|
||||
PageResult<FilesParDetailVo> pageResult = filesPardetailService.getFilesParDetailPage(pageParams, dto);
|
||||
return Result.success(pageResult);
|
||||
}
|
||||
|
||||
@Operation(summary = "添加文件分片信息表,仅在手动分片上传时使用", description = "添加文件分片信息表,仅在手动分片上传时使用", tags = "filesParDetail::add")
|
||||
@PostMapping()
|
||||
public Result<String> addFilesParDetail(@Valid @RequestBody FilesParDetailDto dto) {
|
||||
filesPardetailService.addFilesParDetail(dto);
|
||||
return Result.success(ResultCodeEnum.ADD_SUCCESS);
|
||||
}
|
||||
|
||||
@Operation(summary = "更新文件分片信息表,仅在手动分片上传时使用", description = "更新文件分片信息表,仅在手动分片上传时使用", tags = "filesParDetail::update")
|
||||
@PutMapping()
|
||||
public Result<String> updateFilesParDetail(@Valid @RequestBody FilesParDetailDto dto) {
|
||||
filesPardetailService.updateFilesParDetail(dto);
|
||||
return Result.success(ResultCodeEnum.UPDATE_SUCCESS);
|
||||
}
|
||||
|
||||
@Operation(summary = "删除文件分片信息表,仅在手动分片上传时使用", description = "删除文件分片信息表,仅在手动分片上传时使用", tags = "filesParDetail::delete")
|
||||
@DeleteMapping()
|
||||
public Result<String> deleteFilesParDetail(@RequestBody List<Long> ids) {
|
||||
filesPardetailService.deleteFilesParDetail(ids);
|
||||
return Result.success(ResultCodeEnum.DELETE_SUCCESS);
|
||||
}
|
||||
}
|
|
@ -31,11 +31,17 @@ bunny:
|
|||
database: 0
|
||||
password: "123456"
|
||||
|
||||
dromara:
|
||||
local-plus:
|
||||
# 访问域名,例如:“http://127.0.0.1:8030/file”,注意后面要和 path-patterns 名字一样
|
||||
domain: /api/local-file
|
||||
# 访问路径,使用本地在SpringSecurity中要配置权限,如果是和我一样就不用修改了,如果不是api开头,上线需要配置nginx
|
||||
path-patterns: /api/local-file/**
|
||||
storage-path: D:/Temp # 存储路径
|
||||
base-path: "" # 基础路径
|
||||
minio:
|
||||
endpointUrl: "http://192.168.3.137:9000" # 连接地址
|
||||
accessKey: bunny # 用户名
|
||||
secretKey: "12345678" # 登录密码
|
||||
bucket-name: auth-admin # 指定哪个桶
|
||||
|
||||
backPath: "D:\\MyData\\backup"
|
||||
|
||||
base-path: "" # 基础路径
|
|
@ -12,7 +12,9 @@ spring:
|
|||
name: bunny-service
|
||||
servlet:
|
||||
multipart:
|
||||
max-file-size: 6MB
|
||||
max-file-size: 20MB
|
||||
max-request-size: 20MB
|
||||
resolve-lazily: true
|
||||
datasource:
|
||||
type: com.zaxxer.hikari.HikariDataSource
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
|
@ -80,6 +82,29 @@ spring:
|
|||
date-format: yyyy-MM-dd HH:mm:ss
|
||||
time-zone: GMT+8
|
||||
|
||||
# 可以配置很多但只能使用一个!!!其他平台参考官方文档
|
||||
dromara:
|
||||
x-file-storage: # 文件存储配置
|
||||
default-platform: local-plus-1 # 默认使用的存储平台
|
||||
# default-platform: minio-1 # 默认使用的存储平台
|
||||
thumbnail-suffix: ".min.jpg" # 缩略图后缀,例如【.min.jpg】【.png】
|
||||
local-plus:
|
||||
- platform: local-plus-1 # 存储平台标识
|
||||
enable-storage: true # 启用存储
|
||||
enable-access: true # 启用访问(线上请使用 Nginx 配置,效率更高)
|
||||
domain: ${dromara.local-plus.domain}
|
||||
base-path: ${dromara.local-plus.base-path}
|
||||
path-patterns: ${dromara.local-plus.path-patterns}
|
||||
storage-path: ${dromara.local-plus.storage-path}
|
||||
minio:
|
||||
- platform: minio-1 # 存储平台标识
|
||||
enable-storage: true # 启用存储
|
||||
end-point: ${dromara.minio.endpointUrl}
|
||||
domain: ${dromara.minio.endpointUrl}/${dromara.minio.bucket-name}
|
||||
bucket-name: ${dromara.minio.bucket-name}
|
||||
access-key: ${dromara.minio.accessKey}
|
||||
secret-key: ${dromara.minio.secretKey}
|
||||
base-path: ${dromara.minio.base-path}
|
||||
|
||||
mybatis-plus:
|
||||
mapper-locations: classpath:mapper/**/*.xml
|
||||
|
|
|
@ -3,14 +3,6 @@
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||||
<link crossorigin="anonymous" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
|
||||
integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" rel="stylesheet">
|
||||
<script crossorigin="anonymous"
|
||||
integrity="sha384-I7E8VVD/ismYTF4hNIPjVp/Zjvgyol6VFvRkX/vR+Vc4jQkC+hVqc2pM8ODewa9r"
|
||||
src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.8/dist/umd/popper.min.js"></script>
|
||||
<script crossorigin="anonymous"
|
||||
integrity="sha384-0pUGZvbkm6XF6gxjEnlmuGrJXVbNuzT9qBBavbLwCsOGabYfZo0T0to5eqruptLy"
|
||||
src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.min.js"></script>
|
||||
<title>bunny-admin-server项目介绍</title>
|
||||
<style>
|
||||
body {
|
||||
|
@ -54,6 +46,24 @@
|
|||
color: white;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
padding: 9px;
|
||||
background: transparent;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
color: white;
|
||||
background-color: #007BFF;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
background-color: #3498db;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -68,7 +78,8 @@
|
|||
<ul>
|
||||
<li>登录优化:使用登录策略方便以后扩展登录方式</li>
|
||||
<li>邮件发送模板:邮件发送用的是模板方法模式</li>
|
||||
<li>密码校验:登录密码校验器,改用自带的不是md5加密,看起来像这样:<code>$2a$10$h5BUwmMaVcEuu7Bz0TPPy.PQV8JP6CFJlbHTgT78G1s0YPIu2kfXe</code>
|
||||
<li>密码校验:登录密码校验器,改用自带的不是md5加密,看起来像这样:<code>$2a$10$gD2mTVaqIjfgciN.5vQ7uemf.PYNYLFQL4BZdnYswZEjAuC543Vhe</code>
|
||||
这个表示 <code>admin123</code> 的密码;重置或者登不进去就输入这个密码
|
||||
</li>
|
||||
<li>接口请求路径:将原本请求路径<code>/admin</code>改为<code>/api</code></li>
|
||||
</ul>
|
||||
|
@ -79,23 +90,7 @@
|
|||
<div class="carousel-item active">
|
||||
<img alt="验证码图片" class="d-block w-50" src="/public/checkCode" style="margin: 0 auto">
|
||||
</div>
|
||||
<div class="carousel-item">
|
||||
<img alt="验证码图片" class="d-block w-50" src="/public/checkCode" style="margin: 0 auto">
|
||||
</div>
|
||||
<div class="carousel-item">
|
||||
<img alt="验证码图片" class="d-block w-50" src="/public/checkCode" style="margin: 0 auto">
|
||||
</div>
|
||||
</div>
|
||||
<button class="carousel-control-prev btn-link" data-bs-slide="prev" data-bs-target="#carouselExampleIndicators"
|
||||
type="button">
|
||||
<span aria-hidden="true" class="carousel-control-prev-icon"></span>
|
||||
<span class="visually-hidden">Previous</span>
|
||||
</button>
|
||||
<button class="carousel-control-next" data-bs-slide="next" data-bs-target="#carouselExampleIndicators"
|
||||
type="button">
|
||||
<span aria-hidden="true" class="carousel-control-next-icon"></span>
|
||||
<span class="visually-hidden">Next</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<h2>技术栈</h2>
|
||||
|
@ -107,7 +102,7 @@
|
|||
<a class="btn btn-primary"
|
||||
target="_blank"
|
||||
th:href="@{'http://localhost:'+${@environment.getProperty('server.port')}+'/swagger-ui/index.html'}">打开接口文档-swagger</a>
|
||||
<a class="btn btn-success" href="http://bunny-web.site/" target="_blank">查看在线项目</a>
|
||||
<a class="btn btn-primary" href="http://bunny-web.site/" target="_blank">查看在线项目</a>
|
||||
<a class="btn btn-primary" href="http://localhost:7000/" target="_blank">查看本地项目</a>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -119,6 +119,11 @@
|
|||
<groupId>io.minio</groupId>
|
||||
<artifactId>minio</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.dromara.x-file-storage</groupId>
|
||||
<artifactId>x-file-storage-spring</artifactId>
|
||||
<version>2.2.1</version>
|
||||
</dependency>
|
||||
|
||||
<!-- JWT -->
|
||||
<dependency>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package cn.bunny.services.minio;
|
||||
package cn.bunny.services.config;
|
||||
|
||||
import io.minio.BucketExistsArgs;
|
||||
import io.minio.MakeBucketArgs;
|
||||
|
@ -6,19 +6,21 @@ import io.minio.MinioClient;
|
|||
import io.minio.SetBucketPolicyArgs;
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* 如果项目使用的是minio,创建桶的时候需要设置公开权限
|
||||
* 在这里初始化的时候会自动设置公开权限
|
||||
* 不需要可以删除这个文件
|
||||
*/
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "bunny.minio")
|
||||
// 当属性有值时这个配置才生效
|
||||
@ConditionalOnProperty(name = "bunny.minio.bucket-name")
|
||||
@ConditionalOnProperty(name = "dromara.x-file-storage.minio.bucket-name")
|
||||
@Data
|
||||
public class MinioProperties {
|
||||
public class MinioConfiguration {
|
||||
|
||||
/* 地址 */
|
||||
private String endpointUrl;
|
||||
private String domain;
|
||||
/* 访问秘钥 */
|
||||
private String accessKey;
|
||||
/* 私有秘钥 */
|
||||
|
@ -28,7 +30,7 @@ public class MinioProperties {
|
|||
|
||||
@Bean
|
||||
public MinioClient minioClient() {
|
||||
MinioClient minioClient = MinioClient.builder().endpoint(endpointUrl).credentials(accessKey, secretKey).build();
|
||||
MinioClient minioClient = MinioClient.builder().endpoint(domain).credentials(accessKey, secretKey).build();
|
||||
|
||||
try {
|
||||
// 判断桶是否存在,不存在则创建,并且可以有公开访问权限
|
|
@ -0,0 +1,35 @@
|
|||
package cn.bunny.services.domain.common.constant;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
public class FileStorageConstant {
|
||||
public static final String FAVICON = "favicon";
|
||||
public static final String AVATAR = "avatar";
|
||||
public static final String MESSAGE = "message";
|
||||
public static final String CAROUSEL = "carousel";
|
||||
public static final String BACKUP = "backup";
|
||||
public static final String IMAGES = "images";
|
||||
public static final String VIDEO = "video";
|
||||
public static final Map<String, String> typeMap = new HashMap<>();
|
||||
|
||||
static {
|
||||
typeMap.put(FAVICON, "/" + FAVICON + "/");
|
||||
typeMap.put(AVATAR, "/" + AVATAR + "/");
|
||||
typeMap.put(MESSAGE, "/" + MESSAGE + "/");
|
||||
typeMap.put(CAROUSEL, "/" + CAROUSEL + "/");
|
||||
typeMap.put(BACKUP, "/" + BACKUP + "/");
|
||||
typeMap.put(IMAGES, "/" + IMAGES + "/");
|
||||
typeMap.put(VIDEO, "/" + VIDEO + "/");
|
||||
typeMap.put("default", "/" + "default" + "/");
|
||||
}
|
||||
|
||||
public static String getType(String type) {
|
||||
String value = typeMap.get(type);
|
||||
if (value != null) return value;
|
||||
throw new RuntimeException("上传类型错误或缺失");
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
package cn.bunny.services.domain.common.constant;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
public class MinioConstant {
|
||||
public static final String favicon = "favicon";
|
||||
public static final String avatar = "avatar";
|
||||
public static final String message = "message";
|
||||
public static final String carousel = "carousel";
|
||||
public static final String feedback = "feedback";
|
||||
public static final String backup = "backup";
|
||||
public static final Map<String, String> typeMap = new HashMap<>();
|
||||
|
||||
static {
|
||||
typeMap.put(favicon, "/favicon/");
|
||||
typeMap.put(avatar, "/avatar/");
|
||||
typeMap.put(message, "/message/");
|
||||
typeMap.put(carousel, "/carousel/");
|
||||
typeMap.put(feedback, "/feedback/");
|
||||
typeMap.put(backup, "/backup/");
|
||||
typeMap.put("images", "/images/");
|
||||
typeMap.put("video", "/video/");
|
||||
typeMap.put("default", "/default/");
|
||||
}
|
||||
|
||||
public static String getType(String type) {
|
||||
String value = typeMap.get(type);
|
||||
if (value != null) return value;
|
||||
throw new RuntimeException("上传类型错误或缺失");
|
||||
}
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
package cn.bunny.services.domain.common.model.dto.minio;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
@Schema(name = "MinioFilePath", title = "Minion上传返回西悉尼")
|
||||
public class MinioUploadFileInfo {
|
||||
|
||||
@Schema(name = "filename", title = "文件名")
|
||||
private String filename;
|
||||
|
||||
@Schema(name = "uuidFilename", title = "uuid文件名,防止重复")
|
||||
private String uuidFilename;
|
||||
|
||||
@Schema(name = "timeUuidFilename", title = "时间+uuid文件名")
|
||||
private String timeUuidFilename;
|
||||
|
||||
@Schema(name = "filepath", title = "文件路径")
|
||||
private String filepath;
|
||||
|
||||
@Schema(name = "bucketNameFilepath", title = "上传桶名称文件路径")
|
||||
private String bucketNameFilepath;
|
||||
|
||||
}
|
|
@ -24,4 +24,7 @@ public class FileUploadDto {
|
|||
@NotBlank(message = "文件类型不能为空")
|
||||
private String type;
|
||||
|
||||
@Schema(name = "platform", title = "指定的平台")
|
||||
private String platform;
|
||||
|
||||
}
|
|
@ -3,7 +3,6 @@ package cn.bunny.services.domain.system.files.dto;
|
|||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
@ -15,7 +14,10 @@ import java.util.List;
|
|||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Schema(name = "FilesAddDto对象", title = "添加文件", description = "添加文件")
|
||||
public class FilesAddDto {
|
||||
public class FilesAddOrUpdateDto {
|
||||
|
||||
@Schema(name = "id", title = "主键")
|
||||
private Long id;
|
||||
|
||||
@Schema(name = "filepath", title = "文件在服务器上的存储路径")
|
||||
@NotBlank(message = "存储路径不能为空")
|
||||
|
@ -25,8 +27,10 @@ public class FilesAddDto {
|
|||
@Min(value = 0L, message = "最小值为0")
|
||||
private Integer downloadCount = 0;
|
||||
|
||||
@Schema(name = "files", title = "文件")
|
||||
@NotEmpty(message = "文件不能为空")
|
||||
@Schema(name = "files", title = "文件列表,添加时为列表")
|
||||
private List<MultipartFile> files;
|
||||
|
||||
@Schema(name = "file", title = "文件,修改时为 file")
|
||||
private MultipartFile file;
|
||||
|
||||
}
|
|
@ -19,8 +19,14 @@ public class FilesDto {
|
|||
@Schema(name = "filepath", title = "文件在服务器上的存储路径")
|
||||
private String filepath;
|
||||
|
||||
@Schema(name = "fileType", title = "文件的MIME类型")
|
||||
private String fileType;
|
||||
@Schema(name = "contentType", title = "文件的MIME类型")
|
||||
private String contentType;
|
||||
|
||||
@Schema(name = "ext", title = "扩展名")
|
||||
private String ext;
|
||||
|
||||
@Schema(name = "platform", title = "存储平台")
|
||||
private String platform;
|
||||
|
||||
@Schema(name = "downloadCount", title = "下载数量")
|
||||
private Integer downloadCount;
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
package cn.bunny.services.domain.system.files.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
@Schema(name = "FilesParDetailDTO对象", title = "文件分片信息表,仅在手动分片上传时使用", description = "文件分片信息表,仅在手动分片上传时使用的DTO对象")
|
||||
public class FilesParDetailDto {
|
||||
|
||||
@Schema(name = "id", title = "分片id")
|
||||
private String id;
|
||||
|
||||
@Schema(name = "platform", title = "存储平台")
|
||||
private String platform;
|
||||
|
||||
@Schema(name = "uploadId", title = "上传ID,仅在手动分片上传时使用")
|
||||
private String uploadId;
|
||||
|
||||
@Schema(name = "eTag", title = "分片 ETag")
|
||||
private String eTag;
|
||||
|
||||
@Schema(name = "partNumber", title = "分片号。每一个上传的分片都有一个分片号,一般情况下取值范围是1~10000")
|
||||
private Integer partNumber;
|
||||
|
||||
@Schema(name = "partSize", title = "文件大小,单位字节")
|
||||
private Long partSize;
|
||||
|
||||
@Schema(name = "hashInfo", title = "哈希信息")
|
||||
private String hashInfo;
|
||||
|
||||
@Schema(name = "createUser", title = "创建用户")
|
||||
private Long createUser;
|
||||
|
||||
@Schema(name = "updateUser", title = "操作用户")
|
||||
private Long updateUser;
|
||||
|
||||
@Schema(name = "createTime", title = "创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(name = "updateTime", title = "记录文件最后修改的时间戳")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
@Schema(name = "isDeleted", title = "文件是否被删除")
|
||||
private Boolean isDeleted;
|
||||
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
package cn.bunny.services.domain.system.files.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
@Schema(name = "FilesUpdateDto对象", title = "更新文件", description = "文件管理")
|
||||
public class FilesUpdateDto {
|
||||
|
||||
@Schema(name = "id", title = "主键")
|
||||
@NotNull(message = "id不能为空")
|
||||
private Long id;
|
||||
|
||||
@Schema(name = "filename", title = "文件的名称")
|
||||
@NotBlank(message = "文件的名称不能为空")
|
||||
private String filename;
|
||||
|
||||
@Schema(name = "fileType", title = "文件的MIME类型")
|
||||
@NotBlank(message = "文件类型不能为空")
|
||||
private String fileType;
|
||||
|
||||
@Schema(name = "downloadCount", title = "下载数量")
|
||||
@Min(value = 0L, message = "最小值为0")
|
||||
private Integer downloadCount;
|
||||
|
||||
@Schema(name = "file", title = "文件")
|
||||
private MultipartFile files;
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package cn.bunny.services.domain.system.files.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
@Schema(name = "UploadThumbnail对象", title = "上传图片文件")
|
||||
public class UploadThumbnail {
|
||||
|
||||
@Schema(name = "file", title = "图片")
|
||||
MultipartFile file;
|
||||
|
||||
@Schema(name = "preType", title = "类型(路径)")
|
||||
String preType;
|
||||
|
||||
@Schema(name = "thumbnailSuffix", title = "缩略图后缀")
|
||||
String thumbnailSuffix;
|
||||
|
||||
@Schema(name = "saveThFilename", title = "保存文件名称,不包含扩展名")
|
||||
String saveThFilename;
|
||||
|
||||
@Schema(name = "thumbnailWidth", title = "宽度")
|
||||
Integer thumbnailWidth;
|
||||
|
||||
@Schema(name = "thumbnailHeight", title = "高度")
|
||||
Integer thumbnailHeight;
|
||||
|
||||
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package cn.bunny.services.domain.system.files.entity;
|
||||
|
||||
import cn.bunny.services.domain.common.model.entity.BaseEntity;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
@ -8,38 +9,97 @@ import lombok.Getter;
|
|||
import lombok.Setter;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 系统文件表
|
||||
* </p>
|
||||
*
|
||||
* @author Bunny
|
||||
* @since 2024-10-04
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Getter
|
||||
@Setter
|
||||
@Accessors(chain = true)
|
||||
@TableName("sys_files")
|
||||
@Schema(name = "Files对象", title = "系统文件表", description = "系统文件管理")
|
||||
@Schema(name = "Files对象", title = "文件记录")
|
||||
public class Files extends BaseEntity {
|
||||
|
||||
@Schema(name = "filename", title = "文件的名称")
|
||||
@Schema(name = "thSize", title = "缩略图大小,单位字节")
|
||||
private Long thSize;
|
||||
|
||||
@Schema(name = "size", title = "文件大小,单位字节")
|
||||
private Long size;
|
||||
|
||||
@Schema(name = "fileSizeStr", title = "文件大小(字符串)")
|
||||
private String fileSizeStr;
|
||||
|
||||
@Schema(name = "uploadStatus", title = "上传状态,仅在手动分片上传时使用,1:初始化完成,2:上传完成")
|
||||
private Integer uploadStatus;
|
||||
|
||||
@Schema(name = "filename", title = "文件名称")
|
||||
private String filename;
|
||||
|
||||
@Schema(name = "filepath", title = "文件在服务器上的存储路径")
|
||||
@Schema(name = "objectType", title = "文件所属对象类型,例如用户头像,评价图片")
|
||||
private String objectType;
|
||||
|
||||
@Schema(name = "hashInfo", title = "哈希信息")
|
||||
private String hashInfo;
|
||||
|
||||
@Schema(name = "platform", title = "存储平台")
|
||||
private String platform;
|
||||
|
||||
@Schema(name = "thMetadata", title = "缩略图元数据")
|
||||
private String thMetadata;
|
||||
|
||||
@Schema(name = "thUrl", title = "缩略图访问路径")
|
||||
private String thUrl;
|
||||
|
||||
@Schema(name = "thUserMetadata", title = "缩略图用户元数据")
|
||||
private String thUserMetadata;
|
||||
|
||||
@Schema(name = "uploadId", title = "上传ID,仅在手动分片上传时使用")
|
||||
private String uploadId;
|
||||
|
||||
@Schema(name = "fileAcl", title = "文件ACL")
|
||||
private String fileAcl;
|
||||
|
||||
@Schema(name = "url", title = "文件访问地址")
|
||||
private String url;
|
||||
|
||||
@Schema(name = "thFilename", title = "缩略图名称")
|
||||
private String thFilename;
|
||||
|
||||
@Schema(name = "userMetadata", title = "文件用户元数据")
|
||||
private String userMetadata;
|
||||
|
||||
@Schema(name = "filepath", title = "存储路径")
|
||||
private String filepath;
|
||||
|
||||
@Schema(name = "fileSize", title = "文件的大小,以字节为单位")
|
||||
private Long fileSize;
|
||||
@Schema(name = "attr", title = "附加属性")
|
||||
private String attr;
|
||||
|
||||
@Schema(name = "fileType", title = "文件的MIME类型")
|
||||
private String fileType;
|
||||
@Schema(name = "ext", title = "文件扩展名")
|
||||
private String ext;
|
||||
|
||||
@Schema(name = "thContentType", title = "缩略图MIME类型")
|
||||
private String thContentType;
|
||||
|
||||
@Schema(name = "metadata", title = "文件元数据")
|
||||
private String metadata;
|
||||
|
||||
@Schema(name = "objectId", title = "文件所属对象id")
|
||||
private String objectId;
|
||||
|
||||
@Schema(name = "downloadCount", title = "下载数量")
|
||||
private Integer downloadCount;
|
||||
|
||||
@Schema(name = "isDeleted", title = "是否被删除")
|
||||
@Schema(name = "thFileAcl", title = "缩略图文件ACL")
|
||||
private String thFileAcl;
|
||||
|
||||
@Schema(name = "originalFilename", title = "原始文件名")
|
||||
private String originalFilename;
|
||||
|
||||
@Schema(name = "contentType", title = "MIME类型")
|
||||
private String contentType;
|
||||
|
||||
@Schema(name = "basePath", title = "基础存储路径")
|
||||
private String basePath;
|
||||
|
||||
@Schema(name = "isDeleted", title = "文件是否被删除")
|
||||
@TableField(exist = false)
|
||||
private Boolean isDeleted;
|
||||
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package cn.bunny.services.domain.system.files.entity;
|
||||
|
||||
import cn.bunny.services.domain.common.model.entity.BaseEntity;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Getter
|
||||
@Setter
|
||||
@Accessors(chain = true)
|
||||
@TableName("sys_files_part_detail")
|
||||
@Schema(name = "FilesParDetail对象", title = "文件分片信息表,仅在手动分片上传时使用", description = "文件分片信息表,仅在手动分片上传时使用的实体类对象")
|
||||
public class FilesParDetail extends BaseEntity {
|
||||
|
||||
@Schema(name = "platform", title = "存储平台")
|
||||
private String platform;
|
||||
|
||||
@Schema(name = "uploadId", title = "上传ID,仅在手动分片上传时使用")
|
||||
private String uploadId;
|
||||
|
||||
@Schema(name = "eTag", title = "分片 ETag")
|
||||
private String eTag;
|
||||
|
||||
@Schema(name = "partNumber", title = "分片号。每一个上传的分片都有一个分片号,一般情况下取值范围是1~10000")
|
||||
private Integer partNumber;
|
||||
|
||||
@Schema(name = "partSize", title = "文件大小,单位字节")
|
||||
private Long partSize;
|
||||
|
||||
@Schema(name = "hashInfo", title = "哈希信息")
|
||||
private String hashInfo;
|
||||
|
||||
}
|
|
@ -15,22 +15,85 @@ import lombok.*;
|
|||
@Schema(name = "FileInfoVo对象", title = "管理端返回文件信息", description = "管理端返回文件信息")
|
||||
public class FileInfoVo extends BaseVo {
|
||||
|
||||
@Schema(name = "url", title = "文件的路径")
|
||||
private String url;
|
||||
@Schema(name = "thSize", title = "缩略图大小,单位字节")
|
||||
private Long thSize;
|
||||
|
||||
@Schema(name = "filename", title = "文件的名称")
|
||||
@Schema(name = "size", title = "文件大小,单位字节")
|
||||
private Long size;
|
||||
|
||||
@Schema(name = "fileSizeStr", title = "文件大小(字符串)")
|
||||
private String fileSizeStr;
|
||||
|
||||
@Schema(name = "uploadStatus", title = "上传状态,仅在手动分片上传时使用,1:初始化完成,2:上传完成")
|
||||
private Integer uploadStatus;
|
||||
|
||||
@Schema(name = "filename", title = "文件名称")
|
||||
private String filename;
|
||||
|
||||
@Schema(name = "filepath", title = "文件在服务器上的存储路径")
|
||||
@Schema(name = "objectType", title = "文件所属对象类型,例如用户头像,评价图片")
|
||||
private String objectType;
|
||||
|
||||
@Schema(name = "hashInfo", title = "哈希信息")
|
||||
private String hashInfo;
|
||||
|
||||
@Schema(name = "platform", title = "存储平台")
|
||||
private String platform;
|
||||
|
||||
@Schema(name = "thMetadata", title = "缩略图元数据")
|
||||
private String thMetadata;
|
||||
|
||||
@Schema(name = "thUrl", title = "缩略图访问路径")
|
||||
private String thUrl;
|
||||
|
||||
@Schema(name = "thUserMetadata", title = "缩略图用户元数据")
|
||||
private String thUserMetadata;
|
||||
|
||||
@Schema(name = "uploadId", title = "上传ID,仅在手动分片上传时使用")
|
||||
private String uploadId;
|
||||
|
||||
@Schema(name = "fileAcl", title = "文件ACL")
|
||||
private String fileAcl;
|
||||
|
||||
@Schema(name = "url", title = "文件访问地址")
|
||||
private String url;
|
||||
|
||||
@Schema(name = "thFilename", title = "缩略图名称")
|
||||
private String thFilename;
|
||||
|
||||
@Schema(name = "userMetadata", title = "文件用户元数据")
|
||||
private String userMetadata;
|
||||
|
||||
@Schema(name = "filepath", title = "存储路径")
|
||||
private String filepath;
|
||||
|
||||
@Schema(name = "fileSize", title = "文件的大小,以字节为单位")
|
||||
private Long fileSize;
|
||||
@Schema(name = "attr", title = "附加属性")
|
||||
private String attr;
|
||||
|
||||
@Schema(name = "size", title = "文件大小")
|
||||
private String size;
|
||||
@Schema(name = "ext", title = "文件扩展名")
|
||||
private String ext;
|
||||
|
||||
@Schema(name = "fileType", title = "文件的MIME类型")
|
||||
private String fileType;
|
||||
@Schema(name = "thContentType", title = "缩略图MIME类型")
|
||||
private String thContentType;
|
||||
|
||||
@Schema(name = "metadata", title = "文件元数据")
|
||||
private String metadata;
|
||||
|
||||
@Schema(name = "objectId", title = "文件所属对象id")
|
||||
private String objectId;
|
||||
|
||||
@Schema(name = "downloadCount", title = "下载数量")
|
||||
private Integer downloadCount;
|
||||
|
||||
@Schema(name = "thFileAcl", title = "缩略图文件ACL")
|
||||
private String thFileAcl;
|
||||
|
||||
@Schema(name = "originalFilename", title = "原始文件名")
|
||||
private String originalFilename;
|
||||
|
||||
@Schema(name = "contentType", title = "MIME类型")
|
||||
private String contentType;
|
||||
|
||||
@Schema(name = "basePath", title = "基础存储路径")
|
||||
private String basePath;
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
package cn.bunny.services.domain.system.files.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Schema(name = "FilesParDetailVO对象", title = "文件分片信息表,仅在手动分片上传时使用", description = "文件分片信息表,仅在手动分片上传时使用的VO对象")
|
||||
public class FilesParDetailVo {
|
||||
|
||||
@Schema(name = "id", title = "分片id")
|
||||
private String id;
|
||||
|
||||
@Schema(name = "platform", title = "存储平台")
|
||||
private String platform;
|
||||
|
||||
@Schema(name = "uploadId", title = "上传ID,仅在手动分片上传时使用")
|
||||
private String uploadId;
|
||||
|
||||
@Schema(name = "eTag", title = "分片 ETag")
|
||||
private String eTag;
|
||||
|
||||
@Schema(name = "partNumber", title = "分片号。每一个上传的分片都有一个分片号,一般情况下取值范围是1~10000")
|
||||
private Integer partNumber;
|
||||
|
||||
@Schema(name = "partSize", title = "文件大小,单位字节")
|
||||
private Long partSize;
|
||||
|
||||
@Schema(name = "hashInfo", title = "哈希信息")
|
||||
private String hashInfo;
|
||||
|
||||
@Schema(name = "createUser", title = "创建用户")
|
||||
private Long createUser;
|
||||
|
||||
@Schema(name = "updateUser", title = "操作用户")
|
||||
private Long updateUser;
|
||||
|
||||
@Schema(name = "createTime", title = "创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(name = "updateTime", title = "记录文件最后修改的时间戳")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
@Schema(name = "isDeleted", title = "文件是否被删除")
|
||||
private Boolean isDeleted;
|
||||
|
||||
}
|
||||
|
|
@ -1,111 +0,0 @@
|
|||
package cn.bunny.services.minio;
|
||||
|
||||
import cn.bunny.services.domain.common.constant.UserConstant;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
|
||||
@Component
|
||||
public class MinioHelper {
|
||||
|
||||
@Resource
|
||||
private MinioProperties properties;
|
||||
|
||||
/**
|
||||
* 格式化用户头像URL
|
||||
*
|
||||
* <p>实现头像URL的统一存储和访问格式转换:</p>
|
||||
*
|
||||
* <ol>
|
||||
* <li><b>存储处理</b>:将带HTTP前缀的头像URL转换为数据库存储格式
|
||||
* <ul>
|
||||
* <li>匹配正则表达式:^https?://.*?/(.*)</li>
|
||||
* <li>提取路径部分:matcher.group(1)</li>
|
||||
* <li>转换为存储格式:"/" + 提取的路径</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* <li><b>访问处理</b>:返回带HTTP前缀的完整访问URL</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>典型用例:</p>
|
||||
* <pre>
|
||||
* 输入:"http|s://example.com/images/avatar.jpg"
|
||||
* 存储:"images/avatar.jpg"
|
||||
* 访问:"http|s://xxx/images/avatar.jpg"
|
||||
* </pre>
|
||||
*
|
||||
* @param avatar 头像URL(可能包含HTTP前缀或数据库存储格式)
|
||||
* @return 格式化后的头像URL(确保包含HTTP前缀)
|
||||
* @throws PatternSyntaxException 当正则表达式匹配失败时抛出
|
||||
* @throws IllegalArgumentException 当头像参数为空时抛出
|
||||
*/
|
||||
public String formatUserAvatar(String avatar) {
|
||||
// 如果用户没有头像或者用户头像和默认头像相同,返回默认头像
|
||||
String userAvatar = UserConstant.USER_AVATAR;
|
||||
if (!StringUtils.hasText(avatar) || avatar.equals(userAvatar)) return userAvatar;
|
||||
|
||||
// 替换前端发送的host前缀,将其删除,只保留路径名称
|
||||
String regex = "^https?://.*?/(.*)";
|
||||
Pattern pattern = Pattern.compile(regex);
|
||||
Matcher matcher = pattern.matcher(avatar);
|
||||
|
||||
// 如果没有匹配
|
||||
if (!matcher.matches()) return avatar;
|
||||
|
||||
// 匹配后返回内容
|
||||
return "/" + matcher.group(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查并格式化用户头像URL
|
||||
*
|
||||
* <p>处理逻辑:</p>
|
||||
* <ol>
|
||||
* <li>当头像为空或与默认头像相同时,返回系统默认头像</li>
|
||||
* <li>尝试移除头像URL中的HTTP协议和域名部分(如果存在)</li>
|
||||
* <li>最终返回MinIO存储中的完整对象访问路径</li>
|
||||
* </ol>
|
||||
*
|
||||
* @param avatar 用户头像URL,可能为以下格式:
|
||||
* - 空/null(使用默认头像)
|
||||
* - 完整HTTP URL(如"http|s://example.com/images/1.jpg")
|
||||
* - MinIO对象路径(如"images/1.jpg")
|
||||
* @return 格式化后的头像URL,保证是可访问的完整路径
|
||||
* - 默认头像(当输入无效时)
|
||||
* - MinIO完整访问路径(处理成功时)
|
||||
* @see UserConstant#USER_AVATAR 默认头像常量
|
||||
* @see #getObjectNameFullPath MinIO路径处理方法
|
||||
*/
|
||||
public String getUserAvatar(String avatar) {
|
||||
// 如果用户没有头像或者用户头像和默认头像相同,返回默认头像
|
||||
String userAvatar = UserConstant.USER_AVATAR;
|
||||
if (!StringUtils.hasText(avatar) || avatar.equals(userAvatar)) return userAvatar;
|
||||
|
||||
// 替换前端发送的host前缀,将其删除,只保留路径名称
|
||||
String regex = "^https?://.*?/(.*)";
|
||||
Pattern pattern = Pattern.compile(regex);
|
||||
Matcher matcher = pattern.matcher(avatar);
|
||||
|
||||
// 如果没有匹配
|
||||
if (matcher.matches()) return avatar;
|
||||
|
||||
// 匹配后返回内容
|
||||
return getObjectNameFullPath(avatar);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Minio全路径名,Object带有桶名称
|
||||
*
|
||||
* @param objectName 对象名称
|
||||
* @return 全路径
|
||||
*/
|
||||
public String getObjectNameFullPath(String objectName) {
|
||||
String url = properties.getEndpointUrl();
|
||||
|
||||
return url + objectName;
|
||||
}
|
||||
}
|
|
@ -1,227 +0,0 @@
|
|||
package cn.bunny.services.minio;
|
||||
|
||||
import cn.bunny.services.domain.common.constant.MinioConstant;
|
||||
import cn.bunny.services.domain.common.model.dto.minio.MinioUploadFileInfo;
|
||||
import cn.bunny.services.domain.common.enums.ResultCodeEnum;
|
||||
import cn.bunny.services.exception.AuthCustomerException;
|
||||
import io.minio.*;
|
||||
import io.minio.messages.DeleteError;
|
||||
import io.minio.messages.DeleteObject;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Minio操作工具类 简化操作步骤
|
||||
* 自定义封装
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class MinioService {
|
||||
|
||||
@Resource
|
||||
private MinioProperties properties;
|
||||
|
||||
@Resource
|
||||
private MinioClient minioClient;
|
||||
|
||||
/**
|
||||
* 上传文件到MinIO并返回文件处理信息
|
||||
*
|
||||
* <p><b>文件存储规则:</b></p>
|
||||
* <ul>
|
||||
* <li>按日期分目录存储(格式:yyyy/MM-dd)</li>
|
||||
* <li>使用UUID重命名文件防止冲突</li>
|
||||
* <li>保留原始文件名信息</li>
|
||||
* <li>支持按类型分类存储(通过minioPreType参数)</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p><b>返回信息包含:</b></p>
|
||||
* <ol>
|
||||
* <li>原始文件名</li>
|
||||
* <li>UUID重命名后的文件名</li>
|
||||
* <li>带日期路径的文件名</li>
|
||||
* <li>完整存储路径(不含桶名)</li>
|
||||
* <li>完整访问路径(含桶名)</li>
|
||||
* </ol>
|
||||
*
|
||||
* @param file 上传的文件对象(不可为空)
|
||||
* @param minioPreType 文件类型前缀(用于分类存储,参考MinioConstant定义)
|
||||
* @return 文件处理信息对象(包含各种路径信息),当file为null时返回null
|
||||
* @throws IOException 当文件流读取异常时抛出
|
||||
* @throws AuthCustomerException 当上传失败时抛出(错误码:UPLOAD_ERROR)
|
||||
* @see MinioConstant 文件类型前缀常量
|
||||
* @see MinioUploadFileInfo 返回信息数据结构
|
||||
*/
|
||||
public MinioUploadFileInfo uploadWithFileInfo(MultipartFile file, String minioPreType) throws IOException {
|
||||
if (file == null) return null;
|
||||
|
||||
// 上传文件时的桶名称
|
||||
String bucketName = properties.getBucketName();
|
||||
|
||||
// 上传对象
|
||||
try {
|
||||
String uuid = UUID.randomUUID().toString();
|
||||
// 定义日期时间格式
|
||||
String dateFormatter = new SimpleDateFormat("yyyy/MM-dd").format(new Date());
|
||||
// 文件后缀
|
||||
String extension = "";
|
||||
|
||||
// 原始文件名
|
||||
String filename = file.getOriginalFilename();
|
||||
if (StringUtils.hasText(filename) && filename.contains(".")) {
|
||||
extension = "." + filename.substring(filename.lastIndexOf(".") + 1);
|
||||
}
|
||||
|
||||
// UUID防止重名
|
||||
String uuidFilename = uuid + extension;
|
||||
|
||||
// 拼接时间+UUID文件名 加上时间路径
|
||||
String timeUuidFilename = dateFormatter + "/" + uuidFilename;
|
||||
|
||||
// 上传根文件夹+拼接时间+UUID文件名
|
||||
String filepath = MinioConstant.getType(minioPreType) + timeUuidFilename;
|
||||
|
||||
// 桶名称+上传根文件夹+拼接时间+UUID文件名
|
||||
String buckNameFilepath = "/" + bucketName + MinioConstant.getType(minioPreType) + timeUuidFilename;
|
||||
|
||||
// 设置及Minio基础信息
|
||||
MinioUploadFileInfo minioUploadFIleInfo = new MinioUploadFileInfo();
|
||||
minioUploadFIleInfo.setFilename(filename);
|
||||
minioUploadFIleInfo.setUuidFilename(uuidFilename);
|
||||
minioUploadFIleInfo.setTimeUuidFilename(timeUuidFilename);
|
||||
minioUploadFIleInfo.setFilepath(filepath);
|
||||
minioUploadFIleInfo.setBucketNameFilepath(buckNameFilepath);
|
||||
|
||||
minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(minioUploadFIleInfo.getFilepath()).stream(file.getInputStream(), file.getSize(), -1).build());
|
||||
|
||||
return minioUploadFIleInfo;
|
||||
} catch (Exception exception) {
|
||||
throw new AuthCustomerException(ResultCodeEnum.UPLOAD_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取默认存储桶中的文件字节数组
|
||||
*
|
||||
* <p><b>注意:</b>会一次性读取全部文件内容到内存,大文件慎用</p>
|
||||
*
|
||||
* @param objectName 对象全路径名称(包含目录路径)
|
||||
* @return 文件内容的字节数组
|
||||
* @throws AuthCustomerException 当获取失败时抛出(错误码:{@link ResultCodeEnum#GET_BUCKET_EXCEPTION})
|
||||
*/
|
||||
public byte[] getBucketObjectByte(String objectName) {
|
||||
String bucketName = properties.getBucketName();
|
||||
|
||||
try {
|
||||
GetObjectResponse getObjectResponse = minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(objectName).build());
|
||||
|
||||
return getObjectResponse.readAllBytes();
|
||||
} catch (Exception exception) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
throw new AuthCustomerException(ResultCodeEnum.GET_BUCKET_EXCEPTION);
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传文件到指定存储桶
|
||||
*
|
||||
* @param bucketName 存储桶名称
|
||||
* @param filename 对象存储路径(包含文件名)
|
||||
* @param inputStream 文件输入流(调用方负责关闭)
|
||||
* @param size 文件大小(字节)
|
||||
* @throws AuthCustomerException 当上传失败时抛出(错误码:{@link ResultCodeEnum#UPLOAD_ERROR})
|
||||
*/
|
||||
public void putObject(String bucketName, String filename, InputStream inputStream, Long size) {
|
||||
try {
|
||||
minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(filename).stream(inputStream, size, -1).build());
|
||||
} catch (Exception exception) {
|
||||
log.error("上传文件失败:{}", (Object) exception.getStackTrace());
|
||||
throw new AuthCustomerException(ResultCodeEnum.UPLOAD_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除存储桶中的对象文件
|
||||
*
|
||||
* @param list 要删除的对象路径列表
|
||||
* @throws AuthCustomerException 当删除失败时抛出(包含错误对象信息)
|
||||
*/
|
||||
public void removeObjects(List<String> list) {
|
||||
try {
|
||||
String bucketName = properties.getBucketName();
|
||||
List<DeleteObject> objectList = list.stream().map(DeleteObject::new).toList();
|
||||
|
||||
Iterable<Result<DeleteError>> results = minioClient.removeObjects(RemoveObjectsArgs.builder().bucket(bucketName).objects(objectList).build());
|
||||
for (Result<DeleteError> result : results) {
|
||||
DeleteError error = result.get();
|
||||
throw new AuthCustomerException("Error in deleting object " + error.objectName() + "; " + error.message());
|
||||
}
|
||||
} catch (Exception exception) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新存储桶中的文件(覆盖写入)
|
||||
*
|
||||
* @param bucketName 存储桶名称
|
||||
* @param filepath 对象存储路径
|
||||
* @param file 新的文件对象
|
||||
* @throws AuthCustomerException 当更新失败时抛出
|
||||
*/
|
||||
public void updateFile(String bucketName, String filepath, MultipartFile file) {
|
||||
try {
|
||||
putObject(bucketName, filepath, file.getInputStream(), file.getSize());
|
||||
} catch (IOException e) {
|
||||
throw new AuthCustomerException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查并创建存储桶(如果不存在)
|
||||
*
|
||||
* @param bucketName 存储桶名称
|
||||
* @return true-已存在,false-新创建
|
||||
* @throws AuthCustomerException 当操作失败时抛出
|
||||
*/
|
||||
public boolean createBucketIfNotExists(String bucketName) {
|
||||
boolean found = false;
|
||||
try {
|
||||
found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
|
||||
|
||||
// 如果 bucket 不存在就创建
|
||||
if (!found) makeBucket(bucketName);
|
||||
|
||||
return found;
|
||||
} catch (Exception exception) {
|
||||
log.error("判断桶是否存在 ------ 失败消息:{}", exception.getLocalizedMessage());
|
||||
exception.getStackTrace();
|
||||
}
|
||||
throw new AuthCustomerException("未初始化 bucket");
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建新的存储桶
|
||||
*
|
||||
* @param bucketName 存储桶名称(需符合命名规范)
|
||||
* @throws AuthCustomerException 当创建失败时抛出
|
||||
*/
|
||||
public void makeBucket(String bucketName) {
|
||||
try {
|
||||
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
|
||||
} catch (Exception exception) {
|
||||
exception.getStackTrace();
|
||||
throw new AuthCustomerException("创建失败");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package cn.bunny.services.mapper.system;
|
||||
package cn.bunny.services.mapper.file;
|
||||
|
||||
import cn.bunny.services.domain.system.files.dto.FilesDto;
|
||||
import cn.bunny.services.domain.system.files.entity.Files;
|
|
@ -0,0 +1,31 @@
|
|||
package cn.bunny.services.mapper.file;
|
||||
|
||||
import cn.bunny.services.domain.system.files.dto.FilesParDetailDto;
|
||||
import cn.bunny.services.domain.system.files.entity.FilesParDetail;
|
||||
import cn.bunny.services.domain.system.files.vo.FilesParDetailVo;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 文件分片信息表,仅在手动分片上传时使用 Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author Bunny
|
||||
* @since 2025-05-08 23:01:19
|
||||
*/
|
||||
@Mapper
|
||||
public interface FilesParDetailMapper extends BaseMapper<FilesParDetail> {
|
||||
|
||||
/**
|
||||
* * 分页查询文件分片信息表,仅在手动分片上传时使用内容
|
||||
*
|
||||
* @param pageParams 文件分片信息表,仅在手动分片上传时使用分页参数
|
||||
* @param dto 文件分片信息表,仅在手动分片上传时使用查询表单
|
||||
* @return 文件分片信息表,仅在手动分片上传时使用分页结果
|
||||
*/
|
||||
IPage<FilesParDetailVo> selectListByPage(@Param("page") Page<FilesParDetail> pageParams, @Param("dto") FilesParDetailDto dto);
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
<?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="cn.bunny.services.mapper.file.FilesMapper">
|
||||
|
||||
<!-- 通用查询映射结果 -->
|
||||
<resultMap id="BaseResultMap" type="cn.bunny.services.domain.system.files.entity.Files">
|
||||
<id column="id" property="id"/>
|
||||
<id column="url" property="url"/>
|
||||
<id column="size" property="size"/>
|
||||
<id column="filename" property="filename"/>
|
||||
<id column="original_filename" property="originalFilename"/>
|
||||
<id column="base_path" property="basePath"/>
|
||||
<id column="filepath" property="filepath"/>
|
||||
<id column="ext" property="ext"/>
|
||||
<id column="content_type" property="contentType"/>
|
||||
<id column="platform" property="platform"/>
|
||||
<id column="th_url" property="thUrl"/>
|
||||
<id column="th_filename" property="thFilename"/>
|
||||
<id column="th_size" property="thSize"/>
|
||||
<id column="th_content_type" property="thContentType"/>
|
||||
<id column="object_id" property="objectId"/>
|
||||
<id column="object_type" property="objectType"/>
|
||||
<id column="metadata" property="metadata"/>
|
||||
<id column="user_metadata" property="userMetadata"/>
|
||||
<id column="th_metadata" property="thMetadata"/>
|
||||
<id column="th_user_metadata" property="thUserMetadata"/>
|
||||
<id column="attr" property="attr"/>
|
||||
<id column="file_acl" property="fileAcl"/>
|
||||
<id column="th_file_acl" property="thFileAcl"/>
|
||||
<id column="hash_info" property="hashInfo"/>
|
||||
<id column="upload_id" property="uploadId"/>
|
||||
<id column="upload_status" property="uploadStatus"/>
|
||||
<id column="download_count" property="downloadCount"/>
|
||||
<id column="create_user" property="createUser"/>
|
||||
<id column="update_user" property="updateUser"/>
|
||||
<id column="create_time" property="createTime"/>
|
||||
<id column="update_time" property="updateTime"/>
|
||||
<id column="is_deleted" property="isDeleted"/>
|
||||
<id column="id" property="id"/>
|
||||
<id column="filename" property="filename"/>
|
||||
<id column="filepath" property="filepath"/>
|
||||
</resultMap>
|
||||
|
||||
<!-- 分页查询系统文件表内容 -->
|
||||
<select id="selectListByPage" resultType="cn.bunny.services.domain.system.files.vo.FilesVo">
|
||||
select
|
||||
files.*,
|
||||
create_user.username as create_username,
|
||||
update_user.username as update_username
|
||||
from sys_files files
|
||||
left join sys_user create_user on create_user.id = files.create_user
|
||||
left join sys_user update_user on update_user.id = files.update_user
|
||||
<where>
|
||||
files.is_deleted = 0
|
||||
<if test="dto.filename != null and dto.filename != ''">
|
||||
and files.filename like CONCAT('%',#{dto.filename},'%')
|
||||
</if>
|
||||
<if test="dto.filepath != null and dto.filepath != ''">
|
||||
and files.filepath like CONCAT('%',#{dto.filepath},'%')
|
||||
</if>
|
||||
<if test="dto.contentType != null and dto.contentType != ''">
|
||||
and files.content_type like CONCAT('%',#{dto.contentType},'%')
|
||||
</if>
|
||||
<if test="dto.ext != null and dto.ext != ''">
|
||||
and files.ext like CONCAT('%',#{dto.ext},'%')
|
||||
</if>
|
||||
<if test="dto.platform != null and dto.platform != ''">
|
||||
and files.platform like CONCAT('%',#{dto.platform},'%')
|
||||
</if>
|
||||
<if test="dto.downloadCount != null">
|
||||
and files.download_count = #{dto.downloadCount}
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
</mapper>
|
|
@ -0,0 +1,71 @@
|
|||
<?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="cn.bunny.services.mapper.file.FilesParDetailMapper">
|
||||
|
||||
<!-- 通用查询映射结果 -->
|
||||
<resultMap id="BaseResultMap" type="cn.bunny.services.domain.system.files.entity.FilesParDetail">
|
||||
<id column="id" property="id"/>
|
||||
<id column="platform" property="platform"/>
|
||||
<id column="upload_id" property="uploadId"/>
|
||||
<id column="e_tag" property="eTag"/>
|
||||
<id column="part_number" property="partNumber"/>
|
||||
<id column="part_size" property="partSize"/>
|
||||
<id column="hash_info" property="hashInfo"/>
|
||||
<id column="create_user" property="createUser"/>
|
||||
<id column="update_user" property="updateUser"/>
|
||||
<id column="create_time" property="createTime"/>
|
||||
<id column="update_time" property="updateTime"/>
|
||||
<id column="is_deleted" property="isDeleted"/>
|
||||
</resultMap>
|
||||
|
||||
<!-- 分页查询文件分片信息表,仅在手动分片上传时使用内容 -->
|
||||
<select id="selectListByPage" resultType="cn.bunny.services.domain.system.files.vo.FilesParDetailVo">
|
||||
select
|
||||
base.*,
|
||||
create_user.username as create_username,
|
||||
update_user.username as update_username
|
||||
from sys_files_part_detail base
|
||||
left join sys_user create_user on create_user.id = base.create_user
|
||||
left join sys_user update_user on update_user.id = base.update_user
|
||||
<where>
|
||||
base.is_deleted = 0
|
||||
<if test="dto.id != null and dto.id != ''">
|
||||
and base.id like CONCAT('%',#{dto.id},'%')
|
||||
</if>
|
||||
<if test="dto.platform != null and dto.platform != ''">
|
||||
and base.platform like CONCAT('%',#{dto.platform},'%')
|
||||
</if>
|
||||
<if test="dto.uploadId != null and dto.uploadId != ''">
|
||||
and base.upload_id like CONCAT('%',#{dto.uploadId},'%')
|
||||
</if>
|
||||
<if test="dto.eTag != null and dto.eTag != ''">
|
||||
and base.e_tag like CONCAT('%',#{dto.eTag},'%')
|
||||
</if>
|
||||
<if test="dto.partNumber != null and dto.partNumber != ''">
|
||||
and base.part_number like CONCAT('%',#{dto.partNumber},'%')
|
||||
</if>
|
||||
<if test="dto.partSize != null and dto.partSize != ''">
|
||||
and base.part_size like CONCAT('%',#{dto.partSize},'%')
|
||||
</if>
|
||||
<if test="dto.hashInfo != null and dto.hashInfo != ''">
|
||||
and base.hash_info like CONCAT('%',#{dto.hashInfo},'%')
|
||||
</if>
|
||||
<if test="dto.createUser != null and dto.createUser != ''">
|
||||
and base.create_user like CONCAT('%',#{dto.createUser},'%')
|
||||
</if>
|
||||
<if test="dto.updateUser != null and dto.updateUser != ''">
|
||||
and base.update_user like CONCAT('%',#{dto.updateUser},'%')
|
||||
</if>
|
||||
<if test="dto.createTime != null and dto.createTime != ''">
|
||||
and base.create_time like CONCAT('%',#{dto.createTime},'%')
|
||||
</if>
|
||||
<if test="dto.updateTime != null and dto.updateTime != ''">
|
||||
and base.update_time like CONCAT('%',#{dto.updateTime},'%')
|
||||
</if>
|
||||
<if test="dto.isDeleted != null and dto.isDeleted != ''">
|
||||
and base.is_deleted like CONCAT('%',#{dto.isDeleted},'%')
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
</mapper>
|
|
@ -1,52 +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="cn.bunny.services.mapper.system.FilesMapper">
|
||||
|
||||
<!-- 通用查询映射结果 -->
|
||||
<resultMap id="BaseResultMap" type="cn.bunny.services.domain.system.files.entity.Files">
|
||||
<id column="id" property="id"/>
|
||||
<id column="create_time" property="createTime"/>
|
||||
<id column="update_time" property="updateTime"/>
|
||||
<id column="create_user" property="createUser"/>
|
||||
<id column="update_user" property="updateUser"/>
|
||||
<id column="is_deleted" property="isDeleted"/>
|
||||
<id column="filename" property="filename"/>
|
||||
<id column="filepath" property="filepath"/>
|
||||
<id column="file_size" property="fileSize"/>
|
||||
<id column="file_type" property="fileType"/>
|
||||
<id column="download_count" property="downloadCount"/>
|
||||
</resultMap>
|
||||
|
||||
<!-- 通用查询结果列 -->
|
||||
<sql id="Base_Column_List">
|
||||
id, create_time, update_time, create_user, update_user, is_deleted, filename, filepath, file_size, file_type,
|
||||
download_count
|
||||
</sql>
|
||||
|
||||
<!-- 分页查询系统文件表内容 -->
|
||||
<select id="selectListByPage" resultType="cn.bunny.services.domain.system.files.vo.FilesVo">
|
||||
select
|
||||
files.*,
|
||||
create_user.username as create_username,
|
||||
update_user.username as update_username
|
||||
from sys_files files
|
||||
left join sys_user create_user on create_user.id = files.create_user
|
||||
left join sys_user update_user on update_user.id = files.update_user
|
||||
<where>
|
||||
files.is_deleted = 0
|
||||
<if test="dto.filename != null and dto.filename != ''">
|
||||
and files.filename like CONCAT('%',#{dto.filename},'%')
|
||||
</if>
|
||||
<if test="dto.filepath != null and dto.filepath != ''">
|
||||
and files.filepath like CONCAT('%',#{dto.filepath},'%')
|
||||
</if>
|
||||
<if test="dto.fileType != null and dto.fileType != ''">
|
||||
and files.file_type like CONCAT('%',#{dto.fileType},'%')
|
||||
</if>
|
||||
<if test="dto.downloadCount != null and dto.downloadCount != ''">
|
||||
and files.download_count like CONCAT('%',#{dto.downloadCount},'%')
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
</mapper>
|
|
@ -1,117 +0,0 @@
|
|||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>cn.bunny</groupId>
|
||||
<artifactId>auth-server</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>generator-code</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>generator-code</name>
|
||||
<url>https://maven.apache.org</url>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-devtools</artifactId>
|
||||
<scope>runtime</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- <dependency> -->
|
||||
<!-- <groupId>org.xerial</groupId> -->
|
||||
<!-- <artifactId>sqlite-jdbc</artifactId> -->
|
||||
<!-- <version>3.49.1.0</version> -->
|
||||
<!-- </dependency> -->
|
||||
<dependency>
|
||||
<groupId>com.mysql</groupId>
|
||||
<artifactId>mysql-connector-j</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.zaxxer</groupId>
|
||||
<artifactId>HikariCP</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-jdbc</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.jsqlparser</groupId>
|
||||
<artifactId>jsqlparser</artifactId>
|
||||
<version>5.1</version>
|
||||
</dependency>
|
||||
|
||||
<!-- lombok -->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- knife4j -->
|
||||
<dependency>
|
||||
<groupId>com.github.xiaoymin</groupId>
|
||||
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springdoc</groupId>
|
||||
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
|
||||
<version>2.8.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.swagger</groupId>
|
||||
<artifactId>swagger-annotations</artifactId>
|
||||
<version>1.6.14</version>
|
||||
</dependency>
|
||||
|
||||
<!-- fastjson2 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.fastjson2</groupId>
|
||||
<artifactId>fastjson2</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 小驼峰 和 大驼峰之间互转 -->
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>33.4.7-jre</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.velocity</groupId>
|
||||
<artifactId>velocity-engine-core</artifactId>
|
||||
<version>2.3</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -1,11 +0,0 @@
|
|||
package cn.bunny;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class GeneratorCodeMainApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(GeneratorCodeMainApplication.class, args);
|
||||
}
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
package cn.bunny.config;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer;
|
||||
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
|
||||
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.web.bind.WebDataBinder;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.InitBinder;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* 去除前端传递的空格
|
||||
*/
|
||||
@ControllerAdvice
|
||||
public class ControllerStringParamTrimConfig {
|
||||
|
||||
/**
|
||||
* 创建 String trim 编辑器
|
||||
* 构造方法中 boolean 参数含义为如果是空白字符串,是否转换为null
|
||||
* 即如果为true,那么 " " 会被转换为 null,否者为 ""
|
||||
*/
|
||||
@InitBinder
|
||||
public void initBinder(WebDataBinder binder) {
|
||||
StringTrimmerEditor propertyEditor = new StringTrimmerEditor(false);
|
||||
// 为 String 类对象注册编辑器
|
||||
binder.registerCustomEditor(String.class, propertyEditor);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
|
||||
return jacksonObjectMapperBuilder -> {
|
||||
// 为 String 类型自定义反序列化操作
|
||||
jacksonObjectMapperBuilder
|
||||
.deserializerByType(String.class, new StdScalarDeserializer<String>(String.class) {
|
||||
@Override
|
||||
public String deserialize(JsonParser jsonParser, DeserializationContext ctx) throws IOException {
|
||||
// // 去除全部空格
|
||||
// return StringUtils.trimAllWhitespace(jsonParser.getValueAsString());
|
||||
|
||||
// 仅去除前后空格
|
||||
return jsonParser.getValueAsString().trim();
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
package cn.bunny.config;
|
||||
|
||||
import io.swagger.v3.oas.models.ExternalDocumentation;
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import io.swagger.v3.oas.models.info.Contact;
|
||||
import io.swagger.v3.oas.models.info.Info;
|
||||
import io.swagger.v3.oas.models.info.License;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springdoc.core.models.GroupedOpenApi;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@Slf4j
|
||||
public class Knife4jConfig {
|
||||
|
||||
@Value("${server.port}")
|
||||
private String port;
|
||||
|
||||
@Bean
|
||||
public OpenAPI openAPI() {
|
||||
String url = "http://localhost:" + port;
|
||||
|
||||
// 作者等信息
|
||||
Contact contact = new Contact().name("Bunny").email("1319900154@qq.com").url(url);
|
||||
// 使用协议
|
||||
License license = new License().name("MIT").url("https://mit-license.org");
|
||||
// 相关信息
|
||||
Info info = new Info().title("Bunny-Admin")
|
||||
.contact(contact).license(license)
|
||||
.description("Bunny代码生成器")
|
||||
.summary("Bunny的代码生成器")
|
||||
.termsOfService(url)
|
||||
.version("v1.0.0");
|
||||
|
||||
return new OpenAPI().info(info).externalDocs(new ExternalDocumentation());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public GroupedOpenApi all() {
|
||||
return GroupedOpenApi.builder().group("全部请求接口").pathsToMatch("/api/**").build();
|
||||
}
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
package cn.bunny.config;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import org.apache.velocity.app.Velocity;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
@Component
|
||||
public class VmsHolder {
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
Properties prop = new Properties();
|
||||
prop.put("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
|
||||
Velocity.init(prop);
|
||||
}
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
package cn.bunny.controller;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
||||
@Controller
|
||||
public class IndexController {
|
||||
|
||||
@GetMapping("/")
|
||||
public String index() {
|
||||
return "index";
|
||||
}
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
package cn.bunny.controller;
|
||||
|
||||
import cn.bunny.core.SqlParserCore;
|
||||
import cn.bunny.dao.entity.ColumnMetaData;
|
||||
import cn.bunny.dao.result.Result;
|
||||
import cn.bunny.dao.vo.TableInfoVo;
|
||||
import cn.bunny.service.SqlParserService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Tag(name = "解析SQL", description = "解析SQL接口")
|
||||
@RestController
|
||||
@RequestMapping("/api/sqlParser")
|
||||
public class SqlParserController {
|
||||
|
||||
@Resource
|
||||
private SqlParserService sqlParserService;
|
||||
|
||||
@Operation(summary = "解析SQL成表信息", description = "解析SQL成表信息")
|
||||
@PostMapping("tableInfo")
|
||||
public Result<TableInfoVo> tableInfo(String sql) {
|
||||
TableInfoVo vo = sqlParserService.tableInfo(sql);
|
||||
return Result.success(vo);
|
||||
}
|
||||
|
||||
@Operation(summary = "解析SQL成列数据", description = "解析SQL成列数据")
|
||||
@PostMapping("columnMetaData")
|
||||
public Result<List<ColumnMetaData>> columnMetaData(String sql) {
|
||||
List<ColumnMetaData> vo = SqlParserCore.parserColumnInfo(sql);
|
||||
return Result.success(vo);
|
||||
}
|
||||
}
|
|
@ -1,81 +0,0 @@
|
|||
package cn.bunny.controller;
|
||||
|
||||
import cn.bunny.dao.entity.ColumnMetaData;
|
||||
import cn.bunny.dao.entity.DatabaseInfoMetaData;
|
||||
import cn.bunny.dao.result.Result;
|
||||
import cn.bunny.dao.vo.TableInfoVo;
|
||||
import cn.bunny.service.TableService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Tag(name = "数据库表控制器", description = "数据库表信息接口")
|
||||
@RestController
|
||||
@RequestMapping("/api/table")
|
||||
public class TableController {
|
||||
|
||||
@Value("${bunny.master.database}")
|
||||
private String currentDatabase;
|
||||
|
||||
@Resource
|
||||
private TableService tableService;
|
||||
|
||||
@Operation(summary = "当前数据库信息", description = "当前连接的数据库信息")
|
||||
@GetMapping("databaseInfoMetaData")
|
||||
public Result<DatabaseInfoMetaData> databaseInfoMetaData() {
|
||||
DatabaseInfoMetaData databaseInfoMetaData = tableService.databaseInfoMetaData();
|
||||
return Result.success(databaseInfoMetaData);
|
||||
}
|
||||
|
||||
@Operation(summary = "当前配置的数据库", description = "当前配置的数据库")
|
||||
@GetMapping("currentDatabaseName")
|
||||
public Result<String> getCurrentDatabaseName() {
|
||||
return Result.success(currentDatabase);
|
||||
}
|
||||
|
||||
@Operation(summary = "数据库所有的表", description = "获取[当前/所有]数据库表")
|
||||
@GetMapping("databaseTableList")
|
||||
public Result<List<TableInfoVo>> databaseTableList(String dbName) {
|
||||
List<TableInfoVo> list = tableService.databaseTableList(dbName);
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
@Operation(summary = "所有的数据库名称", description = "当前数据库所有的数据库名称")
|
||||
@GetMapping("databaseList")
|
||||
public Result<List<TableInfoVo>> databaseList() {
|
||||
List<TableInfoVo> allDb = tableService.databaseTableList(null);
|
||||
|
||||
// 将当前数据库表分组,以数据库名称为key
|
||||
List<TableInfoVo> list = allDb.stream()
|
||||
.collect(Collectors.groupingBy(TableInfoVo::getTableCat))
|
||||
.values().stream()
|
||||
.map(tableInfoVos -> {
|
||||
TableInfoVo tableInfoVo = tableInfoVos.get(0);
|
||||
tableInfoVo.setTableName(null);
|
||||
return tableInfoVo;
|
||||
}).toList();
|
||||
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
@Operation(summary = "表属性", description = "获取当前查询表属性")
|
||||
@GetMapping("tableMetaData")
|
||||
public Result<TableInfoVo> tableMetaData(String tableName) {
|
||||
TableInfoVo tableMetaData = tableService.tableMetaData(tableName);
|
||||
return Result.success(tableMetaData);
|
||||
}
|
||||
|
||||
@Operation(summary = "表的列属性", description = "获取当前查询表中列属性")
|
||||
@GetMapping("tableColumnInfo")
|
||||
public Result<List<ColumnMetaData>> tableColumnInfo(String tableName) {
|
||||
List<ColumnMetaData> columnInfo = tableService.tableColumnInfo(tableName);
|
||||
return Result.success(columnInfo);
|
||||
}
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
package cn.bunny.controller;
|
||||
|
||||
import cn.bunny.dao.dto.VmsArgumentDto;
|
||||
import cn.bunny.dao.result.Result;
|
||||
import cn.bunny.dao.vo.GeneratorVo;
|
||||
import cn.bunny.dao.vo.VmsPathVo;
|
||||
import cn.bunny.service.VmsService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Tag(name = "生成器", description = "代码生成器接口")
|
||||
@RestController
|
||||
@RequestMapping("/api/vms")
|
||||
public class VmsController {
|
||||
|
||||
@Resource
|
||||
private VmsService vmsService;
|
||||
|
||||
@Operation(summary = "获取vms文件路径", description = "获取所有vms下的文件路径")
|
||||
@GetMapping("vmsResourcePathList")
|
||||
public Result<Map<String, List<VmsPathVo>>> vmsResourcePathList() {
|
||||
Map<String, List<VmsPathVo>> list = vmsService.vmsResourcePathList();
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
@Operation(summary = "生成代码", description = "生成代码")
|
||||
@PostMapping("generator")
|
||||
public Result<List<GeneratorVo>> generator(@Valid @RequestBody VmsArgumentDto dto) {
|
||||
List<GeneratorVo> list = vmsService.generator(dto);
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
@Operation(summary = "打包成zip下载", description = "打包成zip下载")
|
||||
@PostMapping("downloadByZip")
|
||||
public ResponseEntity<byte[]> downloadByZip(@Valid @RequestBody VmsArgumentDto dto) {
|
||||
return vmsService.downloadByZip(dto);
|
||||
}
|
||||
}
|
|
@ -1,196 +0,0 @@
|
|||
package cn.bunny.core;
|
||||
|
||||
import cn.bunny.dao.entity.ColumnMetaData;
|
||||
import cn.bunny.dao.entity.DatabaseInfoMetaData;
|
||||
import cn.bunny.dao.entity.TableMetaData;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.SneakyThrows;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/* 数据库信息内容 */
|
||||
@Component
|
||||
public class DatabaseInfoCore {
|
||||
|
||||
@Resource
|
||||
private DataSource dataSource;
|
||||
|
||||
/**
|
||||
* 获取表的所有主键列名
|
||||
*
|
||||
* @param tableName 表名
|
||||
* @return 主键列名的集合
|
||||
*/
|
||||
@SneakyThrows
|
||||
public Set<String> getPrimaryKeyColumns(String tableName) {
|
||||
// 主键的key
|
||||
Set<String> primaryKeys = new HashSet<>();
|
||||
|
||||
try (Connection connection = dataSource.getConnection()) {
|
||||
DatabaseMetaData metaData = connection.getMetaData();
|
||||
|
||||
// 当前表的主键
|
||||
ResultSet pkResultSet = metaData.getPrimaryKeys(null, null, tableName);
|
||||
|
||||
while (pkResultSet.next()) {
|
||||
// 列字段
|
||||
String columnName = pkResultSet.getString("COLUMN_NAME").toLowerCase();
|
||||
primaryKeys.add(columnName);
|
||||
}
|
||||
|
||||
return primaryKeys;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取表注释信息
|
||||
*
|
||||
* @param tableName 数据库表名
|
||||
* @return 表信息
|
||||
*/
|
||||
@SneakyThrows
|
||||
public TableMetaData tableInfoMetaData(String tableName) {
|
||||
TableMetaData tableMetaData;
|
||||
|
||||
try (Connection connection = dataSource.getConnection()) {
|
||||
DatabaseMetaData metaData = connection.getMetaData();
|
||||
ResultSet tables = metaData.getTables(null, null, tableName, new String[]{"TABLE"});
|
||||
|
||||
// 获取表的注释信息
|
||||
if (tables.next()) {
|
||||
// 备注信息
|
||||
String remarks = tables.getString("REMARKS");
|
||||
|
||||
// 数组名称
|
||||
String tableCat = tables.getString("TABLE_CAT");
|
||||
|
||||
// 通常是"TABLE"
|
||||
String tableType = tables.getString("TABLE_TYPE");
|
||||
|
||||
tableMetaData = TableMetaData.builder()
|
||||
.tableName(tableName)
|
||||
.comment(remarks)
|
||||
.tableCat(tableCat)
|
||||
.tableType(tableType)
|
||||
.build();
|
||||
} else {
|
||||
throw new RuntimeException("数据表不存在");
|
||||
}
|
||||
|
||||
return tableMetaData;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取[当前/所有]数据库表
|
||||
*
|
||||
* @return 所有表信息
|
||||
*/
|
||||
@SneakyThrows
|
||||
public List<TableMetaData> databaseTableList(String dbName) {
|
||||
// 当前数据库数据库所有的表
|
||||
List<TableMetaData> allTableInfo = new ArrayList<>();
|
||||
|
||||
try (Connection connection = dataSource.getConnection()) {
|
||||
DatabaseMetaData metaData = connection.getMetaData();
|
||||
|
||||
// 当前数据库中所有的表
|
||||
ResultSet tables = metaData.getTables(dbName, null, "%", new String[]{"TABLE"});
|
||||
|
||||
while (tables.next()) {
|
||||
// 表名称
|
||||
dbName = tables.getString("TABLE_NAME");
|
||||
|
||||
// 设置表信息
|
||||
TableMetaData tableMetaData = tableInfoMetaData(dbName);
|
||||
|
||||
allTableInfo.add(tableMetaData);
|
||||
}
|
||||
}
|
||||
|
||||
return allTableInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前表的列属性
|
||||
*
|
||||
* @param tableName 表名称
|
||||
* @return 当前表所有的列内容
|
||||
*/
|
||||
@SneakyThrows
|
||||
public List<ColumnMetaData> tableColumnInfo(String tableName) {
|
||||
try (Connection connection = dataSource.getConnection()) {
|
||||
DatabaseMetaData metaData = connection.getMetaData();
|
||||
List<ColumnMetaData> columns = new ArrayList<>();
|
||||
// 当前表的主键
|
||||
Set<String> primaryKeyColumns = getPrimaryKeyColumns(tableName);
|
||||
|
||||
// 当前表的列信息
|
||||
try (ResultSet columnsRs = metaData.getColumns(null, null, tableName, null)) {
|
||||
while (columnsRs.next()) {
|
||||
ColumnMetaData column = new ColumnMetaData();
|
||||
// 列字段
|
||||
String columnName = columnsRs.getString("COLUMN_NAME");
|
||||
// 将当前表的列类型转成 Java 类型
|
||||
String javaType = TypeConvertCore.convertToJavaType(column.getJdbcType());
|
||||
|
||||
// 设置列字段
|
||||
column.setColumnName(columnName);
|
||||
// 列字段转成 下划线 -> 小驼峰
|
||||
column.setLowercaseName(TypeConvertCore.convertToCamelCase(column.getColumnName()));
|
||||
// 列字段转成 下划线 -> 大驼峰名称
|
||||
column.setUppercaseName(TypeConvertCore.convertToCamelCase(column.getColumnName(), true));
|
||||
// 字段类型
|
||||
column.setJdbcType(columnsRs.getString("TYPE_NAME"));
|
||||
// 字段类型转 Java 类型
|
||||
column.setJavaType(javaType);
|
||||
// 字段类型转 JavaScript 类型
|
||||
column.setJavascriptType(StringUtils.uncapitalize(javaType));
|
||||
// 备注信息
|
||||
column.setComment(columnsRs.getString("REMARKS"));
|
||||
|
||||
// 确保 primaryKeyColumns 不为空
|
||||
if (!primaryKeyColumns.isEmpty()) {
|
||||
// 是否是主键
|
||||
boolean isPrimaryKey = primaryKeyColumns.contains(columnName);
|
||||
column.setIsPrimaryKey(isPrimaryKey);
|
||||
}
|
||||
columns.add(column);
|
||||
}
|
||||
}
|
||||
|
||||
columns.get(0).setIsPrimaryKey(true);
|
||||
return columns;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据库所有的信息
|
||||
*
|
||||
* @return 当前连接的数据库信息属性
|
||||
*/
|
||||
@SneakyThrows
|
||||
public DatabaseInfoMetaData databaseInfoMetaData() {
|
||||
try (Connection connection = dataSource.getConnection()) {
|
||||
DatabaseMetaData metaData = connection.getMetaData();
|
||||
|
||||
return DatabaseInfoMetaData.builder()
|
||||
.databaseProductName(metaData.getDatabaseProductName())
|
||||
.databaseProductVersion(metaData.getDatabaseProductVersion())
|
||||
.driverName(metaData.getDriverName())
|
||||
.driverVersion(metaData.getDriverVersion())
|
||||
.url(metaData.getURL())
|
||||
.username(metaData.getUserName())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,134 +0,0 @@
|
|||
package cn.bunny.core;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/* 当前生产/开发下的资源文件 */
|
||||
public class ResourceFileCore {
|
||||
|
||||
/**
|
||||
* 获取目标文件夹下所有文件完整路径
|
||||
*
|
||||
* @param dirname 文件夹名称
|
||||
* @return 目标文件完整路径
|
||||
* @throws IOException IOException
|
||||
*/
|
||||
public static List<String> getAbsoluteFiles(String dirname) throws IOException {
|
||||
List<String> fileNames = new ArrayList<>();
|
||||
|
||||
// 加载当前类
|
||||
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
||||
Enumeration<URL> urls = classLoader.getResources(dirname);
|
||||
|
||||
while (urls.hasMoreElements()) {
|
||||
URL url = urls.nextElement();
|
||||
if (url.getProtocol().equals("file")) {
|
||||
// 文件系统
|
||||
File file = new File(url.getFile());
|
||||
if (file.isDirectory()) {
|
||||
addFullFilesFromDirectory(file, fileNames);
|
||||
}
|
||||
} else if (url.getProtocol().equals("jar")) {
|
||||
// JAR文件
|
||||
String jarPath = url.getPath().substring(5, url.getPath().indexOf("!"));
|
||||
try (JarFile jar = new JarFile(jarPath)) {
|
||||
Enumeration<JarEntry> entries = jar.entries();
|
||||
while (entries.hasMoreElements()) {
|
||||
String name = entries.nextElement().getName();
|
||||
if (name.startsWith(dirname + "/") && !name.endsWith("/")) {
|
||||
fileNames.add(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return fileNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加文件
|
||||
* 获取目标文件夹下所有文件完整路径
|
||||
*
|
||||
* @param directory 文件夹
|
||||
* @param fileNames 文件名称
|
||||
*/
|
||||
private static void addFullFilesFromDirectory(File directory, List<String> fileNames) {
|
||||
File[] files = directory.listFiles();
|
||||
if (files != null) {
|
||||
for (File file : files) {
|
||||
if (file.isFile()) {
|
||||
fileNames.add(file.getPath());
|
||||
} else if (file.isDirectory()) {
|
||||
addFullFilesFromDirectory(file, fileNames);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取相对文件夹路径
|
||||
*
|
||||
* @return 相对当前的文件夹路径
|
||||
* @throws IOException IOException
|
||||
* @throws URISyntaxException URISyntaxException
|
||||
*/
|
||||
public static List<String> getRelativeFiles(String dirname) throws IOException, URISyntaxException {
|
||||
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
||||
URL resource = classLoader.getResource(dirname);
|
||||
|
||||
if (resource == null) return Collections.emptyList();
|
||||
|
||||
// 处理JAR包内的情况
|
||||
if (resource.getProtocol().equals("jar")) {
|
||||
return getFilesFromJar(resource, dirname);
|
||||
} else {
|
||||
// 处理文件系统情况
|
||||
return getFilesFromFileSystem(resource);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<String> getFilesFromJar(URL jarUrl, String dirname) throws IOException {
|
||||
List<String> fileNames = new ArrayList<>();
|
||||
String jarPath = jarUrl.getPath().substring(5, jarUrl.getPath().indexOf("!"));
|
||||
|
||||
try (JarFile jar = new JarFile(jarPath)) {
|
||||
jar.entries().asIterator()
|
||||
.forEachRemaining(entry -> {
|
||||
String name = entry.getName();
|
||||
String prefix = dirname + "/";
|
||||
|
||||
if (name.startsWith(prefix) && !name.endsWith("/")) {
|
||||
fileNames.add(name.substring(prefix.length()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return fileNames;
|
||||
}
|
||||
|
||||
private static List<String> getFilesFromFileSystem(URL resource) throws IOException, URISyntaxException {
|
||||
Path filepath = Paths.get(resource.toURI());
|
||||
|
||||
try (Stream<Path> paths = Files.walk(filepath)) {
|
||||
return paths.filter(Files::isRegularFile)
|
||||
.map(filepath::relativize)
|
||||
.map(Path::toString)
|
||||
// 统一使用/作为分隔符
|
||||
.map(s -> s.replace('\\', '/'))
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,110 +0,0 @@
|
|||
package cn.bunny.core;
|
||||
|
||||
import cn.bunny.dao.entity.ColumnMetaData;
|
||||
import cn.bunny.dao.entity.TableMetaData;
|
||||
import lombok.SneakyThrows;
|
||||
import net.sf.jsqlparser.JSQLParserException;
|
||||
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
|
||||
import net.sf.jsqlparser.statement.Statement;
|
||||
import net.sf.jsqlparser.statement.create.table.CreateTable;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class SqlParserCore {
|
||||
|
||||
/**
|
||||
* 解析 sql 表信息
|
||||
*
|
||||
* @param sql sql字符串
|
||||
* @return 表西悉尼
|
||||
*/
|
||||
@SneakyThrows
|
||||
public static TableMetaData parserTableInfo(String sql) {
|
||||
TableMetaData tableInfo = new TableMetaData();
|
||||
|
||||
// 解析sql
|
||||
Statement statement;
|
||||
try {
|
||||
statement = CCJSqlParserUtil.parse(sql);
|
||||
} catch (JSQLParserException e) {
|
||||
throw new RuntimeException("SQL解析失败");
|
||||
}
|
||||
if (!(statement instanceof CreateTable createTable)) {
|
||||
throw new IllegalArgumentException("缺少SQL语句");
|
||||
}
|
||||
|
||||
// 设置表基本信息
|
||||
String tableName = createTable.getTable().getName().replaceAll("`", "");
|
||||
tableInfo.setTableName(tableName);
|
||||
tableInfo.setTableType("TABLE");
|
||||
String tableOptionsStrings = String.join(" ", createTable.getTableOptionsStrings());
|
||||
|
||||
// 注释信息
|
||||
Pattern pattern = Pattern.compile("COMMENT\\s*=\\s*'(.*?)'", Pattern.CASE_INSENSITIVE);
|
||||
Matcher matcher = pattern.matcher(tableOptionsStrings);
|
||||
if (matcher.find()) {
|
||||
tableInfo.setComment(matcher.group(1));
|
||||
}
|
||||
|
||||
return tableInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析 sql 列信息
|
||||
*
|
||||
* @param sql sql字符串
|
||||
* @return 列属性列表
|
||||
*/
|
||||
@SneakyThrows
|
||||
public static List<ColumnMetaData> parserColumnInfo(String sql) {
|
||||
// 解析sql
|
||||
Statement statement;
|
||||
try {
|
||||
statement = CCJSqlParserUtil.parse(sql);
|
||||
} catch (JSQLParserException e) {
|
||||
throw new RuntimeException("SQL解析失败");
|
||||
}
|
||||
|
||||
if (!(statement instanceof CreateTable createTable)) {
|
||||
throw new IllegalArgumentException("缺少SQL语句");
|
||||
}
|
||||
|
||||
return createTable.getColumnDefinitions()
|
||||
.stream().map(column -> {
|
||||
// 列信息
|
||||
ColumnMetaData columnInfo = new ColumnMetaData();
|
||||
|
||||
// 列名称
|
||||
columnInfo.setColumnName(column.getColumnName());
|
||||
|
||||
// 设置 JDBC 类型
|
||||
String dataType = column.getColDataType().getDataType();
|
||||
columnInfo.setJdbcType(dataType);
|
||||
|
||||
// 设置 Java 类型
|
||||
String javaType = TypeConvertCore.convertToJavaType(dataType.contains("varchar") ? "varchar" : dataType);
|
||||
columnInfo.setJavaType(javaType);
|
||||
|
||||
// 设置 JavaScript 类型
|
||||
columnInfo.setJavascriptType(StringUtils.uncapitalize(javaType));
|
||||
|
||||
// 列字段转成 下划线 -> 小驼峰
|
||||
columnInfo.setLowercaseName(TypeConvertCore.convertToCamelCase(column.getColumnName()));
|
||||
// 列字段转成 下划线 -> 大驼峰名称
|
||||
columnInfo.setUppercaseName(TypeConvertCore.convertToCamelCase(column.getColumnName(), true));
|
||||
|
||||
// 解析注释
|
||||
List<String> columnSpecs = column.getColumnSpecs();
|
||||
String columnSpecsString = String.join(" ", columnSpecs);
|
||||
Matcher columnSpecsStringMatcher = Pattern.compile("COMMENT\\s*'(.*?)'", Pattern.CASE_INSENSITIVE).matcher(columnSpecsString);
|
||||
if (columnSpecsStringMatcher.find()) {
|
||||
columnInfo.setComment(columnSpecsStringMatcher.group(1));
|
||||
}
|
||||
|
||||
return columnInfo;
|
||||
}).toList();
|
||||
}
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
package cn.bunny.core;
|
||||
|
||||
import com.google.common.base.CaseFormat;
|
||||
import org.assertj.core.util.introspection.CaseFormatUtils;
|
||||
|
||||
/* 类型转换,数据库转Java类型等 */
|
||||
public class TypeConvertCore {
|
||||
|
||||
/**
|
||||
* 将数据库类型转换为Java类型
|
||||
*/
|
||||
public static String convertToJavaType(String columnType) {
|
||||
if (columnType == null) return "Object";
|
||||
|
||||
columnType = columnType.toLowerCase();
|
||||
return switch (columnType) {
|
||||
case "varchar" , "char" , "text" , "longtext" , "mediumtext" , "tinytext" -> "String";
|
||||
case "int" , "integer" , "tinyint" , "smallint" -> "Integer";
|
||||
case "bigint" -> "Long";
|
||||
case "decimal" , "numeric" -> "BigDecimal";
|
||||
case "float" -> "Float";
|
||||
case "double" -> "Double";
|
||||
case "boolean" , "bit" , "tinyint unsigned" -> "Boolean";
|
||||
case "date" , "year" -> "Date";
|
||||
case "time" -> "Time";
|
||||
case "datetime" , "timestamp" -> "LocalDateTime";
|
||||
case "blob" , "longblob" , "mediumblob" , "tinyblob" -> "byte[]";
|
||||
default -> "Object";
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 下划线命名转驼峰命名
|
||||
*/
|
||||
public static String convertToCamelCase(String name) {
|
||||
return convertToCamelCase(name, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 下划线命名转驼峰命名
|
||||
*
|
||||
* @param name 原始名称,传入的值可以是
|
||||
* `xxx_xxx` `CaseFormat`
|
||||
* `caseFormat`
|
||||
* @param firstLetterCapital 首字母是否大写
|
||||
*/
|
||||
public static String convertToCamelCase(String name, boolean firstLetterCapital) {
|
||||
if (name == null || name.isEmpty()) return name;
|
||||
|
||||
// 转成小驼峰
|
||||
String lowerCamelCase = CaseFormatUtils.toCamelCase(name);
|
||||
|
||||
// 首字母不大写
|
||||
if (!firstLetterCapital) {
|
||||
return lowerCamelCase;
|
||||
}
|
||||
|
||||
// 将小驼峰转成大驼峰
|
||||
return CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, lowerCamelCase);
|
||||
}
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
package cn.bunny.core.vms;
|
||||
|
||||
import cn.bunny.dao.entity.ColumnMetaData;
|
||||
import cn.bunny.dao.entity.TableMetaData;
|
||||
import org.apache.velocity.VelocityContext;
|
||||
|
||||
import java.io.StringWriter;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 模板方法模式
|
||||
* 如果需要继承 AbstractVmsGenerator
|
||||
*/
|
||||
public abstract class AbstractVmsGenerator {
|
||||
|
||||
/**
|
||||
* 添加生成内容
|
||||
*/
|
||||
abstract void addContext(VelocityContext context);
|
||||
|
||||
/**
|
||||
* Velocity 生成模板
|
||||
*
|
||||
* @param context VelocityContext
|
||||
* @param writer StringWriter 写入
|
||||
*/
|
||||
abstract void templateMerge(VelocityContext context, StringWriter writer);
|
||||
|
||||
/**
|
||||
* 生成模板
|
||||
*
|
||||
* @param tableMetaData 表属性
|
||||
* @param columnInfoList 列属性数组
|
||||
* @return StringWriter
|
||||
*/
|
||||
public final StringWriter generatorCodeTemplate(TableMetaData tableMetaData, List<ColumnMetaData> columnInfoList) {
|
||||
VelocityContext context = new VelocityContext();
|
||||
|
||||
// 添加要生成的属性
|
||||
StringWriter writer = new StringWriter();
|
||||
List<String> list = columnInfoList.stream().map(ColumnMetaData::getColumnName).toList();
|
||||
|
||||
// vm 不能直接写 `{` 需要转换下
|
||||
context.put("leftBrace", "{");
|
||||
|
||||
// 当前的表名
|
||||
context.put("tableName", tableMetaData.getTableName());
|
||||
|
||||
// 当前表的列信息
|
||||
context.put("columnInfoList", columnInfoList);
|
||||
|
||||
// 数据库sql列
|
||||
context.put("baseColumnList", String.join(",", list));
|
||||
|
||||
// 添加需要生成的内容
|
||||
addContext(context);
|
||||
|
||||
templateMerge(context, writer);
|
||||
|
||||
return writer;
|
||||
}
|
||||
}
|
|
@ -1,85 +0,0 @@
|
|||
package cn.bunny.core.vms;
|
||||
|
||||
import cn.bunny.core.TypeConvertCore;
|
||||
import cn.bunny.dao.dto.VmsArgumentDto;
|
||||
import org.apache.velocity.Template;
|
||||
import org.apache.velocity.VelocityContext;
|
||||
import org.apache.velocity.app.Velocity;
|
||||
|
||||
import java.io.StringWriter;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 使用模板方法,方便扩展
|
||||
* 如果需要继承 AbstractVmsGenerator
|
||||
*/
|
||||
public class VmsArgumentDtoBaseVmsGenerator extends AbstractVmsGenerator {
|
||||
|
||||
private final VmsArgumentDto dto;
|
||||
private final String path;
|
||||
|
||||
/**
|
||||
* @param dto 类名称可以自定义,格式为 xxx_xxx
|
||||
* @param path 当前路径
|
||||
*/
|
||||
public VmsArgumentDtoBaseVmsGenerator(VmsArgumentDto dto, String path) {
|
||||
this.dto = dto;
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加生成内容
|
||||
*
|
||||
* @param context VelocityContext
|
||||
*/
|
||||
@Override
|
||||
void addContext(VelocityContext context) {
|
||||
// 当前日期
|
||||
String date = new SimpleDateFormat(dto.getSimpleDateFormat()).format(new Date());
|
||||
context.put("date", date);
|
||||
|
||||
// 作者名字
|
||||
context.put("author", dto.getAuthor());
|
||||
|
||||
// 每个 Controller 上的请求前缀
|
||||
context.put("requestMapping", dto.getRequestMapping());
|
||||
|
||||
// 表字段的注释内容
|
||||
context.put("comment", dto.getComment());
|
||||
|
||||
// 设置包名称
|
||||
context.put("package", dto.getPackageName());
|
||||
|
||||
// 类名称如果是小驼峰,需要 [手写] 为 [下划线] 之后由 [代码 -> 小驼峰/大驼峰]
|
||||
String className = dto.getClassName();
|
||||
// 去除表开头前缀
|
||||
String tablePrefixes = dto.getTablePrefixes();
|
||||
// 将 表前缀 转成数组
|
||||
String replaceTableName = "";
|
||||
for (String prefix : tablePrefixes.split("[,,]")) {
|
||||
replaceTableName = className.replace(prefix, "");
|
||||
}
|
||||
|
||||
// 将类名称转成小驼峰
|
||||
String toCamelCase = TypeConvertCore.convertToCamelCase(replaceTableName);
|
||||
context.put("classLowercaseName", toCamelCase);
|
||||
|
||||
// 将类名称转成大驼峰
|
||||
String convertToCamelCase = TypeConvertCore.convertToCamelCase(replaceTableName, true);
|
||||
context.put("classUppercaseName", convertToCamelCase);
|
||||
}
|
||||
|
||||
/**
|
||||
* Velocity 生成模板
|
||||
*
|
||||
* @param context VelocityContext
|
||||
* @param writer StringWriter 写入
|
||||
*/
|
||||
@Override
|
||||
void templateMerge(VelocityContext context, StringWriter writer) {
|
||||
// Velocity 生成模板
|
||||
Template servicePathTemplate = Velocity.getTemplate("vms/" + path, "UTF-8");
|
||||
servicePathTemplate.merge(context, writer);
|
||||
}
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
package cn.bunny.dao.dto;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class VmsArgumentDto {
|
||||
|
||||
/* 作者名称 */
|
||||
String author = "Bunny";
|
||||
|
||||
/* 包名称 */
|
||||
String packageName = "cn.bunny.services";
|
||||
|
||||
/* requestMapping 名称 */
|
||||
String requestMapping = "/api";
|
||||
|
||||
/* 类名称,格式为:xxx xxx_xxx */
|
||||
@NotBlank(message = "类名称不能为空")
|
||||
@NotNull(message = "类名称不能为空")
|
||||
@Pattern(regexp = "^(?:[a-z][a-z0-9_]*|[_a-z][a-z0-9_]*)$", message = "类名称不合法")
|
||||
private String className;
|
||||
|
||||
/* 表名称 */
|
||||
@NotBlank(message = "表名称不能为空")
|
||||
@NotNull(message = "表名称不能为空")
|
||||
@Pattern(regexp = "^(?:[a-z][a-z0-9_]*|[_a-z][a-z0-9_]*)$", message = "表名称不合法")
|
||||
private String tableName;
|
||||
|
||||
/* 时间格式 */
|
||||
private String simpleDateFormat = "yyyy-MM-dd HH:mm:ss";
|
||||
|
||||
/* 去除表前缀 */
|
||||
private String tablePrefixes = "t_,sys_,qrtz_,log_";
|
||||
|
||||
/* 注释内容 */
|
||||
private String comment;
|
||||
|
||||
/* 路径 */
|
||||
private List<String> path;
|
||||
|
||||
/* SQL 语句 */
|
||||
private String sql;
|
||||
}
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
package cn.bunny.dao.entity;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ColumnMetaData {
|
||||
|
||||
/* 列名称 */
|
||||
private String columnName;
|
||||
|
||||
/* 字段名称,小驼峰名称 */
|
||||
private String lowercaseName;
|
||||
|
||||
/* 大驼峰名称 */
|
||||
private String uppercaseName;
|
||||
|
||||
/* 数据库字段类型 */
|
||||
private String jdbcType;
|
||||
|
||||
/* Java类型 */
|
||||
private String javaType;
|
||||
|
||||
/* Javascript类型 */
|
||||
private String javascriptType;
|
||||
|
||||
/* 是否为主键 */
|
||||
private Boolean isPrimaryKey;
|
||||
|
||||
/* 字段注释 */
|
||||
private String comment;
|
||||
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
package cn.bunny.dao.entity;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class DatabaseInfoMetaData {
|
||||
|
||||
/* 数据库产品名称 */
|
||||
private String databaseProductName;
|
||||
|
||||
/* 数据库产品版本 */
|
||||
private String databaseProductVersion;
|
||||
|
||||
/* 驱动名称 */
|
||||
private String driverName;
|
||||
|
||||
/* 数据库驱动版本 */
|
||||
private String driverVersion;
|
||||
|
||||
/* 数据链接url */
|
||||
private String url;
|
||||
|
||||
/* 数据库用户 */
|
||||
private String username;
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
package cn.bunny.dao.entity;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class TableMetaData {
|
||||
|
||||
/* 表名 */
|
||||
private String tableName;
|
||||
|
||||
/* 注释内容 */
|
||||
private String comment;
|
||||
|
||||
/* 表目录 */
|
||||
private String tableCat;
|
||||
|
||||
/* 表类型(通常是"TABLE") */
|
||||
private String tableType;
|
||||
|
||||
/* 类名 */
|
||||
private String className;
|
||||
|
||||
/* 列名称 */
|
||||
private List<ColumnMetaData> columns;
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
package cn.bunny.dao.result;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 封装分页查询结果
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
@Schema(name = "PageResult 对象" , title = "分页返回结果" , description = "分页返回结果" )
|
||||
public class PageResult<T> implements Serializable {
|
||||
|
||||
@Schema(name = "pageNo" , title = "当前页" )
|
||||
private Long pageNo;
|
||||
|
||||
@Schema(name = "pageSize" , title = "每页记录数" )
|
||||
private Long pageSize;
|
||||
|
||||
@Schema(name = "total" , title = "总记录数" )
|
||||
private Long total;
|
||||
|
||||
@Schema(name = "list" , title = "当前页数据集合" )
|
||||
private List<T> list;
|
||||
|
||||
}
|
|
@ -1,173 +0,0 @@
|
|||
package cn.bunny.dao.result;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class Result<T> {
|
||||
// 状态码
|
||||
private Integer code;
|
||||
// 返回消息
|
||||
private String message;
|
||||
// 返回数据
|
||||
private T data;
|
||||
|
||||
/**
|
||||
* * 自定义返回体
|
||||
*
|
||||
* @param data 返回体
|
||||
* @return Result<T>
|
||||
*/
|
||||
protected static <T> Result<T> build(T data) {
|
||||
Result<T> result = new Result<>();
|
||||
result.setData(data);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* * 自定义返回体,使用ResultCodeEnum构建
|
||||
*
|
||||
* @param body 返回体
|
||||
* @param codeEnum 返回状态码
|
||||
* @return Result<T>
|
||||
*/
|
||||
public static <T> Result<T> build(T body, ResultCodeEnum codeEnum) {
|
||||
Result<T> result = build(body);
|
||||
result.setCode(codeEnum.getCode());
|
||||
result.setMessage(codeEnum.getMessage());
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* * 自定义返回体
|
||||
*
|
||||
* @param body 返回体
|
||||
* @param code 返回状态码
|
||||
* @param message 返回消息
|
||||
* @return Result<T>
|
||||
*/
|
||||
public static <T> Result<T> build(T body, Integer code, String message) {
|
||||
Result<T> result = build(body);
|
||||
result.setCode(code);
|
||||
result.setMessage(message);
|
||||
result.setData(null);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* * 操作成功
|
||||
*
|
||||
* @return Result<T>
|
||||
*/
|
||||
public static <T> Result<T> success() {
|
||||
return success(null, ResultCodeEnum.SUCCESS);
|
||||
}
|
||||
|
||||
/**
|
||||
* * 操作成功
|
||||
*
|
||||
* @param data baseCategory1List
|
||||
*/
|
||||
public static <T> Result<T> success(T data) {
|
||||
return build(data, ResultCodeEnum.SUCCESS);
|
||||
}
|
||||
|
||||
/**
|
||||
* * 操作成功-状态码
|
||||
*
|
||||
* @param codeEnum 状态码
|
||||
*/
|
||||
public static <T> Result<T> success(ResultCodeEnum codeEnum) {
|
||||
return success(null, codeEnum);
|
||||
}
|
||||
|
||||
/**
|
||||
* * 操作成功-自定义返回数据和状态码
|
||||
*
|
||||
* @param data 返回体
|
||||
* @param codeEnum 状态码
|
||||
*/
|
||||
public static <T> Result<T> success(T data, ResultCodeEnum codeEnum) {
|
||||
return build(data, codeEnum);
|
||||
}
|
||||
|
||||
/**
|
||||
* * 操作失败-自定义返回数据和状态码
|
||||
*
|
||||
* @param data 返回体
|
||||
* @param message 错误信息
|
||||
*/
|
||||
public static <T> Result<T> success(T data, String message) {
|
||||
return build(data, 200, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* * 操作失败-自定义返回数据和状态码
|
||||
*
|
||||
* @param data 返回体
|
||||
* @param code 状态码
|
||||
* @param message 错误信息
|
||||
*/
|
||||
public static <T> Result<T> success(T data, Integer code, String message) {
|
||||
return build(data, code, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* * 操作失败
|
||||
*/
|
||||
public static <T> Result<T> error() {
|
||||
return Result.build(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* * 操作失败-自定义返回数据
|
||||
*
|
||||
* @param data 返回体
|
||||
*/
|
||||
public static <T> Result<T> error(T data) {
|
||||
return build(data, ResultCodeEnum.FAIL);
|
||||
}
|
||||
|
||||
/**
|
||||
* * 操作失败-状态码
|
||||
*
|
||||
* @param codeEnum 状态码
|
||||
*/
|
||||
public static <T> Result<T> error(ResultCodeEnum codeEnum) {
|
||||
return build(null, codeEnum);
|
||||
}
|
||||
|
||||
/**
|
||||
* * 操作失败-自定义返回数据和状态码
|
||||
*
|
||||
* @param data 返回体
|
||||
* @param codeEnum 状态码
|
||||
*/
|
||||
public static <T> Result<T> error(T data, ResultCodeEnum codeEnum) {
|
||||
return build(data, codeEnum);
|
||||
}
|
||||
|
||||
/**
|
||||
* * 操作失败-自定义返回数据和状态码
|
||||
*
|
||||
* @param data 返回体
|
||||
* @param code 状态码
|
||||
* @param message 错误信息
|
||||
*/
|
||||
public static <T> Result<T> error(T data, Integer code, String message) {
|
||||
return build(data, code, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* * 操作失败-自定义返回数据和状态码
|
||||
*
|
||||
* @param data 返回体
|
||||
* @param message 错误信息
|
||||
*/
|
||||
public static <T> Result<T> error(T data, String message) {
|
||||
return build(null, 500, message);
|
||||
}
|
||||
}
|
|
@ -1,90 +0,0 @@
|
|||
package cn.bunny.dao.result;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 统一返回结果状态信息类
|
||||
*/
|
||||
@Getter
|
||||
public enum ResultCodeEnum {
|
||||
// 成功操作 200
|
||||
SUCCESS(200, "操作成功"),
|
||||
ADD_SUCCESS(200, "添加成功"),
|
||||
UPDATE_SUCCESS(200, "修改成功"),
|
||||
DELETE_SUCCESS(200, "删除成功"),
|
||||
SORT_SUCCESS(200, "排序成功"),
|
||||
SUCCESS_UPLOAD(200, "上传成功"),
|
||||
SUCCESS_LOGOUT(200, "退出成功"),
|
||||
LOGOUT_SUCCESS(200, "退出成功"),
|
||||
EMAIL_CODE_REFRESH(200, "邮箱验证码已刷新"),
|
||||
EMAIL_CODE_SEND_SUCCESS(200, "邮箱验证码已发送"),
|
||||
|
||||
// 验证错误 201
|
||||
USERNAME_OR_PASSWORD_NOT_EMPTY(201, "用户名或密码不能为空"),
|
||||
EMAIL_CODE_NOT_EMPTY(201, "邮箱验证码不能为空"),
|
||||
SEND_EMAIL_CODE_NOT_EMPTY(201, "请先发送邮箱验证码"),
|
||||
EMAIL_CODE_NOT_MATCHING(201, "邮箱验证码不匹配"),
|
||||
LOGIN_ERROR(500, "账号或密码错误"),
|
||||
LOGIN_ERROR_USERNAME_PASSWORD_NOT_EMPTY(201, "登录信息不能为空"),
|
||||
GET_BUCKET_EXCEPTION(201, "获取文件信息失败"),
|
||||
SEND_MAIL_CODE_ERROR(201, "邮件发送失败"),
|
||||
EMAIL_CODE_EMPTY(201, "邮箱验证码过期或不存在"),
|
||||
EMAIL_EXIST(201, "邮箱已存在"),
|
||||
REQUEST_IS_EMPTY(201, "请求数据为空"),
|
||||
DATA_TOO_LARGE(201, "请求数据为空"),
|
||||
UPDATE_NEW_PASSWORD_SAME_AS_OLD_PASSWORD(201, "新密码与密码相同"),
|
||||
|
||||
// 数据相关 206
|
||||
ILLEGAL_REQUEST(206, "非法请求"),
|
||||
REPEAT_SUBMIT(206, "重复提交"),
|
||||
DATA_ERROR(206, "数据异常"),
|
||||
EMAIL_USER_TEMPLATE_IS_EMPTY(206, "邮件模板为空"),
|
||||
EMAIL_TEMPLATE_IS_EMPTY(206, "邮件模板为空"),
|
||||
EMAIL_USER_IS_EMPTY(206, "关联邮件用户配置为空"),
|
||||
DATA_EXIST(206, "数据已存在"),
|
||||
DATA_NOT_EXIST(206, "数据不存在"),
|
||||
ALREADY_USER_EXCEPTION(206, "用户已存在"),
|
||||
USER_IS_EMPTY(206, "用户不存在"),
|
||||
FILE_NOT_EXIST(206, "文件不存在"),
|
||||
NEW_PASSWORD_SAME_OLD_PASSWORD(206, "新密码不能和旧密码相同"),
|
||||
MISSING_TEMPLATE_FILES(206, "缺少模板文件"),
|
||||
|
||||
// 身份过期 208
|
||||
LOGIN_AUTH(208, "请先登陆"),
|
||||
AUTHENTICATION_EXPIRED(208, "身份验证过期"),
|
||||
SESSION_EXPIRATION(208, "会话过期"),
|
||||
|
||||
// 209
|
||||
THE_SAME_USER_HAS_LOGGED_IN(209, "相同用户已登录"),
|
||||
|
||||
// 提示错误
|
||||
UPDATE_ERROR(216, "修改失败"),
|
||||
URL_ENCODE_ERROR(216, "URL编码失败"),
|
||||
ILLEGAL_CALLBACK_REQUEST_ERROR(217, "非法回调请求"),
|
||||
FETCH_USERINFO_ERROR(219, "获取用户信息失败"),
|
||||
ILLEGAL_DATA_REQUEST(219, "非法数据请求"),
|
||||
CLASS_NOT_FOUND(219, "类名不存在"),
|
||||
ADMIN_ROLE_CAN_NOT_DELETED(219, "无法删除admin角色"),
|
||||
MENU_RANK_NEED_LARGER_THAN_THE_PARENT(219, "设置路由等级需要大于或等于父级的路由等级"),
|
||||
|
||||
// 无权访问 403
|
||||
FAIL_NO_ACCESS_DENIED(403, "无权访问"),
|
||||
FAIL_NO_ACCESS_DENIED_USER_OFFLINE(403, "用户强制下线"),
|
||||
TOKEN_PARSING_FAILED(403, "token解析失败"),
|
||||
FAIL_NO_ACCESS_DENIED_USER_LOCKED(403, "该账户已封禁"),
|
||||
|
||||
// 系统错误 500
|
||||
UNKNOWN_EXCEPTION(500, "服务异常"),
|
||||
SERVICE_ERROR(500, "服务异常"),
|
||||
UPLOAD_ERROR(500, "上传失败"),
|
||||
FAIL(500, "失败"),
|
||||
;
|
||||
|
||||
private final Integer code;
|
||||
private final String message;
|
||||
|
||||
ResultCodeEnum(Integer code, String message) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
package cn.bunny.dao.vo;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class GeneratorVo {
|
||||
|
||||
/* 生成的代码 */
|
||||
private String code;
|
||||
|
||||
/* 表名 */
|
||||
private String tableName;
|
||||
|
||||
/* 注释内容 */
|
||||
private String comment;
|
||||
|
||||
/* 生成类型路径 */
|
||||
private String path;
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
package cn.bunny.dao.vo;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class TableInfoVo {
|
||||
|
||||
/* 表目录 */
|
||||
private String tableCat;
|
||||
|
||||
/* 表名 */
|
||||
private String tableName;
|
||||
|
||||
/* 表类型(通常是"TABLE") */
|
||||
private String tableType;
|
||||
|
||||
/* 注释内容 */
|
||||
private String comment;
|
||||
|
||||
/* 类名 */
|
||||
private String className;
|
||||
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
package cn.bunny.dao.vo;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class VmsPathVo {
|
||||
|
||||
/* 路径名称 */
|
||||
private String name;
|
||||
|
||||
/* 显示的label */
|
||||
private String label;
|
||||
|
||||
/* 文件夹最上级目录名称 */
|
||||
private String type;
|
||||
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
package cn.bunny.exception;
|
||||
|
||||
import cn.bunny.dao.result.ResultCodeEnum;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@NoArgsConstructor
|
||||
@Getter
|
||||
@ToString
|
||||
@Slf4j
|
||||
public class GeneratorCodeException extends RuntimeException {
|
||||
// 状态码
|
||||
Integer code;
|
||||
|
||||
// 描述信息
|
||||
String message = "服务异常";
|
||||
|
||||
// 返回结果状态
|
||||
ResultCodeEnum resultCodeEnum;
|
||||
|
||||
public GeneratorCodeException(Integer code, String message) {
|
||||
super(message);
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public GeneratorCodeException(String message) {
|
||||
super(message);
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public GeneratorCodeException(ResultCodeEnum codeEnum) {
|
||||
super(codeEnum.getMessage());
|
||||
this.code = codeEnum.getCode();
|
||||
this.message = codeEnum.getMessage();
|
||||
this.resultCodeEnum = codeEnum;
|
||||
}
|
||||
}
|
|
@ -1,105 +0,0 @@
|
|||
package cn.bunny.exception;
|
||||
|
||||
|
||||
import cn.bunny.dao.result.Result;
|
||||
import cn.bunny.dao.result.ResultCodeEnum;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.support.DefaultMessageSourceResolvable;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
|
||||
import java.sql.SQLIntegrityConstraintViolationException;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 全局异常拦截器
|
||||
*/
|
||||
@RestControllerAdvice
|
||||
@Slf4j
|
||||
public class GlobalExceptionHandler {
|
||||
// 自定义异常信息
|
||||
@ExceptionHandler(GeneratorCodeException.class)
|
||||
@ResponseBody
|
||||
public Result<Object> exceptionHandler(GeneratorCodeException exception) {
|
||||
Integer code = exception.getCode() != null ? exception.getCode() : 500;
|
||||
return Result.error(null, code, exception.getMessage());
|
||||
}
|
||||
|
||||
// 运行时异常信息
|
||||
@ExceptionHandler(RuntimeException.class)
|
||||
@ResponseBody
|
||||
public Result<Object> exceptionHandler(RuntimeException exception) {
|
||||
String message = exception.getMessage();
|
||||
message = StringUtils.hasText(message) ? message : "服务器异常";
|
||||
exception.printStackTrace();
|
||||
|
||||
// 解析异常
|
||||
String jsonParseError = "JSON parse error (.*)";
|
||||
Matcher jsonParseErrorMatcher = Pattern.compile(jsonParseError).matcher(message);
|
||||
if (jsonParseErrorMatcher.find()) {
|
||||
return Result.error(null, 500, "JSON解析异常 " + jsonParseErrorMatcher.group(1));
|
||||
}
|
||||
|
||||
// 数据过大
|
||||
String dataTooLongError = "Data too long for column (.*?) at row 1";
|
||||
Matcher dataTooLongErrorMatcher = Pattern.compile(dataTooLongError).matcher(message);
|
||||
if (dataTooLongErrorMatcher.find()) {
|
||||
return Result.error(null, 500, dataTooLongErrorMatcher.group(1) + " 字段数据过大");
|
||||
}
|
||||
|
||||
// 主键冲突
|
||||
String primaryKeyError = "Duplicate entry '(.*?)' for key .*";
|
||||
Matcher primaryKeyErrorMatcher = Pattern.compile(primaryKeyError).matcher(message);
|
||||
if (primaryKeyErrorMatcher.find()) {
|
||||
return Result.error(null, 500, "[" + primaryKeyErrorMatcher.group(1) + "]已存在");
|
||||
}
|
||||
|
||||
// corn表达式错误
|
||||
String cronExpression = "CronExpression '(.*?)' is invalid";
|
||||
Matcher cronExpressionMatcher = Pattern.compile(cronExpression).matcher(message);
|
||||
if (cronExpressionMatcher.find()) {
|
||||
return Result.error(null, 500, "表达式 " + cronExpressionMatcher.group(1) + " 不合法");
|
||||
}
|
||||
|
||||
log.error("GlobalExceptionHandler===>运行时异常信息:{}", message);
|
||||
return Result.error(null, 500, message);
|
||||
}
|
||||
|
||||
// 表单验证字段
|
||||
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||
public Result<String> handleValidationExceptions(MethodArgumentNotValidException ex) {
|
||||
String errorMessage = ex.getBindingResult().getFieldErrors().stream()
|
||||
.map(DefaultMessageSourceResolvable::getDefaultMessage)
|
||||
.collect(Collectors.joining(", "));
|
||||
return Result.error(null, 201, errorMessage);
|
||||
}
|
||||
|
||||
// 特定异常处理
|
||||
@ExceptionHandler(ArithmeticException.class)
|
||||
@ResponseBody
|
||||
public Result<Object> error(ArithmeticException exception) {
|
||||
log.error("GlobalExceptionHandler===>特定异常信息:{}", exception.getMessage());
|
||||
|
||||
return Result.error(null, 500, exception.getMessage());
|
||||
}
|
||||
|
||||
// 处理SQL异常
|
||||
@ExceptionHandler(SQLIntegrityConstraintViolationException.class)
|
||||
@ResponseBody
|
||||
public Result<String> exceptionHandler(SQLIntegrityConstraintViolationException exception) {
|
||||
log.error("GlobalExceptionHandler===>处理SQL异常:{}", exception.getMessage());
|
||||
|
||||
String message = exception.getMessage();
|
||||
if (message.contains("Duplicate entry")) {
|
||||
// 错误信息
|
||||
return Result.error(ResultCodeEnum.USER_IS_EMPTY);
|
||||
} else {
|
||||
return Result.error(ResultCodeEnum.UNKNOWN_EXCEPTION);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
package cn.bunny.service;
|
||||
|
||||
import cn.bunny.dao.vo.TableInfoVo;
|
||||
|
||||
public interface SqlParserService {
|
||||
/**
|
||||
* 解析SQL内容
|
||||
*
|
||||
* @param sql Sql语句
|
||||
* @return 表信息内容
|
||||
*/
|
||||
TableInfoVo tableInfo(String sql);
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
package cn.bunny.service;
|
||||
|
||||
import cn.bunny.dao.entity.ColumnMetaData;
|
||||
import cn.bunny.dao.entity.DatabaseInfoMetaData;
|
||||
import cn.bunny.dao.vo.TableInfoVo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface TableService {
|
||||
|
||||
/**
|
||||
* 获取表属性
|
||||
*
|
||||
* @param tableName 表名称
|
||||
* @return 表属性
|
||||
*/
|
||||
TableInfoVo tableMetaData(String tableName);
|
||||
|
||||
/**
|
||||
* 获取所有数据库
|
||||
*
|
||||
* @return 所有表信息
|
||||
*/
|
||||
List<TableInfoVo> databaseTableList(String tableName);
|
||||
|
||||
/**
|
||||
* 获取列属性
|
||||
*
|
||||
* @param tableName 表名称
|
||||
* @return 当前表所有的列内容
|
||||
*/
|
||||
List<ColumnMetaData> tableColumnInfo(String tableName);
|
||||
|
||||
/**
|
||||
* 数据库所有的信息
|
||||
*
|
||||
* @return 当前连接的数据库信息属性
|
||||
*/
|
||||
DatabaseInfoMetaData databaseInfoMetaData();
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
package cn.bunny.service;
|
||||
|
||||
import cn.bunny.dao.dto.VmsArgumentDto;
|
||||
import cn.bunny.dao.vo.GeneratorVo;
|
||||
import cn.bunny.dao.vo.VmsPathVo;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface VmsService {
|
||||
/**
|
||||
* 生成服务端代码
|
||||
*
|
||||
* @param dto VmsArgumentDto
|
||||
* @return 生成内容
|
||||
*/
|
||||
List<GeneratorVo> generator(VmsArgumentDto dto);
|
||||
|
||||
/**
|
||||
* 获取vms文件路径
|
||||
*
|
||||
* @return vms下的文件路径
|
||||
*/
|
||||
Map<String, List<VmsPathVo>> vmsResourcePathList();
|
||||
|
||||
/**
|
||||
* 打包成zip下载
|
||||
*
|
||||
* @param dto VmsArgumentDto
|
||||
* @return zip 文件
|
||||
*/
|
||||
ResponseEntity<byte[]> downloadByZip(@Valid VmsArgumentDto dto);
|
||||
|
||||
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
package cn.bunny.service.impl;
|
||||
|
||||
import cn.bunny.core.SqlParserCore;
|
||||
import cn.bunny.dao.entity.TableMetaData;
|
||||
import cn.bunny.dao.vo.TableInfoVo;
|
||||
import cn.bunny.service.SqlParserService;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class SqlParserServiceImpl implements SqlParserService {
|
||||
|
||||
/**
|
||||
* 解析SQL内容
|
||||
*
|
||||
* @param sql Sql语句
|
||||
* @return 表信息内容
|
||||
*/
|
||||
@Override
|
||||
public TableInfoVo tableInfo(String sql) {
|
||||
TableInfoVo tableInfoVo = new TableInfoVo();
|
||||
|
||||
TableMetaData tableMetaData = SqlParserCore.parserTableInfo(sql);
|
||||
BeanUtils.copyProperties(tableMetaData, tableInfoVo);
|
||||
return tableInfoVo;
|
||||
}
|
||||
}
|
|
@ -1,79 +0,0 @@
|
|||
package cn.bunny.service.impl;
|
||||
|
||||
import cn.bunny.core.DatabaseInfoCore;
|
||||
import cn.bunny.dao.entity.ColumnMetaData;
|
||||
import cn.bunny.dao.entity.DatabaseInfoMetaData;
|
||||
import cn.bunny.dao.entity.TableMetaData;
|
||||
import cn.bunny.dao.vo.TableInfoVo;
|
||||
import cn.bunny.service.TableService;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.SneakyThrows;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class TableServiceImpl implements TableService {
|
||||
|
||||
@Resource
|
||||
private DatabaseInfoCore databaseInfoCore;
|
||||
|
||||
/**
|
||||
* 获取表属性
|
||||
*
|
||||
* @param tableName 表名称
|
||||
* @return 表属性
|
||||
*/
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public TableInfoVo tableMetaData(String tableName) {
|
||||
TableInfoVo tableInfoVo = new TableInfoVo();
|
||||
|
||||
TableMetaData tableMetaData = databaseInfoCore.tableInfoMetaData(tableName);
|
||||
BeanUtils.copyProperties(tableMetaData, tableInfoVo);
|
||||
|
||||
return tableInfoVo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取[当前/所有]数据库表
|
||||
*
|
||||
* @return 所有表信息
|
||||
*/
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public List<TableInfoVo> databaseTableList(String dbName) {
|
||||
List<TableMetaData> allTableInfo = databaseInfoCore.databaseTableList(dbName);
|
||||
|
||||
return allTableInfo.stream().map(tableMetaData -> {
|
||||
TableInfoVo tableInfoVo = new TableInfoVo();
|
||||
BeanUtils.copyProperties(tableMetaData, tableInfoVo);
|
||||
|
||||
return tableInfoVo;
|
||||
}).toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前表的列属性
|
||||
*
|
||||
* @param tableName 表名称
|
||||
* @return 当前表所有的列内容
|
||||
*/
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public List<ColumnMetaData> tableColumnInfo(String tableName) {
|
||||
return databaseInfoCore.tableColumnInfo(tableName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据库所有的信息
|
||||
*
|
||||
* @return 当前连接的数据库信息属性
|
||||
*/
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public DatabaseInfoMetaData databaseInfoMetaData() {
|
||||
return databaseInfoCore.databaseInfoMetaData();
|
||||
}
|
||||
}
|
|
@ -1,153 +0,0 @@
|
|||
package cn.bunny.service.impl;
|
||||
|
||||
import cn.bunny.core.DatabaseInfoCore;
|
||||
import cn.bunny.core.ResourceFileCore;
|
||||
import cn.bunny.core.SqlParserCore;
|
||||
import cn.bunny.core.vms.VmsArgumentDtoBaseVmsGenerator;
|
||||
import cn.bunny.dao.dto.VmsArgumentDto;
|
||||
import cn.bunny.dao.entity.ColumnMetaData;
|
||||
import cn.bunny.dao.entity.TableMetaData;
|
||||
import cn.bunny.dao.vo.GeneratorVo;
|
||||
import cn.bunny.dao.vo.VmsPathVo;
|
||||
import cn.bunny.service.VmsService;
|
||||
import cn.bunny.utils.VmsUtil;
|
||||
import cn.hutool.crypto.digest.MD5;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.SneakyThrows;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
@Service
|
||||
public class VmsServiceImpl implements VmsService {
|
||||
|
||||
@Resource
|
||||
private DatabaseInfoCore databaseInfoCore;
|
||||
|
||||
/**
|
||||
* 生成服务端代码
|
||||
*
|
||||
* @param dto VmsArgumentDto
|
||||
* @return 生成内容
|
||||
*/
|
||||
@Override
|
||||
public List<GeneratorVo> generator(VmsArgumentDto dto) {
|
||||
String tableName = dto.getTableName();
|
||||
String sql = dto.getSql();
|
||||
|
||||
// 表格属性名 和 列信息
|
||||
TableMetaData tableMetaData;
|
||||
List<ColumnMetaData> columnInfoList;
|
||||
|
||||
// 判断是否有 SQL 如果有SQL 优先解析并生成SQL相关内容
|
||||
if (StringUtils.hasText(sql)) {
|
||||
tableMetaData = SqlParserCore.parserTableInfo(sql);
|
||||
columnInfoList = SqlParserCore.parserColumnInfo(sql);
|
||||
} else {
|
||||
tableMetaData = databaseInfoCore.tableInfoMetaData(tableName);
|
||||
columnInfoList = databaseInfoCore.tableColumnInfo(tableName).stream().distinct().toList();
|
||||
}
|
||||
|
||||
return dto.getPath().stream().map(path -> {
|
||||
// 生成模板
|
||||
VmsArgumentDtoBaseVmsGenerator vmsArgumentDtoBaseVmsGenerator = new VmsArgumentDtoBaseVmsGenerator(dto, path);
|
||||
StringWriter writer = vmsArgumentDtoBaseVmsGenerator.generatorCodeTemplate(tableMetaData, columnInfoList);
|
||||
|
||||
// 处理 vm 文件名
|
||||
path = VmsUtil.handleVmFilename(path, dto.getClassName());
|
||||
|
||||
return GeneratorVo.builder()
|
||||
.code(writer.toString())
|
||||
.comment(tableMetaData.getComment())
|
||||
.tableName(tableMetaData.getTableName())
|
||||
.path(path)
|
||||
.build();
|
||||
}).toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取vms文件路径
|
||||
*
|
||||
* @return vms下的文件路径
|
||||
*/
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public Map<String, List<VmsPathVo>> vmsResourcePathList() {
|
||||
// 读取当前项目中所有的 vm 模板发给前端
|
||||
List<String> vmsRelativeFiles = ResourceFileCore.getRelativeFiles("vms");
|
||||
|
||||
return vmsRelativeFiles.stream().map(vmFile -> {
|
||||
String[] filepathList = vmFile.split("/");
|
||||
String filename = filepathList[filepathList.length - 1].replace(".vm", "");
|
||||
|
||||
return VmsPathVo.builder().name(vmFile).label(filename).type(filepathList[0]).build();
|
||||
})
|
||||
.collect(Collectors.groupingBy(VmsPathVo::getType));
|
||||
}
|
||||
|
||||
/**
|
||||
* 打包成zip下载
|
||||
*
|
||||
* @param dto VmsArgumentDto
|
||||
* @return zip 文件
|
||||
*/
|
||||
@Override
|
||||
public ResponseEntity<byte[]> downloadByZip(VmsArgumentDto dto) {
|
||||
// 需要下载的数据
|
||||
List<GeneratorVo> generatorVoList = generator(dto);
|
||||
|
||||
// 1. 创建临时ZIP文件
|
||||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||
try (ZipOutputStream zipOutputStream = new ZipOutputStream(byteArrayOutputStream)) {
|
||||
// 2. 遍历并创建
|
||||
generatorVoList.forEach(generatorVo -> {
|
||||
// zip中的路径
|
||||
String path = generatorVo.getPath().replace(".vm", "");
|
||||
|
||||
// zip中的文件
|
||||
String code = generatorVo.getCode();
|
||||
|
||||
ZipEntry zipEntry = new ZipEntry(path);
|
||||
try {
|
||||
// 如果有 / 会转成文件夹
|
||||
zipOutputStream.putNextEntry(zipEntry);
|
||||
|
||||
// 写入文件
|
||||
zipOutputStream.write(code.getBytes(StandardCharsets.UTF_8));
|
||||
zipOutputStream.closeEntry();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
// 2.1 文件不重名
|
||||
long currentTimeMillis = System.currentTimeMillis();
|
||||
String digestHex = MD5.create().digestHex(currentTimeMillis + "");
|
||||
|
||||
// 3. 准备响应
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.add("Content-Disposition", "attachment; filename=" + "vms-" + digestHex + ".zip");
|
||||
headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
|
||||
headers.add("Pragma", "no-cache");
|
||||
headers.add("Expires", "0");
|
||||
|
||||
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
|
||||
return new ResponseEntity<>(byteArrayInputStream.readAllBytes(), headers, HttpStatus.OK);
|
||||
}
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
package cn.bunny.utils;
|
||||
|
||||
import cn.bunny.core.TypeConvertCore;
|
||||
import com.google.common.base.CaseFormat;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class VmsUtil {
|
||||
|
||||
private static final Map<String, String> TYPE_MAPPINGS = Map.of(
|
||||
"controller", "Controller",
|
||||
"service", "Service",
|
||||
"serviceImpl", "ServiceImpl",
|
||||
"mapper", "Mapper",
|
||||
"resourceMapper", "Mapper"
|
||||
);
|
||||
|
||||
/**
|
||||
* 处理 vm 文件名
|
||||
*
|
||||
* @param path 文件路径
|
||||
* @param className 类名
|
||||
*/
|
||||
public static String handleVmFilename(String path, String className) {
|
||||
String[] splitPaths = path.split("/");
|
||||
int splitPathsSize = splitPaths.length - 1;
|
||||
|
||||
// 大驼峰名称
|
||||
String CamelCase = TypeConvertCore.convertToCamelCase(className, true);
|
||||
// 小驼峰名称
|
||||
String camelCase = TypeConvertCore.convertToCamelCase(className);
|
||||
// 当前文件名
|
||||
String filename = splitPaths[splitPathsSize];
|
||||
filename = filename.replace(".vm", "");
|
||||
|
||||
String[] split = filename.split("\\.");
|
||||
// 文件名称
|
||||
String name = split[0];
|
||||
// 文件扩展名
|
||||
String extension = "";
|
||||
if (split.length >= 2) {
|
||||
extension = split[1];
|
||||
}
|
||||
|
||||
// 判断是否是 Java 或者 xml 文件
|
||||
String typeMappingsFilename = TYPE_MAPPINGS.get(name);
|
||||
typeMappingsFilename = typeMappingsFilename == null ? "" : typeMappingsFilename;
|
||||
if (filename.contains("java") || filename.contains("xml")) {
|
||||
filename = CamelCase + typeMappingsFilename + "." + extension;
|
||||
}
|
||||
|
||||
if (filename.contains("vue") && !filename.contains("index")) {
|
||||
filename = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_HYPHEN, camelCase) + "-" + name + "." + extension;
|
||||
}
|
||||
|
||||
splitPaths[splitPathsSize] = filename;
|
||||
return String.join("/", splitPaths);
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
bunny:
|
||||
master:
|
||||
host: 192.168.3.137 # localhost
|
||||
port: 3306
|
||||
database: auth_admin
|
||||
username: root
|
||||
password: "123456"
|
|
@ -1,17 +0,0 @@
|
|||
server:
|
||||
port: 8800
|
||||
|
||||
spring:
|
||||
profiles:
|
||||
active: dev
|
||||
application:
|
||||
name: generator-code
|
||||
thymeleaf:
|
||||
check-template-location: false
|
||||
|
||||
datasource:
|
||||
type: com.zaxxer.hikari.HikariDataSource
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://${bunny.master.host}:${bunny.master.port}/${bunny.master.database}?serverTimezone=GMT%2B8&useSSL=false&characterEncoding=utf-8&allowPublicKeyRetrieval=true
|
||||
username: ${bunny.master.username}
|
||||
password: ${bunny.master.password}
|
|
@ -1,10 +0,0 @@
|
|||
_ _
|
||||
| |__ _ _ _ __ _ __ _ _ (_) __ ___ ____ _
|
||||
| '_ \| | | | '_ \| '_ \| | | | | |/ _` \ \ / / _` |
|
||||
| |_) | |_| | | | | | | | |_| | | | (_| |\ V | (_| |
|
||||
|_.__/ \__,_|_| |_|_| |_|\__, | _/ |\__,_| \_/ \__,_|
|
||||
|___/ |__/
|
||||
|
||||
Service Name${spring.application.name}
|
||||
SpringBoot Version: ${spring-boot.version}${spring-boot.formatted-version}
|
||||
SpringActive:${spring.profiles.active}
|
|
@ -1,69 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<contextName>logback</contextName>
|
||||
|
||||
<!-- 格式化 年-月-日 输出 -->
|
||||
<timestamp key="datetime" datePattern="yyyy-MM-dd"/>
|
||||
|
||||
<!--编码-->
|
||||
<property name="ENCODING" value="UTF-8"/>
|
||||
|
||||
<!-- 控制台日志 -->
|
||||
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<!-- 临界值过滤器 -->
|
||||
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||
<level>INFO</level>
|
||||
</filter>
|
||||
<encoder>
|
||||
<pattern>%cyan([%thread %d{yyyy-MM-dd HH:mm:ss}]) %yellow(%-5level) %green(%logger{100}).%boldRed(%method)-%boldMagenta(%line)-%blue(%msg%n)
|
||||
</pattern>
|
||||
<charset>${ENCODING}</charset>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- 文件日志 -->
|
||||
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
|
||||
<file>logs/${datetime}/financial-server.log</file>
|
||||
<append>true</append>
|
||||
<encoder>
|
||||
<pattern>%date{yyyy-MM-dd HH:mm:ss} [%-5level] %thread %file:%line %logger %msg%n</pattern>
|
||||
<charset>${ENCODING}</charset>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- 让SpringBoot内部日志ERROR级别 减少日志输出 -->
|
||||
<logger name="org.springframework" level="ERROR" additivity="false">
|
||||
<appender-ref ref="STOUT"/>
|
||||
</logger>
|
||||
|
||||
<!-- 让mybatis整合包日志ERROR 减少日志输出 -->
|
||||
<logger name="org.mybatis" level="ERROR" additivity="false">
|
||||
<appender-ref ref="STOUT"/>
|
||||
</logger>
|
||||
|
||||
<!-- 让ibatis 日志ERROR 减少日志输出 -->
|
||||
<logger name="org.apache.ibatis" level="ERROR" additivity="false">
|
||||
<appender-ref ref="STOUT"/>
|
||||
</logger>
|
||||
|
||||
<!-- 让 tomcat包打印日志 日志ERROR 减少日志输出 -->
|
||||
<logger name="org.apache" level="ERROR" additivity="false">
|
||||
<appender-ref ref="STOUT"/>
|
||||
</logger>
|
||||
|
||||
<!-- 我们自己开发的程序为DEBUG -->
|
||||
<logger name="cn.bunny" level="DEBUG" additivity="false">
|
||||
<appender-ref ref="STOUT"/>
|
||||
</logger>
|
||||
|
||||
<logger name="com.baomidou" level="ERROR" additivity="false">
|
||||
<appender-ref ref="STOUT"/>
|
||||
</logger>
|
||||
|
||||
<!-- 根日志记录器:INFO级别 -->
|
||||
<root level="INFO">
|
||||
<appender-ref ref="CONSOLE"/>
|
||||
<appender-ref ref="FILE"/>
|
||||
</root>
|
||||
|
||||
</configuration>
|
|
@ -1,69 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>400 错误 - phpstudy</title>
|
||||
<meta content="" name="keywords">
|
||||
<meta content="" name="description">
|
||||
<meta content="webkit" name="renderer">
|
||||
<meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1, maximum-scale=1" name="viewport">
|
||||
<meta content="black" name="apple-mobile-web-app-status-bar-style">
|
||||
<meta content="yes" name="apple-mobile-web-app-capable">
|
||||
<meta content="telephone=no" name="format-detection">
|
||||
<meta CONTENT="no-cache" HTTP-EQUIV="pragma">
|
||||
<meta CONTENT="no-store, must-revalidate" HTTP-EQUIV="Cache-Control">
|
||||
<meta CONTENT="Wed, 26 Feb 1997 08:21:57 GMT" HTTP-EQUIV="expires">
|
||||
<meta CONTENT="0" HTTP-EQUIV="expires">
|
||||
<style>
|
||||
body {
|
||||
font: 16px arial, 'Microsoft Yahei', 'Hiragino Sans GB', sans-serif;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
color: #3a87ad;
|
||||
font-size: 26px;
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 45%;
|
||||
margin: 0 auto;
|
||||
|
||||
}
|
||||
|
||||
.content > div {
|
||||
margin-top: 200px;
|
||||
padding: 20px;
|
||||
background: #d9edf7;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.content dl {
|
||||
color: #2d6a88;
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
.content div div {
|
||||
padding-bottom: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="content">
|
||||
<div>
|
||||
<h1>HTTP 400 - Bad Request</h1>
|
||||
<dl>
|
||||
<dt>错误说明:因为错误的语法导致服务器无法理解请求信息。</dt>
|
||||
<dt>原因1:客户端发起的请求不符合服务器对请求的某些限制,或者请求本身存在一定的错误。</dt>
|
||||
<dd>解决办法:</dd>
|
||||
<dd>链接中有特殊字符或者链接长度过长导致,请对应修改.</dd>
|
||||
<dt>原因2:request header 或者 cookie 过大所引起</dt>
|
||||
<dd>解决办法:</dd>
|
||||
<dd>crtl+shift+delete 快捷键清除cookie.</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,69 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>403 错误 - phpstudy</title>
|
||||
<meta content="" name="keywords">
|
||||
<meta content="" name="description">
|
||||
<meta content="webkit" name="renderer">
|
||||
<meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1, maximum-scale=1" name="viewport">
|
||||
<meta content="black" name="apple-mobile-web-app-status-bar-style">
|
||||
<meta content="yes" name="apple-mobile-web-app-capable">
|
||||
<meta content="telephone=no" name="format-detection">
|
||||
<meta CONTENT="no-cache" HTTP-EQUIV="pragma">
|
||||
<meta CONTENT="no-store, must-revalidate" HTTP-EQUIV="Cache-Control">
|
||||
<meta CONTENT="Wed, 26 Feb 1997 08:21:57 GMT" HTTP-EQUIV="expires">
|
||||
<meta CONTENT="0" HTTP-EQUIV="expires">
|
||||
<style>
|
||||
body {
|
||||
font: 16px arial, 'Microsoft Yahei', 'Hiragino Sans GB', sans-serif;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
color: #3a87ad;
|
||||
font-size: 26px;
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 45%;
|
||||
margin: 0 auto;
|
||||
|
||||
}
|
||||
|
||||
.content > div {
|
||||
margin-top: 200px;
|
||||
padding: 20px;
|
||||
background: #d9edf7;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.content dl {
|
||||
color: #2d6a88;
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
.content div div {
|
||||
padding-bottom: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="content">
|
||||
<div>
|
||||
<h1>403 - Forbidden 禁止访问: 访问被拒绝</h1>
|
||||
<dl>
|
||||
<dt>错误说明:禁止访问,服务器拒绝访问</dt>
|
||||
<dt>原因1:未找到默认的索引文件</dt>
|
||||
<dd>解决办法:</dd>
|
||||
<dd>IIS中【启用默认内容文档】选项中将默认打开文档修改为程序首页文件格式,如:index.html或者index.php</dd>
|
||||
<dt>原因2:文件夹安全权限导致</dt>
|
||||
<dd>解决办法:</dd>
|
||||
<dd>程序文件-右击-属性-安全-Users-修改为读取和执行权限</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,78 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>404 错误 - phpstudy</title>
|
||||
<meta content="" name="keywords">
|
||||
<meta content="" name="description">
|
||||
<meta content="webkit" name="renderer">
|
||||
<meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1, maximum-scale=1" name="viewport">
|
||||
<meta content="black" name="apple-mobile-web-app-status-bar-style">
|
||||
<meta content="yes" name="apple-mobile-web-app-capable">
|
||||
<meta content="telephone=no" name="format-detection">
|
||||
<meta CONTENT="no-cache" HTTP-EQUIV="pragma">
|
||||
<meta CONTENT="no-store, must-revalidate" HTTP-EQUIV="Cache-Control">
|
||||
<meta CONTENT="Wed, 26 Feb 1997 08:21:57 GMT" HTTP-EQUIV="expires">
|
||||
<meta CONTENT="0" HTTP-EQUIV="expires">
|
||||
<style>
|
||||
body {
|
||||
font: 16px arial, 'Microsoft Yahei', 'Hiragino Sans GB', sans-serif;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
color: #3a87ad;
|
||||
font-size: 26px;
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 45%;
|
||||
margin: 0 auto;
|
||||
|
||||
}
|
||||
|
||||
.content > div {
|
||||
margin-top: 50px;
|
||||
padding: 20px;
|
||||
background: #d9edf7;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.content dl {
|
||||
color: #2d6a88;
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
.content div div {
|
||||
padding-bottom: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="content">
|
||||
<div>
|
||||
<h1>404 - Page Not Found 未找到</h1>
|
||||
<dl>
|
||||
<dt>错误说明:请求的页面不存在</dt>
|
||||
<dt>原因1:访问的文档权限不够</dt>
|
||||
<dd>解决办法:</dd>
|
||||
<dd>修改文件权限为755,windos系统修改目录权限为可写可读。</dd>
|
||||
<dt>原因2:防火墙的原因</dt>
|
||||
<dd>解决办法:</dd>
|
||||
<dd>先关闭让防火墙通过WWW服务。</dd>
|
||||
<dt>原因3:站点根目录无默认访问文件</dt>
|
||||
<dd>解决办法:</dd>
|
||||
<dd>在根目录中创建index.html或者创建index.php。</dd>
|
||||
<dt>原因4:站点配置目录不正确</dt>
|
||||
<dd>解决办法:</dd>
|
||||
<dd>将网站应用程序复制到站点目录中,或者修改站点配置目录指定到应用程序目录中。</dd>
|
||||
<dt>原因5:站点使用了伪静态</dt>
|
||||
<dd>解决办法:</dd>
|
||||
<dd>将伪静态规则删除,或者重新编写正确的伪静态规则,或关闭伪静态配置。</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,64 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="zh-cmn-Hans">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>500 - 服务器错误</title>
|
||||
<meta content="width=device-width, maximum-scale=1, initial-scale=1" name="viewport"/>
|
||||
<style>
|
||||
html, body {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
color: #333;
|
||||
margin: auto;
|
||||
padding: 1em;
|
||||
display: table;
|
||||
user-select: none;
|
||||
box-sizing: border-box;
|
||||
font: lighter 20px "微软雅黑";
|
||||
}
|
||||
|
||||
a {
|
||||
color: #3498db;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-top: 0;
|
||||
font-size: 3.5em;
|
||||
}
|
||||
|
||||
main {
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.btn {
|
||||
color: #fff;
|
||||
padding: .75em 1em;
|
||||
background: #3498db;
|
||||
border-radius: 1.5em;
|
||||
display: inline-block;
|
||||
transition: opacity .3s, transform .3s;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.btn:active {
|
||||
opacity: .7;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<h1>:'(</h1>
|
||||
<p>服务器开小差啦!管理员正在修理中...</p>
|
||||
<p>还请阁下静候站点恢复~</p>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
|
@ -1,66 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>501 错误 - phpstudy</title>
|
||||
<meta content="" name="keywords">
|
||||
<meta content="" name="description">
|
||||
<meta content="webkit" name="renderer">
|
||||
<meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1, maximum-scale=1" name="viewport">
|
||||
<meta content="black" name="apple-mobile-web-app-status-bar-style">
|
||||
<meta content="yes" name="apple-mobile-web-app-capable">
|
||||
<meta content="telephone=no" name="format-detection">
|
||||
<meta CONTENT="no-cache" HTTP-EQUIV="pragma">
|
||||
<meta CONTENT="no-store, must-revalidate" HTTP-EQUIV="Cache-Control">
|
||||
<meta CONTENT="Wed, 26 Feb 1997 08:21:57 GMT" HTTP-EQUIV="expires">
|
||||
<meta CONTENT="0" HTTP-EQUIV="expires">
|
||||
<style>
|
||||
body {
|
||||
font: 16px arial, 'Microsoft Yahei', 'Hiragino Sans GB', sans-serif;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
color: #3a87ad;
|
||||
font-size: 26px;
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 45%;
|
||||
margin: 0 auto;
|
||||
|
||||
}
|
||||
|
||||
.content > div {
|
||||
margin-top: 200px;
|
||||
padding: 20px;
|
||||
background: #d9edf7;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.content dl {
|
||||
color: #2d6a88;
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
.content div div {
|
||||
padding-bottom: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="content">
|
||||
<div>
|
||||
<h1>HTTP 501 - Not Implemented</h1>
|
||||
<dl>
|
||||
<dt>错误说明:服务器没有相应的执行动作来完成当前请求。</dt>
|
||||
<dt>原因1:Web 服务器不支持实现此请求所需的功能</dt>
|
||||
<dd>解决办法:</dd>
|
||||
<dd>可以用来HttpWebRequest指定一个UserAgent来试试的,有时候你可以换电脑来测试一下的。</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,80 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>502 错误 - phpstudy</title>
|
||||
<meta content="" name="keywords">
|
||||
<meta content="" name="description">
|
||||
<meta content="webkit" name="renderer">
|
||||
<meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1, maximum-scale=1" name="viewport">
|
||||
<meta content="black" name="apple-mobile-web-app-status-bar-style">
|
||||
<meta content="yes" name="apple-mobile-web-app-capable">
|
||||
<meta content="telephone=no" name="format-detection">
|
||||
<meta CONTENT="no-cache" HTTP-EQUIV="pragma">
|
||||
<meta CONTENT="no-store, must-revalidate" HTTP-EQUIV="Cache-Control">
|
||||
<meta CONTENT="Wed, 26 Feb 1997 08:21:57 GMT" HTTP-EQUIV="expires">
|
||||
<meta CONTENT="0" HTTP-EQUIV="expires">
|
||||
<style>
|
||||
body {
|
||||
font: 16px arial, 'Microsoft Yahei', 'Hiragino Sans GB', sans-serif;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
color: #3a87ad;
|
||||
font-size: 26px;
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 45%;
|
||||
margin: 0 auto;
|
||||
|
||||
}
|
||||
|
||||
.content > div {
|
||||
margin-top: 50px;
|
||||
padding: 20px;
|
||||
background: #d9edf7;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.content dl {
|
||||
color: #2d6a88;
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
.content div div {
|
||||
padding-bottom: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="content">
|
||||
<div>
|
||||
<h1>HTTP 502 - Bad Gateway 没有响应</h1>
|
||||
<dl>
|
||||
<dt>错误说明:坏的网关,http向后端节点请求,没有响应</dt>
|
||||
<dt>原因1:DNS 缓冲</dt>
|
||||
<dd>解决办法:</dd>
|
||||
<dd>在dos窗口运行 ipconfig /flushdns,该命令会刷新DNS缓冲。</dd>
|
||||
<dt>原因2:浏览器代理</dt>
|
||||
<dd>解决办法:</dd>
|
||||
<dd>关掉代理。</dd>
|
||||
<dt>原因3:dns 被劫持了,即使使用国外的dns,也会被劫持</dt>
|
||||
<dd>解决办法:</dd>
|
||||
<dd>
|
||||
去掉VPN服务器的DNS。切换另外的dns。在windows系统中,可以在本地网络连接的属性中,去掉默认的dns,选用国外的dns,比如google的或opendns。
|
||||
</dd>
|
||||
<dt>原因4:php执行超时</dt>
|
||||
<dd>解决办法:</dd>
|
||||
<dd>修改/usr/local/php/etc/php.ini 将max_execution_time 改为300。</dd>
|
||||
<dt>原因5:nginx等待时间超时</dt>
|
||||
<dd>解决办法:</dd>
|
||||
<dd>适当增加nginx.conf配置文件中FastCGI的timeout时间。</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,69 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>503 错误 - phpstudy</title>
|
||||
<meta content="" name="keywords">
|
||||
<meta content="" name="description">
|
||||
<meta content="webkit" name="renderer">
|
||||
<meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1, maximum-scale=1" name="viewport">
|
||||
<meta content="black" name="apple-mobile-web-app-status-bar-style">
|
||||
<meta content="yes" name="apple-mobile-web-app-capable">
|
||||
<meta content="telephone=no" name="format-detection">
|
||||
<meta CONTENT="no-cache" HTTP-EQUIV="pragma">
|
||||
<meta CONTENT="no-store, must-revalidate" HTTP-EQUIV="Cache-Control">
|
||||
<meta CONTENT="Wed, 26 Feb 1997 08:21:57 GMT" HTTP-EQUIV="expires">
|
||||
<meta CONTENT="0" HTTP-EQUIV="expires">
|
||||
<style>
|
||||
body {
|
||||
font: 16px arial, 'Microsoft Yahei', 'Hiragino Sans GB', sans-serif;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
color: #3a87ad;
|
||||
font-size: 26px;
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 45%;
|
||||
margin: 0 auto;
|
||||
|
||||
}
|
||||
|
||||
.content > div {
|
||||
margin-top: 200px;
|
||||
padding: 20px;
|
||||
background: #d9edf7;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.content dl {
|
||||
color: #2d6a88;
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
.content div div {
|
||||
padding-bottom: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="content">
|
||||
<div>
|
||||
<h1>HTTP 503 - Service Unavailable 服务不可用</h1>
|
||||
<dl>
|
||||
<dt>错误说明:服务当前不可用</dt>
|
||||
<dt>原因1:服务不可用状态</dt>
|
||||
<dd>解决办法:</dd>
|
||||
<dd>服务器或许就是正在维护或者暂停了,你可以联系一下服务器空间商。</dd>
|
||||
<dt>原因2:程序占用资源太多</dt>
|
||||
<dd>解决办法:</dd>
|
||||
<dd>通过设置应用程序池把账户改为NetworkService即可解决。</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,81 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>504 错误 - phpstudy</title>
|
||||
<meta content="" name="keywords">
|
||||
<meta content="" name="description">
|
||||
<meta content="webkit" name="renderer">
|
||||
<meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1, maximum-scale=1" name="viewport">
|
||||
<meta content="black" name="apple-mobile-web-app-status-bar-style">
|
||||
<meta content="yes" name="apple-mobile-web-app-capable">
|
||||
<meta content="telephone=no" name="format-detection">
|
||||
<meta CONTENT="no-cache" HTTP-EQUIV="pragma">
|
||||
<meta CONTENT="no-store, must-revalidate" HTTP-EQUIV="Cache-Control">
|
||||
<meta CONTENT="Wed, 26 Feb 1997 08:21:57 GMT" HTTP-EQUIV="expires">
|
||||
<meta CONTENT="0" HTTP-EQUIV="expires">
|
||||
<style>
|
||||
body {
|
||||
font: 16px arial, 'Microsoft Yahei', 'Hiragino Sans GB', sans-serif;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
color: #3a87ad;
|
||||
font-size: 26px;
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 45%;
|
||||
margin: 0 auto;
|
||||
|
||||
}
|
||||
|
||||
.content > div {
|
||||
margin-top: 50px;
|
||||
padding: 20px;
|
||||
background: #d9edf7;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.content dl {
|
||||
color: #2d6a88;
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
.content div div {
|
||||
padding-bottom: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="content">
|
||||
<div>
|
||||
<h1>HTTP 504 - Gateway Timeout 网关超时</h1>
|
||||
<dl>
|
||||
<dt>错误说明:网关超时,服务器响应时间,达到超出设定的范围</dt>
|
||||
<dt>原因1:后端电脑之间 IP 通讯缓慢而产生</dt>
|
||||
<dd>解决办法:</dd>
|
||||
<dd>如果您的 Web 服务器由某一网站托管, 只有负责那个网站设置的人员才能解决这个问题。</dd>
|
||||
<dt>原因2:由于nginx默认的fastcgi进程响应的缓冲区太小造成的错误</dt>
|
||||
<dd>解决办法:</dd>
|
||||
<dd>一般默认的fastcgi进程响应的缓冲区是8K,这时可以设置大一点,在nginx.conf里,加入:fastcgi_buffers 8
|
||||
128k这表示设置fastcgi缓冲区为8块128k大小的空间。当然如果在进行某一项即时的操作, 可能需要nginx的超时参数调大点,
|
||||
例如设置成60秒:send_timeout 60;经过这两个参数的调整,一般不会再提示“504 Gateway Time-out”错误,问题基本解决。
|
||||
</dd>
|
||||
<dt>原因3:PHP环境的配置问题</dt>
|
||||
<dd>解决办法:</dd>
|
||||
<dd>更改php-fpm的几处配置: 把max_children由之前的10改为现在的30,这样就可以保证有充足的php-cgi进程可以被使用;
|
||||
把request_terminate_timeout由之前的0s改为60s,这样php-cgi进程 处理脚本的超时时间就是60秒,可以防止进程都被挂起,提高利用效率。
|
||||
接着再更改nginx的几个配置项,减少FastCGI的请求次数,尽量维持buffers不变: fastcgi_buffers由 4 64k 改为 2
|
||||
256k; fastcgi_buffer_size 由 64k 改为 128K; fastcgi_busy_buffers_size 由 128K 改为 256K;
|
||||
fastcgi_temp_file_write_size 由 128K 改为 256K。 重新加载php-fpm和nginx的配置,再次测试,如果没有出现“504
|
||||
Gateway Time-out”错误,问题解决。
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,72 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>505 错误 - phpstudy</title>
|
||||
<meta content="" name="keywords">
|
||||
<meta content="" name="description">
|
||||
<meta content="webkit" name="renderer">
|
||||
<meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1, maximum-scale=1" name="viewport">
|
||||
<meta content="black" name="apple-mobile-web-app-status-bar-style">
|
||||
<meta content="yes" name="apple-mobile-web-app-capable">
|
||||
<meta content="telephone=no" name="format-detection">
|
||||
<meta CONTENT="no-cache" HTTP-EQUIV="pragma">
|
||||
<meta CONTENT="no-store, must-revalidate" HTTP-EQUIV="Cache-Control">
|
||||
<meta CONTENT="Wed, 26 Feb 1997 08:21:57 GMT" HTTP-EQUIV="expires">
|
||||
<meta CONTENT="0" HTTP-EQUIV="expires">
|
||||
<style>
|
||||
body {
|
||||
font: 16px arial, 'Microsoft Yahei', 'Hiragino Sans GB', sans-serif;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
color: #3a87ad;
|
||||
font-size: 26px;
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 45%;
|
||||
margin: 0 auto;
|
||||
|
||||
}
|
||||
|
||||
.content > div {
|
||||
margin-top: 200px;
|
||||
padding: 20px;
|
||||
background: #d9edf7;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.content dl {
|
||||
color: #2d6a88;
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
.content div div {
|
||||
padding-bottom: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="content">
|
||||
<div>
|
||||
<h1>HTTP 505 - HTTP Version Not Supported</h1>
|
||||
<dl>
|
||||
<dt>错误说明:HTTP 版本不受支持。</dt>
|
||||
<dt>原因1:您的 Web 服务器不支持,或拒绝支持客户端(如您的浏览器)在发送给服务器的 HTTP 请求数据流中指定的 HTTP
|
||||
协议版本
|
||||
</dt>
|
||||
<dd>解决办法:</dd>
|
||||
<dd>升级您的 Web 服务器软件。</dd>
|
||||
<dt>原因2:http请求格式的错误</dt>
|
||||
<dd>解决办法:</dd>
|
||||
<dd>对照一下自己的代码,从打印的信息中终于找到问题所在。可能在请求后面多加了一个空格。http协议真是很严格了。
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,66 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>506 错误 - phpstudy</title>
|
||||
<meta content="" name="keywords">
|
||||
<meta content="" name="description">
|
||||
<meta content="webkit" name="renderer">
|
||||
<meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1, maximum-scale=1" name="viewport">
|
||||
<meta content="black" name="apple-mobile-web-app-status-bar-style">
|
||||
<meta content="yes" name="apple-mobile-web-app-capable">
|
||||
<meta content="telephone=no" name="format-detection">
|
||||
<meta CONTENT="no-cache" HTTP-EQUIV="pragma">
|
||||
<meta CONTENT="no-store, must-revalidate" HTTP-EQUIV="Cache-Control">
|
||||
<meta CONTENT="Wed, 26 Feb 1997 08:21:57 GMT" HTTP-EQUIV="expires">
|
||||
<meta CONTENT="0" HTTP-EQUIV="expires">
|
||||
<style>
|
||||
body {
|
||||
font: 16px arial, 'Microsoft Yahei', 'Hiragino Sans GB', sans-serif;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
color: #3a87ad;
|
||||
font-size: 26px;
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 45%;
|
||||
margin: 0 auto;
|
||||
|
||||
}
|
||||
|
||||
.content > div {
|
||||
margin-top: 200px;
|
||||
padding: 20px;
|
||||
background: #d9edf7;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.content dl {
|
||||
color: #2d6a88;
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
.content div div {
|
||||
padding-bottom: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="content">
|
||||
<div>
|
||||
<h1>HTTP 506 - Variant Also Negotiates</h1>
|
||||
<dl>
|
||||
<dt>错误说明:</dt>
|
||||
<dt>原因1:服务器存在内部配置错误</dt>
|
||||
<dd>解决办法:</dd>
|
||||
<dd>被请求的协商变元资源被配置为在透明内容协商中使用自己,因此在一个协商处理中不是一个合适的重点。</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,66 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>507 错误 - phpstudy</title>
|
||||
<meta content="" name="keywords">
|
||||
<meta content="" name="description">
|
||||
<meta content="webkit" name="renderer">
|
||||
<meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1, maximum-scale=1" name="viewport">
|
||||
<meta content="black" name="apple-mobile-web-app-status-bar-style">
|
||||
<meta content="yes" name="apple-mobile-web-app-capable">
|
||||
<meta content="telephone=no" name="format-detection">
|
||||
<meta CONTENT="no-cache" HTTP-EQUIV="pragma">
|
||||
<meta CONTENT="no-store, must-revalidate" HTTP-EQUIV="Cache-Control">
|
||||
<meta CONTENT="Wed, 26 Feb 1997 08:21:57 GMT" HTTP-EQUIV="expires">
|
||||
<meta CONTENT="0" HTTP-EQUIV="expires">
|
||||
<style>
|
||||
body {
|
||||
font: 16px arial, 'Microsoft Yahei', 'Hiragino Sans GB', sans-serif;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
color: #3a87ad;
|
||||
font-size: 26px;
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 45%;
|
||||
margin: 0 auto;
|
||||
|
||||
}
|
||||
|
||||
.content > div {
|
||||
margin-top: 200px;
|
||||
padding: 20px;
|
||||
background: #d9edf7;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.content dl {
|
||||
color: #2d6a88;
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
.content div div {
|
||||
padding-bottom: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="content">
|
||||
<div>
|
||||
<h1>HTTP 507 - Insufficient Storage</h1>
|
||||
<dl>
|
||||
<dt>错误说明:</dt>
|
||||
<dt>原因1:服务器无法存储完成请求所必须的内容</dt>
|
||||
<dd>解决办法:</dd>
|
||||
<dd>这个状况被认为是临时的。WebDAV (RFC 4918)。</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,66 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>509 错误 - phpstudy</title>
|
||||
<meta content="" name="keywords">
|
||||
<meta content="" name="description">
|
||||
<meta content="webkit" name="renderer">
|
||||
<meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1, maximum-scale=1" name="viewport">
|
||||
<meta content="black" name="apple-mobile-web-app-status-bar-style">
|
||||
<meta content="yes" name="apple-mobile-web-app-capable">
|
||||
<meta content="telephone=no" name="format-detection">
|
||||
<meta CONTENT="no-cache" HTTP-EQUIV="pragma">
|
||||
<meta CONTENT="no-store, must-revalidate" HTTP-EQUIV="Cache-Control">
|
||||
<meta CONTENT="Wed, 26 Feb 1997 08:21:57 GMT" HTTP-EQUIV="expires">
|
||||
<meta CONTENT="0" HTTP-EQUIV="expires">
|
||||
<style>
|
||||
body {
|
||||
font: 16px arial, 'Microsoft Yahei', 'Hiragino Sans GB', sans-serif;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
color: #3a87ad;
|
||||
font-size: 26px;
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 45%;
|
||||
margin: 0 auto;
|
||||
|
||||
}
|
||||
|
||||
.content > div {
|
||||
margin-top: 200px;
|
||||
padding: 20px;
|
||||
background: #d9edf7;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.content dl {
|
||||
color: #2d6a88;
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
.content div div {
|
||||
padding-bottom: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="content">
|
||||
<div>
|
||||
<h1>HTTP 509 - Bandwidth Limit Exceeded</h1>
|
||||
<dl>
|
||||
<dt>错误说明:</dt>
|
||||
<dt>原因1:网站流量已经超出您所购买的方案限制即服务器达到带宽限制</dt>
|
||||
<dd>解决办法:</dd>
|
||||
<dd>1.升级方案 2.等到下个月后流量重新计算,网站即可正常浏览。</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,66 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>510 错误 - phpstudy</title>
|
||||
<meta content="" name="keywords">
|
||||
<meta content="" name="description">
|
||||
<meta content="webkit" name="renderer">
|
||||
<meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width, initial-scale=1, maximum-scale=1" name="viewport">
|
||||
<meta content="black" name="apple-mobile-web-app-status-bar-style">
|
||||
<meta content="yes" name="apple-mobile-web-app-capable">
|
||||
<meta content="telephone=no" name="format-detection">
|
||||
<meta CONTENT="no-cache" HTTP-EQUIV="pragma">
|
||||
<meta CONTENT="no-store, must-revalidate" HTTP-EQUIV="Cache-Control">
|
||||
<meta CONTENT="Wed, 26 Feb 1997 08:21:57 GMT" HTTP-EQUIV="expires">
|
||||
<meta CONTENT="0" HTTP-EQUIV="expires">
|
||||
<style>
|
||||
body {
|
||||
font: 16px arial, 'Microsoft Yahei', 'Hiragino Sans GB', sans-serif;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
color: #3a87ad;
|
||||
font-size: 26px;
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 45%;
|
||||
margin: 0 auto;
|
||||
|
||||
}
|
||||
|
||||
.content > div {
|
||||
margin-top: 200px;
|
||||
padding: 20px;
|
||||
background: #d9edf7;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.content dl {
|
||||
color: #2d6a88;
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
.content div div {
|
||||
padding-bottom: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="content">
|
||||
<div>
|
||||
<h1>HTTP 510 - Not Extended</h1>
|
||||
<dl>
|
||||
<dt>错误说明:</dt>
|
||||
<dt>原因1:获取资源所需要的策略并没有被满足</dt>
|
||||
<dd>解决办法:</dd>
|
||||
<dd>需要请求有额外的扩展内容,服务器才能处理请求。</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
Binary file not shown.
Before Width: | Height: | Size: 66 KiB |
|
@ -1 +0,0 @@
|
|||
.page-container[data-v-128c8218]{display:flex;padding:100px}.page-container .pic-404[data-v-128c8218]{width:600px;overflow:hidden}.page-container .pic-404__parent[data-v-128c8218]{width:100%}.page-container .pic-404__child.left[data-v-128c8218]{top:17px;left:220px;width:80px;opacity:0;animation-name:cloudLeft-128c8218;animation-duration:2s;animation-timing-function:linear;animation-delay:1s;animation-fill-mode:forwards}.page-container .pic-404__child.mid[data-v-128c8218]{top:10px;left:420px;width:46px;opacity:0;animation-name:cloudMid-128c8218;animation-duration:2s;animation-timing-function:linear;animation-delay:1.2s;animation-fill-mode:forwards}.page-container .pic-404__child.right[data-v-128c8218]{top:100px;left:500px;width:62px;opacity:0;animation-name:cloudRight-128c8218;animation-duration:2s;animation-timing-function:linear;animation-delay:1s;animation-fill-mode:forwards}@keyframes cloudLeft-128c8218{0%{top:17px;left:220px;opacity:0}20%{top:33px;left:188px;opacity:1}80%{top:81px;left:92px;opacity:1}to{top:97px;left:60px;opacity:0}}@keyframes cloudMid-128c8218{0%{top:10px;left:420px;opacity:0}20%{top:40px;left:360px;opacity:1}70%{top:130px;left:180px;opacity:1}to{top:160px;left:120px;opacity:0}}@keyframes cloudRight-128c8218{0%{top:100px;left:500px;opacity:0}20%{top:120px;left:460px;opacity:1}80%{top:180px;left:340px;opacity:1}to{top:200px;left:300px;opacity:0}}.page-container .bullshit[data-v-128c8218]{width:300px;padding:30px 0;overflow:hidden}.page-container .bullshit__oops[data-v-128c8218]{margin-bottom:20px;font-size:32px;font-weight:700;line-height:40px;color:#1482f0;opacity:0;animation-name:slideUp-128c8218;animation-duration:.5s;animation-fill-mode:forwards}.page-container .bullshit__headline[data-v-128c8218]{margin-bottom:10px;font-size:20px;font-weight:700;line-height:24px;color:#222;opacity:0;animation-name:slideUp-128c8218;animation-duration:.5s;animation-delay:.1s;animation-fill-mode:forwards}.page-container .bullshit__info[data-v-128c8218]{margin-bottom:30px;font-size:13px;line-height:21px;color:gray;opacity:0;animation-name:slideUp-128c8218;animation-duration:.5s;animation-delay:.2s;animation-fill-mode:forwards}.page-container .bullshit__return-home[data-v-128c8218]{display:block;float:left;width:110px;height:36px;font-size:14px;line-height:36px;color:#fff;text-align:center;cursor:pointer;background:#1482f0;border-radius:100px;opacity:0;animation-name:slideUp-128c8218;animation-duration:.5s;animation-delay:.3s;animation-fill-mode:forwards}@keyframes slideUp-128c8218{0%{opacity:0;transform:translateY(60px)}to{opacity:1;transform:translateY(0)}}
|
File diff suppressed because one or more lines are too long
|
@ -1 +0,0 @@
|
|||
.database-info[data-v-5045df9f]{display:flex;justify-content:space-between;flex-wrap:wrap;flex-direction:column}.database-info p[data-v-5045df9f]{margin:5px 0 0}
|
File diff suppressed because one or more lines are too long
|
@ -1 +0,0 @@
|
|||
import{h as v,c as a,a as f,p as s,b as t,q as e,t as l,j as c}from"./vendor-BT0L8wkZ.js";import{_ as d}from"./index-BZjZ3Az-.js";const i="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJgAAACKCAMAAABhAnODAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAMAUExURUdwTPf6/v////f6/v////////////z9//////////////////7+//v///f6/v////f5/vz///////////////j6/vf7/v////////////v8//////j7/v7+//////////////////////////////////////v8/+nx/fv9//b6/vr7/v////f5/vj7//////j7/vj7//f5/vD2/f///////////////+jy/P////////j6//////f6/v////f7/vj6/vf6/vL3/f////////j7/vv8//////3///f6/vf6/vb6/v////r8//f7/fL3/P///////////+jw/PT4/v3+//////////////7+//b6/v///////+jx/P///+jy/f////f6/uz0/eny/PT9/+jx/PT4/uz0/f////f6/vb6/vv9//z9//////3+//r8//f6/vj7/+ny/P////f6/////////+jw/Pf6/v////f6/vj7/v////f6/fT4//j7//b7//////b6/evy/P///+vz/P////////T3/v///+jx/P3+/////+nx+/f6/v///////+jw/Pj6/v///+nx/P///+vz/P////////////j7/vj7//H2/P///+zz/Pb6/v////////////P3/v39/////+/1/v///+jx++jx/Pj6/unx/ff6/+fx/Pf6/+jx/Ony/Ojx/Pz+//H3/v////7+//b6/vj8//7+//b5/v////b6/uz0/ff6/fj6//v8//j5/fb7//////v9/vn8//v8//f5//f6/vP3/Ojx/ez0/u31/v////f5/f///////////+z0/Pz9/+rz/+nw++30/Or0/fj//+jx/f////////f7//v9/+fw++nw/f////b4/v///+jw/f////P4/vj//+fz+/r8/u/2/unw//////f5/fb6/vb7//////b6/f3+//////L3/vr9/+/1/fT3/ff7/v////n8/vf6/v///+fw+/b5/fP4/f////T4/lxP5j4AAAD6dFJOUwD+9P3lAfb9pvsC/BIO+gnmDM3h7/PtBMLqvPn0NU5AId3+gajrK8T0Fc2/29/S4sXC47/4W8ho+psHMMD8GLvN97nyGfG++h74yMsGbJ/Dddjx5L5E1t/XN9PUjvzo7dHh2uge/sLBtdjs7r/s48rW08bFtMrE8NxS2cAKpy18c2OR0SPPiCnLvv35mdS9bV7z1Tlbl8woy7ToVMuw1c+63qLFM3zOD9i20N+6+GSqT5pLvOfb0Uifrn/ux5e3z4s7G41QVlrEvnzMx7GCaYXt4vw+icDeJG0alHj2jGl56FB5rcAmQfXBInOF13KSlNCEtNSBpOo946pl6lljAAAF7ElEQVR42u3ceVQTRxwH8AVCyk0gUAhKqwFRFAKIgALhEgS5WlBUsCCHCNJntYBCDQL6tGKtVbxqRUXrgYp4lko98BZ7n/a+Sy97X7QO62uRPHgBdjeTzcxm+l6+/2f4PDKZ3+zsb5eiMOdyw8UAZ9/I87VXqx0oQmJ/qfb2eFojkoDUmuvuNgZFvXf9lyQ7mjlnk5bVeBnA1JRRU15Cc+Xwr0CUIKjJqvpo6kYTThQd7S8FPZkl2DfqffKHp+JobZEEpAN1yuzxm5LdU5b50hBRLJSD/rxihRWVcO2K/1QYFG3XkQYG5ElsKNuU1PE0ZLrGycDgnMEFe4GmzSQKf5UqcamW2bVo9ATAkOV4XLWafzpufqIqUjU2j2HxUvo7AuZY34fDdUnJOJPyolTtRwIU2/tWjXvdpIA14k0Ylgct06srK6C9PbLDbTLgyoKnka+lkTBTXukHtEQaixj2KtRvcSHQmlxbpK7TJjCujQAia5IRuuaWwLicR8HAgKc5MpdLItQXeQHAZT8y2ApUE0wdC1SuBiiXxFRo2NdxMC6TGUBgmL0C6h82GggNS4VyLbUUGnYUyhU9EwgMC4tG/UUigv3lC7PmJwHBYd2FzUW/H8ni3k2XyAwAU6dia0xM0lk2WDAwGKw32fnfnepg2JapgIFh6sx5KXDej5o7al9TMmC9mZh/rrNRXRHscgFBMHUKDjyQJHED5MF6s5ZU2D1GmBFmhBlhRpgR9n+FiUV9sbAiCobkJBszDHiQCgOvkQqTP0YoDEy4n1AYSA8jFAZEIwiFAR9vQmFgmwOhMLCbVJilEWaEGWGQ2bS1nkCY/XLHno8oAle1EAVbeeWN/r1wVOC6bDJgVieL5QM/6pR482ChoWE2t0Yyfly292azAWH72sQcQzzSWTTNELDkIIhD+9bpRQXCwhJeh73HIf/jVGmFULCMndY6jRZ/IeZcPXaY7fo0PiOKy+VYYV5bTHkN6LMYAHwwl2vh/IaTlskBPljsGRG/wXKWWAJUkQ1h/e0Zz28oJ1cxMpbpb02DWBFtfjyHCk9Hxhr289Crt9u0WRRXIxrbUK6jkLGs2xh6d0+rWzkO62aTl4mQscBXqxmmfVV/M2uPDbo/IXgPOtZud8Zl4uKAFpjnoWyOaehYwSznPGFDuiGz3EZyDzU7Fx1r9hdse0HGprBHOWw+29Cx9mxgPRdOYe2udfNhGsovWI6M9VyKC2vRvszVfDV/ymCbDOEy7/RZFXd/Mnd7k6YN5TIvfryJa+91FaJjp3JKq3oo18nIWPEfRnDuCR0g28wrx7UOW7IAGUv+rLZTzRWw7e+0MgfdT3Gn1mda9imhYf8gY63J1H452wjtckbFWpwBceX4E7SLfhgNawbU/Y+5w6FdXUhY0g1wt//K4f9haxGwZOsh274b4F3b9Wel74c9w2+SQLvsECzz8E9wnRdu5sdv+QD+PC7TDNoVp+cyb7FSl9Z8hVAzP9xdp3PVj+BdJXotXLo+ghRTAusy0WcjGKJz30J3y8s3JJhnvqkHj8d37x61PbFqep5W11TeV7CTIvS5lbzrRiU37GOermdW690V8G7nIuS7Ckd+LQFD7g0VzMtiWdZ4XRHNDOL/yNHQ1um9jUo0a6vTrVDE3U1jdowd1K9vxuMw6SH9nmtma+o+UKe5SftW5/LjOYKicMDuLiK76vqugaMxlx/db4zm1/UWhrcwlx9ed2zf3PH5cNzlh9+t5O7uf3GXH76wO7jLD3YY3/KDGca//GCFSYPMKQJhTg+GUhR5MH3LDyaY/uUHD8zVnaIIhM3C8gIGvWE5IdjeP6IPDFn5YUo9b5j1pFgKY6o2H5rIC1aM/2VFNp+WFuoKQ1t+OA47v1ynCwx1+eFM9TvNkDD05UdLzN8+MUc7DEf5gTgtO35sDCcMT/mBisPmQ9msMNdMypDxfr+UEYat/OiQ7188OBiWE+JCEZGwT6ZpwMQexLw7j6KsvjlRoYZhLj88Enr8WEv3nWIvisDYdv5JGdOf/wBvCt5Mksy8ZAAAAABJRU5ErkJggg==",j={class:"page-container"},A={class:"bullshit"},n=d(v({__name:"404",setup(v){const d=l();return(v,l)=>(f(),a("div",j,[l[2]||(l[2]=s('<div class="pic-404" data-v-128c8218><img alt="404" class="pic-404__parent" src="/static/png/404-D6_y3Jr2.png" data-v-128c8218><img alt="404" class="pic-404__child left" src="'+i+'" data-v-128c8218><img alt="404" class="pic-404__child mid" src="'+i+'" data-v-128c8218><img alt="404" class="pic-404__child right" src="'+i+'" data-v-128c8218></div>',1)),t("div",A,[l[1]||(l[1]=s('<div class="bullshit__oops" data-v-128c8218>OOPS!</div><div class="bullshit__info" data-v-128c8218> All rights reserved <a href="https://wallstreetcn.com" style="color:#20a0ff;" target="_blank" data-v-128c8218>wallstreetcn</a></div><div class="bullshit__headline" data-v-128c8218>The webmaster said that you can not enter this page...</div><div class="bullshit__info" data-v-128c8218> Please check that the URL you entered is correct, or click the button below to return to the homepage. </div>',4)),t("a",{class:"bullshit__return-home",href:"/",onClick:l[0]||(l[0]=e((v=>c(d).replace("/")),["prevent"]))}," Back to home ")])]))}}),[["__scopeId","data-v-128c8218"]]);export{n as default};
|
|
@ -1,2 +0,0 @@
|
|||
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["static/js/404-DYq3ki41.js","static/js/vendor-BT0L8wkZ.js","static/css/vendor-lSrybVH6.css","static/css/404-XvabTZcV.css","static/js/index-DwLjqHOd.js","static/js/index-Dn1v0MTU.js","static/js/table-R7-h5oL5.js","static/js/index-DNjCtrgM.js","static/css/index-DFq_RgoD.css"])))=>i.map(i=>d[i]);
|
||||
import{o as e,c as t,a as n,b as r,d as o,r as s,e as a,f as i,g as c,s as l,h as d,u,i as m,j as p,N as f,w as h,k as _,l as y,T as v,m as E,n as g}from"./vendor-BT0L8wkZ.js";!function(){const e=document.createElement("link").relList;if(!(e&&e.supports&&e.supports("modulepreload"))){for(const e of document.querySelectorAll('link[rel="modulepreload"]'))t(e);new MutationObserver((e=>{for(const n of e)if("childList"===n.type)for(const e of n.addedNodes)"LINK"===e.tagName&&"modulepreload"===e.rel&&t(e)})).observe(document,{childList:!0,subtree:!0})}function t(e){if(e.ep)return;e.ep=!0;const t=function(e){const t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),"use-credentials"===e.crossOrigin?t.credentials="include":"anonymous"===e.crossOrigin?t.credentials="omit":t.credentials="same-origin",t}(e);fetch(e.href,t)}}();const w={},P=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){document.getElementsByTagName("link");const e=document.querySelector("meta[property=csp-nonce]"),n=(null==e?void 0:e.nonce)||(null==e?void 0:e.getAttribute("nonce"));r=Promise.allSettled(t.map((e=>{if((e=function(e){return"/"+e}(e))in w)return;w[e]=!0;const t=e.endsWith(".css"),r=t?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${e}"]${r}`))return;const o=document.createElement("link");return o.rel=t?"stylesheet":"modulepreload",t||(o.as="script"),o.crossOrigin="",o.href=e,n&&o.setAttribute("nonce",n),document.head.appendChild(o),t?new Promise(((t,n)=>{o.addEventListener("load",t),o.addEventListener("error",(()=>n(new Error(`Unable to preload CSS for ${e}`))))})):void 0})))}function o(e){const t=new Event("vite:preloadError",{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then((t=>{for(const e of t||[])"rejected"===e.status&&o(e.reason);return e().catch(o)}))},b=[{path:"/error",component:()=>P((()=>import("./404-DYq3ki41.js")),__vite__mapDeps([0,1,2,3])),meta:{hidden:!0}}],L=(e,t)=>{const n=e.__vccOpts||e;for(const[r,o]of t)n[r]=o;return n},O={class:"container m-auto"},x={class:"container mx-auto"};const A=L({},[["render",function(e,a){const i=s("router-view");return n(),t("div",O,[a[0]||(a[0]=r("h1",{class:"mt-4 text-center font-bold font-size-[22px] c-primary"},"代码生成器",-1)),r("main",x,[o(i)]),a[1]||(a[1]=r("footer",{class:"my-4 text-center"},[r("p",null,"© 2025 Bunny.保留所有权利.")],-1))])}]]),j=[...[{path:"/redirect",component:A,meta:{hidden:!0},children:[{path:"/redirect/:path(.*)",component:()=>P((()=>import("./index-DwLjqHOd.js")),__vite__mapDeps([4,1,2]))}]}],...[{path:"/",name:"/",component:A,redirect:"/home",meta:{transition:"fade"},children:[{path:"/home",name:"home",component:()=>P((()=>import("./index-Dn1v0MTU.js")),__vite__mapDeps([5,1,2,6]))},{path:"/generator-code",name:"generatorCode",component:()=>P((()=>import("./index-DNjCtrgM.js")),__vite__mapDeps([7,1,2,6,8]))}]}],...b],k=a({history:i(),routes:j,scrollBehavior:()=>({left:0,top:0,behavior:"smooth"})}),S=c();const T={install(t){(e=>{e.use(k)})(t),function(e){S.use(l),e.use(S)}(t),(t=>{t.use(e)})(t)}};const I=L(d({setup(){window.$message=u()}}),[["render",function(e,t,n,r,o,s){return" "}]]);g(d({__name:"App",setup:e=>(e,t)=>{const r=s("router-view");return n(),m(p(f),null,{default:h((()=>[o(p(_),null,{default:h((()=>[o(I),o(p(y),null,{default:h((()=>[o(r,null,{default:h((({Component:e,route:t})=>[o(v,{name:t.meta.transition||"fade-transform",mode:"out-in"},{default:h((()=>[(n(),m(E(e),{key:t.path}))])),_:2},1032,["name"])])),_:1})])),_:1})])),_:1})])),_:1})}})).use(T).mount("#app");export{L as _};
|
File diff suppressed because one or more lines are too long
|
@ -1 +0,0 @@
|
|||
import{t as e,d as t,v as a,x as l,y as n,h as r,z as s,A as i,c as o,a as c,w as u,j as d,B as m,C as p,F as b,b as g,D as y,E as f,G as v}from"./vendor-BT0L8wkZ.js";import{u as h,g as k}from"./table-R7-h5oL5.js";function D(){const l=e(),n=e=>{l.replace({path:"/generator-code",query:{tableName:e.tableName}}).then()};return[{title:"序号",key:"no",titleAlign:"center",align:"center",render:(e,t)=>t+1},{title:"数据库名称",key:"tableCat",titleAlign:"center",align:"center",render:e=>t(a,{type:"primary"},{default:()=>[e.tableCat]})},{title:"表类型",key:"tableType",titleAlign:"center",align:"center",render:e=>t(a,null,{default:()=>[e.tableType]})},{title:"表名",key:"tableName",titleAlign:"center",align:"center",render:e=>t(a,{type:"info",onClick:()=>n(e)},{default:()=>[e.tableName]})},{title:"注释内容",key:"comment",titleAlign:"center",align:"center",render:e=>t(a,{type:"info",onClick:()=>n(e)},{default:()=>[e.comment]})}]}const L=({node:e,option:t})=>l(n,null,{trigger:()=>e,default:()=>t.comment}),N={class:"mt-2"},x=r({__name:"index",setup(e){const l=h(),{tableList:n,dbList:r,tableListLoading:x,currentDatabaseName:A}=s(l),_=e=>{l.currentDatabaseName=null!=e?e:void 0,l.getDatabaseTableList()},C=()=>{return e=this,t=null,a=function*(){const e=yield k();200===e.code&&(l.currentDatabaseName=e.data),yield l.getDatabaseTableList()},new Promise(((l,n)=>{var r=e=>{try{i(a.next(e))}catch(t){n(t)}},s=e=>{try{i(a.throw(e))}catch(t){n(t)}},i=e=>e.done?l(e.value):Promise.resolve(e.value).then(r,s);i((a=a.apply(e,t)).next())}));var e,t,a};return i((()=>{C(),l.getDatabaseList()})),(e,l)=>(c(),o(b,null,[t(d(m),{class:"my-2",title:"提示"},{default:u((()=>[g("p",null,[l[2]||(l[2]=y(" 点击 ")),t(d(a),null,{default:u((()=>l[0]||(l[0]=[y("表名")]))),_:1}),l[3]||(l[3]=y(" 或 ")),t(d(a),null,{default:u((()=>l[1]||(l[1]=[y("注释内容")]))),_:1}),l[4]||(l[4]=y(" 跳转 "))]),g("p",N,[l[5]||(l[5]=y(" 数据库共 ")),t(d(a),{type:"info"},{default:u((()=>[y(f(d(n).length),1)])),_:1}),l[6]||(l[6]=y(" 张表 "))]),t(d(v),{"on-update-value":_,options:d(r),"render-option":d(L),value:d(A),class:"mt-2 w-[200px]","clear-filter-after-select":"",clearable:"",placeholder:"选择数据库"},null,8,["options","render-option","value"])])),_:1}),t(d(p),{bordered:!0,columns:d(D)(),data:d(n),loading:d(x)},null,8,["columns","data","loading"])],64))}});export{x as default};
|
|
@ -1 +0,0 @@
|
|||
import{h as a,I as e,t as s,c as r,a as t}from"./vendor-BT0L8wkZ.js";const p=a({__name:"index",setup(a){const p=e(),n=s(),{params:o,query:u}=p,{path:c}=o;return n.replace({path:"/"+c,query:u}),(a,e)=>(t(),r("div"))}});export{p as default};
|
|
@ -1 +0,0 @@
|
|||
var e=(e,t,a)=>new Promise(((s,r)=>{var o=e=>{try{i(a.next(e))}catch(t){r(t)}},n=e=>{try{i(a.throw(e))}catch(t){r(t)}},i=e=>e.done?s(e.value):Promise.resolve(e.value).then(o,n);i((a=a.apply(e,t)).next())}));import{a7 as t,a8 as a,H as s}from"./vendor-BT0L8wkZ.js";const r=t.create({baseURL:"/api",timeout:5e4,headers:{"Content-Type":"application/json;charset=utf-8"},paramsSerializer:e=>a.stringify(e)});r.interceptors.request.use((e=>{const t=localStorage.getItem("accessToken");return t&&(e.headers.Authorization=t),e}),(e=>Promise.reject(e))),r.interceptors.response.use((e=>{if("blob"===e.config.responseType||"arraybuffer"===e.config.responseType)return e;if(200===e.status){const{code:t,message:a}=e.data;return 200!==t&&window.$message.error(a),e.data}return Promise.reject(e.data.message||"Error")}),(e=>{if(e.response.data){const{code:t,message:a}=e.response.data;500===t?window.$message.error(a):window.$message.error(a||"系统出错")}return Promise.reject(e.message)}));const o=()=>r({url:"/table/currentDatabaseName",method:"GET"}),n=s("tableStore",{state:()=>({currentDatabaseName:void 0,databaseInfoMeta:void 0,tableList:[],tableListLoading:!1,dbList:[]}),getters:{},actions:{getDatabaseInfoMeta(){return e(this,null,(function*(){const e=yield r({url:"/table/databaseInfoMetaData",method:"GET"});200===e.code&&(this.databaseInfoMeta=e.data)}))},getDatabaseList(){return e(this,null,(function*(){this.tableListLoading=!0;const e=yield r({url:"/table/databaseList",method:"GET"});if(200!==e.code)return void(this.tableListLoading=!1);const t=e.data.map((e=>({label:e.tableCat,value:e.tableCat,comment:e.comment})));t.unshift({label:"无",value:void 0,comment:"查询全部"}),this.dbList=t,this.tableListLoading=!1}))},getDatabaseTableList(){return e(this,null,(function*(){const e={dbName:this.currentDatabaseName},t=yield(a=e,r({url:"/table/databaseTableList",method:"get",params:a}));var a;this.tableList=t.data}))},getTableMetaData(t){return e(this,null,(function*(){const e=yield(a={tableName:t},r({url:"/table/tableMetaData",method:"get",params:a}));var a;return 200!==e.code?{}:e.data}))},getTableColumnInfo(t){return e(this,null,(function*(){const e=yield(a={tableName:t},r({url:"/table/tableColumnInfo",method:"get",params:a}));var a;return 200!==e.code?{}:e.data}))}}});export{o as g,r as s,n as u};
|
File diff suppressed because one or more lines are too long
Binary file not shown.
Before Width: | Height: | Size: 20 KiB |
|
@ -1,16 +0,0 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8"/>
|
||||
<link href="/favicon.ico" rel="icon" type="image/svg+xml"/>
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
|
||||
<title>代码生成器</title>
|
||||
<script type="module" crossorigin src="/static/js/index-BZjZ3Az-.js"></script>
|
||||
<link rel="modulepreload" crossorigin href="/static/js/vendor-BT0L8wkZ.js">
|
||||
<link rel="stylesheet" crossorigin href="/static/css/vendor-lSrybVH6.css">
|
||||
<link rel="stylesheet" crossorigin href="/static/css/index-B0-KdCP2.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,65 +0,0 @@
|
|||
package ${package}.controller;
|
||||
|
||||
import cn.bunny.dao.pojo.result.Result;
|
||||
import cn.bunny.dao.pojo.result.ResultCodeEnum;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import reactor.core.publisher.Mono;
|
||||
import cn.bunny.dao.pojo.result.PageResult;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* ${comment}表 前端控制器
|
||||
* </p>
|
||||
*
|
||||
* @author ${author}
|
||||
* @since ${date}
|
||||
*/
|
||||
@Tag(name = "${comment}" , description = "${comment}相关接口" )
|
||||
@RestController
|
||||
@RequestMapping("${requestMapping}/${classLowercaseName}" )
|
||||
public class ${classUppercaseName}Controller {
|
||||
|
||||
@Autowired
|
||||
private ${classUppercaseName}Service ${classLowercaseName}Service;
|
||||
|
||||
@Operation(summary = "分页查询${comment}" , description = "分页查询${comment}" )
|
||||
@GetMapping("get${classUppercaseName}List/{page}/{limit}" )
|
||||
public Result<PageResult<${classUppercaseName}Vo>> get${classUppercaseName}List(
|
||||
@Parameter(name = "page" , description = "当前页" , required = true)
|
||||
@PathVariable("page" ) Integer page,
|
||||
@Parameter(name = "limit" , description = "每页记录数" , required = true)
|
||||
@PathVariable("limit" ) Integer limit,
|
||||
${classUppercaseName}Dto dto) {
|
||||
Page<${classUppercaseName}> pageParams = new Page<>(page, limit);
|
||||
PageResult<${classUppercaseName}Vo> pageResult = ${classLowercaseName}Service.get${classUppercaseName}List(pageParams, dto);
|
||||
return Result.success(pageResult);
|
||||
}
|
||||
|
||||
@Operation(summary = "添加${comment}" , description = "添加${comment}" )
|
||||
@PostMapping("add${classUppercaseName}" )
|
||||
public Result<String> add${classUppercaseName}(@Valid @RequestBody ${classUppercaseName}AddDto dto) {
|
||||
${classLowercaseName}Service.add${classUppercaseName}(dto);
|
||||
return Result.success(ResultCodeEnum.ADD_SUCCESS);
|
||||
}
|
||||
|
||||
@Operation(summary = "更新${comment}" , description = "更新${comment}" )
|
||||
@PutMapping("update${classUppercaseName}" )
|
||||
public Result<String> update${classUppercaseName}(@Valid @RequestBody ${classUppercaseName}UpdateDto dto) {
|
||||
${classLowercaseName}Service.update${classUppercaseName}(dto);
|
||||
return Result.success(ResultCodeEnum.UPDATE_SUCCESS);
|
||||
}
|
||||
|
||||
@Operation(summary = "删除${comment}" , description = "删除${comment}" )
|
||||
@DeleteMapping("delete${classUppercaseName}" )
|
||||
public Result<String> delete${classUppercaseName}(@RequestBody List<Long> ids) {
|
||||
${classLowercaseName}Service.delete${classUppercaseName}(ids);
|
||||
return Result.success(ResultCodeEnum.DELETE_SUCCESS);
|
||||
}
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
package ${package}.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* ${comment} Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author ${author}
|
||||
* @since ${date}
|
||||
*/
|
||||
@Mapper
|
||||
public interface ${classUppercaseName}Mapper extends BaseMapper<${classUppercaseName}> {
|
||||
|
||||
/**
|
||||
* * 分页查询${comment}内容
|
||||
*
|
||||
* @param pageParams ${comment}分页参数
|
||||
* @param dto ${comment}查询表单
|
||||
* @return ${comment}分页结果
|
||||
*/
|
||||
IPage<${classUppercaseName}Vo> selectListByPage(@Param("page") Page<${classUppercaseName}> pageParams, @Param("dto") ${classUppercaseName}Dto dto);
|
||||
}
|
|
@ -1,36 +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="${package}.mapper.${classUppercaseName}Mapper">
|
||||
|
||||
<!-- 通用查询映射结果 -->
|
||||
<resultMap id="BaseResultMap" type="${classUppercaseName}">
|
||||
#foreach($field in ${columnInfoList})
|
||||
<id column="${field.columnName}" property="${field.fieldName}"/>
|
||||
#end
|
||||
</resultMap>
|
||||
|
||||
<!-- 通用查询结果列 -->
|
||||
<sql id="Base_Column_List">
|
||||
${baseColumnList}
|
||||
</sql>
|
||||
|
||||
<!-- 分页查询${comment}内容 -->
|
||||
<select id="selectListByPage" resultType="${voClassType}">
|
||||
select
|
||||
base.*,
|
||||
create_user.username as create_username,
|
||||
update_user.username as update_username
|
||||
from $tableName base
|
||||
left join sys_user create_user on create_user.id = base.create_user
|
||||
left join sys_user update_user on update_user.id = base.update_user
|
||||
<where>
|
||||
base.is_deleted = 0
|
||||
#foreach($field in $columnInfoList)
|
||||
<if test="dto.${field.fieldName} != null and dto.${field.fieldName} != ''">
|
||||
and base.${field.columnName} like CONCAT('%',#{dto.${field.fieldName}},'%')
|
||||
</if>
|
||||
#end
|
||||
</where>
|
||||
</select>
|
||||
|
||||
</mapper>
|
|
@ -1,79 +0,0 @@
|
|||
package ${package}.service.impl;
|
||||
|
||||
import cn.bunny.dao.pojo.result.PageResult;
|
||||
import ${package}.mapper.${classUppercaseName}Mapper;
|
||||
import ${package}.service.${classUppercaseName}Service;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* ${comment} 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author Bunny
|
||||
* @since ${date}
|
||||
*/
|
||||
@Service
|
||||
public class ${classUppercaseName}ServiceImpl extends ServiceImpl<${classUppercaseName}Mapper, ${classUppercaseName}> implements ${classUppercaseName}Service {
|
||||
|
||||
/**
|
||||
* * ${comment} 服务实现类
|
||||
*
|
||||
* @param pageParams ${comment}分页查询page对象
|
||||
* @param dto ${comment}分页查询对象
|
||||
* @return 查询分页${comment}返回对象
|
||||
*/
|
||||
@Override
|
||||
public PageResult<${classUppercaseName}Vo> get${classUppercaseName}List(Page<${classUppercaseName}> pageParams, ${classUppercaseName}Dto dto) {
|
||||
IPage<${classUppercaseName}Vo> page = baseMapper.selectListByPage(pageParams, dto);
|
||||
|
||||
return PageResult.<${classUppercaseName}Vo>builder()
|
||||
.list(page.getRecords())
|
||||
.pageNo(page.getCurrent())
|
||||
.pageSize(page.getSize())
|
||||
.total(page.getTotal())
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加${comment}
|
||||
*
|
||||
* @param dto ${comment}添加
|
||||
*/
|
||||
@Override
|
||||
public void add${classUppercaseName}(@Valid ${classUppercaseName}AddDto dto) {
|
||||
// 保存数据
|
||||
${classUppercaseName} ${classLowercaseName} =new ${classUppercaseName}();
|
||||
BeanUtils.copyProperties(dto, ${classLowercaseName});
|
||||
save(${classLowercaseName});
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新${comment}
|
||||
*
|
||||
* @param dto ${comment}更新
|
||||
*/
|
||||
@Override
|
||||
public void update${classUppercaseName}(@Valid ${classUppercaseName}UpdateDto dto) {
|
||||
// 更新内容
|
||||
${classUppercaseName} ${classLowercaseName} =new ${classUppercaseName}();
|
||||
BeanUtils.copyProperties(dto, ${classLowercaseName});
|
||||
updateById(${classLowercaseName});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除|批量删除${comment}
|
||||
*
|
||||
* @param ids 删除id列表
|
||||
*/
|
||||
@Override
|
||||
public void delete${classUppercaseName}(List<Long> ids) {
|
||||
removeByIds(ids);
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue