Pārlūkot izejas kodu

Merge remote-tracking branch 'origin/master'

luo.yibo@datuai.com 1 gadu atpakaļ
vecāks
revīzija
51a4bc60e5
25 mainītis faili ar 488 papildinājumiem un 32 dzēšanām
  1. 23 1
      ruoyi-api/ruoyi-api-backstage/src/main/java/org/dromara/backstage/api/RemoteBagService.java
  2. 5 0
      ruoyi-api/ruoyi-api-backstage/src/main/java/org/dromara/backstage/api/domain/bo/RemoteCardBo.java
  3. 22 0
      ruoyi-api/ruoyi-api-hotel/src/main/java/org/dromara/hotel/api/service/RemoteAreaPermissionsService.java
  4. 4 4
      ruoyi-common/ruoyi-common-dubbo/src/main/resources/common-dubbo.yml
  5. 2 1
      ruoyi-common/ruoyi-common-message/src/main/java/org/dromara/common/message/kafka/constant/MessageEventTypeConstants.java
  6. 6 0
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/basics/controller/PtRoomTypeController.java
  7. 7 0
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/basics/service/IPtAreaService.java
  8. 4 0
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/basics/service/IPtRoomService.java
  9. 79 1
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/basics/service/impl/PtAreaServiceImpl.java
  10. 71 2
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/basics/service/impl/PtRoomServiceImpl.java
  11. 20 8
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/basics/service/impl/PtRoomTypeServiceImpl.java
  12. 1 0
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/cardCenter/controller/CardApiController.java
  13. 98 7
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/controller/self/SelfController.java
  14. 10 0
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/payment/controller/PtUserAccountController.java
  15. 2 0
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/payment/domain/PtUserAccount4SelectVo.java
  16. 7 0
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/payment/dubbo/RemoteBagServiceImpl.java
  17. 2 0
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/payment/mapper/PtUserAccountMapper.java
  18. 2 0
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/payment/service/IPtUserAccountService.java
  19. 19 0
      ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/payment/service/impl/PtUserAccountServiceImpl.java
  20. 10 0
      ruoyi-modules/ruoyi-backstage/src/main/resources/mapper/payment/PtUserAccountMapper.xml
  21. 9 0
      ruoyi-modules/ruoyi-hotel/src/main/java/org/dromara/hotel/controller/KfProvideCardHisController.java
  22. 39 0
      ruoyi-modules/ruoyi-hotel/src/main/java/org/dromara/hotel/dubbo/RemoteAreaPermissionsServiceImpl.java
  23. 22 8
      ruoyi-modules/ruoyi-hotel/src/main/java/org/dromara/hotel/service/impl/KfProvideCardHisServiceImpl.java
  24. 23 0
      ruoyi-server/ruoyi-server-base/src/main/java/org/dromara/server/base/service/yktOperation/SyncRemotePtCardCenterService.java
  25. 1 0
      ruoyi-server/ruoyi-server-mqdata/src/main/java/org/dromara/server/mq/event/kafka/impl/yktOperation/PtCardCenterEventStrategyImpl.java

+ 23 - 1
ruoyi-api/ruoyi-api-backstage/src/main/java/org/dromara/backstage/api/RemoteBagService.java

@@ -4,6 +4,8 @@ import org.dromara.backstage.api.domain.bo.RemoteCardBo;
 import org.dromara.backstage.api.domain.bo.RemoteConsumptionBo;
 import org.dromara.backstage.api.domain.bo.RemotePurseInOutBo;
 
+import java.util.Map;
+
 /**
  * name: RemoteBagService
  * package: org.dromara.backstage.api
@@ -22,15 +24,35 @@ public interface RemoteBagService {
      * @return 余额串,英文逗号分隔
      */
     String selectAccountBalanceByIds(String userIds);
-
+    /**
+     * 充值
+     */
     Boolean recharge(RemotePurseInOutBo bo);
+    /**
+     * 退款
+     */
     Boolean refund(RemotePurseInOutBo bo);
     Boolean createErrFillRecord(RemoteConsumptionBo bo);
     Boolean batchRecharge(RemotePurseInOutBo bo, Long[] userIds);
     Boolean batchRefund(RemotePurseInOutBo bo, Long[] userIds);
+    /**
+     * 批量设置余额
+     */
     Boolean batchSetBalance(RemotePurseInOutBo bo, Long[] userIds);
+
+    /**
+     * 挂失卡片
+     */
     Boolean lockCard(Long cardId);
     Boolean lockCardByBo(RemoteCardBo bo);
+
+    /**
+     * 回收卡片
+     */
+    Boolean recycleCard(RemoteCardBo bo);
+    /**
+     * 解挂卡片
+     */
     Boolean unlockCard(Long cardId);
 
     Boolean writeCardSuccess(RemoteCardBo bo);

+ 5 - 0
ruoyi-api/ruoyi-api-backstage/src/main/java/org/dromara/backstage/api/domain/bo/RemoteCardBo.java

@@ -146,4 +146,9 @@ public class RemoteCardBo implements Serializable {
      * 更新时间
      */
     private Date updateTime;
+
+    /**
+     * 操作员Id
+     */
+    private Long operatorId;
 }

+ 22 - 0
ruoyi-api/ruoyi-api-hotel/src/main/java/org/dromara/hotel/api/service/RemoteAreaPermissionsService.java

@@ -0,0 +1,22 @@
+package org.dromara.hotel.api.service;
+
+import java.util.List;
+
+/**
+ * @ClassName RemoteAreaPermissionsService
+ * @Description 酒店系统客房权限远程服务接口
+ * @Author xiari
+ * @Date 2025-4-21
+ * @Version 1.0
+ * @since jdk17
+ */
+public interface RemoteAreaPermissionsService {
+
+
+    /**
+     * 根据用户id获取区域楼栋权限
+     * @param userId
+     * @return
+     */
+    List<Long> getAreaPermissions(Long userId);
+}

