进度管理大屏

This commit is contained in:
lcj
2025-12-16 19:10:57 +08:00
parent 5fc35e1a4c
commit f9b8ae5dbb
7 changed files with 289 additions and 47 deletions

View File

@ -6,11 +6,11 @@ import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.dromara.bigscreen.domain.dto.ProjectImageProgressDetailReq;
import org.dromara.bigscreen.domain.progress.DesignProgressVo;
import org.dromara.bigscreen.domain.progress.MaterialProgressDetailVo;
import org.dromara.bigscreen.domain.progress.MilestoneProgressVo;
import org.dromara.bigscreen.domain.progress.ProjectTotalProgressVo;
import org.dromara.bigscreen.domain.vo.ProjectImageProgressDetailVo;
import org.dromara.bigscreen.service.ProgressBigScreenService;
import org.dromara.bigscreen.service.ProjectBigScreenService;
import org.dromara.common.core.domain.R;
import org.dromara.common.web.core.BaseController;
import org.springframework.validation.annotation.Validated;
@ -37,9 +37,6 @@ public class ProgressBigScreenController extends BaseController {
@Resource
private ProgressBigScreenService progressBigScreenService;
@Resource
private ProjectBigScreenService projectBigScreenService;
/**
* 获取项目总进度
*/
@ -71,7 +68,16 @@ public class ProgressBigScreenController extends BaseController {
* 获取施工进度详情
*/
@GetMapping("/constructionProgress/detail")
public R<List<ProjectImageProgressDetailVo>> getProjectImageProgressDetail(@Validated ProjectImageProgressDetailReq req) {
return R.ok(projectBigScreenService.getProjectImageProgressDetail(req));
public R<List<ProjectImageProgressDetailVo>> getProjectTotalProgressDetail(@Validated ProjectImageProgressDetailReq req) {
return R.ok(progressBigScreenService.getProjectTotalProgressDetail(req));
}
/**
* 获取材料进度详情
*/
@GetMapping("/materialProgress/detail/{projectId}")
public R<List<MaterialProgressDetailVo>> getMaterialProgressDetail(@NotNull(message = "项目主键不能为空")
@PathVariable Long projectId) {
return R.ok(progressBigScreenService.getMaterialProgressDetail(projectId));
}
}

View File

@ -0,0 +1,68 @@
package org.dromara.bigscreen.domain.progress;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;
/**
* @author lilemy
* @date 2025-12-16 17:03
*/
@Data
public class MaterialProgressDetailVo implements Serializable {
@Serial
private static final long serialVersionUID = -4499381537680421083L;
/**
* 主键id
*/
private Long id;
/**
* 名称
*/
private String name;
/**
* 数量
*/
private BigDecimal quantity;
/**
* 验收
*/
private BigDecimal acceptedQuantity;
/**
* 缺件
*/
private BigDecimal shortageQuantity;
// region 接收单数据
/**
* 合同名称
*/
private String contractName;
/**
* 订货单位
*/
private String orderingUnit;
/**
* 供货单位
*/
private String supplierUnit;
/**
* 到货时间
*/
private LocalDate arrivalDate;
// endregion
}

View File

@ -1,8 +1,13 @@
package org.dromara.bigscreen.service;
import org.dromara.bigscreen.domain.dto.ProjectImageProgressDetailReq;
import org.dromara.bigscreen.domain.progress.DesignProgressVo;
import org.dromara.bigscreen.domain.progress.MaterialProgressDetailVo;
import org.dromara.bigscreen.domain.progress.MilestoneProgressVo;
import org.dromara.bigscreen.domain.progress.ProjectTotalProgressVo;
import org.dromara.bigscreen.domain.vo.ProjectImageProgressDetailVo;
import org.dromara.bigscreen.domain.vo.wzxqysjdhdbVo;
import org.springframework.validation.annotation.Validated;
import java.util.List;
@ -20,6 +25,14 @@ public interface ProgressBigScreenService {
*/
ProjectTotalProgressVo getProjectTotalProgress(Long projectId);
/**
* 获取施工进度详情
*
* @param req 请求参数
* @return 施工进度详情
*/
List<ProjectImageProgressDetailVo> getProjectTotalProgressDetail(@Validated ProjectImageProgressDetailReq req);
/**
* 获取里程碑进度
*
@ -35,4 +48,20 @@ public interface ProgressBigScreenService {
* @return 设计进度
*/
DesignProgressVo getDesignProgress(Long projectId);
/**
* 获取物料进度详情
*
* @param projectId 项目 id
* @return 物料进度详情
*/
List<MaterialProgressDetailVo> getMaterialProgressDetail(Long projectId);
/**
* 获取物资进度
*
* @param projectId 项目 id
* @return 物资进度
*/
List<wzxqysjdhdbVo> getMaterialProgress(Long projectId);
}

View File

@ -3,14 +3,24 @@ package org.dromara.bigscreen.service.impl;
import cn.hutool.core.collection.CollUtil;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.dromara.bigscreen.domain.dto.ProjectImageProgressDetailReq;
import org.dromara.bigscreen.domain.progress.*;
import org.dromara.bigscreen.domain.vo.ProjectImageProgressDetailVo;
import org.dromara.bigscreen.domain.vo.wzxqysjdhdbVo;
import org.dromara.bigscreen.service.ProgressBigScreenService;
import org.dromara.bigscreen.service.ProjectBigScreenService;
import org.dromara.cailiaoshebei.service.IBusMrpBaseService;
import org.dromara.common.core.enums.BusinessStatusEnum;
import org.dromara.common.core.utils.DateUtils;
import org.dromara.common.utils.BigDecimalUtil;
import org.dromara.design.domain.DesVolumeCatalog;
import org.dromara.design.domain.DesVolumeFile;
import org.dromara.design.service.IDesVolumeCatalogService;
import org.dromara.design.service.IDesVolumeFileService;
import org.dromara.materials.domain.MatMaterialReceive;
import org.dromara.materials.domain.MatMaterialReceiveItem;
import org.dromara.materials.service.IMatMaterialReceiveItemService;
import org.dromara.materials.service.IMatMaterialReceiveService;
import org.dromara.progress.constant.PgsProgressCategoryConstant;
import org.dromara.progress.domain.PgsConstructionSchedulePlan;
import org.dromara.progress.domain.PgsProgressCategory;
@ -28,6 +38,7 @@ import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
@ -44,6 +55,9 @@ import java.util.stream.Collectors;
@Service
public class ProgressBigScreenServiceImpl implements ProgressBigScreenService {
@Resource
private ProjectBigScreenService projectBigScreenService;
@Resource
private IBusProjectService projectService;
@ -65,6 +79,15 @@ public class ProgressBigScreenServiceImpl implements ProgressBigScreenService {
@Resource
private ISysDictDataService dictDataService;
@Resource
private IMatMaterialReceiveService materialReceiveService;
@Resource
private IMatMaterialReceiveItemService materialReceiveItemService;
@Resource
private IBusMrpBaseService mrpBaseService;
/**
* 获取项目总进度
*
@ -116,8 +139,8 @@ public class ProgressBigScreenServiceImpl implements ProgressBigScreenService {
}
// 获取整体完成情况
PgsProgressCategoryValueTotalVo valueTotal = progressCategoryService.getValueTotal(children, true);
vo.setTotalCompletionAmount(valueTotal.getTotalValue());
vo.setCurrentCompletionAmount(valueTotal.getCurrentValue());
vo.setTotalCompletionAmount(valueTotal.getTotalValue().divide(BigDecimal.valueOf(10000), 0, RoundingMode.HALF_UP));
vo.setCurrentCompletionAmount(valueTotal.getCurrentValue().divide(BigDecimal.valueOf(10000), 0, RoundingMode.HALF_UP));
// 获取详情
Map<String, List<PgsProgressCategory>> nameMap = topList.stream()
.collect(Collectors.groupingBy(PgsProgressCategory::getName));
@ -144,6 +167,17 @@ public class ProgressBigScreenServiceImpl implements ProgressBigScreenService {
return vo;
}
/**
* 获取施工进度详情
*
* @param req 请求参数
* @return 施工进度详情
*/
@Override
public List<ProjectImageProgressDetailVo> getProjectTotalProgressDetail(ProjectImageProgressDetailReq req) {
return projectBigScreenService.getProjectImageProgressDetail(req);
}
/**
* 获取里程碑进度
*
@ -284,6 +318,7 @@ public class ProgressBigScreenServiceImpl implements ProgressBigScreenService {
}
}
}
vo.setTotalDesign((long) fileList.size());
vo.setReviewedDesign(reviewedDesign);
vo.setReviewedDesignTrend(reviewedDesignThisM.compareTo(reviewedDesignLastM) >= 0);
vo.setReviewedDesignRate(BigDecimalUtil.toLoopPercentage(reviewedDesignThisM, reviewedDesignLastM));
@ -292,4 +327,58 @@ public class ProgressBigScreenServiceImpl implements ProgressBigScreenService {
vo.setPendingDesignReviewRate(BigDecimalUtil.toLoopPercentage(pendingReviewDesignThisD, pendingReviewDesignLastD));
return vo;
}
/**
* 获取物料进度详情
*
* @param projectId 项目 id
* @return 物料进度详情
*/
@Override
public List<MaterialProgressDetailVo> getMaterialProgressDetail(Long projectId) {
List<MatMaterialReceive> receiveList = materialReceiveService.lambdaQuery()
.eq(MatMaterialReceive::getProjectId, projectId)
.list();
if (CollUtil.isEmpty(receiveList)) {
return List.of();
}
List<Long> ids = receiveList.stream().map(MatMaterialReceive::getId).toList();
List<MatMaterialReceiveItem> itemList = materialReceiveItemService.lambdaQuery()
.in(MatMaterialReceiveItem::getReceiveId, ids)
.list();
if (CollUtil.isEmpty(itemList)) {
return List.of();
}
Map<Long, MatMaterialReceive> receiveMap = receiveList.stream()
.collect(Collectors.toMap(MatMaterialReceive::getId, receive -> receive));
return itemList.stream().map(item -> {
Long receiveId = item.getReceiveId();
MatMaterialReceive receive = receiveMap.get(receiveId);
if (receive == null) {
return null;
}
MaterialProgressDetailVo vo = new MaterialProgressDetailVo();
vo.setId(item.getId());
vo.setName(item.getName());
vo.setQuantity(item.getQuantity());
vo.setAcceptedQuantity(item.getAcceptedQuantity());
vo.setShortageQuantity(item.getShortageQuantity());
vo.setContractName(receive.getContractName());
vo.setOrderingUnit(receive.getOrderingUnit());
vo.setSupplierUnit(receive.getSupplierUnit());
vo.setArrivalDate(DateUtils.toLocalDate(receive.getCreateTime()));
return vo;
}).filter(Objects::nonNull).toList();
}
/**
* 获取物资进度
*
* @param projectId 项目 id
* @return 物资进度
*/
@Override
public List<wzxqysjdhdbVo> getMaterialProgress(Long projectId) {
return mrpBaseService.wzxqysjdhdb(projectId);
}
}

View File

@ -191,7 +191,7 @@ public class BusPurchaseDocServiceImpl extends ServiceImpl<BusPurchaseDocMapper,
BusPurchaseDoc add = MapstructUtils.convert(bo, BusPurchaseDoc.class);
validEntityBeforeSave(add);
validNum(bo.getAssociationList(),add.getSupplierId());
validNum(bo.getAssociationList(), add.getSupplierId());
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setId(add.getId());
@ -212,7 +212,7 @@ public class BusPurchaseDocServiceImpl extends ServiceImpl<BusPurchaseDocMapper,
for (BusPlanDocAssociationBo association : associationList) {
if(association.getDemandQuantity() == null){
if (association.getDemandQuantity() == null) {
throw new ServiceException("请填写需求数量");
}
@ -249,13 +249,13 @@ public class BusPurchaseDocServiceImpl extends ServiceImpl<BusPurchaseDocMapper,
busMaterialbatchdemandplans.forEach(busMaterialbatchdemandplan -> {
planids.add(busMaterialbatchdemandplan.getId());
});
if (!ids1.isEmpty()){
if (!ids1.isEmpty()) {
List<BusPlanDocAssociation> list1 = planDocAssociationService.list(Wrappers.lambdaQuery(BusPlanDocAssociation.class)
.in(BusPlanDocAssociation::getDocId, ids1));
//计算材料已存在的数量
BigDecimal cltotal = list1.stream()
.filter(Objects::nonNull)
.filter(item->planids.contains(item.getPlanId()))
.filter(item -> planids.contains(item.getPlanId()))
.map(BusPlanDocAssociation::getDemandQuantity)
.reduce(BigDecimal.ZERO, BigDecimal::add);
if (cltotal.add(association.getDemandQuantity()).compareTo(quantity) > 0) {
@ -411,7 +411,12 @@ public class BusPurchaseDocServiceImpl extends ServiceImpl<BusPurchaseDocMapper,
.eq(BusPlanDocAssociation::getDocId, purchaseDoc.getId())
.list();
if (CollUtil.isNotEmpty(planDocAssociationList)) {
Map<Long, BigDecimal> map = planDocAssociationList.stream().collect(Collectors.toMap(BusPlanDocAssociation::getPlanId, BusPlanDocAssociation::getDemandQuantity));
Map<Long, BigDecimal> map = planDocAssociationList.stream()
.peek(item -> {
if (item.getDemandQuantity() == null) {
item.setDemandQuantity(BigDecimal.ZERO);
}
}).collect(Collectors.toMap(BusPlanDocAssociation::getPlanId, BusPlanDocAssociation::getDemandQuantity));
items = materialbatchdemandplanService.listByIds(map.keySet());
items.forEach(item -> item.setDemandQuantity(map.get(item.getId())));
}

View File

@ -36,8 +36,10 @@ public class BigDecimalUtil {
if (thisNum == null || lastNum == null) {
return BigDecimal.valueOf(0.00);
}
if (lastNum.compareTo(BigDecimal.ZERO) == 0) {
if (lastNum.compareTo(BigDecimal.ZERO) == 0 && thisNum.compareTo(BigDecimal.ZERO) > 0) {
return BigDecimal.valueOf(100.00);
} else if (lastNum.compareTo(BigDecimal.ZERO) == 0) {
return BigDecimal.valueOf(0.00);
}
return thisNum.subtract(lastNum)
.multiply(new BigDecimal("100"))

View File

@ -5,9 +5,13 @@ import jakarta.websocket.*;
import jakarta.websocket.server.ServerEndpoint;
import lombok.extern.slf4j.Slf4j;
import org.dromara.bigscreen.domain.bo.DpznglBo;
import org.dromara.bigscreen.domain.progress.DesignProgressVo;
import org.dromara.bigscreen.domain.progress.MilestoneProgressVo;
import org.dromara.bigscreen.domain.progress.ProjectTotalProgressVo;
import org.dromara.bigscreen.domain.vo.*;
import org.dromara.bigscreen.service.DpzaglService;
import org.dromara.bigscreen.service.IMaterialsManagementService;
import org.dromara.bigscreen.service.ProgressBigScreenService;
import org.dromara.cailiaoshebei.domain.vo.BusPurchaseDocVo;
import org.dromara.cailiaoshebei.service.IBusMrpBaseService;
import org.dromara.cailiaoshebei.service.IBusPurchaseDocService;
@ -66,7 +70,7 @@ public class BigScreenWebSocketServer {
SUBSCRIPTION_SESSIONS.put(currentSubscriptionId, session);
SESSION_TO_SUBSCRIPTION.put(session.getId(), currentSubscriptionId);
log.info("📌 客户端订阅成功订阅ID{}会话ID{},当前订阅数:{}",
currentSubscriptionId, session.getId(), SUBSCRIPTION_SESSIONS.size());
currentSubscriptionId, session.getId(), SUBSCRIPTION_SESSIONS.size());
} else {
log.warn("📌 客户端连接未携带订阅ID会话ID{}", session.getId());
}
@ -91,69 +95,71 @@ public class BigScreenWebSocketServer {
List<Map<String, String>> maps = new ArrayList<>();
switch ((int) type){
switch ((int) type) {
case 1:
break;
case 2:
Long timeType = Long.parseLong(params.get("timeType").getFirst());
//判断参数
if (timeType != 1L && timeType != 2L && timeType != 3L){
if (timeType != 1L && timeType != 2L && timeType != 3L) {
throw new RuntimeException("时间类型参数错误");
}
//先获取左边坐标得到map
Map<String, String> infoData = busAttendanceService.getRyglOnlineUserInfoData(projectId);
//获取右边数据
busAttendanceService.getAttendanceInfo(projectId,timeType,infoData);
busAttendanceService.getAttendanceInfo(projectId, timeType, infoData);
//返回数据
maps.add(infoData);
break;
case 3:
if (dpzaglService != null){
saveDateDpzagl(dpzaglService,params,projectId,maps);
if (dpzaglService != null) {
saveDateDpzagl(dpzaglService, params, projectId, maps);
}
break;
case 4:
// 进度管理大屏
getProgressBigScreenData(maps, projectId);
break;
case 5:
if (materialsService != null){
if (materialsService != null) {
InventoryStructureAnalysisVo vo = managementService.inventoryStructureAnalysis(projectId);
if (vo != null){
if (vo != null) {
Map<String, String> map = new HashMap<>();
map.put("type","inventoryStructureAnalysis");
map.put("type", "inventoryStructureAnalysis");
map.put("data", JSONUtil.toJsonStr(vo));
maps.add(map);
}
}
if (purchaseDocService != null){
if (purchaseDocService != null) {
List<BusPurchaseDocVo> purchaseDocVos = purchaseDocService.purchaseNote(projectId);
if (purchaseDocVos != null && !purchaseDocVos.isEmpty()){
if (purchaseDocVos != null && !purchaseDocVos.isEmpty()) {
Map<String, String> map = new HashMap<>();
map.put("type","purchaseNote");
map.put("type", "purchaseNote");
map.put("data", JSONUtil.toJsonStr(purchaseDocVos));
maps.add(map);
}
}
if (mrpBaseService != null){
if (mrpBaseService != null) {
List<designAndArrivalComparisonVo> designAndArrivalComparisonVos = mrpBaseService.designAndArrivalComparison(projectId);
if (designAndArrivalComparisonVos != null && !designAndArrivalComparisonVos.isEmpty()){
if (designAndArrivalComparisonVos != null && !designAndArrivalComparisonVos.isEmpty()) {
Map<String, String> map = new HashMap<>();
map.put("type","designAndArrivalComparison");
map.put("type", "designAndArrivalComparison");
map.put("data", JSONUtil.toJsonStr(designAndArrivalComparisonVos));
maps.add(map);
}
List<wzxqysjdhdbVo> wzxqysjdhdbVos = mrpBaseService.wzxqysjdhdb(projectId);
if (wzxqysjdhdbVos != null && !wzxqysjdhdbVos.isEmpty()){
if (wzxqysjdhdbVos != null && !wzxqysjdhdbVos.isEmpty()) {
Map<String, String> map = new HashMap<>();
map.put("type","wzxqysjdhdb");
map.put("type", "wzxqysjdhdb");
map.put("data", JSONUtil.toJsonStr(wzxqysjdhdbVos));
maps.add(map);
}
}
if (materialsService != null){
if (materialsService != null) {
List<MatMaterialsUseDetailVo> useDetailVos = materialsService.listUseDetail(projectId);
if (useDetailVos != null && !useDetailVos.isEmpty()){
if (useDetailVos != null && !useDetailVos.isEmpty()) {
Map<String, String> map = new HashMap<>();
map.put("type","listUseDetail");
map.put("type", "listUseDetail");
map.put("data", JSONUtil.toJsonStr(useDetailVos));
maps.add(map);
}
@ -217,8 +223,8 @@ public class BigScreenWebSocketServer {
log.info("🔌 客户端订阅关系已清除订阅ID{}会话ID{}", subscriptionId, session.getId());
}
log.info("🔌 客户端断开连接会话ID{},原因:{},当前在线数:{},当前订阅数:{}",
session.getId(), reason.getReasonPhrase(),
ONLINE_SESSIONS.size(), SUBSCRIPTION_SESSIONS.size());
session.getId(), reason.getReasonPhrase(),
ONLINE_SESSIONS.size(), SUBSCRIPTION_SESSIONS.size());
}
/**
@ -234,8 +240,9 @@ public class BigScreenWebSocketServer {
/**
* 向指定订阅ID的客户端发送消息
*
* @param subscriptionId 订阅ID
* @param message 消息内容
* @param message 消息内容
* @return 是否发送成功
*/
public static boolean sendToSubscription(String subscriptionId, String message) {
@ -262,6 +269,7 @@ public class BigScreenWebSocketServer {
/**
* 向所有订阅客户端广播消息
*
* @param message 消息内容
*/
public static void broadcastToAllSubscriptions(String message) {
@ -310,39 +318,74 @@ public class BigScreenWebSocketServer {
}
private void saveDateDpzagl(DpzaglService dpzaglService, Map<String, List<String>> params,Long projectId,List<Map<String, String>> maps) {
private void saveDateDpzagl(DpzaglService dpzaglService, Map<String, List<String>> params, Long projectId, List<Map<String, String>> maps) {
DpznglBo dpznglBo = new DpznglBo();
dpznglBo.setProjectId(projectId);
// 查询大屏-质安管理-安全员分布情况
List<DpznglAqyVo> dpznglAqyVos = dpzaglService.listByAqy(dpznglBo);
if (dpznglAqyVos != null && dpznglAqyVos.size() > 0){
if (dpznglAqyVos != null && dpznglAqyVos.size() > 0) {
Map<String, String> map = new HashMap<>();
map.put("type","aqy");
map.put("type", "aqy");
map.put("data", JSONUtil.toJsonStr(dpznglAqyVos));
maps.add(map);
}
// 查询大屏-质安管理-站班会,巡检工单,整改情况
// 查询大屏-质安管理-站班会,巡检工单,整改情况
DpznglVo dpznglVo = dpzaglService.queryList(dpznglBo);
if (dpznglVo != null){
if (dpznglVo != null) {
Map<String, String> map = new HashMap<>();
map.put("type","zagl");
map.put("type", "zagl");
map.put("data", JSONUtil.toJsonStr(dpznglVo));
maps.add(map);
}
//查询大屏-质安管理-站班会
//查询大屏-质安管理-站班会
DpznglVo byzbh = dpzaglService.listByzbh(dpznglBo);
if (byzbh != null){
if (byzbh != null) {
Map<String, String> map = new HashMap<>();
map.put("type","zbh");
map.put("type", "zbh");
map.put("data", JSONUtil.toJsonStr(byzbh));
maps.add(map);
}
}
/**
* 获取进度大屏数据
*/
private static void getProgressBigScreenData(List<Map<String, String>> maps, Long projectId) {
ProgressBigScreenService service = SpringUtils.getBean(ProgressBigScreenService.class);
if (service != null) {
DesignProgressVo designProgress = service.getDesignProgress(projectId);
if (designProgress != null) {
Map<String, String> map = new HashMap<>();
map.put("type", "progressDesignProgress");
map.put("data", JSONUtil.toJsonStr(designProgress));
maps.add(map);
}
ProjectTotalProgressVo projectTotalProgress = service.getProjectTotalProgress(projectId);
if (projectTotalProgress != null) {
Map<String, String> map = new HashMap<>();
map.put("type", "progressProjectTotalProgress");
map.put("data", JSONUtil.toJsonStr(projectTotalProgress));
maps.add(map);
}
List<MilestoneProgressVo> milestoneProgress = service.getMilestoneProgress(projectId);
if (milestoneProgress != null) {
Map<String, String> map = new HashMap<>();
map.put("type", "progressMilestoneProgress");
map.put("data", JSONUtil.toJsonStr(milestoneProgress));
maps.add(map);
}
List<wzxqysjdhdbVo> materialProgress = service.getMaterialProgress(projectId);
if (materialProgress != null) {
Map<String, String> map = new HashMap<>();
map.put("type", "progressMaterialProgress");
map.put("data", JSONUtil.toJsonStr(materialProgress));
maps.add(map);
}
}
}
}