进度管理,企业级大屏,修改bug

This commit is contained in:
lcj
2025-09-09 15:42:00 +08:00
parent 820188863e
commit abad289c2b
34 changed files with 676 additions and 141 deletions

View File

@ -55,7 +55,8 @@ public class UserActionListener implements SaTokenListener {
String username = (String) loginModel.getExtra(LoginHelper.USER_NAME_KEY);
String tenantId = (String) loginModel.getExtra(LoginHelper.TENANT_KEY);
dto.setUserName(username);
dto.setClientKey((String) loginModel.getExtra(LoginHelper.CLIENT_KEY));
String clientId = (String) loginModel.getExtra(LoginHelper.CLIENT_KEY);
dto.setClientKey(clientId);
dto.setDeviceType(loginModel.getDevice());
dto.setDeptName((String) loginModel.getExtra(LoginHelper.DEPT_NAME_KEY));
TenantHelper.dynamic(tenantId, () -> {
@ -75,7 +76,7 @@ public class UserActionListener implements SaTokenListener {
SpringUtils.context().publishEvent(logininforEvent);
// 更新登录信息
loginService.recordLoginInfo((Long) loginModel.getExtra(LoginHelper.USER_KEY), ip);
log.info("user doLogin, userId:{}, token:{}", loginId, tokenValue);
log.info("user doLogin, userId:{}, token:{}, clientid{}", loginId, tokenValue, clientId);
}
/**

View File

@ -0,0 +1,53 @@
package org.dromara.bigscreen.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import jakarta.annotation.Resource;
import org.dromara.bigscreen.domain.dto.WeatherQueryReq;
import org.dromara.bigscreen.domain.vo.WeatherVo;
import org.dromara.bigscreen.service.EnterpriseBigScreenService;
import org.dromara.common.core.domain.R;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.List;
/**
* 企业级大屏
*
* @author lilemy
* @date 2025-09-09 14:55
*/
@Validated
@RestController
@RequestMapping("/enterprise/big/screen")
public class EnterpriseBigScreenController {
@Resource
private EnterpriseBigScreenService enterpriseBigScreenService;
/**
* 查询天气
*/
@SaCheckPermission("enterprise:bigScreen:weather")
@GetMapping("/weather")
public R<List<WeatherVo>> getProjectWeather(WeatherQueryReq req) {
return R.ok(enterpriseBigScreenService.getWeather3DaysList(req));
}
/**
* 查询安全天数
*/
@SaCheckPermission("enterprise:bigScreen:safetyDay")
@GetMapping("/safetyDay")
public R<Long> getProjectSafetyDay() {
LocalDate date = LocalDate.of(2023, 1, 1);
LocalDate now = LocalDate.now();
long days = Math.abs(ChronoUnit.DAYS.between(date, now));
return R.ok(days);
}
}

View File

@ -0,0 +1,28 @@
package org.dromara.bigscreen.domain.dto;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lilemy
* @date 2025-09-09 15:16
*/
@Data
public class WeatherQueryReq implements Serializable {
@Serial
private static final long serialVersionUID = -2550570761981859666L;
/**
* 经度
*/
private String lng;
/**
* 纬度
*/
private String lat;
}

View File

@ -0,0 +1,67 @@
package org.dromara.bigscreen.domain.vo;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lilemy
* @date 2025-09-09 15:14
*/
@Data
public class WeatherVo implements Serializable {
@Serial
private static final long serialVersionUID = 6518020416043269221L;
/**
* 日期
*/
private String date;
/**
* 星期
*/
private String week;
/**
* 最高温度
*/
private String tempMax;
/**
* 最低温度
*/
private String tempMin;
/**
* 日出时间
*/
private String sunRise;
/**
* 日落时间
*/
private String sunSet;
/**
* 白天天气状态
*/
private String dayStatus;
/**
* 白天天气图标
*/
private String dayIcon;
/**
* 晚上天气状态
*/
private String nightStatus;
/**
* 晚上天气图标
*/
private String nightIcon;
}

View File

@ -0,0 +1,21 @@
package org.dromara.bigscreen.service;
import org.dromara.bigscreen.domain.dto.WeatherQueryReq;
import org.dromara.bigscreen.domain.vo.WeatherVo;
import java.util.List;
/**
* @author lilemy
* @date 2025-09-09 15:31
*/
public interface EnterpriseBigScreenService {
/**
* 获取3天的天气列表
*
* @param req 查询参数
* @return 天气列表
*/
List<WeatherVo> getWeather3DaysList(WeatherQueryReq req);
}

View File

@ -0,0 +1,27 @@
package org.dromara.bigscreen.service.impl;
import org.dromara.bigscreen.domain.dto.WeatherQueryReq;
import org.dromara.bigscreen.domain.vo.WeatherVo;
import org.dromara.bigscreen.service.EnterpriseBigScreenService;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @author lilemy
* @date 2025-09-09 15:32
*/
@Service
public class EnterpriseBigScreenServiceImpl implements EnterpriseBigScreenService {
/**
* 获取3天的天气列表
*
* @param req 查询参数
* @return 天气列表
*/
@Override
public List<WeatherVo> getWeather3DaysList(WeatherQueryReq req) {
return List.of();
}
}

View File

@ -2,6 +2,7 @@ package org.dromara.common.utils.baiduUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.utils.baiduUtil.entity.face.ComparisonRes;
import org.dromara.common.utils.baiduUtil.entity.face.HumanFaceReq;
import org.dromara.common.utils.baiduUtil.entity.face.HumanFaceRes;
@ -23,6 +24,7 @@ import java.util.List;
* @Version 1.0
* 处理百度人脸相关逻辑:人脸检测、人脸对比
*/
@Slf4j
@Service
public class BaiDuFace {
@ -92,7 +94,8 @@ public class BaiDuFace {
// 7. 处理API返回错误
if (faceRep.getErrorCode() != 0) {
throw new RuntimeException("错误码说明:" + faceRep.getErrorMsg());
log.warn("百度人脸API返回错误码{}", faceRep.getErrorCode());
throw new RuntimeException("未检测到有效人脸信息");
}
// 8. 验证人脸信息(无人脸时抛出异常)

View File

@ -17,10 +17,7 @@ import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.dromara.contractor.domain.dto.constructionuser.*;
import org.dromara.contractor.domain.exportvo.BusConstructionUserExportVo;
import org.dromara.contractor.domain.vo.constructionuser.SubConstructionUserAttendanceMonthVo;
import org.dromara.contractor.domain.vo.constructionuser.SubConstructionUserAttendanceTotalVo;
import org.dromara.contractor.domain.vo.constructionuser.SubConstructionUserGisVo;
import org.dromara.contractor.domain.vo.constructionuser.SubConstructionUserVo;
import org.dromara.contractor.domain.vo.constructionuser.*;
import org.dromara.contractor.service.ISubConstructionUserService;
import org.dromara.project.domain.dto.project.BusProjectQueryReq;
import org.dromara.project.domain.dto.projectteam.BusProjectTeamQueryReq;
@ -30,8 +27,10 @@ import org.dromara.project.domain.vo.projectteam.BusProjectTeamVo;
import org.dromara.project.service.IBusProjectService;
import org.dromara.project.service.IBusProjectTeamMemberService;
import org.dromara.project.service.IBusProjectTeamService;
import org.dromara.system.domain.vo.SysOssVo;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
@ -233,7 +232,34 @@ public class SubConstructionUserController extends BaseController {
return R.ok(busProjectTeamMemberService.insertByBo(req));
}
/**
* 根据身份证图片获取身份证信息
*/
@SaCheckPermission("contractor:constructionUser:add")
@Log(title = "施工人员", businessType = BusinessType.OTHER)
@PostMapping("/idCard")
public R<SubConstructionUserOrcIdCardVo> getIdCardMessage(@RequestParam("file") MultipartFile file, String idCardSide) {
return R.ok(constructionUserService.getIdCardMessageByPic(file, idCardSide));
}
/**
* 根据银行卡图片获取银行卡信息
*/
@SaCheckPermission("contractor:constructionUser:add")
@Log(title = "施工人员", businessType = BusinessType.OTHER)
@PostMapping("/bankCard")
public R<SubConstructionUserOrcBankVo> getBankCardMessage(@RequestParam("file") MultipartFile file) {
return R.ok(constructionUserService.getBankCardMessageByPic(file));
}
/**
* 人脸识别
*/
@SaCheckPermission("contractor:constructionUser:add")
@Log(title = "施工人员", businessType = BusinessType.OTHER)
@PostMapping("/face/recognize")
public R<SysOssVo> faceRecognize(@RequestParam("file") MultipartFile file) {
return R.ok(constructionUserService.faceRecognize(file));
}
}

View File

@ -15,6 +15,7 @@ import org.dromara.contractor.domain.vo.constructionuser.SubConstructionUserOrcB
import org.dromara.contractor.domain.vo.constructionuser.SubConstructionUserOrcIdCardVo;
import org.dromara.contractor.domain.vo.constructionuser.SubConstructionUserVo;
import org.dromara.contractor.service.ISubConstructionUserService;
import org.dromara.system.domain.vo.SysOssVo;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
@ -111,6 +112,15 @@ public class SubConstructionUserAppController {
return R.ok(constructionUserService.insertByAuthentication(req));
}
/**
* 人脸识别
*/
@Log(title = "施工人员", businessType = BusinessType.OTHER)
@PostMapping("/face/recognize")
public R<SysOssVo> faceRecognize(@RequestParam("file") MultipartFile file) {
return R.ok(constructionUserService.faceRecognize(file));
}
/**
* 施工人员人脸比对
*/

View File

@ -9,6 +9,7 @@ import org.dromara.contractor.domain.SubConstructionUser;
import org.dromara.contractor.domain.dto.constructionuser.*;
import org.dromara.contractor.domain.exportvo.BusConstructionUserExportVo;
import org.dromara.contractor.domain.vo.constructionuser.*;
import org.dromara.system.domain.vo.SysOssVo;
import org.springframework.web.multipart.MultipartFile;
import java.util.Collection;
@ -198,6 +199,14 @@ public interface ISubConstructionUserService extends IService<SubConstructionUse
*/
Long insertByAuthentication(SubConstructionUserAuthenticationReq req);
/**
* 人脸识别
*
* @param file 图片文件
* @return 人脸识别结果
*/
SysOssVo faceRecognize(MultipartFile file);
/**
* 人脸识别
*
@ -213,5 +222,4 @@ public interface ISubConstructionUserService extends IService<SubConstructionUse
* @return 施工人员
*/
SubConstructionUser getBySysUserId(Long sysUserId);
}

View File

@ -6,7 +6,6 @@ import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
@ -320,8 +319,6 @@ public class SubConstructionUserFileServiceImpl extends ServiceImpl<SubConstruct
throw new ServiceException("施工人员不存在", HttpStatus.NOT_FOUND);
}
// 2. 查询当前用户的所有文件记录(一次性查询,避免多次访问数据库)
LambdaQueryWrapper<SubConstructionUserFile> lqw = Wrappers.lambdaQuery(SubConstructionUserFile.class)
.eq(SubConstructionUserFile::getUserId, userId);
List<SubConstructionUserFile> constructionUserFileList = this.lambdaQuery()
.eq(SubConstructionUserFile::getUserId, userId)
.list();

View File

@ -645,10 +645,13 @@ public class SubConstructionUserServiceImpl extends ServiceImpl<SubConstructionU
// 批量删除施工人员下的文件信息
LambdaQueryWrapper<SubConstructionUserFile> constructionUserFileLqw = Wrappers.lambdaQuery(SubConstructionUserFile.class)
.in(SubConstructionUserFile::getUserId, ids);
List<SubConstructionUserFile> fileList = constructionUserFileService.list(constructionUserFileLqw);
if (CollUtil.isNotEmpty(fileList)) {
boolean removeFile = constructionUserFileService.remove(constructionUserFileLqw);
if (!removeFile) {
throw new ServiceException("删除施工人员信息失败,施工人员文件信息删除失败", HttpStatus.ERROR);
}
}
// 批量删除施工人员信息
return this.removeBatchByIds(ids);
}
@ -676,7 +679,10 @@ public class SubConstructionUserServiceImpl extends ServiceImpl<SubConstructionU
// 关联查询分包公司信息信息
Long contractorId = constructionUser.getContractorId();
if (contractorId != null) {
constructionUserVo.setContractorName(contractorService.getById(contractorId).getName());
SubContractor contractor = contractorService.getById(contractorId);
if (contractor != null) {
constructionUserVo.setContractorName(contractor.getName());
}
}
// 关联查询用户头像url
String facePic = constructionUser.getFacePic();
@ -1195,6 +1201,22 @@ public class SubConstructionUserServiceImpl extends ServiceImpl<SubConstructionU
return user.getId();
}
/**
* 人脸识别
*
* @param file 图片文件
* @return 人脸识别结果
*/
@Override
public SysOssVo faceRecognize(MultipartFile file) {
String reqBase64 = this.getPicBase64(file);
HumanFaceReq faceReq = new HumanFaceReq();
faceReq.setImage(reqBase64);
// 调用人脸识别接口
baiDuFace.humanFace(faceReq);
return ossService.upload(file);
}
/**
* 人脸识别
*
@ -1203,18 +1225,7 @@ public class SubConstructionUserServiceImpl extends ServiceImpl<SubConstructionU
*/
@Override
public Boolean faceComparison(MultipartFile file) {
if (file == null) {
throw new ServiceException("请上传图片", HttpStatus.BAD_REQUEST);
}
String reqBase64;
try {
// 获取文件字节数组
byte[] bytes = file.getBytes();
// Base64 编码
reqBase64 = Base64.getEncoder().encodeToString(bytes);
} catch (IOException e) {
throw new ServiceException("图片转换失败,请重新上传");
}
String reqBase64 = this.getPicBase64(file);
HumanFaceReq request = new HumanFaceReq();
request.setImage(reqBase64);
Long userId = LoginHelper.getUserId();
@ -1264,4 +1275,26 @@ public class SubConstructionUserServiceImpl extends ServiceImpl<SubConstructionU
return constructionUser;
}
/**
* 获取图片的Base64编码
*
* @param file 图片文件
* @return 图片的Base64编码
*/
private String getPicBase64(MultipartFile file) {
if (file == null) {
throw new ServiceException("请上传图片", HttpStatus.BAD_REQUEST);
}
String reqBase64;
try {
// 获取文件字节数组
byte[] bytes = file.getBytes();
// Base64 编码
reqBase64 = Base64.getEncoder().encodeToString(bytes);
} catch (IOException e) {
throw new ServiceException("图片转换失败,请重新上传");
}
return reqBase64;
}
}

