From 32960b1b012f43e676b4218590f5be87fdaa911c Mon Sep 17 00:00:00 2001 From: guoxin <371864209@qq.com> Date: Fri, 15 Sep 2023 18:06:52 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=EF=BC=9A=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E8=A1=A5=E5=BD=95=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/static/js/browser.js | 16 +- .../main/resources/static/js/common/common.js | 28 ++- .../common/layui/extend/uploader/uploader.js | 28 ++- .../controller/DirectoryController.java | 11 - .../controller/FIleRepairController.java | 174 +++++++++++++ .../bianmu/mapper/DirectoryMapper.java | 17 +- .../bianmu/service/DirectoryService.java | 4 +- .../service/impl/DirectoryServiceImpl.java | 7 + .../shandan/system/mapper/SysFileMapper.java | 13 +- .../service/impl/SysFileServiceImpl.java | 43 +--- .../system/utils/FileChunkUploadUtil.java | 2 +- .../resources/static/js/sys/file/dirUpload.js | 3 +- .../resources/static/js/sys/file/repair.js | 238 ++++++++++++++++++ .../resources/view/sys/file/fileRepair.html | 125 +++++++++ .../resources/view/sys/file/fileView.html | 2 + 15 files changed, 623 insertions(+), 88 deletions(-) create mode 100644 shandan-control/src/main/java/com/keyware/shandan/control/controller/FIleRepairController.java create mode 100644 shandan-system/src/main/resources/static/js/sys/file/repair.js create mode 100644 shandan-system/src/main/resources/view/sys/file/fileRepair.html diff --git a/shandan-browser/src/main/resources/static/js/browser.js b/shandan-browser/src/main/resources/static/js/browser.js index 261d2d1..161312f 100644 --- a/shandan-browser/src/main/resources/static/js/browser.js +++ b/shandan-browser/src/main/resources/static/js/browser.js @@ -625,7 +625,7 @@ class THeadSetLayer { exerciseData: data => data.exerciseData ? '是' : '否', resourceType: data => data.resourceType === 'file' ? '文件' : '数据库表', fileSize: data => { - return fileSizeFormat(data.fileSize, 'M'); + return Util.fileSizeFormat(data.fileSize, 'M'); } } @@ -650,18 +650,4 @@ class THeadSetLayer { cols.push(operateCol); return [cols]; } -} - -const units = ['B', 'K', 'M', 'G', 'T', 'P']; - -function fileSizeFormat(size, initUnit = 'B') { - initUnit = initUnit.toUpperCase(); - const i = units.indexOf(initUnit); - if (size > 1024 && i < units.length - 1) { - return fileSizeFormat(size / 1024, units[i + 1]); - } else if (size < 1 && i > 0) { - return fileSizeFormat(size * 1024, units[i - 1]); - } else { - return Math.round(size * 100) / 100 + initUnit; - } } \ No newline at end of file diff --git a/shandan-common/src/main/resources/static/js/common/common.js b/shandan-common/src/main/resources/static/js/common/common.js index ee14f84..9bf7ec9 100644 --- a/shandan-common/src/main/resources/static/js/common/common.js +++ b/shandan-common/src/main/resources/static/js/common/common.js @@ -464,7 +464,7 @@ commonUtil = { * @param loading 是否显示loading状态 * @returns {Promise} */ - get: (url, data, loading = true) => Util.send(url, data, 'get', loading), + get: (url, data = {}, loading = true) => Util.send(url, data, 'get', loading), /** * post请求 @@ -473,7 +473,7 @@ commonUtil = { * @param loading 是否显示loading状态 * @returns {Promise} */ - post: (url, data, loading = true) => Util.send(url, data, 'post', loading), + post: (url, data = {}, loading = true) => Util.send(url, data, 'post', loading), /** * 封装ajax异步请求 @@ -486,7 +486,7 @@ commonUtil = { send: (url, data, type = 'get', loading = true) => { if (loading) showLoading() let promise = new Promise(function (resolve, reject) { - if(!url.startsWith("http://") && !url.startsWith("https://") && !url.startsWith(ctx)){ + if (!url.startsWith("http://") && !url.startsWith("https://") && !url.startsWith(ctx)) { url = ctx + url; } $.ajax({ @@ -526,6 +526,26 @@ commonUtil = { var uuid = s.join(""); return uuid; }, + + + /** + * 将文件大小格式化为可读字符串 + * @param size + * @param initUnit 格式化之前的单位 + * @returns {*|string} + */ + fileSizeFormat: (size, initUnit = 'B') => { + const units = ['B', 'K', 'M', 'G', 'T', 'P']; + initUnit = initUnit.toUpperCase(); + const i = units.indexOf(initUnit); + if (size > 1024 && i < units.length - 1) { + return commonUtil.fileSizeFormat(size / 1024, units[i + 1]); + } else if (size < 1 && i > 0) { + return commonUtil.fileSizeFormat(size * 1024, units[i - 1]); + } else { + return Math.round(size * 100) / 100 + initUnit; + } + }, }; const Util = commonUtil; @@ -581,7 +601,7 @@ if (!initTime || (currentTime - initTime) > 1000 * 60) { const DICT = { get: function (type, key) { let _dict = {}, data = _Store.get(STORE_DICT_KEY); - if(typeof key === "number"){ + if (typeof key === "number") { key = key + ''; } if (type && key !== 'undefined' && key !== '') { diff --git a/shandan-common/src/main/resources/static/js/common/layui/extend/uploader/uploader.js b/shandan-common/src/main/resources/static/js/common/layui/extend/uploader/uploader.js index 02dc4fe..af0cd62 100644 --- a/shandan-common/src/main/resources/static/js/common/layui/extend/uploader/uploader.js +++ b/shandan-common/src/main/resources/static/js/common/layui/extend/uploader/uploader.js @@ -67,8 +67,8 @@ layui.extend({ let fileBoxE = options.fileBoxEle || fileBoxEle; $(fileBoxE).html(fileBox); table.init(COMP_TABLE_ID, { - height: 'full-' + 500, - page: true, + height: options.height || ('full-' + 500), + page: options.multiple, limit: 50, done: function () { that.tableHeader = $(`#${COMP_ID} .layui-table-header thead:first`); @@ -86,7 +86,7 @@ layui.extend({ pick: { id: `#${COMP_ID}`,//指定选择文件的按钮容器,不指定则不创建按钮。注意 这里虽然写的是 id, 不仅支持 id, 还支持 class, 或者 dom 节点。 innerHTML: btnText, - multiple: true //开启文件多选 + multiple: options.multiple //开启文件多选 }, fileNumLimit: undefined,//验证文件总数量, 超出则不允许加入队列,默认值:undefined,如果不配置,则不限制数量 fileSizeLimit: undefined, //1kb=1024*1024,验证文件总大小是否超出限制, 超出则不允许加入队列。 @@ -98,7 +98,7 @@ layui.extend({ prepareNextFile: false//在上传当前文件时,准备好下一个文件,请设置成false,不然开启文件多选你浏览器会卡死 }); - if (dirUpload) { + if (options.multiple && dirUpload) { setTimeout(function () { $(`#${COMP_ID} input[type="file"]`).attr('webkitdirectory', ''); }, 100); @@ -123,6 +123,12 @@ layui.extend({ file.nameBak = file.name; file.name = dirUpload ? file.source.source.webkitRelativePath : file.name; file.status = STATUS.added; + // 单文件上传先删除已选择的 + const existsFile = rowData[0] + if (!option.multiple && existsFile) { + upload.removeFile(existsFile.fileId, true); + rowData = removeArray(rowData, existsFile.fileId); + } rowData.push({ fileId: file.id, fileName: file.name, @@ -185,6 +191,7 @@ layui.extend({ //所有文件上传成功后 upload.on('uploadFinished', function (obj) {//成功后 + rowData = []; loading.closeAll(); let {interruptNum, queueNum, uploadFailNum} = upload.getStats(); option.uploadFinished && option.uploadFinished(uploadFailNum === 0 && interruptNum === 0 && queueNum === 0); @@ -278,6 +285,9 @@ layui.extend({ _file.entityId = that.formData.entityId; _file.fileFullName = file.name; _file.labelStr = that.formData.labelStr + if(that.formData.repairId){ + _file.id = that.formData.repairId; + } that.saveFileAndDir(_file, () => deferred.resolve()) } else { deferred.reject(); @@ -311,10 +321,10 @@ layui.extend({ let {fileMd5, source} = file; Util.post(fileCheckUrl, {fileMd5, name: ''}, false).then(res => { if (res.flag) { - if (res.code == 0) { + if (res.code === 0) { // 文件不存在 uploadIndexMap.set(fileMd5, res.data); - } else if (res.code == 1) { + } else if (res.code === 1) { // 文件存在,秒传 let existsFile = res.data; existsFile.entityId = that.formData.entityId; @@ -345,8 +355,8 @@ layui.extend({ * @param callback */ Class.prototype.saveFileAndDir = function (file, callback) { - let that = this; - Util.post(`/sys/file/upload/chunk/complete`, file, false).then((res) => { + let that = this, options = that.options; + Util.post(options.fileMergeUrl, file, false).then((res) => { that.setFileStatus(file); callback && callback(res); }) @@ -451,7 +461,7 @@ class Loading { show(shade = true) { if (this.index === -1) { - this.index = this.layer.load(0, {shade}); + this.index = this.layer.load(0, {shade: shade ? 0.3 : 0}); } this.countDownLatch += 1; } diff --git a/shandan-control/src/main/java/com/keyware/shandan/control/controller/DirectoryController.java b/shandan-control/src/main/java/com/keyware/shandan/control/controller/DirectoryController.java index f25e7c6..c362930 100644 --- a/shandan-control/src/main/java/com/keyware/shandan/control/controller/DirectoryController.java +++ b/shandan-control/src/main/java/com/keyware/shandan/control/controller/DirectoryController.java @@ -2,14 +2,12 @@ package com.keyware.shandan.control.controller; import com.keyware.shandan.bianmu.entity.DirectoryVo; import com.keyware.shandan.bianmu.service.DirPermissionService; -import com.keyware.shandan.bianmu.service.DirectoryMetadataService; import com.keyware.shandan.bianmu.service.DirectoryService; import com.keyware.shandan.common.controller.BaseController; import com.keyware.shandan.common.enums.SystemTypes; import com.keyware.shandan.frame.config.security.SecurityUtil; import com.keyware.shandan.system.entity.SysSetting; import com.keyware.shandan.system.entity.SysUser; -import com.keyware.shandan.system.service.SysFileService; import com.keyware.shandan.system.utils.SysSettingUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; @@ -29,15 +27,6 @@ import org.springframework.web.servlet.ModelAndView; @RequestMapping("/business/directory") public class DirectoryController extends BaseController { - @Autowired - private DirectoryService directoryService; - - @Autowired - private DirectoryMetadataService directoryMetadataService; - - @Autowired - private SysFileService sysFileService; - @Autowired private DirPermissionService dirPermissionService; diff --git a/shandan-control/src/main/java/com/keyware/shandan/control/controller/FIleRepairController.java b/shandan-control/src/main/java/com/keyware/shandan/control/controller/FIleRepairController.java new file mode 100644 index 0000000..f5011ac --- /dev/null +++ b/shandan-control/src/main/java/com/keyware/shandan/control/controller/FIleRepairController.java @@ -0,0 +1,174 @@ +package com.keyware.shandan.control.controller; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.keyware.shandan.bianmu.entity.DirectoryVo; +import com.keyware.shandan.bianmu.service.DirectoryService; +import com.keyware.shandan.common.entity.Result; +import com.keyware.shandan.common.enums.SystemTypes; +import com.keyware.shandan.frame.properties.CustomProperties; +import com.keyware.shandan.system.entity.SysFile; +import com.keyware.shandan.system.entity.SysFileChunk; +import com.keyware.shandan.system.entity.SysSetting; +import com.keyware.shandan.system.service.SysFileService; +import com.keyware.shandan.system.service.SysUserService; +import com.keyware.shandan.system.utils.FileChunkUploadUtil; +import com.keyware.shandan.system.utils.SysSettingUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.servlet.ModelAndView; + +import java.io.File; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Slf4j +@RestController +@RequestMapping("/sys/file/repair") +public class FIleRepairController { + + private final String storagePath; + private final SysUserService userService; + private final DirectoryService directoryService; + private final SysFileService fileService; + + public FIleRepairController(CustomProperties customProperties, + SysUserService userService, + DirectoryService directoryService, + SysFileService fileService) { + storagePath = customProperties.getFileStorage().getPath(); + this.userService = userService; + this.directoryService = directoryService; + this.fileService = fileService; + } + + /** + * 数据补录页面 + * + * @return + */ + @GetMapping("/index") + public ModelAndView repair(ModelAndView mav) { + mav.setViewName("sys/file/fileRepair"); + SysSetting bianmuSetting = SysSettingUtil.getSysSetting(SystemTypes.BIANMU.name()); + mav.addObject("bianmuAddress", bianmuSetting.getSysAddress()); + return mav; + } + + @GetMapping("/list") + public Result invalidFile(@RequestParam String dirId) { + Map fileMap = new HashMap<>(); + directoryService.handlerAllChildrenListById(dirId, (context) -> { + DirectoryVo dir = context.getResultObject(); + if (StringUtils.hasText(dir.getResourceId())) { + // 查询对应的文件资源 + SysFile file = fileService.getById(dir.getResourceId()); + if (file != null && !validate(file)) { + Map data = new HashMap<>(); + data.put("id", file.getId()); + data.put("dirId", dir.getId()); + data.put("directoryPath", dir.getDirectoryPath()); + data.put("fileName", file.getFileName()); + data.put("fileType", file.getFileType()); + data.put("fileSize", file.getFileSize()); + data.put("createTime", DateUtil.format(file.getModifyTime(), "yyyy-MM-dd HH:mm")); + data.put("createUser", userService.getById(file.getModifyUser()).getUserName()); + fileMap.put(file.getId(), data); + } + } + }); + return Result.of(fileMap.values()); + } + + /** + * 清理数据 + * + * @param fileId + * @return + */ + @GetMapping("/clean/{fileId}") + public Result remove(@PathVariable String fileId) { + try { + fileService.deleteById(fileId); + cleanDirectory(fileId); + } catch (Exception e) { + log.error("清理文件异常", e); + } + return Result.of(null); + } + + /** + * 递归清理文件管理的目录资源,以及引用的资源 + * + * @param resourceId + */ + private void cleanDirectory(String resourceId) { + LambdaQueryWrapper query = new LambdaQueryWrapper<>(); + query.eq(DirectoryVo::getResourceId, resourceId); + List dirs = directoryService.list(query); + dirs.forEach(dir -> { + cleanDirectory(dir.getId()); + directoryService.deleteById(dir.getId()); + }); + } + + /** + * 验证文件是否存在 + * + * @param sysFile + * @return + */ + private boolean validate(SysFile sysFile) { + if (sysFile == null) { + return false; + } + File file = new File(storagePath + File.separator + sysFile.getPath()); + return file.exists(); + } + + @PostMapping("/upload/check") + public Result uploadFileCheck() { + Result result = Result.of(null, true); + result.setCode(0); + return result; + } + + /** + * 大文件分片上传 + * + * @param file 分片文件 + * @param fileChunk 分片数据 + * @return 结果集 + */ + @PostMapping("/upload/chunk") + public Result uploadChunk(MultipartFile file, SysFile fileInfo, SysFileChunk fileChunk) throws Exception { + return Result.of(FileChunkUploadUtil.uploadChunk(file, fileInfo, fileChunk)); + + } + + /** + * 文件分片上传完成,需要自动生成目录结构,并保存目录文件关系 + * + * @param file 文件信息 + * @return 结果 + */ + @PostMapping("/upload/chunk/complete") + public Result mergerChunk(SysFile file) throws Exception { + FileChunkUploadUtil.mergeChunk(file, sysFile -> { + SysFile oldFile = fileService.getById(file.getId()); + if (oldFile == null) { + oldFile = sysFile; + } + QueryWrapper query = new QueryWrapper<>(); + query.eq("MD5", oldFile.getMD5()).eq("PATH", oldFile.getPath()); + List files = fileService.list(query); + files.forEach(f -> f.setPath(sysFile.getPath())); + fileService.updateBatchById(files); + }); + return Result.of(true); + } +} diff --git a/shandan-system/src/main/java/com/keyware/shandan/bianmu/mapper/DirectoryMapper.java b/shandan-system/src/main/java/com/keyware/shandan/bianmu/mapper/DirectoryMapper.java index a758ca6..8444e9c 100644 --- a/shandan-system/src/main/java/com/keyware/shandan/bianmu/mapper/DirectoryMapper.java +++ b/shandan-system/src/main/java/com/keyware/shandan/bianmu/mapper/DirectoryMapper.java @@ -3,8 +3,9 @@ package com.keyware.shandan.bianmu.mapper; import com.keyware.shandan.bianmu.entity.DirectoryVo; import com.keyware.shandan.bianmu.entity.MetadataBasicVo; import com.keyware.shandan.common.mapper.IBaseMapper; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Update; +import org.apache.ibatis.annotations.*; +import org.apache.ibatis.mapping.ResultSetType; +import org.apache.ibatis.session.ResultHandler; import java.util.List; @@ -20,7 +21,8 @@ import java.util.List; public interface DirectoryMapper extends IBaseMapper { /** * 根据父目录ID获取目录信息 - * @param parentId 父目录ID + * + * @param parentId 父目录ID * @param reviewStatus 审核状态 * @return */ @@ -28,6 +30,7 @@ public interface DirectoryMapper extends IBaseMapper { /** * 获取目录下的数据资源 + * * @param id 目录ID * @return */ @@ -35,11 +38,17 @@ public interface DirectoryMapper extends IBaseMapper { /** * 获取目录下所有数据资源,包含子级 + * * @param id 目录ID * @return - */ List selectAllMetadataByDirectory(String id); - @Update("update B_DIRECTORY set DIRECTORY_PATH = REPLACE(DIRECTORY_PATH, '${oldPath}', '${newPath}') where DIRECTORY_PATH like '${oldPath}%'") + @Update("update B_DIRECTORY set DIRECTORY_PATH = REPLACE(DIRECTORY_PATH, #{oldPath}, #{newPath}) where DIRECTORY_PATH like '${oldPath}%'") void updateDirectoryPath(String oldPath, String newPath); + + @Select("SELECT * FROM B_DIRECTORY D1 WHERE EXISTS(SELECT * FROM B_DIRECTORY D2 WHERE D2.ID = #{dirId} AND D1.DIRECTORY_PATH LIKE D2.DIRECTORY_PATH || '/%')") + @Options(resultSetType = ResultSetType.FORWARD_ONLY, fetchSize = Integer.MIN_VALUE) + @ResultType(DirectoryVo.class) + void handlerAllChildrenListById(@Param("dirId") String dirId, ResultHandler handler); } diff --git a/shandan-system/src/main/java/com/keyware/shandan/bianmu/service/DirectoryService.java b/shandan-system/src/main/java/com/keyware/shandan/bianmu/service/DirectoryService.java index 10758f2..93e5657 100644 --- a/shandan-system/src/main/java/com/keyware/shandan/bianmu/service/DirectoryService.java +++ b/shandan-system/src/main/java/com/keyware/shandan/bianmu/service/DirectoryService.java @@ -1,6 +1,5 @@ package com.keyware.shandan.bianmu.service; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.keyware.shandan.bianmu.entity.DirectoryVo; import com.keyware.shandan.bianmu.entity.MetadataBasicVo; import com.keyware.shandan.bianmu.enums.ReviewStatus; @@ -8,6 +7,7 @@ import com.keyware.shandan.common.service.IBaseService; import com.keyware.shandan.system.entity.SysFile; import com.keyware.shandan.system.entity.SysOrg; import com.keyware.shandan.system.entity.SysUser; +import org.apache.ibatis.session.ResultHandler; import java.io.Serializable; import java.util.Collection; @@ -127,4 +127,6 @@ public interface DirectoryService extends IBaseService { boolean saveFileDIr(SysFile file, String parentId); List childrenListByParent(String parentId); + + void handlerAllChildrenListById(String dirId, ResultHandler handler); } diff --git a/shandan-system/src/main/java/com/keyware/shandan/bianmu/service/impl/DirectoryServiceImpl.java b/shandan-system/src/main/java/com/keyware/shandan/bianmu/service/impl/DirectoryServiceImpl.java index 28e8fc3..875fb46 100644 --- a/shandan-system/src/main/java/com/keyware/shandan/bianmu/service/impl/DirectoryServiceImpl.java +++ b/shandan-system/src/main/java/com/keyware/shandan/bianmu/service/impl/DirectoryServiceImpl.java @@ -23,6 +23,8 @@ import com.keyware.shandan.system.entity.SysOrg; import com.keyware.shandan.system.entity.SysUser; import com.keyware.shandan.system.service.SysFileService; import com.keyware.shandan.system.service.SysOrgService; +import org.apache.ibatis.cursor.Cursor; +import org.apache.ibatis.session.ResultHandler; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -376,6 +378,11 @@ public class DirectoryServiceImpl extends BaseServiceImpl(param)); } + @Override + public void handlerAllChildrenListById(String dirId, ResultHandler handler) { + directoryMapper.handlerAllChildrenListById(dirId, handler); + } + private DirectoryVo createDirByOrg(SysOrg org, String parentDirId) throws Exception { DirectoryVo dir = DirectoryVo.builder().build(); dir.setParentId(parentDirId); diff --git a/shandan-system/src/main/java/com/keyware/shandan/system/mapper/SysFileMapper.java b/shandan-system/src/main/java/com/keyware/shandan/system/mapper/SysFileMapper.java index 39be38d..3b3c952 100644 --- a/shandan-system/src/main/java/com/keyware/shandan/system/mapper/SysFileMapper.java +++ b/shandan-system/src/main/java/com/keyware/shandan/system/mapper/SysFileMapper.java @@ -1,8 +1,15 @@ package com.keyware.shandan.system.mapper; -import com.keyware.shandan.system.entity.SysFile; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.toolkit.Constants; import com.keyware.shandan.common.mapper.IBaseMapper; +import com.keyware.shandan.system.entity.SysFile; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Options; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; +import org.apache.ibatis.cursor.Cursor; +import org.apache.ibatis.mapping.ResultSetType; import java.util.List; @@ -18,4 +25,8 @@ import java.util.List; public interface SysFileMapper extends IBaseMapper { List listByDirId(String dirId); + + @Select("SELECT * FROM SYS_FILE ${ew.customSqlSegment}") + @Options(resultSetType = ResultSetType.FORWARD_ONLY, fetchSize = 2) + Cursor streamList(@Param(Constants.WRAPPER) Wrapper wrapper); } diff --git a/shandan-system/src/main/java/com/keyware/shandan/system/service/impl/SysFileServiceImpl.java b/shandan-system/src/main/java/com/keyware/shandan/system/service/impl/SysFileServiceImpl.java index 58e8a45..23a10f3 100644 --- a/shandan-system/src/main/java/com/keyware/shandan/system/service/impl/SysFileServiceImpl.java +++ b/shandan-system/src/main/java/com/keyware/shandan/system/service/impl/SysFileServiceImpl.java @@ -4,7 +4,6 @@ import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.io.FileUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.keyware.shandan.bianmu.entity.DirectoryVo; -import com.keyware.shandan.bianmu.entity.LabelEntity; import com.keyware.shandan.bianmu.enums.DirectoryType; import com.keyware.shandan.bianmu.enums.ReviewStatus; import com.keyware.shandan.bianmu.service.DirectoryService; @@ -26,7 +25,6 @@ import com.keyware.shandan.system.mapper.SysFileMapper; import com.keyware.shandan.system.repositories.EsSysFileRepository; import com.keyware.shandan.system.service.SysFileService; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.io.FileUtils; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -37,7 +35,6 @@ import org.springframework.web.multipart.MultipartFile; import javax.validation.constraints.NotNull; import java.io.File; -import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; @@ -141,20 +138,6 @@ public class SysFileServiceImpl extends BaseServiceImpl deleteFileChunkQuery = new QueryWrapper<>(); - deleteFileChunkQuery.eq("FILE_MD5", file.getMD5()); - fileChunkMapper.delete(deleteFileChunkQuery); - } /** * 生成文件的路径名称(包含文件名称及后缀) diff --git a/shandan-system/src/main/java/com/keyware/shandan/system/utils/FileChunkUploadUtil.java b/shandan-system/src/main/java/com/keyware/shandan/system/utils/FileChunkUploadUtil.java index dfd53f7..8bef647 100644 --- a/shandan-system/src/main/java/com/keyware/shandan/system/utils/FileChunkUploadUtil.java +++ b/shandan-system/src/main/java/com/keyware/shandan/system/utils/FileChunkUploadUtil.java @@ -117,7 +117,7 @@ public class FileChunkUploadUtil { @Data - static class TempFile { + public static class TempFile { private SysFile sysFile; private ConcurrentHashMap chunksCache = new ConcurrentHashMap<>(); diff --git a/shandan-system/src/main/resources/static/js/sys/file/dirUpload.js b/shandan-system/src/main/resources/static/js/sys/file/dirUpload.js index 952ad68..39e6b1f 100644 --- a/shandan-system/src/main/resources/static/js/sys/file/dirUpload.js +++ b/shandan-system/src/main/resources/static/js/sys/file/dirUpload.js @@ -22,8 +22,9 @@ layui.use(['layer', 'uploader', 'element', 'form', 'laydate', 'dict', 'datalabel let uploader = layui.uploader.render({ url: `${ctx}/sys/file/upload/chunk`,//上传文件服务器地址,必填 fileCheckUrl: `${ctx}/sys/file/upload/check`,//文件校验地址 + fileMergeUrl: `/sys/file/upload/chunk/complete`, fileBoxEle: "#uploader-table",//上传容器 - chooseFolder: true, + multiple: true, dirUpload: param.dirUpload, getFormData: getFormVal, uploadFinished: function (ok) { diff --git a/shandan-system/src/main/resources/static/js/sys/file/repair.js b/shandan-system/src/main/resources/static/js/sys/file/repair.js new file mode 100644 index 0000000..5666537 --- /dev/null +++ b/shandan-system/src/main/resources/static/js/sys/file/repair.js @@ -0,0 +1,238 @@ +/** + *

+ * repair + *

+ * + * @author Administrator + * @since 2021/6/1 + */ +// 目录树数据缓存 +const dirCache = new Map(); + +function startRender() { + layui.use(['uploader'], function () { + const uploader = layui.uploader; + // 目录树 + let dirTree, fileTable, activeNode; + let currentNode, currentParentNode; + let treeChildrenUrl = `${ctx}/business/directory/tree?busType=` + bus_type + + // 加载并渲染目录树 + let treeOps = { + id: 'directoryTree', + url: treeChildrenUrl, + cache: false, + // type: 'all', + initLevel: 1, // 默认展开一级 + scroll: '#tree-toobar-div', + width: 'fit-content', + toolbar: true, + toolbarShow: [], //置空默认菜单项 + sendSuccess: function (res) { + if (res.flag) { + res.data.forEach(item => { + dirCache.set(item.id, item); + }) + + setTimeout(() => { + $('.dtree-nav-div.dtree-theme-item').each((index, elem) => { + let data = $(elem).data('basic'); + if (data) { + if (typeof data === 'string') { + data = JSON.parse(data); + } + let title = data.metadataComment || data.directoryName || data.fileName + data.fileSuffix; + $(elem).attr('title', title) + } + }); + }, 200) + } + }, + done: function (nodes, elem) { + // 模拟鼠标点击事件展开第一层目录 + elem.find('li:first>div:first>i:first').click(); + elem.find('li:first>div:first').click(); + }, + onClick: function (node) { + activeNode = node; + currentNode = getCurrentNode(); + currentParentNode = getCurrentParentNode(); + const {basicData} = node.param; + setLocation(basicData.directoryPath) + loadFileList(activeNode.param) + }, + toolbarFun: { + // 显示右键菜单之前的回调,用于设置显示哪些菜单 + loadToolbarBefore: function (buttons, param, $div) { + return buttons; + } + }, + toolbarExt: [ + { + toolbarId: "toolbar_dir_rename", + icon: "dtreefont dtree-icon-bianji", + title: "修改目录", + handler: function (node, elem) { + const {basicData} = node; + openDirectoryEditLayer(basicData, function (data) { + dirTree.partialRefreshEdit(elem, data); + dirTree.getChild(elem); + elem[0].click(); + }); + } + }, + { + toolbarId: "toolbar_dir_delete", + icon: "dtreefont dtree-icon-delete1", + title: "删除目录", + handler: function (node, elem) { + const {id, parentId} = node; + deleteDirectory(id).then(() => { + //dirTree.partialRefreshDel(elem) + reZhanKai(currentParentNode); + // 点击父节点 + $(`div[data-id="${parentId}"]`).click(); + }) + } + } + ], + formatter: { + title: function (data) { // 文字过滤,返回null,"",undefined之后,都不会改变原有的内容返回。 + return formatterTitle(data); + } + } + } + dirTree = globalTree.init(treeOps); + + /** + * 加载数据资源列表 + */ + function loadFileList(directory) { + const {basicData} = directory, dirId = basicData.id; + if (!basicData) return; + Util.get(`/sys/file/repair/list?dirId=${dirId}`).then(({flag, data, msg}) => { + if (!flag) { + showErrorMsg(msg); + return; + } + data && renderFileTable(data); + }); + } + + function renderFileTable(data) { + fileTable = listPage.init({ + table: { + id: 'dirMetadataTable', + toolbar: '#tableToolBar', + searchFieldNames: 'metadataName', + height: 'full-110', + data: data, + cols: [[ + {field: 'id', title: 'ID', hide: true}, + {field: 'fileName', title: '文件名称', width: 300}, + {field: 'directoryPath', title: '所属目录'}, + {field: 'fileType', title: '文件类型', width: 160, align: 'center'}, + { + field: 'fileSize', + title: '文件大小', + width: 160, + align: 'center', + templet: (data) => Util.fileSizeFormat(data.fileSize, "M") + }, + {field: 'createTime', title: '最后修改时间', width: 160, align: 'center'}, + {field: 'createUser', title: '最后修改用户', width: 160, align: 'center'}, + { + fixed: 'right', + title: '操作', + toolbar: `#rowToolBar`, + width: 160, + align: 'center' + } + ]], + }, + }); + // 查看按钮监听 + fileTable.addTableRowEvent('reupload', reupload) + fileTable.addTableRowEvent('clean', cleanData) + } + + function reupload(obj) { + const fileId = obj.id; + const layerId = 'reupload-layer'; + let uploadObject; + let layerIndex = layer.open({ + title: '重新上传文件', + content: `
`, + btn: ['上传', '取消'], + success: function (layObj, index) { + uploadObject = renderUploader(); + }, + yes: function () { + uploadObject.uploadToServer(); + }, + }); + + function renderUploader() { + return uploader.render({ + url: `${ctx}/sys/file/repair/upload/chunk`,//上传文件服务器地址,必填 + fileCheckUrl: `${ctx}/sys/file/repair/upload/check`,//文件校验地址 + fileMergeUrl: `/sys/file/repair/upload/chunk/complete`, + fileBoxEle: `#${layerId}`,//上传容器 + height: '130px', + multiple: false, + getFormData: () => ({repairId: fileId}), + uploadFinished: function (ok) { + loadFileList(activeNode.param); + layer.close(layerIndex); + } + }); + } + } + + /** + * 移除数据 + * @param obj + */ + function cleanData(obj) { + layer.confirm('该清理操作将删除该文件记录以及对该文件引用的资源数据,是否确定清理?', {}, function (index) { + layer.close(index); + Util.get(`/sys/file/repair/clean/${obj.id}`, {},).then(res => { + if (res.flag) { + showOkMsg('清理成功') + loadFileList(activeNode.param) + } else { + showErrorMsg(res.msg); + } + }).catch(() => showErrorMsg()); + }) + + } + + + /** + * 获取当前节点 + * @returns {*|jQuery|HTMLElement} + */ + function getCurrentNode() { + return $('li.dtree-nav-item div.dtree-theme-item-this'); + } + + /** + * 获取当前节点的父级节点 + * @returns {*|jQuery} + */ + function getCurrentParentNode() { + return getCurrentNode().parent().parent().prev(); + } + + function reZhanKai(node) { + let iconNode = node.find('i:first'); + if (iconNode.data('spread') === 'open') { + iconNode.click(); + iconNode.click(); + } else { + iconNode.click(); + } + } + }); +} diff --git a/shandan-system/src/main/resources/view/sys/file/fileRepair.html b/shandan-system/src/main/resources/view/sys/file/fileRepair.html new file mode 100644 index 0000000..ff67865 --- /dev/null +++ b/shandan-system/src/main/resources/view/sys/file/fileRepair.html @@ -0,0 +1,125 @@ + + + + + + + + + + + + +
+ +
+
+
+
+
    + +
+
+
+
+
+
+ + +
+
+
+
+
+
    +
    +
    +
    +
    +
    +
    + + +
    +
    +
    +
    +
      + +
    +
    +
    +
    当前位置:
    +
    + + +
    +
    +
    +
    +
    +
    +
    + + + + + + + + diff --git a/shandan-system/src/main/resources/view/sys/file/fileView.html b/shandan-system/src/main/resources/view/sys/file/fileView.html index 8d377c9..6c3ff26 100644 --- a/shandan-system/src/main/resources/view/sys/file/fileView.html +++ b/shandan-system/src/main/resources/view/sys/file/fileView.html @@ -17,6 +17,8 @@ const file = /*[[${fileData}]]*/ {}; const fileViewUrl = /*[[${fileViewUrl}]]*/ ''; const downloadUrl = /*[[${downloadUrl}]]*/ ''; + const fileNotExists = /*[[${fileNotExists}]]*/ false; + const fileReadError = /*[[${fileReadError}]]*/ false;