优化
This commit is contained in:
@ -628,6 +628,7 @@ public class DesDesignChangeServiceImpl extends ServiceImpl<DesDesignChangeMappe
|
|||||||
} else if ("2".equals(bean.getDesignDisposal())) {
|
} else if ("2".equals(bean.getDesignDisposal())) {
|
||||||
LambdaUpdateWrapper<DesVolumeFile> wrapper = new LambdaUpdateWrapper<>();
|
LambdaUpdateWrapper<DesVolumeFile> wrapper = new LambdaUpdateWrapper<>();
|
||||||
wrapper.set(DesVolumeFile::getType, DesVolumeFile.WASTE)
|
wrapper.set(DesVolumeFile::getType, DesVolumeFile.WASTE)
|
||||||
|
.eq(DesVolumeFile::getType, DesVolumeFile.BLUEPRINT)
|
||||||
.eq(DesVolumeFile::getVolumeCatalogId, volumeCatalog.getDesign());
|
.eq(DesVolumeFile::getVolumeCatalogId, volumeCatalog.getDesign());
|
||||||
String saveFile = designChange.getSaveFile();
|
String saveFile = designChange.getSaveFile();
|
||||||
if (StringUtils.isNotBlank(saveFile)) {
|
if (StringUtils.isNotBlank(saveFile)) {
|
||||||
@ -658,7 +659,7 @@ public class DesDesignChangeServiceImpl extends ServiceImpl<DesDesignChangeMappe
|
|||||||
String lastVersion = list.getFirst().getVersion();
|
String lastVersion = list.getFirst().getVersion();
|
||||||
// 提取版本号数字部分(去除LT-前缀)
|
// 提取版本号数字部分(去除LT-前缀)
|
||||||
String versionNumber = lastVersion;
|
String versionNumber = lastVersion;
|
||||||
if (lastVersion.startsWith("LT-")) {
|
if (lastVersion.startsWith("LT-") || lastVersion.startsWith("GC-")) {
|
||||||
versionNumber = lastVersion.substring(3); // 去除"LT-"前缀
|
versionNumber = lastVersion.substring(3); // 去除"LT-"前缀
|
||||||
}
|
}
|
||||||
int majorVersion = (int) Math.floor(Double.parseDouble(versionNumber)) + 1;
|
int majorVersion = (int) Math.floor(Double.parseDouble(versionNumber)) + 1;
|
||||||
|
|||||||
@ -421,17 +421,17 @@ public class DesVolumeFileServiceImpl extends ServiceImpl<DesVolumeFileMapper, D
|
|||||||
|
|
||||||
if (DesVolumeFile.BLUEPRINT.equals(type)) {
|
if (DesVolumeFile.BLUEPRINT.equals(type)) {
|
||||||
// 蓝图文件:LT-1.0, LT-1.1, LT-1.2...
|
// 蓝图文件:LT-1.0, LT-1.1, LT-1.2...
|
||||||
double maxVersion = Double.parseDouble(maxBatchVersion);
|
if (CollectionUtil.isEmpty(existingFilesInDB)) {
|
||||||
int majorVersion = (int) Math.floor(maxVersion);
|
// 没有历史版本,从1.0开始,根据文件索引递增
|
||||||
int minorVersion = (int) ((maxVersion - majorVersion) * 10) + fileIndex + 1;
|
int minorVersion = fileIndex;
|
||||||
|
versionStr = "LT-1." + minorVersion;
|
||||||
// 如果是第一个文件且没有历史版本,则从1.0开始
|
|
||||||
if (fileIndex == 0 && CollectionUtil.isEmpty(existingFilesInDB)) {
|
|
||||||
versionStr = "1.0";
|
|
||||||
} else {
|
} else {
|
||||||
versionStr = majorVersion + "." + minorVersion;
|
// 有历史版本,基于最高版本递增
|
||||||
|
double maxVersion = Double.parseDouble(maxBatchVersion);
|
||||||
|
int majorVersion = (int) Math.floor(maxVersion);
|
||||||
|
int minorVersion = (int) Math.round((maxVersion - majorVersion) * 10) + fileIndex + 1;
|
||||||
|
versionStr = "LT-" + majorVersion + "." + minorVersion;
|
||||||
}
|
}
|
||||||
versionStr = "LT-" + versionStr;
|
|
||||||
} else if (DesVolumeFile.PROCESS.equals(type)) {
|
} else if (DesVolumeFile.PROCESS.equals(type)) {
|
||||||
// 过程图纸:基于蓝图版本号
|
// 过程图纸:基于蓝图版本号
|
||||||
List<DesVolumeFile> blueprintFiles = baseMapper.selectList(new LambdaQueryWrapper<DesVolumeFile>()
|
List<DesVolumeFile> blueprintFiles = baseMapper.selectList(new LambdaQueryWrapper<DesVolumeFile>()
|
||||||
|
|||||||
@ -330,6 +330,8 @@ public class MatMaterialsServiceImpl extends ServiceImpl<MatMaterialsMapper, Mat
|
|||||||
lqw.eq(ObjectUtils.isNotEmpty(status), MatMaterials::getStatus, status);
|
lqw.eq(ObjectUtils.isNotEmpty(status), MatMaterials::getStatus, status);
|
||||||
lqw.eq(ObjectUtils.isNotEmpty(projectId), MatMaterials::getProjectId, projectId);
|
lqw.eq(ObjectUtils.isNotEmpty(projectId), MatMaterials::getProjectId, projectId);
|
||||||
lqw.eq(ObjectUtils.isNotEmpty(companyId), MatMaterials::getCompanyId, companyId);
|
lqw.eq(ObjectUtils.isNotEmpty(companyId), MatMaterials::getCompanyId, companyId);
|
||||||
|
|
||||||
|
lqw.orderByDesc(MatMaterials::getCreateTime);
|
||||||
return lqw;
|
return lqw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,51 @@
|
|||||||
|
package org.dromara.project.controller.app;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.dromara.common.core.domain.R;
|
||||||
|
import org.dromara.common.core.validate.AddGroup;
|
||||||
|
import org.dromara.common.core.validate.EditGroup;
|
||||||
|
import org.dromara.common.excel.utils.ExcelUtil;
|
||||||
|
import org.dromara.common.idempotent.annotation.RepeatSubmit;
|
||||||
|
import org.dromara.common.log.annotation.Log;
|
||||||
|
import org.dromara.common.log.enums.BusinessType;
|
||||||
|
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||||
|
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||||
|
import org.dromara.common.web.core.BaseController;
|
||||||
|
import org.dromara.project.domain.dto.workwage.BusWorkWageCreateReq;
|
||||||
|
import org.dromara.project.domain.dto.workwage.BusWorkWageQueryReq;
|
||||||
|
import org.dromara.project.domain.dto.workwage.BusWorkWageUpdateReq;
|
||||||
|
import org.dromara.project.domain.vo.workwage.BusWorkWageVo;
|
||||||
|
import org.dromara.project.service.IBusWorkWageService;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工种薪水
|
||||||
|
*
|
||||||
|
* @author lilemy
|
||||||
|
* @date 2025-03-26
|
||||||
|
*/
|
||||||
|
@Validated
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/app/project/workWage")
|
||||||
|
public class BusWorkWageAppController extends BaseController {
|
||||||
|
|
||||||
|
private final IBusWorkWageService busWorkWageService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询工种薪水列表
|
||||||
|
*/
|
||||||
|
|
||||||
|
@GetMapping("/list")
|
||||||
|
public R<List<BusWorkWageVo>> list(BusWorkWageQueryReq req) {
|
||||||
|
return R.ok(busWorkWageService.queryList(req));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,6 +1,8 @@
|
|||||||
package org.dromara.project.domain.dto.workwage;
|
package org.dromara.project.domain.dto.workwage;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import org.dromara.common.translation.annotation.Translation;
|
||||||
|
import org.dromara.common.translation.constant.TransConstant;
|
||||||
|
|
||||||
import java.io.Serial;
|
import java.io.Serial;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@ -31,6 +33,7 @@ public class BusWorkWageQueryReq implements Serializable {
|
|||||||
*/
|
*/
|
||||||
private String workType;
|
private String workType;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否是特种兵(1是 2否)
|
* 是否是特种兵(1是 2否)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -6,6 +6,8 @@ import io.github.linpeilie.annotations.AutoMapper;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.dromara.common.excel.annotation.ExcelDictFormat;
|
import org.dromara.common.excel.annotation.ExcelDictFormat;
|
||||||
import org.dromara.common.excel.convert.ExcelDictConvert;
|
import org.dromara.common.excel.convert.ExcelDictConvert;
|
||||||
|
import org.dromara.common.translation.annotation.Translation;
|
||||||
|
import org.dromara.common.translation.constant.TransConstant;
|
||||||
import org.dromara.project.domain.BusWorkWage;
|
import org.dromara.project.domain.BusWorkWage;
|
||||||
|
|
||||||
import java.io.Serial;
|
import java.io.Serial;
|
||||||
@ -47,6 +49,12 @@ public class BusWorkWageVo implements Serializable {
|
|||||||
@ExcelDictFormat(dictType = "type_of_work")
|
@ExcelDictFormat(dictType = "type_of_work")
|
||||||
private String workType;
|
private String workType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工种
|
||||||
|
*/
|
||||||
|
@Translation(type = TransConstant.DICT_TYPE_TO_LABEL, mapper = "workType",other = "type_of_work")
|
||||||
|
private String workTypeName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否是特种兵(1是 2否)
|
* 是否是特种兵(1是 2否)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -505,6 +505,7 @@ public class BusLeaveServiceImpl extends ServiceImpl<BusLeaveMapper, BusLeave>
|
|||||||
@Override
|
@Override
|
||||||
public TableDataInfo<BusLeaveVo> listByLoginUser(BusLeaveQueryReq req, PageQuery pageQuery) {
|
public TableDataInfo<BusLeaveVo> listByLoginUser(BusLeaveQueryReq req, PageQuery pageQuery) {
|
||||||
LambdaQueryWrapper<BusLeave> lqw = new LambdaQueryWrapper<>();
|
LambdaQueryWrapper<BusLeave> lqw = new LambdaQueryWrapper<>();
|
||||||
|
lqw.orderByDesc(BusLeave::getCreateTime);
|
||||||
|
|
||||||
lqw.eq(ObjectUtils.isNotEmpty(req.getUserId()), BusLeave::getUserId, req.getUserId());
|
lqw.eq(ObjectUtils.isNotEmpty(req.getUserId()), BusLeave::getUserId, req.getUserId());
|
||||||
|
|
||||||
|
|||||||
@ -214,9 +214,9 @@ public class BusReissueCardServiceImpl extends ServiceImpl<BusReissueCardMapper,
|
|||||||
byId.setClockStatus(BusAttendanceClockStatusEnum.REISSUE.getValue());
|
byId.setClockStatus(BusAttendanceClockStatusEnum.REISSUE.getValue());
|
||||||
attendanceService.updateById(byId);
|
attendanceService.updateById(byId);
|
||||||
//缺卡补充当天的工资表
|
//缺卡补充当天的工资表
|
||||||
if(BusAttendanceClockStatusEnum.UNCLOCK.getValue().equals(clockStatus)){
|
// if(BusAttendanceClockStatusEnum.UNCLOCK.getValue().equals(clockStatus)){
|
||||||
userSalaryDetailService.insertByAttendance(byId.getUserId(),byId.getClockDate());
|
// userSalaryDetailService.insertByAttendance(byId.getUserId(),byId.getClockDate());
|
||||||
}
|
// }
|
||||||
CompletableFuture.runAsync(() -> {
|
CompletableFuture.runAsync(() -> {
|
||||||
try {
|
try {
|
||||||
chatServerHandler.sendSystemMessageToUser(bean.getUserId(),"补卡申请已通过","1");
|
chatServerHandler.sendSystemMessageToUser(bean.getUserId(),"补卡申请已通过","1");
|
||||||
@ -511,9 +511,9 @@ public class BusReissueCardServiceImpl extends ServiceImpl<BusReissueCardMapper,
|
|||||||
byId.setClockStatus(BusAttendanceClockStatusEnum.REISSUE.getValue());
|
byId.setClockStatus(BusAttendanceClockStatusEnum.REISSUE.getValue());
|
||||||
attendanceService.updateById(byId);
|
attendanceService.updateById(byId);
|
||||||
//缺卡补充当天的工资表
|
//缺卡补充当天的工资表
|
||||||
if(BusAttendanceClockStatusEnum.UNCLOCK.getValue().equals(clockStatus)){
|
// if(BusAttendanceClockStatusEnum.UNCLOCK.getValue().equals(clockStatus)){
|
||||||
userSalaryDetailService.insertByAttendance(byId.getUserId(),byId.getClockDate());
|
// userSalaryDetailService.insertByAttendance(byId.getUserId(),byId.getClockDate());
|
||||||
}
|
// }
|
||||||
CompletableFuture.runAsync(() -> {
|
CompletableFuture.runAsync(() -> {
|
||||||
try {
|
try {
|
||||||
chatServerHandler.sendSystemMessageToUser(bean.getUserId(),"补卡申请已通过","1");
|
chatServerHandler.sendSystemMessageToUser(bean.getUserId(),"补卡申请已通过","1");
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import org.dromara.safety.domain.dto.fileFolder.FileFolderCreateDTO;
|
|||||||
import org.dromara.safety.domain.dto.fileFolder.FileFolderMoveDTO;
|
import org.dromara.safety.domain.dto.fileFolder.FileFolderMoveDTO;
|
||||||
import org.dromara.safety.domain.dto.fileFolder.ListQueryDto;
|
import org.dromara.safety.domain.dto.fileFolder.ListQueryDto;
|
||||||
import org.dromara.safety.domain.vo.fileFolder.FileFolderTreeVO;
|
import org.dromara.safety.domain.vo.fileFolder.FileFolderTreeVO;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
@ -29,6 +30,7 @@ import org.dromara.safety.domain.vo.HseFileFolderVo;
|
|||||||
import org.dromara.safety.domain.bo.HseFileFolderBo;
|
import org.dromara.safety.domain.bo.HseFileFolderBo;
|
||||||
import org.dromara.safety.service.IHseFileFolderService;
|
import org.dromara.safety.service.IHseFileFolderService;
|
||||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 会议纪要
|
* 会议纪要
|
||||||
@ -61,6 +63,7 @@ public class HseFileFolderController extends BaseController {
|
|||||||
|
|
||||||
// 1. 查询所有子项(利用path前缀匹配,一次性加载所有层级)
|
// 1. 查询所有子项(利用path前缀匹配,一次性加载所有层级)
|
||||||
List<HseFileFolder> allItems = hseFileFolderService.list(new LambdaQueryWrapper<HseFileFolder>()
|
List<HseFileFolder> allItems = hseFileFolderService.list(new LambdaQueryWrapper<HseFileFolder>()
|
||||||
|
.eq(HseFileFolder::getProjectId, dto.getProjectId())
|
||||||
.like(HseFileFolder::getPath, "," + dto.getParentId() + ",") // 包含父ID的所有子项
|
.like(HseFileFolder::getPath, "," + dto.getParentId() + ",") // 包含父ID的所有子项
|
||||||
.eq(dto.getType()!=null,HseFileFolder::getType, dto.getType())
|
.eq(dto.getType()!=null,HseFileFolder::getType, dto.getType())
|
||||||
.orderByDesc(HseFileFolder::getId)
|
.orderByDesc(HseFileFolder::getId)
|
||||||
@ -122,8 +125,25 @@ public class HseFileFolderController extends BaseController {
|
|||||||
return R.ok(hseFileFolderService.moveFileOrFolder(dto.getId(), dto.getTargetParentId()));
|
return R.ok(hseFileFolderService.moveFileOrFolder(dto.getId(), dto.getTargetParentId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传ZIP文件并自动解压到指定目录(支持多层级)
|
||||||
|
*/
|
||||||
|
@PostMapping("/uploadAndUnzip")
|
||||||
|
public R<String> uploadAndUnzip(
|
||||||
|
@RequestParam("file") MultipartFile file,
|
||||||
|
@RequestParam("parentId") Long parentId,
|
||||||
|
@RequestParam("projectId") Long projectId) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 实际应用中,userId和deptId通常从登录信息中获取
|
||||||
|
String result = hseFileFolderService.uploadAndUnzip(file, parentId, projectId);
|
||||||
|
return R.ok(result);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
return R.fail(e.getMessage());
|
||||||
|
} catch (Exception e) {
|
||||||
|
return R.fail("文件处理失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -16,6 +16,8 @@ public class FileFolderCreateDTO {
|
|||||||
@NotBlank(message = "名称不能为空")
|
@NotBlank(message = "名称不能为空")
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
|
private Long projectId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 父级ID(0表示根目录)
|
* 父级ID(0表示根目录)
|
||||||
*/
|
*/
|
||||||
@ -32,6 +34,12 @@ public class FileFolderCreateDTO {
|
|||||||
*/
|
*/
|
||||||
private Integer sort=0;
|
private Integer sort=0;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件id
|
||||||
|
*/
|
||||||
|
private Long fileId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 文件后缀
|
* 文件后缀
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -19,4 +19,8 @@ public class ListQueryDto {
|
|||||||
private Integer type;
|
private Integer type;
|
||||||
|
|
||||||
|
|
||||||
|
@NotNull(message = "项目不能为空")
|
||||||
|
private Long projectId;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,6 +9,8 @@ import org.dromara.common.mybatis.core.page.TableDataInfo;
|
|||||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -87,4 +89,15 @@ public interface IHseFileFolderService extends IService<HseFileFolder>{
|
|||||||
* 移动文件或文件夹到指定目录
|
* 移动文件或文件夹到指定目录
|
||||||
*/
|
*/
|
||||||
boolean moveFileOrFolder(Long id, Long targetParentId);
|
boolean moveFileOrFolder(Long id, Long targetParentId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传并解压ZIP文件
|
||||||
|
*/
|
||||||
|
String uploadAndUnzip(MultipartFile file, Long parentId, Long projectId) throws Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取指定目录的树形结构(一次性加载所有层级)
|
||||||
|
* @return 树形结构列表
|
||||||
|
*/
|
||||||
|
String unzip(Long id, Long parentId);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,11 +19,14 @@ import org.dromara.safety.domain.HseFileFolder;
|
|||||||
import org.dromara.safety.mapper.HseFileFolderMapper;
|
import org.dromara.safety.mapper.HseFileFolderMapper;
|
||||||
import org.dromara.safety.service.IHseFileFolderService;
|
import org.dromara.safety.service.IHseFileFolderService;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.io.File;
|
||||||
import java.util.List;
|
import java.io.FileInputStream;
|
||||||
import java.util.Map;
|
import java.nio.charset.Charset;
|
||||||
import java.util.Collection;
|
import java.util.*;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
import java.util.zip.ZipInputStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 会议纪要Service业务层处理
|
* 会议纪要Service业务层处理
|
||||||
@ -44,7 +47,7 @@ public class HseFileFolderServiceImpl extends ServiceImpl<HseFileFolderMapper, H
|
|||||||
* @return 会议纪要
|
* @return 会议纪要
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public HseFileFolderVo queryById(Long id){
|
public HseFileFolderVo queryById(Long id) {
|
||||||
return baseMapper.selectVoById(id);
|
return baseMapper.selectVoById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,7 +128,7 @@ public class HseFileFolderServiceImpl extends ServiceImpl<HseFileFolderMapper, H
|
|||||||
/**
|
/**
|
||||||
* 保存前的数据校验
|
* 保存前的数据校验
|
||||||
*/
|
*/
|
||||||
private void validEntityBeforeSave(HseFileFolder entity){
|
private void validEntityBeforeSave(HseFileFolder entity) {
|
||||||
//TODO 做一些数据校验,如唯一约束
|
//TODO 做一些数据校验,如唯一约束
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,7 +141,7 @@ public class HseFileFolderServiceImpl extends ServiceImpl<HseFileFolderMapper, H
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||||
if(isValid){
|
if (isValid) {
|
||||||
//TODO 做一些业务上的校验,判断是否需要校验
|
//TODO 做一些业务上的校验,判断是否需要校验
|
||||||
}
|
}
|
||||||
return baseMapper.deleteByIds(ids) > 0;
|
return baseMapper.deleteByIds(ids) > 0;
|
||||||
@ -151,8 +154,9 @@ public class HseFileFolderServiceImpl extends ServiceImpl<HseFileFolderMapper, H
|
|||||||
lqw.orderByDesc(HseFileFolder::getId);
|
lqw.orderByDesc(HseFileFolder::getId);
|
||||||
lqw.orderByAsc(HseFileFolder::getSort);
|
lqw.orderByAsc(HseFileFolder::getSort);
|
||||||
|
|
||||||
|
lqw.eq(HseFileFolder::getProjectId, dto.getProjectId());
|
||||||
lqw.eq(HseFileFolder::getParentId, dto.getParentId());
|
lqw.eq(HseFileFolder::getParentId, dto.getParentId());
|
||||||
lqw.eq(dto.getType()!=null,HseFileFolder::getType, dto.getType());
|
lqw.eq(dto.getType() != null, HseFileFolder::getType, dto.getType());
|
||||||
|
|
||||||
return baseMapper.selectVoList(lqw);
|
return baseMapper.selectVoList(lqw);
|
||||||
}
|
}
|
||||||
@ -168,11 +172,13 @@ public class HseFileFolderServiceImpl extends ServiceImpl<HseFileFolderMapper, H
|
|||||||
|
|
||||||
// 2. 构建新文件/文件夹对象
|
// 2. 构建新文件/文件夹对象
|
||||||
HseFileFolder entity = new HseFileFolder();
|
HseFileFolder entity = new HseFileFolder();
|
||||||
|
entity.setProjectId(dto.getProjectId());
|
||||||
entity.setName(dto.getName());
|
entity.setName(dto.getName());
|
||||||
entity.setParentId(dto.getParentId());
|
entity.setParentId(dto.getParentId());
|
||||||
entity.setType(dto.getType());
|
entity.setType(dto.getType());
|
||||||
entity.setSort(dto.getSort() != null ? dto.getSort() : 0);
|
entity.setSort(dto.getSort() != null ? dto.getSort() : 0);
|
||||||
entity.setRemark(dto.getRemark());
|
entity.setRemark(dto.getRemark());
|
||||||
|
entity.setFileId(dto.getFileId());
|
||||||
|
|
||||||
|
|
||||||
// 3. 设置层级和路径
|
// 3. 设置层级和路径
|
||||||
@ -236,7 +242,7 @@ public class HseFileFolderServiceImpl extends ServiceImpl<HseFileFolderMapper, H
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 2. 防止循环移动(不能移动到自身或子目录下)
|
// 2. 防止循环移动(不能移动到自身或子目录下)
|
||||||
if (source.getPath().contains("," + targetParentId + ",")) {
|
if (targetParent.getPath().contains(source.getPath())) {
|
||||||
throw new ServiceException("不能将文件夹移动到其子目录下");
|
throw new ServiceException("不能将文件夹移动到其子目录下");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,6 +250,7 @@ public class HseFileFolderServiceImpl extends ServiceImpl<HseFileFolderMapper, H
|
|||||||
String oldPath = source.getPath();
|
String oldPath = source.getPath();
|
||||||
String oldParentPath = source.getParentId() == 0 ? ",0," : getById(source.getParentId()).getPath();
|
String oldParentPath = source.getParentId() == 0 ? ",0," : getById(source.getParentId()).getPath();
|
||||||
String newParentPath = targetParent.getPath();
|
String newParentPath = targetParent.getPath();
|
||||||
|
int oldLevel = source.getLevel();
|
||||||
|
|
||||||
// 4. 计算新路径和新层级
|
// 4. 计算新路径和新层级
|
||||||
String newPath = newParentPath + id + ",";
|
String newPath = newParentPath + id + ",";
|
||||||
@ -260,7 +267,7 @@ public class HseFileFolderServiceImpl extends ServiceImpl<HseFileFolderMapper, H
|
|||||||
// 计算路径替换的前后缀
|
// 计算路径替换的前后缀
|
||||||
String pathReplaceFrom = oldPath;
|
String pathReplaceFrom = oldPath;
|
||||||
String pathReplaceTo = newPath;
|
String pathReplaceTo = newPath;
|
||||||
int levelDiff = newLevel - source.getLevel(); // 层级变化量
|
int levelDiff = newLevel - oldLevel; // 层级变化量
|
||||||
|
|
||||||
// 批量更新子项
|
// 批量更新子项
|
||||||
baseMapper.batchUpdateChildPaths(pathReplaceFrom, pathReplaceTo, levelDiff, id);
|
baseMapper.batchUpdateChildPaths(pathReplaceFrom, pathReplaceTo, levelDiff, id);
|
||||||
@ -268,4 +275,262 @@ public class HseFileFolderServiceImpl extends ServiceImpl<HseFileFolderMapper, H
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional
|
||||||
|
public String uploadAndUnzip(MultipartFile file, Long parentId, Long projectId) throws Exception {
|
||||||
|
// 1. 参数验证
|
||||||
|
if (file == null || file.isEmpty()) {
|
||||||
|
throw new ServiceException("上传文件不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 验证文件类型是否为ZIP
|
||||||
|
String originalFilename = file.getOriginalFilename();
|
||||||
|
if (originalFilename == null || !originalFilename.toLowerCase().endsWith(".zip")) {
|
||||||
|
throw new ServiceException("只支持上传ZIP格式的文件");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 验证父目录是否存在且为文件夹
|
||||||
|
HseFileFolder parentFolder = null;
|
||||||
|
if (parentId != null && parentId != 0) {
|
||||||
|
parentFolder = getById(parentId);
|
||||||
|
if (parentFolder == null || parentFolder.getType() != 1) {
|
||||||
|
throw new ServiceException("指定的父目录不存在或不是文件夹");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 创建临时文件用于解压
|
||||||
|
File tempZipFile = File.createTempFile("upload_", ".zip");
|
||||||
|
try {
|
||||||
|
// 5. 保存上传的文件到临时位置
|
||||||
|
file.transferTo(tempZipFile);
|
||||||
|
|
||||||
|
// 6. 解压ZIP文件
|
||||||
|
String unzipResult = doUnzipFile(tempZipFile, parentId, projectId, parentFolder);
|
||||||
|
|
||||||
|
return unzipResult;
|
||||||
|
} finally {
|
||||||
|
// 7. 清理临时文件
|
||||||
|
if (tempZipFile.exists()) {
|
||||||
|
tempZipFile.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 实际执行解压操作的方法
|
||||||
|
*
|
||||||
|
* @param zipFile ZIP文件
|
||||||
|
* @param parentId 父目录ID
|
||||||
|
* @param projectId 项目ID
|
||||||
|
* @param parentFolder 父目录对象
|
||||||
|
* @return 解压结果信息
|
||||||
|
* @throws Exception 解压过程中可能出现的异常
|
||||||
|
*/
|
||||||
|
private String doUnzipFile(File zipFile, Long parentId, Long projectId, HseFileFolder parentFolder) throws Exception {
|
||||||
|
// 用于记录解压的文件数量
|
||||||
|
int fileCount = 0;
|
||||||
|
int folderCount = 0;
|
||||||
|
|
||||||
|
// 获取父级路径信息
|
||||||
|
String parentPath = parentId == null || parentId == 0 ? "," : parentFolder.getPath();
|
||||||
|
int parentLevel = parentId == null || parentId == 0 ? 0 : parentFolder.getLevel();
|
||||||
|
|
||||||
|
try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile), Charset.forName("GBK"))) {
|
||||||
|
ZipEntry entry;
|
||||||
|
while ((entry = zis.getNextEntry()) != null) {
|
||||||
|
// 跳过目录项(目录会根据文件路径自动创建)
|
||||||
|
if (entry.isDirectory()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String entryName = entry.getName();
|
||||||
|
// 处理中文文件名乱码问题
|
||||||
|
if (!Charset.forName("GBK").newEncoder().canEncode(entryName)) {
|
||||||
|
// 尝试用UTF-8编码解析
|
||||||
|
entryName = new String(entryName.getBytes("ISO-8859-1"), "UTF-8");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分离路径和文件名
|
||||||
|
String[] pathParts = entryName.split("/");
|
||||||
|
String fileName = pathParts[pathParts.length - 1];
|
||||||
|
|
||||||
|
// 构造文件在系统中的虚拟路径
|
||||||
|
Long currentParentId = parentId == null ? 0L : parentId;
|
||||||
|
String currentPath = parentPath;
|
||||||
|
|
||||||
|
// 如果ZIP中有目录结构,则需要逐级创建文件夹
|
||||||
|
for (int i = 0; i < pathParts.length - 1; i++) {
|
||||||
|
String folderName = pathParts[i];
|
||||||
|
if (folderName.isEmpty()) continue;
|
||||||
|
|
||||||
|
// 查找是否已存在同名文件夹
|
||||||
|
LambdaQueryWrapper<HseFileFolder> folderQuery = Wrappers.lambdaQuery();
|
||||||
|
folderQuery.eq(HseFileFolder::getProjectId, projectId)
|
||||||
|
.eq(HseFileFolder::getParentId, currentParentId)
|
||||||
|
.eq(HseFileFolder::getName, folderName)
|
||||||
|
.eq(HseFileFolder::getType, 1); // 文件夹类型
|
||||||
|
|
||||||
|
HseFileFolder existingFolder = getOne(folderQuery);
|
||||||
|
|
||||||
|
if (existingFolder == null) {
|
||||||
|
// 创建新的文件夹
|
||||||
|
HseFileFolder newFolder = new HseFileFolder();
|
||||||
|
newFolder.setProjectId(projectId);
|
||||||
|
newFolder.setName(folderName);
|
||||||
|
newFolder.setParentId(currentParentId);
|
||||||
|
newFolder.setType(1); // 文件夹
|
||||||
|
newFolder.setLevel(parentLevel + i + 1);
|
||||||
|
newFolder.setSort(0);
|
||||||
|
newFolder.setPath(currentPath);
|
||||||
|
|
||||||
|
// 先保存获取ID
|
||||||
|
save(newFolder);
|
||||||
|
|
||||||
|
// 更新路径,格式为 ,parentId,childId,
|
||||||
|
newFolder.setPath(currentPath + newFolder.getId() + ",");
|
||||||
|
updateById(newFolder);
|
||||||
|
|
||||||
|
currentParentId = newFolder.getId();
|
||||||
|
currentPath = newFolder.getPath();
|
||||||
|
folderCount++;
|
||||||
|
} else {
|
||||||
|
currentParentId = existingFolder.getId();
|
||||||
|
currentPath = existingFolder.getPath();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建文件记录
|
||||||
|
HseFileFolder fileRecord = new HseFileFolder();
|
||||||
|
fileRecord.setProjectId(projectId);
|
||||||
|
fileRecord.setName(fileName);
|
||||||
|
fileRecord.setParentId(currentParentId);
|
||||||
|
fileRecord.setType(2); // 文件类型
|
||||||
|
fileRecord.setLevel(parentLevel + pathParts.length);
|
||||||
|
// 文件路径格式为 ,parentId,fileId,
|
||||||
|
fileRecord.setPath(currentPath + fileRecord.getId() + ",");
|
||||||
|
|
||||||
|
// 设置文件扩展名
|
||||||
|
int dotIndex = fileName.lastIndexOf(".");
|
||||||
|
if (dotIndex > 0 && dotIndex < fileName.length() - 1) {
|
||||||
|
fileRecord.setFileSuffix(fileName.substring(dotIndex + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: 这里应该与实际文件存储服务集成,设置真实的文件路径
|
||||||
|
fileRecord.setFilePath(""); // 实际应用中应设置真实文件存储路径
|
||||||
|
|
||||||
|
save(fileRecord);
|
||||||
|
|
||||||
|
// 更新文件的路径(因为ID是自增的,需要先保存再更新路径)
|
||||||
|
fileRecord.setPath(currentPath + fileRecord.getId() + ",");
|
||||||
|
updateById(fileRecord);
|
||||||
|
|
||||||
|
fileCount++;
|
||||||
|
|
||||||
|
zis.closeEntry();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return String.format("解压完成,共创建 %d 个文件夹,%d 个文件", folderCount, fileCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional
|
||||||
|
public String unzip(Long id, Long parentId) {
|
||||||
|
// 1. 参数验证
|
||||||
|
if (id == null) {
|
||||||
|
throw new ServiceException("文件ID不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 获取要解压的ZIP文件
|
||||||
|
HseFileFolder zipFile = getById(id);
|
||||||
|
if (zipFile == null) {
|
||||||
|
throw new ServiceException("指定的文件不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 验证是否为ZIP文件
|
||||||
|
if (!"zip".equalsIgnoreCase(zipFile.getFileSuffix())) {
|
||||||
|
throw new ServiceException("只能解压ZIP格式的文件");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 验证文件路径是否存在
|
||||||
|
if (StringUtils.isBlank(zipFile.getFilePath())) {
|
||||||
|
throw new ServiceException("文件存储路径不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. 验证目标目录是否存在且为文件夹
|
||||||
|
HseFileFolder parentFolder = null;
|
||||||
|
if (parentId != null && parentId != 0) {
|
||||||
|
parentFolder = getById(parentId);
|
||||||
|
if (parentFolder == null || parentFolder.getType() != 1) {
|
||||||
|
throw new ServiceException("指定的目标目录不存在或不是文件夹");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6. 下载ZIP文件到临时位置
|
||||||
|
try {
|
||||||
|
// 从URL下载文件
|
||||||
|
String fileUrl = zipFile.getFilePath();
|
||||||
|
File tempZipFile = downloadFileToTemp(fileUrl);
|
||||||
|
|
||||||
|
if (tempZipFile == null || !tempZipFile.exists()) {
|
||||||
|
throw new ServiceException("下载文件失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 7. 解压ZIP文件
|
||||||
|
String unzipResult = doUnzipFile(tempZipFile, parentId, zipFile.getProjectId(), parentFolder);
|
||||||
|
return unzipResult;
|
||||||
|
} finally {
|
||||||
|
// 8. 清理临时文件
|
||||||
|
if (tempZipFile.exists()) {
|
||||||
|
tempZipFile.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new ServiceException("解压文件失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从URL下载文件到临时位置
|
||||||
|
*
|
||||||
|
* @param fileUrl 文件URL
|
||||||
|
* @return 临时文件
|
||||||
|
* @throws Exception 下载过程中的异常
|
||||||
|
*/
|
||||||
|
private File downloadFileToTemp(String fileUrl) throws Exception {
|
||||||
|
// 创建临时文件
|
||||||
|
File tempFile = File.createTempFile("download_", ".zip");
|
||||||
|
|
||||||
|
// 使用Apache HttpClient或其他HTTP客户端下载文件
|
||||||
|
// 这里简化处理,实际项目中应根据具体文件存储服务实现
|
||||||
|
|
||||||
|
// 示例实现(需要根据实际文件存储服务调整):
|
||||||
|
/*
|
||||||
|
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
|
||||||
|
HttpGet httpGet = new HttpGet(fileUrl);
|
||||||
|
try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
|
||||||
|
HttpEntity entity = response.getEntity();
|
||||||
|
if (entity != null) {
|
||||||
|
try (InputStream inputStream = entity.getContent();
|
||||||
|
FileOutputStream outputStream = new FileOutputStream(tempFile)) {
|
||||||
|
byte[] buffer = new byte[8192];
|
||||||
|
int bytesRead;
|
||||||
|
while ((bytesRead = inputStream.read(buffer)) != -1) {
|
||||||
|
outputStream.write(buffer, 0, bytesRead);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 如果使用MinIO或其他存储服务,需要相应调整实现
|
||||||
|
|
||||||
|
// 占位实现,实际需要根据文件存储服务来实现
|
||||||
|
throw new ServiceException("未实现文件下载功能,请根据实际文件存储服务完善此方法");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,6 +13,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
update_time = NOW()
|
update_time = NOW()
|
||||||
WHERE
|
WHERE
|
||||||
path LIKE CONCAT(#{oldPath}, '%')
|
path LIKE CONCAT(#{oldPath}, '%')
|
||||||
AND parent_id != #{parentId}
|
AND id != #{parentId}
|
||||||
</update>
|
</update>
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|||||||
Reference in New Issue
Block a user