View File

@ -13,6 +13,7 @@ import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.utils.JSTUtil;
import org.dromara.facility.constant.FacRedisKeyConstant;
import org.dromara.facility.domain.*;
import org.dromara.facility.domain.dto.geojson.*;
@ -27,7 +28,6 @@ import org.dromara.facility.service.*;
import org.dromara.progress.service.IPgsProgressCategoryService;
import org.dromara.project.domain.BusProject;
import org.dromara.project.service.IBusProjectService;
import org.dromara.common.utils.JSTUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.RedisTemplate;
@ -659,7 +659,7 @@ public class FacMatrixServiceImpl extends ServiceImpl<FacMatrixMapper, FacMatrix
FacPhotovoltaicPanel::getStatus
)
.eq(FacPhotovoltaicPanel::getProjectId, projectId)
.eq(FacPhotovoltaicPanel::getProgressCategoryName, "光伏板")
.eq(FacPhotovoltaicPanel::getProgressCategoryName, "组件安装")
.in(CollUtil.isNotEmpty(matrixIdList), FacPhotovoltaicPanel::getMatrixId, matrixIdList)
.list();
List<FacFacilityPositionGisVo> panelVoList = panelList.stream().map(obj ->

View File

@ -19,10 +19,7 @@ import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.web.core.BaseController;
import org.dromara.progress.domain.PgsProgressCategory;
import org.dromara.progress.domain.dto.progresscategory.PgsProgressCategoryCreatePriceReq;
import org.dromara.progress.domain.dto.progresscategory.PgsProgressCategoryCreateReq;
import org.dromara.progress.domain.dto.progresscategory.PgsProgressCategoryQueryReq;
import org.dromara.progress.domain.dto.progresscategory.PgsProgressCategoryUpdateReq;
import org.dromara.progress.domain.dto.progresscategory.*;
import org.dromara.progress.domain.vo.progresscategory.*;
import org.dromara.progress.service.IPgsProgressCategoryService;
import org.springframework.transaction.annotation.Transactional;
@ -65,10 +62,9 @@ public class PgsProgressCategoryController extends BaseController {
* 根据进度父级查询进度类别列表
*/
@SaCheckPermission("progress:progressCategory:listByParent")
@GetMapping("/listByParent/{parentId}")
public R<List<PgsProgressCategoryVo>> listByParent(@NotNull(message = "项目id不能为空")
@PathVariable Long parentId) {
List<PgsProgressCategoryVo> list = pgsProgressCategoryService.queryListByParent(parentId);
@GetMapping("/listByParent")
public R<List<PgsProgressCategoryVo>> listByParent(PgsProgressCategoryQueryByParentReq req) {
List<PgsProgressCategoryVo> list = pgsProgressCategoryService.queryListByParent(req);
return R.ok(list);
}

View File

@ -14,6 +14,7 @@ import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.dromara.progress.domain.dto.progresscategorytemplate.PgsProgressCategoryTemplateCreateReq;
import org.dromara.progress.domain.dto.progresscategorytemplate.PgsProgressCategoryTemplateQueryByParentReq;
import org.dromara.progress.domain.dto.progresscategorytemplate.PgsProgressCategoryTemplateQueryReq;
import org.dromara.progress.domain.dto.progresscategorytemplate.PgsProgressCategoryTemplateUpdateReq;
import org.dromara.progress.domain.vo.progresscategorytemplate.PgsProgressCategoryTemplateVo;
@ -60,10 +61,9 @@ public class PgsProgressCategoryTemplateController extends BaseController {
* 根据进度父级查询进度类别模版列表
*/
@SaCheckPermission("progress:progressCategoryTemplate:listByParent")
@GetMapping("/listByParent/{parentId}")
public R<List<PgsProgressCategoryTemplateVo>> listByParent(@NotNull(message = "父级类别主键不能为空")
@PathVariable Long parentId) {
List<PgsProgressCategoryTemplateVo> list = pgsProgressCategoryTemplateService.queryListByParent(parentId);
@GetMapping("/listByParent")
public R<List<PgsProgressCategoryTemplateVo>> listByParent(PgsProgressCategoryTemplateQueryByParentReq req) {
List<PgsProgressCategoryTemplateVo> list = pgsProgressCategoryTemplateService.queryListByParent(req);
return R.ok(list);
}

View File

@ -6,7 +6,6 @@ import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
@ -76,7 +75,7 @@ public class PgsProgressPlanController extends BaseController {
@Log(title = "进度计划", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Long> add(@Validated(AddGroup.class) @RequestBody PgsProgressPlanCreateReq req) {
public R<Long> add(@Validated @RequestBody PgsProgressPlanCreateReq req) {
return R.ok(pgsProgressPlanService.insertByBo(req));
}

View File

@ -4,7 +4,10 @@ import jakarta.annotation.Resource;
import jakarta.validation.constraints.NotNull;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R;
import org.dromara.progress.domain.dto.progresscategory.PgsProgressCategoryQueryByParentReq;
import org.dromara.progress.domain.vo.progresscategory.PgsProgressCategoryLastTimeVo;
import org.dromara.progress.domain.vo.progresscategory.PgsProgressCategoryTopVo;
import org.dromara.progress.domain.vo.progresscategory.PgsProgressCategoryVo;
import org.dromara.progress.service.IPgsProgressCategoryService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
@ -39,4 +42,24 @@ public class PgsProgressCategoryAppController {
return R.ok(list);
}
/**
* 根据进度父级查询进度类别列表
*/
@GetMapping("/listByParent")
public R<List<PgsProgressCategoryVo>> listByParent(PgsProgressCategoryQueryByParentReq req) {
List<PgsProgressCategoryVo> list = progressCategoryService.queryListByParent(req);
return R.ok(list);
}
/**
* 获取进度类别最后一次进度信息
*
* @param id 主键
*/
@GetMapping("/lastTime/{id}")
public R<PgsProgressCategoryLastTimeVo> getLastTimeInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(progressCategoryService.queryLastTimeById(id));
}
}

View File

@ -1,9 +1,20 @@
package org.dromara.progress.controller.app;
import cn.dev33.satoken.annotation.SaCheckPermission;
import jakarta.annotation.Resource;
import org.dromara.common.core.domain.R;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.dromara.progress.domain.dto.progressplan.PgsProgressPlanCreateReq;
import org.dromara.progress.domain.dto.progressplan.PgsProgressPlanQueryReq;
import org.dromara.progress.domain.vo.progressplan.PgsProgressPlanVo;
import org.dromara.progress.service.IPgsProgressPlanService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
/**
* 进度计划 app 接口
@ -15,4 +26,26 @@ import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/app/progress/progressPlan")
public class PgsProgressPlanAppController extends BaseController {
@Resource
private IPgsProgressPlanService progressPlanService;
/**
* 查询进度计划列表
*/
@GetMapping("/list")
public TableDataInfo<PgsProgressPlanVo> list(PgsProgressPlanQueryReq req, PageQuery pageQuery) {
return progressPlanService.queryPageList(req, pageQuery);
}
/**
* 新增进度计划
*/
@Log(title = "进度计划", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Long> add(@Validated @RequestBody PgsProgressPlanCreateReq req) {
return R.ok(progressPlanService.insertByBo(req));
}
}

View File

@ -1,9 +1,19 @@
package org.dromara.progress.controller.app;
import jakarta.annotation.Resource;
import jakarta.validation.constraints.NotNull;
import org.dromara.common.core.domain.R;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.dromara.progress.domain.dto.progressplandetail.PgsProgressPlanDetailFinishedCreateReq;
import org.dromara.progress.domain.dto.progressplandetail.PgsProgressPlanDetailRemoveReq;
import org.dromara.progress.domain.vo.progressplandetail.PgsProgressPlanDetailFinishedVo;
import org.dromara.progress.domain.vo.progressplandetail.PgsProgressPlanDetailUnFinishVo;
import org.dromara.progress.service.IPgsProgressPlanDetailService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
/**
* 进度计划详情 app 接口
@ -15,4 +25,50 @@ import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/app/progress/progressPlanDetail")
public class PgsProgressPlanDetailAppController extends BaseController {
@Resource
private IPgsProgressPlanDetailService progressPlanDetailService;
/**
* 新增进度计划详情(普通设施)
*/
@RepeatSubmit()
@PostMapping("/insert/detail")
public R<Void> insertFinishedDetail(@Validated @RequestBody PgsProgressPlanDetailFinishedCreateReq req) {
return toAjax(progressPlanDetailService.insertFinishedDetail(req));
}
/**
* 获取进度计划详情已完成设施详细信息
*
* @param id 主键
*/
@GetMapping("/detail/finished/{id}")
public TableDataInfo<PgsProgressPlanDetailFinishedVo> getFinishedDetail(@NotNull(message = "主键不能为空")
@PathVariable Long id,
PageQuery pageQuery) {
return progressPlanDetailService.queryFinishedById(id, pageQuery);
}
/**
* 获取进度计划详情未完成设施详细信息
*
* @param id 主键
*/
@GetMapping("/detail/unFinish/{id}")
public TableDataInfo<PgsProgressPlanDetailUnFinishVo> getUnFinishDetail(@NotNull(message = "主键不能为空")
@PathVariable Long id,
PageQuery pageQuery) {
return progressPlanDetailService.queryUnFinishById(id, pageQuery);
}
/**
* 删除进度计划详情
*/
@RepeatSubmit()
@DeleteMapping("/remove/detail")
public R<Void> removeDetail(@Validated PgsProgressPlanDetailRemoveReq req) {
return toAjax(progressPlanDetailService.removeDetail(req));
}
}

View File

@ -8,7 +8,7 @@ import org.dromara.common.mybatis.core.domain.BaseEntity;
import java.io.Serial;
import java.math.BigDecimal;
import java.util.Date;
import java.time.LocalDate;
/**
* 进度计划对象 pgs_progress_plan
@ -58,12 +58,12 @@ public class PgsProgressPlan extends BaseEntity {
/**
* 计划开始时间
*/
private Date startDate;
private LocalDate startDate;
/**
* 计划结束时间
*/
private Date endDate;
private LocalDate endDate;
/**
* 计划数量/百分比

View File

@ -0,0 +1,27 @@
package org.dromara.progress.domain.dto.progresscategory;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lilemy
* @date 2025-09-08 16:14
*/
@Data
public class PgsProgressCategoryQueryByParentReq implements Serializable {
@Serial
private static final long serialVersionUID = 9086069361042762679L;
/**
* 父级id
*/
private Long parentId;
/**
* 类别名称
*/
private String name;
}

View File

@ -0,0 +1,27 @@
package org.dromara.progress.domain.dto.progresscategorytemplate;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author lilemy
* @date 2025-09-08 16:21
*/
@Data
public class PgsProgressCategoryTemplateQueryByParentReq implements Serializable {
@Serial
private static final long serialVersionUID = -8113409205840032942L;
/**
* 父类别id
*/
private Long parentId;
/**
* 类别名称
*/
private String name;
}

View File

@ -1,13 +1,13 @@
package org.dromara.progress.domain.dto.progressplan;
import com.fasterxml.jackson.annotation.JsonFormat;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.dromara.progress.domain.dto.progressplandetail.PgsProgressPlanDetailCreateDto;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
import java.time.LocalDate;
import java.util.List;
/**
@ -23,6 +23,7 @@ public class PgsProgressPlanCreateReq implements Serializable {
/**
* 项目id
*/
@NotNull(message = "项目id不能为空")
private Long projectId;
/**
@ -33,28 +34,31 @@ public class PgsProgressPlanCreateReq implements Serializable {
/**
* 进度类型id
*/
@NotNull(message = "进度类型id不能为空")
private Long progressCategoryId;
/**
* 计划开始时间
*/
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
private Date startDate;
@NotNull(message = "计划开始时间不能为空")
private LocalDate startDate;
/**
* 计划结束时间
*/
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
private Date endDate;
@NotNull(message = "计划结束时间不能为空")
private LocalDate endDate;
/**
* 计划数量/百分比
*/
@NotNull(message = "计划数量/百分比不能为空")
private BigDecimal planNumber;
/**
* 计划详情列表
*/
@NotNull(message = "计划详情列表不能为空")
List<PgsProgressPlanDetailCreateDto> detailList;
}

View File

@ -1,11 +1,10 @@
package org.dromara.progress.domain.dto.progressplan;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
import java.time.LocalDate;
/**
* @author lilemy
@ -35,13 +34,11 @@ public class PgsProgressPlanQueryReq implements Serializable {
/**
* 计划开始时间
*/
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
private Date startDate;
private LocalDate startDate;
/**
* 计划结束时间
*/
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
private Date endDate;
private LocalDate endDate;
}

View File

@ -1,12 +1,11 @@
package org.dromara.progress.domain.vo.progresscategory;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
import java.time.LocalDate;
/**
* @author lilemy
@ -21,8 +20,7 @@ public class PgsProgressCategoryLastTimeVo implements Serializable {
/**
* 计划结束时间
*/
@JsonFormat(pattern = "yyyy-MM-dd")
private Date endDate;
private LocalDate endDate;
/**
* 剩余数量

View File

@ -15,5 +15,19 @@ public class PgsProgressCategorySecondVo implements Serializable {
@Serial
private static final long serialVersionUID = 5297363236416903392L;
/**
* 关联结构(1子项目 2方阵)
*/
private String relevancyStructure;
/**
* 主键id
*/
private Long id;
/**
* 类别名称
*/
private String name;
}

View File

@ -2,7 +2,6 @@ package org.dromara.progress.domain.vo.progressplan;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.progress.domain.PgsProgressPlan;
@ -11,7 +10,7 @@ import org.dromara.progress.domain.vo.progressplandetail.PgsProgressPlanDetailNu
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
import java.time.LocalDate;
import java.util.List;
@ -50,16 +49,14 @@ public class PgsProgressPlanVo implements Serializable {
/**
* 计划开始时间
*/
@JsonFormat(pattern = "yyyy-MM-dd")
@ExcelProperty(value = "计划开始时间")
private Date startDate;
private LocalDate startDate;
/**
* 计划结束时间
*/
@JsonFormat(pattern = "yyyy-MM-dd")
@ExcelProperty(value = "计划结束时间")
private Date endDate;
private LocalDate endDate;
/**
* 计划数量/百分比

View File

@ -4,10 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import org.dromara.facility.domain.FacMatrix;
import org.dromara.progress.domain.PgsProgressCategory;
import org.dromara.progress.domain.dto.progresscategory.PgsProgressCategoryCreatePriceReq;
import org.dromara.progress.domain.dto.progresscategory.PgsProgressCategoryCreateReq;
import org.dromara.progress.domain.dto.progresscategory.PgsProgressCategoryQueryReq;
import org.dromara.progress.domain.dto.progresscategory.PgsProgressCategoryUpdateReq;
import org.dromara.progress.domain.dto.progresscategory.*;
import org.dromara.progress.domain.vo.progresscategory.*;
import java.math.BigDecimal;
@ -42,10 +39,10 @@ public interface IPgsProgressCategoryService extends IService<PgsProgressCategor
/**
* 根据进度父级id查询符合条件的进度类别列表
*
* @param parentId 父级id
* @param req 查询条件
* @return 进度类别列表
*/
List<PgsProgressCategoryVo> queryListByParent(Long parentId);
List<PgsProgressCategoryVo> queryListByParent(PgsProgressCategoryQueryByParentReq req);
/**
* 查询设施剩余数量
@ -176,6 +173,14 @@ public interface IPgsProgressCategoryService extends IService<PgsProgressCategor
*/
List<PgsProgressCategory> getLeafNodesByTopIds(List<Long> topIds);
/**
* 获取子节点支持多个顶级id
*
* @param topIds 顶级节点id集合
* @return 子节点
*/
List<PgsProgressCategory> getChildrenNodeByTopIds(List<Long> topIds);
/**
* 获取项目进度百分比
*

View File

@ -7,6 +7,7 @@ import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.progress.domain.PgsProgressCategoryTemplate;
import org.dromara.progress.domain.dto.progresscategorytemplate.PgsProgressCategoryTemplateCreateReq;
import org.dromara.progress.domain.dto.progresscategorytemplate.PgsProgressCategoryTemplateQueryByParentReq;
import org.dromara.progress.domain.dto.progresscategorytemplate.PgsProgressCategoryTemplateQueryReq;
import org.dromara.progress.domain.dto.progresscategorytemplate.PgsProgressCategoryTemplateUpdateReq;
import org.dromara.progress.domain.vo.progresscategorytemplate.PgsProgressCategoryTemplateVo;
@ -50,10 +51,10 @@ public interface IPgsProgressCategoryTemplateService extends IService<PgsProgres
/**
* 根据父级id获取进度类别模版列表
*
* @param parentId 父级id
* @param req 查询条件
* @return 类别模版列表
*/
List<PgsProgressCategoryTemplateVo> queryListByParent(Long parentId);
List<PgsProgressCategoryTemplateVo> queryListByParent(PgsProgressCategoryTemplateQueryByParentReq req);
/**
* 新增进度类别模版

View File

@ -12,7 +12,6 @@ import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.constant.HttpStatus;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.DateUtils;
import org.dromara.common.core.utils.ObjectUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.utils.BigDecimalUtil;
@ -24,10 +23,7 @@ import org.dromara.progress.domain.PgsProgressCategory;
import org.dromara.progress.domain.PgsProgressCategoryTemplate;
import org.dromara.progress.domain.PgsProgressPlan;
import org.dromara.progress.domain.PgsProgressPlanDetail;
import org.dromara.progress.domain.dto.progresscategory.PgsProgressCategoryCreatePriceReq;
import org.dromara.progress.domain.dto.progresscategory.PgsProgressCategoryCreateReq;
import org.dromara.progress.domain.dto.progresscategory.PgsProgressCategoryQueryReq;
import org.dromara.progress.domain.dto.progresscategory.PgsProgressCategoryUpdateReq;
import org.dromara.progress.domain.dto.progresscategory.*;
import org.dromara.progress.domain.enums.PgsCoordinateTypeEnum;
import org.dromara.progress.domain.enums.PgsFinishStatusEnum;
import org.dromara.progress.domain.enums.PgsProgressUnitTypeEnum;
@ -51,6 +47,7 @@ import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
/**
@ -139,13 +136,16 @@ public class PgsProgressCategoryServiceImpl extends ServiceImpl<PgsProgressCateg
/**
* 根据进度父级id查询符合条件的进度类别列表
*
* @param parentId 父级id
* @param req 查询条件
* @return 进度类别列表
*/
@Override
public List<PgsProgressCategoryVo> queryListByParent(Long parentId) {
public List<PgsProgressCategoryVo> queryListByParent(PgsProgressCategoryQueryByParentReq req) {
Long parentId = req.getParentId();
String name = req.getName();
QueryWrapper<PgsProgressCategory> queryWrapper = new QueryWrapper<>();
queryWrapper.apply("FIND_IN_SET({0}, ancestors)", parentId);
queryWrapper.apply(parentId != null, "FIND_IN_SET({0}, ancestors)", parentId);
queryWrapper.like(StringUtils.isNotBlank(name), "name", name);
return this.getVoList(this.list(queryWrapper));
}
@ -175,13 +175,11 @@ public class PgsProgressCategoryServiceImpl extends ServiceImpl<PgsProgressCateg
.last("limit 1")
.one();
LocalDate now = LocalDate.now();
Date date = DateUtils.toDate(now);
if (progressPlan != null && progressPlan.getEndDate().after(date)) {
if (progressPlan != null && progressPlan.getEndDate().isAfter(now)) {
lastTimeVo.setEndDate(progressPlan.getEndDate());
} else {
LocalDate yesterday = now.minusDays(1);
Date y = DateUtils.toDate(yesterday);
lastTimeVo.setEndDate(y);
lastTimeVo.setEndDate(yesterday);
}
return lastTimeVo;
}
@ -190,77 +188,153 @@ public class PgsProgressCategoryServiceImpl extends ServiceImpl<PgsProgressCateg
* 根据子项目id获取顶级进度类别模版
*
* @param subProjectId 子项目id
* @return 顶级进度类别模版
* @return 顶级进度类别模版列表
*/
@Override
public List<PgsProgressCategoryTopVo> getTopListByProjectId(Long subProjectId) {
// 查询该子项目下的顶级进度类别父ID为0
List<PgsProgressCategory> list = this.lambdaQuery()
.eq(PgsProgressCategory::getProjectId, subProjectId)
.eq(PgsProgressCategory::getParentId, PgsProgressCategoryConstant.TOP_PARENT_ID)
.list();
// 如果没有查询到顶级进度类别,直接返回空集合
if (CollUtil.isEmpty(list)) {
return List.of();
}
List<PgsProgressCategoryTopVo> topList = new ArrayList<>();
// 获取关联子项的数据
// 获取这些顶级类别的所有子节点
List<Long> ids = list.stream().map(PgsProgressCategory::getId).distinct().toList();
List<PgsProgressCategory> childrenNodes = this.getChildrenNodeByTopIds(ids);
// ============================= 处理关联子项目的数据 =============================
// 筛选出关联子项目的顶级类别
List<PgsProgressCategory> subList = list.stream()
.filter(category ->
category.getRelevancyStructure().equals(PgsRelevancyStructureEnum.SUB_PROJECT.getValue()))
.toList();
if (CollUtil.isNotEmpty(subList)) {
List<Long> topIds = subList.stream().map(PgsProgressCategory::getId).distinct().toList();
List<PgsProgressCategory> leafNodesByTopIds = this.getLeafNodesByTopIds(topIds);
// 将子项目类别转换为VO对象
List<PgsProgressCategoryTopVo> subVoList = subList.stream().map(category -> {
PgsProgressCategoryTopVo vo = new PgsProgressCategoryTopVo();
BeanUtils.copyProperties(category, vo);
List<PgsProgressCategory> children = leafNodesByTopIds.stream()
PgsProgressCategoryTopVo topVo = new PgsProgressCategoryTopVo();
// 属性拷贝
BeanUtils.copyProperties(category, topVo);
// 统计深度
AtomicInteger count = new AtomicInteger(1);
// 找出当前类别对应的所有叶子节点(根据 ancestors 字段包含关系)
List<PgsProgressCategory> children = childrenNodes.stream()
.filter(node -> {
Set<Long> ancestorSet = Arrays.stream(node.getAncestors().split(",")).map(Long::parseLong).collect(Collectors.toSet());
return ancestorSet.contains(category.getId());
Set<Long> ancestorSet = Arrays.stream(node.getAncestors().split(","))
.map(Long::parseLong)
.collect(Collectors.toSet());
boolean result = ancestorSet.contains(category.getId());
if (result) {
count.set(Math.max(ancestorSet.size(), count.get()));
}
return result;
}).toList();
// 如果有子级,统计总进度和状态;否则初始化为未完成
if (CollUtil.isNotEmpty(children)) {
topVo.setProgressTotal(this.getCompletedPercentage(children));
topVo.setStatus(this.getParentStatus(children));
if (count.get() == 2) {
topVo.setType("1");
} else if (count.get() == 3) {
topVo.setType("2");
List<PgsProgressCategorySecondVo> second = children.stream()
.filter(node -> {
Set<Long> ancestorSet = Arrays.stream(node.getAncestors().split(","))
.map(Long::parseLong)
.collect(Collectors.toSet());
return ancestorSet.size() == 2;
}).map(node -> {
PgsProgressCategorySecondVo vo = new PgsProgressCategorySecondVo();
BeanUtils.copyProperties(node, vo);
return vo;
})
.toList();
if (CollUtil.isNotEmpty(children)) {
vo.setProgressTotal(this.getCompletedPercentage(children));
vo.setStatus(this.getParentStatus(children));
} else {
vo.setProgressTotal(BigDecimal.ZERO);
topVo.setCategorySecondList(second);
}
return vo;
} else {
topVo.setProgressTotal(BigDecimal.ZERO);
topVo.setStatus(PgsFinishStatusEnum.UNFINISH.getValue());
topVo.setType("1");
}
return topVo;
}).toList();
// 将处理好的子项目VO加入结果集
topList.addAll(subVoList);
}
// 获取关联方阵数据
// ============================= 处理关联方阵数据 =============================
// 筛选出关联方阵的顶级类别
List<PgsProgressCategory> matrixList = list.stream()
.filter(category ->
category.getRelevancyStructure().equals(PgsRelevancyStructureEnum.MATRIX.getValue()))
.toList();
if (CollUtil.isNotEmpty(matrixList)) {
// 按名称分组(同名的放在一起)
Map<String, List<PgsProgressCategory>> matrixMap = matrixList.stream()
.collect(Collectors.groupingBy(PgsProgressCategory::getName));
for (Map.Entry<String, List<PgsProgressCategory>> entry : matrixMap.entrySet()) {
PgsProgressCategoryTopVo topVo = new PgsProgressCategoryTopVo();
topVo.setName(entry.getKey());
topVo.setRelevancyStructure(PgsRelevancyStructureEnum.MATRIX.getValue());
// 取分组中的第一条记录的排序字段作为当前VO的排序值
List<PgsProgressCategory> value = entry.getValue();
topVo.setSort(value.getFirst().getSort());
// 转换为方阵结构的VO列表
List<PgsProgressCategoryMatrixStructureTopVo> matrixVoList = value.stream().map(category -> {
PgsProgressCategoryMatrixStructureTopVo vo = new PgsProgressCategoryMatrixStructureTopVo();
BeanUtils.copyProperties(category, vo);
return vo;
}).toList();
topVo.setMatrixStructureList(matrixVoList);
// 获取所有子级,并进行统计
// 统计深度
AtomicInteger count = new AtomicInteger(1);
// 获取这些类别下的所有叶子节点
List<Long> topIds = value.stream().map(PgsProgressCategory::getId).distinct().toList();
List<PgsProgressCategory> leafNodesByTopIds = this.getLeafNodesByTopIds(topIds);
List<PgsProgressCategory> leafNodesByTopIds = childrenNodes.stream()
.filter(node -> {
Set<Long> ancestorSet = Arrays.stream(node.getAncestors().split(","))
.map(Long::parseLong)
.collect(Collectors.toSet());
boolean result = topIds.stream().anyMatch(ancestorSet::contains);
if (result) {
count.set(Math.max(ancestorSet.size(), count.get()));
}
return result;
}).toList();
// 如果有叶子节点,统计进度和状态;否则初始化为未完成
if (CollUtil.isNotEmpty(leafNodesByTopIds)) {
topVo.setProgressTotal(this.getCompletedPercentage(leafNodesByTopIds));
topVo.setStatus(this.getParentStatus(leafNodesByTopIds));
if (count.get() == 2) {
topVo.setType("3");
} else if (count.get() == 3) {
topVo.setType("4");
List<PgsProgressCategorySecondVo> second = leafNodesByTopIds.stream()
.filter(node -> {
Set<Long> ancestorSet = Arrays.stream(node.getAncestors().split(","))
.map(Long::parseLong)
.collect(Collectors.toSet());
return ancestorSet.size() == 2;
}).map(node -> {
PgsProgressCategorySecondVo vo = new PgsProgressCategorySecondVo();
BeanUtils.copyProperties(node, vo);
return vo;
})
.toList();
topVo.setCategorySecondList(second);
}
} else {
topVo.setProgressTotal(BigDecimal.ZERO);
topVo.setStatus(PgsFinishStatusEnum.UNFINISH.getValue());
topVo.setType("3");
}
// 加入结果集
topList.add(topVo);
}
}
// ============================= 排序 & 返回结果 =============================
// 按 sort 字段升序排序
topList.sort(Comparator.comparing(PgsProgressCategoryTopVo::getSort));
return topList;
}
@ -1214,12 +1288,32 @@ public class PgsProgressCategoryServiceImpl extends ServiceImpl<PgsProgressCateg
*/
@Override
public List<PgsProgressCategory> getLeafNodesByTopIds(List<Long> topIds) {
if (topIds == null || topIds.isEmpty()) {
List<PgsProgressCategory> allChildren = this.getChildrenNodeByTopIds(topIds);
if (allChildren.isEmpty()) {
return Collections.emptyList();
}
// 过滤掉那些还有子节点的,只保留最底层
Set<Long> parentIds = allChildren.stream()
.map(PgsProgressCategory::getParentId)
.collect(Collectors.toSet());
return allChildren.stream()
.filter(item -> !parentIds.contains(item.getId())) // 没有被当作别人父id的就是叶子节点
.toList();
}
// 1. 查出所有属于这些顶级节点的子孙节点
List<PgsProgressCategory> allChildren = this.list(
/**
* 获取子节点支持多个顶级id
*
* @param topIds 顶级节点id集合
* @return 子节点
*/
@Override
public List<PgsProgressCategory> getChildrenNodeByTopIds(List<Long> topIds) {
if (CollUtil.isEmpty(topIds)) {
return Collections.emptyList();
}
// 查出所有属于这些顶级节点的子孙节点
return this.list(
Wrappers.<PgsProgressCategory>lambdaQuery()
.and(wrapper -> {
for (Long topId : topIds) {
@ -1228,19 +1322,6 @@ public class PgsProgressCategoryServiceImpl extends ServiceImpl<PgsProgressCateg
}
})
);
if (allChildren.isEmpty()) {
return Collections.emptyList();
}
// 2. 过滤掉那些还有子节点的,只保留最底层
Set<Long> parentIds = allChildren.stream()
.map(PgsProgressCategory::getParentId)
.collect(Collectors.toSet());
return allChildren.stream()
.filter(item -> !parentIds.contains(item.getId())) // 没有被当作别人父id的就是叶子节点
.toList();
}
/**

View File

@ -18,6 +18,7 @@ import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.progress.constant.PgsProgressCategoryConstant;
import org.dromara.progress.domain.PgsProgressCategoryTemplate;
import org.dromara.progress.domain.dto.progresscategorytemplate.PgsProgressCategoryTemplateCreateReq;
import org.dromara.progress.domain.dto.progresscategorytemplate.PgsProgressCategoryTemplateQueryByParentReq;
import org.dromara.progress.domain.dto.progresscategorytemplate.PgsProgressCategoryTemplateQueryReq;
import org.dromara.progress.domain.dto.progresscategorytemplate.PgsProgressCategoryTemplateUpdateReq;
import org.dromara.progress.domain.vo.progresscategorytemplate.PgsProgressCategoryTemplateVo;
@ -89,13 +90,16 @@ public class PgsProgressCategoryTemplateServiceImpl extends ServiceImpl<PgsProgr
/**
* 根据父级id获取进度类别模版列表
*
* @param parentId 父级id
* @param req 查询条件
* @return 类别模版列表
*/
@Override
public List<PgsProgressCategoryTemplateVo> queryListByParent(Long parentId) {
public List<PgsProgressCategoryTemplateVo> queryListByParent(PgsProgressCategoryTemplateQueryByParentReq req) {
Long parentId = req.getParentId();
String name = req.getName();
QueryWrapper<PgsProgressCategoryTemplate> queryWrapper = new QueryWrapper<>();
queryWrapper.apply("FIND_IN_SET({0}, ancestors)", parentId);
queryWrapper.apply(parentId != null, "FIND_IN_SET({0}, ancestors)", parentId);
queryWrapper.like(StringUtils.isNotBlank(name), "name", name);
return this.list(queryWrapper).stream().map(this::getVo).toList();
}

View File

@ -38,7 +38,6 @@ import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@ -119,10 +118,10 @@ public class PgsProgressPlanServiceImpl extends ServiceImpl<PgsProgressPlanMappe
PgsProgressPlan progressPlan = new PgsProgressPlan();
BeanUtils.copyProperties(req, progressPlan);
// 数据校验
Date startDate = req.getStartDate();
Date endDate = req.getEndDate();
LocalDate startDate = req.getStartDate();
LocalDate endDate = req.getEndDate();
// 结束日期不能早于开始日期
if (endDate.before(startDate)) {
if (endDate.isBefore(startDate)) {
throw new ServiceException("结束日期不能早于开始日期");
}
Long projectId = progressPlan.getProjectId();
@ -142,7 +141,7 @@ public class PgsProgressPlanServiceImpl extends ServiceImpl<PgsProgressPlanMappe
.orderByDesc(PgsProgressPlan::getEndDate)
.last("limit 1")
.one();
if (lastProgressPlan != null && startDate.before(lastProgressPlan.getEndDate())) {
if (lastProgressPlan != null && startDate.isBefore(lastProgressPlan.getEndDate())) {
throw new ServiceException("开始日期不能早于上一条进度计划结束日期", HttpStatus.BAD_REQUEST);
}
PgsProgressCategory progressCategory = progressCategoryService.getById(progressCategoryId);
@ -265,8 +264,8 @@ public class PgsProgressPlanServiceImpl extends ServiceImpl<PgsProgressPlanMappe
Long projectId = req.getProjectId();
Long matrixId = req.getMatrixId();
Long progressCategoryId = req.getProgressCategoryId();
Date startDate = req.getStartDate();
Date endDate = req.getEndDate();
LocalDate startDate = req.getStartDate();
LocalDate endDate = req.getEndDate();
lqw.eq(ObjectUtils.isNotEmpty(projectId), PgsProgressPlan::getProjectId, projectId);
lqw.eq(ObjectUtils.isNotEmpty(matrixId), PgsProgressPlan::getMatrixId, matrixId);
lqw.eq(ObjectUtils.isNotEmpty(progressCategoryId), PgsProgressPlan::getProgressCategoryId, progressCategoryId);
@ -374,13 +373,13 @@ public class PgsProgressPlanServiceImpl extends ServiceImpl<PgsProgressPlanMappe
.eq(PgsProgressPlan::getProgressCategoryId, progressCategory.getId())
.list();
// 获取当前时间
Date current = new Date();
LocalDate current = LocalDate.now();
// 记录当前完成的和计划的总和
BigDecimal planFinishSum = BigDecimal.ZERO;
for (PgsProgressPlan plan : planList) {
Date endDate = plan.getEndDate();
LocalDate endDate = plan.getEndDate();
BigDecimal finishedNumber = plan.getFinishedNumber();
if (endDate.before(current)) {
if (endDate.isBefore(current)) {
// 计划结束时间在当前时间之前的,统计 -> 完成数量
planFinishSum = planFinishSum.add(finishedNumber);
} else {

View File

@ -61,7 +61,7 @@ public interface ISysOssService {
* @param filePath 文件路径
* @return 上传成功后的 SysOssVo 对象,包含文件信息
*/
SysOssVo upload(MultipartFile file,String filePath);
SysOssVo upload(MultipartFile file, String filePath);
/**
* 上传 MultipartFile 到对象存储服务,不保存文件信息到数据库

View File

@ -23,7 +23,7 @@ import org.springframework.stereotype.Component;
@Slf4j
@Configuration
public class ChatServer {
private final int port = 9099; // 聊天服务器端口
private final int port = 19099; // 聊天服务器端口
private EventLoopGroup bossGroup;
private EventLoopGroup workerGroup;