优化
This commit is contained in:
@ -1,5 +1,6 @@
|
||||
package org.dromara.project.domain.dto.leave;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
@ -26,12 +27,14 @@ public class BusLeaveManagerReviewReq implements Serializable {
|
||||
* 管理员意见(1未读 2同意 3拒绝)
|
||||
*/
|
||||
@NotNull(message = "管理员意见不能为空")
|
||||
private String managerOpinion;
|
||||
private String gangerOpinion;
|
||||
|
||||
/**
|
||||
* 管理员说明
|
||||
* 班组长说明
|
||||
*/
|
||||
private String managerExplain;
|
||||
@ExcelProperty(value = "班组长说明")
|
||||
private String gangerExplain;
|
||||
|
||||
|
||||
/**
|
||||
* 备注
|
||||
|
||||
@ -6,8 +6,11 @@ import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
import org.dromara.common.excel.annotation.ExcelDictFormat;
|
||||
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.BusLeave;
|
||||
import org.dromara.project.domain.vo.reissuecard.AuditUserVo;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
@ -65,6 +68,9 @@ public class BusLeaveVo implements Serializable {
|
||||
@ExcelDictFormat(dictType = "user_leave_type")
|
||||
private String leaveType;
|
||||
|
||||
@Translation(type = TransConstant.DICT_TYPE_TO_LABEL, mapper = "leaveType",other = "user_leave_type")
|
||||
private String leaveTypeName;
|
||||
|
||||
/**
|
||||
* 请假开始时间
|
||||
*/
|
||||
|
||||
@ -760,6 +760,7 @@ public class BusAttendanceServiceImpl extends ServiceImpl<BusAttendanceMapper, B
|
||||
.eq(BusAttendance::getUserId, userId)
|
||||
.eq(b, BusAttendance::getProjectId, projectId)
|
||||
.in(BusAttendance::getClockStatus, abnormalList)
|
||||
.ge(BusAttendance::getClockDate, LocalDate.now().minusDays(29))
|
||||
.orderByDesc(BusAttendance::getClockDate)
|
||||
.orderByDesc(BusAttendance::getRuleTime)
|
||||
);
|
||||
|
||||
@ -59,6 +59,8 @@ import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.dromara.common.core.constant.TenantConstants.SUPER_ADMIN_ID;
|
||||
|
||||
/**
|
||||
* 施工人员请假申请Service业务层处理
|
||||
*
|
||||
@ -236,73 +238,79 @@ public class BusLeaveServiceImpl extends ServiceImpl<BusLeaveMapper, BusLeave>
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean managerReview(BusLeaveManagerReviewReq req) {
|
||||
Long id = req.getId();
|
||||
String managerOpinion = req.getManagerOpinion();
|
||||
// 判断该请假记录是否存在
|
||||
BusLeave oldLeave = this.getById(id);
|
||||
if (oldLeave == null) {
|
||||
throw new ServiceException("施工人员请假申请不存在", HttpStatus.NOT_FOUND);
|
||||
|
||||
BusLeave busLeave = baseMapper.selectById(req.getId());
|
||||
if (busLeave == null) {
|
||||
throw new ServiceException("未找到该申请");
|
||||
}
|
||||
// 如果已经审核过,则返回
|
||||
if (!BusOpinionStatusEnum.UNREAD.getValue().equals(oldLeave.getManagerOpinion())) {
|
||||
throw new ServiceException("该请假已审核,请勿重复操作", HttpStatus.BAD_REQUEST);
|
||||
String gangerOpinion = req.getGangerOpinion();
|
||||
busLeave.setGangerOpinion(gangerOpinion);
|
||||
busLeave.setGangerExplain(req.getGangerExplain());
|
||||
if(busLeave.getGangerId() == null){
|
||||
LoginUser loginUser = LoginHelper.getLoginUser();
|
||||
busLeave.setGangerName(loginUser.getNickname());
|
||||
busLeave.setGangerId(loginUser.getUserId());
|
||||
}
|
||||
// 判断班组长是否审核通过
|
||||
String gangerOpinion = oldLeave.getGangerOpinion();
|
||||
if (!BusOpinionStatusEnum.PASS.getValue().equals(gangerOpinion)) {
|
||||
throw new ServiceException("请等待班组长审核通过后再进行操作", HttpStatus.BAD_REQUEST);
|
||||
|
||||
busLeave.setGangerTime(LocalDateTime.now());
|
||||
|
||||
int i = baseMapper.updateById(busLeave);
|
||||
|
||||
if(gangerOpinion.equals("2")){
|
||||
if(busLeave.getTimeType().equals("1")){
|
||||
LocalDateTime startTime = busLeave.getStartTime();
|
||||
LocalDateTime endTime = busLeave.getEndTime();
|
||||
LocalDate startDate = startTime.toLocalDate();
|
||||
LocalDate endDate = endTime.toLocalDate();
|
||||
|
||||
List<BusAttendance> list = attendanceService.list(Wrappers.lambdaQuery(BusAttendance.class)
|
||||
.eq(BusAttendance::getProjectId, busLeave.getProjectId())
|
||||
.le(BusAttendance::getClockDate, endDate)
|
||||
.ge(BusAttendance::getClockDate, startDate)
|
||||
.eq(BusAttendance::getUserId, busLeave.getUserId())
|
||||
);
|
||||
for (BusAttendance attendance : list) {
|
||||
attendance.setClockStatus(BusAttendanceClockStatusEnum.LATE.getValue());
|
||||
}
|
||||
if(!list.isEmpty()){
|
||||
attendanceService.updateBatchById(list);
|
||||
}
|
||||
}else if(busLeave.getTimeType().equals("2")){
|
||||
if(busLeave.getPeriodType().equals("1")){
|
||||
LocalDateTime startTime = busLeave.getStartTime();
|
||||
LocalDate localDate = startTime.toLocalDate();
|
||||
List<BusAttendance> list = attendanceService.list(Wrappers.lambdaQuery(BusAttendance.class)
|
||||
.eq(BusAttendance::getProjectId, busLeave.getProjectId())
|
||||
.eq(BusAttendance::getClockDate, localDate)
|
||||
.eq(BusAttendance::getClockType, "1")
|
||||
.eq(BusAttendance::getUserId, busLeave.getUserId())
|
||||
);
|
||||
for (BusAttendance attendance : list) {
|
||||
attendance.setClockStatus(BusAttendanceClockStatusEnum.LATE.getValue());
|
||||
}
|
||||
if(!list.isEmpty()){
|
||||
attendanceService.updateBatchById(list);
|
||||
}
|
||||
|
||||
}else if(busLeave.getPeriodType().equals("2")){
|
||||
LocalDateTime endTime = busLeave.getEndTime();
|
||||
LocalDate localDate = endTime.toLocalDate();
|
||||
List<BusAttendance> list = attendanceService.list(Wrappers.lambdaQuery(BusAttendance.class)
|
||||
.eq(BusAttendance::getProjectId, busLeave.getProjectId())
|
||||
.eq(BusAttendance::getClockDate, localDate)
|
||||
.eq(BusAttendance::getClockType, "2")
|
||||
.eq(BusAttendance::getUserId, busLeave.getUserId())
|
||||
);
|
||||
for (BusAttendance attendance : list) {
|
||||
attendance.setClockStatus(BusAttendanceClockStatusEnum.LATE.getValue());
|
||||
}
|
||||
if(!list.isEmpty()){
|
||||
attendanceService.updateBatchById(list);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// todo 判断当前用户是否为项目管理员
|
||||
// 判断是否为分包公司管理员
|
||||
Long contractorId = oldLeave.getContractorId();
|
||||
SubConstructionUser constructionUser = constructionUserService.lambdaQuery()
|
||||
.eq(SubConstructionUser::getSysUserId, LoginHelper.getUserId())
|
||||
.eq(SubConstructionUser::getContractorId, contractorId)
|
||||
.eq(SubConstructionUser::getUserRole, SubConstructionUserRoleEnum.ADMIN.getValue())
|
||||
.one();
|
||||
if (constructionUser == null) {
|
||||
throw new ServiceException("您无权审核该请假申请", HttpStatus.FORBIDDEN);
|
||||
}
|
||||
// 填充默认值,更新数据
|
||||
BusLeave leave = new BusLeave();
|
||||
leave.setId(id);
|
||||
leave.setManagerId(constructionUser.getId());
|
||||
leave.setManagerOpinion(managerOpinion);
|
||||
leave.setManagerExplain(req.getManagerExplain());
|
||||
leave.setManagerTime(LocalDateTime.now());
|
||||
leave.setRemark(req.getRemark());
|
||||
boolean result = this.updateById(leave);
|
||||
if (!result) {
|
||||
throw new ServiceException("更新管理员审核操作失败", HttpStatus.ERROR);
|
||||
}
|
||||
// 更新考勤表记录
|
||||
LocalDateTime startTime = oldLeave.getStartTime();
|
||||
LocalDateTime endTime = oldLeave.getEndTime();
|
||||
// 计算相差的时间
|
||||
// long diffInMillis = endTime.getTime() - startTime.getTime();
|
||||
// long day = TimeUnit.MILLISECONDS.toDays(diffInMillis) + 1;
|
||||
// Long userId = oldLeave.getUserId();
|
||||
// String userName = oldLeave.getUserName();
|
||||
// Long projectId = oldLeave.getProjectId();
|
||||
// 遍历每一天
|
||||
List<BusAttendance> attendanceList = new ArrayList<>();
|
||||
// for (long i = 0; i < day; i++) {
|
||||
// BusAttendance attendance = new BusAttendance();
|
||||
// attendance.setUserId(userId);
|
||||
// attendance.setUserName(userName);
|
||||
// attendance.setProjectId(projectId);
|
||||
// Date date = DateUtils.addDays(startTime, (int) i);
|
||||
// attendance.setLeaveId(id);
|
||||
// attendance.setClockDate(date);
|
||||
// attendance.setClockStatus(BusAttendanceClockStatusEnum.LEAVE.getValue());
|
||||
// attendance.setCommuter(BusAttendanceCommuterEnum.ALLDAY.getValue());
|
||||
// attendanceList.add(attendance);
|
||||
// }
|
||||
boolean saveBatch = attendanceService.saveBatch(attendanceList);
|
||||
if (!saveBatch) {
|
||||
throw new ServiceException("更新考勤记录失败", HttpStatus.ERROR);
|
||||
}
|
||||
return true;
|
||||
return i>0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -375,7 +383,7 @@ public class BusLeaveServiceImpl extends ServiceImpl<BusLeaveMapper, BusLeave>
|
||||
// 精确查询
|
||||
lqw.eq(ObjectUtils.isNotEmpty(id), BusLeave::getId, id);
|
||||
lqw.eq(ObjectUtils.isNotEmpty(userId), BusLeave::getUserId, userId);
|
||||
lqw.eq(ObjectUtils.isNotEmpty(gangerId), BusLeave::getGangerId, gangerId);
|
||||
lqw.eq(ObjectUtils.isNotEmpty(gangerId) && !Objects.equals(gangerId, SUPER_ADMIN_ID), BusLeave::getGangerId, gangerId);
|
||||
lqw.eq(StringUtils.isNotBlank(gangerOpinion), BusLeave::getGangerOpinion, gangerOpinion);
|
||||
lqw.eq(StringUtils.isNotBlank(managerOpinion), BusLeave::getManagerOpinion, managerOpinion);
|
||||
lqw.eq(ObjectUtils.isNotEmpty(projectId), BusLeave::getProjectId, projectId);
|
||||
@ -418,6 +426,28 @@ public class BusLeaveServiceImpl extends ServiceImpl<BusLeaveMapper, BusLeave>
|
||||
// 添加审核状态
|
||||
String status = BusReviewStatusEnum.getEnumByOpinionStatus(leave.getGangerOpinion(), leave.getManagerOpinion());
|
||||
leaveVo.setAuditStatus(status);
|
||||
|
||||
//添加审核人
|
||||
if(StrUtil.isBlank(leaveVo.getGangerName())){
|
||||
String userType = leaveVo.getUserType();
|
||||
List<SysUser> sysUsers = new ArrayList<>();
|
||||
if(leaveVo.getGangerId()==null){
|
||||
if("1".equals(userType)){
|
||||
sysUsers = userService.selectUserByRoleIdAndProjectId(6L, leaveVo.getProjectId());
|
||||
} else if ("2".equals(userType)) {
|
||||
sysUsers = userService.selectUserByRoleIdAndProjectId(7L, leaveVo.getProjectId());
|
||||
}
|
||||
}else {
|
||||
SysUserVo sysUserVo = userService.selectUserById(leaveVo.getGangerId());
|
||||
if(sysUserVo != null){
|
||||
leaveVo.setGangerName(sysUserVo.getNickName());
|
||||
}
|
||||
}
|
||||
if(CollectionUtil.isNotEmpty(sysUsers)){
|
||||
String collect = sysUsers.stream().map(SysUser::getNickName).collect(Collectors.joining());
|
||||
leaveVo.setGangerName(collect);
|
||||
}
|
||||
}
|
||||
return leaveVo;
|
||||
}).toList();
|
||||
leaveVoPage.setRecords(leaveVoList);
|
||||
@ -462,6 +492,12 @@ public class BusLeaveServiceImpl extends ServiceImpl<BusLeaveMapper, BusLeave>
|
||||
|
||||
// 5. 保存新记录(需补充完整字段赋值)
|
||||
leave.setUserTime(LocalDateTime.now());
|
||||
//插入班组
|
||||
SubConstructionUser bySysUserId = constructionUserService.getBySysUserId(userId);
|
||||
if (bySysUserId != null) {
|
||||
leave.setTeamId(bySysUserId.getTeamId());
|
||||
leave.setContractorId(bySysUserId.getContractorId());
|
||||
}
|
||||
this.save(leave);
|
||||
return leave.getId();
|
||||
}
|
||||
|
||||
@ -359,6 +359,28 @@ public class BusReissueCardServiceImpl extends ServiceImpl<BusReissueCardMapper,
|
||||
// 添加审核状态
|
||||
String status = BusReviewStatusEnum.getEnumByOpinionStatus(reissueCard.getGangerOpinion(), reissueCard.getManagerOpinion());
|
||||
reissueCardVo.setStatus(status);
|
||||
|
||||
//添加审核人
|
||||
if(StrUtil.isBlank(reissueCardVo.getGangerName())){
|
||||
String userType = reissueCardVo.getUserType();
|
||||
List<SysUser> sysUsers = new ArrayList<>();
|
||||
if(reissueCardVo.getGangerId()==null){
|
||||
if("1".equals(userType)){
|
||||
sysUsers = userService.selectUserByRoleIdAndProjectId(6L, reissueCardVo.getProjectId());
|
||||
} else if ("2".equals(userType)) {
|
||||
sysUsers = userService.selectUserByRoleIdAndProjectId(7L, reissueCardVo.getProjectId());
|
||||
}
|
||||
}else {
|
||||
SysUserVo sysUserVo = userService.selectUserById(reissueCardVo.getGangerId());
|
||||
if(sysUserVo != null){
|
||||
reissueCardVo.setGangerName(sysUserVo.getNickName());
|
||||
}
|
||||
}
|
||||
if(CollectionUtil.isNotEmpty(sysUsers)){
|
||||
String collect = sysUsers.stream().map(SysUser::getNickName).collect(Collectors.joining());
|
||||
reissueCardVo.setGangerName(collect);
|
||||
}
|
||||
}
|
||||
return reissueCardVo;
|
||||
}).toList();
|
||||
reissueCardVoPage.setRecords(reissueCardVoList);
|
||||
|
||||
@ -0,0 +1,140 @@
|
||||
package org.dromara.safety.controller;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.constraints.*;
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import org.dromara.safety.domain.HseFileFolder;
|
||||
import org.dromara.safety.domain.dto.fileFolder.FileFolderCreateDTO;
|
||||
import org.dromara.safety.domain.dto.fileFolder.FileFolderMoveDTO;
|
||||
import org.dromara.safety.domain.dto.fileFolder.ListQueryDto;
|
||||
import org.dromara.safety.domain.vo.fileFolder.FileFolderTreeVO;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.dromara.common.idempotent.annotation.RepeatSubmit;
|
||||
import org.dromara.common.log.annotation.Log;
|
||||
import org.dromara.common.web.core.BaseController;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
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.log.enums.BusinessType;
|
||||
import org.dromara.common.excel.utils.ExcelUtil;
|
||||
import org.dromara.safety.domain.vo.HseFileFolderVo;
|
||||
import org.dromara.safety.domain.bo.HseFileFolderBo;
|
||||
import org.dromara.safety.service.IHseFileFolderService;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
|
||||
/**
|
||||
* 会议纪要
|
||||
*
|
||||
* @author Lion Li
|
||||
* @date 2025-10-14
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/safety/fileFolder")
|
||||
public class HseFileFolderController extends BaseController {
|
||||
|
||||
private final IHseFileFolderService hseFileFolderService;
|
||||
|
||||
/**
|
||||
* 查询会议纪要列表
|
||||
*/
|
||||
@GetMapping("/list-all")
|
||||
public R<List<HseFileFolderVo>> listAll(ListQueryDto dto) {
|
||||
return R.ok(hseFileFolderService.listAll(dto));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询指定目录的树形结构(一次性加载所有层级)
|
||||
* @return 树形结构列表
|
||||
*/
|
||||
@GetMapping("/tree-all")
|
||||
public R<List<FileFolderTreeVO>> treeAll(ListQueryDto dto) {
|
||||
|
||||
// 1. 查询所有子项(利用path前缀匹配,一次性加载所有层级)
|
||||
List<HseFileFolder> allItems = hseFileFolderService.list(new LambdaQueryWrapper<HseFileFolder>()
|
||||
.like(HseFileFolder::getPath, "," + dto.getParentId() + ",") // 包含父ID的所有子项
|
||||
.eq(dto.getType()!=null,HseFileFolder::getType, dto.getType())
|
||||
.orderByDesc(HseFileFolder::getId)
|
||||
.orderByAsc(HseFileFolder::getSort)
|
||||
);
|
||||
|
||||
// 2. 构建树形结构
|
||||
List<FileFolderTreeVO> treeVOS = buildTree(allItems, dto.getParentId());
|
||||
return R.ok(treeVOS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归构建树形结构
|
||||
*/
|
||||
private List<FileFolderTreeVO> buildTree(List<HseFileFolder> allItems, Long parentId) {
|
||||
return allItems.stream()
|
||||
.filter(item -> parentId.equals(item.getParentId()))
|
||||
.map(item -> {
|
||||
FileFolderTreeVO vo = new FileFolderTreeVO();
|
||||
// 复制基本属性(可使用BeanUtils.copyProperties)
|
||||
vo.setId(item.getId());
|
||||
vo.setName(item.getName());
|
||||
vo.setParentId(item.getParentId());
|
||||
vo.setType(item.getType());
|
||||
vo.setLevel(item.getLevel());
|
||||
vo.setSort(item.getSort());
|
||||
vo.setFileSuffix(item.getFileSuffix());
|
||||
|
||||
// 递归查询子节点
|
||||
vo.setChildren(buildTree(allItems, item.getId()));
|
||||
return vo;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建文件或文件夹
|
||||
*/
|
||||
@PostMapping("/create")
|
||||
public R<HseFileFolder> create(@RequestBody FileFolderCreateDTO dto) {
|
||||
return R.ok(hseFileFolderService.createFileOrFolder(dto));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除文件或文件夹(级联删除子项)
|
||||
*/
|
||||
@DeleteMapping("/{id}")
|
||||
@Transactional
|
||||
public R<Boolean> delete(@PathVariable Long id) {
|
||||
return R.ok(hseFileFolderService.deleteFileOrFolder(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 移动文件或文件夹到指定目录
|
||||
*/
|
||||
@PostMapping("/move")
|
||||
@Transactional
|
||||
public R<Boolean> move(@RequestBody FileFolderMoveDTO dto) {
|
||||
return R.ok(hseFileFolderService.moveFileOrFolder(dto.getId(), dto.getTargetParentId()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,92 @@
|
||||
package org.dromara.safety.domain;
|
||||
|
||||
import org.dromara.common.mybatis.core.domain.BaseEntity;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* 会议纪要对象 hse_file_folder
|
||||
*
|
||||
* @author Lion Li
|
||||
* @date 2025-10-14
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("hse_file_folder")
|
||||
public class HseFileFolder extends BaseEntity {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(value = "id")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 项目id
|
||||
*/
|
||||
private Long projectId;
|
||||
|
||||
/**
|
||||
* 名称(文件名或文件夹名)
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 父级ID(0表示根目录)
|
||||
*/
|
||||
private Long parentId;
|
||||
|
||||
/**
|
||||
* 类型(1-文件夹,2-文件)
|
||||
*/
|
||||
private Integer type;
|
||||
|
||||
/**
|
||||
* 层级(根目录为1,子级+1)
|
||||
*/
|
||||
private Integer level;
|
||||
|
||||
/**
|
||||
* 同层级排序号
|
||||
*/
|
||||
private Integer sort;
|
||||
|
||||
/**
|
||||
* 层级路径(如:1,2,3 表示ID为1→2→3的层级)
|
||||
*/
|
||||
private String path;
|
||||
|
||||
/**
|
||||
* 文件id
|
||||
*/
|
||||
private Long fileId;
|
||||
|
||||
/**
|
||||
* 文件后缀
|
||||
*/
|
||||
private String fileSuffix;
|
||||
|
||||
/**
|
||||
* 存储路径
|
||||
*/
|
||||
private String filePath;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 删除标志(0代表存在 1代表删除)
|
||||
*/
|
||||
// @TableLogic
|
||||
private String delFlag;
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,90 @@
|
||||
package org.dromara.safety.domain.bo;
|
||||
|
||||
import org.dromara.safety.domain.HseFileFolder;
|
||||
import org.dromara.common.mybatis.core.domain.BaseEntity;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
import org.dromara.common.core.validate.EditGroup;
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import jakarta.validation.constraints.*;
|
||||
|
||||
/**
|
||||
* 会议纪要业务对象 hse_file_folder
|
||||
*
|
||||
* @author Lion Li
|
||||
* @date 2025-10-14
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@AutoMapper(target = HseFileFolder.class, reverseConvertGenerate = false)
|
||||
public class HseFileFolderBo extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@NotNull(message = "主键ID不能为空", groups = { EditGroup.class })
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 项目id
|
||||
*/
|
||||
@NotNull(message = "项目id不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private Long projectId;
|
||||
|
||||
/**
|
||||
* 名称(文件名或文件夹名)
|
||||
*/
|
||||
@NotBlank(message = "名称(文件名或文件夹名)不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 父级ID(0表示根目录)
|
||||
*/
|
||||
private Long parentId;
|
||||
|
||||
/**
|
||||
* 类型(1-文件夹,2-文件)
|
||||
*/
|
||||
@NotNull(message = "类型(1-文件夹,2-文件)不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private Integer type;
|
||||
|
||||
/**
|
||||
* 层级(根目录为1,子级+1)
|
||||
*/
|
||||
@NotNull(message = "层级(根目录为1,子级+1)不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private Integer level;
|
||||
|
||||
/**
|
||||
* 同层级排序号
|
||||
*/
|
||||
private Integer sort;
|
||||
|
||||
/**
|
||||
* 层级路径(如:1,2,3 表示ID为1→2→3的层级)
|
||||
*/
|
||||
@NotBlank(message = "层级路径(如:1,2,3 表示ID为1→2→3的层级)不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String path;
|
||||
|
||||
/**
|
||||
* 文件id
|
||||
*/
|
||||
private Long fileId;
|
||||
|
||||
/**
|
||||
* 文件后缀
|
||||
*/
|
||||
private String fileSuffix;
|
||||
|
||||
/**
|
||||
* 存储路径
|
||||
*/
|
||||
private String filePath;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,51 @@
|
||||
package org.dromara.safety.domain.dto.fileFolder;
|
||||
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
|
||||
|
||||
@Data
|
||||
public class FileFolderCreateDTO {
|
||||
|
||||
/**
|
||||
* 名称
|
||||
*/
|
||||
@NotBlank(message = "名称不能为空")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 父级ID(0表示根目录)
|
||||
*/
|
||||
private Long parentId = 0L;
|
||||
|
||||
/**
|
||||
* 文件类型
|
||||
*/
|
||||
@NotNull(message = "类型不能为空")
|
||||
private Integer type;
|
||||
|
||||
/**
|
||||
* 排序号
|
||||
*/
|
||||
private Integer sort=0;
|
||||
|
||||
/**
|
||||
* 文件后缀
|
||||
*/
|
||||
private String fileSuffix;
|
||||
|
||||
/**
|
||||
* 文件存储路径(仅文件有效)
|
||||
*/
|
||||
private String filePath;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,14 @@
|
||||
package org.dromara.safety.domain.dto.fileFolder;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class FileFolderMoveDTO {
|
||||
|
||||
@NotNull(message = "文件/文件夹ID不能为空")
|
||||
private Long id;
|
||||
|
||||
@NotNull(message = "目标父目录ID不能为空")
|
||||
private Long targetParentId;
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
package org.dromara.safety.domain.dto.fileFolder;
|
||||
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class ListQueryDto {
|
||||
/**
|
||||
* 父目录ID,默认0(根目录)
|
||||
*/
|
||||
@NotNull(message = "父目录ID不能为空")
|
||||
private Long parentId;
|
||||
|
||||
|
||||
/**
|
||||
* 类型:1-文件夹,2-文件,null-全部
|
||||
*/
|
||||
private Integer type;
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,109 @@
|
||||
package org.dromara.safety.domain.vo;
|
||||
|
||||
import org.dromara.safety.domain.HseFileFolder;
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import org.dromara.common.excel.annotation.ExcelDictFormat;
|
||||
import org.dromara.common.excel.convert.ExcelDictConvert;
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 会议纪要视图对象 hse_file_folder
|
||||
*
|
||||
* @author Lion Li
|
||||
* @date 2025-10-14
|
||||
*/
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
@AutoMapper(target = HseFileFolder.class)
|
||||
public class HseFileFolderVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@ExcelProperty(value = "主键ID")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 项目id
|
||||
*/
|
||||
@ExcelProperty(value = "项目id")
|
||||
private Long projectId;
|
||||
|
||||
/**
|
||||
* 名称(文件名或文件夹名)
|
||||
*/
|
||||
@ExcelProperty(value = "名称", converter = ExcelDictConvert.class)
|
||||
@ExcelDictFormat(readConverterExp = "文=件名或文件夹名")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 父级ID(0表示根目录)
|
||||
*/
|
||||
@ExcelProperty(value = "父级ID", converter = ExcelDictConvert.class)
|
||||
@ExcelDictFormat(readConverterExp = "0=表示根目录")
|
||||
private Long parentId;
|
||||
|
||||
/**
|
||||
* 类型(1-文件夹,2-文件)
|
||||
*/
|
||||
@ExcelProperty(value = "类型", converter = ExcelDictConvert.class)
|
||||
@ExcelDictFormat(readConverterExp = "1=-文件夹,2-文件")
|
||||
private Integer type;
|
||||
|
||||
/**
|
||||
* 层级(根目录为1,子级+1)
|
||||
*/
|
||||
@ExcelProperty(value = "层级", converter = ExcelDictConvert.class)
|
||||
@ExcelDictFormat(readConverterExp = "根=目录为1,子级+1")
|
||||
private Integer level;
|
||||
|
||||
/**
|
||||
* 同层级排序号
|
||||
*/
|
||||
@ExcelProperty(value = "同层级排序号")
|
||||
private Integer sort;
|
||||
|
||||
/**
|
||||
* 层级路径(如:1,2,3 表示ID为1→2→3的层级)
|
||||
*/
|
||||
@ExcelProperty(value = "层级路径", converter = ExcelDictConvert.class)
|
||||
@ExcelDictFormat(readConverterExp = "如=:1,2,3,表=示ID为1→2→3的层级")
|
||||
private String path;
|
||||
|
||||
/**
|
||||
* 文件id
|
||||
*/
|
||||
@ExcelProperty(value = "文件id")
|
||||
private Long fileId;
|
||||
|
||||
/**
|
||||
* 文件后缀
|
||||
*/
|
||||
@ExcelProperty(value = "文件后缀")
|
||||
private String fileSuffix;
|
||||
|
||||
/**
|
||||
* 存储路径
|
||||
*/
|
||||
@ExcelProperty(value = "存储路径")
|
||||
private String filePath;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@ExcelProperty(value = "")
|
||||
private String remark;
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,53 @@
|
||||
package org.dromara.safety.domain.vo.fileFolder;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class FileFolderTreeVO {
|
||||
|
||||
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 名称(文件名或文件夹名)
|
||||
*/
|
||||
private String name;
|
||||
|
||||
|
||||
/**
|
||||
* 父级ID(0表示根目录)
|
||||
*/
|
||||
private Long parentId;
|
||||
|
||||
/**
|
||||
* 1-文件夹,2-文件
|
||||
*/
|
||||
private Integer type;
|
||||
|
||||
/**
|
||||
* 层级(根目录为1,子级+1)
|
||||
*/
|
||||
private Integer level;
|
||||
|
||||
/**
|
||||
* 同层级排序号
|
||||
*/
|
||||
private Integer sort;
|
||||
|
||||
/**
|
||||
* 文件id
|
||||
*/
|
||||
private Long fileId;
|
||||
|
||||
/**
|
||||
* 文件后缀
|
||||
*/
|
||||
private String fileSuffix;
|
||||
|
||||
/**
|
||||
* 子级
|
||||
*/
|
||||
private List<FileFolderTreeVO> children;
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
package org.dromara.safety.mapper;
|
||||
|
||||
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.dromara.safety.domain.HseFileFolder;
|
||||
import org.dromara.safety.domain.vo.HseFileFolderVo;
|
||||
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
|
||||
/**
|
||||
* 会议纪要Mapper接口
|
||||
*
|
||||
* @author Lion Li
|
||||
* @date 2025-10-14
|
||||
*/
|
||||
public interface HseFileFolderMapper extends BaseMapperPlus<HseFileFolder, HseFileFolderVo> {
|
||||
|
||||
/**
|
||||
* 批量更新子项的路径和层级
|
||||
*/
|
||||
void batchUpdateChildPaths(
|
||||
@Param("oldPath") String oldPath,
|
||||
@Param("newPath") String newPath,
|
||||
@Param("levelDiff") int levelDiff,
|
||||
@Param("parentId") Long parentId);
|
||||
}
|
||||
@ -0,0 +1,90 @@
|
||||
package org.dromara.safety.service;
|
||||
|
||||
import org.dromara.safety.domain.dto.fileFolder.FileFolderCreateDTO;
|
||||
import org.dromara.safety.domain.dto.fileFolder.ListQueryDto;
|
||||
import org.dromara.safety.domain.vo.HseFileFolderVo;
|
||||
import org.dromara.safety.domain.bo.HseFileFolderBo;
|
||||
import org.dromara.safety.domain.HseFileFolder;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 会议纪要Service接口
|
||||
*
|
||||
* @author Lion Li
|
||||
* @date 2025-10-14
|
||||
*/
|
||||
public interface IHseFileFolderService extends IService<HseFileFolder>{
|
||||
|
||||
/**
|
||||
* 查询会议纪要
|
||||
*
|
||||
* @param id 主键
|
||||
* @return 会议纪要
|
||||
*/
|
||||
HseFileFolderVo queryById(Long id);
|
||||
|
||||
/**
|
||||
* 分页查询会议纪要列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @param pageQuery 分页参数
|
||||
* @return 会议纪要分页列表
|
||||
*/
|
||||
TableDataInfo<HseFileFolderVo> queryPageList(HseFileFolderBo bo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 查询符合条件的会议纪要列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @return 会议纪要列表
|
||||
*/
|
||||
List<HseFileFolderVo> queryList(HseFileFolderBo bo);
|
||||
|
||||
/**
|
||||
* 新增会议纪要
|
||||
*
|
||||
* @param bo 会议纪要
|
||||
* @return 是否新增成功
|
||||
*/
|
||||
Boolean insertByBo(HseFileFolderBo bo);
|
||||
|
||||
/**
|
||||
* 修改会议纪要
|
||||
*
|
||||
* @param bo 会议纪要
|
||||
* @return 是否修改成功
|
||||
*/
|
||||
Boolean updateByBo(HseFileFolderBo bo);
|
||||
|
||||
/**
|
||||
* 校验并批量删除会议纪要信息
|
||||
*
|
||||
* @param ids 待删除的主键集合
|
||||
* @param isValid 是否进行有效性校验
|
||||
* @return 是否删除成功
|
||||
*/
|
||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||
|
||||
|
||||
List<HseFileFolderVo> listAll(ListQueryDto dto);
|
||||
|
||||
/**
|
||||
* 创建文件或文件夹
|
||||
*/
|
||||
HseFileFolder createFileOrFolder(FileFolderCreateDTO dto);
|
||||
|
||||
/**
|
||||
* 删除文件或文件夹(级联删除子项)
|
||||
*/
|
||||
boolean deleteFileOrFolder(Long id);
|
||||
|
||||
/**
|
||||
* 移动文件或文件夹到指定目录
|
||||
*/
|
||||
boolean moveFileOrFolder(Long id, Long targetParentId);
|
||||
}
|
||||
@ -0,0 +1,271 @@
|
||||
package org.dromara.safety.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
import org.dromara.common.core.utils.MapstructUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.safety.domain.dto.fileFolder.FileFolderCreateDTO;
|
||||
import org.dromara.safety.domain.dto.fileFolder.ListQueryDto;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.dromara.safety.domain.bo.HseFileFolderBo;
|
||||
import org.dromara.safety.domain.vo.HseFileFolderVo;
|
||||
import org.dromara.safety.domain.HseFileFolder;
|
||||
import org.dromara.safety.mapper.HseFileFolderMapper;
|
||||
import org.dromara.safety.service.IHseFileFolderService;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* 会议纪要Service业务层处理
|
||||
*
|
||||
* @author Lion Li
|
||||
* @date 2025-10-14
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class HseFileFolderServiceImpl extends ServiceImpl<HseFileFolderMapper, HseFileFolder> implements IHseFileFolderService {
|
||||
|
||||
private final HseFileFolderMapper baseMapper;
|
||||
|
||||
/**
|
||||
* 查询会议纪要
|
||||
*
|
||||
* @param id 主键
|
||||
* @return 会议纪要
|
||||
*/
|
||||
@Override
|
||||
public HseFileFolderVo queryById(Long id){
|
||||
return baseMapper.selectVoById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询会议纪要列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @param pageQuery 分页参数
|
||||
* @return 会议纪要分页列表
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<HseFileFolderVo> queryPageList(HseFileFolderBo bo, PageQuery pageQuery) {
|
||||
LambdaQueryWrapper<HseFileFolder> lqw = buildQueryWrapper(bo);
|
||||
Page<HseFileFolderVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||
return TableDataInfo.build(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询符合条件的会议纪要列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @return 会议纪要列表
|
||||
*/
|
||||
@Override
|
||||
public List<HseFileFolderVo> queryList(HseFileFolderBo bo) {
|
||||
LambdaQueryWrapper<HseFileFolder> lqw = buildQueryWrapper(bo);
|
||||
return baseMapper.selectVoList(lqw);
|
||||
}
|
||||
|
||||
private LambdaQueryWrapper<HseFileFolder> buildQueryWrapper(HseFileFolderBo bo) {
|
||||
Map<String, Object> params = bo.getParams();
|
||||
LambdaQueryWrapper<HseFileFolder> lqw = Wrappers.lambdaQuery();
|
||||
lqw.orderByDesc(HseFileFolder::getId);
|
||||
lqw.orderByAsc(HseFileFolder::getSort);
|
||||
lqw.eq(bo.getProjectId() != null, HseFileFolder::getProjectId, bo.getProjectId());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getName()), HseFileFolder::getName, bo.getName());
|
||||
lqw.eq(bo.getParentId() != null, HseFileFolder::getParentId, bo.getParentId());
|
||||
lqw.eq(bo.getType() != null, HseFileFolder::getType, bo.getType());
|
||||
lqw.eq(bo.getLevel() != null, HseFileFolder::getLevel, bo.getLevel());
|
||||
lqw.eq(bo.getSort() != null, HseFileFolder::getSort, bo.getSort());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getPath()), HseFileFolder::getPath, bo.getPath());
|
||||
lqw.eq(bo.getFileId() != null, HseFileFolder::getFileId, bo.getFileId());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getFileSuffix()), HseFileFolder::getFileSuffix, bo.getFileSuffix());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getFilePath()), HseFileFolder::getFilePath, bo.getFilePath());
|
||||
return lqw;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增会议纪要
|
||||
*
|
||||
* @param bo 会议纪要
|
||||
* @return 是否新增成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean insertByBo(HseFileFolderBo bo) {
|
||||
HseFileFolder add = MapstructUtils.convert(bo, HseFileFolder.class);
|
||||
validEntityBeforeSave(add);
|
||||
boolean flag = baseMapper.insert(add) > 0;
|
||||
if (flag) {
|
||||
bo.setId(add.getId());
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改会议纪要
|
||||
*
|
||||
* @param bo 会议纪要
|
||||
* @return 是否修改成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean updateByBo(HseFileFolderBo bo) {
|
||||
HseFileFolder update = MapstructUtils.convert(bo, HseFileFolder.class);
|
||||
validEntityBeforeSave(update);
|
||||
return baseMapper.updateById(update) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存前的数据校验
|
||||
*/
|
||||
private void validEntityBeforeSave(HseFileFolder entity){
|
||||
//TODO 做一些数据校验,如唯一约束
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验并批量删除会议纪要信息
|
||||
*
|
||||
* @param ids 待删除的主键集合
|
||||
* @param isValid 是否进行有效性校验
|
||||
* @return 是否删除成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||
if(isValid){
|
||||
//TODO 做一些业务上的校验,判断是否需要校验
|
||||
}
|
||||
return baseMapper.deleteByIds(ids) > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<HseFileFolderVo> listAll(ListQueryDto dto) {
|
||||
|
||||
LambdaQueryWrapper<HseFileFolder> lqw = Wrappers.lambdaQuery();
|
||||
lqw.orderByDesc(HseFileFolder::getId);
|
||||
lqw.orderByAsc(HseFileFolder::getSort);
|
||||
|
||||
lqw.eq(HseFileFolder::getParentId, dto.getParentId());
|
||||
lqw.eq(dto.getType()!=null,HseFileFolder::getType, dto.getType());
|
||||
|
||||
return baseMapper.selectVoList(lqw);
|
||||
}
|
||||
|
||||
public HseFileFolder createFileOrFolder(FileFolderCreateDTO dto) {
|
||||
// 1. 验证父目录是否存在
|
||||
if (dto.getParentId() != 0) {
|
||||
HseFileFolder parent = getById(dto.getParentId());
|
||||
if (parent == null || parent.getType() != 1) { // 父级必须是文件夹
|
||||
throw new ServiceException("父目录不存在或不是文件夹");
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 构建新文件/文件夹对象
|
||||
HseFileFolder entity = new HseFileFolder();
|
||||
entity.setName(dto.getName());
|
||||
entity.setParentId(dto.getParentId());
|
||||
entity.setType(dto.getType());
|
||||
entity.setSort(dto.getSort() != null ? dto.getSort() : 0);
|
||||
entity.setRemark(dto.getRemark());
|
||||
|
||||
|
||||
// 3. 设置层级和路径
|
||||
if (dto.getParentId() == 0) { // 根目录
|
||||
entity.setLevel(1);
|
||||
entity.setPath("," + entity.getId() + ","); // ID会在插入后自动生成,这里先占位
|
||||
} else { // 子目录/文件
|
||||
HseFileFolder parent = getById(dto.getParentId());
|
||||
entity.setLevel(parent.getLevel() + 1);
|
||||
entity.setPath(parent.getPath() + entity.getId() + ","); // ID会在插入后更新
|
||||
}
|
||||
|
||||
// 4. 处理文件特有属性
|
||||
if (dto.getType() == 2) { // 如果是文件
|
||||
entity.setFileSuffix(dto.getFileSuffix());
|
||||
entity.setFilePath(dto.getFilePath());
|
||||
}
|
||||
|
||||
// 5. 保存并更新路径(因为ID是自增的,需要先保存再更新路径)
|
||||
save(entity);
|
||||
|
||||
// 6. 修正路径中的ID
|
||||
if (dto.getParentId() == 0) {
|
||||
entity.setPath("," + entity.getId() + ",");
|
||||
} else {
|
||||
HseFileFolder parent = getById(dto.getParentId());
|
||||
entity.setPath(parent.getPath() + entity.getId() + ",");
|
||||
}
|
||||
updateById(entity);
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public boolean deleteFileOrFolder(Long id) {
|
||||
HseFileFolder entity = getById(id);
|
||||
if (entity == null) {
|
||||
throw new ServiceException("文件/文件夹不存在");
|
||||
}
|
||||
|
||||
// 1. 删除自身及所有子项(通过path匹配)
|
||||
LambdaQueryWrapper<HseFileFolder> queryWrapper = Wrappers.<HseFileFolder>lambdaQuery()
|
||||
.like(HseFileFolder::getPath, "," + id + ",");
|
||||
|
||||
return remove(queryWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public boolean moveFileOrFolder(Long id, Long targetParentId) {
|
||||
// 1. 验证源文件和目标目录是否存在
|
||||
HseFileFolder source = getById(id);
|
||||
if (source == null) {
|
||||
throw new ServiceException("源文件/文件夹不存在");
|
||||
}
|
||||
|
||||
HseFileFolder targetParent = getById(targetParentId);
|
||||
if (targetParent == null || targetParent.getType() != 1) {
|
||||
throw new ServiceException("目标目录不存在或不是文件夹");
|
||||
}
|
||||
|
||||
// 2. 防止循环移动(不能移动到自身或子目录下)
|
||||
if (source.getPath().contains("," + targetParentId + ",")) {
|
||||
throw new ServiceException("不能将文件夹移动到其子目录下");
|
||||
}
|
||||
|
||||
// 3. 获取原路径和新路径的前缀
|
||||
String oldPath = source.getPath();
|
||||
String oldParentPath = source.getParentId() == 0 ? ",0," : getById(source.getParentId()).getPath();
|
||||
String newParentPath = targetParent.getPath();
|
||||
|
||||
// 4. 计算新路径和新层级
|
||||
String newPath = newParentPath + id + ",";
|
||||
int newLevel = targetParent.getLevel() + 1;
|
||||
|
||||
// 5. 更新自身信息
|
||||
source.setParentId(targetParentId);
|
||||
source.setLevel(newLevel);
|
||||
source.setPath(newPath);
|
||||
updateById(source);
|
||||
|
||||
// 6. 更新所有子项的路径和层级
|
||||
if (source.getType() == 1) { // 如果是文件夹,需要更新其子项
|
||||
// 计算路径替换的前后缀
|
||||
String pathReplaceFrom = oldPath;
|
||||
String pathReplaceTo = newPath;
|
||||
int levelDiff = newLevel - source.getLevel(); // 层级变化量
|
||||
|
||||
// 批量更新子项
|
||||
baseMapper.batchUpdateChildPaths(pathReplaceFrom, pathReplaceTo, levelDiff, id);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="org.dromara.safety.mapper.HseFileFolderMapper">
|
||||
|
||||
<!-- 批量更新子项的路径和层级 -->
|
||||
<update id="batchUpdateChildPaths">
|
||||
UPDATE hse_file_folder
|
||||
SET
|
||||
path = REPLACE(path, #{oldPath}, #{newPath}),
|
||||
level = level + #{levelDiff},
|
||||
update_time = NOW()
|
||||
WHERE
|
||||
path LIKE CONCAT(#{oldPath}, '%')
|
||||
AND parent_id != #{parentId}
|
||||
</update>
|
||||
</mapper>
|
||||
Reference in New Issue
Block a user