mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2024-11-22 15:21:53 +08:00
增加文件服务的展示
This commit is contained in:
parent
daa38661d2
commit
cee1aa3e60
@ -50,6 +50,7 @@
|
||||
| --- | --- | --- |
|
||||
| 🚀 | 配置管理 | 对系统动态配置常用参数,支持 SpringBoot 加载 |
|
||||
| | 定时任务 | 在线(添加、修改、删除)任务调度包含执行结果日志 |
|
||||
| 🚀 | 文件服务 | 支持本地文件存储,同时支持兼容 Amazon S3 协议的云服务、开源组件 |
|
||||
| 🚀 | API 日志 | 包括 RESTful API 访问日志、异常日志两部分,方便排查 API 相关的问题 |
|
||||
| | MySQL 监控 | 监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈 |
|
||||
| | Redis 监控 |监控 Redis 数据库的使用情况,使用的 Redis Key 管理 |
|
||||
@ -64,7 +65,6 @@
|
||||
计划新增:
|
||||
* 工作流
|
||||
* 错误码
|
||||
* 文件服务
|
||||
|
||||
### 研发工具
|
||||
|
||||
|
26
pom.xml
26
pom.xml
@ -40,8 +40,8 @@
|
||||
<skywalking.version>8.3.0</skywalking.version>
|
||||
<spring-boot-admin.version>2.3.1</spring-boot-admin.version>
|
||||
<!-- 工具类相关 -->
|
||||
<mapstruct.version>1.4.2.Final</mapstruct.version>
|
||||
<lombok-mapstruct-binding.version>0.2.0</lombok-mapstruct-binding.version>
|
||||
<lombok.version>1.16.14</lombok.version>
|
||||
<mapstruct.version>1.4.1.Final</mapstruct.version>
|
||||
<hutool.version>5.5.6</hutool.version>
|
||||
<easyexcel.verion>2.2.7</easyexcel.verion>
|
||||
<velocity.version>2.2</velocity.version>
|
||||
@ -227,14 +227,13 @@
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
<version>${lombok.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mapstruct</groupId>
|
||||
<artifactId>mapstruct</artifactId> <!-- use mapstruct-jdk8 for Java 8 or higher -->
|
||||
<version>${mapstruct.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mapstruct</groupId>
|
||||
@ -246,13 +245,6 @@
|
||||
<groupId>org.mapstruct</groupId>
|
||||
<artifactId>mapstruct-jdk8</artifactId>
|
||||
<version>${mapstruct.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok-mapstruct-binding</artifactId>
|
||||
<version>${lombok-mapstruct-binding.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@ -331,6 +323,18 @@
|
||||
<configuration>
|
||||
<source>${java.version}</source> <!-- or higher, depending on your project -->
|
||||
<target>${java.version}</target> <!-- or higher, depending on your project -->
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>org.mapstruct</groupId>
|
||||
<artifactId>mapstruct-processor</artifactId>
|
||||
<version>${mapstruct.version}</version>
|
||||
</path>
|
||||
<path>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>${lombok.version}</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
18
ruoyi-ui/src/api/infra/file.js
Normal file
18
ruoyi-ui/src/api/infra/file.js
Normal file
@ -0,0 +1,18 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 删除文件
|
||||
export function deleteFile(id) {
|
||||
return request({
|
||||
url: '/infra/file/delete?id=' + id,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
// 获得文件分页
|
||||
export function getFilePage(query) {
|
||||
return request({
|
||||
url: '/infra/file/page',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
202
ruoyi-ui/src/views/infra/file/index.vue
Normal file
202
ruoyi-ui/src/views/infra/file/index.vue
Normal file
@ -0,0 +1,202 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="文件路径" prop="id">
|
||||
<el-input v-model="queryParams.id" placeholder="请输入文件路径" clearable size="small" @keyup.enter.native="handleQuery"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="文件类型" prop="type">
|
||||
<el-select v-model="queryParams.type" placeholder="请选择文件类型" clearable size="small">
|
||||
<el-option label="请选择字典生成" value="" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建时间">
|
||||
<el-date-picker v-model="dateRangeCreateTime" size="small" style="width: 240px" value-format="yyyy-MM-dd"
|
||||
type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 操作工具栏 -->
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd">上传文件</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- 列表 -->
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="文件路径" align="center" prop="id" width="300" />
|
||||
<el-table-column label="文件类型" align="center" prop="type" width="80" />
|
||||
<el-table-column label="文件内容" align="center" prop="content">
|
||||
<template slot-scope="scope">
|
||||
<img v-if="scope.row.type === 'jpg' || scope.row.type === 'png' || scope.row.type === 'gif'"
|
||||
width="200px" :src="getFileUrl + scope.row.id">
|
||||
<i v-else>非图片,无法预览</i>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template slot-scope="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['infra:file:delete']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"/>
|
||||
|
||||
<!-- 对话框(添加 / 修改) -->
|
||||
<el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
|
||||
<el-upload ref="upload" :limit="1" accept=".jpg, .png, .gif" :auto-upload="false" drag
|
||||
:headers="upload.headers" :action="upload.url" :data="upload.data" :disabled="upload.isUploading"
|
||||
:on-change="handleFileChange"
|
||||
:on-progress="handleFileUploadProgress"
|
||||
:on-success="handleFileSuccess">
|
||||
<i class="el-icon-upload"></i>
|
||||
<div class="el-upload__text">
|
||||
将文件拖到此处,或 <em>点击上传</em>
|
||||
</div>
|
||||
<div class="el-upload__tip" style="color:red" slot="tip">提示:仅允许导入 jpg、png、gif 格式文件!</div>
|
||||
</el-upload>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitFileForm">确 定</el-button>
|
||||
<el-button @click="upload.open = false">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { deleteFile, getFilePage } from "@/api/infra/file";
|
||||
import {getToken} from "@/utils/auth";
|
||||
|
||||
export default {
|
||||
name: "File",
|
||||
data() {
|
||||
return {
|
||||
getFileUrl: process.env.VUE_APP_BASE_API + '/api/infra/file/get/',
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 文件列表
|
||||
list: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
dateRangeCreateTime: [],
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
id: null,
|
||||
type: null,
|
||||
},
|
||||
// 用户导入参数
|
||||
upload: {
|
||||
open: false, // 是否显示弹出层
|
||||
title: "", // 弹出层标题
|
||||
isUploading: false, // 是否禁用上传
|
||||
url: process.env.VUE_APP_BASE_API + '/api/' + "/infra/file/upload", // 请求地址
|
||||
headers: { Authorization: "Bearer " + getToken() }, // 设置上传的请求头部
|
||||
data: {} // 上传的额外数据,用于文件名
|
||||
},
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
// 处理查询参数
|
||||
let params = {...this.queryParams};
|
||||
this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime');
|
||||
// 执行查询
|
||||
getFilePage(params).then(response => {
|
||||
this.list = response.data.list;
|
||||
this.total = response.data.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 取消按钮 */
|
||||
cancel() {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
/** 表单重置 */
|
||||
reset() {
|
||||
this.form = {
|
||||
content: undefined,
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNo = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.dateRangeCreateTime = [];
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.upload.open = true;
|
||||
this.upload.title = "上传文件";
|
||||
},
|
||||
/** 处理上传的文件发生变化 */
|
||||
handleFileChange(file, fileList) {
|
||||
this.upload.data.path = file.name;
|
||||
},
|
||||
/** 处理文件上传中 */
|
||||
handleFileUploadProgress(event, file, fileList) {
|
||||
this.upload.isUploading = true; // 禁止修改
|
||||
},
|
||||
/** 发起文件上窜 */
|
||||
submitFileForm() {
|
||||
this.$refs.upload.submit();
|
||||
},
|
||||
/** 文件上传成功处理 */
|
||||
handleFileSuccess(response, file, fileList) {
|
||||
// 清理
|
||||
this.upload.open = false;
|
||||
this.upload.isUploading = false;
|
||||
this.$refs.upload.clearFiles();
|
||||
// 提示成功,并刷新
|
||||
this.msgSuccess("上传成功");
|
||||
this.getList();
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const id = row.id;
|
||||
this.$confirm('是否确认删除文件编号为"' + id + '"的数据项?', "警告", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(function() {
|
||||
return deleteFile(id);
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.msgSuccess("删除成功");
|
||||
})
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
File diff suppressed because one or more lines are too long
@ -1,6 +1,6 @@
|
||||
package cn.iocoder.dashboard.framework.file.config;
|
||||
|
||||
import cn.iocoder.dashboard.modules.system.controller.common.SysFileController;
|
||||
import cn.iocoder.dashboard.modules.infra.controller.file.InfFileController;
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
@ -13,7 +13,7 @@ import javax.validation.constraints.NotNull;
|
||||
public class FileProperties {
|
||||
|
||||
/**
|
||||
* 对应 {@link SysFileController#}
|
||||
* 对应 {@link InfFileController#}
|
||||
*/
|
||||
@NotNull(message = "基础文件路径不能为空")
|
||||
private String basePath;
|
||||
|
@ -134,7 +134,7 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
|
||||
// 静态资源,可匿名访问
|
||||
.antMatchers(HttpMethod.GET, "/*.html", "/**/*.html", "/**/*.css", "/**/*.js").permitAll()
|
||||
// 文件的获取接口,可匿名访问
|
||||
.antMatchers(webProperties.getApiPrefix() + "/system/file/get/**").anonymous()
|
||||
.antMatchers(webProperties.getApiPrefix() + "/infra/file/get/**").anonymous()
|
||||
// Swagger 接口文档
|
||||
.antMatchers("/swagger-ui.html").anonymous()
|
||||
.antMatchers("/swagger-resources/**").anonymous()
|
||||
|
@ -1,9 +1,13 @@
|
||||
package cn.iocoder.dashboard.modules.system.controller.common;
|
||||
package cn.iocoder.dashboard.modules.infra.controller.file;
|
||||
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.iocoder.dashboard.common.pojo.CommonResult;
|
||||
import cn.iocoder.dashboard.modules.system.dal.dataobject.common.SysFileDO;
|
||||
import cn.iocoder.dashboard.modules.system.service.common.SysFileService;
|
||||
import cn.iocoder.dashboard.common.pojo.PageResult;
|
||||
import cn.iocoder.dashboard.modules.infra.controller.file.vo.InfFilePageReqVO;
|
||||
import cn.iocoder.dashboard.modules.infra.controller.file.vo.InfFileRespVO;
|
||||
import cn.iocoder.dashboard.modules.infra.convert.file.InfFileConvert;
|
||||
import cn.iocoder.dashboard.modules.infra.dal.dataobject.file.InfFileDO;
|
||||
import cn.iocoder.dashboard.modules.infra.service.file.InfFileService;
|
||||
import cn.iocoder.dashboard.util.servlet.ServletUtils;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
@ -11,40 +15,53 @@ import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.io.IOException;
|
||||
|
||||
import static cn.iocoder.dashboard.common.pojo.CommonResult.success;
|
||||
|
||||
@Api(tags = "文件存储")
|
||||
@RestController
|
||||
@RequestMapping("/system/file")
|
||||
@RequestMapping("/infra/file")
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class SysFileController {
|
||||
public class InfFileController {
|
||||
|
||||
@Resource
|
||||
private SysFileService fileService;
|
||||
private InfFileService fileService;
|
||||
|
||||
@PostMapping("/upload")
|
||||
@ApiOperation("上传文件")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "path", value = "文件附件", required = true, dataTypeClass = MultipartFile.class),
|
||||
@ApiImplicitParam(name = "path", value = "文件路径", required = true, example = "yudaoyuanma.png", dataTypeClass = Long.class)
|
||||
@ApiImplicitParam(name = "file", value = "文件附件", required = true, dataTypeClass = MultipartFile.class),
|
||||
@ApiImplicitParam(name = "path", value = "文件路径", required = false, example = "yudaoyuanma.png", dataTypeClass = String.class)
|
||||
})
|
||||
@PostMapping("/upload")
|
||||
public CommonResult<String> uploadFile(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam("path") String path) throws IOException {
|
||||
return success(fileService.createFile(path, IoUtil.readBytes(file.getInputStream())));
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@ApiOperation("删除文件")
|
||||
@ApiImplicitParam(name = "id", value = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('infra:file:delete')")
|
||||
public CommonResult<Boolean> deleteFile(@RequestParam("id") String id) {
|
||||
fileService.deleteFile(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get/{path}")
|
||||
@ApiOperation("下载文件")
|
||||
@ApiImplicitParam(name = "path", value = "文件附件", required = true, dataTypeClass = MultipartFile.class)
|
||||
@GetMapping("/get/{path}")
|
||||
public void getFile(HttpServletResponse response, @PathVariable("path") String path) throws IOException {
|
||||
SysFileDO file = fileService.getFile(path);
|
||||
InfFileDO file = fileService.getFile(path);
|
||||
if (file == null) {
|
||||
log.warn("[getFile][path({}) 文件不存在]", path);
|
||||
response.setStatus(HttpStatus.NOT_FOUND.value());
|
||||
@ -53,4 +70,12 @@ public class SysFileController {
|
||||
ServletUtils.writeAttachment(response, path, file.getContent());
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@ApiOperation("获得文件分页")
|
||||
@PreAuthorize("@ss.hasPermission('infra:file:query')")
|
||||
public CommonResult<PageResult<InfFileRespVO>> getFilePage(@Valid InfFilePageReqVO pageVO) {
|
||||
PageResult<InfFileDO> pageResult = fileService.getFilePage(pageVO);
|
||||
return success(InfFileConvert.INSTANCE.convertPage(pageResult));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package cn.iocoder.dashboard.modules.infra.controller.file.vo;
|
||||
|
||||
import cn.iocoder.dashboard.common.pojo.PageParam;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@ApiModel("文件分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class InfFilePageReqVO extends PageParam {
|
||||
|
||||
@ApiModelProperty(value = "文件路径", example = "yudao", notes = "模糊匹配")
|
||||
private String id;
|
||||
|
||||
@ApiModelProperty(value = "文件类型", example = "jpg", notes = "模糊匹配")
|
||||
private String type;
|
||||
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@ApiModelProperty(value = "开始创建时间")
|
||||
private Date beginCreateTime;
|
||||
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
@ApiModelProperty(value = "结束创建时间")
|
||||
private Date endCreateTime;
|
||||
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package cn.iocoder.dashboard.modules.infra.controller.file.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@ApiModel(value = "文件 Response VO", description = "不返回 content 字段,太大")
|
||||
@Data
|
||||
public class InfFileRespVO {
|
||||
|
||||
@ApiModelProperty(value = "文件路径", required = true, example = "yudao.jpg")
|
||||
private String id;
|
||||
|
||||
@ApiModelProperty(value = "文件类型", required = true, example = "jpg")
|
||||
private String type;
|
||||
|
||||
@ApiModelProperty(value = "创建时间", required = true)
|
||||
private Date createTime;
|
||||
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package cn.iocoder.dashboard.modules.infra.convert.file;
|
||||
|
||||
import cn.iocoder.dashboard.common.pojo.PageResult;
|
||||
import cn.iocoder.dashboard.modules.infra.controller.file.vo.InfFileRespVO;
|
||||
import cn.iocoder.dashboard.modules.infra.dal.dataobject.file.InfFileDO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
@Mapper
|
||||
public interface InfFileConvert {
|
||||
|
||||
InfFileConvert INSTANCE = Mappers.getMapper(InfFileConvert.class);
|
||||
|
||||
InfFileRespVO convert(InfFileDO bean);
|
||||
|
||||
PageResult<InfFileRespVO> convertPage(PageResult<InfFileDO> page);
|
||||
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package cn.iocoder.dashboard.modules.infra.dal.dataobject.file;
|
||||
|
||||
import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.*;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* 文件表
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
@TableName("inf_file")
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class InfFileDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 文件路径
|
||||
*/
|
||||
@TableId(type = IdType.INPUT)
|
||||
private String id;
|
||||
/**
|
||||
* 文件类型
|
||||
*
|
||||
* 通过 {@link cn.hutool.core.io.FileTypeUtil#getType(InputStream)} 获取
|
||||
*/
|
||||
@TableField(value = "`type`")
|
||||
private String type;
|
||||
/**
|
||||
* 文件内容
|
||||
*/
|
||||
private byte[] content;
|
||||
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package cn.iocoder.dashboard.modules.infra.dal.mysql.file;
|
||||
|
||||
import cn.iocoder.dashboard.common.pojo.PageResult;
|
||||
import cn.iocoder.dashboard.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.dashboard.framework.mybatis.core.query.QueryWrapperX;
|
||||
import cn.iocoder.dashboard.modules.infra.controller.file.vo.InfFilePageReqVO;
|
||||
import cn.iocoder.dashboard.modules.infra.dal.dataobject.file.InfFileDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface InfFileMapper extends BaseMapperX<InfFileDO> {
|
||||
|
||||
default Integer selectCountById(String id) {
|
||||
return selectCount("id", id);
|
||||
}
|
||||
|
||||
default PageResult<InfFileDO> selectPage(InfFilePageReqVO reqVO) {
|
||||
return selectPage(reqVO, new QueryWrapperX<InfFileDO>()
|
||||
.likeIfPresent("id", reqVO.getId())
|
||||
.likeIfPresent("type", reqVO.getType())
|
||||
.betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
|
||||
.orderByDesc("create_time"));
|
||||
}
|
||||
|
||||
}
|
@ -27,4 +27,7 @@ public interface InfErrorCodeConstants {
|
||||
ErrorCode API_ERROR_LOG_NOT_FOUND = new ErrorCode(1001002000, "API 错误日志不存在");
|
||||
ErrorCode API_ERROR_LOG_PROCESSED = new ErrorCode(1001002001, "API 错误日志已处理");
|
||||
|
||||
// ========== 文件 1001003000 ==========
|
||||
ErrorCode FILE_NOT_EXISTS = new ErrorCode(1001003000, "文件不存在");
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,46 @@
|
||||
package cn.iocoder.dashboard.modules.infra.service.file;
|
||||
|
||||
import cn.iocoder.dashboard.common.pojo.PageResult;
|
||||
import cn.iocoder.dashboard.modules.infra.controller.file.vo.InfFilePageReqVO;
|
||||
import cn.iocoder.dashboard.modules.infra.dal.dataobject.file.InfFileDO;
|
||||
|
||||
/**
|
||||
* 文件 Service 接口
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface InfFileService {
|
||||
|
||||
/**
|
||||
* 保存文件,并返回文件的访问路径
|
||||
*
|
||||
* @param path 文件路径
|
||||
* @param content 文件内容
|
||||
* @return 文件路径
|
||||
*/
|
||||
String createFile(String path, byte[] content);
|
||||
|
||||
/**
|
||||
* 删除文件
|
||||
*
|
||||
* @param id 编号
|
||||
*/
|
||||
void deleteFile(String id);
|
||||
|
||||
/**
|
||||
* 获得文件
|
||||
*
|
||||
* @param path 文件路径
|
||||
* @return 文件
|
||||
*/
|
||||
InfFileDO getFile(String path);
|
||||
|
||||
/**
|
||||
* 获得文件分页
|
||||
*
|
||||
* @param pageReqVO 分页查询
|
||||
* @return 文件分页
|
||||
*/
|
||||
PageResult<InfFileDO> getFilePage(InfFilePageReqVO pageReqVO);
|
||||
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
package cn.iocoder.dashboard.modules.infra.service.file.impl;
|
||||
|
||||
import cn.hutool.core.io.FileTypeUtil;
|
||||
import cn.iocoder.dashboard.common.pojo.PageResult;
|
||||
import cn.iocoder.dashboard.framework.file.config.FileProperties;
|
||||
import cn.iocoder.dashboard.modules.infra.controller.file.vo.InfFilePageReqVO;
|
||||
import cn.iocoder.dashboard.modules.infra.dal.dataobject.file.InfFileDO;
|
||||
import cn.iocoder.dashboard.modules.infra.dal.mysql.file.InfFileMapper;
|
||||
import cn.iocoder.dashboard.modules.infra.service.file.InfFileService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.ByteArrayInputStream;
|
||||
|
||||
import static cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.dashboard.modules.infra.enums.InfErrorCodeConstants.FILE_NOT_EXISTS;
|
||||
import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.FILE_PATH_EXISTS;
|
||||
|
||||
/**
|
||||
* 文件 Service 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Service
|
||||
public class InfFileServiceImpl implements InfFileService {
|
||||
|
||||
@Resource
|
||||
private InfFileMapper fileMapper;
|
||||
|
||||
@Resource
|
||||
private FileProperties fileProperties;
|
||||
|
||||
@Override
|
||||
public String createFile(String path, byte[] content) {
|
||||
if (fileMapper.selectCountById(path) > 0) {
|
||||
throw exception(FILE_PATH_EXISTS);
|
||||
}
|
||||
// 保存到数据库
|
||||
InfFileDO file = new InfFileDO();
|
||||
file.setId(path);
|
||||
file.setType(FileTypeUtil.getType(new ByteArrayInputStream(content)));
|
||||
file.setContent(content);
|
||||
fileMapper.insert(file);
|
||||
// 拼接路径返回
|
||||
return fileProperties.getBasePath() + path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteFile(String id) {
|
||||
// 校验存在
|
||||
this.validateFileExists(id);
|
||||
// 更新
|
||||
fileMapper.deleteById(id);
|
||||
}
|
||||
|
||||
private void validateFileExists(String id) {
|
||||
if (fileMapper.selectById(id) == null) {
|
||||
throw exception(FILE_NOT_EXISTS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InfFileDO getFile(String path) {
|
||||
return fileMapper.selectById(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<InfFileDO> getFilePage(InfFilePageReqVO pageReqVO) {
|
||||
return fileMapper.selectPage(pageReqVO);
|
||||
}
|
||||
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
package cn.iocoder.dashboard.modules.system.dal.dataobject.common;
|
||||
|
||||
import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 文件表
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
@TableName("sys_file")
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class SysFileDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 文件路径
|
||||
*/
|
||||
@TableId(type = IdType.INPUT)
|
||||
private String id;
|
||||
/**
|
||||
* 文件内容
|
||||
*/
|
||||
private byte[] content;
|
||||
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
package cn.iocoder.dashboard.modules.system.dal.mysql.common;
|
||||
|
||||
import cn.iocoder.dashboard.modules.system.dal.dataobject.common.SysFileDO;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface SysFileMapper extends BaseMapper<SysFileDO> {
|
||||
|
||||
default Integer selectCountById(String id) {
|
||||
return selectCount(new QueryWrapper<SysFileDO>().eq("id", id));
|
||||
}
|
||||
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
package cn.iocoder.dashboard.modules.system.service.common;
|
||||
|
||||
import cn.iocoder.dashboard.modules.system.dal.dataobject.common.SysFileDO;
|
||||
|
||||
/**
|
||||
* 文件 Service 接口
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface SysFileService {
|
||||
|
||||
/**
|
||||
* 保存文件,并返回文件的访问路径
|
||||
*
|
||||
* @param path 文件路径
|
||||
* @param content 文件内容
|
||||
* @return 文件路径
|
||||
*/
|
||||
String createFile(String path, byte[] content);
|
||||
|
||||
/**
|
||||
* 获得文件
|
||||
*
|
||||
* @param path 文件路径
|
||||
* @return 文件
|
||||
*/
|
||||
SysFileDO getFile(String path);
|
||||
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
package cn.iocoder.dashboard.modules.system.service.common.impl;
|
||||
|
||||
import cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil;
|
||||
import cn.iocoder.dashboard.framework.file.config.FileProperties;
|
||||
import cn.iocoder.dashboard.modules.system.dal.dataobject.common.SysFileDO;
|
||||
import cn.iocoder.dashboard.modules.system.dal.mysql.common.SysFileMapper;
|
||||
import cn.iocoder.dashboard.modules.system.service.common.SysFileService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.FILE_PATH_EXISTS;
|
||||
|
||||
/**
|
||||
* 文件 Service 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Service
|
||||
public class SysFileServiceImpl implements SysFileService {
|
||||
|
||||
@Resource
|
||||
private SysFileMapper fileMapper;
|
||||
|
||||
@Resource
|
||||
private FileProperties fileProperties;
|
||||
|
||||
@Override
|
||||
public String createFile(String path, byte[] content) {
|
||||
if (fileMapper.selectCountById(path) > 0) {
|
||||
throw ServiceExceptionUtil.exception(FILE_PATH_EXISTS);
|
||||
}
|
||||
// 保存到数据库
|
||||
SysFileDO file = new SysFileDO();
|
||||
file.setId(path);
|
||||
file.setContent(content);
|
||||
fileMapper.insert(file);
|
||||
// 拼接路径返回
|
||||
return fileProperties.getBasePath() + path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SysFileDO getFile(String path) {
|
||||
return fileMapper.selectById(path);
|
||||
}
|
||||
|
||||
}
|
@ -99,6 +99,7 @@ public class ToolCodegenBuilder {
|
||||
.put(String.class.getSimpleName(), Sets.newHashSet("tinytext", "text", "mediumtext", "longtext", // 长文本
|
||||
"char", "varchar", "nvarchar", "varchar2")) // 短文本
|
||||
.put(Date.class.getSimpleName(), Sets.newHashSet("datetime", "time", "date", "timestamp"))
|
||||
.put("byte[]", Sets.newHashSet("blob"))
|
||||
.build();
|
||||
|
||||
static {
|
||||
|
@ -152,7 +152,7 @@ yudao:
|
||||
width: 160
|
||||
height: 60
|
||||
file:
|
||||
base-path: http://127.0.0.1:${server.port}/${yudao.web.api-prefix}/file/get/
|
||||
base-path: http://127.0.0.1:${server.port}/${yudao.web.api-prefix}/infra/file/get/
|
||||
codegen:
|
||||
base-package: ${yudao.info.base-package}
|
||||
db-schemas: ${spring.datasource.name}
|
||||
|
@ -152,7 +152,7 @@ yudao:
|
||||
width: 160
|
||||
height: 60
|
||||
file:
|
||||
base-path: http://127.0.0.1:${server.port}/${yudao.web.api-prefix}/file/get/
|
||||
base-path: http://127.0.0.1:${server.port}/${yudao.web.api-prefix}/infra/file/get/
|
||||
codegen:
|
||||
base-package: ${yudao.info.base-package}
|
||||
db-schemas: ${spring.datasource.name}
|
||||
|
@ -16,6 +16,7 @@ import ${basePackage}.modules.${table.moduleName}.service.${table.businessName}.
|
||||
|
||||
import ${ServiceExceptionUtilClassName};
|
||||
|
||||
import static cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static ${basePackage}.modules.${table.moduleName}.enums.${simpleModuleName_upperFirst}ErrorCodeConstants.*;
|
||||
|
||||
/**
|
||||
@ -58,7 +59,7 @@ public class ${table.className}ServiceImpl implements ${table.className}Service
|
||||
|
||||
private void validate${simpleClassName}Exists(${primaryColumn.javaType} id) {
|
||||
if (${classNameVar}Mapper.selectById(id) == null) {
|
||||
throw ServiceExceptionUtil.exception(${simpleClassName_underlineCase.toUpperCase()}_NOT_EXISTS);
|
||||
throw exception(${simpleClassName_underlineCase.toUpperCase()}_NOT_EXISTS);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,13 +1,11 @@
|
||||
package ${basePackage}.modules.${table.moduleName}.service.${table.businessName};
|
||||
|
||||
import ${basePackage}.BaseSpringBootUnitTest;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import cn.iocoder.dashboard.BaseSpringBootUnitTest;
|
||||
import ${basePackage}.BaseDbUnitTest;
|
||||
import ${basePackage}.modules.${table.moduleName}.service.${table.businessName}.impl.${table.className}ServiceImpl;
|
||||
import ${basePackage}.modules.${table.moduleName}.controller.${table.businessName}.vo.*;
|
||||
import ${basePackage}.modules.${table.moduleName}.dal.dataobject.${table.businessName}.${table.className}DO;
|
||||
@ -16,6 +14,7 @@ import ${basePackage}.util.object.ObjectUtils;
|
||||
import ${PageResultClassName};
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import java.util.*;
|
||||
|
||||
import static cn.hutool.core.util.RandomUtil.*;
|
||||
@ -64,7 +63,8 @@ import static org.mockito.Mockito.*;
|
||||
*
|
||||
* @author ${table.author}
|
||||
*/
|
||||
public class ${table.className}ServiceTest extends BaseSpringBootUnitTest {
|
||||
@Import(${table.className}ServiceImpl.class)
|
||||
public class ${table.className}ServiceTest extends BaseDbUnitTest {
|
||||
|
||||
@Resource
|
||||
private ${table.className}ServiceImpl ${classNameVar}Service;
|
||||
@ -78,7 +78,7 @@ public class ${table.className}ServiceTest extends BaseSpringBootUnitTest {
|
||||
${table.className}CreateReqVO reqVO = randomPojo(${table.className}CreateReqVO.class);
|
||||
|
||||
// 调用
|
||||
Long ${classNameVar}Id = ${classNameVar}Service.create${simpleClassName}(reqVO);
|
||||
${primaryColumn.javaType} ${classNameVar}Id = ${classNameVar}Service.create${simpleClassName}(reqVO);
|
||||
// 断言
|
||||
assertNotNull(${classNameVar}Id);
|
||||
// 校验记录的属性是否正确
|
||||
@ -118,7 +118,7 @@ public class ${table.className}ServiceTest extends BaseSpringBootUnitTest {
|
||||
${table.className}DO db${simpleClassName} = randomPojo(${table.className}DO.class);
|
||||
${classNameVar}Mapper.insert(db${simpleClassName});// @Sql: 先插入出一条存在的数据
|
||||
// 准备参数
|
||||
Long id = db${simpleClassName}.getId();
|
||||
${primaryColumn.javaType} id = db${simpleClassName}.getId();
|
||||
|
||||
// 调用
|
||||
${classNameVar}Service.delete${simpleClassName}(id);
|
||||
@ -129,7 +129,7 @@ public class ${table.className}ServiceTest extends BaseSpringBootUnitTest {
|
||||
@Test
|
||||
public void testDelete${simpleClassName}_notExists() {
|
||||
// 准备参数
|
||||
Long id = randomLongId();
|
||||
${primaryColumn.javaType} id = random${primaryColumn.javaType}Id();
|
||||
|
||||
// 调用, 并断言异常
|
||||
assertServiceException(() -> ${classNameVar}Service.delete${simpleClassName}(id), ${simpleClassName_underlineCase.toUpperCase()}_NOT_EXISTS);
|
||||
|
@ -4,7 +4,7 @@ INSERT INTO `sys_menu`(
|
||||
`path`, `icon`, `component`, `status`
|
||||
)
|
||||
VALUES (
|
||||
'${table.classComment}管理', '${permissionPrefix}:query', 2, 0, ${table.parentMenuId},
|
||||
'${table.classComment}管理', '', 2, 0, ${table.parentMenuId},
|
||||
'${simpleClassName_strikeCase}', '', '${table.moduleName}/${classNameVar}/index', 0
|
||||
);
|
||||
|
||||
@ -12,8 +12,8 @@ VALUES (
|
||||
SELECT @parentId := LAST_INSERT_ID();
|
||||
|
||||
-- 按钮 SQL
|
||||
#set ($functionNames = ['创建', '更新', '删除', '导出'])
|
||||
#set ($functionOps = ['create', 'update', 'delete', 'export'])
|
||||
#set ($functionNames = ['查询', '创建', '更新', '删除', '导出'])
|
||||
#set ($functionOps = ['query', 'create', 'update', 'delete', 'export'])
|
||||
#foreach ($functionName in $functionNames)
|
||||
#set ($index = $foreach.count - 1)
|
||||
INSERT INTO `sys_menu`(
|
||||
@ -21,7 +21,7 @@ INSERT INTO `sys_menu`(
|
||||
`path`, `icon`, `component`, `status`
|
||||
)
|
||||
VALUES (
|
||||
'${table.tableComment}${functionName}', '${permissionPrefix}:${functionOps.get($index)}', 3, $foreach.count, @parentId,
|
||||
'${table.classComment}${functionName}', '${permissionPrefix}:${functionOps.get($index)}', 3, $foreach.count, @parentId,
|
||||
'', '', '', 0
|
||||
);
|
||||
#end
|
||||
|
@ -68,7 +68,7 @@
|
||||
#if ($column.javaType == "Date")## 时间类型
|
||||
<el-table-column label="${comment}" align="center" prop="${javaField}" width="180">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ parseTime(scope.row.${javaField}, '{y}-{m}-{d}') }}</span>
|
||||
<span>{{ parseTime(scope.row.${javaField}) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
#elseif("" != $column.dictType)## 数据字典
|
||||
|
@ -0,0 +1,126 @@
|
||||
package cn.iocoder.dashboard.modules.infra.service.file;
|
||||
|
||||
import cn.hutool.core.io.resource.ResourceUtil;
|
||||
import cn.iocoder.dashboard.BaseDbUnitTest;
|
||||
import cn.iocoder.dashboard.common.pojo.PageResult;
|
||||
import cn.iocoder.dashboard.framework.file.config.FileProperties;
|
||||
import cn.iocoder.dashboard.modules.infra.controller.file.vo.InfFilePageReqVO;
|
||||
import cn.iocoder.dashboard.modules.infra.dal.dataobject.file.InfFileDO;
|
||||
import cn.iocoder.dashboard.modules.infra.dal.mysql.file.InfFileMapper;
|
||||
import cn.iocoder.dashboard.modules.infra.service.file.impl.InfFileServiceImpl;
|
||||
import cn.iocoder.dashboard.util.object.ObjectUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import static cn.iocoder.dashboard.modules.infra.enums.InfErrorCodeConstants.FILE_NOT_EXISTS;
|
||||
import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.FILE_PATH_EXISTS;
|
||||
import static cn.iocoder.dashboard.util.AssertUtils.assertPojoEquals;
|
||||
import static cn.iocoder.dashboard.util.AssertUtils.assertServiceException;
|
||||
import static cn.iocoder.dashboard.util.RandomUtils.randomPojo;
|
||||
import static cn.iocoder.dashboard.util.RandomUtils.randomString;
|
||||
import static cn.iocoder.dashboard.util.date.DateUtils.buildTime;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
@Import({InfFileServiceImpl.class, FileProperties.class})
|
||||
public class InfFileServiceTest extends BaseDbUnitTest {
|
||||
|
||||
@Resource
|
||||
private InfFileServiceImpl fileService;
|
||||
|
||||
@Resource
|
||||
private FileProperties fileProperties;
|
||||
@Resource
|
||||
private InfFileMapper fileMapper;
|
||||
|
||||
@Test
|
||||
public void testCreateFile_success() {
|
||||
// 准备参数
|
||||
String path = randomString();
|
||||
byte[] content = ResourceUtil.readBytes("file/erweima.jpg");
|
||||
|
||||
// 调用
|
||||
String url = fileService.createFile(path, content);
|
||||
// 断言
|
||||
assertEquals(fileProperties.getBasePath() + path, url);
|
||||
// 校验数据
|
||||
InfFileDO file = fileMapper.selectById(path);
|
||||
assertEquals(path, file.getId());
|
||||
assertEquals("jpg", file.getType());
|
||||
assertArrayEquals(content, file.getContent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateFile_exists() {
|
||||
// mock 数据
|
||||
InfFileDO dbFile = randomPojo(InfFileDO.class);
|
||||
fileMapper.insert(dbFile);
|
||||
// 准备参数
|
||||
String path = dbFile.getId(); // 模拟已存在
|
||||
byte[] content = ResourceUtil.readBytes("file/erweima.jpg");
|
||||
|
||||
// 调用,并断言异常
|
||||
assertServiceException(() -> fileService.createFile(path, content), FILE_PATH_EXISTS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteFile_success() {
|
||||
// mock 数据
|
||||
InfFileDO dbFile = randomPojo(InfFileDO.class);
|
||||
fileMapper.insert(dbFile);// @Sql: 先插入出一条存在的数据
|
||||
// 准备参数
|
||||
String id = dbFile.getId();
|
||||
|
||||
// 调用
|
||||
fileService.deleteFile(id);
|
||||
// 校验数据不存在了
|
||||
assertNull(fileMapper.selectById(id));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteFile_notExists() {
|
||||
// 准备参数
|
||||
String id = randomString();
|
||||
|
||||
// 调用, 并断言异常
|
||||
assertServiceException(() -> fileService.deleteFile(id), FILE_NOT_EXISTS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetFilePage() {
|
||||
// mock 数据
|
||||
InfFileDO dbFile = randomPojo(InfFileDO.class, o -> { // 等会查询到
|
||||
o.setId("yudao");
|
||||
o.setType("jpg");
|
||||
o.setCreateTime(buildTime(2021, 1, 15));
|
||||
});
|
||||
fileMapper.insert(dbFile);
|
||||
// 测试 id 不匹配
|
||||
fileMapper.insert(ObjectUtils.clone(dbFile, o -> o.setId("tudou")));
|
||||
// 测试 type 不匹配
|
||||
fileMapper.insert(ObjectUtils.clone(dbFile, o -> {
|
||||
o.setId("yudao02");
|
||||
o.setType("png");
|
||||
}));
|
||||
// 测试 createTime 不匹配
|
||||
fileMapper.insert(ObjectUtils.clone(dbFile, o -> {
|
||||
o.setId("yudao03");
|
||||
o.setCreateTime(buildTime(2020, 1, 15));
|
||||
}));
|
||||
// 准备参数
|
||||
InfFilePageReqVO reqVO = new InfFilePageReqVO();
|
||||
reqVO.setId("yudao");
|
||||
reqVO.setType("jp");
|
||||
reqVO.setBeginCreateTime(buildTime(2021, 1, 10));
|
||||
reqVO.setEndCreateTime(buildTime(2021, 1, 20));
|
||||
|
||||
// 调用
|
||||
PageResult<InfFileDO> pageResult = fileService.getFilePage(reqVO);
|
||||
// 断言
|
||||
assertEquals(1, pageResult.getTotal());
|
||||
assertEquals(1, pageResult.getList().size());
|
||||
assertPojoEquals(dbFile, pageResult.getList().get(0), "content");
|
||||
}
|
||||
|
||||
}
|
@ -2,7 +2,6 @@ package cn.iocoder.dashboard.modules.system.service.auth;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.iocoder.dashboard.BaseDbAndRedisUnitTest;
|
||||
import cn.iocoder.dashboard.framework.mybatis.core.query.QueryWrapperX;
|
||||
import cn.iocoder.dashboard.framework.security.config.SecurityProperties;
|
||||
import cn.iocoder.dashboard.modules.system.dal.dataobject.auth.SysUserSessionDO;
|
||||
import cn.iocoder.dashboard.modules.system.dal.mysql.auth.SysUserSessionMapper;
|
||||
@ -32,24 +31,24 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
* @version 1.0
|
||||
* @since <pre>3月 8, 2021</pre>
|
||||
*/
|
||||
@Import(
|
||||
SysUserSessionServiceImpl.class)
|
||||
@Import(SysUserSessionServiceImpl.class)
|
||||
public class SysUserSessionServiceImplTest extends BaseDbAndRedisUnitTest {
|
||||
|
||||
@Resource
|
||||
SysUserSessionServiceImpl sysUserSessionService;
|
||||
private SysUserSessionServiceImpl sysUserSessionService;
|
||||
@Resource
|
||||
SysUserSessionMapper sysUserSessionMapper;
|
||||
private SysUserSessionMapper sysUserSessionMapper;
|
||||
|
||||
@MockBean
|
||||
SecurityProperties securityProperties;
|
||||
private SecurityProperties securityProperties;
|
||||
@MockBean
|
||||
SysDeptServiceImpl sysDeptService;
|
||||
private SysDeptServiceImpl sysDeptService;
|
||||
@MockBean
|
||||
SysUserServiceImpl sysUserService;
|
||||
private SysUserServiceImpl sysUserService;
|
||||
@MockBean
|
||||
SysLoginLogServiceImpl sysLoginLogService;
|
||||
private SysLoginLogServiceImpl sysLoginLogService;
|
||||
@MockBean
|
||||
SysLoginUserRedisDAO sysLoginUserRedisDAO;
|
||||
private SysLoginUserRedisDAO sysLoginUserRedisDAO;
|
||||
|
||||
@Test
|
||||
public void testClearSessionTimeout_success() throws Exception {
|
||||
|
BIN
src/test/resources/file/erweima.jpg
Normal file
BIN
src/test/resources/file/erweima.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
@ -1,5 +1,6 @@
|
||||
-- inf 开头的 DB
|
||||
DELETE FROM "inf_config";
|
||||
DELETE FROM "inf_file";
|
||||
|
||||
-- sys 开头的 DB
|
||||
DELETE FROM "sys_dept";
|
||||
|
@ -17,6 +17,18 @@ CREATE TABLE IF NOT EXISTS "inf_config" (
|
||||
PRIMARY KEY ("id")
|
||||
) COMMENT '参数配置表';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "inf_file" (
|
||||
"id" varchar(188) NOT NULL,
|
||||
"type" varchar(63) DEFAULT NULL,
|
||||
"content" blob NOT NULL,
|
||||
"creator" varchar(64) DEFAULT '',
|
||||
"create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updater" varchar(64) DEFAULT '',
|
||||
"update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"deleted" bit NOT NULL DEFAULT FALSE,
|
||||
PRIMARY KEY ("id")
|
||||
) COMMENT '文件表';
|
||||
|
||||
-- sys 开头的 DB
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "sys_dept" (
|
||||
|
Loading…
Reference in New Issue
Block a user