diff --git a/db/mall_merchant_user.sql b/db/mall_merchant_user.sql new file mode 100644 index 000000000..1419957d6 --- /dev/null +++ b/db/mall_merchant_user.sql @@ -0,0 +1,21 @@ +-- 商户用户绑定表 +CREATE TABLE `mall_merchant_user` ( + `id` bigint(20) NOT NULL COMMENT '主键ID', + `merchant_id` bigint(20) NOT NULL COMMENT '商户ID', + `user_id` bigint(20) NOT NULL COMMENT '用户ID', + `user_name` varchar(50) DEFAULT NULL COMMENT '用户名称', + `user_phone` varchar(20) DEFAULT NULL COMMENT '用户手机号', + `role_type` tinyint(2) NOT NULL DEFAULT '1' COMMENT '角色类型(1:管理员 2:普通用户)', + `status` tinyint(2) NOT NULL DEFAULT '1' COMMENT '状态(1:启用 0:禁用)', + `create_by` varchar(50) DEFAULT NULL COMMENT '创建者', + `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_by` varchar(50) DEFAULT NULL COMMENT '更新者', + `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `del_flag` char(1) DEFAULT '0' COMMENT '是否删除(0=正常 1=删除)', + `tenant_id` bigint(20) DEFAULT NULL COMMENT '租户编号', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_merchant_user` (`merchant_id`, `user_id`, `del_flag`), + KEY `idx_user_id` (`user_id`), + KEY `idx_merchant_id` (`merchant_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商户用户绑定表'; + diff --git a/extract_product_codes.py b/extract_product_codes.py new file mode 100644 index 000000000..ccd86e248 --- /dev/null +++ b/extract_product_codes.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Excel货号提取工具 +从Excel文件中提取货号并生成删除SQL +""" + +import pandas as pd +import sys +from pathlib import Path + +def extract_product_codes_and_generate_sql(excel_file_path): + """ + 从Excel文件提取货号并生成删除SQL + """ + try: + # 读取Excel文件 + print(f"正在读取Excel文件: {excel_file_path}") + + # 尝试读取第一个工作表 + df = pd.read_excel(excel_file_path, sheet_name=0) + + print(f"Excel文件包含 {len(df)} 行数据") + print("列名:", list(df.columns)) + + # 寻找货号列 + product_code_column = None + possible_columns = ['货号', 'productCode', 'product_code', '商品编码', '编码'] + + for col in df.columns: + if any(keyword in str(col) for keyword in possible_columns): + product_code_column = col + break + + if product_code_column is None: + print("未找到货号列,请检查Excel文件格式") + print("可用的列:", list(df.columns)) + return + + print(f"找到货号列: {product_code_column}") + + # 提取货号 + product_codes = df[product_code_column].dropna().astype(str).tolist() + product_codes = [code.strip() for code in product_codes if code.strip()] + + print(f"共提取到 {len(product_codes)} 个货号") + + if not product_codes: + print("没有找到有效的货号数据") + return + + # 生成SQL语句 + generate_delete_sql(product_codes) + + except Exception as e: + print(f"处理Excel文件时出错: {str(e)}") + +def generate_delete_sql(product_codes): + """ + 生成删除SQL语句 + """ + # 格式化货号列表 + formatted_codes = [f"'{code}'" for code in product_codes] + codes_str = ',\n '.join(formatted_codes) + + sql_template = f""" +-- 根据货号删除商品及相关数据的SQL语句 +-- 总共 {len(product_codes)} 个货号 + +-- 1. 首先查询要删除的商品ID (用于确认) +SELECT id, product_code, product_name +FROM sm_erp_spu +WHERE product_code IN ( + {codes_str} +); + +-- 2. 删除相关的辅助条码数据 +DELETE FROM sm_erp_auxiliary_code +WHERE spu_id IN ( + SELECT id FROM sm_erp_spu WHERE product_code IN ( + {codes_str} + ) +); + +-- 3. 删除相关的单位数据 +DELETE FROM sm_erp_unit +WHERE spu_id IN ( + SELECT id FROM sm_erp_spu WHERE product_code IN ( + {codes_str} + ) +); + +-- 4. 删除相关的库存数据 +DELETE FROM sm_erp_stock +WHERE erp_spu_id IN ( + SELECT id FROM sm_erp_spu WHERE product_code IN ( + {codes_str} + ) +); + +-- 5. 最后删除商品主表数据 +DELETE FROM sm_erp_spu +WHERE product_code IN ( + {codes_str} +); + +-- 货号列表: +{chr(10).join([f"-- {i+1}. {code}" for i, code in enumerate(product_codes)])} +""" + + # 保存到文件 + with open('delete_products.sql', 'w', encoding='utf-8') as f: + f.write(sql_template) + + print("SQL语句已生成并保存到 delete_products.sql 文件") + print("\n" + "="*50) + print(sql_template) + +if __name__ == "__main__": + # Excel文件路径 + excel_file = "pjcloud-supermarket/pjcloud-supermarket-biz/青少年宫.111xls.xls" + + if not Path(excel_file).exists(): + print(f"Excel文件不存在: {excel_file}") + sys.exit(1) + + extract_product_codes_and_generate_sql(excel_file) \ No newline at end of file diff --git a/pjcloud-common/pjcloud-common-core/pom.xml b/pjcloud-common/pjcloud-common-core/pom.xml index 673557583..a63e04bf3 100644 --- a/pjcloud-common/pjcloud-common-core/pom.xml +++ b/pjcloud-common/pjcloud-common-core/pom.xml @@ -77,5 +77,6 @@ io.swagger.core.v3 swagger-annotations-jakarta + diff --git a/pjcloud-common/pjcloud-common-core/src/main/java/com/bsd/pjcloud/common/core/exception/ErrorCodes.java b/pjcloud-common/pjcloud-common-core/src/main/java/com/bsd/pjcloud/common/core/exception/ErrorCodes.java index c2603dd21..71a4a027f 100644 --- a/pjcloud-common/pjcloud-common-core/src/main/java/com/bsd/pjcloud/common/core/exception/ErrorCodes.java +++ b/pjcloud-common/pjcloud-common-core/src/main/java/com/bsd/pjcloud/common/core/exception/ErrorCodes.java @@ -110,4 +110,6 @@ public interface ErrorCodes { */ String APP_USER_USERINFO_EMPTY = "app.user.userInfo.empty"; + + } diff --git a/pjcloud-integrated/pjcloud-integrated-api/src/main/java/com/bsd/pjcloud/integrated/constant/IntegratedConstants.java b/pjcloud-integrated/pjcloud-integrated-api/src/main/java/com/bsd/pjcloud/integrated/constant/IntegratedConstants.java new file mode 100644 index 000000000..c1b87c2b3 --- /dev/null +++ b/pjcloud-integrated/pjcloud-integrated-api/src/main/java/com/bsd/pjcloud/integrated/constant/IntegratedConstants.java @@ -0,0 +1,111 @@ +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 MCH_USER = "MCH_USER"; + + /** + * 超市管理员角色 + */ + String SUPERMARKET_ADMIN = "SUPERMARKET_ADMIN"; + } + + + /** + * 商户相关常量 + */ + interface Merchant { + /** + * 商户状态 - 正常 + */ + String STATUS_NORMAL = "1"; + + /** + * 商户状态 - 停用 + */ + String STATUS_DISABLED = "0"; + } + + /** + * 删除标记 + */ + interface DelFlag { + /** + * 正常 + */ + String NORMAL = "0"; + + /** + * 删除 + */ + String DELETED = "1"; + } + + /** + * 会议室状态 + */ + interface MeetingRoomStatus { + /** + * 维护中 + */ + String MAINTENANCE = "1"; + + /** + * 可用 + */ + String AVAILABLE = "0"; + } + + /** + * 会务服务需求 + */ + interface NeedService { + /** + * 不需要 + */ + String NO = "0"; + + /** + * 需要 + */ + String YES = "1"; + } + +} + + + 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-api/src/main/java/com/bsd/pjcloud/integrated/vo/meeting/app/MeetingBookingDetailVo.java b/pjcloud-integrated/pjcloud-integrated-api/src/main/java/com/bsd/pjcloud/integrated/vo/meeting/app/MeetingBookingDetailVo.java new file mode 100644 index 000000000..dbf53d39b --- /dev/null +++ b/pjcloud-integrated/pjcloud-integrated-api/src/main/java/com/bsd/pjcloud/integrated/vo/meeting/app/MeetingBookingDetailVo.java @@ -0,0 +1,198 @@ +package com.bsd.pjcloud.integrated.vo.meeting.app; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; + +/** + * 会议预约详情VO + * + * @author zjf + * @date 2025-01-17 + */ +@Data +@Schema(description = "会议预约详情VO") +public class MeetingBookingDetailVo { + + /** + * 预约ID + */ + @Schema(description = "预约ID") + private Long id; + + /** + * 会议主题 + */ + @Schema(description = "会议主题") + private String title; + + /** + * 会议室ID + */ + @Schema(description = "会议室ID") + private Long roomId; + + /** + * 会议室名称 + */ + @Schema(description = "会议室名称") + private String roomName; + + /** + * 会议室位置 + */ + @Schema(description = "会议室位置") + private String roomLocation; + + /** + * 会议室容量 + */ + @Schema(description = "会议室容量") + private Integer roomCapacity; + + /** + * 会议室设备 + */ + @Schema(description = "会议室设备") + private String roomEquipment; + + /** + * 会议室图片URL + */ + @Schema(description = "会议室图片URL") + private String roomPicUrl; + + /** + * 会议室描述 + */ + @Schema(description = "会议室描述") + private String roomDescription; + + /** + * 会议室状态 + */ + @Schema(description = "会议室状态") + private String roomStatus; + + /** + * 会议室状态描述 + */ + @Schema(description = "会议室状态描述") + private String roomStatusText; + + /** + * 会议说明 + */ + @Schema(description = "会议说明") + private String description; + + /** + * 审批状态 + */ + @Schema(description = "审批状态") + private String checkStatus; + + /** + * 审批状态描述 + */ + @Schema(description = "审批状态描述") + private String checkStatusText; + + /** + * 审批原因 + */ + @Schema(description = "审批原因") + private String checkReason; + + /** + * 申请人ID + */ + @Schema(description = "申请人ID") + private Long applicantId; + + /** + * 申请人姓名 + */ + @Schema(description = "申请人姓名") + private String applicantName; + + /** + * 会议负责人 + */ + @Schema(description = "会议负责人") + private String assigneeName; + + /** + * 预约日期 + */ + @Schema(description = "预约日期") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private LocalDate bookingDate; + + /** + * 开始时间 + */ + @Schema(description = "开始时间") + @JsonFormat(pattern = "HH:mm", timezone = "GMT+8") + private LocalTime startTime; + + /** + * 结束时间 + */ + @Schema(description = "结束时间") + @JsonFormat(pattern = "HH:mm", timezone = "GMT+8") + private LocalTime endTime; + + /** + * 会议时长(分钟) + */ + @Schema(description = "会议时长(分钟)") + private Integer duration; + + /** + * 是否需要会务服务(0=不需要 1=需要) + */ + @Schema(description = "是否需要会务服务(0=不需要 1=需要)") + private String needService; + + /** + * 是否需要会务服务描述 + */ + @Schema(description = "是否需要会务服务描述") + private String needServiceText; + + /** + * 桌子摆放形态 + */ + @Schema(description = "桌子摆放形态") + private String deskLayout; + + /** + * 桌子摆放形态描述 + */ + @Schema(description = "桌子摆放形态描述") + private String deskLayoutText; + + /** + * 是否确认结束 + */ + @Schema(description = "是否确认结束") + private Integer isConfirmEnd; + + /** + * 创建人 + */ + @Schema(description = "创建人") + private String createBy; + + /** + * 创建时间 + */ + @Schema(description = "创建时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime createTime; +} diff --git a/pjcloud-integrated/pjcloud-integrated-api/src/main/java/com/bsd/pjcloud/integrated/vo/meeting/app/MeetingBookingListVo.java b/pjcloud-integrated/pjcloud-integrated-api/src/main/java/com/bsd/pjcloud/integrated/vo/meeting/app/MeetingBookingListVo.java new file mode 100644 index 000000000..533394111 --- /dev/null +++ b/pjcloud-integrated/pjcloud-integrated-api/src/main/java/com/bsd/pjcloud/integrated/vo/meeting/app/MeetingBookingListVo.java @@ -0,0 +1,158 @@ +package com.bsd.pjcloud.integrated.vo.meeting.app; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; + +/** + * 我的预约列表VO + * + * @author zjf + * @date 2025-01-17 + */ +@Data +@Schema(description = "我的预约列表VO") +public class MeetingBookingListVo { + + /** + * id + */ + @Schema(description = "预约ID") + private Long id; + + /** + * 会议主题 + */ + @Schema(description = "会议主题") + private String title; + + /** + * 会议室id + */ + @Schema(description = "会议室ID") + private Long roomId; + + /** + * 会议室名称 + */ + @Schema(description = "会议室名称") + private String roomName; + + /** + * 会议说明 + */ + @Schema(description = "会议说明") + private String description; + + /** + * 审批状态 + */ + @Schema(description = "审批状态") + private String checkStatus; + + /** + * 审批状态描述 + */ + @Schema(description = "审批状态描述") + private String checkStatusText; + + /** + * 部门id + */ + @Schema(description = "部门ID") + private Long deptId; + + /** + * 部门名称 + */ + @Schema(description = "部门名称") + private String deptName; + + /** + * 申请人 + */ + @Schema(description = "申请人ID") + private Long applicantId; + + /** + * 申请人姓名 + */ + @Schema(description = "申请人姓名") + private String applicantName; + + /** + * 会议负责人 + */ + @Schema(description = "会议负责人") + private String assigneeName; + + /** + * 预约日期 + */ + @Schema(description = "预约日期") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private LocalDate bookingDate; + + /** + * 开始时间 + */ + @Schema(description = "开始时间") + @JsonFormat(pattern = "HH:mm", timezone = "GMT+8") + private LocalTime startTime; + + /** + * 结束时间 + */ + @Schema(description = "结束时间") + @JsonFormat(pattern = "HH:mm", timezone = "GMT+8") + private LocalTime endTime; + + /** + * 会议时长(分钟) + */ + @Schema(description = "会议时长(分钟)") + private Integer duration; + + /** + * 是否需要会务服务(0=不需要 1=需要) + */ + @Schema(description = "是否需要会务服务(0=不需要 1=需要)") + private String needService; + + /** + * 桌子摆放形态 + */ + @Schema(description = "桌子摆放形态") + private String deskLayout; + + /** + * 审批原因 + */ + @Schema(description = "审批原因") + private String checkReason; + + /** + * 是否确认结束 + */ + @Schema(description = "是否确认结束") + private Integer isConfirmEnd; + + /** + * 创建时间 + */ + @Schema(description = "创建时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime createTime; + + /** + * 更新时间 + */ + @Schema(description = "更新时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime updateTime; +} + diff --git a/pjcloud-integrated/pjcloud-integrated-api/src/main/java/com/bsd/pjcloud/integrated/vo/meeting/app/MeetingBookingReqVo.java b/pjcloud-integrated/pjcloud-integrated-api/src/main/java/com/bsd/pjcloud/integrated/vo/meeting/app/MeetingBookingReqVo.java index 35e12e16e..779535412 100644 --- a/pjcloud-integrated/pjcloud-integrated-api/src/main/java/com/bsd/pjcloud/integrated/vo/meeting/app/MeetingBookingReqVo.java +++ b/pjcloud-integrated/pjcloud-integrated-api/src/main/java/com/bsd/pjcloud/integrated/vo/meeting/app/MeetingBookingReqVo.java @@ -30,4 +30,10 @@ public class MeetingBookingReqVo { @Schema(description = "参会人员ID列表") private List attendees; + + @Schema(description = "桌子摆放形态") + private String deskLayout; + + @Schema(description = "是否需要会务服务") + private String needService; } \ No newline at end of file diff --git a/pjcloud-integrated/pjcloud-integrated-api/src/main/java/com/bsd/pjcloud/integrated/vo/visitor/app/VisitorsAppYYDetailVo.java b/pjcloud-integrated/pjcloud-integrated-api/src/main/java/com/bsd/pjcloud/integrated/vo/visitor/app/VisitorsAppYYDetailVo.java new file mode 100644 index 000000000..8bd840335 --- /dev/null +++ b/pjcloud-integrated/pjcloud-integrated-api/src/main/java/com/bsd/pjcloud/integrated/vo/visitor/app/VisitorsAppYYDetailVo.java @@ -0,0 +1,124 @@ +package com.bsd.pjcloud.integrated.vo.visitor.app; + +import com.bsd.pjcloud.integrated.dto.visitor.app.VisitorsCarAppDTO; +import com.bsd.pjcloud.integrated.dto.visitor.app.VisitorsPeopleAppDTO; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 访客表 + * + * @author zjf + * @date 2025-04-09 15:22:47 + */ +@Data +@Schema(description = "app邀约详情vo") +public class VisitorsAppYYDetailVo { + + + /** + * 姓名 + */ + @Schema(description="姓名") + @NotNull + private String name; + + /** + * 手机号 + */ + @NotNull + @Schema(description="手机号") + private String mobile; + + /** + * 身份证号 + */ + @Schema(description="身份证号") + private String idCard; + + /** + * 描述 + */ + @Schema(description="描述") + private String reasonValue; + + + /** + * 到访单位 + */ + @Schema(description="到访单位id") + private Long deptId; + + /** + * 到访单位 + */ + @Schema(description="到访单位") + private String deptName; + + + /** + * 接待人 + */ + @Schema(description="接待人") + private String userName; + + + /** + * 公司名称 + */ + @Schema(description="公司名称") + private String companyName; + + /** + * 随行人员数量 + */ + @Schema(description="随行人员数量") + private Integer peopleNumber; + + + /** + * 到访时间 + */ + @Schema(description="到访时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime vStartDate; + /** + * 到访时间 + */ + @Schema(description="到访时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime vEndDate; + + /** + * 是否驾驶车辆0 否 1是 + */ + @Schema(description="是否驾驶车辆0 否 1是") + private String isDrive; + + /** + * 是否驾驶车辆0 否 1是 + */ + @Schema(description="是否有随行人员 0 否 1是") + private String isOtherPeople; + + @Schema(description="接待人id") + private Long receiveId; + + + @Schema(description="车牌号集合") + private List carList; + + @Schema(description="随行人员集合") + private List otherPeople; + + + +// @Schema(description="邀约id") +// private Long yyId; + +} \ 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..ee0d9e51a --- /dev/null +++ b/pjcloud-integrated/pjcloud-integrated-biz/MEETING_BOOKING_FLOW_EXAMPLE.md @@ -0,0 +1,230 @@ +# 会议室预约流程动态审批人实现示例 + +## 📋 概述 + +本文档展示如何在会议室预约的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..81ae2b52d --- /dev/null +++ b/pjcloud-integrated/pjcloud-integrated-biz/MEETING_DESK_LAYOUT_API.md @@ -0,0 +1,137 @@ +# 移动端摆放形式选择接口使用说明 + +## 📋 概述 + +本文档介绍移动端预约课程时选择摆放形式的接口使用方法。 + +## 🌐 接口信息 + +### 获取摆放形式列表接口 + +- **接口地址**: `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/controller/AppVisitorController.java b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/controller/AppVisitorController.java index f8f898c9c..790017a81 100644 --- a/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/controller/AppVisitorController.java +++ b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/controller/AppVisitorController.java @@ -19,6 +19,7 @@ import com.bsd.pjcloud.integrated.entity.VisitorsEntity; import com.bsd.pjcloud.integrated.service.VisitorUserService; import com.bsd.pjcloud.integrated.service.VisitorsService; import com.bsd.pjcloud.integrated.vo.visitor.app.VisitorsAppVo; +import com.bsd.pjcloud.integrated.vo.visitor.app.VisitorsAppYYDetailVo; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.tags.Tag; @@ -107,6 +108,20 @@ public class AppVisitorController { return R.ok(visitorsService.getByToken(token)); } + + /** + * 邀约详情 + * + * @param token + * @return + */ + @Operation(summary = "通过token查询邀约详情" , description = "通过token查询邀约详情" ) + @GetMapping("/get/visitorsYYDetail") + public R getVisitorsYYDetail(@RequestParam("token") String token) { + + return R.ok(visitorsService.getVisitorsYYDetail(token)); + } + @PostMapping("/app/receiveYY") @SysLog("访客接收邀约更新状态" ) @Operation(summary = "访客接收邀约" , description = "访客接收邀约" ) 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/FeedbackController.java b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/controller/FeedbackController.java index c027a33b0..f22d1bc60 100644 --- a/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/controller/FeedbackController.java +++ b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/controller/FeedbackController.java @@ -24,6 +24,7 @@ import io.swagger.v3.oas.annotations.Operation; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; import com.bsd.pjcloud.integrated.vo.feedback.FeedbackScreenVo; +import com.bsd.pjcloud.integrated.vo.FeedbackTypeVO; import java.util.stream.Collectors; import java.util.HashMap; @@ -185,8 +186,20 @@ public class FeedbackController { @Operation(summary = "获取反馈类型" , description = "获取反馈类型" ) @GetMapping("/app/getFeedbackType" ) - public R getFeedbackType() { - return R.ok(remoteDictService.getDictByType("feedback_type")); + public R> getFeedbackType() { + R> dictResult = remoteDictService.getDictByType("feedback_type"); + if (!dictResult.isOk() || dictResult.getData() == null) { + return R.failed("获取反馈类型失败"); + } + + List voList = dictResult.getData().stream().map(item -> { + FeedbackTypeVO vo = new FeedbackTypeVO(); + vo.setId(item.getId()); + vo.setLabel(item.getLabel()); + return vo; + }).collect(Collectors.toList()); + + return R.ok(voList); } /** diff --git a/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/controller/MaintenanceOrderController.java b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/controller/MaintenanceOrderController.java index 812f488ac..2a852639c 100644 --- a/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/controller/MaintenanceOrderController.java +++ b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/controller/MaintenanceOrderController.java @@ -25,6 +25,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; import com.bsd.pjcloud.integrated.dto.MaintenanceOrderAppCreateDTO; import com.bsd.pjcloud.integrated.vo.maintenance.MaintenanceOrderScreenVo; +import com.bsd.pjcloud.integrated.vo.MaintenanceTypeVO; import com.bsd.pjcloud.admin.api.entity.SysDictItem; import java.util.Map; @@ -140,7 +141,7 @@ public class MaintenanceOrderController { @PostMapping("/app/apply") @Operation(summary = "App端-维修申请新增", description = "App端用户提交维修申请") @SysLog("App端-维修申请新增") - @PreAuthorize("@pms.hasPermission('integrated_maintenanceOrder_add')") +// @PreAuthorize("@pms.hasPermission('integrated_maintenanceOrder_add')") public R appApply(@RequestBody MaintenanceOrderAppCreateDTO dto) { PjcloudUser user = SecurityUtils.getUser(); Long userId = user.getId(); @@ -158,7 +159,7 @@ public class MaintenanceOrderController { */ @GetMapping("/app/my") @Operation(summary = "App端-我的维修分页列表", description = "App端用户分页查询自己的维修单") - @PreAuthorize("@pms.hasPermission('integrated_maintenanceOrder_view')") +// @PreAuthorize("@pms.hasPermission('integrated_maintenanceOrder_view')") public R myMaintenanceOrders(@ParameterObject Page page) { Long userId = SecurityUtils.getUser().getId(); LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); @@ -173,7 +174,7 @@ public class MaintenanceOrderController { */ @GetMapping("/app/my/{id}") @Operation(summary = "App端-我的维修单详情", description = "App端用户查看自己维修单详情") - @PreAuthorize("@pms.hasPermission('integrated_maintenanceOrder_view')") +// @PreAuthorize("@pms.hasPermission('integrated_maintenanceOrder_view')") public R myMaintenanceOrderDetail(@PathVariable("id") Long id) { Long userId = SecurityUtils.getUser().getId(); MaintenanceOrderEntity entity = maintenanceOrderService.getById(id); @@ -214,4 +215,22 @@ public class MaintenanceOrderController { }).collect(Collectors.toList()); return R.ok(voList); } + + @Operation(summary = "获取维修类型" , description = "获取维修类型" ) + @GetMapping("/app/getFeedbackType" ) + public R> getFeedbackType() { + R> dictResult = remoteDictService.getDictByType("maintenance_type"); + if (!dictResult.isOk() || dictResult.getData() == null) { + return R.failed("获取维修类型失败"); + } + + List voList = dictResult.getData().stream().map(item -> { + MaintenanceTypeVO vo = new MaintenanceTypeVO(); + vo.setId(item.getId()); + vo.setLabel(item.getLabel()); + return vo; + }).collect(Collectors.toList()); + + 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..3373baa38 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(); @@ -254,9 +259,9 @@ public class MeetingBookingController { /** * 会议开始之前,通知阿姨需要对会议室桌面和桌椅拜访进行整理 */ - @PostMapping("/app/notice-visit-desk/{bookingId}") - public R noticeVisitDesk(@PathVariable("bookingId") Long bookingId) { - meetingBookingService.noticeVisitDesk(bookingId); - return R.ok(); - } +// @PostMapping("/app/notice-visit-desk/{bookingId}") +// public R noticeVisitDesk(@PathVariable("bookingId") Long bookingId) { +// meetingBookingService.noticeVisitDesk(bookingId); +// return R.ok(); +// } } \ No newline at end of file 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..f57fc5016 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 @@ -20,15 +20,20 @@ import com.bsd.pjcloud.flow.task.dto.ProcessNodeRecordParamDto; import com.bsd.pjcloud.flow.task.entity.Process; import com.bsd.pjcloud.flow.task.utils.GetCheckReasonUtils; import com.bsd.pjcloud.flow.task.vo.CheckStatusAndReasonVo; +import com.bsd.pjcloud.integrated.constant.IntegratedConstants; import com.bsd.pjcloud.integrated.constant.IntegratedFlowConstant; import com.bsd.pjcloud.integrated.dto.flow.MeetingFlowDto; import com.bsd.pjcloud.integrated.dto.meeting.app.MeetingPageDto; import com.bsd.pjcloud.integrated.entity.MeetingBookingEntity; +import com.bsd.pjcloud.integrated.entity.MeetingEquipmentEntity; import com.bsd.pjcloud.integrated.entity.MeetingRoomEntity; import com.bsd.pjcloud.integrated.entity.MeetingRoomEquipmentEntity; import com.bsd.pjcloud.integrated.service.MeetingBookingService; +import com.bsd.pjcloud.integrated.service.MeetingEquipmentService; import com.bsd.pjcloud.integrated.service.MeetingRoomEquipmentService; import com.bsd.pjcloud.integrated.service.MeetingRoomService; +import com.bsd.pjcloud.integrated.vo.meeting.app.MeetingBookingDetailVo; +import com.bsd.pjcloud.integrated.vo.meeting.app.MeetingBookingListVo; import com.bsd.pjcloud.integrated.vo.meeting.app.MeetingBookingReqVo; import com.bsd.pjcloud.integrated.vo.meeting.app.MeetingRoomPageVo; import com.bsd.pjcloud.integrated.vo.meeting.app.TimeSlotVo; @@ -70,6 +75,8 @@ public class MeetingRoomController { private final MeetingRoomEquipmentService meetingRoomEquipmentService; + private final MeetingEquipmentService meetingEquipmentService; + private final MeetingBookingService meetingBookingService; private final RemoteFlowApiFlowService remoteFlowApiFlowService; @@ -315,12 +322,14 @@ public class MeetingRoomController { booking.setBookingDate(bookingDate); booking.setStartTime(startTime); booking.setEndTime(endTime); - + booking.setDeskLayout(reqVo.getDeskLayout()); + booking.setNeedService(reqVo.getNeedService()); //发起流程 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(); @@ -348,19 +357,108 @@ public class MeetingRoomController { * @param checkStatus 审核状态(可选),传空查全部 */ @GetMapping("/app/my-bookings") - public R> myBookings(@ParameterObject Page page, @RequestParam(value = "checkStatus", required = false) String checkStatus) { + public R> myBookings(@ParameterObject Page page, @RequestParam(value = "checkStatus", required = false) String checkStatus) { Long userId = SecurityUtils.getUser().getId(); LambdaQueryWrapper wrapper = Wrappers.lambdaQuery() .eq(MeetingBookingEntity::getApplicantId, userId); if (checkStatus != null && !checkStatus.isEmpty()) { wrapper.eq(MeetingBookingEntity::getCheckStatus, checkStatus); } - wrapper.orderByDesc(MeetingBookingEntity::getBookingDate) + wrapper.orderByDesc(MeetingBookingEntity::getCreateTime) + .orderByDesc(MeetingBookingEntity::getBookingDate) .orderByDesc(MeetingBookingEntity::getStartTime); - Page result = meetingBookingService.page(page, wrapper); - return R.ok(result); + Page entityPage = meetingBookingService.page(page, wrapper); + + // 批量查会议室名称,避免N+1 + List roomIds = entityPage.getRecords().stream().map(MeetingBookingEntity::getRoomId).distinct().toList(); + Map roomNameMap = new HashMap<>(); + if (!roomIds.isEmpty()) { + List rooms = meetingRoomService.listByIds(roomIds); + for (MeetingRoomEntity room : rooms) { + roomNameMap.put(room.getId(), room.getRoomName()); + } + } + + // 转VO + List voList = entityPage.getRecords().stream().map(e -> { + MeetingBookingListVo vo = new MeetingBookingListVo(); + vo.setId(e.getId()); + vo.setTitle(e.getTitle()); + vo.setRoomId(e.getRoomId()); + vo.setRoomName(roomNameMap.get(e.getRoomId())); + vo.setDescription(e.getDescription()); + vo.setCheckStatus(e.getCheckStatus()); + vo.setCheckStatusText(getCheckStatusText(e.getCheckStatus())); + vo.setApplicantId(e.getApplicantId()); + vo.setApplicantName(SecurityUtils.getUser().getUsername()); + vo.setAssigneeName(e.getAssigneeName()); + vo.setBookingDate(e.getBookingDate()); + vo.setStartTime(e.getStartTime()); + vo.setEndTime(e.getEndTime()); + vo.setDuration(calculateDuration(e.getStartTime(), e.getEndTime())); + vo.setNeedService(e.getNeedService()); + vo.setDeskLayout(e.getDeskLayout()); + vo.setCheckReason(e.getCheckReason()); + vo.setIsConfirmEnd(e.getIsConfirmEnd()); + vo.setCreateTime(e.getCreateTime()); + return vo; + }).toList(); + + Page voPage = new Page<>(entityPage.getCurrent(), entityPage.getSize(), entityPage.getTotal()); + voPage.setRecords(voList); + return R.ok(voPage); } + /** + * 获取审核状态描述 + */ + private String getCheckStatusText(String checkStatus) { + if (checkStatus == null) return ""; + switch (checkStatus) { + case "1": return "审核中"; + case "2": return "审核通过"; + case "3": return "审核拒绝"; + case "4": return "已取消"; + case "5": return "取消"; + case "0": return "已到访"; + default: return "未知状态"; + } + } + + /** + * 计算会议时长(分钟) + */ + private Integer calculateDuration(LocalTime startTime, LocalTime endTime) { + if (startTime == null || endTime == null) return 0; + return (int) java.time.Duration.between(startTime, endTime).toMinutes(); + } + + /** + * 获取会议室状态描述 + */ + private String getRoomStatusText(String status) { + if (status == null) return ""; + switch (status) { + case IntegratedConstants.MeetingRoomStatus.MAINTENANCE: return "维护中"; + case IntegratedConstants.MeetingRoomStatus.AVAILABLE: return "可用"; + default: return "未知状态"; + } + } + + /** + * 获取是否需要会务服务描述 + */ + private String getNeedServiceText(String needService) { + if (needService == null) return ""; + switch (needService) { + case IntegratedConstants.NeedService.NO: return "不需要"; + case IntegratedConstants.NeedService.YES: return "需要"; + default: return "未知"; + } + } + + + /** * 取消预约 */ @@ -384,7 +482,7 @@ public class MeetingRoomController { * 预约详情 */ @GetMapping("/app/booking-detail/{bookingId}") - public R bookingDetail(@PathVariable("bookingId") Long bookingId) { + public R bookingDetail(@PathVariable("bookingId") Long bookingId) { Long userId = SecurityUtils.getUser().getId(); MeetingBookingEntity booking = meetingBookingService.getById(bookingId); if (booking == null) { @@ -393,7 +491,82 @@ public class MeetingRoomController { if (!Objects.equals(booking.getApplicantId(), userId)) { return R.failed("无权查看他人预约详情"); } - return R.ok(booking); + + // 查询会议室详细信息 + MeetingRoomEntity room = meetingRoomService.getById(booking.getRoomId()); + if (room == null) { + return R.failed("会议室不存在"); + } + + // 查询会议室设备信息 + List equipmentList = meetingRoomEquipmentService.list( + Wrappers.lambdaQuery() + .eq(MeetingRoomEquipmentEntity::getRoomId, booking.getRoomId()) + ); + + // 构建设备信息字符串 + StringBuilder equipmentInfo = new StringBuilder(); + if (!equipmentList.isEmpty()) { + // 获取所有设备ID + List equipmentIds = equipmentList.stream() + .map(MeetingRoomEquipmentEntity::getEquipId) + .distinct() + .toList(); + + // 批量查询设备信息 + Map equipmentNameMap = new HashMap<>(); + if (!equipmentIds.isEmpty()) { + List equipments = meetingEquipmentService.listByIds(equipmentIds); + for (MeetingEquipmentEntity equipment : equipments) { + equipmentNameMap.put(equipment.getId(), equipment.getName()); + } + } + + // 构建设备信息字符串 + for (MeetingRoomEquipmentEntity roomEquipment : equipmentList) { + if (equipmentInfo.length() > 0) { + equipmentInfo.append("、"); + } + String equipmentName = equipmentNameMap.get(roomEquipment.getEquipId()); + if (equipmentName != null) { + equipmentInfo.append(equipmentName) + .append("(").append(roomEquipment.getQuantity()).append("台)"); + } + } + } + + // 转换为VO + MeetingBookingDetailVo vo = new MeetingBookingDetailVo(); + vo.setId(booking.getId()); + vo.setTitle(booking.getTitle()); + vo.setRoomId(booking.getRoomId()); + vo.setRoomName(room.getRoomName()); + vo.setRoomLocation(room.getLocation()); + vo.setRoomCapacity(room.getCapacity()); + vo.setRoomEquipment(equipmentInfo.toString()); + vo.setRoomPicUrl(room.getPicUrl()); + vo.setRoomDescription(room.getDescription()); + vo.setRoomStatus(room.getStatus()); + vo.setRoomStatusText(getRoomStatusText(room.getStatus())); + vo.setDescription(booking.getDescription()); + vo.setCheckStatus(booking.getCheckStatus()); + vo.setCheckStatusText(getCheckStatusText(booking.getCheckStatus())); + vo.setCheckReason(booking.getCheckReason()); + vo.setApplicantId(booking.getApplicantId()); + vo.setApplicantName(SecurityUtils.getUser().getUsername()); + vo.setAssigneeName(booking.getAssigneeName()); + vo.setBookingDate(booking.getBookingDate()); + vo.setStartTime(booking.getStartTime()); + vo.setEndTime(booking.getEndTime()); + vo.setDuration(calculateDuration(booking.getStartTime(), booking.getEndTime())); + vo.setNeedService(booking.getNeedService()); + vo.setNeedServiceText(getNeedServiceText(booking.getNeedService())); + vo.setDeskLayout(booking.getDeskLayout()); + vo.setDeskLayoutText(booking.getDeskLayout()); + vo.setIsConfirmEnd(booking.getIsConfirmEnd()); + vo.setCreateBy(booking.getCreateBy()); + vo.setCreateTime(booking.getCreateTime()); + return R.ok(vo); } @@ -408,10 +581,23 @@ public class MeetingRoomController { System.out.println(processNodeRecordParamDto.getData()); LambdaQueryWrapper boxesBookingEntityLambdaQueryWrapper = new LambdaQueryWrapper<>(); boxesBookingEntityLambdaQueryWrapper.eq(MeetingBookingEntity::getProcessInstanceId, processInstanceId); + MeetingBookingEntity one = meetingBookingService.getOne(boxesBookingEntityLambdaQueryWrapper); + if (null== one){ + return R.failed("流程不存在"); + } CheckStatusAndReasonVo checkReason = GetCheckReasonUtils.getCheckReason(processNodeRecordParamDto); meetingBookingEntity.setCheckStatus(checkReason.getCheckStatus()); meetingBookingEntity.setCheckReason(checkReason.getCheckReason()); - meetingBookingService.update(meetingBookingEntity,boxesBookingEntityLambdaQueryWrapper); + Long id = one.getId(); + meetingBookingEntity.setId(id); + meetingBookingService.updateById(meetingBookingEntity); + + + //发送通知短信,告知会议打扫 + meetingBookingService.noticeVisitDesk(one); + + //告知预约人 + meetingBookingService.noticeVisitor(one); return R.ok(); } 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/MeetingBookingService.java b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/service/MeetingBookingService.java index 395f39c5e..11ca9295c 100644 --- a/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/service/MeetingBookingService.java +++ b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/service/MeetingBookingService.java @@ -27,8 +27,14 @@ public interface MeetingBookingService extends IService { /** * 通知阿姨会议前整理会议室 - * @param bookingId + * @param * @return */ - void noticeVisitDesk(Long bookingId); + void noticeVisitDesk(MeetingBookingEntity meetingBookingEntity); + + /** + * 通知会议预约人 + * @param + */ + void noticeVisitor(MeetingBookingEntity meetingBookingEntity); } \ 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/VisitorsService.java b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/service/VisitorsService.java index eb3442ad9..6eb23f0ad 100644 --- a/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/service/VisitorsService.java +++ b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/service/VisitorsService.java @@ -9,6 +9,7 @@ import com.bsd.pjcloud.integrated.dto.visitor.app.VisitorsReceiveAppDTO; import com.bsd.pjcloud.integrated.dto.visitor.app.VisitorsYYAppDTO; import com.bsd.pjcloud.integrated.entity.VisitorsEntity; import com.bsd.pjcloud.integrated.vo.visitor.app.VisitorsAppVo; +import com.bsd.pjcloud.integrated.vo.visitor.app.VisitorsAppYYDetailVo; import java.util.List; @@ -86,4 +87,12 @@ public interface VisitorsService extends IService { Object receiveYY(VisitorsReceiveAppDTO visitorsReceiveAppDTO); + + + /** + * 获取邀约详情 + * @param token + * @return + */ + VisitorsAppYYDetailVo getVisitorsYYDetail(String token); } \ No newline at end of file diff --git a/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/service/impl/MeetingBookingServiceImpl.java b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/service/impl/MeetingBookingServiceImpl.java index b0316e51c..abe4dea97 100644 --- a/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/service/impl/MeetingBookingServiceImpl.java +++ b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/service/impl/MeetingBookingServiceImpl.java @@ -66,41 +66,52 @@ public class MeetingBookingServiceImpl extends ServiceImpl stringStringHashMap = new HashMap<>(); stringStringHashMap.put("meetingName", meetingRoomEntity.getRoomName()+",地址:"+meetingRoomEntity.getLocation()); - stringStringHashMap.put("meetingDate", booking.getBookingDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))); - stringStringHashMap.put("deskType", "1"); + String format = meetingBookingEntity.getBookingDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")); + stringStringHashMap.put("meetingDate", format); + stringStringHashMap.put("deskType", meetingBookingEntity.getDeskLayout()==null?"无要求":meetingBookingEntity.getDeskLayout()); reminderThirdPartySmsService.sendParamsMsg(cleanUserEntity.getPhone(), "30758", stringStringHashMap, WebUtils.getIP()); }else { + System.out.println("没有设置阿姨,无法发送短信"); //没有设置阿姨,无法发送短信 } } - - private void sendConfirmEndMeetingSms(VisitorUserEntity visitorUserEntity, VisitorsEntity dataVisitors) { - Map stringStringHashMap = new HashMap<>(); - DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); - stringStringHashMap.put("createTime", visitorUserEntity.getCreateTime().format(formatter)); - stringStringHashMap.put("visitorName", visitorUserEntity.getRealName()==null?visitorUserEntity.getPhone():visitorUserEntity.getRealName()); - stringStringHashMap.put("visitorPhone", visitorUserEntity.getPhone()); - stringStringHashMap.put("visitorTime", dataVisitors.getVStartDate() + "至" + dataVisitors.getVEndDate()); - stringStringHashMap.put("visitorLocal", dataVisitors.getDeptName()); + @Override + public void noticeVisitor(MeetingBookingEntity meetingBookingEntity) { - reminderThirdPartySmsService.sendParamsMsg(visitorUserEntity.getPhone(), "20658", stringStringHashMap, WebUtils.getIP()); } + +// private void sendConfirmEndMeetingSms(VisitorUserEntity visitorUserEntity, VisitorsEntity dataVisitors) { +// Map stringStringHashMap = new HashMap<>(); +// DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); +// stringStringHashMap.put("createTime", visitorUserEntity.getCreateTime().format(formatter)); +// stringStringHashMap.put("visitorName", visitorUserEntity.getRealName()==null?visitorUserEntity.getPhone():visitorUserEntity.getRealName()); +// stringStringHashMap.put("visitorPhone", visitorUserEntity.getPhone()); +// stringStringHashMap.put("visitorTime", dataVisitors.getVStartDate() + "至" + dataVisitors.getVEndDate()); +// stringStringHashMap.put("visitorLocal", dataVisitors.getDeptName()); +// +// +// reminderThirdPartySmsService.sendParamsMsg(visitorUserEntity.getPhone(), "30757", stringStringHashMap, WebUtils.getIP()); +// } } \ 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/service/impl/VisitorsServiceImpl.java b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/service/impl/VisitorsServiceImpl.java index 12d3382e8..226cba0c4 100644 --- a/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/service/impl/VisitorsServiceImpl.java +++ b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/service/impl/VisitorsServiceImpl.java @@ -1,6 +1,7 @@ package com.bsd.pjcloud.integrated.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -36,10 +37,7 @@ import com.bsd.pjcloud.integrated.mapper.VisitorsMapper; import com.bsd.pjcloud.integrated.mapper.VisitorsPeopleMapper; import com.bsd.pjcloud.integrated.service.VisitorUserService; import com.bsd.pjcloud.integrated.service.VisitorsService; -import com.bsd.pjcloud.integrated.vo.visitor.app.VisitorsAppPageVo; -import com.bsd.pjcloud.integrated.vo.visitor.app.VisitorsAppVo; -import com.bsd.pjcloud.integrated.vo.visitor.app.VisitorsCarAppVo; -import com.bsd.pjcloud.integrated.vo.visitor.app.VisitorsPeopleAppVo; +import com.bsd.pjcloud.integrated.vo.visitor.app.*; import com.bsd.pjcloud.thirdparty.api.feign.RemoterThirdPartySmsService; import com.bsd.pjcloud.thirdparty.api.feign.RemoterVisitorService; import com.bsd.pjcloud.thirdparty.dto.visitor.AppointmentInfo; @@ -285,7 +283,7 @@ public class VisitorsServiceImpl extends ServiceImpl deptByDeptId = remoteDeptService.getDeptByDeptId(deptId); bean.setDeptName(deptByDeptId.getData().getName()); - + bean.setUserName(SecurityUtils.getUser().getName()); String uniqueToken = UUID.randomUUID().toString(); String token = uniqueToken.replace("-", ""); bean.setToken(token); @@ -511,5 +509,41 @@ public class VisitorsServiceImpl extends ServiceImpl() + .eq("token", token) + .eq("type", VisitorTypeEnum.ZDYQ.getType())); + if(visitorsEntity == null){ + throw new ServiceException("数据不存在"); + } + // 转换为VO对象 + VisitorsAppYYDetailVo result = BeanUtils.toBean(visitorsEntity, VisitorsAppYYDetailVo.class); + + // 查询车辆信息 + List visitorsCarEntities = visitorsCarMapper.selectList( + new LambdaQueryWrapper().eq(VisitorsCarEntity::getVisitorsId, visitorsEntity.getId()) + ); + if (!CollectionUtils.isEmpty(visitorsCarEntities)) { + List carList = BeanUtils.toBean(visitorsCarEntities, VisitorsCarAppDTO.class); + result.setCarList(carList); + } + + // 查询随行人员信息 + List visitorsPeopleEntities = visitorsPeopleMapper.selectList( + new LambdaQueryWrapper().eq(VisitorsPeopleEntity::getVisitorsId, visitorsEntity.getId()) + ); + if (!CollectionUtils.isEmpty(visitorsPeopleEntities)) { + List otherPeople = BeanUtils.toBean(visitorsPeopleEntities, VisitorsPeopleAppDTO.class); + result.setOtherPeople(otherPeople); + } + //设置邀约者的信息 + // 设置邀约ID +// result.setYyId(visitorsEntity.getId()); + + return result; + } + } \ No newline at end of file diff --git a/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/vo/FeedbackTypeVO.java b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/vo/FeedbackTypeVO.java new file mode 100644 index 000000000..d396d2125 --- /dev/null +++ b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/vo/FeedbackTypeVO.java @@ -0,0 +1,31 @@ +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 FeedbackTypeVO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 字典项ID + */ + @Schema(description = "字典项ID") + private Long id; + + /** + * 标签名称 + */ + @Schema(description = "标签名称") + private String label; +} diff --git a/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/vo/MaintenanceTypeVO.java b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/vo/MaintenanceTypeVO.java new file mode 100644 index 000000000..a7cec5247 --- /dev/null +++ b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/vo/MaintenanceTypeVO.java @@ -0,0 +1,31 @@ +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 MaintenanceTypeVO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 字典项ID + */ + @Schema(description = "字典项ID") + private Long id; + + /** + * 标签名称 + */ + @Schema(description = "标签名称") + private String label; +} 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..cc1be5743 --- /dev/null +++ b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/vo/MeetingDeskLayoutAppVO.java @@ -0,0 +1,58 @@ +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 @@ + +