+ 4 - 4
ruoyi-common/ruoyi-common-dubbo/src/main/resources/common-dubbo.yml

@@ -20,16 +20,16 @@ dubbo:
     parameters:
       namespace: ${spring.profiles.active}
   metadata-report:
-    #address: redis://${spring.data.redis.host}:${spring.data.redis.port}
+    address: redis://${spring.data.redis.host}:${spring.data.redis.port}
     group: DUBBO_GROUP
     username: dubbo
     password: ${spring.data.redis.password}
     # redis 集群模式
-    cluster: true
+    cluster: false
     parameters:
       namespace: ${spring.profiles.active}
-      #database: ${spring.data.redis.database}
-      backup: ${spring.data.redis.cluster.nodes}
+      database: ${spring.data.redis.database}
+#      backup: ${spring.data.redis.cluster.nodes}
   # 消费者相关配置
   consumer:
     # 结果缓存(LRU算法)

+ 2 - 1
ruoyi-common/ruoyi-common-message/src/main/java/org/dromara/common/message/kafka/constant/MessageEventTypeConstants.java

@@ -139,7 +139,8 @@ public class MessageEventTypeConstants {
     public static final String CARD_OPERATION = "YKT_109_CARD_WRITE";
     /** 卡务中心 挂失*/
     public static final String	CARD_LOCK = "YKT_109_CARD_LOCK";
-
+    /** 房态页面 回收卡片 */
+    public static final String	CARD_RECOVERY = "YKT_109_CARD_RECOVERY";
     /** 补助设置新增 */
     public static final String	SUBSIDY_ADD = "YKT_102_ADD";
 

+ 6 - 0
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/basics/controller/PtRoomTypeController.java

@@ -37,6 +37,8 @@ public class PtRoomTypeController extends BaseController {
 
     private final IPtRoomTypeService ptRoomTypeService;
 
+
+
     /**
      * 查询房型管理列表
      */
@@ -46,6 +48,10 @@ public class PtRoomTypeController extends BaseController {
         return ptRoomTypeService.queryPageList(bo, pageQuery);
     }
 
+    /**
+     * 按房型统计房间数量
+     * @return
+     */
 //    @SaCheckPermission("roomType:ptRoomType:list")
     @GetMapping("/all")
     public R<List<PtRoomTypeVo>> all() {

+ 7 - 0
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/basics/service/IPtAreaService.java

@@ -38,6 +38,13 @@ public interface IPtAreaService {
     List<PtAreaVo> queryListHasKF();
     List<PtAreaVo> queryByLDList(List<PtAreaBo> dataList);
 
+    /**
+     * 根据楼栋ids 查询 楼层ids
+     * @param ids
+     * @return
+     */
+    List<Long> queryFloorByLDList(List<Long> ids);
+
     List<PtAreaVo> queryListLD(Long areaId);
 
     Map<Long, PtAreaVo> queryMapByIds(List<Long> ids);

+ 4 - 0
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/basics/service/IPtRoomService.java

@@ -56,6 +56,8 @@ public interface IPtRoomService {
      */
     List<PtRoomVo> selectList(PtRoomBo bo);
 
+    List<PtRoomVo> selectListByAreas(PtRoomBo bo,List<Long> areaIds);
+
     /**
      * 查询房间信息并转换成区域信息
      * @param bo 房间定义
@@ -99,6 +101,8 @@ public interface IPtRoomService {
      * @return
      */
     Map<String, Long> getCountByStatus();
+
+    public List<Long> getHasPermissionFloor(Long userId);
     /**
      * 更新客房的状态
      *

+ 79 - 1
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/basics/service/impl/PtAreaServiceImpl.java

@@ -23,7 +23,9 @@ import org.dromara.common.core.utils.StringUtils;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import lombok.RequiredArgsConstructor;
+import org.dromara.common.satoken.utils.LoginHelper;
 import org.dromara.hotel.api.domain.vo.RemoteOrderVo;
+import org.dromara.hotel.api.service.RemoteAreaPermissionsService;
 import org.dromara.hotel.api.service.RemoteOrderService;
 import org.springframework.stereotype.Service;
 import org.dromara.backstage.basics.domain.PtArea;
@@ -54,6 +56,9 @@ public class PtAreaServiceImpl implements IPtAreaService {
     @DubboReference
     private RemoteOrderService remoteOrderService;
 
+    @DubboReference
+    private RemoteAreaPermissionsService areaPermissionsService;
+
     /**
      * 查询建筑物区域
      *
@@ -82,7 +87,32 @@ public class PtAreaServiceImpl implements IPtAreaService {
     public List<PtAreaVo> queryListHasKF() {
 //        lqw.notIn(PtArea::getAreaType, BuildAreaTypeEnum.LC.code());
 
-        List<PtAreaVo> ptAreaVos = baseMapper.selectVoList();
+        boolean isAdmin = LoginHelper.isSuperAdmin();
+        Long userId = LoginHelper.getUserId();
+        List<PtAreaVo> ptAreaVos;
+        if(!isAdmin){
+            List<Long> lds = areaPermissionsService.getAreaPermissions(userId);
+            if(CollectionUtil.isEmpty(lds)){
+                return new ArrayList<>();
+            }
+            LambdaQueryWrapper<PtArea> lqw = new LambdaQueryWrapper<>();
+            List<PtAreaVo> ldAreas = baseMapper.selectVoList(lqw.in(PtArea::getAreaId, lds));
+            Set<Long> alls = new HashSet<>(lds);
+            ldAreas.forEach(ptAreaVo -> {
+                String ancestors = ptAreaVo.getAncestors();
+                if (StringUtils.isNotBlank(ancestors)) {
+                    String[] split = ancestors.split(",");
+                    alls.addAll(Arrays.stream(split).map(Long::parseLong).toList());
+                }
+            });
+            lqw.clear();
+            lqw.in(PtArea::getAreaId, alls).or().in(PtArea::getParentId,lds);
+            ptAreaVos = baseMapper.selectVoList(lqw);
+        }else {
+            ptAreaVos = baseMapper.selectVoList();
+        }
+
+//        List<PtAreaVo> ptAreaVos = baseMapper.selectVoList();
 
         List<PtAreaVo> rs = ptAreaVos.stream().filter(ptAreaVo -> !ptAreaVo.getAreaType().equals(BuildAreaTypeEnum.LC.code())).toList();
 
@@ -191,6 +221,25 @@ public class PtAreaServiceImpl implements IPtAreaService {
         return rs;
     }
 
+    /**
+     * 根据楼栋ids 查询 楼层ids
+     * @param ids
+     * @return
+     */
+    @Override
+    public List<Long> queryFloorByLDList(List<Long> ids) {
+        if(ids==null||ids.isEmpty()) return ListUtil.empty();
+        LambdaQueryWrapper<PtArea> lqw = Wrappers.lambdaQuery();
+        lqw.eq(PtArea::getAreaType, BuildAreaTypeEnum.LC.code());
+        lqw.in(PtArea::getParentId, ids).select(PtArea::getAreaId);
+        List<Long> rs = new ArrayList<>();
+        baseMapper.selectList(lqw).forEach(e->{
+            rs.add(e.getAreaId());
+        });
+        return rs;
+    }
+
+
     @Override
     public Map<Long, PtAreaVo> queryMapByIds(List<Long> ids) {
         List<PtArea> ptAreas = baseMapper.selectBatchIds(ids);
@@ -418,6 +467,19 @@ public class PtAreaServiceImpl implements IPtAreaService {
             if(CollectionUtil.isEmpty(floors)){
                 return rs;
             }
+
+            //校验权限
+            boolean isAdmin = LoginHelper.isSuperAdmin();
+            if(!isAdmin){
+                // 如果不是超级管理员,则查询用户权限
+                Long userId = LoginHelper.getUserId();
+                List<Long> lds = areaPermissionsService.getAreaPermissions(userId);
+                if(CollectionUtil.isEmpty(lds)){
+                    return rs;
+                }
+                floors = floors.stream().filter(ptAreaVo -> lds.contains(ptAreaVo.getParentId())).toList();
+            }
+
             List<Long> floorIds = floors.stream().map(PtAreaVo::getAreaId).toList();
             // 根据楼层查询所有房间
             List<PtRoomVo> guestRooms = ptRoomMapper.selectVoList(Wrappers.lambdaQuery(PtRoom.class)
@@ -492,6 +554,22 @@ public class PtAreaServiceImpl implements IPtAreaService {
         List<FloorRoomsVo> rs = new ArrayList<>();
         List<String> checkStatus =
                     List.of(HotelRoomStatusEnum.YZ.code(), HotelRoomStatusEnum.CS.code(), HotelRoomStatusEnum.SF.code(), HotelRoomStatusEnum.YD.code());
+        boolean isAdmin = LoginHelper.isSuperAdmin();
+        if(!isAdmin){
+            //校验权限
+            Long userId = LoginHelper.getUserId();
+            List<Long> areaPermissions = areaPermissionsService.getAreaPermissions(userId);
+            if(CollectionUtil.isEmpty(areaPermissions)){
+                throw new ServiceException("您没有权限查看该数据!");
+            }
+            List<Long> floorIds = queryFloorByLDList(areaPermissions);
+            if(CollectionUtil.isEmpty(floorIds)){
+                throw new ServiceException("您没有权限查看该数据!");
+            }
+           if(!floorIds.contains(param.getFloorId())){
+               throw new ServiceException("您没有权限查看该数据!");
+           }
+        }
         if(StringUtils.isEmpty(param.getMultiParams())){
 //        1.基础平台的房间数据:根据楼层、房型、房间状态、房间号 查询房间数据
             // 1.1.先查询所有房间数据

+ 71 - 2
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/basics/service/impl/PtRoomServiceImpl.java

@@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import lombok.RequiredArgsConstructor;
+import org.apache.dubbo.config.annotation.DubboReference;
 import org.dromara.backstage.basics.domain.PtRoom;
 import org.dromara.backstage.basics.domain.PtRoomType;
 import org.dromara.backstage.basics.domain.bo.PtRoomBatchSetBo;
@@ -24,7 +25,9 @@ import org.dromara.common.core.utils.MapstructUtils;
 import org.dromara.common.core.utils.StringUtils;
 import org.dromara.common.mybatis.core.page.PageQuery;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.satoken.utils.LoginHelper;
 import org.dromara.common.tenant.helper.TenantHelper;
+import org.dromara.hotel.api.service.RemoteAreaPermissionsService;
 import org.springframework.cache.annotation.CacheEvict;
 import org.springframework.cache.annotation.Cacheable;
 import org.springframework.stereotype.Service;
@@ -49,6 +52,9 @@ public class PtRoomServiceImpl implements IPtRoomService {
 
     private final PtRoomTypeMapper roomTypeMapper;
 
+    @DubboReference
+    private RemoteAreaPermissionsService areaPermissionsService;
+
     /**
      * 查询房间定义
      *
@@ -97,6 +103,15 @@ public class PtRoomServiceImpl implements IPtRoomService {
     @Override
     public TableDataInfo<PtRoomVo> queryPageListByAreaIds(QueryRoomBo bo, PageQuery pageQuery) {
         LambdaQueryWrapper<PtRoom> lqw = new LambdaQueryWrapper<>();
+        //校验权限
+        boolean isAdmin = LoginHelper.isSuperAdmin();
+        if (!isAdmin) {
+            List<Long> floors = getHasPermissionFloor(LoginHelper.getUserId());
+            if(CollectionUtil.isEmpty(floors)){
+                return TableDataInfo.build(new Page<>());
+            }
+            lqw.in(PtRoom::getAreaId, floors);
+        }
         lqw.eq(StringUtils.isNotBlank(bo.getRoomType()), PtRoom::getRoomType, bo.getRoomType());
         lqw.eq(StringUtils.isNotBlank(bo.getStatus()), PtRoom::getStatus, bo.getStatus());
         lqw.in(CollectionUtil.isNotEmpty(bo.getFloorIds()), PtRoom::getAreaId, bo.getFloorIds())
@@ -152,6 +167,16 @@ public class PtRoomServiceImpl implements IPtRoomService {
             }
 
         }
+        //校验权限
+        boolean isAdmin = LoginHelper.isSuperAdmin();
+        if (!isAdmin) {
+            List<Long> floors = getHasPermissionFloor(LoginHelper.getUserId());
+            if(CollectionUtil.isEmpty(floors)){
+                // 没有任何权限
+                return new ArrayList<>();
+            }
+            lqw.in(PtRoom::getAreaId, floors);
+        }
         lqw.orderByDesc(PtRoom::getCreateTime);
         List<PtRoomVo> ptRoomVos = baseMapper.selectVoList(lqw);
         setAreaName(ptRoomVos);
@@ -170,6 +195,20 @@ public class PtRoomServiceImpl implements IPtRoomService {
         return baseMapper.selectVoList(lqw);
     }
 
+    /**
+     * 根据区域id查询房间
+     * @param bo
+     * @param areaIds
+     * @return
+     */
+    public List<PtRoomVo> selectListByAreas(PtRoomBo bo,List<Long> areaIds) {
+        LambdaQueryWrapper<PtRoom> lqw = buildQueryWrapper(bo);
+        if (CollectionUtil.isNotEmpty(areaIds)){
+            lqw.in(PtRoom::getAreaId,areaIds);
+        }
+        return baseMapper.selectVoList(lqw);
+    }
+
     /**
      * 仅用于选择房间
      *
@@ -309,22 +348,37 @@ public class PtRoomServiceImpl implements IPtRoomService {
     /**
      * 查询所有房间状态的房间数量
      *
+     * 根据客房权限,进行过滤
+     *
      * @return
      */
     @Override
     public Map<String, Long> getCountByStatus() {
 
+        HotelRoomStatusEnum[] values = HotelRoomStatusEnum.values();
         Map<String, Long> map = new HashMap<>();
+        List<Long> floors = new ArrayList<>();
+
+        boolean isAdmin = LoginHelper.isSuperAdmin();
+        Long userId = LoginHelper.getUserId();
+        if(!isAdmin){
+            floors = getHasPermissionFloor(userId);
+            if(CollectionUtil.isEmpty(floors)){
+                for (HotelRoomStatusEnum value : values) {
+                    map.put(value.code(), 0L);
+                }
+                return map;
+            }
+        }
 
         LambdaQueryWrapper<PtRoom> lambdaQuery = Wrappers.<PtRoom>lambdaQuery();
-        lambdaQuery.eq(PtRoom::getRoomType, FJLXEnum.KF.code());
+        lambdaQuery.eq(PtRoom::getRoomType, FJLXEnum.KF.code()).in(!isAdmin, PtRoom::getAreaId, floors);
 
         List<PtRoomVo> list = baseMapper.selectVoList(lambdaQuery);
 
         // 按 status 分组 统计
         Map<String, Long> mapList = list.stream().collect(Collectors.groupingBy(PtRoomVo::getStatus, Collectors.counting()));
 
-        HotelRoomStatusEnum[] values = HotelRoomStatusEnum.values();
         if (mapList.isEmpty()) {
             for (HotelRoomStatusEnum value : values) {
                 map.put(value.code(), 0L);
@@ -338,6 +392,21 @@ public class PtRoomServiceImpl implements IPtRoomService {
         return map;
     }
 
+    /**
+     * 查询当前账号有权限的楼层
+     * @return
+     */
+    public List<Long> getHasPermissionFloor(Long userId){
+        List<Long> rs = new ArrayList<>();
+        List<Long> areaPermissions = areaPermissionsService.getAreaPermissions(userId);
+        if(CollectionUtil.isNotEmpty(areaPermissions)){
+            // 根据楼栋 查询 楼层
+            return areaService.queryFloorByLDList(areaPermissions);
+        }
+
+        return rs;
+    }
+
 
     /**
      * 保存前的数据校验

+ 20 - 8
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/basics/service/impl/PtRoomTypeServiceImpl.java

@@ -18,6 +18,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import lombok.RequiredArgsConstructor;
+import org.dromara.common.satoken.utils.LoginHelper;
 import org.dromara.hotel.api.domain.vo.RemoteOrderVo;
 import org.dromara.hotel.api.service.RemoteOrderService;
 import org.springframework.stereotype.Service;
@@ -27,10 +28,7 @@ import org.dromara.backstage.basics.domain.PtRoomType;
 import org.dromara.backstage.basics.mapper.PtRoomTypeMapper;
 import org.dromara.backstage.basics.service.IPtRoomTypeService;
 
-import java.util.List;
-import java.util.Map;
-import java.util.Collection;
-import java.util.Objects;
+import java.util.*;
 import java.util.stream.Collectors;
 
 /**
@@ -96,14 +94,28 @@ public class PtRoomTypeServiceImpl implements IPtRoomTypeService {
      */
     @Override
     public List<PtRoomTypeVo> queryAllCount() {
+
+        List<Long> floors = new ArrayList<>();
+        boolean isAdmin = LoginHelper.isSuperAdmin();
+        Long userId = LoginHelper.getUserId();
+        if(!isAdmin){
+            floors = roomService.getHasPermissionFloor(userId);
+        }
+
         LambdaQueryWrapper<PtRoomType> lqw = new LambdaQueryWrapper<>();
         lqw.orderByDesc(PtRoomType::getCreateTime);
         List<PtRoomTypeVo> vos = baseMapper.selectVoList(lqw);
 
-        // 房间总数量
-        PtRoomBo bo = new PtRoomBo();
-        bo.setRoomType(FJLXEnum.KF.code());
-        List<PtRoomVo> ptRoomVos = roomService.selectList(bo);
+        List<PtRoomVo> ptRoomVos;
+
+        if(!isAdmin && CollectionUtil.isEmpty(floors)){
+            ptRoomVos = new ArrayList<>();
+        }else{
+            // 房间总数量
+            PtRoomBo bo = new PtRoomBo();
+            bo.setRoomType(FJLXEnum.KF.code());
+            ptRoomVos = roomService.selectListByAreas(bo,floors);
+        }
 
         // 按照房间类型分组统计
 //        Map<Long, Long> allCountMap = ptRoomVos.stream().collect(Collectors.groupingBy(PtRoomVo::getGuestRoomType, Collectors.counting()));

+ 1 - 0
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/cardCenter/controller/CardApiController.java

@@ -137,6 +137,7 @@ public class CardApiController extends BaseController {
      * @return 回收结果
      */
     @PostMapping("/api/v1/recycle")
+    @SyncDataToLocal(eventType = CARD_RECOVERY, sender = CARD_CENTER_SENDER)
     public ReturnResult recycleCard(@RequestBody Map<String, String> mapParams){
         String defaultTenantId = defaultConfig.getTenantId();
         Long cardNo = Long.parseLong(mapParams.get("cardNo"));

+ 98 - 7
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/controller/self/SelfController.java

@@ -1,5 +1,6 @@
 package org.dromara.backstage.controller.self;
 
+import cn.hutool.json.JSONUtil;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.dromara.backstage.business.accouunt.UserFaceBusiness;
@@ -10,8 +11,12 @@ import org.dromara.common.core.api.ResponseResult;
 import org.dromara.common.core.api.ReturnResult;
 import org.dromara.common.core.domain.R;
 import org.dromara.common.core.enums.ResultCodeEnum;
+import org.dromara.common.core.utils.StringUtilsByYC;
+import org.dromara.common.encrypt.utils.EncryptUtils;
 import org.springframework.web.bind.annotation.*;
 
+import java.util.Date;
+import java.util.LinkedHashMap;
 import java.util.Map;
 
 /**
@@ -47,44 +52,45 @@ public class SelfController {
     }
 
     @PostMapping(value = "/api/v1/sms/no")
-    public void sendNoRoomSms(@RequestBody Map<String, String> mapSendInfo){
+    public void sendNoRoomSms(@RequestBody Map<String, String> mapSendInfo) {
         String phone = mapSendInfo.get("mobile");
         String realName = mapSendInfo.get("realName");
         String className = mapSendInfo.get("className");
-        selfBusiness.sendSmsNoRoom(phone,realName,className);
+        selfBusiness.sendSmsNoRoom(phone, realName, className);
     }
 
     /**
      * 短信系统登录
      */
     @GetMapping(value = "/api/v1/sms/login")
-    public void loginSms(){
+    public void loginSms() {
         selfBusiness.loginSms();
     }
 
     @GetMapping("/api/v1/wechat/result/{deptId}/{userId}")
     public ReturnResult queryWxPayResult(@PathVariable("deptId") String deptId, @PathVariable("userId") String userId) {
         ReturnResult result = selfBusiness.queryPayResultByUserAndDept(Long.parseLong(deptId), Long.parseLong(userId));
-        return result.isSuccess() ? ReturnResult.success(true) : ReturnResult.failure(ResultCodeEnum.DATA_NOT_FOUND,false);
+        return result.isSuccess() ? ReturnResult.success(true) : ReturnResult.failure(ResultCodeEnum.DATA_NOT_FOUND, false);
 
     }
 
     @GetMapping("/api/v1/wechat/result/{orderSn}")
-    public ReturnResult queryPayResultByOrderSn(@PathVariable("orderSn") String orderSn){
+    public ReturnResult queryPayResultByOrderSn(@PathVariable("orderSn") String orderSn) {
         R<Void> result = thirdPayBusiness.queryOrderPayResult(orderSn);
         if (R.isSuccess(result)) {
             return ReturnResult.success();
         }
-        return ReturnResult.failure(ResultCodeEnum.SYSTEM_INNER_ERROR.code(),result.getMsg());
+        return ReturnResult.failure(ResultCodeEnum.SYSTEM_INNER_ERROR.code(), result.getMsg());
     }
 
     @RequestMapping(value = "api/v1/lock/card/{cardId}/{cardData}/{userId}", method = RequestMethod.GET)
-    public boolean setLockCardDataId(@PathVariable("cardId") String cardId,@PathVariable("cardData") String cardData,@PathVariable("userId") String userId) {
+    public boolean setLockCardDataId(@PathVariable("cardId") String cardId, @PathVariable("cardData") String cardData, @PathVariable("userId") String userId) {
         return traineeBusiness.updateCardIdToCardData(cardData, userId, cardId);
     }
 
     /**
      * 自助工具查询卡片信息(餐卡、房卡)
+     *
      * @param mapInfo 查询条件
      * @return 卡片信息
      */
@@ -135,4 +141,89 @@ public class SelfController {
 
         return userFaceBusiness.extractUserFaces(userId, imageData);
     }
+
+    /**
+     * 根据用户流水号生成校园码字符串
+     *
+     * @param userNo 用户流水号
+     * @return 二维码串
+     */
+    @RequestMapping(value = "api/v1/test/code/en/{userNo}", method = RequestMethod.GET)
+    public R<Void> getQrCodeByUserNo(@PathVariable("userNo") String userNo) {
+        long currentTime = new Date().getTime();
+        long secondTime = currentTime / 1000 % 60;
+        long minuteTime = currentTime / 1000 - secondTime;
+        String head = "1";
+        String clientNo = "20200813044411";
+        Map<String, Object> m = new LinkedHashMap<>();
+        m.put("head", head);
+        m.put("userNo", Integer.valueOf(userNo));
+        m.put("clientNo", clientNo);
+        m.put("minuteTime", minuteTime);
+        m.put("secondTime", secondTime);
+
+        String jsonStr = JSONUtil.toJsonStr(m);
+        String keyStr = StringUtilsByYC.addString("YC" + userNo, "X", 16, "R");
+        String base64Mac = EncryptUtils.encryptByAes(jsonStr, keyStr);
+
+        String code = String.format("Q1|%s|%s|%s", userNo, clientNo, base64Mac);
+        String codeStr = StringUtilsByYC.addString(String.valueOf(code.length()), "0", 4, "L");
+        String data = String.format("YC|%s|%s|ZN", codeStr, code);
+
+        long hashCode = data.hashCode();
+        if (hashCode < 0) {
+            hashCode = 2147483648L + hashCode;
+        }
+
+        // 截取到前6位字符串
+        String currentHashCodeStr = String.valueOf(hashCode);
+        if (currentHashCodeStr.length() > 6) {
+            // 当值大于6位数时,就用前六位值 加 后N位值,以提高验证时的准确性
+            currentHashCodeStr = String.valueOf(Integer.parseInt(currentHashCodeStr.substring(0, 6))
+                + Integer.parseInt(currentHashCodeStr.substring(6)));
+        } else {
+            currentHashCodeStr = StringUtilsByYC.addString(currentHashCodeStr, "0", 6, "L");
+        }
+        String userNoStr = StringUtilsByYC.addString(userNo, "0", 10, "R");// 10位字符串,后面补0
+        int padValue = 10 - userNo.length(); // 用于代表用户编号补了几个0
+        // 整型数据加起来,得到10位字符串(确保在解析时,能够解除userNo 和 时间戳的分钟值)
+        String value = String.valueOf(minuteTime / 10 + Long.parseLong(userNoStr) + Long.parseLong(currentHashCodeStr));
+        String qrCode = head + currentHashCodeStr + padValue + value + secondTime;
+
+        return R.ok(qrCode);
+    }
+
+    /**
+     * 根据二维码字符串解析出用户流水号
+     *
+     * @param userCode 二维码字符串
+     * @return 用户流水号
+     */
+    @RequestMapping(value = "api/v1/test/code/de/{userCode}", method = RequestMethod.GET)
+    public R<Void> getUserNoFromQrCode(@PathVariable("userCode") String userCode) {
+        if (userCode.length() != 20)
+            return null;
+        long currentTime = new Date().getTime();
+        // 取出值
+        String head = userCode.substring(0, 1);
+        String hashCodeStr = userCode.substring(1, 7);
+        int padValue = Integer.parseInt(userCode.substring(7, 8));
+        String valueStr = userCode.substring(8, 18);
+        long secondTime = Long.parseLong(userCode.substring(18, 20));
+
+        // 取出包含时间戳分钟和用户编号的值
+        long value = (Long.parseLong(valueStr) - Long.parseLong(hashCodeStr)) * 10;
+        // 取出时间戳分钟值(当前时间戳 + 编号中的时间戳的分钟值 )(此值在服务器与二维码的时间在1000秒内使用才可能正确)
+        long codeMinuteTime = currentTime / 1000 - currentTime / 1000 % 1000 + value % 1000;
+
+        //计算两者差值,小于0或者大于90都认为二维码失效
+        long diffTime = currentTime / 1000 - codeMinuteTime;
+        if (diffTime < -180 || diffTime > 180) {
+            return R.fail("二维码失效");
+        }
+
+        // 计算出用户编号(若codeMinuteTime是不准确的,那么userNo也不正确)
+        String userNo = String.valueOf(value - codeMinuteTime).substring(0, 10 - padValue);
+        return R.ok(userNo);
+    }
 }

+ 10 - 0
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/payment/controller/PtUserAccountController.java

@@ -348,4 +348,14 @@ public class PtUserAccountController extends BaseController {
             return R.fail("账户余额不为0,销户失败");
         }
     }
+
+    /**
+     * 根据物理卡号查询用户卡片信息
+     */
+    @SaCheckPermission("basics:kfCardData:query")
+    @GetMapping("/getCardInfoByFactoryId")
+    public R<PtUserAccount4SelectVo> getCardInfoByFactoryId(String factoryId) {
+        return R.ok(ptUserAccountService.getCardInfoByFactoryId(factoryId));
+    }
+
 }

+ 2 - 0
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/payment/domain/PtUserAccount4SelectVo.java

@@ -240,4 +240,6 @@ public class PtUserAccount4SelectVo implements Serializable {
      */
 //    @Translation(type = TransConstant.USER_ID_TO_CARD_INFO, mapper = "userId")
     private String accountCard;
+
+    private String cardStatus;
 }

+ 7 - 0
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/payment/dubbo/RemoteBagServiceImpl.java

@@ -22,6 +22,8 @@ import org.dromara.common.core.domain.R;
 import org.dromara.common.core.enums.SystemUseTypeEnum;
 import org.springframework.stereotype.Service;
 
+import java.util.Map;
+
 /**
  * name: RemoteBagServiceImpl
  * package: org.dromara.backstage.dubbo
@@ -133,6 +135,11 @@ public class RemoteBagServiceImpl implements RemoteBagService {
         return true;
     }
 
+    @Override
+    public Boolean recycleCard(RemoteCardBo bo) {
+        R<Void> res = cardBusiness.recycleCard(BeanUtil.copyProperties(bo, PtCardBo.class));
+        return R.isSuccess(res);
+    }
     @Override
     public Boolean unlockCard(Long cardId) {
         return ptCardService.unlockCard(cardId);

+ 2 - 0
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/payment/mapper/PtUserAccountMapper.java

@@ -44,4 +44,6 @@ public interface PtUserAccountMapper extends BaseMapperPlus<PtUserAccount, PtUse
     }
 
     YcTraineeVo selectTraineeByBo(@Param("bo") PtUserAccountBo bo, @Param("doingDate") Date doingDate);
+
+    List<PtUserAccount4SelectVo> getCardInfoByFactoryId (@Param("factoryId") String factoryId);
 }

+ 2 - 0
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/payment/service/IPtUserAccountService.java

@@ -199,4 +199,6 @@ public interface IPtUserAccountService {
      * @return 操作成功与否
      */
     int delByUserAndDeptId(Long userId,Long deptId, Long operatorId);
+
+    PtUserAccount4SelectVo getCardInfoByFactoryId(String factoryId);
 }

+ 19 - 0
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/payment/service/impl/PtUserAccountServiceImpl.java

@@ -31,6 +31,7 @@ import org.dromara.backstage.payment.service.IPtUserAccountService;
 import org.dromara.common.core.constant.CacheNames;
 import org.dromara.common.core.constant.DefaultConstants;
 import org.dromara.common.core.domain.R;
+import org.dromara.common.core.service.DictService;
 import org.dromara.common.core.utils.MapstructUtils;
 import org.dromara.common.core.utils.SpringUtils;
 import org.dromara.common.core.utils.StringUtils;
@@ -74,6 +75,7 @@ public class PtUserAccountServiceImpl implements IPtUserAccountService {
     private final IPtBagService bagService;
     private final IPtCardtypeService cardTypeService;
     private final PushKafkaData kafkaNormalProducer;
+    private final DictService dictService;
 
     @DubboReference
     private final RemoteDeptService remoteDeptService;
@@ -710,4 +712,21 @@ public class PtUserAccountServiceImpl implements IPtUserAccountService {
         System.err.println("11111");
     }
 
+    @Override
+    public PtUserAccount4SelectVo getCardInfoByFactoryId(String factoryId) {
+        if (StringUtils.isBlank(factoryId)){
+            return null;
+        }
+        List<PtUserAccount4SelectVo> list = baseMapper.getCardInfoByFactoryId(factoryId);
+        if (list.isEmpty()){
+            return null;
+        }
+        PtUserAccount4SelectVo res = list.get(0);
+        if(StringUtils.isNotBlank(res.getCardStatus())){
+            String cardStatusName = dictService.getDictLabel("KZT",  res.getCardStatus());
+            res.setCardStatus(cardStatusName);
+        }
+        return res;
+
+    }
 }

+ 10 - 0
ruoyi-modules/ruoyi-backstage/src/main/resources/mapper/payment/PtUserAccountMapper.xml

@@ -115,4 +115,14 @@
         </where>
 
     </select>
+
+    <select id="getCardInfoByFactoryId" resultType="org.dromara.backstage.payment.domain.PtUserAccount4SelectVo">
+        SELECT a.real_name as realName, a.phone, b.dept_name as deptName, a.lifespan,c.create_time as createTime, c.status as cardStatus
+        FROM t_pt_userAccount a
+            LEFT JOIN t_sys_dept b ON a.dept_id=b.dept_id
+            LEFT JOIN t_pt_card c ON a.user_id=c.user_id
+        WHERE a.del_flag='0' AND b.del_flag='0' AND c.del_flag='0'
+        AND c.factory_id=#{factoryId}
+        ORDER BY c.create_time DESC
+    </select>
 </mapper>

+ 9 - 0
ruoyi-modules/ruoyi-hotel/src/main/java/org/dromara/hotel/controller/KfProvideCardHisController.java

@@ -69,6 +69,15 @@ public class KfProvideCardHisController extends BaseController {
         return R.ok(kfProvideCardHisService.queryById(id));
     }
 
+    /**
+     * 查看发卡记录详情
+     */
+    @SaCheckPermission("basics:kfCardData:query")
+    @GetMapping("/getInfoByBo")
+    public R<KfProvideCardHisVo> getInfoByBo(KfProvideCardHisBo bo) {
+        return R.ok(kfProvideCardHisService.queryByBo(bo));
+    }
+
     /**
      * 新增发卡记录
      */

+ 39 - 0
ruoyi-modules/ruoyi-hotel/src/main/java/org/dromara/hotel/dubbo/RemoteAreaPermissionsServiceImpl.java

@@ -0,0 +1,39 @@
+package org.dromara.hotel.dubbo;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import lombok.RequiredArgsConstructor;
+import org.apache.dubbo.config.annotation.DubboService;
+import org.dromara.hotel.api.service.RemoteAreaPermissionsService;
+import org.dromara.hotel.domain.KfAreaPermissions;
+import org.dromara.hotel.mapper.KfAreaPermissionsMapper;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+
+@Service
+@DubboService
+@RequiredArgsConstructor
+public class RemoteAreaPermissionsServiceImpl implements RemoteAreaPermissionsService {
+
+    private final KfAreaPermissionsMapper baseMapper;
+
+
+
+    /**
+     * 根据用户id获取区域楼栋权限
+     *
+     * @param userId
+     * @return
+     */
+    @Override
+    public List<Long> getAreaPermissions(Long userId) {
+        if (userId != null) {
+            LambdaQueryWrapper<KfAreaPermissions> queryWrapper = new LambdaQueryWrapper<>();
+            return baseMapper.selectList(
+                queryWrapper.eq(KfAreaPermissions::getUserId, userId).select(KfAreaPermissions::getAreaId)
+            ).stream().map(KfAreaPermissions::getAreaId).toList();
+        }
+        return null;
+    }
+}

+ 22 - 8
ruoyi-modules/ruoyi-hotel/src/main/java/org/dromara/hotel/service/impl/KfProvideCardHisServiceImpl.java

@@ -1,9 +1,11 @@
 package org.dromara.hotel.service.impl;
 
 import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.util.HexUtil;
 import cn.hutool.core.util.ObjectUtil;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import org.dromara.common.core.constant.HotelBusinessConstants;
+import org.dromara.common.core.service.DictService;
 import org.dromara.common.core.utils.MapstructUtils;
 import org.dromara.common.core.utils.StringUtils;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
@@ -20,10 +22,7 @@ import org.dromara.hotel.domain.KfProvideCardHis;
 import org.dromara.hotel.mapper.KfProvideCardHisMapper;
 import org.dromara.hotel.service.IKfProvideCardHisService;
 
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import java.util.Collection;
+import java.util.*;
 
 /**
  * 发卡记录Service业务层处理
@@ -36,6 +35,7 @@ import java.util.Collection;
 public class KfProvideCardHisServiceImpl implements IKfProvideCardHisService {
 
     private final KfProvideCardHisMapper baseMapper;
+    private final DictService dictService;
 
     /**
      * 查询发卡记录
@@ -78,7 +78,11 @@ public class KfProvideCardHisServiceImpl implements IKfProvideCardHisService {
         Map<String, Object> params = bo.getParams();
         LambdaQueryWrapper<KfProvideCardHis> lqw = Wrappers.lambdaQuery();
         lqw.eq(bo.getCardId() != null, KfProvideCardHis::getCardId, bo.getCardId());
-        lqw.eq(StringUtils.isNotBlank(bo.getFactoryId()), KfProvideCardHis::getFactoryId, bo.getFactoryId());
+        String roomFixId = HexUtil.toHex(Long.parseLong(bo.getFactoryId()));
+        if (roomFixId.length() < 16) {
+            roomFixId = StringUtils.rightPad(roomFixId, 16, "F");
+        }
+        lqw.eq(StringUtils.isNotBlank(bo.getFactoryId()), KfProvideCardHis::getFactoryId, roomFixId);
         lqw.eq(StringUtils.isNotBlank(bo.getCardType()), KfProvideCardHis::getCardType, bo.getCardType());
         lqw.eq(StringUtils.isNotBlank(bo.getRoomCode()), KfProvideCardHis::getRoomCode, bo.getRoomCode());
         lqw.eq(bo.getMasterId() != null, KfProvideCardHis::getMasterId, bo.getMasterId());
@@ -177,10 +181,20 @@ public class KfProvideCardHisServiceImpl implements IKfProvideCardHisService {
     @Override
     public KfProvideCardHisVo queryByBo(KfProvideCardHisBo bo) {
         List<KfProvideCardHisVo> list = this.queryList(bo);
-        if (CollectionUtil.isNotEmpty(list)) {
-            return this.queryList(bo).get(0);
+        if(list.isEmpty()){
+            return null;
+        }else {
+            KfProvideCardHisVo res = list.get(0);
+            if(StringUtils.isNotBlank(res.getCardType())){
+               String cardTypeName = dictService.getDictLabel("room_card_type",  res.getCardType());
+               res.setCardType(cardTypeName);
+            }
+            if(StringUtils.isNotBlank(res.getCardStatus())){
+                String cardStatusName = dictService.getDictLabel("room_card_status",  res.getCardStatus());
+                res.setCardStatus(cardStatusName);
+            }
+            return res;
         }
-        return null;
     }
 
     @Override

+ 23 - 0
ruoyi-server/ruoyi-server-base/src/main/java/org/dromara/server/base/service/yktOperation/SyncRemotePtCardCenterService.java

@@ -154,6 +154,29 @@ public class SyncRemotePtCardCenterService {
             throw new ServiceException("卡片挂失失败");
         }
     }
+
+    /**
+     * 回收卡片
+     */
+    public void recycleCard(Object msg) throws ServiceException{
+        //json转map
+        Map<String, String> initParam = JSONUtil.parseObj(msg).toBean(Map.class);
+        String defaultTenantId = defaultConfig.getTenantId();
+        Long cardNo = Long.parseLong(initParam.get("cardNo"));
+        Long FactorId = Long.parseLong(initParam.get("factoryFixId"));
+        Long operatorId = Long.parseLong((initParam.get("operatorId")));
+        String tenantId = ObjectUtil.isEmpty(initParam.get("tenantId")) ? defaultTenantId : initParam.get("tenantId");
+        RemoteCardBo bo = new RemoteCardBo();
+        bo.setCardNo(cardNo);
+        bo.setFactoryId(FactorId);
+        bo.setOperatorId(operatorId);
+        bo.setTenantId(tenantId);
+        boolean flag = bagService.recycleCard(bo);
+        if (!flag){
+            throw new ServiceException("卡片回收失败");
+        }
+    }
+
     private RemoteCardBo getInitInfo(Map<String, Object> initParam) {
         RemoteCardBo bo = new RemoteCardBo();
         bo.setCardId(ObjUtil.isNotEmpty(initParam.get("cardId")) ? Long.parseLong(initParam.get("cardId").toString()) : null);

+ 1 - 0
ruoyi-server/ruoyi-server-mqdata/src/main/java/org/dromara/server/mq/event/kafka/impl/yktOperation/PtCardCenterEventStrategyImpl.java

@@ -32,6 +32,7 @@ public class PtCardCenterEventStrategyImpl implements IYktEventStrategy {
             case MessageEventTypeConstants.ptCard_CARD_UNLOCK -> cardCenterService.unlockCard(msg);
             case MessageEventTypeConstants.CARD_OPERATION -> cardCenterService.cardWrite(msg);
             case MessageEventTypeConstants.CARD_LOCK -> cardCenterService.cardLock(msg);
+            case MessageEventTypeConstants.CARD_RECOVERY -> cardCenterService.recycleCard(msg);
             default -> log.info("未知事件");
         }
     }