物资、里程碑进度execl导出
This commit is contained in:
@ -10,7 +10,6 @@ import jakarta.servlet.http.HttpServletResponse;
|
|||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.poi.ss.usermodel.*;
|
import org.apache.poi.ss.usermodel.*;
|
||||||
import org.apache.poi.ss.util.CellRangeAddressList;
|
import org.apache.poi.ss.util.CellRangeAddressList;
|
||||||
import org.apache.poi.xssf.usermodel.XSSFSheet;
|
|
||||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||||
import org.dromara.common.core.constant.HttpStatus;
|
import org.dromara.common.core.constant.HttpStatus;
|
||||||
import org.dromara.common.core.domain.event.ProcessDeleteEvent;
|
import org.dromara.common.core.domain.event.ProcessDeleteEvent;
|
||||||
@ -36,7 +35,6 @@ import org.dromara.project.service.IBusProjectService;
|
|||||||
import org.dromara.system.domain.vo.SysUserVo;
|
import org.dromara.system.domain.vo.SysUserVo;
|
||||||
import org.dromara.system.service.ISysUserService;
|
import org.dromara.system.service.ISysUserService;
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.context.event.EventListener;
|
import org.springframework.context.event.EventListener;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@ -435,21 +433,15 @@ public class DesVolumeCatalogServiceImpl extends ServiceImpl<DesVolumeCatalogMap
|
|||||||
Map<String, String> uniqueMajors = desUserService.getUserMajor(desUserBo);
|
Map<String, String> uniqueMajors = desUserService.getUserMajor(desUserBo);
|
||||||
Map<String, String> userList = desUserService.getUserList(desUserBo);
|
Map<String, String> userList = desUserService.getUserList(desUserBo);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//TODO 数据绑定下拉
|
|
||||||
// String[] namesArray = names.toArray(String[]::new);
|
|
||||||
|
|
||||||
|
|
||||||
// 2. 设置响应头
|
// 2. 设置响应头
|
||||||
// 设置响应头,指定Excel格式和下载文件名
|
// 设置响应头,指定Excel格式和下载文件名
|
||||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||||
response.setCharacterEncoding("utf-8");
|
response.setCharacterEncoding("utf-8");
|
||||||
response.setHeader("Content-Disposition", "attachment; filename="+ URLEncoder.encode("收资清单模板.xlsx", StandardCharsets.UTF_8));
|
response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("卷册目录模板.xlsx", StandardCharsets.UTF_8));
|
||||||
|
|
||||||
Workbook workbook = new XSSFWorkbook();
|
Workbook workbook = new XSSFWorkbook();
|
||||||
// 创建主 Sheet 和隐藏 Sheet
|
// 创建主 Sheet 和隐藏 Sheet
|
||||||
Sheet mainSheet = workbook.createSheet("收资清单模板");
|
Sheet mainSheet = workbook.createSheet("卷册目录模板");
|
||||||
Sheet dataSheet = workbook.createSheet("DropdownData");
|
Sheet dataSheet = workbook.createSheet("DropdownData");
|
||||||
workbook.setSheetHidden(workbook.getSheetIndex(dataSheet), true);
|
workbook.setSheetHidden(workbook.getSheetIndex(dataSheet), true);
|
||||||
|
|
||||||
@ -493,7 +485,6 @@ public class DesVolumeCatalogServiceImpl extends ServiceImpl<DesVolumeCatalogMap
|
|||||||
setMajorDropdown(mainSheet, uniqueMajors.size());
|
setMajorDropdown(mainSheet, uniqueMajors.size());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 8. 设置人员下拉列表(第四列)
|
// 8. 设置人员下拉列表(第四列)
|
||||||
setPersonDropdown(mainSheet, userList.size());
|
setPersonDropdown(mainSheet, userList.size());
|
||||||
|
|
||||||
@ -544,7 +535,6 @@ public class DesVolumeCatalogServiceImpl extends ServiceImpl<DesVolumeCatalogMap
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 保护工作表,仅允许编辑未锁定的单元格
|
// 保护工作表,仅允许编辑未锁定的单元格
|
||||||
mainSheet.protectSheet("123456"); // 空密码
|
mainSheet.protectSheet("123456"); // 空密码
|
||||||
|
|
||||||
@ -573,7 +563,6 @@ public class DesVolumeCatalogServiceImpl extends ServiceImpl<DesVolumeCatalogMap
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建可编辑单元格样式
|
* 创建可编辑单元格样式
|
||||||
*/
|
*/
|
||||||
@ -616,7 +605,6 @@ public class DesVolumeCatalogServiceImpl extends ServiceImpl<DesVolumeCatalogMap
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置人员下拉列表(第四列,索引3)
|
* 设置人员下拉列表(第四列,索引3)
|
||||||
*/
|
*/
|
||||||
|
@ -36,7 +36,7 @@ public class MatMaterialsUseDetailVo implements Serializable {
|
|||||||
/**
|
/**
|
||||||
* 供货单位
|
* 供货单位
|
||||||
*/
|
*/
|
||||||
private String companyName;
|
private String supplier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 入库id
|
* 入库id
|
||||||
@ -53,11 +53,6 @@ public class MatMaterialsUseDetailVo implements Serializable {
|
|||||||
*/
|
*/
|
||||||
private String operator;
|
private String operator;
|
||||||
|
|
||||||
/**
|
|
||||||
* 交接单位
|
|
||||||
*/
|
|
||||||
private String recipient;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 入库时间
|
* 入库时间
|
||||||
*/
|
*/
|
||||||
|
@ -170,12 +170,14 @@ public interface IMatMaterialsService extends IService<MatMaterials> {
|
|||||||
* 获取材料使用详情列表
|
* 获取材料使用详情列表
|
||||||
*
|
*
|
||||||
* @param materials 材料
|
* @param materials 材料
|
||||||
* @param inventoryList 材料库存列表
|
* @param putList 材料入库列表
|
||||||
|
* @param outList 材料出库列表
|
||||||
* @param useList 材料使用列表
|
* @param useList 材料使用列表
|
||||||
* @return 材料使用详情列表
|
* @return 材料使用详情列表
|
||||||
*/
|
*/
|
||||||
List<MatMaterialsUseDetailVo> getUseDetailList(List<MatMaterials> materials,
|
List<MatMaterialsUseDetailVo> getUseDetailList(List<MatMaterials> materials,
|
||||||
List<MatMaterialsInventory> inventoryList,
|
List<MatMaterialsInventory> putList,
|
||||||
|
List<MatMaterialsInventory> outList,
|
||||||
List<MatMaterialsUseRecord> useList);
|
List<MatMaterialsUseRecord> useList);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -31,8 +31,10 @@ import org.dromara.materials.domain.dto.materialsinventory.MatMaterialsInventory
|
|||||||
import org.dromara.materials.domain.enums.MatMaterialsInventoryOutPutEnum;
|
import org.dromara.materials.domain.enums.MatMaterialsInventoryOutPutEnum;
|
||||||
import org.dromara.materials.domain.enums.MatMaterialsInventoryReceiveStatusEnum;
|
import org.dromara.materials.domain.enums.MatMaterialsInventoryReceiveStatusEnum;
|
||||||
import org.dromara.materials.domain.vo.materials.*;
|
import org.dromara.materials.domain.vo.materials.*;
|
||||||
|
import org.dromara.materials.domain.vo.materialsinventory.MatMaterialsInventoryOutUseVo;
|
||||||
import org.dromara.materials.domain.vo.materialsinventory.MatMaterialsInventoryOutVo;
|
import org.dromara.materials.domain.vo.materialsinventory.MatMaterialsInventoryOutVo;
|
||||||
import org.dromara.materials.domain.vo.materialsinventory.MatMaterialsInventoryVo;
|
import org.dromara.materials.domain.vo.materialsinventory.MatMaterialsInventoryVo;
|
||||||
|
import org.dromara.materials.domain.vo.materialsuserecord.MatMaterialsUseRecordByOutVo;
|
||||||
import org.dromara.materials.mapper.MatMaterialsMapper;
|
import org.dromara.materials.mapper.MatMaterialsMapper;
|
||||||
import org.dromara.materials.service.*;
|
import org.dromara.materials.service.*;
|
||||||
import org.dromara.project.domain.BusProject;
|
import org.dromara.project.domain.BusProject;
|
||||||
@ -613,84 +615,190 @@ public class MatMaterialsServiceImpl extends ServiceImpl<MatMaterialsMapper, Mat
|
|||||||
result.getSize(),
|
result.getSize(),
|
||||||
result.getTotal()
|
result.getTotal()
|
||||||
);
|
);
|
||||||
/* if (CollUtil.isEmpty(materialsList)) {
|
if (CollUtil.isEmpty(materialsList)) {
|
||||||
return materialsVoPage;
|
return TableDataInfo.build(materialsVoPage);
|
||||||
}*/
|
}
|
||||||
return null;
|
// 查询材料出入库列表
|
||||||
|
List<Long> ids = materialsList.stream().map(MatMaterials::getId).toList();
|
||||||
|
List<MatMaterialsInventory> materialsInventoryList = materialsInventoryService.lambdaQuery()
|
||||||
|
.in(MatMaterialsInventory::getMaterialsId, ids)
|
||||||
|
.list();
|
||||||
|
List<MatMaterialsInventory> putList = materialsInventoryList.stream()
|
||||||
|
.filter(inventory -> inventory.getOutPut().equals(MatMaterialsInventoryOutPutEnum.PUT.getValue()))
|
||||||
|
.toList();
|
||||||
|
// 查询使用列表
|
||||||
|
List<MatMaterialsInventory> outList = materialsInventoryList.stream()
|
||||||
|
.filter(inventory -> inventory.getOutPut().equals(MatMaterialsInventoryOutPutEnum.OUT.getValue()))
|
||||||
|
.toList();
|
||||||
|
List<MatMaterialsUseRecord> useList = new ArrayList<>();
|
||||||
|
if (CollUtil.isNotEmpty(outList)) {
|
||||||
|
List<Long> outIds = outList.stream().map(MatMaterialsInventory::getId).toList();
|
||||||
|
useList = materialsUseRecordService.lambdaQuery()
|
||||||
|
.in(MatMaterialsUseRecord::getInventoryId, outIds)
|
||||||
|
.list();
|
||||||
|
}
|
||||||
|
List<MatMaterialsUseDetailVo> useDetailList = this.getUseDetailList(materialsList, putList, outList, useList);
|
||||||
|
materialsVoPage.setRecords(useDetailList);
|
||||||
|
return TableDataInfo.build(materialsVoPage);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取材料使用详情列表
|
* 获取材料使用详情列表
|
||||||
*
|
*
|
||||||
* @param materials 材料
|
* @param materials 材料
|
||||||
* @param inventoryList 材料库存列表
|
* @param putList 材料入库列表
|
||||||
|
* @param outList 材料出库列表
|
||||||
* @param useList 材料使用列表
|
* @param useList 材料使用列表
|
||||||
* @return 材料使用详情列表
|
* @return 材料使用详情列表
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public List<MatMaterialsUseDetailVo> getUseDetailList(List<MatMaterials> materials, List<MatMaterialsInventory> inventoryList, List<MatMaterialsUseRecord> useList) {
|
public List<MatMaterialsUseDetailVo> getUseDetailList(List<MatMaterials> materials,
|
||||||
return List.of();
|
List<MatMaterialsInventory> putList,
|
||||||
|
List<MatMaterialsInventory> outList,
|
||||||
|
List<MatMaterialsUseRecord> useList) {
|
||||||
|
Map<Long, MatMaterialsInventory> putMap = putList.stream()
|
||||||
|
.collect(Collectors.toMap(MatMaterialsInventory::getMaterialsId, inventory -> inventory));
|
||||||
|
return materials.stream().map(material -> {
|
||||||
|
MatMaterialsUseDetailVo vo = new MatMaterialsUseDetailVo();
|
||||||
|
BeanUtils.copyProperties(material, vo);
|
||||||
|
Long id = material.getId();
|
||||||
|
MatMaterialsInventory put = putMap.get(id);
|
||||||
|
vo.setSupplier(put.getRecipient());
|
||||||
|
vo.setInventoryId(put.getId());
|
||||||
|
vo.setNumber(put.getNumber());
|
||||||
|
vo.setOperator(put.getOperator());
|
||||||
|
vo.setEnterTime(put.getCreateTime());
|
||||||
|
if (CollUtil.isNotEmpty(outList)) {
|
||||||
|
List<MatMaterialsInventory> outs = outList.stream()
|
||||||
|
.filter(inventory -> inventory.getMaterialsId().equals(id))
|
||||||
|
.toList();
|
||||||
|
if (CollUtil.isNotEmpty(outs)) {
|
||||||
|
List<MatMaterialsInventoryOutUseVo> outUseVos = outs.stream().map(inventory -> {
|
||||||
|
MatMaterialsInventoryOutUseVo outUseVo = new MatMaterialsInventoryOutUseVo();
|
||||||
|
BeanUtils.copyProperties(inventory, outUseVo);
|
||||||
|
if (CollUtil.isNotEmpty(useList)) {
|
||||||
|
List<MatMaterialsUseRecord> uses = useList.stream()
|
||||||
|
.filter(record -> record.getInventoryId().equals(inventory.getId()))
|
||||||
|
.toList();
|
||||||
|
List<MatMaterialsUseRecordByOutVo> useRecordList = uses.stream().map(record -> {
|
||||||
|
MatMaterialsUseRecordByOutVo useRecordVo = new MatMaterialsUseRecordByOutVo();
|
||||||
|
BeanUtils.copyProperties(record, useRecordVo);
|
||||||
|
return useRecordVo;
|
||||||
|
}).toList();
|
||||||
|
outUseVo.setUseList(useRecordList);
|
||||||
|
}
|
||||||
|
return outUseVo;
|
||||||
|
}).toList();
|
||||||
|
vo.setOutList(outUseVos);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return vo;
|
||||||
|
}).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取材料库存数据列表
|
* 获取材料库存数据列表(导出 Excel 用)
|
||||||
*
|
*
|
||||||
* @param req 查询条件
|
* @param req 查询条件
|
||||||
* @return 材料库存数据列表
|
* @return 材料库存数据列表
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public List<MatMaterialsExcelVo> queryExcelList(MatMaterialsQueryReq req) {
|
public List<MatMaterialsExcelVo> queryExcelList(MatMaterialsQueryReq req) {
|
||||||
// 查询数据库
|
|
||||||
LambdaQueryWrapper<MatMaterials> lqw = this.buildQueryWrapper(req);
|
LambdaQueryWrapper<MatMaterials> lqw = this.buildQueryWrapper(req);
|
||||||
List<MatMaterials> materials = this.list(lqw);
|
List<MatMaterials> materials = this.list(lqw);
|
||||||
if (CollUtil.isEmpty(materials)) {
|
if (CollUtil.isEmpty(materials)) {
|
||||||
return List.of();
|
return List.of();
|
||||||
}
|
}
|
||||||
// 获取材料主键
|
|
||||||
List<Long> ids = materials.stream().map(MatMaterials::getId).toList();
|
List<Long> ids = materials.stream().map(MatMaterials::getId).toList();
|
||||||
// 获取出入库记录
|
|
||||||
List<MatMaterialsInventory> inventoryList = materialsInventoryService.lambdaQuery()
|
List<MatMaterialsInventory> inventoryList = materialsInventoryService.lambdaQuery()
|
||||||
.in(MatMaterialsInventory::getMaterialsId, ids)
|
.in(MatMaterialsInventory::getMaterialsId, ids)
|
||||||
.list();
|
.list();
|
||||||
// 获取入库记录
|
|
||||||
List<MatMaterialsInventory> putList = inventoryList.stream()
|
Map<Long, MatMaterialsInventory> putMap = inventoryList.stream()
|
||||||
.filter(inventory -> inventory.getOutPut().equals(MatMaterialsInventoryOutPutEnum.PUT.getValue()))
|
.filter(inv -> inv.getOutPut().equals(MatMaterialsInventoryOutPutEnum.PUT.getValue()))
|
||||||
.toList();
|
.collect(Collectors.toMap(MatMaterialsInventory::getMaterialsId, Function.identity()));
|
||||||
Map<Long, MatMaterialsInventory> putMap = putList.stream()
|
|
||||||
.collect(Collectors.toMap(MatMaterialsInventory::getMaterialsId, inventory -> inventory));
|
|
||||||
// 获取使用记录
|
|
||||||
List<MatMaterialsInventory> outList = inventoryList.stream()
|
List<MatMaterialsInventory> outList = inventoryList.stream()
|
||||||
.filter(inventory -> inventory.getOutPut().equals(MatMaterialsInventoryOutPutEnum.OUT.getValue()))
|
.filter(inv -> inv.getOutPut().equals(MatMaterialsInventoryOutPutEnum.OUT.getValue()))
|
||||||
.toList();
|
.toList();
|
||||||
List<MatMaterialsUseRecord> useList = new ArrayList<>();
|
|
||||||
if (CollUtil.isEmpty(outList)) {
|
Map<Long, List<MatMaterialsUseRecord>> useMap = new HashMap<>();
|
||||||
List<Long> outIds = outList.stream().map(MatMaterialsInventory::getId).distinct().toList();
|
if (CollUtil.isNotEmpty(outList)) {
|
||||||
// 获取使用记录
|
List<Long> outIds = outList.stream().map(MatMaterialsInventory::getId).toList();
|
||||||
useList = materialsUseRecordService.lambdaQuery()
|
List<MatMaterialsUseRecord> useList = materialsUseRecordService.lambdaQuery()
|
||||||
.in(MatMaterialsUseRecord::getInventoryId, outIds)
|
.in(MatMaterialsUseRecord::getInventoryId, outIds)
|
||||||
.list();
|
.list();
|
||||||
|
useMap = useList.stream().collect(Collectors.groupingBy(MatMaterialsUseRecord::getInventoryId));
|
||||||
}
|
}
|
||||||
|
|
||||||
List<MatMaterialsExcelVo> excelVoList = new ArrayList<>();
|
List<MatMaterialsExcelVo> excelVoList = new ArrayList<>();
|
||||||
|
|
||||||
for (MatMaterials material : materials) {
|
for (MatMaterials material : materials) {
|
||||||
|
MatMaterialsInventory put = putMap.get(material.getId());
|
||||||
|
|
||||||
|
List<MatMaterialsInventory> materialOutList = outList.stream()
|
||||||
|
.filter(inv -> inv.getMaterialsId().equals(material.getId()))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
boolean firstMaterialRow = true; // 记录材料是否是第一行
|
||||||
|
|
||||||
|
if (CollUtil.isEmpty(materialOutList)) {
|
||||||
|
excelVoList.add(buildVo(material, put, null, null, firstMaterialRow, false));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (MatMaterialsInventory out : materialOutList) {
|
||||||
|
List<MatMaterialsUseRecord> outUseList = useMap.getOrDefault(out.getId(), List.of());
|
||||||
|
boolean firstOutRow = true; // 记录出库是否是第一行
|
||||||
|
|
||||||
|
if (CollUtil.isEmpty(outUseList)) {
|
||||||
|
excelVoList.add(buildVo(material, put, out, null, firstMaterialRow, firstOutRow));
|
||||||
|
firstMaterialRow = false;
|
||||||
|
} else {
|
||||||
|
for (MatMaterialsUseRecord use : outUseList) {
|
||||||
|
excelVoList.add(buildVo(material, put, out, use, firstMaterialRow, firstOutRow));
|
||||||
|
firstMaterialRow = false;
|
||||||
|
firstOutRow = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return excelVoList;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建一行导出数据
|
||||||
|
*/
|
||||||
|
private MatMaterialsExcelVo buildVo(MatMaterials material,
|
||||||
|
MatMaterialsInventory put,
|
||||||
|
MatMaterialsInventory out,
|
||||||
|
MatMaterialsUseRecord use,
|
||||||
|
boolean showMaterial,
|
||||||
|
boolean showOut) {
|
||||||
MatMaterialsExcelVo vo = new MatMaterialsExcelVo();
|
MatMaterialsExcelVo vo = new MatMaterialsExcelVo();
|
||||||
Long id = material.getId();
|
|
||||||
|
// 材料信息(只显示一次)
|
||||||
|
if (showMaterial) {
|
||||||
vo.setMaterialsName(material.getMaterialsName());
|
vo.setMaterialsName(material.getMaterialsName());
|
||||||
vo.setQuantityCount(material.getQuantityCount());
|
vo.setQuantityCount(material.getQuantityCount());
|
||||||
// 拼接入库记录
|
|
||||||
MatMaterialsInventory put = putMap.get(id);
|
if (put != null) {
|
||||||
vo.setSupplier(put.getRecipient());
|
vo.setSupplier(put.getRecipient());
|
||||||
vo.setPutNumber(put.getNumber());
|
vo.setPutNumber(put.getNumber());
|
||||||
vo.setSigner(put.getOperator());
|
vo.setSigner(put.getOperator());
|
||||||
if (put.getCreateTime() != null) {
|
if (put.getCreateTime() != null) {
|
||||||
vo.setPutTime(DateUtils.parseDateToStr(FormatsType.YYYY_MM_DD_DOT, put.getCreateTime()));
|
vo.setPutTime(DateUtils.parseDateToStr(FormatsType.YYYY_MM_DD_DOT, put.getCreateTime()));
|
||||||
}
|
}
|
||||||
List<MatMaterialsInventory> materialOutList = outList.stream()
|
}
|
||||||
.filter(inventory -> inventory.getMaterialsId().equals(id))
|
}
|
||||||
.toList();
|
|
||||||
List<MatMaterialsUseRecord> materialUseList = new ArrayList<>();
|
// 出库信息(同一条出库只显示一次)
|
||||||
if (CollUtil.isNotEmpty(materialOutList)) {
|
if (showOut && out != null) {
|
||||||
// 拼接第一条出库数据
|
|
||||||
MatMaterialsInventory out = materialOutList.getFirst();
|
|
||||||
vo.setRecipient(out.getRecipient());
|
vo.setRecipient(out.getRecipient());
|
||||||
vo.setOutNumber(out.getNumber());
|
vo.setOutNumber(out.getNumber());
|
||||||
vo.setOperator(out.getOperator());
|
vo.setOperator(out.getOperator());
|
||||||
@ -700,12 +808,10 @@ public class MatMaterialsServiceImpl extends ServiceImpl<MatMaterialsMapper, Mat
|
|||||||
}
|
}
|
||||||
vo.setResidue(out.getResidue());
|
vo.setResidue(out.getResidue());
|
||||||
vo.setDisposition(out.getDisposition());
|
vo.setDisposition(out.getDisposition());
|
||||||
materialUseList = useList.stream()
|
}
|
||||||
.filter(record -> record.getInventoryId().equals(out.getId()))
|
|
||||||
.toList();
|
// 使用信息(每条都显示)
|
||||||
if (CollUtil.isNotEmpty(materialUseList)) {
|
if (use != null) {
|
||||||
// 拼接第一条使用记录
|
|
||||||
MatMaterialsUseRecord use = materialUseList.getFirst();
|
|
||||||
vo.setUsePart(use.getUsePart());
|
vo.setUsePart(use.getUsePart());
|
||||||
vo.setUseNumber(use.getUseNumber());
|
vo.setUseNumber(use.getUseNumber());
|
||||||
if (use.getCreateTime() != null) {
|
if (use.getCreateTime() != null) {
|
||||||
@ -714,75 +820,9 @@ public class MatMaterialsServiceImpl extends ServiceImpl<MatMaterialsMapper, Mat
|
|||||||
vo.setSurplus(use.getResidueNumber());
|
vo.setSurplus(use.getResidueNumber());
|
||||||
vo.setRemark(use.getRemark());
|
vo.setRemark(use.getRemark());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return vo;
|
||||||
}
|
}
|
||||||
List<MatMaterialsExcelVo> childList = new ArrayList<>();
|
|
||||||
if (CollUtil.isNotEmpty(materialUseList)) {
|
|
||||||
for (int i = 1; i < materialOutList.size(); i++) {
|
|
||||||
MatMaterialsInventory out = materialOutList.get(i);
|
|
||||||
List<MatMaterialsUseRecord> outUseList = materialUseList.stream()
|
|
||||||
.filter(record -> record.getInventoryId().equals(out.getId()))
|
|
||||||
.toList();
|
|
||||||
if (CollUtil.isNotEmpty(outUseList)) {
|
|
||||||
for (int j = 1; j < outUseList.size(); j++) {
|
|
||||||
MatMaterialsExcelVo child = new MatMaterialsExcelVo();
|
|
||||||
MatMaterialsUseRecord use = outUseList.get(j);
|
|
||||||
if (j == 1) {
|
|
||||||
// 拼接出库记录
|
|
||||||
child.setRecipient(out.getRecipient());
|
|
||||||
child.setOutNumber(out.getNumber());
|
|
||||||
child.setOperator(out.getOperator());
|
|
||||||
child.setShipper(out.getShipper());
|
|
||||||
if (out.getCreateTime() != null) {
|
|
||||||
child.setReceivingDate(DateUtils.parseDateToStr(FormatsType.YYYY_MM_DD_DOT, out.getCreateTime()));
|
|
||||||
}
|
|
||||||
child.setResidue(out.getResidue());
|
|
||||||
child.setDisposition(out.getDisposition());
|
|
||||||
}
|
|
||||||
// 拼接使用记录
|
|
||||||
vo.setUsePart(use.getUsePart());
|
|
||||||
vo.setUseNumber(use.getUseNumber());
|
|
||||||
if (use.getCreateTime() != null) {
|
|
||||||
vo.setUseTime(DateUtils.parseDateToStr(FormatsType.YYYY_MM_DD_DOT, use.getCreateTime()));
|
|
||||||
}
|
|
||||||
vo.setSurplus(use.getResidueNumber());
|
|
||||||
vo.setRemark(use.getRemark());
|
|
||||||
childList.add(child);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
MatMaterialsExcelVo child = new MatMaterialsExcelVo();
|
|
||||||
child.setRecipient(out.getRecipient());
|
|
||||||
child.setOutNumber(out.getNumber());
|
|
||||||
child.setOperator(out.getOperator());
|
|
||||||
child.setShipper(out.getShipper());
|
|
||||||
if (out.getCreateTime() != null) {
|
|
||||||
child.setReceivingDate(DateUtils.parseDateToStr(FormatsType.YYYY_MM_DD_DOT, out.getCreateTime()));
|
|
||||||
}
|
|
||||||
child.setResidue(out.getResidue());
|
|
||||||
child.setDisposition(out.getDisposition());
|
|
||||||
childList.add(child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
childList = materialOutList.stream()
|
|
||||||
.skip(1)
|
|
||||||
.map(out -> {
|
|
||||||
MatMaterialsExcelVo v = new MatMaterialsExcelVo();
|
|
||||||
v.setRecipient(out.getRecipient());
|
|
||||||
v.setOutNumber(out.getNumber());
|
|
||||||
v.setOperator(out.getOperator());
|
|
||||||
v.setShipper(out.getShipper());
|
|
||||||
if (out.getCreateTime() != null) {
|
|
||||||
v.setReceivingDate(DateUtils.parseDateToStr(FormatsType.YYYY_MM_DD_DOT, out.getCreateTime()));
|
|
||||||
}
|
|
||||||
v.setResidue(out.getResidue());
|
|
||||||
v.setDisposition(out.getDisposition());
|
|
||||||
return v;
|
|
||||||
}).toList();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
excelVoList.add(vo);
|
|
||||||
excelVoList.addAll(childList);
|
|
||||||
}
|
|
||||||
return excelVoList;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package org.dromara.out.service.impl;
|
package org.dromara.out.service.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.convert.Convert;
|
import cn.hutool.core.convert.Convert;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
@ -32,6 +33,7 @@ import org.springframework.context.event.EventListener;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -109,7 +111,13 @@ public class OutConstructionValueServiceImpl extends ServiceImpl<OutConstruction
|
|||||||
List<BusProject> subProjectIds = projectService.lambdaQuery()
|
List<BusProject> subProjectIds = projectService.lambdaQuery()
|
||||||
.eq(BusProject::getPId, projectId)
|
.eq(BusProject::getPId, projectId)
|
||||||
.list();
|
.list();
|
||||||
lqw.in(OutConstructionValue::getProjectId, projectId, subProjectIds);
|
if (CollUtil.isNotEmpty(subProjectIds)) {
|
||||||
|
List<Long> ids = new ArrayList<>(subProjectIds.stream().map(BusProject::getId).toList());
|
||||||
|
ids.add(projectId);
|
||||||
|
lqw.in(OutConstructionValue::getProjectId, ids);
|
||||||
|
} else {
|
||||||
|
lqw.eq(OutConstructionValue::getProjectId, projectId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
lqw.eq(bo.getMatrixId() != null, OutConstructionValue::getMatrixId, bo.getMatrixId());
|
lqw.eq(bo.getMatrixId() != null, OutConstructionValue::getMatrixId, bo.getMatrixId());
|
||||||
lqw.eq(bo.getProgressCategoryId() != null, OutConstructionValue::getProgressCategoryId, bo.getProgressCategoryId());
|
lqw.eq(bo.getProgressCategoryId() != null, OutConstructionValue::getProgressCategoryId, bo.getProgressCategoryId());
|
||||||
@ -225,7 +233,7 @@ public class OutConstructionValueServiceImpl extends ServiceImpl<OutConstruction
|
|||||||
vo.setProjectName(busProjectVo.getProjectName());
|
vo.setProjectName(busProjectVo.getProjectName());
|
||||||
|
|
||||||
//查询方阵以及子项目
|
//查询方阵以及子项目
|
||||||
if (vo.getMatrixId() != null) {
|
if (vo.getMatrixId() != null && vo.getMatrixId() != 0) {
|
||||||
FacMatrix facMatrix = facMatrixService.getById(vo.getMatrixId());
|
FacMatrix facMatrix = facMatrixService.getById(vo.getMatrixId());
|
||||||
vo.setMatrixName(facMatrix.getMatrixName());
|
vo.setMatrixName(facMatrix.getMatrixName());
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package org.dromara.progress.controller;
|
package org.dromara.progress.controller;
|
||||||
|
|
||||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import jakarta.validation.constraints.NotEmpty;
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
@ -13,13 +14,17 @@ import org.dromara.common.idempotent.annotation.RepeatSubmit;
|
|||||||
import org.dromara.common.log.annotation.Log;
|
import org.dromara.common.log.annotation.Log;
|
||||||
import org.dromara.common.log.enums.BusinessType;
|
import org.dromara.common.log.enums.BusinessType;
|
||||||
import org.dromara.common.web.core.BaseController;
|
import org.dromara.common.web.core.BaseController;
|
||||||
|
import org.dromara.progress.domain.PgsConstructionSchedulePlan;
|
||||||
import org.dromara.progress.domain.dto.constructionscheduleplan.PgsConstructionSchedulePlanCreateReq;
|
import org.dromara.progress.domain.dto.constructionscheduleplan.PgsConstructionSchedulePlanCreateReq;
|
||||||
|
import org.dromara.progress.domain.dto.constructionscheduleplan.PgsConstructionSchedulePlanExcelDto;
|
||||||
import org.dromara.progress.domain.dto.constructionscheduleplan.PgsConstructionSchedulePlanQueryReq;
|
import org.dromara.progress.domain.dto.constructionscheduleplan.PgsConstructionSchedulePlanQueryReq;
|
||||||
import org.dromara.progress.domain.dto.constructionscheduleplan.PgsConstructionSchedulePlanUpdateReq;
|
import org.dromara.progress.domain.dto.constructionscheduleplan.PgsConstructionSchedulePlanUpdateReq;
|
||||||
import org.dromara.progress.domain.vo.constructionscheduleplan.PgsConstructionSchedulePlanVo;
|
import org.dromara.progress.domain.vo.constructionscheduleplan.PgsConstructionSchedulePlanVo;
|
||||||
import org.dromara.progress.service.IPgsConstructionSchedulePlanService;
|
import org.dromara.progress.service.IPgsConstructionSchedulePlanService;
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -58,6 +63,36 @@ public class PgsConstructionSchedulePlanController extends BaseController {
|
|||||||
ExcelUtil.exportExcel(list, "施工进度计划", PgsConstructionSchedulePlanVo.class, response);
|
ExcelUtil.exportExcel(list, "施工进度计划", PgsConstructionSchedulePlanVo.class, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据项目id导出施工进度计划模版
|
||||||
|
*/
|
||||||
|
@SaCheckPermission("progress:constructionSchedulePlan:exportTemplate")
|
||||||
|
@Log(title = "施工进度计划", businessType = BusinessType.EXPORT)
|
||||||
|
@PostMapping("/exportTemplate/{projectId}")
|
||||||
|
public void exportExcelByProjectId(@NotNull(message = "项目id不能为空")
|
||||||
|
@PathVariable Long projectId, HttpServletResponse response) {
|
||||||
|
pgsConstructionSchedulePlanService.exportExcelByProjectId(projectId, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 读取施工进度计划模版
|
||||||
|
*/
|
||||||
|
@SaCheckPermission("progress:constructionSchedulePlan:readTemplate")
|
||||||
|
@Log(title = "施工进度计划", businessType = BusinessType.IMPORT)
|
||||||
|
@PostMapping("/readTemplate")
|
||||||
|
public R<Void> readExcel(@RequestParam("file") MultipartFile file, Long projectId) {
|
||||||
|
List<PgsConstructionSchedulePlanExcelDto> list = pgsConstructionSchedulePlanService.readExcel(file, projectId);
|
||||||
|
if (CollUtil.isNotEmpty(list)) {
|
||||||
|
List<PgsConstructionSchedulePlan> planList = list.stream().map(dto -> {
|
||||||
|
PgsConstructionSchedulePlan plan = new PgsConstructionSchedulePlan();
|
||||||
|
BeanUtils.copyProperties(dto, plan);
|
||||||
|
return plan;
|
||||||
|
}).toList();
|
||||||
|
return toAjax(pgsConstructionSchedulePlanService.saveBatch(planList));
|
||||||
|
}
|
||||||
|
return toAjax(true);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取施工进度计划详细信息
|
* 获取施工进度计划详细信息
|
||||||
*
|
*
|
||||||
|
@ -7,7 +7,7 @@ import lombok.EqualsAndHashCode;
|
|||||||
import org.dromara.common.mybatis.core.domain.BaseEntity;
|
import org.dromara.common.mybatis.core.domain.BaseEntity;
|
||||||
|
|
||||||
import java.io.Serial;
|
import java.io.Serial;
|
||||||
import java.util.Date;
|
import java.time.LocalDate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 施工进度计划对象 pgs_construction_schedule_plan
|
* 施工进度计划对象 pgs_construction_schedule_plan
|
||||||
@ -57,22 +57,22 @@ public class PgsConstructionSchedulePlan extends BaseEntity {
|
|||||||
/**
|
/**
|
||||||
* 预计开始时间
|
* 预计开始时间
|
||||||
*/
|
*/
|
||||||
private Date planStartDate;
|
private LocalDate planStartDate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 预计结束时间
|
* 预计结束时间
|
||||||
*/
|
*/
|
||||||
private Date planEndDate;
|
private LocalDate planEndDate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 实际开始时间
|
* 实际开始时间
|
||||||
*/
|
*/
|
||||||
private Date practicalStartDate;
|
private LocalDate practicalStartDate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 实际结束时间
|
* 实际结束时间
|
||||||
*/
|
*/
|
||||||
private Date practicalEndDate;
|
private LocalDate practicalEndDate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 状态
|
* 状态
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
package org.dromara.progress.domain.dto.constructionscheduleplan;
|
package org.dromara.progress.domain.dto.constructionscheduleplan;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
|
||||||
import jakarta.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
import jakarta.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.io.Serial;
|
import java.io.Serial;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.time.LocalDate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lilemy
|
* @author lilemy
|
||||||
@ -49,26 +48,22 @@ public class PgsConstructionSchedulePlanCreateReq implements Serializable {
|
|||||||
/**
|
/**
|
||||||
* 预计开始时间
|
* 预计开始时间
|
||||||
*/
|
*/
|
||||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
|
private LocalDate planStartDate;
|
||||||
private Date planStartDate;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 预计结束时间
|
* 预计结束时间
|
||||||
*/
|
*/
|
||||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
|
private LocalDate planEndDate;
|
||||||
private Date planEndDate;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 实际开始时间
|
* 实际开始时间
|
||||||
*/
|
*/
|
||||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
|
private LocalDate practicalStartDate;
|
||||||
private Date practicalStartDate;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 实际结束时间
|
* 实际结束时间
|
||||||
*/
|
*/
|
||||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
|
private LocalDate practicalEndDate;
|
||||||
private Date practicalEndDate;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 状态
|
* 状态
|
||||||
|
@ -0,0 +1,71 @@
|
|||||||
|
package org.dromara.progress.domain.dto.constructionscheduleplan;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author lilemy
|
||||||
|
* @date 2025-09-06 17:12
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class PgsConstructionSchedulePlanExcelDto {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 项目ID
|
||||||
|
*/
|
||||||
|
private Long projectId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 父ID
|
||||||
|
*/
|
||||||
|
private Long parentId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 节点名称
|
||||||
|
*/
|
||||||
|
private String nodeName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对应项目结构
|
||||||
|
*/
|
||||||
|
private Long projectStructure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对应项目结构名称
|
||||||
|
*/
|
||||||
|
private String projectStructureName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 预计开始时间
|
||||||
|
*/
|
||||||
|
private LocalDate planStartDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 预计结束时间
|
||||||
|
*/
|
||||||
|
private LocalDate planEndDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 实际开始时间
|
||||||
|
*/
|
||||||
|
private LocalDate practicalStartDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 实际结束时间
|
||||||
|
*/
|
||||||
|
private LocalDate practicalEndDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态
|
||||||
|
*/
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
*/
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
}
|
@ -1,11 +1,10 @@
|
|||||||
package org.dromara.progress.domain.dto.constructionscheduleplan;
|
package org.dromara.progress.domain.dto.constructionscheduleplan;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.io.Serial;
|
import java.io.Serial;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.time.LocalDate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lilemy
|
* @author lilemy
|
||||||
@ -40,19 +39,16 @@ public class PgsConstructionSchedulePlanUpdateReq implements Serializable {
|
|||||||
/**
|
/**
|
||||||
* 实际开始时间
|
* 实际开始时间
|
||||||
*/
|
*/
|
||||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
|
private LocalDate practicalStartDate;
|
||||||
private Date practicalStartDate;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 实际结束时间
|
* 实际结束时间
|
||||||
*/
|
*/
|
||||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
|
private LocalDate practicalEndDate;
|
||||||
private Date practicalEndDate;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 状态
|
* 状态
|
||||||
*/
|
*/
|
||||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
|
|
||||||
private String status;
|
private String status;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2,7 +2,6 @@ package org.dromara.progress.domain.vo.constructionscheduleplan;
|
|||||||
|
|
||||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||||
import com.alibaba.excel.annotation.ExcelProperty;
|
import com.alibaba.excel.annotation.ExcelProperty;
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
|
||||||
import io.github.linpeilie.annotations.AutoMapper;
|
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;
|
||||||
@ -11,7 +10,7 @@ import org.dromara.progress.domain.PgsConstructionSchedulePlan;
|
|||||||
|
|
||||||
import java.io.Serial;
|
import java.io.Serial;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.time.LocalDate;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -68,29 +67,25 @@ public class PgsConstructionSchedulePlanVo implements Serializable {
|
|||||||
* 预计开始时间
|
* 预计开始时间
|
||||||
*/
|
*/
|
||||||
@ExcelProperty(value = "预计开始时间")
|
@ExcelProperty(value = "预计开始时间")
|
||||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
private LocalDate planStartDate;
|
||||||
private Date planStartDate;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 预计结束时间
|
* 预计结束时间
|
||||||
*/
|
*/
|
||||||
@ExcelProperty(value = "预计结束时间")
|
@ExcelProperty(value = "预计结束时间")
|
||||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
private LocalDate planEndDate;
|
||||||
private Date planEndDate;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 实际开始时间
|
* 实际开始时间
|
||||||
*/
|
*/
|
||||||
@ExcelProperty(value = "实际开始时间")
|
@ExcelProperty(value = "实际开始时间")
|
||||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
private LocalDate practicalStartDate;
|
||||||
private Date practicalStartDate;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 实际结束时间
|
* 实际结束时间
|
||||||
*/
|
*/
|
||||||
@ExcelProperty(value = "实际结束时间")
|
@ExcelProperty(value = "实际结束时间")
|
||||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
private LocalDate practicalEndDate;
|
||||||
private Date practicalEndDate;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 状态
|
* 状态
|
||||||
|
@ -2,11 +2,14 @@ package org.dromara.progress.service;
|
|||||||
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import org.dromara.progress.domain.PgsConstructionSchedulePlan;
|
import org.dromara.progress.domain.PgsConstructionSchedulePlan;
|
||||||
import org.dromara.progress.domain.dto.constructionscheduleplan.PgsConstructionSchedulePlanCreateReq;
|
import org.dromara.progress.domain.dto.constructionscheduleplan.PgsConstructionSchedulePlanCreateReq;
|
||||||
|
import org.dromara.progress.domain.dto.constructionscheduleplan.PgsConstructionSchedulePlanExcelDto;
|
||||||
import org.dromara.progress.domain.dto.constructionscheduleplan.PgsConstructionSchedulePlanQueryReq;
|
import org.dromara.progress.domain.dto.constructionscheduleplan.PgsConstructionSchedulePlanQueryReq;
|
||||||
import org.dromara.progress.domain.dto.constructionscheduleplan.PgsConstructionSchedulePlanUpdateReq;
|
import org.dromara.progress.domain.dto.constructionscheduleplan.PgsConstructionSchedulePlanUpdateReq;
|
||||||
import org.dromara.progress.domain.vo.constructionscheduleplan.PgsConstructionSchedulePlanVo;
|
import org.dromara.progress.domain.vo.constructionscheduleplan.PgsConstructionSchedulePlanVo;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -82,4 +85,20 @@ public interface IPgsConstructionSchedulePlanService extends IService<PgsConstru
|
|||||||
* @return 施工进度计划分页对象视图
|
* @return 施工进度计划分页对象视图
|
||||||
*/
|
*/
|
||||||
List<PgsConstructionSchedulePlanVo> getVoList(List<PgsConstructionSchedulePlan> constructionSchedulePlanList);
|
List<PgsConstructionSchedulePlanVo> getVoList(List<PgsConstructionSchedulePlan> constructionSchedulePlanList);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出Excel
|
||||||
|
*
|
||||||
|
* @param projectId 项目id
|
||||||
|
*/
|
||||||
|
void exportExcelByProjectId(Long projectId, HttpServletResponse response);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 读取Excel文件
|
||||||
|
*
|
||||||
|
* @param file Excel文件
|
||||||
|
* @param projectId 项目ID
|
||||||
|
* @return 读取的数据列表
|
||||||
|
*/
|
||||||
|
List<PgsConstructionSchedulePlanExcelDto> readExcel(MultipartFile file, Long projectId);
|
||||||
}
|
}
|
||||||
|
@ -2,23 +2,41 @@ package org.dromara.progress.service.impl;
|
|||||||
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.poi.ss.usermodel.*;
|
||||||
|
import org.apache.poi.ss.util.CellRangeAddressList;
|
||||||
|
import org.apache.poi.xssf.usermodel.XSSFSheet;
|
||||||
|
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||||
import org.dromara.common.core.constant.HttpStatus;
|
import org.dromara.common.core.constant.HttpStatus;
|
||||||
import org.dromara.common.core.exception.ServiceException;
|
import org.dromara.common.core.exception.ServiceException;
|
||||||
import org.dromara.common.core.utils.ObjectUtils;
|
import org.dromara.common.core.utils.ObjectUtils;
|
||||||
import org.dromara.common.core.utils.StringUtils;
|
import org.dromara.common.core.utils.StringUtils;
|
||||||
|
import org.dromara.design.domain.bo.DesUserBo;
|
||||||
import org.dromara.progress.domain.PgsConstructionSchedulePlan;
|
import org.dromara.progress.domain.PgsConstructionSchedulePlan;
|
||||||
import org.dromara.progress.domain.dto.constructionscheduleplan.PgsConstructionSchedulePlanCreateReq;
|
import org.dromara.progress.domain.dto.constructionscheduleplan.PgsConstructionSchedulePlanCreateReq;
|
||||||
|
import org.dromara.progress.domain.dto.constructionscheduleplan.PgsConstructionSchedulePlanExcelDto;
|
||||||
import org.dromara.progress.domain.dto.constructionscheduleplan.PgsConstructionSchedulePlanQueryReq;
|
import org.dromara.progress.domain.dto.constructionscheduleplan.PgsConstructionSchedulePlanQueryReq;
|
||||||
import org.dromara.progress.domain.dto.constructionscheduleplan.PgsConstructionSchedulePlanUpdateReq;
|
import org.dromara.progress.domain.dto.constructionscheduleplan.PgsConstructionSchedulePlanUpdateReq;
|
||||||
import org.dromara.progress.domain.vo.constructionscheduleplan.PgsConstructionSchedulePlanVo;
|
import org.dromara.progress.domain.vo.constructionscheduleplan.PgsConstructionSchedulePlanVo;
|
||||||
import org.dromara.progress.mapper.PgsConstructionSchedulePlanMapper;
|
import org.dromara.progress.mapper.PgsConstructionSchedulePlanMapper;
|
||||||
import org.dromara.progress.service.IPgsConstructionSchedulePlanService;
|
import org.dromara.progress.service.IPgsConstructionSchedulePlanService;
|
||||||
|
import org.dromara.project.service.IBusProjectService;
|
||||||
|
import org.dromara.system.domain.vo.SysDictDataVo;
|
||||||
|
import org.dromara.system.service.ISysDictDataService;
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.io.InputStream;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 施工进度计划Service业务层处理
|
* 施工进度计划Service业务层处理
|
||||||
@ -26,8 +44,16 @@ import java.util.List;
|
|||||||
* @author lilemy
|
* @author lilemy
|
||||||
* @date 2025-08-01
|
* @date 2025-08-01
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
public class PgsConstructionSchedulePlanServiceImpl extends ServiceImpl<PgsConstructionSchedulePlanMapper, PgsConstructionSchedulePlan> implements IPgsConstructionSchedulePlanService {
|
public class PgsConstructionSchedulePlanServiceImpl extends ServiceImpl<PgsConstructionSchedulePlanMapper, PgsConstructionSchedulePlan>
|
||||||
|
implements IPgsConstructionSchedulePlanService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private IBusProjectService projectService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ISysDictDataService dictDataService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询施工进度计划
|
* 查询施工进度计划
|
||||||
@ -146,4 +172,350 @@ public class PgsConstructionSchedulePlanServiceImpl extends ServiceImpl<PgsConst
|
|||||||
public List<PgsConstructionSchedulePlanVo> getVoList(List<PgsConstructionSchedulePlan> constructionSchedulePlanList) {
|
public List<PgsConstructionSchedulePlanVo> getVoList(List<PgsConstructionSchedulePlan> constructionSchedulePlanList) {
|
||||||
return constructionSchedulePlanList.stream().map(this::getVo).toList();
|
return constructionSchedulePlanList.stream().map(this::getVo).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// region
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出Excel
|
||||||
|
*
|
||||||
|
* @param projectId 项目id
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void exportExcelByProjectId(Long projectId, HttpServletResponse response) {
|
||||||
|
DesUserBo desUserBo = new DesUserBo();
|
||||||
|
desUserBo.setProjectId(projectId);
|
||||||
|
Map<Long, String> projectStructureMap = projectService.getStructureAsList(projectId);
|
||||||
|
List<SysDictDataVo> dictDataVos = dictDataService.selectByDictType("project_construction_status");
|
||||||
|
Map<String, String> statusMap = new HashMap<>();
|
||||||
|
for (SysDictDataVo vo : dictDataVos) {
|
||||||
|
statusMap.put(vo.getDictValue(), vo.getDictLabel());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 2. 设置响应头
|
||||||
|
// 设置响应头,指定Excel格式和下载文件名
|
||||||
|
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||||
|
response.setCharacterEncoding("utf-8");
|
||||||
|
response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("施工里程碑计划模版.xlsx", StandardCharsets.UTF_8));
|
||||||
|
|
||||||
|
Workbook workbook = new XSSFWorkbook();
|
||||||
|
// 创建主 Sheet 和隐藏 Sheet
|
||||||
|
Sheet mainSheet = workbook.createSheet("施工里程碑计划模版");
|
||||||
|
Sheet dataSheet = workbook.createSheet("DropdownData");
|
||||||
|
workbook.setSheetHidden(workbook.getSheetIndex(dataSheet), true);
|
||||||
|
|
||||||
|
// 3. 创建单元格样式
|
||||||
|
CellStyle editableStyle = createEditableCellStyle(workbook); // 可编辑单元格样式
|
||||||
|
CellStyle protectedStyle = createProtectedCellStyle(workbook); // 受保护单元格样式(ID列用
|
||||||
|
//填充隐藏数据Sheet
|
||||||
|
int rowIndex = 0;
|
||||||
|
// 填充项目关联结构(A列和B列)
|
||||||
|
for (Map.Entry<Long, String> entry : projectStructureMap.entrySet()) {
|
||||||
|
Row row = dataSheet.createRow(rowIndex++);
|
||||||
|
row.createCell(0).setCellValue(entry.getValue());
|
||||||
|
row.createCell(1).setCellValue(entry.getKey().toString());
|
||||||
|
}
|
||||||
|
// 重置行索引,填充人员和人员ID(C列和D列)
|
||||||
|
rowIndex = 0;
|
||||||
|
for (Map.Entry<String, String> entry : statusMap.entrySet()) {
|
||||||
|
Row row = dataSheet.getRow(rowIndex);
|
||||||
|
if (row == null) {
|
||||||
|
row = dataSheet.createRow(rowIndex);
|
||||||
|
}
|
||||||
|
row.createCell(4).setCellValue(entry.getValue());
|
||||||
|
row.createCell(5).setCellValue(entry.getKey());
|
||||||
|
rowIndex++;
|
||||||
|
}
|
||||||
|
// 主 Sheet 设置表头
|
||||||
|
Row sheetRow = mainSheet.createRow(0);
|
||||||
|
String[] headers = {"节点名称", "对应项目结构", "对应项目结构编码", "预计开始时间(格式:2025-09-06)",
|
||||||
|
"预计结束时间", "实际开始时间", "实际结束时间", "状态", "状态编码", "备注"};
|
||||||
|
for (int i = 0; i < headers.length; i++) {
|
||||||
|
Cell cell = sheetRow.createCell(i);
|
||||||
|
cell.setCellValue(headers[i]);
|
||||||
|
}
|
||||||
|
// 6. 设置专业下拉列表(第二列)
|
||||||
|
setMajorDropdown(mainSheet, projectStructureMap.size());
|
||||||
|
setStatusDropdown(mainSheet, statusMap.size());
|
||||||
|
String formulaTemplate = "IFERROR(INDEX(DropdownData!$B$1:$B$" + projectStructureMap.size() + ", MATCH(B{rowNum}, DropdownData!$A$1:$A$" + projectStructureMap.size() + ", 0)),\"\")";
|
||||||
|
String formulaTemplate1 = "IFERROR(INDEX(DropdownData!$F$1:$F$" + statusMap.size() + ", MATCH(H{rowNum}, DropdownData!$E$1:$E$" + statusMap.size() + ", 0)),\"\")";
|
||||||
|
for (int i = 1; i <= 1000; i++) { // 从第2行到101行
|
||||||
|
Row row = mainSheet.createRow(i);
|
||||||
|
int currentRowNum = i + 1; // Excel行号从1开始
|
||||||
|
String formula = formulaTemplate.replace("{rowNum}", String.valueOf(currentRowNum));
|
||||||
|
|
||||||
|
Cell cell = row.createCell(1);
|
||||||
|
cell.setCellStyle(editableStyle); //专业不锁定
|
||||||
|
|
||||||
|
Cell idCell = row.createCell(2);
|
||||||
|
idCell.setCellFormula(formula);
|
||||||
|
idCell.setCellStyle(protectedStyle); // 应用隐藏公式样式
|
||||||
|
|
||||||
|
String formula1 = formulaTemplate1.replace("{rowNum}", String.valueOf(currentRowNum));
|
||||||
|
|
||||||
|
Cell cell1 = row.createCell(7);
|
||||||
|
cell1.setCellStyle(editableStyle); //专业不锁定
|
||||||
|
|
||||||
|
Cell idCell1 = row.createCell(8);
|
||||||
|
idCell1.setCellFormula(formula1);
|
||||||
|
idCell1.setCellStyle(protectedStyle); // 应用隐藏公式样式
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (int i = 1; i <= 100; i++) {
|
||||||
|
Row row = mainSheet.getRow(i);
|
||||||
|
if (row == null) {
|
||||||
|
row = mainSheet.createRow(i);
|
||||||
|
}
|
||||||
|
Cell cell = row.createCell(0);
|
||||||
|
cell.setCellStyle(editableStyle);
|
||||||
|
|
||||||
|
Cell cell3 = row.createCell(3);
|
||||||
|
cell3.setCellStyle(editableStyle);
|
||||||
|
|
||||||
|
Cell cell4 = row.createCell(4);
|
||||||
|
cell4.setCellStyle(editableStyle);
|
||||||
|
|
||||||
|
Cell cell5 = row.createCell(5);
|
||||||
|
cell5.setCellStyle(editableStyle);
|
||||||
|
|
||||||
|
Cell cell6 = row.createCell(6);
|
||||||
|
cell6.setCellStyle(editableStyle);
|
||||||
|
|
||||||
|
Cell cell9 = row.createCell(9);
|
||||||
|
cell9.setCellStyle(editableStyle);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 保护工作表,仅允许编辑未锁定的单元格
|
||||||
|
mainSheet.protectSheet("123456"); // 空密码
|
||||||
|
|
||||||
|
// 核心:锁定表头(第1行)和前1列(包含ID列)
|
||||||
|
mainSheet.createFreezePane(0, 1, 0, 1);
|
||||||
|
|
||||||
|
|
||||||
|
// 调整列宽
|
||||||
|
mainSheet.setColumnWidth(0, 20 * 256);
|
||||||
|
mainSheet.setColumnWidth(1, 20 * 280);
|
||||||
|
mainSheet.setColumnWidth(2, 20 * 280);
|
||||||
|
mainSheet.setColumnWidth(3, 20 * 400);
|
||||||
|
mainSheet.setColumnWidth(4, 20 * 200);
|
||||||
|
mainSheet.setColumnWidth(5, 20 * 200);
|
||||||
|
mainSheet.setColumnWidth(6, 20 * 200);
|
||||||
|
mainSheet.setColumnWidth(7, 20 * 200);
|
||||||
|
mainSheet.setColumnWidth(8, 20 * 100);
|
||||||
|
mainSheet.setColumnWidth(9, 20 * 200);
|
||||||
|
|
||||||
|
// 直接写入响应输出流
|
||||||
|
try {
|
||||||
|
workbook.write(response.getOutputStream());
|
||||||
|
workbook.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建可编辑单元格样式
|
||||||
|
*/
|
||||||
|
private CellStyle createEditableCellStyle(Workbook workbook) {
|
||||||
|
CellStyle style = workbook.createCellStyle();
|
||||||
|
style.setLocked(false); // 关键:允许编辑
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建受保护单元格样式(用于ID列)
|
||||||
|
*/
|
||||||
|
private CellStyle createProtectedCellStyle(Workbook workbook) {
|
||||||
|
CellStyle style = workbook.createCellStyle();
|
||||||
|
DataFormat dataFormat = workbook.createDataFormat();
|
||||||
|
short formatIndex = dataFormat.getFormat("0"); // 匹配“自定义→0”格式
|
||||||
|
style.setDataFormat(formatIndex);
|
||||||
|
style.setHidden(true); // 隐藏公式
|
||||||
|
style.setLocked(true);
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置专业下拉列表(第二列,索引1)
|
||||||
|
*/
|
||||||
|
private void setMajorDropdown(Sheet mainSheet, int majorCount) {
|
||||||
|
DataValidationHelper helper = mainSheet.getDataValidationHelper();
|
||||||
|
|
||||||
|
// 专业数据范围:数据Sheet的A列(从第1行到专业数量行)
|
||||||
|
String majorRange = "DropdownData!$A$1:$A$" + majorCount;
|
||||||
|
|
||||||
|
DataValidationConstraint constraint = helper.createFormulaListConstraint(majorRange);
|
||||||
|
// 作用范围:第2行到100行,第二列
|
||||||
|
CellRangeAddressList addressList = new CellRangeAddressList(1, 1000, 1, 1);
|
||||||
|
|
||||||
|
DataValidation validation = helper.createValidation(constraint, addressList);
|
||||||
|
validation.setShowErrorBox(true);
|
||||||
|
mainSheet.addValidationData(validation);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置专业下拉列表(第二列,索引1)
|
||||||
|
*/
|
||||||
|
private void setStatusDropdown(Sheet mainSheet, int majorCount) {
|
||||||
|
DataValidationHelper helper = mainSheet.getDataValidationHelper();
|
||||||
|
|
||||||
|
// 专业数据范围:数据Sheet的A列(从第1行到专业数量行)
|
||||||
|
String majorRange = "DropdownData!$E$1:$E$" + majorCount;
|
||||||
|
|
||||||
|
DataValidationConstraint constraint = helper.createFormulaListConstraint(majorRange);
|
||||||
|
// 作用范围:第2行到100行,第二列
|
||||||
|
CellRangeAddressList addressList = new CellRangeAddressList(1, 1000, 7, 7);
|
||||||
|
|
||||||
|
DataValidation validation = helper.createValidation(constraint, addressList);
|
||||||
|
validation.setShowErrorBox(true);
|
||||||
|
mainSheet.addValidationData(validation);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 读取Excel文件
|
||||||
|
*
|
||||||
|
* @param file Excel文件
|
||||||
|
* @param projectId 项目ID
|
||||||
|
* @return 读取的数据列表
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<PgsConstructionSchedulePlanExcelDto> readExcel(MultipartFile file, Long projectId) {
|
||||||
|
List<PgsConstructionSchedulePlanExcelDto> dataList = new ArrayList<>();
|
||||||
|
|
||||||
|
try (InputStream inputStream = file.getInputStream();
|
||||||
|
XSSFWorkbook workbook = new XSSFWorkbook(inputStream)) {
|
||||||
|
|
||||||
|
XSSFSheet sheet = workbook.getSheetAt(0);
|
||||||
|
|
||||||
|
// 从第二行(index=1)开始读取数据,跳过表头
|
||||||
|
for (int rowIndex = 1; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
|
||||||
|
Row row = sheet.getRow(rowIndex);
|
||||||
|
if (hasValidData(row)) {
|
||||||
|
|
||||||
|
String nodeName = getCellValue(row.getCell(0));
|
||||||
|
String projectStructureName = getCellValue(row.getCell(1));
|
||||||
|
Long projectStructure = Long.valueOf(getCellValue(row.getCell(2)));
|
||||||
|
LocalDate planStartDate = getLocalDateValue(row.getCell(3));
|
||||||
|
LocalDate planEndDate = getLocalDateValue(row.getCell(4));
|
||||||
|
LocalDate practicalStartDate = getLocalDateValue(row.getCell(5));
|
||||||
|
LocalDate practicalEndDate = getLocalDateValue(row.getCell(6));
|
||||||
|
String status = getCellValue(row.getCell(8));
|
||||||
|
String remark = getCellValue(row.getCell(9));
|
||||||
|
|
||||||
|
PgsConstructionSchedulePlanExcelDto excelData = new PgsConstructionSchedulePlanExcelDto(
|
||||||
|
projectId, 0L, nodeName, projectStructure, projectStructureName,
|
||||||
|
planStartDate, planEndDate, practicalStartDate, practicalEndDate, status, remark
|
||||||
|
);
|
||||||
|
dataList.add(excelData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("读取表格数据失败", e);
|
||||||
|
throw new ServiceException("读取表格数据失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
return dataList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean hasValidData(Row row) {
|
||||||
|
// 遍历行中的所有单元格
|
||||||
|
for (int cellIndex = 0; cellIndex < row.getLastCellNum(); cellIndex++) {
|
||||||
|
Cell cell = row.getCell(cellIndex, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
|
||||||
|
String cellValue = getCellValue(cell).trim();
|
||||||
|
|
||||||
|
// 只要有一个单元格有非空值,就认为是有效行
|
||||||
|
if (!cellValue.isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getCellValue(Cell cell) {
|
||||||
|
if (cell == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
// 使用CellType枚举判断单元格类型(POI 4.0+版本推荐方式)
|
||||||
|
CellType cellType = cell.getCellType();
|
||||||
|
// 对于公式单元格,获取其计算结果的类型
|
||||||
|
if (cellType == CellType.FORMULA) {
|
||||||
|
cellType = cell.getCachedFormulaResultType();
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (cellType) {
|
||||||
|
case STRING:
|
||||||
|
return cell.getStringCellValue().trim();
|
||||||
|
case NUMERIC:
|
||||||
|
if (DateUtil.isCellDateFormatted(cell)) {
|
||||||
|
Date date = cell.getDateCellValue();
|
||||||
|
return date.toString();
|
||||||
|
} else {
|
||||||
|
// 处理数字类型,避免科学计数法
|
||||||
|
return String.valueOf((long) cell.getNumericCellValue());
|
||||||
|
}
|
||||||
|
case BOOLEAN:
|
||||||
|
return String.valueOf(cell.getBooleanCellValue());
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static LocalDate getLocalDateValue(Cell cell) {
|
||||||
|
if (cell == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
CellType cellType = cell.getCellType();
|
||||||
|
if (cellType == CellType.FORMULA) {
|
||||||
|
cellType = cell.getCachedFormulaResultType();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (cellType == CellType.NUMERIC) {
|
||||||
|
if (DateUtil.isCellDateFormatted(cell)) {
|
||||||
|
Date date = cell.getDateCellValue();
|
||||||
|
return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
|
||||||
|
} else {
|
||||||
|
// 如果是数字但不是日期,就尝试转为 LocalDate (例如 20250730)
|
||||||
|
double numericValue = cell.getNumericCellValue();
|
||||||
|
String text = String.valueOf((long) numericValue);
|
||||||
|
return LocalDate.parse(text);
|
||||||
|
}
|
||||||
|
} else if (cellType == CellType.STRING) {
|
||||||
|
String text = cell.getStringCellValue().trim();
|
||||||
|
if (text.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// 尝试解析不同格式
|
||||||
|
try {
|
||||||
|
return LocalDate.parse(text); // 默认 ISO 格式 yyyy-MM-dd
|
||||||
|
} catch (Exception e) {
|
||||||
|
// 如果 Excel 是 yyyy/MM/dd 或 yyyy.MM.dd,可以额外处理
|
||||||
|
try {
|
||||||
|
return LocalDate.parse(text, java.time.format.DateTimeFormatter.ofPattern("yyyy/MM/dd"));
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return LocalDate.parse(text, java.time.format.DateTimeFormatter.ofPattern("yyyy.MM.dd"));
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
return null; // 不识别的格式就返回 null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -809,9 +809,15 @@ public class PgsProgressPlanDetailServiceImpl extends ServiceImpl<PgsProgressPla
|
|||||||
value.setProjectId(planDetail.getProjectId());
|
value.setProjectId(planDetail.getProjectId());
|
||||||
value.setMatrixId(category.getMatrixId());
|
value.setMatrixId(category.getMatrixId());
|
||||||
value.setProgressCategoryId(progressCategoryId);
|
value.setProgressCategoryId(progressCategoryId);
|
||||||
int artificialNum = planDetail.getFinishedNumber().intValue();
|
BigDecimal finishedNumber = planDetail.getFinishedNumber();
|
||||||
|
BigDecimal aiFill = planDetail.getAiFill();
|
||||||
|
// 如果完成数量为0, 则不保存
|
||||||
|
if (finishedNumber.compareTo(BigDecimal.ZERO) == 0 && aiFill.compareTo(BigDecimal.ZERO) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int artificialNum = finishedNumber.intValue();
|
||||||
value.setArtificialNum(artificialNum);
|
value.setArtificialNum(artificialNum);
|
||||||
int uavNum = planDetail.getAiFill().intValue();
|
int uavNum = aiFill.intValue();
|
||||||
value.setUavNum(uavNum);
|
value.setUavNum(uavNum);
|
||||||
value.setPlanNum(planDetail.getPlanNumber().intValue());
|
value.setPlanNum(planDetail.getPlanNumber().intValue());
|
||||||
value.setReportDate(LocalDate.now());
|
value.setReportDate(LocalDate.now());
|
||||||
|
@ -11,6 +11,7 @@ import org.dromara.project.domain.vo.project.*;
|
|||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -197,6 +198,14 @@ public interface IBusProjectService extends IService<BusProject> {
|
|||||||
*/
|
*/
|
||||||
BusProjectStructureVo getStructure(Long projectId);
|
BusProjectStructureVo getStructure(Long projectId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取项目结构
|
||||||
|
*
|
||||||
|
* @param projectId 项目id
|
||||||
|
* @return 结构(key 主键id,value 名称)
|
||||||
|
*/
|
||||||
|
Map<Long, String> getStructureAsList(Long projectId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 改变项目所属用户
|
* 改变项目所属用户
|
||||||
*
|
*
|
||||||
|
@ -1066,6 +1066,57 @@ public class BusProjectServiceImpl extends ServiceImpl<BusProjectMapper, BusProj
|
|||||||
return vo;
|
return vo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取项目结构
|
||||||
|
*
|
||||||
|
* @param projectId 项目id
|
||||||
|
* @return 结构(key 主键id,value 名称)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Map<Long, String> getStructureAsList(Long projectId) {
|
||||||
|
Map<Long, String> map = new HashMap<>();
|
||||||
|
// 获取项目
|
||||||
|
BusProject project = this.getById(projectId);
|
||||||
|
if (project == null) {
|
||||||
|
throw new ServiceException("项目信息不存在", HttpStatus.NOT_FOUND);
|
||||||
|
}
|
||||||
|
map.put(project.getId(), "项目:" + project.getProjectName());
|
||||||
|
|
||||||
|
// 获取项目子项
|
||||||
|
List<BusProject> subProjects = this.lambdaQuery()
|
||||||
|
.eq(BusProject::getPId, projectId)
|
||||||
|
.list();
|
||||||
|
if (CollUtil.isNotEmpty(subProjects)) {
|
||||||
|
for (BusProject subProject : subProjects) {
|
||||||
|
map.put(subProject.getId(), "子项目:" + subProject.getProjectName());
|
||||||
|
}
|
||||||
|
// 获取方阵信息
|
||||||
|
List<FacMatrix> matrixList = matrixService.lambdaQuery()
|
||||||
|
.in(FacMatrix::getProjectId, subProjects.stream().map(BusProject::getId).toList())
|
||||||
|
.list();
|
||||||
|
if (CollUtil.isNotEmpty(matrixList)) {
|
||||||
|
for (FacMatrix matrix : matrixList) {
|
||||||
|
map.put(matrix.getId(), "方阵:" + matrix.getMatrixName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 获取分项工程
|
||||||
|
List<PgsProgressCategory> progressCategoryList = progressCategoryService.lambdaQuery()
|
||||||
|
.in(PgsProgressCategory::getMatrixId, matrixList.stream().map(FacMatrix::getId).toList())
|
||||||
|
.list();
|
||||||
|
if (CollUtil.isNotEmpty(progressCategoryList)) {
|
||||||
|
for (PgsProgressCategory progressCategory : progressCategoryList) {
|
||||||
|
String matrixName = progressCategory.getMatrixName();
|
||||||
|
if (StringUtils.isNotBlank(matrixName)) {
|
||||||
|
map.put(progressCategory.getId(), "分项工程:" + matrixName + "-" + progressCategory.getName());
|
||||||
|
} else {
|
||||||
|
map.put(progressCategory.getId(), "分项工程:" + progressCategory.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 改变项目所属用户
|
* 改变项目所属用户
|
||||||
*
|
*
|
||||||
|
Reference in New Issue
Block a user