From 9a6bd54fbac0670dcf1c3a59588c5c642b566f69 Mon Sep 17 00:00:00 2001 From: yuyongle <1150359267@qq.com> Date: Mon, 8 Sep 2025 16:41:32 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=AE=A2=E6=88=B7?= =?UTF-8?q?=E6=9C=8D=E5=8A=A1=E6=B4=BB=E5=8A=A8=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CustomerActivityController.java | 106 ++++++++++++ .../property/controller/TbRoomController.java | 2 +- .../mobile/MCustomerNoticesController.java | 38 ++++ .../property/domain/CustomerActivity.java | 78 +++++++++ .../domain/bo/CustomerActivityBo.java | 77 +++++++++ .../domain/entity/resident/ResidentUnit.java | 5 +- .../domain/vo/CustomerActivityVo.java | 93 ++++++++++ .../domain/vo/residentVo/ResidentUnitVo.java | 5 + .../mapper/CustomerActivityMapper.java | 15 ++ .../service/ICustomerActivityService.java | 69 ++++++++ .../service/ICustomerNoticesService.java | 9 + .../impl/CustomerActivityServiceImpl.java | 162 ++++++++++++++++++ .../impl/CustomerNoticesServiceImpl.java | 11 ++ .../impl/InspectionTaskDetailServiceImpl.java | 32 +++- .../impl/ServiceWorkOrdersServiceImpl.java | 1 + .../service/impl/TbRoomServiceImpl.java | 7 +- .../residentImpl/ResidentUnitServiceImpl.java | 23 ++- .../Property/CustomerActivityMapper.xml | 7 + 18 files changed, 726 insertions(+), 14 deletions(-) create mode 100644 ruoyi-modules/Property/src/main/java/org/dromara/property/controller/CustomerActivityController.java create mode 100644 ruoyi-modules/Property/src/main/java/org/dromara/property/controller/mobile/MCustomerNoticesController.java create mode 100644 ruoyi-modules/Property/src/main/java/org/dromara/property/domain/CustomerActivity.java create mode 100644 ruoyi-modules/Property/src/main/java/org/dromara/property/domain/bo/CustomerActivityBo.java create mode 100644 ruoyi-modules/Property/src/main/java/org/dromara/property/domain/vo/CustomerActivityVo.java create mode 100644 ruoyi-modules/Property/src/main/java/org/dromara/property/mapper/CustomerActivityMapper.java create mode 100644 ruoyi-modules/Property/src/main/java/org/dromara/property/service/ICustomerActivityService.java create mode 100644 ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/CustomerActivityServiceImpl.java create mode 100644 ruoyi-modules/Property/src/main/resources/mapper/Property/CustomerActivityMapper.xml diff --git a/ruoyi-modules/Property/src/main/java/org/dromara/property/controller/CustomerActivityController.java b/ruoyi-modules/Property/src/main/java/org/dromara/property/controller/CustomerActivityController.java new file mode 100644 index 00000000..1601f98e --- /dev/null +++ b/ruoyi-modules/Property/src/main/java/org/dromara/property/controller/CustomerActivityController.java @@ -0,0 +1,106 @@ +package org.dromara.property.controller; + +import java.util.List; + +import lombok.RequiredArgsConstructor; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.constraints.*; +import cn.dev33.satoken.annotation.SaCheckPermission; +import org.springframework.web.bind.annotation.*; +import org.springframework.validation.annotation.Validated; +import org.dromara.common.idempotent.annotation.RepeatSubmit; +import org.dromara.common.log.annotation.Log; +import org.dromara.common.web.core.BaseController; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.core.domain.R; +import org.dromara.common.core.validate.AddGroup; +import org.dromara.common.core.validate.EditGroup; +import org.dromara.common.log.enums.BusinessType; +import org.dromara.common.excel.utils.ExcelUtil; +import org.dromara.property.domain.vo.CustomerActivityVo; +import org.dromara.property.domain.bo.CustomerActivityBo; +import org.dromara.property.service.ICustomerActivityService; +import org.dromara.common.mybatis.core.page.TableDataInfo; + +/** + * 客户服务-活动 + * 前端访问路由地址为:/property/activity + * + * @author yuyongle + * @date 2025-09-08 + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/activity") +public class CustomerActivityController extends BaseController { + + private final ICustomerActivityService customerActivityService; + + /** + * 查询客户服务-活动列表 + */ + @SaCheckPermission("property:activity:list") + @GetMapping("/list") + public TableDataInfo list(CustomerActivityBo bo, PageQuery pageQuery) { + return customerActivityService.queryPageList(bo, pageQuery); + } + + /** + * 导出客户服务-活动列表 + */ + @SaCheckPermission("property:activity:export") + @Log(title = "客户服务-活动", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(CustomerActivityBo bo, HttpServletResponse response) { + List list = customerActivityService.queryList(bo); + ExcelUtil.exportExcel(list, "客户服务-活动", CustomerActivityVo.class, response); + } + + /** + * 获取客户服务-活动详细信息 + * + * @param id 主键 + */ + @SaCheckPermission("property:activity:query") + @GetMapping("/{id}") + public R getInfo(@NotNull(message = "主键不能为空") + @PathVariable("id") Long id) { + return R.ok(customerActivityService.queryById(id)); + } + + /** + * 新增客户服务-活动 + */ + @SaCheckPermission("property:activity:add") + @Log(title = "客户服务-活动", businessType = BusinessType.INSERT) + @RepeatSubmit() + @PostMapping() + public R add(@Validated(AddGroup.class) @RequestBody CustomerActivityBo bo) { + return toAjax(customerActivityService.insertByBo(bo)); + } + + /** + * 修改客户服务-活动 + */ + @SaCheckPermission("property:activity:edit") + @Log(title = "客户服务-活动", businessType = BusinessType.UPDATE) + @RepeatSubmit() + @PutMapping() + public R edit(@Validated(EditGroup.class) @RequestBody CustomerActivityBo bo) { + return toAjax(customerActivityService.updateByBo(bo)); + } + + /** + * 删除客户服务-活动 + * + * @param ids 主键串 + */ + @SaCheckPermission("property:activity:remove") + @Log(title = "客户服务-活动", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@NotEmpty(message = "主键不能为空") + @PathVariable("ids") Long[] ids) { + return toAjax(customerActivityService.deleteWithValidByIds(List.of(ids), true)); + } +} diff --git a/ruoyi-modules/Property/src/main/java/org/dromara/property/controller/TbRoomController.java b/ruoyi-modules/Property/src/main/java/org/dromara/property/controller/TbRoomController.java index a1c30400..1423204b 100644 --- a/ruoyi-modules/Property/src/main/java/org/dromara/property/controller/TbRoomController.java +++ b/ruoyi-modules/Property/src/main/java/org/dromara/property/controller/TbRoomController.java @@ -62,7 +62,7 @@ public class TbRoomController extends BaseController { * * @param id 主键 */ - @SaCheckPermission("property:room:query") + // @SaCheckPermission("property:room:query") @GetMapping("/{id}") public R getInfo(@NotNull(message = "主键不能为空") @PathVariable("id") Long id) { diff --git a/ruoyi-modules/Property/src/main/java/org/dromara/property/controller/mobile/MCustomerNoticesController.java b/ruoyi-modules/Property/src/main/java/org/dromara/property/controller/mobile/MCustomerNoticesController.java new file mode 100644 index 00000000..0bebd6cb --- /dev/null +++ b/ruoyi-modules/Property/src/main/java/org/dromara/property/controller/mobile/MCustomerNoticesController.java @@ -0,0 +1,38 @@ +package org.dromara.property.controller.mobile; + + +import lombok.RequiredArgsConstructor; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.property.domain.bo.CustomerNoticesBo; +import org.dromara.property.domain.vo.CustomerNoticesVo; +import org.dromara.property.service.ICustomerNoticesService; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author yuyongle + * @version 1.0 + * @description: TODO + * @date 2025/9/8 11:15 + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/mobile/notices") +public class MCustomerNoticesController { + private final ICustomerNoticesService customerNoticesService; + + /** + * 头条滚动列表 + * @param bo + * @param pageQuery + * @return + */ + @GetMapping("/todayList") + public TableDataInfo todayList(CustomerNoticesBo bo, PageQuery pageQuery) { + return customerNoticesService.todayList(bo, pageQuery); + } +} diff --git a/ruoyi-modules/Property/src/main/java/org/dromara/property/domain/CustomerActivity.java b/ruoyi-modules/Property/src/main/java/org/dromara/property/domain/CustomerActivity.java new file mode 100644 index 00000000..9997848e --- /dev/null +++ b/ruoyi-modules/Property/src/main/java/org/dromara/property/domain/CustomerActivity.java @@ -0,0 +1,78 @@ +package org.dromara.property.domain; + +import org.dromara.common.tenant.core.TenantEntity; +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; +import lombok.EqualsAndHashCode; +import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; + +import java.io.Serial; + +/** + * 客户服务-活动对象 customer_activity + * + * @author yuyongle + * @date 2025-09-08 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("customer_activity") +public class CustomerActivity extends TenantEntity { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + @TableId(value = "id") + private Long id; + + /** + * 标题 + */ + private String title; + + /** + * 状态(1待进行2进行中3已完成) + */ + private String status; + + /** + * 活动图片 + */ + private String activityImgUrl; + + /** + * 开始时间 + */ + private Date startTime; + + /** + * 结束时间 + */ + private Date endTime; + + /** + * 活动内容 + */ + private String activityContent; + + /** + * 备注 + */ + private String remark; + + /** + * 发布人 + */ + private Long issuers; + + /** + * 搜索值 + */ + private String searchValue; + + +} diff --git a/ruoyi-modules/Property/src/main/java/org/dromara/property/domain/bo/CustomerActivityBo.java b/ruoyi-modules/Property/src/main/java/org/dromara/property/domain/bo/CustomerActivityBo.java new file mode 100644 index 00000000..96447477 --- /dev/null +++ b/ruoyi-modules/Property/src/main/java/org/dromara/property/domain/bo/CustomerActivityBo.java @@ -0,0 +1,77 @@ +package org.dromara.property.domain.bo; + +import org.dromara.property.domain.CustomerActivity; +import org.dromara.common.mybatis.core.domain.BaseEntity; +import org.dromara.common.core.validate.AddGroup; +import org.dromara.common.core.validate.EditGroup; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; +import lombok.EqualsAndHashCode; +import jakarta.validation.constraints.*; +import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; + +/** + * 客户服务-活动业务对象 customer_activity + * + * @author yuyongle + * @date 2025-09-08 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@AutoMapper(target = CustomerActivity.class, reverseConvertGenerate = false) +public class CustomerActivityBo extends BaseEntity { + + /** + * 主键 + */ + @NotNull(message = "主键不能为空", groups = { EditGroup.class }) + private Long id; + + /** + * 标题 + */ + @NotBlank(message = "标题不能为空", groups = { AddGroup.class, EditGroup.class }) + private String title; + + /** + * 状态(1待进行2进行中3已完成) + */ + private String status; + + /** + * 活动图片 + */ +// @NotBlank(message = "活动图片不能为空", groups = { AddGroup.class, EditGroup.class }) + private String activityImgUrl; + + /** + * 开始时间 + */ + @NotNull(message = "开始时间不能为空", groups = { AddGroup.class, EditGroup.class }) + private Date startTime; + + /** + * 结束时间 + */ + @NotNull(message = "结束时间不能为空", groups = { AddGroup.class, EditGroup.class }) + private Date endTime; + + /** + * 活动内容 + */ + @NotBlank(message = "活动内容不能为空", groups = { AddGroup.class, EditGroup.class }) + private String activityContent; + + /** + * 备注 + */ + private String remark; + + /** + * 发布人 + */ + private Long issuers; + + +} diff --git a/ruoyi-modules/Property/src/main/java/org/dromara/property/domain/entity/resident/ResidentUnit.java b/ruoyi-modules/Property/src/main/java/org/dromara/property/domain/entity/resident/ResidentUnit.java index 0b5d4986..71c3bfb2 100644 --- a/ruoyi-modules/Property/src/main/java/org/dromara/property/domain/entity/resident/ResidentUnit.java +++ b/ruoyi-modules/Property/src/main/java/org/dromara/property/domain/entity/resident/ResidentUnit.java @@ -72,7 +72,10 @@ public class ResidentUnit extends TenantEntity { * 员工人数 */ private Long number; - + /** + * 建筑面积(房间建筑面积和,平方千米) + */ + private Float area; /** * 备注 */ diff --git a/ruoyi-modules/Property/src/main/java/org/dromara/property/domain/vo/CustomerActivityVo.java b/ruoyi-modules/Property/src/main/java/org/dromara/property/domain/vo/CustomerActivityVo.java new file mode 100644 index 00000000..a0347a5f --- /dev/null +++ b/ruoyi-modules/Property/src/main/java/org/dromara/property/domain/vo/CustomerActivityVo.java @@ -0,0 +1,93 @@ +package org.dromara.property.domain.vo; + +import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.dromara.property.domain.CustomerActivity; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import org.dromara.common.excel.annotation.ExcelDictFormat; +import org.dromara.common.excel.convert.ExcelDictConvert; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.Date; + + + +/** + * 客户服务-活动视图对象 customer_activity + * + * @author yuyongle + * @date 2025-09-08 + */ +@Data +@ExcelIgnoreUnannotated +@AutoMapper(target = CustomerActivity.class) +public class CustomerActivityVo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + @ExcelProperty(value = "主键") + private Long id; + + /** + * 标题 + */ + @ExcelProperty(value = "标题") + private String title; + + /** + * 状态(1待进行2进行中3已完成) + */ + @ExcelProperty(value = "状态(1待进行2进行中3已完成)") + private String status; + + /** + * 活动图片 + */ + @ExcelProperty(value = "活动图片") + private String activityImgUrl; + + /** + * 开始时间 + */ + @ExcelProperty(value = "开始时间") + private Date startTime; + + /** + * 结束时间 + */ + @ExcelProperty(value = "结束时间") + private Date endTime; + + /** + * 活动内容 + */ + @ExcelProperty(value = "活动内容") + private String activityContent; + + /** + * 备注 + */ + @ExcelProperty(value = "备注") + private String remark; + + /** + * 发布人 + */ + @ExcelProperty(value = "发布人") + private Long issuers; + /** + * 发布人文本 + */ + @ExcelProperty(value = "发布人文本") + private String issuersText; + + +} diff --git a/ruoyi-modules/Property/src/main/java/org/dromara/property/domain/vo/residentVo/ResidentUnitVo.java b/ruoyi-modules/Property/src/main/java/org/dromara/property/domain/vo/residentVo/ResidentUnitVo.java index e93abf8d..8509c52d 100644 --- a/ruoyi-modules/Property/src/main/java/org/dromara/property/domain/vo/residentVo/ResidentUnitVo.java +++ b/ruoyi-modules/Property/src/main/java/org/dromara/property/domain/vo/residentVo/ResidentUnitVo.java @@ -91,6 +91,11 @@ public class ResidentUnitVo implements Serializable { @ExcelProperty(value = "员工人数") private Long number; + /** + * 建筑面积(房间建筑面积和,平方千米) + */ + private Float area; + /** * 备注 */ diff --git a/ruoyi-modules/Property/src/main/java/org/dromara/property/mapper/CustomerActivityMapper.java b/ruoyi-modules/Property/src/main/java/org/dromara/property/mapper/CustomerActivityMapper.java new file mode 100644 index 00000000..d97e720b --- /dev/null +++ b/ruoyi-modules/Property/src/main/java/org/dromara/property/mapper/CustomerActivityMapper.java @@ -0,0 +1,15 @@ +package org.dromara.property.mapper; + +import org.dromara.property.domain.CustomerActivity; +import org.dromara.property.domain.vo.CustomerActivityVo; +import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; + +/** + * 客户服务-活动Mapper接口 + * + * @author yuyongle + * @date 2025-09-08 + */ +public interface CustomerActivityMapper extends BaseMapperPlus { + +} diff --git a/ruoyi-modules/Property/src/main/java/org/dromara/property/service/ICustomerActivityService.java b/ruoyi-modules/Property/src/main/java/org/dromara/property/service/ICustomerActivityService.java new file mode 100644 index 00000000..94be834f --- /dev/null +++ b/ruoyi-modules/Property/src/main/java/org/dromara/property/service/ICustomerActivityService.java @@ -0,0 +1,69 @@ +package org.dromara.property.service; + +import org.dromara.property.domain.CustomerActivity; +import org.dromara.property.domain.vo.CustomerActivityVo; +import org.dromara.property.domain.bo.CustomerActivityBo; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.mybatis.core.page.PageQuery; + +import java.util.Collection; +import java.util.List; + +/** + * 客户服务-活动Service接口 + * + * @author yuyongle + * @date 2025-09-08 + */ +public interface ICustomerActivityService { + + /** + * 查询客户服务-活动 + * + * @param id 主键 + * @return 客户服务-活动 + */ + CustomerActivityVo queryById(Long id); + + /** + * 分页查询客户服务-活动列表 + * + * @param bo 查询条件 + * @param pageQuery 分页参数 + * @return 客户服务-活动分页列表 + */ + TableDataInfo queryPageList(CustomerActivityBo bo, PageQuery pageQuery); + + /** + * 查询符合条件的客户服务-活动列表 + * + * @param bo 查询条件 + * @return 客户服务-活动列表 + */ + List queryList(CustomerActivityBo bo); + + /** + * 新增客户服务-活动 + * + * @param bo 客户服务-活动 + * @return 是否新增成功 + */ + Boolean insertByBo(CustomerActivityBo bo); + + /** + * 修改客户服务-活动 + * + * @param bo 客户服务-活动 + * @return 是否修改成功 + */ + Boolean updateByBo(CustomerActivityBo bo); + + /** + * 校验并批量删除客户服务-活动信息 + * + * @param ids 待删除的主键集合 + * @param isValid 是否进行有效性校验 + * @return 是否删除成功 + */ + Boolean deleteWithValidByIds(Collection ids, Boolean isValid); +} diff --git a/ruoyi-modules/Property/src/main/java/org/dromara/property/service/ICustomerNoticesService.java b/ruoyi-modules/Property/src/main/java/org/dromara/property/service/ICustomerNoticesService.java index 0376d125..812bd787 100644 --- a/ruoyi-modules/Property/src/main/java/org/dromara/property/service/ICustomerNoticesService.java +++ b/ruoyi-modules/Property/src/main/java/org/dromara/property/service/ICustomerNoticesService.java @@ -65,4 +65,13 @@ public interface ICustomerNoticesService { * @return 是否删除成功 */ Boolean deleteWithValidByIds(Collection ids, Boolean isValid); + + //APP端 + /** + * 头条滚动列表 + * @param bo + * @param pageQuery + * @return + */ + TableDataInfo todayList(CustomerNoticesBo bo, PageQuery pageQuery); } diff --git a/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/CustomerActivityServiceImpl.java b/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/CustomerActivityServiceImpl.java new file mode 100644 index 00000000..ae554982 --- /dev/null +++ b/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/CustomerActivityServiceImpl.java @@ -0,0 +1,162 @@ +package org.dromara.property.service.impl; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import org.apache.dubbo.config.annotation.DubboReference; +import org.dromara.common.core.utils.MapstructUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.mybatis.core.page.PageQuery; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.satoken.utils.LoginHelper; +import org.dromara.system.api.RemoteUserService; +import org.dromara.system.api.model.LoginUser; +import org.springframework.stereotype.Service; +import org.dromara.property.domain.bo.CustomerActivityBo; +import org.dromara.property.domain.vo.CustomerActivityVo; +import org.dromara.property.domain.CustomerActivity; +import org.dromara.property.mapper.CustomerActivityMapper; +import org.dromara.property.service.ICustomerActivityService; + +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.Collection; + +/** + * 客户服务-活动Service业务层处理 + * + * @author yuyongle + * @date 2025-09-08 + */ +@Slf4j +@RequiredArgsConstructor +@Service +public class CustomerActivityServiceImpl implements ICustomerActivityService { + + private final CustomerActivityMapper baseMapper; + @DubboReference + private RemoteUserService remoteUserService; + + /** + * 查询客户服务-活动 + * + * @param id 主键 + * @return 客户服务-活动 + */ + @Override + public CustomerActivityVo queryById(Long id){ + CustomerActivityVo customerActivityVo = baseMapper.selectVoById(id); + String issuersText = remoteUserService.selectNicknameById(customerActivityVo.getIssuers()); + customerActivityVo.setIssuersText(issuersText); + return customerActivityVo; + } + + /** + * 分页查询客户服务-活动列表 + * + * @param bo 查询条件 + * @param pageQuery 分页参数 + * @return 客户服务-活动分页列表 + */ + @Override + public TableDataInfo queryPageList(CustomerActivityBo bo, PageQuery pageQuery) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + Page result = baseMapper.selectVoPage(pageQuery.build(), lqw); + if(CollUtil.isNotEmpty(result.getRecords())){ + result.getRecords().forEach(r -> r.setIssuersText(remoteUserService.selectNicknameById(r.getIssuers()))); + } + return TableDataInfo.build(result); + } + + /** + * 查询符合条件的客户服务-活动列表 + * + * @param bo 查询条件 + * @return 客户服务-活动列表 + */ + @Override + public List queryList(CustomerActivityBo bo) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + return baseMapper.selectVoList(lqw); + } + + private LambdaQueryWrapper buildQueryWrapper(CustomerActivityBo bo) { + Map params = bo.getParams(); + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.orderByAsc(CustomerActivity::getId); + lqw.eq(StringUtils.isNotBlank(bo.getTitle()), CustomerActivity::getTitle, bo.getTitle()); + lqw.eq(StringUtils.isNotBlank(bo.getStatus()), CustomerActivity::getStatus, bo.getStatus()); + lqw.eq(bo.getStartTime() != null, CustomerActivity::getStartTime, bo.getStartTime()); + lqw.eq(bo.getEndTime() != null, CustomerActivity::getEndTime, bo.getEndTime()); + return lqw; + } + + /** + * 新增客户服务-活动 + * + * @param bo 客户服务-活动 + * @return 是否新增成功 + */ + @Override + public Boolean insertByBo(CustomerActivityBo bo) { + CustomerActivity add = MapstructUtils.convert(bo, CustomerActivity.class); + validEntityBeforeSave(add); + //获取当前登录 用户 + LoginUser user = LoginHelper.getLoginUser(); + add.setIssuers(user.getUserId()); + boolean flag = baseMapper.insert(add) > 0; + if (flag) { + bo.setId(add.getId()); + } + return flag; + } + + /** + * 修改客户服务-活动 + * + * @param bo 客户服务-活动 + * @return 是否修改成功 + */ + @Override + public Boolean updateByBo(CustomerActivityBo bo) { + CustomerActivity update = MapstructUtils.convert(bo, CustomerActivity.class); + validEntityBeforeSave(update); + return baseMapper.updateById(update) > 0; + } + + /** + * 保存前的数据校验 + */ + private void validEntityBeforeSave(CustomerActivity entity){ + //TODO 做一些数据校验,如唯一约束 + //判断当前时间是否在开始时间和结束时间之间 + Date now = new Date(); + if (entity.getStartTime() != null && entity.getEndTime() != null) { + entity.setStatus( + now.before(entity.getStartTime()) ? "1" : + now.after(entity.getEndTime()) ? "3" : "2" + ); + } + } + + /** + * 校验并批量删除客户服务-活动信息 + * + * @param ids 待删除的主键集合 + * @param isValid 是否进行有效性校验 + * @return 是否删除成功 + */ + @Override + public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { + if(isValid){ + //TODO 做一些业务上的校验,判断是否需要校验 + } + return baseMapper.deleteByIds(ids) > 0; + } +} diff --git a/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/CustomerNoticesServiceImpl.java b/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/CustomerNoticesServiceImpl.java index f2ccdc1c..336e9542 100644 --- a/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/CustomerNoticesServiceImpl.java +++ b/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/CustomerNoticesServiceImpl.java @@ -237,4 +237,15 @@ public class CustomerNoticesServiceImpl implements ICustomerNoticesService { } return baseMapper.deleteByIds(ids) > 0; } + //APP端接口 + /** + * 头条滚动列表 + * @param bo + * @param pageQuery + * @return + */ + @Override + public TableDataInfo todayList(CustomerNoticesBo bo, PageQuery pageQuery) { + return queryPageList(bo, pageQuery); + } } diff --git a/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/InspectionTaskDetailServiceImpl.java b/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/InspectionTaskDetailServiceImpl.java index 04423e19..3ea7a95f 100644 --- a/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/InspectionTaskDetailServiceImpl.java +++ b/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/InspectionTaskDetailServiceImpl.java @@ -250,15 +250,15 @@ public class InspectionTaskDetailServiceImpl implements IInspectionTaskDetailSer private void dataProcessing(MInspectionTaskDetailVo mInspectionTaskDetailVo, Map pointNameMap) { mInspectionTaskDetailVo.setPointName(ObjectUtil.defaultIfNull(pointNameMap.get(mInspectionTaskDetailVo.getPointId()), "未知点位")); //查询工单 - if(ObjectUtil.isNotEmpty(mInspectionTaskDetailVo.getOrderId())){ + if (ObjectUtil.isNotEmpty(mInspectionTaskDetailVo.getOrderId())) { ServiceWorkOrdersVo serviceWorkOrdersVo = serviceWorkOrdersMapper.selectVoById(mInspectionTaskDetailVo.getOrderId()); - if(ObjectUtil.isNotEmpty(serviceWorkOrdersVo)){ + if (ObjectUtil.isNotEmpty(serviceWorkOrdersVo)) { List serviceWorkOrdersRecordVos = workOrdersRecordMapper.selectVoList( new LambdaQueryWrapper<>(ServiceWorkOrdersRecord.class).eq(ServiceWorkOrdersRecord::getOrderId, serviceWorkOrdersVo.getId()) ); List mServiceWorkOrdersRecordVos = BeanUtil.copyToList(serviceWorkOrdersRecordVos, MServiceWorkOrdersRecordVo.class); serviceWorkOrdersVo.setRecordVoList(mServiceWorkOrdersRecordVos); - mInspectionTaskDetailVo.setMServiceWorkOrdersVo(ObjectUtil.isNotEmpty( serviceWorkOrdersVo)? BeanUtil.copyProperties(serviceWorkOrdersVo, MServiceWorkOrdersVo.class):null); + mInspectionTaskDetailVo.setMServiceWorkOrdersVo(ObjectUtil.isNotEmpty(serviceWorkOrdersVo) ? BeanUtil.copyProperties(serviceWorkOrdersVo, MServiceWorkOrdersVo.class) : null); } } @@ -295,7 +295,18 @@ public class InspectionTaskDetailServiceImpl implements IInspectionTaskDetailSer Assert.isTrue(planInspectionPersonIds.contains(loginUser.getUserId()), "当前签到人不在计划巡检人列表内"); bo.setActualInspectionPerson(loginUser.getUserId().toString()); InspectionTaskDetail update = MapstructUtils.convert(bo, InspectionTaskDetail.class); - return baseMapper.updateById(update) > 0; + boolean flag = baseMapper.updateById(update) > 0; + if (flag) { + + } + return flag; + } + + /** + * 新增巡检点记录 + */ + private void insertPointRecord(InspectionTaskDetail inspectionTaskDetail) { + } /** @@ -313,8 +324,10 @@ public class InspectionTaskDetailServiceImpl implements IInspectionTaskDetailSer InspectionTaskDetail update = MapstructUtils.convert(bo, InspectionTaskDetail.class); return baseMapper.updateById(update) > 0; } + /** * 巡检提报工单 + * * @param bo * @return */ @@ -327,7 +340,7 @@ public class InspectionTaskDetailServiceImpl implements IInspectionTaskDetailSer serviceWorkOrders.setReportingType(OrderReportingTypeEnum.PHONE_REPORT.getValue()); LoginUser user = LoginHelper.getLoginUser(); serviceWorkOrders.setOrderNo("GD" + IdUtil.getSnowflakeNextIdStr()); - serviceWorkOrders.setOrderName("巡检"+bo.getPointId()); + serviceWorkOrders.setOrderName("巡检" + bo.getPointId()); serviceWorkOrders.setStatus(WorkOrderStatusEnum.CREATE_ORDER.getValue()); serviceWorkOrders.setInitiatorPeople(user.getNickname()); serviceWorkOrders.setProcessingWeight(serviceWorkOrdersType.getProcessingWeight()); @@ -343,14 +356,15 @@ public class InspectionTaskDetailServiceImpl implements IInspectionTaskDetailSer boolean flags = workOrdersRecordMapper.insert(serviceWorkOrdersRecord) > 0; if (flags) { if (serviceWorkOrdersType.getOperationMode().equals(OrderTypeOperationEnum.AUTOMATE_DISPATCH.getValue())) { - handleServiceWorkOrder(serviceWorkOrders,serviceWorkOrdersType,bo); + handleServiceWorkOrder(serviceWorkOrders, serviceWorkOrdersType, bo); } } } return flag; } + //自动派单 - private void handleServiceWorkOrder(ServiceWorkOrders serviceWorkOrders,ServiceWorkOrdersType serviceWorkOrdersType,InspectionTaskDetailToOrderBo bo) { + private void handleServiceWorkOrder(ServiceWorkOrders serviceWorkOrders, ServiceWorkOrdersType serviceWorkOrdersType, InspectionTaskDetailToOrderBo bo) { LocalDate today = LocalDate.now(); // 1. 获取今日排班人员(优先查缓存,未命中则查询数据库并缓存) List attendanceUserGroups = RedisUtils.getCacheList(DateUtil.today()); @@ -361,8 +375,8 @@ public class InspectionTaskDetailServiceImpl implements IInspectionTaskDetailSer .eq(AttendanceUserGroup::getDeptId, serviceWorkOrdersType.getDeptId()) .orderByAsc(AttendanceUserGroup::getStartDate) ); - if (CollUtil.isEmpty(attendanceUserGroups)|| attendanceUserGroups.size() != attendanceUserGroupList.size()) { - attendanceUserGroups=attendanceUserGroupList; + if (CollUtil.isEmpty(attendanceUserGroups) || attendanceUserGroups.size() != attendanceUserGroupList.size()) { + attendanceUserGroups = attendanceUserGroupList; Assert.isTrue(CollUtil.isNotEmpty(attendanceUserGroups), "暂无排班人员"); // 缓存当天排班数据(假设当天不会变) RedisUtils.setCacheList(DateUtil.today(), attendanceUserGroups); diff --git a/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/ServiceWorkOrdersServiceImpl.java b/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/ServiceWorkOrdersServiceImpl.java index 2afb6c2a..e54e1b34 100644 --- a/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/ServiceWorkOrdersServiceImpl.java +++ b/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/ServiceWorkOrdersServiceImpl.java @@ -586,6 +586,7 @@ public class ServiceWorkOrdersServiceImpl implements IServiceWorkOrdersService { add.setOrderName("工单名称"); add.setStatus(WorkOrderStatusEnum.CREATE_ORDER.getValue()); add.setReportingType(OrderReportingTypeEnum.PHONE_REPORT.getValue()); + add.setProcessingWeight(serviceWorkOrdersType.getProcessingWeight()); add.setInitiatorPeople(user.getNickname()); validEntityBeforeSave(add); boolean flag = baseMapper.insert(add) > 0; diff --git a/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/TbRoomServiceImpl.java b/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/TbRoomServiceImpl.java index c7b2de9e..77db89e3 100644 --- a/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/TbRoomServiceImpl.java +++ b/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/TbRoomServiceImpl.java @@ -30,6 +30,7 @@ import org.springframework.stereotype.Service; import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; /** * 房间信息Service业务层处理 @@ -68,10 +69,12 @@ public class TbRoomServiceImpl implements ITbRoomService { tbRoomVo.setFloorText(ObjectUtil.isNotEmpty(tbFloorVo) ? tbFloorVo.getFloorName() : null); List residentUnits = residentUnitMapper.selectList( new LambdaQueryWrapper() - .eq(ResidentUnit::getLocation, tbRoomVo.getId()) + .like(ResidentUnit::getLocation, tbRoomVo.getId()) + .orderByDesc(ResidentUnit::getCreateTime) ); if (CollUtil.isNotEmpty(residentUnits)) { - tbRoomVo.setResidentUnitText(residentUnits.get(0).getName()); + //多个yi,拼接 + tbRoomVo.setResidentUnitText(residentUnits.stream().map(ResidentUnit::getName).collect(Collectors.joining(","))); } return tbRoomVo; } diff --git a/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/residentImpl/ResidentUnitServiceImpl.java b/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/residentImpl/ResidentUnitServiceImpl.java index b1fbf5b0..f2a2e460 100644 --- a/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/residentImpl/ResidentUnitServiceImpl.java +++ b/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/residentImpl/ResidentUnitServiceImpl.java @@ -1,6 +1,8 @@ package org.dromara.property.service.impl.residentImpl; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.digest.BCrypt; import org.dromara.common.core.utils.MapstructUtils; import org.dromara.common.core.utils.StringUtils; @@ -12,7 +14,9 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.dromara.property.domain.entity.resident.ResidentPerson; +import org.dromara.property.domain.vo.TbRoomVo; import org.dromara.property.mapper.ResidentPersonMapper; +import org.dromara.property.mapper.TbRoomMapper; import org.dromara.property.service.residentService.IResidentPersonService; import org.dromara.property.service.ITbRoomService; import org.springframework.stereotype.Service; @@ -43,6 +47,7 @@ public class ResidentUnitServiceImpl implements IResidentUnitService { private final ResidentUnitMapper baseMapper; private final ITbRoomService roomService; + private final TbRoomMapper roomMapper; private final IResidentPersonService personService; private final ResidentPersonMapper personMapper; @@ -134,6 +139,7 @@ public class ResidentUnitServiceImpl implements IResidentUnitService { if (flag) { bo.setId(add.getId()); addResidentPerson(add); + } return flag; } @@ -170,12 +176,27 @@ public class ResidentUnitServiceImpl implements IResidentUnitService { validEntityBeforeSave(update); return baseMapper.updateById(update) > 0; } - /** * 保存前的数据校验 */ private void validEntityBeforeSave(ResidentUnit entity){ //TODO 做一些数据校验,如唯一约束 + //查询入驻房间总面积 + String roomId= entity.getLocation(); + if(StrUtil.isNotEmpty(roomId)){ + //roomId转换为Long类型的list + // 完整的代码实现 + List idList = Arrays.stream(roomId.split(",")) + .map(Long::parseLong) + .collect(Collectors.toList()); + List tbRoomVos = roomMapper.selectVoByIds(idList); + if(CollUtil.isNotEmpty(tbRoomVos)){ + Float totalArea = tbRoomVos.stream() + .map(TbRoomVo::getArea) + .reduce(0.0f, Float::sum); + entity.setArea(totalArea); + } + } } /** diff --git a/ruoyi-modules/Property/src/main/resources/mapper/Property/CustomerActivityMapper.xml b/ruoyi-modules/Property/src/main/resources/mapper/Property/CustomerActivityMapper.xml new file mode 100644 index 00000000..9d57ced4 --- /dev/null +++ b/ruoyi-modules/Property/src/main/resources/mapper/Property/CustomerActivityMapper.xml @@ -0,0 +1,7 @@ + + + + + From 6a2898e0d741ab3517d3a6b7b182a5e706629669 Mon Sep 17 00:00:00 2001 From: zcxlsm Date: Mon, 8 Sep 2025 17:48:10 +0800 Subject: [PATCH 2/2] =?UTF-8?q?feat(Property):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E5=AE=9A=E6=97=B6=E4=BB=BB=E5=8A=A1=E6=89=A7=E8=A1=8C=E9=80=BB?= =?UTF-8?q?=E8=BE=91=E5=B9=B6=E6=B7=BB=E5=8A=A0=E6=97=B6=E9=97=B4=E9=99=90?= =?UTF-8?q?=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TbMeterInfoServiceImpl.java | 20 +- .../TbMeterRecordServiceImpl.java | 9 +- .../property/tasks/HeartbeatTasks.java | 30 ++- .../sdk/smartDevices/utils/LightingUtil.java | 202 +++++++++++------- 4 files changed, 165 insertions(+), 96 deletions(-) diff --git a/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/smartDevicesImpl/TbMeterInfoServiceImpl.java b/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/smartDevicesImpl/TbMeterInfoServiceImpl.java index 4da94807..dff02dba 100644 --- a/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/smartDevicesImpl/TbMeterInfoServiceImpl.java +++ b/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/smartDevicesImpl/TbMeterInfoServiceImpl.java @@ -266,17 +266,17 @@ public class TbMeterInfoServiceImpl implements ITbMeterInfoService { */ @Override public void getMeterStatus(Long meterType, Long floorId) { - // 参数校验 - if (meterType == 0L || floorId == 0L) { - heartbeatTasks.stopTask("Meter_Status_Reading"); - return; - } - // 获取当前登录用户 LoginUser user = LoginHelper.getLoginUser(); String tokenValue = StpUtil.getTokenValue(); if (user == null) { - heartbeatTasks.stopTask("Meter_Status_Reading"); + heartbeatTasks.stopTask(tokenValue); + return; + } + + // 参数校验 + if (meterType == 0L || floorId == 0L) { + heartbeatTasks.stopTask(tokenValue); return; } @@ -292,7 +292,7 @@ public class TbMeterInfoServiceImpl implements ITbMeterInfoService { // 如果没有仪表信息,直接返回 if (meterInfoVoList.isEmpty()) { - heartbeatTasks.stopTask("Meter_Status_Reading"); + heartbeatTasks.stopTask(tokenValue); jsonObject.put("readingTime", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss")); jsonObject.put("data", new ArrayList<>()); remoteMessageService.sendMessage(user.getUserId(), tokenValue, jsonObject.toString()); @@ -309,7 +309,7 @@ public class TbMeterInfoServiceImpl implements ITbMeterInfoService { } // 启动定时任务 - heartbeatTasks.startHeartbeatTask("Meter_Status_Reading", () -> { + heartbeatTasks.startHeartbeatTask(tokenValue, () -> { jsonObject.put("readingTime", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss")); List meterResults; @@ -325,7 +325,7 @@ public class TbMeterInfoServiceImpl implements ITbMeterInfoService { // 处理仪表读数和状态 processMeterResults(user, jsonObject, meterResults, meterInfoVoList, tokenValue); - }, 30000); + }, 30000,300000); } /** diff --git a/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/smartDevicesImpl/TbMeterRecordServiceImpl.java b/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/smartDevicesImpl/TbMeterRecordServiceImpl.java index 1492aaeb..5e917eab 100644 --- a/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/smartDevicesImpl/TbMeterRecordServiceImpl.java +++ b/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/smartDevicesImpl/TbMeterRecordServiceImpl.java @@ -212,12 +212,8 @@ public class TbMeterRecordServiceImpl implements ITbMeterRecordService { // 设置上次读数 if (hasOldRecords) { TbMeterRecord oldRecord = oldRecordMap.get(info.getId()); - if (oldRecord != null) { - record.setPreviousReading(oldRecord.getCurrentReading()); - } else { - // 如果没有找到对应的旧记录,使用默认值 - record.setPreviousReading(record.getCurrentReading()); - } + // 如果没有找到对应的旧记录,使用默认值 + record.setPreviousReading(Objects.requireNonNullElse(oldRecord, record).getCurrentReading()); } else { record.setPreviousReading(record.getCurrentReading()); } @@ -308,7 +304,6 @@ public class TbMeterRecordServiceImpl implements ITbMeterRecordService { private Map trendMonthData(String floorId, String meterId, Long meterType, String year) { Map resultMap = new HashMap<>(); List> monthList = baseMapper.getMonthTrend(StrUtil.isBlank(floorId) ? null : Long.parseLong(floorId), StrUtil.isBlank(meterId) ? null : Long.parseLong(meterId), meterType, year); - log.info("year:{},monthList:{}", year, monthList); List monthData = new ArrayList<>(); monthList.forEach(item -> monthData.add(new String[]{item.get("month").toString(), item.get("total_consumption").toString()})); Float total = monthList.stream().map(map -> new BigDecimal(map.get("total_consumption").toString())).reduce(BigDecimal::add).orElse(BigDecimal.ZERO).floatValue(); diff --git a/ruoyi-modules/Property/src/main/java/org/dromara/property/tasks/HeartbeatTasks.java b/ruoyi-modules/Property/src/main/java/org/dromara/property/tasks/HeartbeatTasks.java index 3ea0917e..60249a4f 100644 --- a/ruoyi-modules/Property/src/main/java/org/dromara/property/tasks/HeartbeatTasks.java +++ b/ruoyi-modules/Property/src/main/java/org/dromara/property/tasks/HeartbeatTasks.java @@ -15,14 +15,36 @@ public class HeartbeatTasks { private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); private final Map> tasks = new ConcurrentHashMap<>(); - public void startHeartbeatTask(String taskId, Runnable task, long intervalMs) { + public void startHeartbeatTask(String taskId, Runnable task, long intervalMs, long durationMs) { // 先停止同名任务(如果存在) stopTask(taskId); - // 创建新任务 - ScheduledFuture future = scheduler.scheduleAtFixedRate( - task, 0, intervalMs, TimeUnit.MILLISECONDS); + // 如果 durationMs 为 0,表示任务无需时间限制 + if (durationMs <= 0) { + ScheduledFuture future = scheduler.scheduleAtFixedRate( + task, + 0, + intervalMs, + TimeUnit.MILLISECONDS + ); + tasks.put(taskId, future); + return; + } + // 创建一个包装任务,带时长检查 + long startTime = System.currentTimeMillis(); + ScheduledFuture future = scheduler.scheduleAtFixedRate( + () -> { + long elapsedTime = System.currentTimeMillis() - startTime; + if (elapsedTime >= durationMs) { + stopTask(taskId); + } + task.run(); + }, + 0, + intervalMs, + TimeUnit.MILLISECONDS + ); tasks.put(taskId, future); } diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/smartDevices/utils/LightingUtil.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/smartDevices/utils/LightingUtil.java index 61ca06ed..d5847ae8 100644 --- a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/smartDevices/utils/LightingUtil.java +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/sdk/smartDevices/utils/LightingUtil.java @@ -9,6 +9,8 @@ import java.io.IOException; import java.net.Socket; import java.nio.ByteBuffer; import java.nio.ByteOrder; +import java.util.ArrayList; +import java.util.List; import static com.ghgande.j2mod.modbus.Modbus.WRITE_SINGLE_REGISTER; @@ -24,9 +26,8 @@ public class LightingUtil { private static final int MODBUS_PORT = 502; // 功能码03(读保持寄存器) private static final byte FUNCTION_CODE = 0x03; - // 采集寄存器范围(协议地址) - private static final int START_ADDRESS = 42; // 40043 - 40001 = 42 - private static final int REGISTER_COUNT = 4; // 40046 - 40043 + 1 = 4 + // Modbus协议一次最多读取的寄存器数量 + private static final int MAX_REGISTERS_PER_REQUEST = 63; private Socket socket; private DataInputStream input; @@ -70,78 +71,6 @@ public class LightingUtil { return header; } - /** - * 读取40043-40046寄存器数据 - * - * @return 包含4个寄存器值的int数组 - */ - public int[] readRegisters() throws IOException { - // 发送读取请求 - sendRequest(); - - // 接收并解析响应 - return parseResponse(); - } - - /** - * 构造并发送Modbus TCP请求帧 - */ - private void sendRequest() throws IOException { - // 事务ID(递增) - int currentTransactionId = transactionId++; - - // 创建请求帧(12字节) - ByteBuffer buffer = ByteBuffer.allocate(12) - .order(ByteOrder.BIG_ENDIAN); - - // Header(7字节) - buffer.putShort((short) currentTransactionId); // 事务ID - buffer.putShort((short) 0); // 协议ID(0=Modbus) - buffer.putShort((short) 6); // 长度(后续字节数) - buffer.put((byte) 1); // 单元ID - - // PDU(协议数据单元) - buffer.put(FUNCTION_CODE); // 功能码 - buffer.putShort((short) START_ADDRESS); // 起始地址 - buffer.putShort((short) REGISTER_COUNT); // 寄存器数量 - - output.write(buffer.array()); - output.flush(); - } - - /** - * 解析Modbus TCP响应 - */ - private int[] parseResponse() throws IOException { - // 读取头(7字节) - byte[] header = initParse(); - - // 读取PDU(协议数据单元) - int pduLength = ByteBuffer.wrap(header, 4, 2) - .getShort() & 0xFFFF - 1; // 减去单元ID长度 - byte[] pdu = new byte[pduLength]; - input.readFully(pdu); - - // 检查异常响应(功能码高位为1) - if ((pdu[0] & 0xFF) == (FUNCTION_CODE | 0x80)) { - throw new IOException("Modbus异常响应,错误码: " + (pdu[1] & 0xFF)); - } - - // 验证功能码和字节数 - if (pdu[0] != FUNCTION_CODE || pdu[1] != REGISTER_COUNT * 2) { - throw new IOException("无效响应格式"); - } - - // 提取寄存器数据(每个寄存器2字节) - int[] values = new int[REGISTER_COUNT]; - for (int i = 0; i < REGISTER_COUNT; i++) { - int offset = 2 + i * 2; - values[i] = ByteBuffer.wrap(pdu, offset, 2) - .order(ByteOrder.BIG_ENDIAN).getShort() & 0xFFFF; - } - return values; - } - /** * 写单个保持寄存器(功能码06) * @@ -214,5 +143,128 @@ public class LightingUtil { return true; } + /** + * 读取指定数量的开关状态 + * + * @param startAddress 起始地址(协议地址) + * @param switchCount 开关数量 + * @return 包含所有开关状态的int数组,每个元素代表一个开关的状态 + * @throws IOException 如果读取过程中发生IO错误 + */ + public int[] readSwitchStatus(int startAddress, int switchCount) throws IOException { + // 如果开关数量超过单次请求限制,分批读取 + if (switchCount > MAX_REGISTERS_PER_REQUEST) { + return readSwitchStatusBatch(startAddress, switchCount); + } + + // 发送读取请求 + sendCustomRequest(startAddress, switchCount); + + // 接收并解析响应 + return parseCustomResponse(switchCount); + } + + /** + * 分批读取大量开关状态 + */ + private int[] readSwitchStatusBatch(int startAddress, int totalSwitchCount) throws IOException { + List allValues = new ArrayList<>(); + int remaining = totalSwitchCount; + int currentAddress = startAddress; + + while (remaining > 0) { + int batchSize = Math.min(remaining, MAX_REGISTERS_PER_REQUEST); + + // 发送读取请求 + sendCustomRequest(currentAddress, batchSize); + + // 接收并解析响应 + int[] batchValues = parseCustomResponse(batchSize); + + // 添加到结果列表 + for (int value : batchValues) { + allValues.add(value); + } + + // 更新剩余数量和当前地址 + remaining -= batchSize; + currentAddress += batchSize; + + // 添加小延迟,避免请求过快 + try { + Thread.sleep(10); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new IOException("读取过程被中断", e); + } + } + + // 转换为数组返回 + int[] result = new int[allValues.size()]; + for (int i = 0; i < allValues.size(); i++) { + result[i] = allValues.get(i); + } + return result; + } + + /** + * 构造并发送自定义Modbus TCP请求帧 + */ + private void sendCustomRequest(int startAddress, int registerCount) throws IOException { + // 事务ID(递增) + int currentTransactionId = transactionId++; + + // 创建请求帧(12字节) + ByteBuffer buffer = ByteBuffer.allocate(12) + .order(ByteOrder.BIG_ENDIAN); + + // Header(7字节) + buffer.putShort((short) currentTransactionId); // 事务ID + buffer.putShort((short) 0); // 协议ID(0=Modbus) + buffer.putShort((short) 6); // 长度(后续字节数) + buffer.put((byte) 1); // 单元ID + + // PDU(协议数据单元) + buffer.put(FUNCTION_CODE); // 功能码 + buffer.putShort((short) startAddress); // 起始地址 + buffer.putShort((short) registerCount); // 寄存器数量 + + output.write(buffer.array()); + output.flush(); + } + + /** + * 解析自定义Modbus TCP响应 + */ + private int[] parseCustomResponse(int expectedRegisterCount) throws IOException { + // 读取头(7字节) + byte[] header = initParse(); + + // 读取PDU(协议数据单元) + int pduLength = ByteBuffer.wrap(header, 4, 2) + .getShort() & 0xFFFF - 1; // 减去单元ID长度 + byte[] pdu = new byte[pduLength]; + input.readFully(pdu); + + // 检查异常响应(功能码高位为1) + if ((pdu[0] & 0xFF) == (FUNCTION_CODE | 0x80)) { + throw new IOException("Modbus异常响应,错误码: " + (pdu[1] & 0xFF)); + } + + // 验证功能码和字节数 + if (pdu[0] != FUNCTION_CODE || pdu[1] != expectedRegisterCount * 2) { + throw new IOException("无效响应格式"); + } + + // 提取寄存器数据(每个寄存器2字节) + int[] values = new int[expectedRegisterCount]; + for (int i = 0; i < expectedRegisterCount; i++) { + int offset = 2 + i * 2; + values[i] = ByteBuffer.wrap(pdu, offset, 2) + .order(ByteOrder.BIG_ENDIAN).getShort() & 0xFFFF; + } + return values; + } + }