feat: 文件管理适配详情、下载,音视频、图片文件允许在线打开

This commit is contained in:
Charles7c 2023-12-30 14:44:32 +08:00
parent c90361d7d9
commit 9a30da9334
16 changed files with 242 additions and 211 deletions

View File

@ -1,93 +0,0 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.charles7c.continew.admin.system.model.resp;
import java.io.Serial;
import lombok.Data;
import io.swagger.v3.oas.annotations.media.Schema;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import top.charles7c.continew.admin.system.enums.FileTypeEnum;
import top.charles7c.continew.starter.extension.crud.base.BaseDetailResp;
/**
* 文件详情信息
*
* @author Charles7c
* @since 2023/12/23 10:38
*/
@Data
@ExcelIgnoreUnannotated
@Schema(description = "文件详情信息")
public class FileDetailResp extends BaseDetailResp {
@Serial
private static final long serialVersionUID = 1L;
/**
* 名称
*/
@Schema(description = "名称")
@ExcelProperty(value = "名称")
private String name;
/**
* 大小字节
*/
@Schema(description = "大小(字节)")
@ExcelProperty(value = "大小(字节)")
private Long size;
/**
* URL
*/
@Schema(description = "URL")
@ExcelProperty(value = "URL")
private String url;
/**
* 扩展名
*/
@Schema(description = "扩展名")
@ExcelProperty(value = "扩展名")
private String extension;
/**
* MIME类型
*/
@Schema(description = "MIME类型")
@ExcelProperty(value = "MIME类型")
private String mimeType;
/**
* 类型
*/
@Schema(description = "类型")
@ExcelProperty(value = "类型")
private FileTypeEnum type;
/**
* 存储库ID
*/
@Schema(description = "存储库ID")
@ExcelProperty(value = "存储库ID")
private Long storageId;
}

View File

