会议后台接口

This commit is contained in:
zjf committed 2025-07-04 19:54:22 +08:00
1 parent 236a4278fd
commit 8f554e933c
7 files changed
+167 -26

No files matched your search

@@ -7,6 +7,7 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
/**
* 包厢预约记录表
@@ -38,13 +39,13 @@ public class BoxesBookingEntity extends Model<BoxesBookingEntity> {
* 开始时间
*/
@Schema(description="开始时间")
private Object startTime;
private LocalTime startTime;
/**
* 结束时间
*/
@Schema(description="结束时间")
private Object endTime;
private LocalTime endTime;
/**
* 审核人id
@@ -20,9 +20,27 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import com.bsd.pjcloud.integrated.entity.MeetingRoomEntity;
import com.bsd.pjcloud.integrated.service.MeetingRoomService;
import com.bsd.pjcloud.flow.task.api.feign.RemoteFlowApiFlowService;
import com.bsd.pjcloud.flow.task.constant.TaskCheckStatusEnum;
import com.bsd.pjcloud.flow.task.dto.ProcessInstanceParamDto;
import com.bsd.pjcloud.flow.task.entity.Process;
import com.bsd.pjcloud.integrated.constant.IntegratedFlowConstant;
import com.bsd.pjcloud.integrated.dto.flow.MeetingFlowDto;
import cn.hutool.core.bean.BeanUtil;
import com.bsd.pjcloud.common.core.constant.enums.YesNoEnum;
import com.bsd.pjcloud.common.core.exception.ServiceException;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDate;
import java.time.LocalTime;
import java.util.Map;
import java.util.List;
import java.util.Objects;
import com.bsd.pjcloud.integrated.dto.meeting.MeetingBookingSaveDto;
import com.bsd.pjcloud.integrated.vo.meeting.MeetingBookingPageVo;
import java.util.HashMap;
/**
* 会议室预约
@@ -38,6 +56,8 @@ import java.util.Objects;
public class MeetingBookingController {
private final MeetingBookingService meetingBookingService;
private final MeetingRoomService meetingRoomService;
private final RemoteFlowApiFlowService remoteFlowApiFlowService;
/**
* 分页查询
@@ -45,13 +65,47 @@ public class MeetingBookingController {
* @param meetingBooking 会议室预约
* @return
*/
@Operation(summary = "分页查询" , description = "分页查询" )
@GetMapping("/page" )
@PreAuthorize("@pms.hasPermission('integrated_meetingBooking_view')" )
public R getMeetingBookingPage(@ParameterObject Page page, @ParameterObject MeetingBookingEntity meetingBooking) {
@Operation(summary = "分页查询", description = "分页查询")
@GetMapping("/page")
@PreAuthorize("@pms.hasPermission('integrated_meetingBooking_view')")
public R<Page<MeetingBookingPageVo>> getMeetingBookingPage(@ParameterObject Page page, @ParameterObject MeetingBookingEntity meetingBooking) {
LambdaQueryWrapper<MeetingBookingEntity> wrapper = Wrappers.lambdaQuery();
wrapper.eq(StrUtil.isNotBlank(meetingBooking.getTitle()),MeetingBookingEntity::getTitle,meetingBooking.getTitle());
return R.ok(meetingBookingService.pageScope(page, wrapper));
wrapper.eq(StrUtil.isNotBlank(meetingBooking.getTitle()), MeetingBookingEntity::getTitle, meetingBooking.getTitle());
Page<MeetingBookingEntity> entityPage = meetingBookingService.pageScope(page, wrapper);
// 批量查会议室名称,避免N+1
List<Long> roomIds = entityPage.getRecords().stream().map(MeetingBookingEntity::getRoomId).distinct().toList();
Map<Long, String> roomNameMap = new HashMap<>();
if (!roomIds.isEmpty()) {
List<MeetingRoomEntity> rooms = meetingRoomService.listByIds(roomIds);
for (MeetingRoomEntity room : rooms) {
roomNameMap.put(room.getId(), room.getRoomName());
}
}
// 转VO
List<MeetingBookingPageVo> voList = entityPage.getRecords().stream().map(e -> {
MeetingBookingPageVo vo = new MeetingBookingPageVo();
vo.setId(e.getId());
vo.setTitle(e.getTitle());
vo.setRoomId(e.getRoomId());
vo.setRoomName(roomNameMap.get(e.getRoomId()));
vo.setBookingDate(e.getBookingDate());
vo.setStartTime(e.getStartTime());
vo.setEndTime(e.getEndTime());
vo.setApplicantId(e.getApplicantId());
vo.setAssigneeName(e.getAssigneeName());
vo.setCheckStatus(e.getCheckStatus());
vo.setCheckReason(e.getCheckReason());
vo.setCreateTime(e.getCreateTime());
vo.setCreateBy(e.getCreateBy());
vo.setDescription(e.getDescription());
return vo;
}).toList();
Page<MeetingBookingPageVo> voPage = new Page<>(entityPage.getCurrent(), entityPage.getSize(), entityPage.getTotal());
voPage.setRecords(voList);
return R.ok(voPage);
}
@@ -68,17 +122,84 @@ public class MeetingBookingController {
}
/**
* 新增会议室预约
* @param meetingBooking 会议室预约
* 新增会议室预约(PC端,逻辑与手机端一致)
* @param dto 预约参数
* @return R
*/
@Operation(summary = "新增会议室预约" , description = "新增会议室预约" )
@SysLog("新增会议室预约" )
@Operation(summary = "新增会议室预约", description = "新增会议室预约")
@SysLog("新增会议室预约")
@PostMapping
@PreAuthorize("@pms.hasPermission('integrated_meetingBooking_add')" )
public R save(@RequestBody MeetingBookingEntity meetingBooking) {
@PreAuthorize("@pms.hasPermission('integrated_meetingBooking_add')")
@Transactional
public R save(@RequestBody MeetingBookingSaveDto dto) {
// 1. 参数转换
MeetingBookingEntity meetingBooking = new MeetingBookingEntity();
meetingBooking.setTitle(dto.getTitle());
meetingBooking.setRoomId(dto.getRoomId());
meetingBooking.setDescription(dto.getDescription());
meetingBooking.setBookingDate(LocalDate.parse(dto.getBookingDate()));
meetingBooking.setStartTime(LocalTime.parse(dto.getStartTime()));
meetingBooking.setEndTime(LocalTime.parse(dto.getEndTime()));
// 2. 验证会议室是否存在
MeetingRoomEntity room = meetingRoomService.getById(meetingBooking.getRoomId());
if (room == null) {
return R.failed("会议室不存在");
}
// 3. 验证会议室状态
if (!YesNoEnum.NO.getCode().equals(room.getStatus())) {
return R.failed("会议室当前不可用");
}
// 4. 校验时间
LocalDate bookingDate = meetingBooking.getBookingDate();
LocalTime startTime = meetingBooking.getStartTime();
LocalTime endTime = meetingBooking.getEndTime();
if (startTime == null || endTime == null || bookingDate == null) {
return R.failed("预约日期和时间不能为空");
}
if (startTime.isAfter(endTime)) {
return R.failed("开始时间不能晚于结束时间");
}
LocalTime availableStart = LocalTime.of(8, 0);
LocalTime availableEnd = LocalTime.of(18, 0);
if (startTime.isBefore(availableStart) || endTime.isAfter(availableEnd)) {
return R.failed("预约时间必须在8:00-18:00之间");
}
// 5. 检查时间段是否已被预约
var existingBookings = meetingBookingService.list(
Wrappers.<MeetingBookingEntity>lambdaQuery()
.eq(MeetingBookingEntity::getRoomId, meetingBooking.getRoomId())
.eq(MeetingBookingEntity::getBookingDate, bookingDate)
.eq(MeetingBookingEntity::getCheckStatus, TaskCheckStatusEnum.RESULT.getCode())
);
for (MeetingBookingEntity booking : existingBookings) {
LocalTime bookingStart = booking.getStartTime();
LocalTime bookingEnd = booking.getEndTime();
if (!(endTime.compareTo(bookingStart) <= 0 || startTime.compareTo(bookingEnd) >= 0)) {
return R.failed("该时间段已被预约");
}
}
// 6. 设置预约人、部门
meetingBooking.setApplicantId(SecurityUtils.getUser().getId());
meetingBooking.setDeptId(SecurityUtils.getUser().getDeptId());
return R.ok(meetingBookingService.save(meetingBooking));
// 7. 发起流程
var processByBusinessKey = remoteFlowApiFlowService.getProcessByBusinessKey(IntegratedFlowConstant.INTEGRATED_MEETING_BOOKING);
if (!processByBusinessKey.isOk() || processByBusinessKey.getData() == null) {
throw new ServiceException("流程配置获取失败: " + processByBusinessKey.getMsg());
}
Process process = processByBusinessKey.getData();
MeetingFlowDto meetingFlowDto = new MeetingFlowDto();
meetingFlowDto.setRoomName(room.getRoomName());
meetingFlowDto.setApplicantName(SecurityUtils.getUser().getUsername());
meetingFlowDto.setMeetingTime(bookingDate + " " + startTime + "-" + endTime);
Map<String, Object> stringObjectMap = BeanUtil.beanToMap(meetingFlowDto);
ProcessInstanceParamDto processInstanceParamDto = new ProcessInstanceParamDto();
processInstanceParamDto.setFlowId(process.getFlowId());
processInstanceParamDto.setParamMap(stringObjectMap);
var stringR = remoteFlowApiFlowService.startProcessInstance(processInstanceParamDto);
meetingBooking.setCheckStatus(TaskCheckStatusEnum.PADDING.getCode());
meetingBooking.setProcessInstanceId(stringR.getData());
boolean success = meetingBookingService.save(meetingBooking);
return R.ok(success);
}
/**
@@ -9,6 +9,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsd.pjcloud.common.core.constant.enums.YesNoEnum;
import com.bsd.pjcloud.common.core.exception.ServiceException;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.idempotent.annotation.Idempotent;
import com.bsd.pjcloud.common.log.annotation.SysLog;
import com.bsd.pjcloud.common.security.annotation.Inner;
import com.bsd.pjcloud.common.security.util.SecurityUtils;
@@ -50,6 +51,7 @@ import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.time.LocalDateTime;
import java.util.HashMap;
/**
* 会议室信息表
@@ -211,7 +213,7 @@ public class MeetingRoomController {
Wrappers.<MeetingBookingEntity>lambdaQuery()
.eq(MeetingBookingEntity::getRoomId, roomId)
.eq(MeetingBookingEntity::getBookingDate, bookingDate)
.eq(MeetingBookingEntity::getCheckStatus, TaskCheckStatusEnum.RESULT.getCode()) // 已通过的预约
// .eq(MeetingBookingEntity::getCheckStatus, TaskCheckStatusEnum.RESULT.getCode()) // 已通过的预约
);
// 标记已预约的时间段
@@ -250,6 +252,7 @@ public class MeetingRoomController {
@PostMapping("/{roomId}/book")
@Operation(summary = "预约会议室", description = "预约会议室")
@Transactional
@Idempotent(expireTime = 5, info = "请勿重复预约")
public R<Boolean> bookMeetingRoom(@PathVariable("roomId") Long roomId, @RequestBody MeetingBookingReqVo reqVo) {
// 1. 验证会议室是否存在
MeetingRoomEntity room = meetingRoomService.getById(roomId);
@@ -413,8 +416,24 @@ public class MeetingRoomController {
}
/**
* 会议室下拉选择(仅返回可用会议室id和名称)
*/
@GetMapping("/app/select")
public R<List<Map<String, Object>>> selectMeetingRooms() {
LambdaQueryWrapper<MeetingRoomEntity> wrapper = Wrappers.lambdaQuery();
wrapper.eq(MeetingRoomEntity::getStatus, YesNoEnum.NO.getCode()); // 只查可用
wrapper.select(MeetingRoomEntity::getId, MeetingRoomEntity::getRoomName);
List<MeetingRoomEntity> list = meetingRoomService.list(wrapper);
List<Map<String, Object>> result = new ArrayList<>();
for (MeetingRoomEntity room : list) {
Map<String, Object> map = new HashMap<>();
map.put("id", room.getId());
map.put("name", room.getRoomName());
result.add(map);
}
return R.ok(result);
}
}
@@ -63,16 +63,16 @@ public class MeetingBookingEntity extends Model<MeetingBookingEntity> {
private Long deptId;
/**
* 申请人id
* 申请人
*/
@Schema(description="申请人id")
@Schema(description="申请人")
private Long applicantId;
/**
* 会议负责人id
* 会议负责人
*/
@Schema(description="会议负责人id")
private Long assigneeId;
@Schema(description="会议负责人")
private String assigneeName;
/**
* 开始时间
@@ -14,5 +14,5 @@ public interface MeetingBookingService extends IService<MeetingBookingEntity> {
* @param wrapper
* @return
*/
Object pageScope(Page page, LambdaQueryWrapper<MeetingBookingEntity> wrapper);
Page pageScope(Page page, LambdaQueryWrapper<MeetingBookingEntity> wrapper);
}
@@ -17,7 +17,7 @@ import org.springframework.stereotype.Service;
@Service
public class MeetingBookingServiceImpl extends ServiceImpl<MeetingBookingMapper, MeetingBookingEntity> implements MeetingBookingService {
@Override
public Object pageScope(Page page, LambdaQueryWrapper<MeetingBookingEntity> wrapper) {
public Page pageScope(Page page, LambdaQueryWrapper<MeetingBookingEntity> wrapper) {
return baseMapper.selectPageByScope(page, wrapper, DataScope.of());
}
}
@@ -11,7 +11,7 @@
<result property="checkStatus" column="meeting_status"/>
<result property="deptId" column="dept_id"/>
<result property="applicantId" column="applicant_id"/>
<result property="assigneeId" column="assignee_id"/>
<result property="assigneeName" column="assignee_name"/>
<result property="startTime" column="start_time"/>
<result property="endTime" column="end_time"/>
<result property="createBy" column="create_by"/>