Commit c5f29f18d386d2dcc564e8f8842257eed2225904
Merge remote-tracking branch 'origin/master' into dev
Showing
9 changed files
with
35 additions
and
17 deletions
pom.xml
| @@ -29,7 +29,7 @@ | @@ -29,7 +29,7 @@ | ||
| 29 | <url>https://github.com/YunaiV/ruoyi-vue-pro</url> | 29 | <url>https://github.com/YunaiV/ruoyi-vue-pro</url> |
| 30 | 30 | ||
| 31 | <properties> | 31 | <properties> |
| 32 | - <revision>1.6.5-snapshot</revision> | 32 | + <revision>1.6.6-snapshot</revision> |
| 33 | <!-- Maven 相关 --> | 33 | <!-- Maven 相关 --> |
| 34 | <java.version>1.8</java.version> | 34 | <java.version>1.8</java.version> |
| 35 | <maven.compiler.source>${java.version}</maven.compiler.source> | 35 | <maven.compiler.source>${java.version}</maven.compiler.source> |
yudao-dependencies/pom.xml
| @@ -14,7 +14,7 @@ | @@ -14,7 +14,7 @@ | ||
| 14 | <url>https://github.com/YunaiV/ruoyi-vue-pro</url> | 14 | <url>https://github.com/YunaiV/ruoyi-vue-pro</url> |
| 15 | 15 | ||
| 16 | <properties> | 16 | <properties> |
| 17 | - <revision>1.6.5-snapshot</revision> | 17 | + <revision>1.6.6-snapshot</revision> |
| 18 | <!-- 统一依赖管理 --> | 18 | <!-- 统一依赖管理 --> |
| 19 | <spring.boot.version>2.7.7</spring.boot.version> | 19 | <spring.boot.version>2.7.7</spring.boot.version> |
| 20 | <!-- Web 相关 --> | 20 | <!-- Web 相关 --> |
yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClient.java
| @@ -9,10 +9,11 @@ import io.minio.*; | @@ -9,10 +9,11 @@ import io.minio.*; | ||
| 9 | import java.io.ByteArrayInputStream; | 9 | import java.io.ByteArrayInputStream; |
| 10 | 10 | ||
| 11 | import static cn.iocoder.yudao.framework.file.core.client.s3.S3FileClientConfig.ENDPOINT_ALIYUN; | 11 | import static cn.iocoder.yudao.framework.file.core.client.s3.S3FileClientConfig.ENDPOINT_ALIYUN; |
| 12 | +import static cn.iocoder.yudao.framework.file.core.client.s3.S3FileClientConfig.ENDPOINT_TENCENT; | ||
| 12 | 13 | ||
| 13 | /** | 14 | /** |
| 14 | * 基于 S3 协议的文件客户端,实现 MinIO、阿里云、腾讯云、七牛云、华为云等云服务 | 15 | * 基于 S3 协议的文件客户端,实现 MinIO、阿里云、腾讯云、七牛云、华为云等云服务 |
| 15 | - * | 16 | + * <p> |
| 16 | * S3 协议的客户端,采用亚马逊提供的 software.amazon.awssdk.s3 库 | 17 | * S3 协议的客户端,采用亚马逊提供的 software.amazon.awssdk.s3 库 |
| 17 | * | 18 | * |
| 18 | * @author 芋道源码 | 19 | * @author 芋道源码 |
| @@ -78,6 +79,11 @@ public class S3FileClient extends AbstractFileClient<S3FileClientConfig> { | @@ -78,6 +79,11 @@ public class S3FileClient extends AbstractFileClient<S3FileClientConfig> { | ||
| 78 | .replaceAll("-internal", "")// 去除内网 Endpoint 的后缀 | 79 | .replaceAll("-internal", "")// 去除内网 Endpoint 的后缀 |
| 79 | .replaceAll("https://", ""); | 80 | .replaceAll("https://", ""); |
| 80 | } | 81 | } |
| 82 | + // 腾讯云必须有 region,否则会报错 | ||
| 83 | + if (config.getEndpoint().contains(ENDPOINT_TENCENT)) { | ||
| 84 | + return StrUtil.subAfter(config.getEndpoint(), ".cos.", false) | ||
| 85 | + .replaceAll("." + ENDPOINT_TENCENT, ""); // 去除 Endpoint | ||
| 86 | + } | ||
| 81 | return null; | 87 | return null; |
| 82 | } | 88 | } |
| 83 | 89 |
yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClientConfig.java
| @@ -19,6 +19,7 @@ public class S3FileClientConfig implements FileClientConfig { | @@ -19,6 +19,7 @@ public class S3FileClientConfig implements FileClientConfig { | ||
| 19 | 19 | ||
| 20 | public static final String ENDPOINT_QINIU = "qiniucs.com"; | 20 | public static final String ENDPOINT_QINIU = "qiniucs.com"; |
| 21 | public static final String ENDPOINT_ALIYUN = "aliyuncs.com"; | 21 | public static final String ENDPOINT_ALIYUN = "aliyuncs.com"; |
| 22 | + public static final String ENDPOINT_TENCENT = "myqcloud.com"; | ||
| 22 | 23 | ||
| 23 | /** | 24 | /** |
| 24 | * 节点地址 | 25 | * 节点地址 |
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/ConfigController.java
| @@ -75,7 +75,7 @@ public class ConfigController { | @@ -75,7 +75,7 @@ public class ConfigController { | ||
| 75 | if (config == null) { | 75 | if (config == null) { |
| 76 | return null; | 76 | return null; |
| 77 | } | 77 | } |
| 78 | - if (config.getVisible()) { | 78 | + if (!config.getVisible()) { |
| 79 | throw ServiceExceptionUtil.exception(ErrorCodeConstants.CONFIG_GET_VALUE_ERROR_IF_VISIBLE); | 79 | throw ServiceExceptionUtil.exception(ErrorCodeConstants.CONFIG_GET_VALUE_ERROR_IF_VISIBLE); |
| 80 | } | 80 | } |
| 81 | return success(config.getValue()); | 81 | return success(config.getValue()); |
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/dal/mysql/file/FileContentDAOImpl.java
| 1 | package cn.iocoder.yudao.module.infra.dal.mysql.file; | 1 | package cn.iocoder.yudao.module.infra.dal.mysql.file; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.collection.CollUtil; | ||
| 3 | import cn.iocoder.yudao.framework.file.core.client.db.DBFileContentFrameworkDAO; | 4 | import cn.iocoder.yudao.framework.file.core.client.db.DBFileContentFrameworkDAO; |
| 4 | import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileContentDO; | 5 | import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileContentDO; |
| 5 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | 6 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| 6 | import org.springframework.stereotype.Repository; | 7 | import org.springframework.stereotype.Repository; |
| 7 | 8 | ||
| 8 | import javax.annotation.Resource; | 9 | import javax.annotation.Resource; |
| 10 | +import java.util.List; | ||
| 11 | +import java.util.Optional; | ||
| 9 | 12 | ||
| 10 | @Repository | 13 | @Repository |
| 11 | public class FileContentDAOImpl implements DBFileContentFrameworkDAO { | 14 | public class FileContentDAOImpl implements DBFileContentFrameworkDAO { |
| @@ -27,9 +30,11 @@ public class FileContentDAOImpl implements DBFileContentFrameworkDAO { | @@ -27,9 +30,11 @@ public class FileContentDAOImpl implements DBFileContentFrameworkDAO { | ||
| 27 | 30 | ||
| 28 | @Override | 31 | @Override |
| 29 | public byte[] selectContent(Long configId, String path) { | 32 | public byte[] selectContent(Long configId, String path) { |
| 30 | - FileContentDO fileContentDO = fileContentMapper.selectOne( | ||
| 31 | - buildQuery(configId, path).select(FileContentDO::getContent)); | ||
| 32 | - return fileContentDO != null ? fileContentDO.getContent() : null; | 33 | + List<FileContentDO> list = fileContentMapper.selectList( |
| 34 | + buildQuery(configId, path).select(FileContentDO::getContent).orderByDesc(FileContentDO::getId)); | ||
| 35 | + return Optional.ofNullable(CollUtil.getFirst(list)) | ||
| 36 | + .map(FileContentDO::getContent) | ||
| 37 | + .orElse(null); | ||
| 33 | } | 38 | } |
| 34 | 39 | ||
| 35 | private LambdaQueryWrapper<FileContentDO> buildQuery(Long configId, String path) { | 40 | private LambdaQueryWrapper<FileContentDO> buildQuery(Long configId, String path) { |
yudao-ui-admin-vue3/package.json
| 1 | { | 1 | { |
| 2 | "name": "yudao-ui-admin-vue3", | 2 | "name": "yudao-ui-admin-vue3", |
| 3 | - "version": "1.6.5-snapshot.1901", | 3 | + "version": "1.6.6-snapshot.1901", |
| 4 | "description": "基于vue3、vite4、element-plus、typesScript", | 4 | "description": "基于vue3、vite4、element-plus、typesScript", |
| 5 | "author": "xingyu", | 5 | "author": "xingyu", |
| 6 | "private": false, | 6 | "private": false, |
yudao-ui-admin/package.json
yudao-ui-admin/src/views/infra/file/index.vue
| 1 | <template> | 1 | <template> |
| 2 | <div class="app-container"> | 2 | <div class="app-container"> |
| 3 | - <doc-alert title="上传下载" url="https://doc.iocoder.cn/file/" /> | 3 | + <doc-alert title="上传下载" url="https://doc.iocoder.cn/file/"/> |
| 4 | <!-- 搜索工作栏 --> | 4 | <!-- 搜索工作栏 --> |
| 5 | <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px"> | 5 | <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px"> |
| 6 | <el-form-item label="文件路径" prop="path"> | 6 | <el-form-item label="文件路径" prop="path"> |
| 7 | <el-input v-model="queryParams.path" placeholder="请输入文件路径" clearable @keyup.enter.native="handleQuery"/> | 7 | <el-input v-model="queryParams.path" placeholder="请输入文件路径" clearable @keyup.enter.native="handleQuery"/> |
| 8 | </el-form-item> | 8 | </el-form-item> |
| 9 | <el-form-item label="创建时间" prop="createTime"> | 9 | <el-form-item label="创建时间" prop="createTime"> |
| 10 | - <el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange" | ||
| 11 | - range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" /> | 10 | + <el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" |
| 11 | + type="daterange" | ||
| 12 | + range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" | ||
| 13 | + :default-time="['00:00:00', '23:59:59']"/> | ||
| 12 | </el-form-item> | 14 | </el-form-item> |
| 13 | <el-form-item> | 15 | <el-form-item> |
| 14 | <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button> | 16 | <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button> |
| @@ -35,6 +37,9 @@ | @@ -35,6 +37,9 @@ | ||
| 35 | <template v-slot="scope"> | 37 | <template v-slot="scope"> |
| 36 | <image-preview v-if="scope.row.type&&scope.row.type.indexOf('image/') === 0" :src="scope.row.url" | 38 | <image-preview v-if="scope.row.type&&scope.row.type.indexOf('image/') === 0" :src="scope.row.url" |
| 37 | :width="'100px'"></image-preview> | 39 | :width="'100px'"></image-preview> |
| 40 | + <video v-else-if="scope.row.type&&scope.row.type.indexOf('video/') === 0" :width="'100px'"> | ||
| 41 | + <source :src="scope.row.url"/> | ||
| 42 | + </video> | ||
| 38 | <i v-else>无法预览,点击 | 43 | <i v-else>无法预览,点击 |
| 39 | <el-link type="primary" :underline="false" style="font-size:12px;vertical-align: baseline;" target="_blank" | 44 | <el-link type="primary" :underline="false" style="font-size:12px;vertical-align: baseline;" target="_blank" |
| 40 | :href="getFileUrl + scope.row.configId + '/get/' + scope.row.path">下载 | 45 | :href="getFileUrl + scope.row.configId + '/get/' + scope.row.path">下载 |
| @@ -118,7 +123,7 @@ export default { | @@ -118,7 +123,7 @@ export default { | ||
| 118 | title: "", // 弹出层标题 | 123 | title: "", // 弹出层标题 |
| 119 | isUploading: false, // 是否禁用上传 | 124 | isUploading: false, // 是否禁用上传 |
| 120 | url: process.env.VUE_APP_BASE_API + "/admin-api/infra/file/upload", // 请求地址 | 125 | url: process.env.VUE_APP_BASE_API + "/admin-api/infra/file/upload", // 请求地址 |
| 121 | - headers: { Authorization: "Bearer " + getAccessToken() }, // 设置上传的请求头部 | 126 | + headers: {Authorization: "Bearer " + getAccessToken()}, // 设置上传的请求头部 |
| 122 | data: {} // 上传的额外数据,用于文件名 | 127 | data: {} // 上传的额外数据,用于文件名 |
| 123 | }, | 128 | }, |
| 124 | }; | 129 | }; |
| @@ -189,19 +194,20 @@ export default { | @@ -189,19 +194,20 @@ export default { | ||
| 189 | /** 删除按钮操作 */ | 194 | /** 删除按钮操作 */ |
| 190 | handleDelete(row) { | 195 | handleDelete(row) { |
| 191 | const id = row.id; | 196 | const id = row.id; |
| 192 | - this.$modal.confirm('是否确认删除文件编号为"' + id + '"的数据项?').then(function() { | 197 | + this.$modal.confirm('是否确认删除文件编号为"' + id + '"的数据项?').then(function () { |
| 193 | return deleteFile(id); | 198 | return deleteFile(id); |
| 194 | }).then(() => { | 199 | }).then(() => { |
| 195 | this.getList(); | 200 | this.getList(); |
| 196 | this.$modal.msgSuccess("删除成功"); | 201 | this.$modal.msgSuccess("删除成功"); |
| 197 | - }).catch(() => {}); | 202 | + }).catch(() => { |
| 203 | + }); | ||
| 198 | }, | 204 | }, |
| 199 | // 用户昵称展示 | 205 | // 用户昵称展示 |
| 200 | sizeFormat(row, column) { | 206 | sizeFormat(row, column) { |
| 201 | - const unitArr = ["Bytes","KB","MB","GB","TB","PB","EB","ZB","YB"]; | 207 | + const unitArr = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]; |
| 202 | const srcSize = parseFloat(row.size); | 208 | const srcSize = parseFloat(row.size); |
| 203 | const index = Math.floor(Math.log(srcSize) / Math.log(1024)); | 209 | const index = Math.floor(Math.log(srcSize) / Math.log(1024)); |
| 204 | - let size =srcSize/Math.pow(1024,index); | 210 | + let size = srcSize / Math.pow(1024, index); |
| 205 | size = size.toFixed(2);//保留的小数位数 | 211 | size = size.toFixed(2);//保留的小数位数 |
| 206 | return size + ' ' + unitArr[index]; | 212 | return size + ' ' + unitArr[index]; |
| 207 | }, | 213 | }, |