diff --git a/pjcloud-integrated/pjcloud-integrated-api/src/main/java/com/bsd/pjcloud/integrated/dto/meeting/MeetingBookingSaveDto.java b/pjcloud-integrated/pjcloud-integrated-api/src/main/java/com/bsd/pjcloud/integrated/dto/meeting/MeetingBookingSaveDto.java index 0f4313050..4a29d1231 100644 --- a/pjcloud-integrated/pjcloud-integrated-api/src/main/java/com/bsd/pjcloud/integrated/dto/meeting/MeetingBookingSaveDto.java +++ b/pjcloud-integrated/pjcloud-integrated-api/src/main/java/com/bsd/pjcloud/integrated/dto/meeting/MeetingBookingSaveDto.java @@ -22,4 +22,10 @@ public class MeetingBookingSaveDto { @Schema(description = "结束时间,格式HH:mm") private String endTime; + + @Schema(description = "是否需要会务服务(0=不需要 1=需要)") + private String needService; + + @Schema(description = "桌子摆放形态") + private String deskLayout; } \ No newline at end of file diff --git a/pjcloud-integrated/pjcloud-integrated-api/src/main/java/com/bsd/pjcloud/integrated/vo/clean/CleanUserDropdownVo.java b/pjcloud-integrated/pjcloud-integrated-api/src/main/java/com/bsd/pjcloud/integrated/vo/clean/CleanUserDropdownVo.java new file mode 100644 index 000000000..3391008b4 --- /dev/null +++ b/pjcloud-integrated/pjcloud-integrated-api/src/main/java/com/bsd/pjcloud/integrated/vo/clean/CleanUserDropdownVo.java @@ -0,0 +1,29 @@ +package com.bsd.pjcloud.integrated.vo.clean; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 保洁用户下拉列表VO + * + * @author zjf + * @date 2025-01-27 + */ +@Data +@Schema(description = "保洁用户下拉列表") +public class CleanUserDropdownVo { + + @Schema(description = "id") + private Long id; + + @Schema(description = "姓名") + private String name; + + @Schema(description = "手机号") + private String phone; + + + @Schema(description = "1保洁阿姨,2会务人员") + private String type; +} + diff --git a/pjcloud-integrated/pjcloud-integrated-api/src/main/java/com/bsd/pjcloud/integrated/vo/meeting/MeetingBookingPageVo.java b/pjcloud-integrated/pjcloud-integrated-api/src/main/java/com/bsd/pjcloud/integrated/vo/meeting/MeetingBookingPageVo.java index c089a6306..f429deb25 100644 --- a/pjcloud-integrated/pjcloud-integrated-api/src/main/java/com/bsd/pjcloud/integrated/vo/meeting/MeetingBookingPageVo.java +++ b/pjcloud-integrated/pjcloud-integrated-api/src/main/java/com/bsd/pjcloud/integrated/vo/meeting/MeetingBookingPageVo.java @@ -49,4 +49,10 @@ public class MeetingBookingPageVo { @Schema(description = "审核原因") private String checkReason; + + @Schema(description = "是否需要会务服务(0=不需要 1=需要)") + private String needService; + + @Schema(description = "桌子摆放形态") + private String deskLayout; } \ No newline at end of file diff --git a/pjcloud-integrated/pjcloud-integrated-biz/MEETING_BOOKING_FLOW_EXAMPLE.md b/pjcloud-integrated/pjcloud-integrated-biz/MEETING_BOOKING_FLOW_EXAMPLE.md new file mode 100644 index 000000000..22bf7d6ed --- /dev/null +++ b/pjcloud-integrated/pjcloud-integrated-biz/MEETING_BOOKING_FLOW_EXAMPLE.md @@ -0,0 +1,228 @@ +# 会议室预约流程动态审批人实现示例 + +## 📋 概述 + +本文档展示如何在会议室预约的save方法中实现根据会议室管理员字段动态确定审批人的功能。 + +## 🔧 核心修改 + +### 1. 添加必要的依赖注入 + +```java +@RestController +@RequiredArgsConstructor +public class MeetingBookingController { + + private final MeetingBookingService meetingBookingService; + private final MeetingRoomService meetingRoomService; + private final RemoteFlowApiFlowService remoteFlowApiFlowService; + private final RemoteUserService remoteUserService; // 新增:用于获取用户信息 +} +``` + +### 2. 修改save方法中的流程启动部分 + +```java +@PostMapping +@Transactional +public R save(@RequestBody MeetingBookingSaveDto dto) { + // ... 前面的验证逻辑保持不变 ... + + // 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 stringObjectMap = BeanUtil.beanToMap(meetingFlowDto); + + // 🔥 关键:动态设置审批人 - 根据会议室管理员 + List approvers = determineApproversByRoomAdmin(room); + if (!approvers.isEmpty()) { + // 注意:这里的 "approval_node_1" 需要根据实际流程设计中的节点ID调整 + stringObjectMap.put("approval_node_1_assignee_select", approvers); + } + + ProcessInstanceParamDto processInstanceParamDto = new ProcessInstanceParamDto(); + processInstanceParamDto.setFlowId(process.getFlowId()); + processInstanceParamDto.setParamMap(stringObjectMap); + var stringR = remoteFlowApiFlowService.startProcessInstance(processInstanceParamDto); + + // ... 后续逻辑保持不变 ... +} +``` + +### 3. 实现动态审批人确定方法 + +```java +/** + * 根据会议室管理员确定审批人 + * @param room 会议室信息 + * @return 审批人列表 + */ +private List determineApproversByRoomAdmin(MeetingRoomEntity room) { + List approvers = new ArrayList<>(); + + // 1. 优先使用会议室指定的管理员 + if (room.getAdminId() != null) { + try { + // 获取管理员用户信息 + R> userResult = remoteUserService.getUserById(Arrays.asList(room.getAdminId())); + if (userResult.isOk() && !userResult.getData().isEmpty()) { + SysUser adminUser = userResult.getData().get(0); + NodeUser approver = NodeUser.builder() + .id(adminUser.getUserId()) + .name(adminUser.getName()) + .type("user") + .selected(true) + .avatar(adminUser.getAvatar()) + .build(); + approvers.add(approver); + } + } catch (Exception e) { + log.error("获取会议室管理员信息失败: {}", e.getMessage()); + } + } + + // 2. 如果会议室没有管理员,使用部门经理 + if (approvers.isEmpty() && room.getDeptId() != null) { + approvers.addAll(getDeptManagerAsApprovers(room.getDeptId())); + } + + // 3. 如果仍然没有审批人,使用默认审批人 + if (approvers.isEmpty()) { + approvers.addAll(getDefaultApprovers()); + } + + return approvers; +} + +/** + * 获取部门经理作为审批人 + */ +private List getDeptManagerAsApprovers(Long deptId) { + List approvers = new ArrayList<>(); + try { + // 这里需要根据实际的部门服务接口获取部门经理 + // 示例:假设有部门服务可以获取部门经理 + /* + R deptResult = remoteDeptService.getDeptById(deptId); + if (deptResult.isOk() && deptResult.getData() != null) { + SysDept dept = deptResult.getData(); + Long managerId = dept.getManagerId(); + if (managerId != null) { + R> userResult = remoteUserService.getUserById(Arrays.asList(managerId)); + if (userResult.isOk() && !userResult.getData().isEmpty()) { + SysUser manager = userResult.getData().get(0); + NodeUser approver = NodeUser.builder() + .id(manager.getUserId()) + .name(manager.getName()) + .type("user") + .selected(true) + .avatar(manager.getAvatar()) + .build(); + approvers.add(approver); + } + } + } + */ + } catch (Exception e) { + log.error("获取部门经理信息失败: {}", e.getMessage()); + } + return approvers; +} + +/** + * 获取默认审批人 + */ +private List getDefaultApprovers() { + List approvers = new ArrayList<>(); + try { + // 设置系统管理员作为默认审批人 + Long systemAdminId = 1L; // 需要替换为实际的系统管理员ID + NodeUser defaultApprover = NodeUser.builder() + .id(systemAdminId) + .name("系统管理员") + .type("user") + .selected(true) + .build(); + approvers.add(defaultApprover); + } catch (Exception e) { + log.error("获取默认审批人失败: {}", e.getMessage()); + } + return approvers; +} +``` + +## 🎯 关键要点 + +### 1. 流程节点ID配置 +```java +// 这个key的格式是:{节点ID}_assignee_select +stringObjectMap.put("approval_node_1_assignee_select", approvers); +``` +- `approval_node_1` 需要替换为实际流程设计中的审批节点ID +- 节点ID可以在流程设计器中查看 + +### 2. NodeUser对象构建 +```java +NodeUser approver = NodeUser.builder() + .id(adminUser.getUserId()) // 用户ID + .name(adminUser.getName()) // 用户姓名 + .type("user") // 用户类型,固定为"user" + .selected(true) // 是否选中 + .avatar(adminUser.getAvatar()) // 用户头像(可选) + .build(); +``` + +### 3. 审批人优先级 +1. **会议室管理员** - 最高优先级 +2. **部门经理** - 次优先级 +3. **默认审批人** - 兜底方案 + +### 4. 错误处理 +- 所有获取用户信息的操作都有异常处理 +- 确保即使获取审批人失败,流程也能正常启动 +- 使用日志记录错误信息,便于排查问题 + +## 🔄 流程设计配置 + +在流程设计器中,需要将审批节点配置为: +- **分配类型**: `SELF_SELECT` (发起人自选) +- **节点ID**: 与代码中的key保持一致 +- **多实例模式**: 根据需要选择会签/或签/顺签 + +## 📝 使用示例 + +```java +// 会议室预约时,系统会自动: +// 1. 检查会议室是否有管理员 +// 2. 如果有管理员,使用管理员作为审批人 +// 3. 如果没有管理员,使用部门经理 +// 4. 如果都没有,使用系统管理员 + +// 流程启动后,审批人会收到待办任务 +// 审批人可以在流程中看到会议预约的详细信息 +``` + +## ⚠️ 注意事项 + +1. **节点ID一致性**: 确保代码中的节点ID与流程设计中的节点ID一致 +2. **用户服务可用性**: 确保用户服务接口可用,避免获取用户信息失败 +3. **权限控制**: 确保选择的审批人有相应的审批权限 +4. **测试验证**: 建议在测试环境先验证流程是否正常工作 + +## 🚀 扩展功能 + +可以根据业务需求进一步扩展: + +1. **多级审批**: 根据会议室等级设置多级审批 +2. **时间限制**: 根据预约时间长度确定审批人 +3. **部门规则**: 根据部门特殊规则确定审批人 +4. **用户角色**: 根据用户角色确定审批人 diff --git a/pjcloud-integrated/pjcloud-integrated-biz/MEETING_DESK_LAYOUT_API.md b/pjcloud-integrated/pjcloud-integrated-biz/MEETING_DESK_LAYOUT_API.md new file mode 100644 index 000000000..004e315cb --- /dev/null +++ b/pjcloud-integrated/pjcloud-integrated-biz/MEETING_DESK_LAYOUT_API.md @@ -0,0 +1,135 @@ +# 移动端摆放形式选择接口使用说明 + +## 📋 概述 + +本文档介绍移动端预约课程时选择摆放形式的接口使用方法。 + +## 🌐 接口信息 + +### 获取摆放形式列表接口 + +- **接口地址**: `GET /meetingDeskLayout/app/list` +- **请求方式**: GET +- **认证方式**: 无需认证(移动端公开接口) +- **数据格式**: JSON + +## 📡 响应格式 + +### 成功响应 +```json +{ + "code": 0, + "msg": "操作成功", + "data": [ + { + "id": 1, + "layoutName": "U型摆放", + "layoutImage": "https://example.com/images/u-layout.jpg", + "capacityMin": 8, + "capacityMax": 12, + "description": "适合小组讨论的U型摆放方式" + }, + { + "id": 2, + "layoutName": "课桌式摆放", + "layoutImage": "https://example.com/images/classroom-layout.jpg", + "capacityMin": 20, + "capacityMax": 50, + "description": "传统课桌式摆放,适合培训课程" + }, + { + "id": 3, + "layoutName": "圆桌式摆放", + "layoutImage": "https://example.com/images/round-table-layout.jpg", + "capacityMin": 6, + "capacityMax": 10, + "description": "圆桌式摆放,促进互动交流" + } + ] +} +``` + +### 字段说明 + +| 字段名 | 类型 | 说明 | +|--------|------|------| +| id | Long | 摆放形式ID | +| layoutName | String | 摆放形式名称 | +| layoutImage | String | 摆放形式示意图URL | +| capacityMin | Integer | 最小容纳人数 | +| capacityMax | Integer | 最大容纳人数 | +| description | String | 摆放形式描述 | + +## 🔍 业务逻辑说明 + +1. **数据过滤**: 只返回状态为"可用"(isAvailable = "0")的摆放形式 +2. **排序规则**: 按照sortOrder字段升序排列 +3. **数据精简**: 只返回移动端需要的核心字段,减少数据传输量 + +## 📱 使用示例 + +### JavaScript 调用示例 +```javascript +fetch('/meetingDeskLayout/app/list', { + method: 'GET', + headers: { + 'Content-Type': 'application/json' + } +}) +.then(response => response.json()) +.then(data => { + if (data.code === 0) { + // 处理摆放形式数据 + const layouts = data.data; + layouts.forEach(layout => { + console.log(`摆放形式: ${layout.layoutName}, 容纳人数: ${layout.capacityMin}-${layout.capacityMax}人`); + }); + } +}) +.catch(error => { + console.error('获取摆放形式失败:', error); +}); +``` + +### React Native 调用示例 +```javascript +const fetchDeskLayouts = async () => { + try { + const response = await fetch('/meetingDeskLayout/app/list'); + const result = await response.json(); + + if (result.code === 0) { + return result.data; + } else { + throw new Error(result.msg); + } + } catch (error) { + console.error('获取摆放形式失败:', error); + return []; + } +}; +``` + +### cURL 调用示例 +```bash +curl -X GET "http://your-domain/meetingDeskLayout/app/list" \ + -H "Content-Type: application/json" +``` + +## 🎯 应用场景 + +1. **课程预约**: 用户在预约课程时选择适合的摆放形式 +2. **会议室配置**: 根据参会人数推荐合适的摆放形式 +3. **活动策划**: 根据活动类型选择合适的桌椅摆放方式 + +## ⚠️ 注意事项 + +1. **数据一致性**: 接口返回的数据与后台管理系统的摆放形式数据保持一致 +2. **图片加载**: layoutImage字段可能为空,前端需要处理图片加载失败的情况 +3. **容量限制**: 建议根据实际参会人数选择合适的摆放形式 +4. **缓存策略**: 建议前端对摆放形式数据进行适当缓存,减少重复请求 + +## 🔄 版本更新 + +- **v1.0.0** (2025-01-27): 初始版本,提供基本的摆放形式选择功能 + diff --git a/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/constant/IntegratedConstants.java b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/constant/IntegratedConstants.java new file mode 100644 index 000000000..f6616592d --- /dev/null +++ b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/constant/IntegratedConstants.java @@ -0,0 +1,75 @@ +package com.bsd.pjcloud.integrated.constant; + +/** + * 商城相关常量 + * + * @author pjcloud + * @date 2025-01-27 + */ +public interface IntegratedConstants { + + /** + * 会议保洁/会务人员用户类型 + */ + interface MeetingUserType { + /** + * 启用状态 + */ + String BJ_USER = "1"; + + /** + * 禁用状态 + */ + String HW_USER = "2"; + + } + + /** + * 角色相关常量 + */ + interface RoleCode { + /** + * 商户用户角色 + */ + String MERCHANT_USER = "MALL_MCH"; + + /** + * 超市管理员角色 + */ + String SUPERMARKET_ADMIN = "SUPERMARKET_ADMIN"; + } + + + /** + * 商户相关常量 + */ + interface Merchant { + /** + * 商户状态 - 正常 + */ + String STATUS_NORMAL = "1"; + + /** + * 商户状态 - 停用 + */ + String STATUS_DISABLED = "0"; + } + + /** + * 删除标记 + */ + interface DelFlag { + /** + * 正常 + */ + String NORMAL = "0"; + + /** + * 删除 + */ + String DELETED = "1"; + } +} + + + diff --git a/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/controller/CleanUserController.java b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/controller/CleanUserController.java index 14747104b..31ea01dea 100644 --- a/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/controller/CleanUserController.java +++ b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/controller/CleanUserController.java @@ -7,10 +7,12 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.bsd.pjcloud.common.core.util.R; +import com.bsd.pjcloud.common.core.util.BeanUtils; import com.bsd.pjcloud.common.log.annotation.SysLog; import com.bsd.pjcloud.common.security.util.SecurityUtils; import com.bsd.pjcloud.integrated.entity.CleanUserEntity; import com.bsd.pjcloud.integrated.service.CleanUserService; +import com.bsd.pjcloud.integrated.vo.clean.CleanUserDropdownVo; import org.springframework.security.access.prepost.PreAuthorize; import com.bsd.pjcloud.common.excel.annotation.ResponseExcel; import io.swagger.v3.oas.annotations.security.SecurityRequirement; @@ -52,6 +54,7 @@ public class CleanUserController { LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); wrapper.eq(StrUtil.isNotBlank(cleanUser.getName()),CleanUserEntity::getName,cleanUser.getName()); wrapper.eq(StrUtil.isNotBlank(cleanUser.getPhone()),CleanUserEntity::getPhone,cleanUser.getPhone()); + wrapper.eq(CleanUserEntity::getType, cleanUser.getType()); return R.ok(cleanUserService.page(page, wrapper)); } @@ -105,6 +108,15 @@ public class CleanUserController { @DeleteMapping @PreAuthorize("@pms.hasPermission('integrated_cleanUser_del')" ) public R removeById(@RequestBody Long[] ids) { + // 验证要删除的记录是否属于指定的type + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); + wrapper.in(CleanUserEntity::getId, CollUtil.toList(ids)); + List validRecords = cleanUserService.list(wrapper); + + if (validRecords.size() != ids.length) { + return R.failed("部分记录不属于指定类型,无法删除"); + } + return R.ok(cleanUserService.removeBatchByIds(CollUtil.toList(ids))); } @@ -113,13 +125,18 @@ public class CleanUserController { * 导出excel 表格 * @param cleanUser 查询条件 * @param ids 导出指定ID + * @param type 类型:1保洁阿姨,2会务人员 * @return excel 文件流 */ @ResponseExcel @GetMapping("/export") @PreAuthorize("@pms.hasPermission('integrated_cleanUser_export')" ) - public List export(CleanUserEntity cleanUser,Long[] ids) { - return cleanUserService.list(Wrappers.lambdaQuery(cleanUser).in(ArrayUtil.isNotEmpty(ids), CleanUserEntity::getId, ids)); + public List export(CleanUserEntity cleanUser, Long[] ids, + @RequestParam(value = "type", required = false) String type) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(cleanUser); + wrapper.in(ArrayUtil.isNotEmpty(ids), CleanUserEntity::getId, ids); + wrapper.eq(StrUtil.isNotBlank(type), CleanUserEntity::getType, type); + return cleanUserService.list(wrapper); } @@ -130,12 +147,13 @@ public class CleanUserController { @Operation(summary = "获取保洁/会务人员用户下拉列表", description = "获取保洁/会务人员用户下拉列表") @GetMapping("/dropdown") // @PreAuthorize("@pms.hasPermission('integrated_cleanUser_view')") - public R getCleanUserDropdown(@RequestParam("type")String type) { + public R> getCleanUserDropdown(@RequestParam(value = "type",required = false)String type) { LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); - wrapper.eq(CleanUserEntity::getType, type); - wrapper.select(CleanUserEntity::getId, CleanUserEntity::getName, CleanUserEntity::getPhone); + wrapper.eq(type != null,CleanUserEntity::getType, type); +// wrapper.select(CleanUserEntity::getId, CleanUserEntity::getName, CleanUserEntity::getPhone); wrapper.orderByAsc(CleanUserEntity::getName); List list = cleanUserService.list(wrapper); - return R.ok(list); + List voList = BeanUtils.toBean(list, CleanUserDropdownVo.class); + return R.ok(voList); } } \ No newline at end of file diff --git a/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/controller/MeetingBookingController.java b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/controller/MeetingBookingController.java index b7bc3adb7..0742db7e5 100644 --- a/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/controller/MeetingBookingController.java +++ b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/controller/MeetingBookingController.java @@ -100,6 +100,8 @@ public class MeetingBookingController { vo.setCreateTime(e.getCreateTime()); vo.setCreateBy(e.getCreateBy()); vo.setDescription(e.getDescription()); + vo.setNeedService(e.getNeedService()); + vo.setDeskLayout(e.getDeskLayout()); return vo; }).toList(); @@ -140,6 +142,8 @@ public class MeetingBookingController { meetingBooking.setBookingDate(LocalDate.parse(dto.getBookingDate())); meetingBooking.setStartTime(LocalTime.parse(dto.getStartTime())); meetingBooking.setEndTime(LocalTime.parse(dto.getEndTime())); + meetingBooking.setNeedService(dto.getNeedService()); + meetingBooking.setDeskLayout(dto.getDeskLayout()); // 2. 验证会议室是否存在 MeetingRoomEntity room = meetingRoomService.getById(meetingBooking.getRoomId()); if (room == null) { @@ -184,7 +188,8 @@ public class MeetingBookingController { // 7. 发起流程 var processByBusinessKey = remoteFlowApiFlowService.getProcessByBusinessKey(IntegratedFlowConstant.INTEGRATED_MEETING_BOOKING); if (!processByBusinessKey.isOk() || processByBusinessKey.getData() == null) { - throw new ServiceException("流程配置获取失败: " + processByBusinessKey.getMsg()); +// throw new ServiceException("流程配置获取失败: " + processByBusinessKey.getMsg()); + return R.failed("流程配置获取失败"); } Process process = processByBusinessKey.getData(); MeetingFlowDto meetingFlowDto = new MeetingFlowDto(); diff --git a/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/controller/MeetingDeskLayoutController.java b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/controller/MeetingDeskLayoutController.java new file mode 100644 index 000000000..8a5de4465 --- /dev/null +++ b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/controller/MeetingDeskLayoutController.java @@ -0,0 +1,143 @@ +package com.bsd.pjcloud.integrated.controller; + +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.collection.CollUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.bsd.pjcloud.common.core.util.R; +import com.bsd.pjcloud.common.log.annotation.SysLog; +import com.bsd.pjcloud.integrated.entity.MeetingDeskLayoutEntity; +import com.bsd.pjcloud.integrated.service.MeetingDeskLayoutService; +import com.bsd.pjcloud.integrated.vo.MeetingDeskLayoutAppVO; +import com.bsd.pjcloud.common.core.util.BeanUtils; +import org.springframework.security.access.prepost.PreAuthorize; +import com.bsd.pjcloud.common.excel.annotation.ResponseExcel; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import org.springdoc.core.annotations.ParameterObject; +import org.springframework.http.HttpHeaders; +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 java.util.List; +import java.util.Objects; + +/** + * 摆放形式 + * + * @author zjf + * @date 2025-09-10 12:56:45 + */ +@RestController +@RequiredArgsConstructor +@RequestMapping("/meetingDeskLayout" ) +@Tag(description = "meetingDeskLayout" , name = "摆放形式管理" ) +@SecurityRequirement(name = HttpHeaders.AUTHORIZATION) +public class MeetingDeskLayoutController { + + private final MeetingDeskLayoutService meetingDeskLayoutService; + + /** + * 分页查询 + * @param page 分页对象 + * @param meetingDeskLayout 摆放形式 + * @return + */ + @Operation(summary = "分页查询" , description = "分页查询" ) + @GetMapping("/page" ) + @PreAuthorize("@pms.hasPermission('integrated_meetingDeskLayout_view')" ) + public R getMeetingDeskLayoutPage(@ParameterObject Page page, @ParameterObject MeetingDeskLayoutEntity meetingDeskLayout) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); + return R.ok(meetingDeskLayoutService.page(page, wrapper)); + } + + + /** + * 通过id查询摆放形式 + * @param id id + * @return R + */ + @Operation(summary = "通过id查询" , description = "通过id查询" ) + @GetMapping("/{id}" ) + @PreAuthorize("@pms.hasPermission('integrated_meetingDeskLayout_view')" ) + public R getById(@PathVariable("id" ) Long id) { + return R.ok(meetingDeskLayoutService.getById(id)); + } + + /** + * 新增摆放形式 + * @param meetingDeskLayout 摆放形式 + * @return R + */ + @Operation(summary = "新增摆放形式" , description = "新增摆放形式" ) + @SysLog("新增摆放形式" ) + @PostMapping + @PreAuthorize("@pms.hasPermission('integrated_meetingDeskLayout_add')" ) + public R save(@RequestBody MeetingDeskLayoutEntity meetingDeskLayout) { + return R.ok(meetingDeskLayoutService.save(meetingDeskLayout)); + } + + /** + * 修改摆放形式 + * @param meetingDeskLayout 摆放形式 + * @return R + */ + @Operation(summary = "修改摆放形式" , description = "修改摆放形式" ) + @SysLog("修改摆放形式" ) + @PutMapping + @PreAuthorize("@pms.hasPermission('integrated_meetingDeskLayout_edit')" ) + public R updateById(@RequestBody MeetingDeskLayoutEntity meetingDeskLayout) { + return R.ok(meetingDeskLayoutService.updateById(meetingDeskLayout)); + } + + /** + * 通过id删除摆放形式 + * @param ids id列表 + * @return R + */ + @Operation(summary = "通过id删除摆放形式" , description = "通过id删除摆放形式" ) + @SysLog("通过id删除摆放形式" ) + @DeleteMapping + @PreAuthorize("@pms.hasPermission('integrated_meetingDeskLayout_del')" ) + public R removeById(@RequestBody Long[] ids) { + return R.ok(meetingDeskLayoutService.removeBatchByIds(CollUtil.toList(ids))); + } + + + /** + * 导出excel 表格 + * @param meetingDeskLayout 查询条件 + * @param ids 导出指定ID + * @return excel 文件流 + */ + @ResponseExcel + @GetMapping("/export") + @PreAuthorize("@pms.hasPermission('integrated_meetingDeskLayout_export')" ) + public List export(MeetingDeskLayoutEntity meetingDeskLayout,Long[] ids) { + return meetingDeskLayoutService.list(Wrappers.lambdaQuery(meetingDeskLayout).in(ArrayUtil.isNotEmpty(ids), MeetingDeskLayoutEntity::getId, ids)); + } + + + + //----------------------------------APP---------------------------------*/ + /** + * 移动端获取可用的摆放形式列表 + * @return R + */ + @Operation(summary = "移动端获取摆放形式列表", description = "移动端预约课程时选择摆放形式") + @GetMapping("/app/list") + public R> getAppLayoutList() { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); + // 只查询可用的摆放形式 + wrapper.eq(MeetingDeskLayoutEntity::getIsAvailable, "0"); + // 按排序字段排序 + wrapper.orderByAsc(MeetingDeskLayoutEntity::getSortOrder); + + List entityList = meetingDeskLayoutService.list(wrapper); + List voList = BeanUtils.toBean(entityList, MeetingDeskLayoutAppVO.class); + + return R.ok(voList); + } +} \ No newline at end of file diff --git a/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/controller/MeetingRoomController.java b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/controller/MeetingRoomController.java index c2ec1551c..f4917a742 100644 --- a/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/controller/MeetingRoomController.java +++ b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/controller/MeetingRoomController.java @@ -320,7 +320,8 @@ public class MeetingRoomController { //发起流程 R processByBusinessKey = remoteFlowApiFlowService.getProcessByBusinessKey(IntegratedFlowConstant.INTEGRATED_MEETING_BOOKING); if (!processByBusinessKey.isOk() || processByBusinessKey.getData() == null) { - throw new ServiceException("流程配置获取失败: " + processByBusinessKey.getMsg()); +// throw new ServiceException("流程配置获取失败: " + processByBusinessKey.getMsg()); + return R.failed("流程配置获取失败"); } Process process = processByBusinessKey.getData(); diff --git a/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/entity/MeetingBookingEntity.java b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/entity/MeetingBookingEntity.java index 2f54aec98..b87c3bbb5 100644 --- a/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/entity/MeetingBookingEntity.java +++ b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/entity/MeetingBookingEntity.java @@ -143,4 +143,16 @@ public class MeetingBookingEntity extends Model { @Schema(description = "审批原因") private String checkReason; + /** + * 是否需要会务服务(0=不需要 1=需要) + */ + @Schema(description = "是否需要会务服务(0=不需要 1=需要)") + private String needService; + + /** + * 桌子摆放形态 + */ + @Schema(description = "桌子摆放形态") + private String deskLayout; + } \ No newline at end of file diff --git a/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/entity/MeetingDeskLayoutEntity.java b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/entity/MeetingDeskLayoutEntity.java new file mode 100644 index 000000000..61533a2bf --- /dev/null +++ b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/entity/MeetingDeskLayoutEntity.java @@ -0,0 +1,133 @@ +package com.bsd.pjcloud.integrated.entity; + +import com.baomidou.mybatisplus.annotation.*; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import com.bsd.pjcloud.common.core.util.TenantTable; +import java.time.LocalDateTime; + +/** + * 摆放形式 + * + * @author zjf + * @date 2025-09-10 12:56:45 + */ +@Data +@TenantTable +@TableName("meeting_desk_layout") +@EqualsAndHashCode(callSuper = true) +@Schema(description = "摆放形式") +public class MeetingDeskLayoutEntity extends Model { + + + /** + * 编号 + */ + @TableId(type = IdType.ASSIGN_ID) + @Schema(description="编号") + private Long id; + + /** + * 摆放形式名称 + */ + @Schema(description="摆放形式名称") + private String layoutName; + + /** + * 摆放形式编码 + */ + @Schema(description="摆放形式编码") + private String layoutCode; + + /** + * 摆放形式描述 + */ + @Schema(description="摆放形式描述") + private String description; + + /** + * 最小容纳人数 + */ + @Schema(description="最小容纳人数") + private Integer capacityMin; + + /** + * 最大容纳人数 + */ + @Schema(description="最大容纳人数") + private Integer capacityMax; + + /** + * 摆放形式示意图 + */ + @Schema(description="摆放形式示意图") + private String layoutImage; + + /** + * 布置所需时间(分钟) + */ + @Schema(description="布置所需时间(分钟)") + private Integer setupTime; + + /** + * 是否可用(0=可用 1=不可用) + */ + @Schema(description="是否可用(0=可用 1=不可用)") + private String isAvailable; + + /** + * 排序 + */ + @Schema(description="排序") + private Integer sortOrder; + + /** + * 备注 + */ + @Schema(description="备注") + private String remark; + + /** + * 创建人 + */ + @TableField(fill = FieldFill.INSERT) + @Schema(description="创建人") + private String createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + @Schema(description="创建时间") + private LocalDateTime createTime; + + /** + * 修改人 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + @Schema(description="修改人") + private String updateBy; + + /** + * 修改时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + @Schema(description="修改时间") + private LocalDateTime updateTime; + + /** + * 删除标记 + */ + @TableLogic + @TableField(fill = FieldFill.INSERT) + @Schema(description="删除标记") + private String delFlag; + + /** + * 租户ID + */ + @Schema(description="租户ID") + private Long tenantId; +} \ No newline at end of file diff --git a/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/entity/MeetingRoomEquipmentEntity.java b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/entity/MeetingRoomEquipmentEntity.java index 3ef964314..6444b66ee 100644 --- a/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/entity/MeetingRoomEquipmentEntity.java +++ b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/entity/MeetingRoomEquipmentEntity.java @@ -16,7 +16,7 @@ import java.time.LocalDateTime; */ @Data @TenantTable -@TableName("meeting__room_equipment") +@TableName("meeting_room_equipment") @EqualsAndHashCode(callSuper = true) @Schema(description = "设备会议室关联表") public class MeetingRoomEquipmentEntity extends Model { diff --git a/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/mapper/MeetingDeskLayoutMapper.java b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/mapper/MeetingDeskLayoutMapper.java new file mode 100644 index 000000000..6796656c3 --- /dev/null +++ b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/mapper/MeetingDeskLayoutMapper.java @@ -0,0 +1,11 @@ +package com.bsd.pjcloud.integrated.mapper; + +import com.bsd.pjcloud.common.data.datascope.PjcloudBaseMapper; +import com.bsd.pjcloud.integrated.entity.MeetingDeskLayoutEntity; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface MeetingDeskLayoutMapper extends PjcloudBaseMapper { + + +} \ No newline at end of file diff --git a/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/service/MeetingDeskLayoutService.java b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/service/MeetingDeskLayoutService.java new file mode 100644 index 000000000..6aa2dca25 --- /dev/null +++ b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/service/MeetingDeskLayoutService.java @@ -0,0 +1,8 @@ +package com.bsd.pjcloud.integrated.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.bsd.pjcloud.integrated.entity.MeetingDeskLayoutEntity; + +public interface MeetingDeskLayoutService extends IService { + +} \ No newline at end of file diff --git a/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/service/impl/MeetingDeskLayoutServiceImpl.java b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/service/impl/MeetingDeskLayoutServiceImpl.java new file mode 100644 index 000000000..bac2495ea --- /dev/null +++ b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/service/impl/MeetingDeskLayoutServiceImpl.java @@ -0,0 +1,16 @@ +package com.bsd.pjcloud.integrated.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.bsd.pjcloud.integrated.entity.MeetingDeskLayoutEntity; +import com.bsd.pjcloud.integrated.mapper.MeetingDeskLayoutMapper; +import com.bsd.pjcloud.integrated.service.MeetingDeskLayoutService; +import org.springframework.stereotype.Service; +/** + * 摆放形式 + * + * @author zjf + * @date 2025-09-10 12:56:45 + */ +@Service +public class MeetingDeskLayoutServiceImpl extends ServiceImpl implements MeetingDeskLayoutService { +} \ No newline at end of file diff --git a/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/vo/MeetingDeskLayoutAppVO.java b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/vo/MeetingDeskLayoutAppVO.java new file mode 100644 index 000000000..6bae17658 --- /dev/null +++ b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/vo/MeetingDeskLayoutAppVO.java @@ -0,0 +1,56 @@ +package com.bsd.pjcloud.integrated.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +/** + * 移动端摆放形式选择VO + * + * @author zjf + * @date 2025-01-27 + */ +@Data +@Schema(description = "移动端摆放形式选择VO") +public class MeetingDeskLayoutAppVO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @Schema(description = "编号") + private Long id; + + /** + * 摆放形式名称 + */ + @Schema(description = "摆放形式名称") + private String layoutName; + + /** + * 摆放形式示意图 + */ + @Schema(description = "摆放形式示意图") + private String layoutImage; + + /** + * 最小容纳人数 + */ + @Schema(description = "最小容纳人数") + private Integer capacityMin; + + /** + * 最大容纳人数 + */ + @Schema(description = "最大容纳人数") + private Integer capacityMax; + + /** + * 摆放形式描述 + */ + @Schema(description = "摆放形式描述") + private String description; +} + diff --git a/pjcloud-integrated/pjcloud-integrated-biz/src/main/resources/mapper/MeetingBookingMapper.xml b/pjcloud-integrated/pjcloud-integrated-biz/src/main/resources/mapper/MeetingBookingMapper.xml index b82fabfc3..755d43be2 100644 --- a/pjcloud-integrated/pjcloud-integrated-biz/src/main/resources/mapper/MeetingBookingMapper.xml +++ b/pjcloud-integrated/pjcloud-integrated-biz/src/main/resources/mapper/MeetingBookingMapper.xml @@ -24,6 +24,8 @@ + +