@ -17,14 +17,16 @@
package top.charles7c.continew.admin.system.model.resp;
import java.io.Serial;
import java.time.LocalDateTime;
import lombok.Data;
import io.swagger.v3.oas.annotations.media.Schema;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import top.charles7c.continew.admin.system.enums.FileTypeEnum;
import top.charles7c.continew.starter.extension.crud.base.BaseResp;
import top.charles7c.continew.starter.extension.crud.base.BaseDetailResp;
/**
* 文件信息
@ -33,8 +35,9 @@ import top.charles7c.continew.starter.extension.crud.base.BaseResp;
* @since 2023/12/23 10:38
*/
@Data
@Schema(description = "文件信息")
public class FileResp extends BaseResp {
@ExcelIgnoreUnannotated
@Schema(description = "文件详情信息")
public class FileResp extends BaseDetailResp {
@Serial
private static final long serialVersionUID = 1L;
@ -42,48 +45,49 @@ public class FileResp extends BaseResp {
/**
* 名称
*/
@Schema(description = "名称")
@Schema(description = "名称", example = "example")
@ExcelProperty(value = "名称")
private String name;
/**
* 大小字节
*/
@Schema(description = "大小(字节)")
@Schema(description = "大小(字节)", example = "4096")
@ExcelProperty(value = "大小(字节)")
private Long size;
/**
* URL
*/
@Schema(description = "URL")
@Schema(description = "URL", example = "https://examplebucket.oss-cn-hangzhou.aliyuncs.com/example/example.jpg")
@ExcelProperty(value = "URL")
private String url;
/**
* 扩展名
*/
@Schema(description = "扩展名")
@Schema(description = "扩展名", example = "jpg")
@ExcelProperty(value = "扩展名")
private String extension;
/**
* MIME类型
*/
@Schema(description = "MIME类型")
@ExcelProperty(value = "MIME类型")
private String mimeType;
/**
* 类型
*/
@Schema(description = "类型")
@Schema(description = "类型", type = "Integer", allowableValues = {"1", "2", "3", "4", "5"}, example = "2")
@ExcelProperty(value = "类型")
private FileTypeEnum type;
/**
* 存储库ID
* 存储库 ID
*/
@Schema(description = "存储库ID")
@Schema(description = "存储库ID", example = "1")
@ExcelProperty(value = "存储库ID")
private Long storageId;
/**
* 修改时间
*/
@Schema(description = "修改时间")
private LocalDateTime updateTime;
}

View File

@ -23,7 +23,6 @@ import org.springframework.web.multipart.MultipartFile;
import top.charles7c.continew.admin.system.model.query.FileQuery;
import top.charles7c.continew.admin.system.model.req.FileReq;
import top.charles7c.continew.admin.system.model.resp.FileDetailResp;
import top.charles7c.continew.admin.system.model.resp.FileResp;
import top.charles7c.continew.starter.extension.crud.base.BaseService;
@ -33,7 +32,7 @@ import top.charles7c.continew.starter.extension.crud.base.BaseService;
* @author Charles7c
* @since 2023/12/23 10:38
*/
public interface FileService extends BaseService<FileResp, FileDetailResp, FileQuery, FileReq> {
public interface FileService extends BaseService<FileResp, FileResp, FileQuery, FileReq> {
/**
* 上传到默认存储库

View File

@ -38,7 +38,6 @@ import top.charles7c.continew.admin.system.model.entity.FileDO;
import top.charles7c.continew.admin.system.model.entity.StorageDO;
import top.charles7c.continew.admin.system.model.query.FileQuery;
import top.charles7c.continew.admin.system.model.req.FileReq;
import top.charles7c.continew.admin.system.model.resp.FileDetailResp;
import top.charles7c.continew.admin.system.model.resp.FileResp;
import top.charles7c.continew.admin.system.model.resp.StorageDetailResp;
import top.charles7c.continew.admin.system.service.FileService;
@ -57,7 +56,7 @@ import top.charles7c.continew.starter.extension.crud.base.BaseServiceImpl;
@Slf4j
@Service
@RequiredArgsConstructor
public class FileServiceImpl extends BaseServiceImpl<FileMapper, FileDO, FileResp, FileDetailResp, FileQuery, FileReq>
public class FileServiceImpl extends BaseServiceImpl<FileMapper, FileDO, FileResp, FileResp, FileQuery, FileReq>
implements FileService {
@Resource

View File

@ -48,7 +48,8 @@
"pinia": "^2.1.7",
"query-string": "^8.1.0",
"sortablejs": "^1.15.1",
"v-viewer": "^1.6.4",
"v-viewer": "^3.0.10",
"viewerjs": "^1.11.6",
"vue": "3.3.7",
"vue-codemirror": "^6.1.1",
"vue-cropper": "^1.1.1",
@ -57,7 +58,7 @@
"vue-json-pretty": "^2.3.0",
"vue-router": "^4.2.5",
"vue3-colorpicker": "^2.2.3",
"xgplayer": "^3.0.11"
"xgplayer": "^2.31.6"
},
"devDependencies": {
"@arco-plugins/vite-vue": "^1.4.5",

View File

@ -60,8 +60,11 @@ dependencies:
specifier: ^1.15.1
version: 1.15.1
v-viewer:
specifier: ^1.6.4
version: 1.6.4
specifier: ^3.0.10
version: 3.0.11(vue@3.3.7)
viewerjs:
specifier: ^1.11.6
version: 1.11.6
vue:
specifier: 3.3.7
version: 3.3.7(typescript@5.3.3)
@ -87,8 +90,8 @@ dependencies:
specifier: ^2.2.3
version: 2.2.3(@aesoper/normal-utils@0.1.5)(@popperjs/core@2.11.8)(@vueuse/core@10.7.0)(gradient-parser@1.0.2)(lodash-es@4.17.21)(tinycolor2@1.6.0)(vue-types@4.2.1)(vue@3.3.7)
xgplayer:
specifier: ^3.0.11
version: 3.0.11(core-js@3.34.0)
specifier: ^2.31.6
version: 2.32.6
devDependencies:
'@arco-plugins/vite-vue':
@ -2073,6 +2076,11 @@ packages:
uri-js: 4.4.1
dev: true
/amdefine@1.0.1:
resolution: {integrity: sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==, tarball: https://registry.npmmirror.com/amdefine/-/amdefine-1.0.1.tgz}
engines: {node: '>=0.4.2'}
dev: false
/ansi-escapes@6.2.0:
resolution: {integrity: sha512-kzRaCqXnpzWs+3z5ABPQiVke+iq0KXkHo8xiWV4RPTi5Yli0l97BEQuhXV1s7+aSU/fu1kUuxgS4MsQ0fRuygw==, tarball: https://registry.npmmirror.com/ansi-escapes/-/ansi-escapes-6.2.0.tgz}
engines: {node: '>=14.16'}
@ -2923,11 +2931,6 @@ packages:
toggle-selection: 1.0.6
dev: false
/core-js@3.34.0:
resolution: {integrity: sha512-aDdvlDder8QmY91H88GzNi9EtQi2TjvQhpCX6B1v/dAZHU1AuLgHvRh54RiOerpEhEW46Tkf+vgAViB/CWC0ag==, tarball: https://registry.npmmirror.com/core-js/-/core-js-3.34.0.tgz}
requiresBuild: true
dev: false
/core-util-is@1.0.3:
resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==, tarball: https://registry.npmmirror.com/core-util-is/-/core-util-is-1.0.3.tgz}
dev: true
@ -3677,10 +3680,6 @@ packages:
robust-predicates: 3.0.2
dev: false
/delegate@3.2.0:
resolution: {integrity: sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==, tarball: https://registry.npmmirror.com/delegate/-/delegate-3.2.0.tgz}
dev: false
/dequal@2.0.3:
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==, tarball: https://registry.npmmirror.com/dequal/-/dequal-2.0.3.tgz}
engines: {node: '>=6'}
@ -3842,6 +3841,13 @@ packages:
resolution: {integrity: sha512-LN1gO7+u9xjU5oEScGFKvXhYf7Y/empUIIEAGBs1LzUq/rg5duiDrkuH5A2lQGd5jfMOb9X9usDa2oVXwJ0U/Q==, tarball: https://registry.npmmirror.com/downloadjs/-/downloadjs-1.4.7.tgz}
dev: false
/draggabilly@2.4.1:
resolution: {integrity: sha512-HHHLPEPZqRXIDQDFRFdK7RONZausNlJ4WkA73ST7Z6O2HPWttxFHVwHo8nccuDLzXWwiVKRVuc6fTkW+CQA++A==, tarball: https://registry.npmmirror.com/draggabilly/-/draggabilly-2.4.1.tgz}
dependencies:
get-size: 2.0.3
unidragger: 2.4.0
dev: false
/duplexer3@0.1.5:
resolution: {integrity: sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==, tarball: https://registry.npmmirror.com/duplexer3/-/duplexer3-0.1.5.tgz}
dev: true
@ -4509,6 +4515,12 @@ packages:
eslint-visitor-keys: 3.4.3
dev: true
/esprima@1.2.5:
resolution: {integrity: sha512-S9VbPDU0adFErpDai3qDkjq8+G05ONtKzcyNrPKg/ZKa+tf879nX2KexNU95b31UoTJjRLInNBHHHjFPoCd7lQ==, tarball: https://registry.npmmirror.com/esprima/-/esprima-1.2.5.tgz}
engines: {node: '>=0.4.0'}
hasBin: true
dev: false
/esprima@4.0.1:
resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==, tarball: https://registry.npmmirror.com/esprima/-/esprima-4.0.1.tgz}
engines: {node: '>=4'}
@ -4546,6 +4558,10 @@ packages:
engines: {node: '>= 0.6'}
dev: true
/ev-emitter@1.1.1:
resolution: {integrity: sha512-ipiDYhdQSCZ4hSbX4rMW+XzNKMD1prg/sTvoVmSLkuQ1MVlwjJQQA+sW8tMYR3BLUr9KjodFV4pvzunvRhd33Q==, tarball: https://registry.npmmirror.com/ev-emitter/-/ev-emitter-1.1.1.tgz}
dev: false
/event-emitter@0.3.5:
resolution: {integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==, tarball: https://registry.npmmirror.com/event-emitter/-/event-emitter-0.3.5.tgz}
dependencies:
@ -5021,6 +5037,14 @@ packages:
universalify: 2.0.0
dev: true
/fs-extra@5.0.0:
resolution: {integrity: sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==, tarball: https://registry.npmmirror.com/fs-extra/-/fs-extra-5.0.0.tgz}
dependencies:
graceful-fs: 4.2.11
jsonfile: 4.0.0
universalify: 0.1.2
dev: false
/fs-extra@7.0.1:
resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==, tarball: https://registry.npmmirror.com/fs-extra/-/fs-extra-7.0.1.tgz}
engines: {node: '>=6 <7 || >=8'}
@ -5059,6 +5083,13 @@ packages:
resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==, tarball: https://registry.npmmirror.com/functions-have-names/-/functions-have-names-1.2.3.tgz}
dev: true
/generate-source-map@0.0.5:
resolution: {integrity: sha512-jqiE7f3FEaeMcjnMSEYLjMa39bdx+RrrdfhxdJpMm9S/8IugHF4vLQLZ9sxHylWyxpsBILukC/l/7B0/O0zhNg==, tarball: https://registry.npmmirror.com/generate-source-map/-/generate-source-map-0.0.5.tgz}
dependencies:
esprima: 1.2.5
source-map: 0.1.43
dev: false
/gensync@1.0.0-beta.2:
resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==, tarball: https://registry.npmmirror.com/gensync/-/gensync-1.0.0-beta.2.tgz}
engines: {node: '>=6.9.0'}
@ -5090,6 +5121,10 @@ packages:
npm-conf: 1.1.3
dev: true
/get-size@2.0.3:
resolution: {integrity: sha512-lXNzT/h/dTjTxRbm9BXb+SGxxzkm97h/PCIKtlN/CBCxxmkkIVV21udumMS93MuVTDX583gqc94v3RjuHmI+2Q==, tarball: https://registry.npmmirror.com/get-size/-/get-size-2.0.3.tgz}
dev: false
/get-stdin@4.0.1:
resolution: {integrity: sha512-F5aQMywwJ2n85s4hJPTT9RPxGmubonuB10MNYo17/xph174n2MIR33HRguhzVag10O/npM7SPk73LMZNP+FaWw==, tarball: https://registry.npmmirror.com/get-stdin/-/get-stdin-4.0.1.tgz}
engines: {node: '>=0.10.0'}
@ -8904,6 +8939,13 @@ packages:
resolution: {integrity: sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==, tarball: https://registry.npmmirror.com/source-map-url/-/source-map-url-0.4.1.tgz}
deprecated: See https://github.com/lydell/source-map-url#deprecated
/source-map@0.1.43:
resolution: {integrity: sha512-VtCvB9SIQhk3aF6h+N85EaqIaBFIAfZ9Cu+NJHHVvc8BbEcnvDcFw6sqQ2dQrT6SlOrZq3tIvyD9+EGq/lJryQ==, tarball: https://registry.npmmirror.com/source-map/-/source-map-0.1.43.tgz}
engines: {node: '>=0.8.0'}
dependencies:
amdefine: 1.0.1
dev: false
/source-map@0.5.7:
resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==, tarball: https://registry.npmmirror.com/source-map/-/source-map-0.5.7.tgz}
engines: {node: '>=0.10.0'}
@ -9554,11 +9596,6 @@ packages:
resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==, tarball: https://registry.npmmirror.com/text-table/-/text-table-0.2.0.tgz}
dev: true
/throttle-debounce@2.3.0:
resolution: {integrity: sha512-H7oLPV0P7+jgvrk+6mwwwBDmxTaxnu9HMXmloNLXwnNO0ZxZ31Orah2n8lU1eMPvsaowP2CX+USCgyovXfdOFQ==, tarball: https://registry.npmmirror.com/throttle-debounce/-/throttle-debounce-2.3.0.tgz}
engines: {node: '>=8'}
dev: false
/through2@4.0.2:
resolution: {integrity: sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==, tarball: https://registry.npmmirror.com/through2/-/through2-4.0.2.tgz}
dependencies:
@ -9819,6 +9856,12 @@ packages:
xtend: 4.0.2
dev: true
/unidragger@2.4.0:
resolution: {integrity: sha512-MueZK2oXuGE6OAlGKIrSXK2zCq+8yb1QUZgqyTDCSJzvwYL0g2Llrad+TtoQTYxtFnNyxxSw0IMnKNIgEMia1w==, tarball: https://registry.npmmirror.com/unidragger/-/unidragger-2.4.0.tgz}
dependencies:
unipointer: 2.4.0
dev: false
/unified@7.1.0:
resolution: {integrity: sha512-lbk82UOIGuCEsZhPj8rNAkXSDXd6p0QLzIuSsCdxrqnqU56St4eyOB+AlXsVgVeRmetPTYydIuvFfpDIed8mqw==, tarball: https://registry.npmmirror.com/unified/-/unified-7.1.0.tgz}
dependencies:
@ -9841,6 +9884,12 @@ packages:
is-extendable: 0.1.1
set-value: 2.0.1
/unipointer@2.4.0:
resolution: {integrity: sha512-VjzDLPjGK7aYpQKH7bnDZS8X4axF5AFU/LQi+NQe1oyEHfaz6lWKhaQ7n4o7vJ1iJ4i2T0quCIfrQM139p05Sw==, tarball: https://registry.npmmirror.com/unipointer/-/unipointer-2.4.0.tgz}
dependencies:
ev-emitter: 1.1.1
dev: false
/uniq@1.0.1:
resolution: {integrity: sha512-Gw+zz50YNKPDKXs+9d+aKAjVwpjNwqzvNpLigIruT4HA9lMZNdMqs9x07kKHB/L9WRzqp4+DlTU5s4wG2esdoA==, tarball: https://registry.npmmirror.com/uniq/-/uniq-1.0.1.tgz}
dev: true
@ -10017,12 +10066,14 @@ packages:
sade: 1.8.1
dev: false
/v-viewer@1.6.4:
resolution: {integrity: sha512-LVkiUHpmsbsZXebeNXnu8krRCi5i2n07FeLFxoIVGhw8lVvTBO0ffpbDC6mLEuacCjrIh09HjIqpciwUtWE8lQ==, tarball: https://registry.npmmirror.com/v-viewer/-/v-viewer-1.6.4.tgz}
engines: {node: '>=4', npm: '>=3'}
/v-viewer@3.0.11(vue@3.3.7):
resolution: {integrity: sha512-E8LOdAxhzuktt4HB3PswVCccQ1Q1sYHYnLsS6zaJISpb5EvmAFs5sYNfXnDLFxVb5DQ82v4ZlGxkYlseXwWRJw==, tarball: https://registry.npmmirror.com/v-viewer/-/v-viewer-3.0.11.tgz}
peerDependencies:
vue: ^3.0.0
dependencies:
throttle-debounce: 2.3.0
lodash: 4.17.21
viewerjs: 1.11.6
vue: 3.3.7(typescript@5.3.3)
dev: false
/validate-npm-package-license@3.0.4:
@ -10480,26 +10531,25 @@ packages:
resolution: {integrity: sha512-GojqklwG8gpzOVEVki5KudKNoq7MbbjYZCbyWzEz7tyPA7eleiE0+ePwOWQQRb5fm86rD3S8Tc0tSFf3AOv50w==, tarball: https://registry.npmmirror.com/x-is-string/-/x-is-string-0.1.0.tgz}
dev: true
/xgplayer-subtitles@3.0.11(core-js@3.34.0):
resolution: {integrity: sha512-m/fk9TeeLuwqnryHTqo5SVVS3w9A27hHe7R1HxWQlk5ZZ5H2CxAXn4dv/PU+gI61DWG3sNkjftlq5duHJtdz2g==, tarball: https://registry.npmmirror.com/xgplayer-subtitles/-/xgplayer-subtitles-3.0.11.tgz}
peerDependencies:
core-js: '>=3.12.1'
/xgplayer-subtitles@1.0.19:
resolution: {integrity: sha512-ITvMTgnHD0uytWUYYoS3Qtz10T0o8W0YW3J7/GbfipeJQs4IiFyzhnvTXYB2KnZ6wRXLO6LrNhK9esY9iISJWA==, tarball: https://registry.npmmirror.com/xgplayer-subtitles/-/xgplayer-subtitles-1.0.19.tgz}
dependencies:
core-js: 3.34.0
eventemitter3: 4.0.7
generate-source-map: 0.0.5
dev: false
/xgplayer@3.0.11(core-js@3.34.0):
resolution: {integrity: sha512-n7qpUG46IVjcYWCFq9WLe4OQpIZvtT67lObu6RPgxbMm8IMGCscTVdbWQjRbgrlsvTVfes3zTfjyaymuS5g17g==, tarball: https://registry.npmmirror.com/xgplayer/-/xgplayer-3.0.11.tgz}
peerDependencies:
core-js: '>=3.12.1'
/xgplayer@2.32.6:
resolution: {integrity: sha512-ESwYYcG8SQciPaN43tZkN3r0dS/jQ5RtyxyGbxn2+qcKgZQ861M899xq8Cab/z6qVVX+/4eIsxDbm3lfYGYzvA==, tarball: https://registry.npmmirror.com/xgplayer/-/xgplayer-2.32.6.tgz}
hasBin: true
dependencies:
core-js: 3.34.0
chalk: 2.4.2
commander: 2.20.3
danmu.js: 1.1.13
delegate: 3.2.0
downloadjs: 1.4.7
eventemitter3: 4.0.7
xgplayer-subtitles: 3.0.11(core-js@3.34.0)
draggabilly: 2.4.1
event-emitter: 0.3.5
fs-extra: 5.0.0
xgplayer-subtitles: 1.0.19
dev: false
/xml-name-validator@4.0.0:

View File

@ -43,10 +43,6 @@ export function list(params: ListParam) {
});
}
export function get(id: string) {
return axios.get<FileItem>(`${BASE_URL}/${id}`);
}
export interface FileItemUpdate {
name: string;
}

View File

@ -0,0 +1,89 @@
<template>
<a-modal
v-model:visible="visible"
:title="title"
title-align="start"
width="90%"
modal-animation-name="el-fade"
:footer="false"
:modal-style="{ maxWidth: '300px' }"
@close="cancel"
>
<a-row justify="center" align="center">
<div style="height: 100px">
<FileImg :data="fileInfo" style="border-radius: 5px"></FileImg>
</div>
</a-row>
<a-row style="margin-top: 15px">
<a-descriptions :column="1" title="详细信息" layout="inline-vertical">
<a-descriptions-item :label="title">{{
formatFileSize(fileInfo.size)
}}</a-descriptions-item>
<a-descriptions-item label="创建时间">{{
fileInfo.createTime
}}</a-descriptions-item>
<a-descriptions-item label="修改时间">{{
fileInfo.updateTime
}}</a-descriptions-item>
</a-descriptions>
</a-row>
</a-modal>
</template>
<script setup lang="ts">
import { onMounted, ref } from 'vue';
import { FileItem } from '@/api/system/file';
import FileImg from '../../main/FileMain/FileImg.vue';
interface Props {
fileInfo: FileItem;
onClose: () => void;
}
const props = withDefaults(defineProps<Props>(), {});
const visible = ref(false);
const title = ref();
onMounted(() => {
title.value = `${props.fileInfo.name}.${props.fileInfo.extension}`;
visible.value = true;
});
const cancel = () => {
visible.value = false;
props.onClose();
};
const formatFileSize = (fileSize: number) => {
if (fileSize == null || fileSize === 0) {
return '0 Bytes';
}
const unitArr = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
let index = 0;
const srcSize = parseFloat(fileSize.toString());
index = Math.floor(Math.log(srcSize) / Math.log(1024));
const size = srcSize / 1024 ** index;
return `${size.toFixed(2)} ${unitArr[index]}`;
};
</script>
<style lang="less" scoped>
.label {
color: var(--color-text-2);
}
:deep(.arco-form-item) {
margin-bottom: 0;
}
:deep(.arco-form-item-label-col > label) {
white-space: nowrap;
}
:deep(.arco-descriptions-title) {
font-size: 14px;
}
:deep(.arco-descriptions-item-label-inline) {
font-size: 12px;
}
:deep(.arco-descriptions-item-value-inline) {
font-size: 12px;
margin-bottom: 10px;
}
</style>

View File

@ -1,8 +1,9 @@
<template>
<a-modal
v-model:visible="visible"
title="视频播放"
:title="title"
width="auto"
:footer="false"
draggable
@close="close"
>
@ -22,8 +23,10 @@
const props = withDefaults(defineProps<Props>(), {});
const visible = ref(false);
const title = ref();
onMounted(() => {
title.value = `${props.fileInfo.name}.${props.fileInfo.extension}`;
visible.value = true;
nextTick(() => {
// eslint-disable-next-line no-new
@ -34,6 +37,7 @@
autoplay: true,
closeVideoClick: true,
videoInit: true,
fitVideoSize: 'auto',
});
});
});

View File

@ -5,6 +5,7 @@ import ArcoVue from '@arco-design/web-vue';
import { FileItem } from '@/api/system/file';
import FileRenameModal from './FileRenameModal/index.vue';
import FileDetailModal from './FileDetailModal/index.vue';
import PreviewVideoModal from './PreviewVideoModal/index.vue';
import PreviewAudioModal from './PreviewAudioModal/index.vue';
@ -41,15 +42,22 @@ export function openFileRenameModal(fileItem: FileItem) {
return createModal<TFileOptions>(FileRenameModal, { fileInfo: fileItem });
}
/** 打开 详情 弹窗 */
export function openFileDetailModal(fileItem: FileItem) {
return createModal<TFileOptions>(FileDetailModal, { fileInfo: fileItem });
}
/** 预览 视频文件 弹窗 */
export function previewFileVideoModal(fileItem: FileItem) {
return createModal<TFileOptions>(PreviewVideoModal, { fileInfo: fileItem });
}
/** 预览 音频文件 弹窗 */
let fileAudioId = '';
let fileAudioId: string = '';
export function previewFileAudioModal(fileItem: FileItem) {
if (fileAudioId) return; // 防止重复打开
if (fileAudioId) {
fileAudioId = '';
}
fileAudioId = fileItem.id;
// eslint-disable-next-line consistent-return
return createModal<TFileOptions>(PreviewAudioModal, {

View File

@ -167,6 +167,9 @@
padding: 0 5px;
text-align: center;
box-sizing: border-box;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}

View File

@ -1,12 +1,13 @@
<template>
<img v-if="isImage" class="img" :src="props.data.url || ''" alt="" />
<svg-icon v-else :icon-class="getFileImg" style="height: 100%; width: 100%" />
<SvgIcon v-else :icon-class="getFileImg" style="height: 100%; width: 100%" />
</template>
<script setup lang="ts">
import { computed } from 'vue';
import { fileExtendNameIconMap, imageTypeList } from '@/constant/file';
import type { FileItem } from '@/api/system/file';
import { computed } from 'vue';
import SvgIcon from '@/components/svg-icon/index.vue';
interface Props {
data: FileItem;
@ -21,9 +22,6 @@
//
const getFileImg = computed<string>(() => {
// if (props.data?.isDir) {
// return fileExtendNameIconMap.dir || '';
// }
if (imageTypeList.includes(props.data.extension.toLowerCase())) {
return props.data.url || '';
}

View File

@ -8,29 +8,6 @@
<template #icon><svg-icon icon-class="menu-download" /></template>
<span>下载</span>
</GiOptionItem>
<a-popover
v-if="props.fileInfo.extension === 'zip'"
position="right"
:content-style="{ padding: 0, overflow: 'hidden', width: '150px' }"
:arrow-style="{ display: 'none' }"
>
<GiOptionItem more>
<template #icon><svg-icon icon-class="menu-zip" /></template>
<span>解压</span>
</GiOptionItem>
<template #content>
<GiOption>
<GiOptionItem @click="onClickItem('zip1')">
<template #icon><svg-icon icon-class="file-rar" /></template>
<span>解压到当前目录</span>
</GiOptionItem>
<GiOptionItem @click="onClickItem('zip2')">
<template #icon><svg-icon icon-class="file-rar" /></template>
<span>解压到其他目录</span>
</GiOptionItem>
</GiOption>
</template>
</a-popover>
<GiOptionItem @click="onClickItem('detail')">
<template #icon><svg-icon icon-class="menu-detail" /></template>
<span>详情</span>
@ -43,25 +20,14 @@
</template>
<script setup lang="ts">
import type { FileItem } from '@/api/system/file';
import GiOption from '@/components/gi-option/index.vue';
import GiOptionItem from '@/components/gi-option-item/index.vue';
interface Props {
fileInfo?: FileItem;
showClassStyle?: boolean;
}
const props = withDefaults(defineProps<Props>(), {
fileInfo: () => ({
id: '',
name: '',
size: 0,
url: '',
extension: '',
type: '',
updateTime: '',
}), //
withDefaults(defineProps<Props>(), {
showClassStyle: true,
});

View File

@ -73,7 +73,7 @@
:selected-file-ids="fileStore.selectedFileIds"
@click="handleClickFile"
@check="handleCheckFile"
@rightMenuClick="handleRightMenuClick"
@right-menu-click="handleRightMenuClick"
></FileGrid>
<!-- 文件列表-列表模式 -->
@ -82,7 +82,7 @@
:data="fileList"
:is-batch-mode="isBatchMode"
@click="handleClickFile"
@rightMenuClick="handleRightMenuClick"
@right-menu-click="handleRightMenuClick"
></FileList>
<a-empty v-show="!fileList.length"></a-empty>
@ -91,26 +91,27 @@
</template>
<script setup lang="ts">
import { Message, Modal, RequestOption } from '@arco-design/web-vue';
import { Modal, RequestOption } from '@arco-design/web-vue';
import { api as viewerApi } from 'v-viewer';
import { imageTypeList } from '@/constant/file';
import { useFileStore } from '@/store/modules/file';
import type { ListParam, FileItem } from '@/api/system/file';
import { list, del } from '@/api/system/file';
import { upload } from '@/api/common';
import { onBeforeRouteUpdate, useRoute, useRouter } from 'vue-router';
import { onBeforeRouteUpdate, useRoute } from 'vue-router';
import { getCurrentInstance, onMounted, reactive, ref, toRefs } from 'vue';
import FileGrid from './FileGrid.vue';
import FileList from './FileList.vue';
import {
openFileRenameModal,
openFileDetailModal,
previewFileVideoModal,
previewFileAudioModal,
} from '../../components/index';
import 'viewerjs/dist/viewer.css';
const { proxy } = getCurrentInstance() as any;
const route = useRoute();
const router = useRouter();
const fileStore = useFileStore();
const loading = ref(false);
//
@ -152,7 +153,6 @@
//
const handleClickFile = (item: FileItem) => {
Message.success(`点击了文件-${item.name}`);
if (imageTypeList.includes(item.extension)) {
if (item.url) {
const imgList: string[] = fileList.value
@ -196,11 +196,19 @@
},
});
}
if (mode === 'download') {
const link = document.createElement('a');
link.href = fileInfo.url;
link.download = fileInfo.name;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
if (mode === 'rename') {
openFileRenameModal(fileInfo);
}
if (mode === 'detail') {
// TODO
openFileDetailModal(fileInfo);
}
};

View File

@ -22,7 +22,6 @@ import org.springframework.web.bind.annotation.*;
import top.charles7c.continew.admin.system.model.query.FileQuery;
import top.charles7c.continew.admin.system.model.req.FileReq;
import top.charles7c.continew.admin.system.model.resp.FileDetailResp;
import top.charles7c.continew.admin.system.model.resp.FileResp;
import top.charles7c.continew.admin.system.service.FileService;
import top.charles7c.continew.starter.extension.crud.annotation.CrudRequestMapping;
@ -37,5 +36,5 @@ import top.charles7c.continew.starter.extension.crud.enums.Api;
*/
@Tag(name = "文件管理 API")
@RestController
@CrudRequestMapping(value = "/system/file", api = {Api.PAGE, Api.GET, Api.UPDATE, Api.DELETE})
public class FileController extends BaseController<FileService, FileResp, FileDetailResp, FileQuery, FileReq> {}
@CrudRequestMapping(value = "/system/file", api = {Api.PAGE, Api.UPDATE, Api.DELETE})
public class FileController extends BaseController<FileService, FileResp, FileResp, FileQuery, FileReq> {}