@@ -114,7 +114,6 @@ public class DashboardExpertManage { | |||||
// 评审次数 | // 评审次数 | ||||
List<Meeting> normalMeetingList = iMeetingService.list(Wrappers.lambdaQuery(Meeting.class) | List<Meeting> normalMeetingList = iMeetingService.list(Wrappers.lambdaQuery(Meeting.class) | ||||
.eq(StringUtils.isNotBlank(queryRegionCode), Meeting::getRegionCode, queryRegionCode) | |||||
.ne(Meeting::getStatus, MeetingStatusEnum.CANCELED.getCode())); | .ne(Meeting::getStatus, MeetingStatusEnum.CANCELED.getCode())); | ||||
Integer meetingCnt = normalMeetingList.size(); | Integer meetingCnt = normalMeetingList.size(); | ||||
@@ -1,206 +0,0 @@ | |||||
package com.hz.pm.api.dashboard.manage; | |||||
import cn.hutool.core.collection.CollUtil; | |||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers; | |||||
import com.google.common.collect.Lists; | |||||
import com.hz.pm.api.common.constant.RegionConst; | |||||
import com.hz.pm.api.common.helper.RegionCacheHelper; | |||||
import com.hz.pm.api.common.model.entity.DataDTO; | |||||
import com.hz.pm.api.dashboard.model.vo.MeetingStatisticsVO; | |||||
import com.hz.pm.api.ding.constants.DingOrganizationContant; | |||||
import com.hz.pm.api.expert.constant.ReviewResultEnum; | |||||
import com.hz.pm.api.expert.model.entity.ExpertReview; | |||||
import com.hz.pm.api.expert.model.enumeration.ReviewTemplateTypeEnum; | |||||
import com.hz.pm.api.expert.service.IExpertReviewService; | |||||
import com.hz.pm.api.meeting.entity.domain.Meeting; | |||||
import com.hz.pm.api.meeting.service.IMeetingService; | |||||
import com.hz.pm.api.organization.model.entity.DingOrganization; | |||||
import com.hz.pm.api.organization.service.IDingOrganizationService; | |||||
import com.hz.pm.api.projectlib.model.entity.Project; | |||||
import com.hz.pm.api.projectlib.service.IProjectService; | |||||
import com.hz.pm.api.sys.model.dto.RegionDTO; | |||||
import lombok.RequiredArgsConstructor; | |||||
import lombok.extern.slf4j.Slf4j; | |||||
import org.apache.commons.lang3.StringUtils; | |||||
import org.springframework.stereotype.Component; | |||||
import java.math.BigDecimal; | |||||
import java.math.RoundingMode; | |||||
import java.util.Comparator; | |||||
import java.util.List; | |||||
import java.util.Objects; | |||||
import java.util.stream.Collectors; | |||||
/** | |||||
* @Classname MeetingStatisticsManage | |||||
* @Description | |||||
* @Date 2023/12/05 17:44 | |||||
* @Author PoffyZhang | |||||
*/ | |||||
@Component | |||||
@RequiredArgsConstructor | |||||
@Slf4j | |||||
public class MeetingStatisticsManage { | |||||
private final IMeetingService meetingService; | |||||
private final IExpertReviewService expertReviewService; | |||||
private final RegionCacheHelper regionCacheHelper; | |||||
private final IDingOrganizationService dingOrganizationService; | |||||
private final IProjectService projectService; | |||||
public MeetingStatisticsVO statistics(Integer year) { | |||||
MeetingStatisticsVO res = new MeetingStatisticsVO(); | |||||
List<Meeting> meetings = meetingService.list(Wrappers.lambdaQuery(Meeting.class)); | |||||
//查出 年份的 会议数据 | |||||
meetings = meetings.stream().filter(m -> { | |||||
if(Objects.nonNull(m.getStartTime()) && | |||||
(Objects.isNull(year) || year.equals(m.getStartTime().getYear()))){ | |||||
return Boolean.TRUE; | |||||
} | |||||
return Boolean.FALSE; | |||||
}).collect(Collectors.toList()); | |||||
List<Long> meetingIds = meetings.stream().map(Meeting::getId) | |||||
.collect(Collectors.toList()); | |||||
//会议总数 | |||||
res.setMeetingTotal(meetings.size()); | |||||
//评审数 | |||||
List<ExpertReview> expertReviews = Lists.newArrayList(); | |||||
Integer reviewsTotal = 0; | |||||
if(CollUtil.isNotEmpty(meetingIds)){ | |||||
expertReviews = expertReviewService.list(Wrappers.lambdaQuery(ExpertReview.class) | |||||
.eq(ExpertReview::getIsFinal, Boolean.TRUE) | |||||
.in(ExpertReview::getMeetingId,meetingIds)); | |||||
reviewsTotal = expertReviews.size(); | |||||
} | |||||
//通过的评审 | |||||
List<ExpertReview> passExpertReviews = expertReviews.stream() | |||||
.filter(r -> Objects.nonNull(r.getReviewResult()) && | |||||
r.getReviewResult().equals(ReviewResultEnum.PASSED.getCode())) | |||||
.collect(Collectors.toList()); | |||||
//不通过的评审 | |||||
List<ExpertReview> notpassExpertReviews = expertReviews.stream() | |||||
.filter(r -> Objects.nonNull(r.getReviewResult()) && | |||||
r.getReviewResult().equals(ReviewResultEnum.REFUSED.getCode())) | |||||
.collect(Collectors.toList()); | |||||
res.setPassReview(passExpertReviews.size()); | |||||
res.setNotPassRate(reviewsTotal.compareTo(0) == 0 ? BigDecimal.ZERO : | |||||
BigDecimal.valueOf(notpassExpertReviews.size()).multiply(BigDecimal.valueOf(100) | |||||
.divide(BigDecimal.valueOf(reviewsTotal), RoundingMode.HALF_UP))); | |||||
//各区域 | |||||
List<RegionDTO> regions = regionCacheHelper.listChildren(RegionConst.RC_LS, RegionConst.RL_CITY) | |||||
.stream().filter(r -> r.getRegionLevel().equals(RegionConst.RL_COUNTY)) | |||||
.sorted(Comparator.comparing(RegionDTO::getRegionCode)).collect(Collectors.toList()); | |||||
List<DataDTO> regionMeetngs = Lists.newArrayList(); | |||||
for(RegionDTO region : regions){ | |||||
regionMeetngs.add(DataDTO.of(region.getRegionName(),region.getRegionCode(),meetings.stream().filter(m -> { | |||||
if(StringUtils.isNotBlank(m.getRegionCode()) && | |||||
m.getRegionCode().equals(region.getRegionCode())){ | |||||
return Boolean.TRUE; | |||||
} | |||||
return Boolean.FALSE; | |||||
}).collect(Collectors.toList()).size())); | |||||
} | |||||
res.setRegionMeetings(regionMeetngs); | |||||
//预审 验收 会议 | |||||
List<DataDTO> meetingTypes = Lists.newArrayList(); | |||||
meetingTypes.add(DataDTO.of("预审会议",ReviewTemplateTypeEnum.PRELIMINARY_SCHEME_REVIEW.getCode().toString(), | |||||
meetings.stream().filter(m -> { | |||||
if(StringUtils.isNotBlank(m.getType()) && | |||||
m.getType().equals(ReviewTemplateTypeEnum.PRELIMINARY_SCHEME_REVIEW.getCode() | |||||
.toString())){ | |||||
return Boolean.TRUE; | |||||
} | |||||
return Boolean.FALSE; | |||||
}).collect(Collectors.toList()).size())); | |||||
Long yanshouCount = meetings.stream().filter(m -> { | |||||
if (StringUtils.isNotBlank(m.getType()) && | |||||
m.getType().equals(ReviewTemplateTypeEnum.ACCEPTANCE_SCHEME_REVIEW.getCode() | |||||
.toString())) { | |||||
return Boolean.TRUE; | |||||
} | |||||
return Boolean.FALSE; | |||||
}).count(); | |||||
meetingTypes.add(DataDTO.of("验收会议",ReviewTemplateTypeEnum.ACCEPTANCE_SCHEME_REVIEW.getCode().toString(), | |||||
yanshouCount.intValue())); | |||||
res.setMeetingTypes(meetingTypes); | |||||
//各区县评审 不通过率 | |||||
List<DataDTO> regionNotpassReview = Lists.newArrayList(); | |||||
for(RegionDTO region : regions){ | |||||
DataDTO data = new DataDTO(); | |||||
data.setCode(region.getRegionCode()); | |||||
data.setName(region.getRegionName()); | |||||
//先求出 此区域会议 | |||||
List<Long> regionMeetingIds = meetings.stream().filter(m -> { | |||||
if (StringUtils.isNotBlank(m.getRegionCode()) && | |||||
m.getRegionCode().equals(region.getRegionCode())) { | |||||
return Boolean.TRUE; | |||||
} | |||||
return Boolean.FALSE; | |||||
}).map(Meeting::getId).collect(Collectors.toList()); | |||||
List<ExpertReview> regionReviews = expertReviews.stream().filter(r -> { | |||||
if (Objects.nonNull(r.getMeetingId()) && | |||||
regionMeetingIds.contains(r.getMeetingId())) { | |||||
return Boolean.TRUE; | |||||
} | |||||
return Boolean.FALSE; | |||||
}).collect(Collectors.toList()); | |||||
long regionNotpass = regionReviews.stream().filter(r -> Objects.nonNull(r.getReviewResult()) && | |||||
r.getReviewResult().equals(ReviewResultEnum.REFUSED.getCode())) | |||||
.count(); | |||||
data.setRate(CollUtil.isEmpty(regionReviews) ? BigDecimal.ZERO : | |||||
BigDecimal.valueOf(regionNotpass).multiply(BigDecimal.valueOf(100)) | |||||
.divide(BigDecimal.valueOf(regionReviews.size()),BigDecimal.ROUND_CEILING,RoundingMode.HALF_UP)); | |||||
regionNotpassReview.add(data); | |||||
} | |||||
res.setNotPassRegionMeetings(regionNotpassReview); | |||||
//各部门 不通过项目TOP10 | |||||
List<DingOrganization> organizations = dingOrganizationService.list(Wrappers.lambdaQuery(DingOrganization.class) | |||||
.in(DingOrganization::getTypeCode, Lists.newArrayList(DingOrganizationContant.UNIT_TYPE, | |||||
DingOrganizationContant.GOV_TEMPORARY))); | |||||
List<Project> projects = projectService.list(Wrappers.lambdaQuery(Project.class) | |||||
.eq(Project::getNewest, Boolean.TRUE)); | |||||
//TOP10 | |||||
List<ExpertReview> finalExpertReviews = expertReviews; | |||||
List<DataDTO> notpassTop10 = organizations.stream() | |||||
.map(o -> { | |||||
DataDTO data = new DataDTO(); | |||||
data.setCode(o.getOrganizationCode()); | |||||
data.setName(o.getOrganizationName()); | |||||
List<Project> orgProjects = projects.stream().filter(p -> Objects.nonNull(p.getBuildOrgCode()) && | |||||
p.getBuildOrgCode().equals(o.getOrganizationCode())) | |||||
.collect(Collectors.toList()); | |||||
List<String> projectCodes = orgProjects.stream().map(Project::getProjectCode) | |||||
.collect(Collectors.toList()); | |||||
if(CollUtil.isEmpty(projectCodes)){ | |||||
data.setRate(BigDecimal.ZERO); | |||||
return data; | |||||
} | |||||
List<ExpertReview> reviews = finalExpertReviews.stream().filter(r -> Objects.nonNull(r.getProjectCode()) && | |||||
projectCodes.contains(r.getProjectCode())).collect(Collectors.toList()); | |||||
long orgNotpass = reviews.stream().filter(r -> Objects.nonNull(r.getReviewResult()) && | |||||
r.getReviewResult().equals(ReviewResultEnum.REFUSED.getCode())) | |||||
.count(); | |||||
data.setRate(CollUtil.isEmpty(reviews) ? BigDecimal.ZERO : | |||||
BigDecimal.valueOf(orgNotpass).multiply(BigDecimal.valueOf(100)) | |||||
.divide(BigDecimal.valueOf(reviews.size()),BigDecimal.ROUND_CEILING,RoundingMode.HALF_UP)); | |||||
return data; | |||||
}) | |||||
.sorted(Comparator.comparing(DataDTO::getRate).reversed()) | |||||
.limit(10).collect(Collectors.toList()); | |||||
res.setNotPassTop10(notpassTop10); | |||||
return res; | |||||
} | |||||
} |
@@ -203,6 +203,13 @@ public class MeetingController { | |||||
meetingManage.uploadMeetingResult(req); | meetingManage.uploadMeetingResult(req); | ||||
} | } | ||||
@PostMapping("/project/result/upload") | |||||
@ApiOperation("评审结果上传") | |||||
@WebLog("评审结果上传") | |||||
public void uploadProjectReviewResult(@RequestBody @Valid ProjectReviewResultUploadReq req) { | |||||
meetingManage.uploadProjectReviewResult(req); | |||||
} | |||||
@GetMapping("/{meetingId}/listExpertJudge") | @GetMapping("/{meetingId}/listExpertJudge") | ||||
@ApiOperation("查询会议专家评价信息") | @ApiOperation("查询会议专家评价信息") | ||||
@WebLog("查询会议专家评价信息") | @WebLog("查询会议专家评价信息") | ||||
@@ -0,0 +1,33 @@ | |||||
package com.hz.pm.api.meeting.controller; | |||||
import com.hz.pm.api.meeting.entity.enumeration.MeetingSettingsTypeEnum; | |||||
import com.hz.pm.api.meeting.entity.req.MeetingSettingsSaveReq; | |||||
import com.hz.pm.api.meeting.manage.MeetingSettingsManage; | |||||
import lombok.AllArgsConstructor; | |||||
import org.springframework.web.bind.annotation.GetMapping; | |||||
import org.springframework.web.bind.annotation.PathVariable; | |||||
import org.springframework.web.bind.annotation.RequestMapping; | |||||
import org.springframework.web.bind.annotation.RestController; | |||||
/** | |||||
* <p> | |||||
* 前端控制器 | |||||
* </p> | |||||
* | |||||
* @author WendyYang | |||||
* @since 2023-12-27 | |||||
*/ | |||||
@RestController | |||||
@AllArgsConstructor | |||||
@RequestMapping("/api/v1/meeting/settings") | |||||
public class MeetingSettingsController { | |||||
private final MeetingSettingsManage meetingSettingsManage; | |||||
@GetMapping("/{settingsType}") | |||||
public MeetingSettingsSaveReq getSettings(@PathVariable MeetingSettingsTypeEnum settingsType) { | |||||
return meetingSettingsManage.getSettings(settingsType); | |||||
} | |||||
} |
@@ -27,30 +27,18 @@ public class Meeting implements Serializable { | |||||
@TableId(type = IdType.AUTO) | @TableId(type = IdType.AUTO) | ||||
private Long id; | private Long id; | ||||
@ApiModelProperty("事务名称") | |||||
@ApiModelProperty("会议名称") | |||||
private String name; | private String name; | ||||
@ApiModelProperty("事务类型") | |||||
@ApiModelProperty("会议类型") | |||||
private String type; | private String type; | ||||
@ApiModelProperty("评审耗时:1 半天、2 一天") | |||||
private Integer meetingUsageTime; | |||||
@ApiModelProperty("开始时间") | @ApiModelProperty("开始时间") | ||||
private LocalDateTime startTime; | private LocalDateTime startTime; | ||||
@ApiModelProperty("结束时间") | @ApiModelProperty("结束时间") | ||||
private LocalDateTime endTime; | private LocalDateTime endTime; | ||||
@ApiModelProperty("评委出席时间") | |||||
private LocalDateTime judgesAttendanceTime; | |||||
@ApiModelProperty("地区编码") | |||||
private String regionCode; | |||||
@ApiModelProperty("地区层级") | |||||
private Integer regionLevel; | |||||
@ApiModelProperty("联系人") | @ApiModelProperty("联系人") | ||||
private String connecter; | private String connecter; | ||||
@@ -71,9 +59,6 @@ public class Meeting implements Serializable { | |||||
@ApiModelProperty("是否确认名单") | @ApiModelProperty("是否确认名单") | ||||
private Boolean confirmedRoster; | private Boolean confirmedRoster; | ||||
@ApiModelProperty("短信通知签名") | |||||
private String smsNotifySign; | |||||
@ApiModelProperty("举办单位") | @ApiModelProperty("举办单位") | ||||
private String holdOrg; | private String holdOrg; | ||||
@@ -95,6 +80,12 @@ public class Meeting implements Serializable { | |||||
@ApiModelProperty("备注") | @ApiModelProperty("备注") | ||||
private String remark; | private String remark; | ||||
@ApiModelProperty("会议结果说明") | |||||
private String resultDescription; | |||||
@ApiModelProperty("相关材料") | |||||
private String resultAttachFiles; | |||||
@ApiModelProperty("创建人ID") | @ApiModelProperty("创建人ID") | ||||
@TableField(fill = FieldFill.INSERT) | @TableField(fill = FieldFill.INSERT) | ||||
private Long createBy; | private Long createBy; | ||||
@@ -0,0 +1,48 @@ | |||||
package com.hz.pm.api.meeting.entity.domain; | |||||
import com.baomidou.mybatisplus.annotation.*; | |||||
import java.io.Serializable; | |||||
import java.time.LocalDateTime; | |||||
import com.hz.pm.api.meeting.entity.enumeration.MeetingSettingsTypeEnum; | |||||
import io.swagger.annotations.ApiModel; | |||||
import lombok.Data; | |||||
/** | |||||
* <p> | |||||
* | |||||
* </p> | |||||
* | |||||
* @author WendyYang | |||||
* @since 2023-12-27 | |||||
*/ | |||||
@Data | |||||
@TableName("MEETING_SETTINGS") | |||||
@ApiModel(value = "MeetingSettings对象") | |||||
public class MeetingSettings implements Serializable { | |||||
private static final long serialVersionUID = 1L; | |||||
@TableId(value = "ID", type = IdType.AUTO) | |||||
private Long id; | |||||
private Boolean enable; | |||||
private String settingsContent; | |||||
private MeetingSettingsTypeEnum settingsType; | |||||
@TableField(fill = FieldFill.INSERT) | |||||
private LocalDateTime createOn; | |||||
@TableField(fill = FieldFill.INSERT) | |||||
private Long createBy; | |||||
@TableField(fill = FieldFill.INSERT_UPDATE) | |||||
private LocalDateTime updateOn; | |||||
@TableField(fill = FieldFill.INSERT_UPDATE) | |||||
private Long updateBy; | |||||
} |
@@ -0,0 +1,22 @@ | |||||
package com.hz.pm.api.meeting.entity.dto; | |||||
import lombok.Data; | |||||
import java.time.LocalTime; | |||||
/** | |||||
* <p> | |||||
* MeetingInviteIgnoreTmeContentDTO | |||||
* </p> | |||||
* | |||||
* @author WendyYang | |||||
* @since 00:27 2023/12/27 | |||||
*/ | |||||
@Data | |||||
public class ExpertInviteIgnoreTimeContentDTO { | |||||
private LocalTime startTime; | |||||
private LocalTime stopTime; | |||||
} |
@@ -0,0 +1,18 @@ | |||||
package com.hz.pm.api.meeting.entity.dto; | |||||
import lombok.Data; | |||||
/** | |||||
* <p> | |||||
* ExpertJudgeTimeLimitContentDTO | |||||
* </p> | |||||
* | |||||
* @author WendyYang | |||||
* @since 09:24 2023/12/27 | |||||
*/ | |||||
@Data | |||||
public class ExpertJudgeTimeLimitContentDTO { | |||||
private Integer days; | |||||
} |
@@ -0,0 +1,23 @@ | |||||
package com.hz.pm.api.meeting.entity.enumeration; | |||||
import lombok.AllArgsConstructor; | |||||
import lombok.Getter; | |||||
/** | |||||
* <p> | |||||
* MeetingSettingsTypeEnum | |||||
* </p> | |||||
* | |||||
* @author WendyYang | |||||
* @since 00:06 2023/12/27 | |||||
*/ | |||||
@Getter | |||||
@AllArgsConstructor | |||||
public enum MeetingSettingsTypeEnum { | |||||
MEETING_INVITE_IGNORE_TIME("专家抽取免打扰时段配置"), | |||||
EXPERT_JUDGE_TIME_LIMIT("专家星级评分时间配置"); | |||||
private final String name; | |||||
} |
@@ -45,12 +45,6 @@ public class MeetingListReq extends PagePo { | |||||
@ApiModelProperty("项目名称") | @ApiModelProperty("项目名称") | ||||
private String projectName; | private String projectName; | ||||
@ApiModelProperty("区域编码") | |||||
private String regionCode; | |||||
@ApiModelProperty("区域层级") | |||||
private Integer regionLevel; | |||||
@ApiModelProperty("参会名单是否确认") | @ApiModelProperty("参会名单是否确认") | ||||
private Boolean confirmedRoster; | private Boolean confirmedRoster; | ||||
@@ -4,7 +4,6 @@ import io.swagger.annotations.ApiModelProperty; | |||||
import lombok.Data; | import lombok.Data; | ||||
import javax.validation.constraints.NotNull; | import javax.validation.constraints.NotNull; | ||||
import java.math.BigDecimal; | |||||
/** | /** | ||||
* <p> | * <p> | ||||
@@ -21,29 +20,10 @@ public class MeetingResultUploadReq { | |||||
@NotNull(message = "会议ID不能为空") | @NotNull(message = "会议ID不能为空") | ||||
private Long meetingId; | private Long meetingId; | ||||
@ApiModelProperty("项目关联会议ID") | |||||
@NotNull(message = "项目关联会议ID不能为空") | |||||
private Long meetingProjectId; | |||||
@ApiModelProperty("会议结果说明") | |||||
private String resultDescription; | |||||
@ApiModelProperty("建设必要性") | |||||
private String buildNecessity; | |||||
@ApiModelProperty("需求合理性") | |||||
private String needRationality; | |||||
@ApiModelProperty("技术方案可行性") | |||||
private String techFeasibility; | |||||
@ApiModelProperty("审核结果:1 通过、0 不通过") | |||||
private Integer reviewResult; | |||||
@ApiModelProperty("其他意见") | |||||
private String otherAdvices; | |||||
@ApiModelProperty("投资测算合理性") | |||||
private String investRationality; | |||||
@ApiModelProperty("建议资金(单位:万元)") | |||||
private BigDecimal suggestedFunding; | |||||
@ApiModelProperty("相关材料") | |||||
private String resultAttachFiles; | |||||
} | } |
@@ -0,0 +1,42 @@ | |||||
package com.hz.pm.api.meeting.entity.req; | |||||
import com.hz.pm.api.meeting.entity.dto.ExpertInviteIgnoreTimeContentDTO; | |||||
import com.hz.pm.api.meeting.entity.dto.ExpertJudgeTimeLimitContentDTO; | |||||
import com.hz.pm.api.meeting.entity.enumeration.MeetingSettingsTypeEnum; | |||||
import io.swagger.annotations.ApiModelProperty; | |||||
import lombok.Data; | |||||
/** | |||||
* <p> | |||||
* MeetingSettingsSaveReq | |||||
* </p> | |||||
* | |||||
* @author WendyYang | |||||
* @since 09:53 2023/12/27 | |||||
*/ | |||||
@Data | |||||
public class MeetingSettingsSaveReq { | |||||
@ApiModelProperty("是否启用") | |||||
private Boolean enable; | |||||
@ApiModelProperty("配置内容") | |||||
private Object settingsContent; | |||||
@ApiModelProperty("配置类型") | |||||
private MeetingSettingsTypeEnum settingsType; | |||||
@ApiModelProperty("仅做参数展示") | |||||
private SettingsContentPackageDTO settingsContentPackage; | |||||
public static class SettingsContentPackageDTO { | |||||
@ApiModelProperty("专家邀请免打扰时段设置") | |||||
private ExpertInviteIgnoreTimeContentDTO expertInviteIgnoreTimeContent; | |||||
@ApiModelProperty("专家评价时间设置") | |||||
private ExpertJudgeTimeLimitContentDTO expertJudgeTimeLimitContent; | |||||
} | |||||
} |
@@ -50,16 +50,6 @@ public class MeetingDetailBasicVO { | |||||
@JSONField(format = "yyyy-MM-dd HH:mm") | @JSONField(format = "yyyy-MM-dd HH:mm") | ||||
private LocalDateTime endTime; | private LocalDateTime endTime; | ||||
@ApiModelProperty("评委到场时间") | |||||
@JSONField(format = "yyyy-MM-dd HH:mm") | |||||
private LocalDateTime judgesAttendanceTime; | |||||
@ApiModelProperty("会议耗时") | |||||
private Integer meetingUsageTime; | |||||
@ApiModelProperty("短信通知单位签名") | |||||
private String smsNotifySign; | |||||
@ApiModelProperty("联系人") | @ApiModelProperty("联系人") | ||||
private String connecter; | private String connecter; | ||||
@@ -111,4 +101,10 @@ public class MeetingDetailBasicVO { | |||||
@ApiModelProperty("相关材料") | @ApiModelProperty("相关材料") | ||||
private String attachFiles; | private String attachFiles; | ||||
@ApiModelProperty("会议结果说明") | |||||
private String resultDescription; | |||||
@ApiModelProperty("会议结果附件") | |||||
private String resultAttachFiles; | |||||
} | } |
@@ -121,11 +121,6 @@ public class MeetingManageHelper { | |||||
} | } | ||||
public void buildMeetingQuery(LambdaQueryWrapper<Meeting> query, MeetingListReq req) { | public void buildMeetingQuery(LambdaQueryWrapper<Meeting> query, MeetingListReq req) { | ||||
if (StrUtils.isNotBlank(req.getRegionCode())) { | |||||
List<RegionDTO> regions = regionCacheHelper.listChildren(req.getRegionCode(), req.getRegionLevel()); | |||||
List<String> regionCodes = CollUtils.fieldList(regions, RegionDTO::getRegionCode); | |||||
query.in(Meeting::getRegionCode, regionCodes).ge(Meeting::getRegionLevel, req.getRegionLevel()); | |||||
} | |||||
if (StrUtil.isNotBlank(req.getName())) { | if (StrUtil.isNotBlank(req.getName())) { | ||||
query.like(Meeting::getName, req.getName()); | query.like(Meeting::getName, req.getName()); | ||||
} | } | ||||
@@ -195,7 +195,6 @@ public class ExpertExportManage { | |||||
Meeting meeting = meetingService.getById(meetingId); | Meeting meeting = meetingService.getById(meetingId); | ||||
LaborFeeAuditTableDTO data = new LaborFeeAuditTableDTO(); | LaborFeeAuditTableDTO data = new LaborFeeAuditTableDTO(); | ||||
data.setMeetingTime(DateUtil.localDateTimeFormat(meeting.getStartTime(), "yyyy-MM-dd HH:mm")); | data.setMeetingTime(DateUtil.localDateTimeFormat(meeting.getStartTime(), "yyyy-MM-dd HH:mm")); | ||||
data.setMeetingUsageTime(meetingUsageTime.apply(meeting.getMeetingUsageTime())); | |||||
List<String> projectNames = new ArrayList<>(); | List<String> projectNames = new ArrayList<>(); | ||||
if (meeting.getIsInnerProject()) { | if (meeting.getIsInnerProject()) { | ||||
List<MeetingInnerProject> inners = meetingInnerProjectService.listByMeetingId(meetingId); | List<MeetingInnerProject> inners = meetingInnerProjectService.listByMeetingId(meetingId); | ||||
@@ -243,7 +242,6 @@ public class ExpertExportManage { | |||||
Meeting meeting = meetingService.getById(meetingId); | Meeting meeting = meetingService.getById(meetingId); | ||||
ExpertInviteTableDTO data = new ExpertInviteTableDTO(); | ExpertInviteTableDTO data = new ExpertInviteTableDTO(); | ||||
data.setMeetingTime(DateUtil.localDateTimeFormat(meeting.getStartTime(), "yyyy-MM-dd HH:mm")); | data.setMeetingTime(DateUtil.localDateTimeFormat(meeting.getStartTime(), "yyyy-MM-dd HH:mm")); | ||||
data.setMeetingUsageTime(meetingUsageTime.apply(meeting.getMeetingUsageTime())); | |||||
data.setMeetingCreateBy(meeting.getCreator()); | data.setMeetingCreateBy(meeting.getCreator()); | ||||
data.setMeetingAddress(meeting.getMeetingAddress()); | data.setMeetingAddress(meeting.getMeetingAddress()); | ||||
if (meeting.getIsInnerProject()) { | if (meeting.getIsInnerProject()) { | ||||
@@ -7,12 +7,12 @@ import cn.hutool.core.util.StrUtil; | |||||
import cn.hutool.crypto.SecureUtil; | import cn.hutool.crypto.SecureUtil; | ||||
import cn.hutool.json.JSONUtil; | import cn.hutool.json.JSONUtil; | ||||
import com.alibaba.fastjson.JSON; | import com.alibaba.fastjson.JSON; | ||||
import com.baomidou.mybatisplus.core.conditions.Wrapper; | |||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | ||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; | ||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers; | import com.baomidou.mybatisplus.core.toolkit.Wrappers; | ||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; | ||||
import com.hz.pm.api.common.helper.RegionCacheHelper; | import com.hz.pm.api.common.helper.RegionCacheHelper; | ||||
import com.hz.pm.api.common.model.entity.ViewRegionDTO; | |||||
import com.hz.pm.api.expert.entity.ExpertUserFullInfo; | import com.hz.pm.api.expert.entity.ExpertUserFullInfo; | ||||
import com.hz.pm.api.expert.service.IExpertReviewService; | import com.hz.pm.api.expert.service.IExpertReviewService; | ||||
import com.hz.pm.api.expert.service.IExpertUserFullInfoService; | import com.hz.pm.api.expert.service.IExpertUserFullInfoService; | ||||
@@ -132,8 +132,6 @@ public class MeetingManage { | |||||
meeting.setStatus(MeetingStatusEnum.NORMAL.getCode()); | meeting.setStatus(MeetingStatusEnum.NORMAL.getCode()); | ||||
meeting.setHoldOrg(userDetail.getOrganizationName()); | meeting.setHoldOrg(userDetail.getOrganizationName()); | ||||
meeting.setHoldOrgCode(userDetail.getOrganizationCode()); | meeting.setHoldOrgCode(userDetail.getOrganizationCode()); | ||||
meeting.setRegionCode(userDetail.getRegionCode()); | |||||
meeting.setRegionLevel(userDetail.getRegionLevel()); | |||||
meeting.setCreator(userDetail.getUsername()); | meeting.setCreator(userDetail.getUsername()); | ||||
meeting.setInviteStatus(Boolean.FALSE); | meeting.setInviteStatus(Boolean.FALSE); | ||||
meeting.setConfirmedRoster(Boolean.FALSE); | meeting.setConfirmedRoster(Boolean.FALSE); | ||||
@@ -356,7 +354,7 @@ public class MeetingManage { | |||||
item.setMeetingExpertId(info.getMeetingExpertId()); | item.setMeetingExpertId(info.getMeetingExpertId()); | ||||
item.setExpertStatus(info.getStatus()); | item.setExpertStatus(info.getStatus()); | ||||
MeetingExpertJudge judge = expertJudgeMap.get(info.getMeetingExpertId()); | MeetingExpertJudge judge = expertJudgeMap.get(info.getMeetingExpertId()); | ||||
item.setHasJudge(judge!= null); | |||||
item.setHasJudge(judge != null); | |||||
if (judge != null) { | if (judge != null) { | ||||
item.setJudgeScore(judge.getScore()); | item.setJudgeScore(judge.getScore()); | ||||
} | } | ||||
@@ -404,19 +402,9 @@ public class MeetingManage { | |||||
* @author WendyYang | * @author WendyYang | ||||
*/ | */ | ||||
public PageVo<MeetingByManagerVO> meetingListForManager(MeetingListReq req) { | public PageVo<MeetingByManagerVO> meetingListForManager(MeetingListReq req) { | ||||
ViewRegionDTO viewRegions = meetingDataScopeHelper.meetingListViewRegions(); | |||||
Collection<String> regions; | |||||
if ((regions = viewRegions.getRegions()) != null && regions.isEmpty()) { | |||||
return PageVo.empty(); | |||||
} | |||||
LambdaQueryWrapper<Meeting> query = new LambdaQueryWrapper<Meeting>() | LambdaQueryWrapper<Meeting> query = new LambdaQueryWrapper<Meeting>() | ||||
.eq(req.getStatus() != null, Meeting::getStatus, req.getStatus()) | |||||
.orderByDesc(Meeting::getCreateOn); | .orderByDesc(Meeting::getCreateOn); | ||||
// 补充逻辑 如果拥有超级管理员权限可以看到所有事务 | |||||
if (regions != null) { | |||||
query.in(Meeting::getRegionCode, regions); | |||||
query.ge(Meeting::getRegionLevel, viewRegions.getRegionLevel()); | |||||
} | |||||
query.eq(req.getStatus() != null, Meeting::getStatus, req.getStatus()); | |||||
meetingManageHelper.buildMeetingQuery(query, req); | meetingManageHelper.buildMeetingQuery(query, req); | ||||
Page<Meeting> page = meetingService.page(req.page(), query); | Page<Meeting> page = meetingService.page(req.page(), query); | ||||
if (page.getTotal() == 0) { | if (page.getTotal() == 0) { | ||||
@@ -435,15 +423,12 @@ public class MeetingManage { | |||||
Assert.notNull(meeting, "会议不存在"); | Assert.notNull(meeting, "会议不存在"); | ||||
MeetingDetailBasicVO detail = MeetingDetailBasicVO.builder() | MeetingDetailBasicVO detail = MeetingDetailBasicVO.builder() | ||||
.meetingId(meeting.getId()) | .meetingId(meeting.getId()) | ||||
.regionCode(meeting.getRegionCode()) | |||||
.meetingName(meeting.getName()) | .meetingName(meeting.getName()) | ||||
.meetingType(meeting.getType()) | .meetingType(meeting.getType()) | ||||
.meetingAddress(meeting.getMeetingAddress()) | .meetingAddress(meeting.getMeetingAddress()) | ||||
.typeName(getDictName(meeting.getType())) | .typeName(getDictName(meeting.getType())) | ||||
.startTime(meeting.getStartTime()) | .startTime(meeting.getStartTime()) | ||||
.endTime(meeting.getEndTime()) | .endTime(meeting.getEndTime()) | ||||
.judgesAttendanceTime(meeting.getJudgesAttendanceTime()) | |||||
.meetingUsageTime(meeting.getMeetingUsageTime()) | |||||
.contact(meeting.getContact()) | .contact(meeting.getContact()) | ||||
.connecter(meeting.getConnecter()) | .connecter(meeting.getConnecter()) | ||||
.status(meeting.getStatus()) | .status(meeting.getStatus()) | ||||
@@ -456,7 +441,8 @@ public class MeetingManage { | |||||
.invitedStopped(meeting.getInviteStatus()) | .invitedStopped(meeting.getInviteStatus()) | ||||
.attachFiles(meeting.getAttachFiles()) | .attachFiles(meeting.getAttachFiles()) | ||||
.description(meeting.getDescription()) | .description(meeting.getDescription()) | ||||
.smsNotifySign(meeting.getSmsNotifySign()) | |||||
.resultDescription(meeting.getResultDescription()) | |||||
.resultAttachFiles(meeting.getResultAttachFiles()) | |||||
.remark(meeting.getRemark()) | .remark(meeting.getRemark()) | ||||
.build(); | .build(); | ||||
if (meeting.getIsInnerProject() != null) { | if (meeting.getIsInnerProject() != null) { | ||||
@@ -935,7 +921,32 @@ public class MeetingManage { | |||||
} | } | ||||
public void uploadMeetingResult(MeetingResultUploadReq req) { | public void uploadMeetingResult(MeetingResultUploadReq req) { | ||||
String key = "meeting_result_upload:" + req.getMeetingProjectId(); | |||||
String key = "meeting_result_upload:" + req.getMeetingId(); | |||||
if (!distributedLock.lock(key, RETRY_TIMES)) { | |||||
throw BizException.wrap("正在上传会议结果,请勿重复操作"); | |||||
} | |||||
try { | |||||
Meeting meeting = meetingService.getById(req.getMeetingId()); | |||||
if (meeting == null || MeetingStatusEnum.CANCELED.eq(meeting.getStatus())) { | |||||
throw BizException.wrap("会议不存在或已取消"); | |||||
} | |||||
LocalDateTime now = LocalDateTime.now(); | |||||
if (meeting.getEndTime().isAfter(now)) { | |||||
throw BizException.wrap("会议未结束"); | |||||
} | |||||
Wrapper<Meeting> update = Wrappers.lambdaUpdate(Meeting.class) | |||||
.set(Meeting::getResultDescription, req.getResultDescription()) | |||||
.set(Meeting::getResultAttachFiles, req.getResultAttachFiles()) | |||||
.set(Meeting::getUpdateOn, now) | |||||
.eq(Meeting::getId, req.getMeetingId()); | |||||
meetingService.update(update); | |||||
} finally { | |||||
distributedLock.releaseLock(key); | |||||
} | |||||
} | |||||
public void uploadProjectReviewResult(ProjectReviewResultUploadReq req) { | |||||
String key = "meeting_project_result_upload:" + req.getMeetingProjectId(); | |||||
if (!distributedLock.lock(key, RETRY_TIMES)) { | if (!distributedLock.lock(key, RETRY_TIMES)) { | ||||
throw BizException.wrap("正在上传会议结果,请勿重复操作"); | throw BizException.wrap("正在上传会议结果,请勿重复操作"); | ||||
} | } | ||||
@@ -0,0 +1,60 @@ | |||||
package com.hz.pm.api.meeting.manage; | |||||
import cn.hutool.json.JSONUtil; | |||||
import com.baomidou.mybatisplus.core.conditions.Wrapper; | |||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers; | |||||
import com.hz.pm.api.meeting.entity.domain.MeetingSettings; | |||||
import com.hz.pm.api.meeting.entity.enumeration.MeetingSettingsTypeEnum; | |||||
import com.hz.pm.api.meeting.entity.req.MeetingSettingsSaveReq; | |||||
import com.hz.pm.api.meeting.service.IMeetingSettingsService; | |||||
import lombok.AllArgsConstructor; | |||||
import org.springframework.stereotype.Component; | |||||
/** | |||||
* <p> | |||||
* MeetingSettingSmanage | |||||
* </p> | |||||
* | |||||
* @author WendyYang | |||||
* @since 09:48 2023/12/27 | |||||
*/ | |||||
@Component | |||||
@AllArgsConstructor | |||||
public class MeetingSettingsManage { | |||||
private final IMeetingSettingsService meetingSettingsService; | |||||
private MeetingSettings getBySettingsType(MeetingSettingsTypeEnum settingsType){ | |||||
Wrapper<MeetingSettings> query = Wrappers.lambdaQuery(MeetingSettings.class) | |||||
.eq(MeetingSettings::getSettingsType, settingsType); | |||||
return meetingSettingsService.getOne(query); | |||||
} | |||||
public static <T> T parseContent(String content,Class<T> tClass){ | |||||
return JSONUtil.toBean(content, tClass); | |||||
} | |||||
public MeetingSettingsSaveReq getSettings(MeetingSettingsTypeEnum settingsType){ | |||||
MeetingSettings settings = getBySettingsType(settingsType); | |||||
if (settings == null) { | |||||
return null; | |||||
} | |||||
MeetingSettingsSaveReq result = new MeetingSettingsSaveReq(); | |||||
result.setEnable(settings.getEnable()); | |||||
result.setSettingsType(settings.getSettingsType()); | |||||
result.setSettingsContent(settings.getSettingsContent()); | |||||
return result; | |||||
} | |||||
public synchronized void saveSettings(MeetingSettingsSaveReq req) { | |||||
MeetingSettings settings = getBySettingsType(req.getSettingsType()); | |||||
if (settings == null) { | |||||
settings = new MeetingSettings(); | |||||
settings.setSettingsContent(req.getSettingsType().name()); | |||||
settings.setEnable(req.getEnable()); | |||||
settings.setSettingsContent(JSONUtil.toJsonStr(req.getSettingsContent())); | |||||
} | |||||
meetingSettingsService.saveOrUpdate(settings); | |||||
} | |||||
} |
@@ -0,0 +1,16 @@ | |||||
package com.hz.pm.api.meeting.mapper; | |||||
import com.hz.pm.api.meeting.entity.domain.MeetingSettings; | |||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; | |||||
/** | |||||
* <p> | |||||
* Mapper 接口 | |||||
* </p> | |||||
* | |||||
* @author WendyYang | |||||
* @since 2023-12-27 | |||||
*/ | |||||
public interface MeetingSettingsMapper extends BaseMapper<MeetingSettings> { | |||||
} |
@@ -0,0 +1,5 @@ | |||||
<?xml version="1.0" encoding="UTF-8"?> | |||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | |||||
<mapper namespace="com.hz.pm.api.meeting.mapper.MeetingSettingsMapper"> | |||||
</mapper> |
@@ -0,0 +1,16 @@ | |||||
package com.hz.pm.api.meeting.service; | |||||
import com.hz.pm.api.meeting.entity.domain.MeetingSettings; | |||||
import com.baomidou.mybatisplus.extension.service.IService; | |||||
/** | |||||
* <p> | |||||
* 服务类 | |||||
* </p> | |||||
* | |||||
* @author WendyYang | |||||
* @since 2023-12-27 | |||||
*/ | |||||
public interface IMeetingSettingsService extends IService<MeetingSettings> { | |||||
} |
@@ -0,0 +1,20 @@ | |||||
package com.hz.pm.api.meeting.service.impl; | |||||
import com.hz.pm.api.meeting.entity.domain.MeetingSettings; | |||||
import com.hz.pm.api.meeting.mapper.MeetingSettingsMapper; | |||||
import com.hz.pm.api.meeting.service.IMeetingSettingsService; | |||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; | |||||
import org.springframework.stereotype.Service; | |||||
/** | |||||
* <p> | |||||
* 服务实现类 | |||||
* </p> | |||||
* | |||||
* @author WendyYang | |||||
* @since 2023-12-27 | |||||
*/ | |||||
@Service | |||||
public class MeetingSettingsServiceImpl extends ServiceImpl<MeetingSettingsMapper, MeetingSettings> implements IMeetingSettingsService { | |||||
} |
@@ -55,7 +55,7 @@ public class CodeGen { | |||||
} | } | ||||
public static void main(String[] args) { | public static void main(String[] args) { | ||||
generate("CMM", "user", PATH_YYD, "mh_unit"); | |||||
generate("WendyYang", "meeting", PATH_YYD, "meeting_settings"); | |||||
} | } | ||||
} | } |