opt: 附件上传/删除
This commit is contained in:
@@ -111,5 +111,16 @@ public interface DevFileApi {
|
|||||||
*/
|
*/
|
||||||
JSONObject getFileInfoById(String id);
|
JSONObject getFileInfoById(String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过文件地址获取文件信息
|
||||||
|
* @param fileAddress 文件地址
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
JSONObject getFileInfoByUrl(String fileAddress);
|
JSONObject getFileInfoByUrl(String fileAddress);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过文件id删除文件
|
||||||
|
* @param fileId
|
||||||
|
*/
|
||||||
|
void deleteById(String fileId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,4 +91,9 @@ public class DevFileApiProvider implements DevFileApi {
|
|||||||
.map(JSONUtil::parseObj)
|
.map(JSONUtil::parseObj)
|
||||||
.orElse(new JSONObject());
|
.orElse(new JSONObject());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteById(String fileId) {
|
||||||
|
devFileService.removeById(fileId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,29 +15,29 @@ package org.nl.pmm.modular.projectfile.controller;
|
|||||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||||
import cn.dev33.satoken.annotation.SaIgnore;
|
import cn.dev33.satoken.annotation.SaIgnore;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
|
import org.nl.common.annotation.CommonLog;
|
||||||
|
import org.nl.common.pojo.CommonResult;
|
||||||
|
import org.nl.pmm.modular.projectfile.entity.ProjectFile;
|
||||||
import org.nl.pmm.modular.projectfile.param.*;
|
import org.nl.pmm.modular.projectfile.param.*;
|
||||||
|
import org.nl.pmm.modular.projectfile.service.ProjectFileService;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import org.nl.common.annotation.CommonLog;
|
|
||||||
import org.nl.common.pojo.CommonResult;
|
|
||||||
import org.nl.pmm.modular.projectfile.entity.ProjectFile;
|
|
||||||
import org.nl.pmm.modular.projectfile.service.ProjectFileService;
|
|
||||||
|
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
import jakarta.validation.Valid;
|
|
||||||
import jakarta.validation.constraints.NotEmpty;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 项目附件表控制器
|
* 项目附件表控制器
|
||||||
*
|
*
|
||||||
* @author liyongde
|
* @author liyongde
|
||||||
* @date 2025/11/17 20:24
|
* @date 2025/11/17 20:24
|
||||||
*/
|
*/
|
||||||
@Tag(name = "项目附件表控制器")
|
@Tag(name = "项目附件表控制器")
|
||||||
@RestController
|
@RestController
|
||||||
@@ -51,7 +51,7 @@ public class ProjectFileController {
|
|||||||
* 获取项目附件表分页
|
* 获取项目附件表分页
|
||||||
*
|
*
|
||||||
* @author liyongde
|
* @author liyongde
|
||||||
* @date 2025/11/17 20:24
|
* @date 2025/11/17 20:24
|
||||||
*/
|
*/
|
||||||
@Operation(summary = "获取项目附件表分页")
|
@Operation(summary = "获取项目附件表分页")
|
||||||
@SaCheckPermission("/pmm/projectfile/page")
|
@SaCheckPermission("/pmm/projectfile/page")
|
||||||
@@ -64,7 +64,7 @@ public class ProjectFileController {
|
|||||||
* 添加项目附件表
|
* 添加项目附件表
|
||||||
*
|
*
|
||||||
* @author liyongde
|
* @author liyongde
|
||||||
* @date 2025/11/17 20:24
|
* @date 2025/11/17 20:24
|
||||||
*/
|
*/
|
||||||
@Operation(summary = "添加项目附件表")
|
@Operation(summary = "添加项目附件表")
|
||||||
@CommonLog("添加项目附件表")
|
@CommonLog("添加项目附件表")
|
||||||
@@ -79,7 +79,7 @@ public class ProjectFileController {
|
|||||||
* 编辑项目附件表
|
* 编辑项目附件表
|
||||||
*
|
*
|
||||||
* @author liyongde
|
* @author liyongde
|
||||||
* @date 2025/11/17 20:24
|
* @date 2025/11/17 20:24
|
||||||
*/
|
*/
|
||||||
@Operation(summary = "编辑项目附件表")
|
@Operation(summary = "编辑项目附件表")
|
||||||
@CommonLog("编辑项目附件表")
|
@CommonLog("编辑项目附件表")
|
||||||
@@ -94,22 +94,23 @@ public class ProjectFileController {
|
|||||||
* 删除项目附件表
|
* 删除项目附件表
|
||||||
*
|
*
|
||||||
* @author liyongde
|
* @author liyongde
|
||||||
* @date 2025/11/17 20:24
|
* @date 2025/11/17 20:24
|
||||||
*/
|
*/
|
||||||
@Operation(summary = "删除项目附件表")
|
@Operation(summary = "删除项目附件表")
|
||||||
@CommonLog("删除项目附件表")
|
@CommonLog("删除项目附件表")
|
||||||
@SaCheckPermission("/pmm/projectfile/delete")
|
@SaCheckPermission("/pmm/projectfile/delete")
|
||||||
@PostMapping("/pmm/projectfile/delete")
|
@PostMapping("/pmm/projectfile/delete")
|
||||||
public CommonResult<String> delete(@RequestBody @Valid @NotEmpty(message = "集合不能为空")
|
public CommonResult<String> delete(@RequestBody @Valid @NotEmpty(message = "集合不能为空")
|
||||||
List<ProjectFileIdParam> projectFileIdParamList) {
|
List<ProjectFileIdParam> projectFileIdParamList) {
|
||||||
projectFileService.delete(projectFileIdParamList);
|
projectFileService.delete(projectFileIdParamList);
|
||||||
return CommonResult.ok();
|
return CommonResult.ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除项目附件表
|
* 删除项目附件表
|
||||||
*
|
*
|
||||||
* @author liyongde
|
* @author liyongde
|
||||||
* @date 2025/11/17 20:24
|
* @date 2025/11/17 20:24
|
||||||
*/
|
*/
|
||||||
@Operation(summary = "保存项目附件表")
|
@Operation(summary = "保存项目附件表")
|
||||||
@CommonLog("保存项目附件表")
|
@CommonLog("保存项目附件表")
|
||||||
@@ -125,7 +126,7 @@ public class ProjectFileController {
|
|||||||
* 获取项目附件表详情
|
* 获取项目附件表详情
|
||||||
*
|
*
|
||||||
* @author liyongde
|
* @author liyongde
|
||||||
* @date 2025/11/17 20:24
|
* @date 2025/11/17 20:24
|
||||||
*/
|
*/
|
||||||
@Operation(summary = "获取项目附件表详情")
|
@Operation(summary = "获取项目附件表详情")
|
||||||
@SaCheckPermission("/pmm/projectfile/detail")
|
@SaCheckPermission("/pmm/projectfile/detail")
|
||||||
@@ -133,4 +134,19 @@ public class ProjectFileController {
|
|||||||
public CommonResult<ProjectFile> detail(@Valid ProjectFileIdParam projectFileIdParam) {
|
public CommonResult<ProjectFile> detail(@Valid ProjectFileIdParam projectFileIdParam) {
|
||||||
return CommonResult.data(projectFileService.detail(projectFileIdParam));
|
return CommonResult.data(projectFileService.detail(projectFileIdParam));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除项目附件表
|
||||||
|
*
|
||||||
|
* @author liyongde
|
||||||
|
* @date 2025/11/17 20:24
|
||||||
|
*/
|
||||||
|
@Operation(summary = "删除项目附件表")
|
||||||
|
@CommonLog("删除项目附件表")
|
||||||
|
@SaCheckPermission("/pmm/projectfile/delete-file")
|
||||||
|
@PostMapping("/pmm/projectfile/delete-file")
|
||||||
|
public CommonResult<String> deleteFile(@RequestBody ProjectFileParam param) {
|
||||||
|
projectFileService.deleteAttachment(param);
|
||||||
|
return CommonResult.ok();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package org.nl.pmm.modular.projectfile.param;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: lyd
|
||||||
|
* @Date: 2025/11/21
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class ProjectFileParam {
|
||||||
|
private String id;
|
||||||
|
}
|
||||||
@@ -79,4 +79,6 @@ public interface ProjectFileService extends IService<ProjectFile> {
|
|||||||
List<ProjectAttachmentVo> getFileByProjectId(String projectId);
|
List<ProjectAttachmentVo> getFileByProjectId(String projectId);
|
||||||
|
|
||||||
void bindProjectFile(ProjectFileAddParam param);
|
void bindProjectFile(ProjectFileAddParam param);
|
||||||
|
|
||||||
|
void deleteAttachment(ProjectFileParam param);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import cn.hutool.core.collection.CollStreamUtil;
|
|||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.hutool.json.JSONObject;
|
import cn.hutool.json.JSONObject;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
@@ -28,10 +29,7 @@ import org.nl.dev.api.DevFileApi;
|
|||||||
import org.nl.pmm.modular.project.entity.vo.ProjectAttachmentVo;
|
import org.nl.pmm.modular.project.entity.vo.ProjectAttachmentVo;
|
||||||
import org.nl.pmm.modular.projectfile.entity.ProjectFile;
|
import org.nl.pmm.modular.projectfile.entity.ProjectFile;
|
||||||
import org.nl.pmm.modular.projectfile.mapper.ProjectFileMapper;
|
import org.nl.pmm.modular.projectfile.mapper.ProjectFileMapper;
|
||||||
import org.nl.pmm.modular.projectfile.param.ProjectFileAddParam;
|
import org.nl.pmm.modular.projectfile.param.*;
|
||||||
import org.nl.pmm.modular.projectfile.param.ProjectFileEditParam;
|
|
||||||
import org.nl.pmm.modular.projectfile.param.ProjectFileIdParam;
|
|
||||||
import org.nl.pmm.modular.projectfile.param.ProjectFilePageParam;
|
|
||||||
import org.nl.pmm.modular.projectfile.service.ProjectFileService;
|
import org.nl.pmm.modular.projectfile.service.ProjectFileService;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
@@ -111,4 +109,12 @@ public class ProjectFileServiceImpl extends ServiceImpl<ProjectFileMapper, Proje
|
|||||||
param.setFileAddress(file.getStr("downloadPath"));
|
param.setFileAddress(file.getStr("downloadPath"));
|
||||||
add(param);
|
add(param);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteAttachment(ProjectFileParam param) {
|
||||||
|
// 删除文件
|
||||||
|
devFileApi.deleteById(param.getId());
|
||||||
|
// 删除附件表记录
|
||||||
|
remove(new LambdaQueryWrapper<ProjectFile>().eq(ProjectFile::getFileId, param.getId()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import cn.dev33.satoken.annotation.SaCheckPermission;
|
|||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import org.nl.pmm.modular.projectstage.param.*;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
@@ -24,10 +25,6 @@ import org.springframework.web.bind.annotation.RestController;
|
|||||||
import org.nl.common.annotation.CommonLog;
|
import org.nl.common.annotation.CommonLog;
|
||||||
import org.nl.common.pojo.CommonResult;
|
import org.nl.common.pojo.CommonResult;
|
||||||
import org.nl.pmm.modular.projectstage.entity.ProjectStage;
|
import org.nl.pmm.modular.projectstage.entity.ProjectStage;
|
||||||
import org.nl.pmm.modular.projectstage.param.ProjectStageAddParam;
|
|
||||||
import org.nl.pmm.modular.projectstage.param.ProjectStageEditParam;
|
|
||||||
import org.nl.pmm.modular.projectstage.param.ProjectStageIdParam;
|
|
||||||
import org.nl.pmm.modular.projectstage.param.ProjectStagePageParam;
|
|
||||||
import org.nl.pmm.modular.projectstage.service.ProjectStageService;
|
import org.nl.pmm.modular.projectstage.service.ProjectStageService;
|
||||||
|
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
@@ -91,6 +88,20 @@ public class ProjectStageController {
|
|||||||
projectStageService.edit(projectStageEditParam);
|
projectStageService.edit(projectStageEditParam);
|
||||||
return CommonResult.ok();
|
return CommonResult.ok();
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* 编辑项目阶段
|
||||||
|
*
|
||||||
|
* @author liyongde
|
||||||
|
* @date 2025/11/17 20:32
|
||||||
|
*/
|
||||||
|
@Operation(summary = "编辑项目阶段")
|
||||||
|
@CommonLog("编辑项目阶段")
|
||||||
|
// @SaCheckPermission("/pmm/projectstage/batch-edit")
|
||||||
|
@PostMapping("/pmm/projectstage/batch-edit")
|
||||||
|
public CommonResult<String> batchEdit(@RequestBody @Valid List<ProjectStageAddBatchParam> param) {
|
||||||
|
projectStageService.batchEdit(param);
|
||||||
|
return CommonResult.ok();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除项目阶段
|
* 删除项目阶段
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package org.nl.pmm.modular.projectstage.param;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: lyd
|
||||||
|
* @Date: 2025/11/19
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class ProjectStageAddBatchParam {
|
||||||
|
/** 阶段名称 */
|
||||||
|
@Schema(description = "阶段名称")
|
||||||
|
private String stageName;
|
||||||
|
|
||||||
|
/** 阶段序号 */
|
||||||
|
@Schema(description = "阶段序号")
|
||||||
|
private String stageSeq;
|
||||||
|
|
||||||
|
/** 项目id */
|
||||||
|
@Schema(description = "项目id")
|
||||||
|
private String projectId;
|
||||||
|
|
||||||
|
/** 阶段id */
|
||||||
|
@Schema(description = "阶段id")
|
||||||
|
private String stageId;
|
||||||
|
|
||||||
|
/** 是否删除 */
|
||||||
|
@Schema(description = "是否删除")
|
||||||
|
private Boolean isDeleted;
|
||||||
|
}
|
||||||
@@ -15,10 +15,7 @@ package org.nl.pmm.modular.projectstage.service;
|
|||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
import org.nl.pmm.modular.projectstage.entity.ProjectStage;
|
import org.nl.pmm.modular.projectstage.entity.ProjectStage;
|
||||||
import org.nl.pmm.modular.projectstage.param.ProjectStageAddParam;
|
import org.nl.pmm.modular.projectstage.param.*;
|
||||||
import org.nl.pmm.modular.projectstage.param.ProjectStageEditParam;
|
|
||||||
import org.nl.pmm.modular.projectstage.param.ProjectStageIdParam;
|
|
||||||
import org.nl.pmm.modular.projectstage.param.ProjectStagePageParam;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -84,4 +81,6 @@ public interface ProjectStageService extends IService<ProjectStage> {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
List<ProjectStage> getByProjectId(String projectId);
|
List<ProjectStage> getByProjectId(String projectId);
|
||||||
|
|
||||||
|
void batchEdit(List<ProjectStageAddBatchParam> param);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,10 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.nl.pmm.modular.projectstage.param.*;
|
||||||
|
import org.nl.pmm.modular.stagedetail.entity.StageDetail;
|
||||||
|
import org.nl.pmm.modular.stagedetail.service.StageDetailService;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.nl.common.enums.CommonSortOrderEnum;
|
import org.nl.common.enums.CommonSortOrderEnum;
|
||||||
@@ -27,13 +31,12 @@ import org.nl.common.exception.CommonException;
|
|||||||
import org.nl.common.page.CommonPageRequest;
|
import org.nl.common.page.CommonPageRequest;
|
||||||
import org.nl.pmm.modular.projectstage.entity.ProjectStage;
|
import org.nl.pmm.modular.projectstage.entity.ProjectStage;
|
||||||
import org.nl.pmm.modular.projectstage.mapper.ProjectStageMapper;
|
import org.nl.pmm.modular.projectstage.mapper.ProjectStageMapper;
|
||||||
import org.nl.pmm.modular.projectstage.param.ProjectStageAddParam;
|
|
||||||
import org.nl.pmm.modular.projectstage.param.ProjectStageEditParam;
|
|
||||||
import org.nl.pmm.modular.projectstage.param.ProjectStageIdParam;
|
|
||||||
import org.nl.pmm.modular.projectstage.param.ProjectStagePageParam;
|
|
||||||
import org.nl.pmm.modular.projectstage.service.ProjectStageService;
|
import org.nl.pmm.modular.projectstage.service.ProjectStageService;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 项目阶段Service接口实现类
|
* 项目阶段Service接口实现类
|
||||||
@@ -44,6 +47,9 @@ import java.util.List;
|
|||||||
@Service
|
@Service
|
||||||
public class ProjectStageServiceImpl extends ServiceImpl<ProjectStageMapper, ProjectStage> implements ProjectStageService {
|
public class ProjectStageServiceImpl extends ServiceImpl<ProjectStageMapper, ProjectStage> implements ProjectStageService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private StageDetailService stageDetailService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Page<ProjectStage> page(ProjectStagePageParam projectStagePageParam) {
|
public Page<ProjectStage> page(ProjectStagePageParam projectStagePageParam) {
|
||||||
QueryWrapper<ProjectStage> queryWrapper = new QueryWrapper<ProjectStage>().checkSqlInjection();
|
QueryWrapper<ProjectStage> queryWrapper = new QueryWrapper<ProjectStage>().checkSqlInjection();
|
||||||
@@ -100,4 +106,31 @@ public class ProjectStageServiceImpl extends ServiceImpl<ProjectStageMapper, Pro
|
|||||||
.orderByAsc(ProjectStage::getStageSeq);
|
.orderByAsc(ProjectStage::getStageSeq);
|
||||||
return list(lambdaQueryWrapper);
|
return list(lambdaQueryWrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void batchEdit(List<ProjectStageAddBatchParam> param) {
|
||||||
|
// 获取新增的 / 修改的
|
||||||
|
List<ProjectStageAddBatchParam> addItems = param.stream().filter(p ->
|
||||||
|
(ObjectUtil.isEmpty(p.getStageId()) && !p.getIsDeleted())
|
||||||
|
|| (ObjectUtil.isNotEmpty(p.getStageId()) && !p.getIsDeleted())).toList();
|
||||||
|
if (addItems.size() > 0) {
|
||||||
|
List<ProjectStage> projectStageList = new ArrayList<>();
|
||||||
|
for (ProjectStageAddBatchParam addItem : addItems) {
|
||||||
|
ProjectStage projectStage = BeanUtil.toBean(addItem, ProjectStage.class);
|
||||||
|
projectStageList.add(projectStage);
|
||||||
|
}
|
||||||
|
saveOrUpdateBatch(projectStageList);
|
||||||
|
}
|
||||||
|
// 获取删除的
|
||||||
|
List<ProjectStageAddBatchParam> deletedItems = param.stream().filter(p -> ObjectUtil.isNotEmpty(p.getStageId()) && p.getIsDeleted()).toList();
|
||||||
|
if (deletedItems.size() > 0) {
|
||||||
|
List<String> ids = new ArrayList<>();
|
||||||
|
for (ProjectStageAddBatchParam deletedItem : deletedItems) {
|
||||||
|
ids.add(deletedItem.getStageId());
|
||||||
|
}
|
||||||
|
// 删除明细
|
||||||
|
stageDetailService.remove(new LambdaQueryWrapper<StageDetail>().in(StageDetail::getStageId, ids));
|
||||||
|
removeBatchByIds(ids);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,5 +28,9 @@ export default {
|
|||||||
// 获取项目附件表详情
|
// 获取项目附件表详情
|
||||||
bindProjectFile(data) {
|
bindProjectFile(data) {
|
||||||
return request('bindProjectFile', data, 'post')
|
return request('bindProjectFile', data, 'post')
|
||||||
|
},
|
||||||
|
// 获取项目附件表详情
|
||||||
|
deleteFile(data) {
|
||||||
|
return request('delete-file', data, 'post')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,5 +24,9 @@ export default {
|
|||||||
// 获取项目阶段详情
|
// 获取项目阶段详情
|
||||||
projectStageDetail(data) {
|
projectStageDetail(data) {
|
||||||
return request('detail', data, 'get')
|
return request('detail', data, 'get')
|
||||||
|
},
|
||||||
|
// 获取项目阶段详情
|
||||||
|
batchEdit(data) {
|
||||||
|
return request('batch-edit', data, 'post')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
153
nl-vue/src/views/pmm/project/request/batchStageAddDialog.vue
Normal file
153
nl-vue/src/views/pmm/project/request/batchStageAddDialog.vue
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
<template>
|
||||||
|
<xn-form-container title="编辑项目阶段" :width="700" v-model:open="open" :destroy-on-close="true" @close="onClose">
|
||||||
|
<div class="stage-form">
|
||||||
|
<div class="stage-form__header">
|
||||||
|
<div>阶段名称</div>
|
||||||
|
<div>阶段序号</div>
|
||||||
|
<div>操作</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="!visibleStages.length" class="stage-form__empty">
|
||||||
|
<a-empty description="暂无阶段,请新增一行" />
|
||||||
|
</div>
|
||||||
|
<div v-for="(stage, index) in visibleStages" :key="stage._key ?? index" class="stage-form__row">
|
||||||
|
<a-input v-model:value="stage.stageName" placeholder="请输入阶段名称" allow-clear :maxlength="50" />
|
||||||
|
<a-input-number v-model:value="stage.stageSeq" placeholder="请输入阶段序号" :min="1" style="width: 100%" />
|
||||||
|
<a-space>
|
||||||
|
<a-tooltip title="删除当前行以及需求">
|
||||||
|
<a-button type="link" danger @click="removeRow(stage)">删除</a-button>
|
||||||
|
</a-tooltip>
|
||||||
|
</a-space>
|
||||||
|
</div>
|
||||||
|
<a-button type="dashed" block @click="addRow"> 新增一行 </a-button>
|
||||||
|
</div>
|
||||||
|
<template #footer>
|
||||||
|
<a-button style="margin-right: 8px" @click="onClose">关闭</a-button>
|
||||||
|
<a-button type="primary" @click="onSubmit" :loading="submitLoading">保存</a-button>
|
||||||
|
</template>
|
||||||
|
</xn-form-container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="projectStageForm">
|
||||||
|
import projectStageApi from '@/api/pmm/projectStageApi'
|
||||||
|
import { createVNode } from 'vue'
|
||||||
|
import { Modal } from 'ant-design-vue'
|
||||||
|
import { ExclamationCircleOutlined } from '@ant-design/icons-vue'
|
||||||
|
import { cloneDeep } from 'lodash-es'
|
||||||
|
// 抽屉状态
|
||||||
|
const open = ref(false)
|
||||||
|
const emit = defineEmits({ successful: null })
|
||||||
|
// 表单数据
|
||||||
|
const formData = ref([])
|
||||||
|
const projectId = ref('')
|
||||||
|
const visibleStages = computed(() => formData.value.filter((item) => !item.isDeleted))
|
||||||
|
const submitLoading = ref(false)
|
||||||
|
|
||||||
|
const createEmptyStage = () => ({
|
||||||
|
stageId: '',
|
||||||
|
stageName: '',
|
||||||
|
projectId: projectId,
|
||||||
|
stageSeq: visibleStages.value.length + 1,
|
||||||
|
isDeleted: false,
|
||||||
|
_key: `${Date.now()}-${Math.random()}`
|
||||||
|
})
|
||||||
|
|
||||||
|
// 打开抽屉
|
||||||
|
const onOpen = (record) => {
|
||||||
|
if (record.length > 0) {
|
||||||
|
projectId.value = record[0].projectId
|
||||||
|
}
|
||||||
|
open.value = true
|
||||||
|
const list = Array.isArray(record) ? record : []
|
||||||
|
formData.value = cloneDeep(list).map((item, index) => ({
|
||||||
|
stageId: item.stageId ?? '',
|
||||||
|
stageName: item.stageName ?? '',
|
||||||
|
projectId: item.projectId ?? '',
|
||||||
|
stageSeq: item.stageSeq ?? index + 1,
|
||||||
|
isDeleted: item.isDeleted ?? false,
|
||||||
|
_key: `${Date.now()}-${index}`
|
||||||
|
}))
|
||||||
|
if (!formData.value.length) {
|
||||||
|
formData.value.push(createEmptyStage())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 关闭抽屉
|
||||||
|
const onClose = () => {
|
||||||
|
formData.value = []
|
||||||
|
open.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const addRow = () => {
|
||||||
|
formData.value.push(createEmptyStage())
|
||||||
|
}
|
||||||
|
|
||||||
|
const removeRow = (stage) => {
|
||||||
|
stage.isDeleted = true
|
||||||
|
if (!visibleStages.value.length) {
|
||||||
|
formData.value.push(createEmptyStage())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const submitStages = () => {
|
||||||
|
submitLoading.value = true
|
||||||
|
const submitList = formData.value.map(({ _key, ...rest }) => rest)
|
||||||
|
projectStageApi
|
||||||
|
.batchEdit(submitList)
|
||||||
|
.then(() => {
|
||||||
|
onClose()
|
||||||
|
emit('successful')
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
submitLoading.value = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 验证并提交数据
|
||||||
|
const onSubmit = () => {
|
||||||
|
const deletedStageCount = formData.value.filter((item) => item.stageId && item.isDeleted).length
|
||||||
|
const addedStageCount = formData.value.filter((item) => !item.stageId && !item.isDeleted).length
|
||||||
|
const content = `将删除${deletedStageCount}个阶段以及该阶段的需求,新增${addedStageCount}个阶段,是否继续?`
|
||||||
|
Modal.confirm({
|
||||||
|
title: '提示',
|
||||||
|
content,
|
||||||
|
icon: createVNode(ExclamationCircleOutlined),
|
||||||
|
okText: '确定',
|
||||||
|
cancelText: '取消',
|
||||||
|
onOk: () => {
|
||||||
|
submitStages()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 抛出函数
|
||||||
|
defineExpose({
|
||||||
|
onOpen
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.stage-form {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
.stage-form__header,
|
||||||
|
.stage-form__row {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr 120px;
|
||||||
|
gap: 12px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.stage-form__header {
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--text-color);
|
||||||
|
}
|
||||||
|
.stage-form__empty {
|
||||||
|
padding: 24px 0;
|
||||||
|
border: 1px dashed var(--border-color-split);
|
||||||
|
border-radius: 4px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.stage-form__row {
|
||||||
|
padding: 12px;
|
||||||
|
border: 1px solid var(--border-color-split);
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -60,6 +60,7 @@
|
|||||||
<span class="hours-label">计划工时:</span>
|
<span class="hours-label">计划工时:</span>
|
||||||
<span class="hours-value">{{ plannedHours }}</span>
|
<span class="hours-value">{{ plannedHours }}</span>
|
||||||
<a-button type="primary" class="create-stage-btn" @click="formRef.onOpen(projectInfo.projectId)">创建项目阶段</a-button>
|
<a-button type="primary" class="create-stage-btn" @click="formRef.onOpen(projectInfo.projectId)">创建项目阶段</a-button>
|
||||||
|
<a-button type="primary" class="create-stage-btn" @click="form2Ref.onOpen(stageList)">编辑项目阶段</a-button>
|
||||||
</div>
|
</div>
|
||||||
</a-card>
|
</a-card>
|
||||||
|
|
||||||
@@ -156,6 +157,14 @@
|
|||||||
class="attachment-item"
|
class="attachment-item"
|
||||||
@click="handlePreview(file)"
|
@click="handlePreview(file)"
|
||||||
>
|
>
|
||||||
|
<a-button
|
||||||
|
type="text"
|
||||||
|
size="small"
|
||||||
|
class="attachment-delete-btn"
|
||||||
|
@click.stop="handleAttachmentDelete(file)"
|
||||||
|
>
|
||||||
|
<CloseOutlined />
|
||||||
|
</a-button>
|
||||||
<div class="attachment-thumb">
|
<div class="attachment-thumb">
|
||||||
<img :src="getAttachmentThumbnail(file)" :alt="file.name" />
|
<img :src="getAttachmentThumbnail(file)" :alt="file.name" />
|
||||||
</div>
|
</div>
|
||||||
@@ -173,6 +182,7 @@
|
|||||||
<preview v-else ref="previewRef" @goBack="handlePreviewClose" />
|
<preview v-else ref="previewRef" @goBack="handlePreviewClose" />
|
||||||
<stage-add-dialog ref="formRef" @successful="fetchDetail"/>
|
<stage-add-dialog ref="formRef" @successful="fetchDetail"/>
|
||||||
<fj-upload-form ref="uploadFormRef" @successful="fetchAttachments"/>
|
<fj-upload-form ref="uploadFormRef" @successful="fetchAttachments"/>
|
||||||
|
<batch-stage-add-dialog ref="form2Ref" @successful="fetchDetail"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -180,10 +190,13 @@
|
|||||||
import { computed, nextTick, ref, watch } from 'vue'
|
import { computed, nextTick, ref, watch } from 'vue'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
import projectApi from '@/api/pmm/projectApi'
|
import projectApi from '@/api/pmm/projectApi'
|
||||||
import { message } from 'ant-design-vue'
|
import projectFileApi from '@/api/pmm/projectFileApi'
|
||||||
|
import { Modal, message } from 'ant-design-vue'
|
||||||
import StageAddDialog from "@/views/pmm/project/request/stageAddDialog.vue";
|
import StageAddDialog from "@/views/pmm/project/request/stageAddDialog.vue";
|
||||||
import Preview from '@/views/dev/file/preview.vue'
|
import Preview from '@/views/dev/file/preview.vue'
|
||||||
import FjUploadForm from "@/views/pmm/project/request/fjUploadForm.vue";
|
import FjUploadForm from "@/views/pmm/project/request/fjUploadForm.vue";
|
||||||
|
import BatchStageAddDialog from "@/views/pmm/project/request/batchStageAddDialog.vue";
|
||||||
|
import { CloseOutlined } from '@ant-design/icons-vue'
|
||||||
|
|
||||||
interface AttachmentItem {
|
interface AttachmentItem {
|
||||||
id: number | string
|
id: number | string
|
||||||
@@ -199,6 +212,7 @@
|
|||||||
const stageList = ref<any[]>([])
|
const stageList = ref<any[]>([])
|
||||||
const plannedHours = ref(0)
|
const plannedHours = ref(0)
|
||||||
const formRef = ref()
|
const formRef = ref()
|
||||||
|
const form2Ref = ref()
|
||||||
const previewRef = ref()
|
const previewRef = ref()
|
||||||
const uploadFormRef = ref()
|
const uploadFormRef = ref()
|
||||||
const previewVisible = ref(false)
|
const previewVisible = ref(false)
|
||||||
@@ -324,7 +338,7 @@ const attachmentList = ref<AttachmentItem[]>([])
|
|||||||
return total
|
return total
|
||||||
}
|
}
|
||||||
|
|
||||||
// 计算计划工时(所有阶段的总天数 * 24)
|
// 计算计划工时(所有阶段的总天数 * 8)
|
||||||
const calculatePlannedHours = (stages: any[]) => {
|
const calculatePlannedHours = (stages: any[]) => {
|
||||||
let total = 0
|
let total = 0
|
||||||
stages.forEach((stage) => {
|
stages.forEach((stage) => {
|
||||||
@@ -332,7 +346,7 @@ const attachmentList = ref<AttachmentItem[]>([])
|
|||||||
total += getStageTotalDays(stage.descriptions)
|
total += getStageTotalDays(stage.descriptions)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return total * 24
|
return total * 8
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取项目需求明细
|
// 获取项目需求明细
|
||||||
@@ -512,6 +526,29 @@ watch(projectId, () => {
|
|||||||
const handlePreviewClose = () => {
|
const handlePreviewClose = () => {
|
||||||
previewVisible.value = false
|
previewVisible.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleAttachmentDelete = (file: AttachmentItem) => {
|
||||||
|
const param = {
|
||||||
|
id: file.id
|
||||||
|
}
|
||||||
|
Modal.confirm({
|
||||||
|
title: '确认删除该附件?',
|
||||||
|
content: `附件:${file.name}`,
|
||||||
|
okText: '确认',
|
||||||
|
cancelText: '取消',
|
||||||
|
onOk: () => {
|
||||||
|
projectFileApi
|
||||||
|
.deleteFile(param)
|
||||||
|
.then(() => {
|
||||||
|
message.success(`已确认删除:${file.name}`)
|
||||||
|
fetchAttachments()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onCancel: () => {
|
||||||
|
console.log('取消删除附件:', file)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
@@ -669,6 +706,23 @@ watch(projectId, () => {
|
|||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.attachment-delete-btn {
|
||||||
|
position: absolute;
|
||||||
|
right: 4px;
|
||||||
|
top: 4px;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.attachment-delete-btn:hover {
|
||||||
|
color: #ff4d4f;
|
||||||
|
}
|
||||||
|
|
||||||
.attachment-item:hover {
|
.attachment-item:hover {
|
||||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
|
||||||
transform: translateY(-2px);
|
transform: translateY(-2px);
|
||||||
|
|||||||
@@ -49,7 +49,6 @@
|
|||||||
const onOpen = (record) => {
|
const onOpen = (record) => {
|
||||||
open.value = true
|
open.value = true
|
||||||
if (record) {
|
if (record) {
|
||||||
console.log(record)
|
|
||||||
formData.value.projectId = record
|
formData.value.projectId = record
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user