فهرست منبع

Merge remote-tracking branch 'origin/master'

wujiefeng 1 سال پیش
والد
کامیت
e7f594be82
20فایلهای تغییر یافته به همراه320 افزوده شده و 23 حذف شده
  1. 1 1
      FullCardClient/src/main/java/com/zhongshu/card/client/model/base/UserIdAndOidModel.java
  2. 13 0
      FullCardClient/src/main/java/com/zhongshu/card/client/model/devices/DevicePermissModel.java
  3. 4 0
      FullCardClient/src/main/java/com/zhongshu/card/client/model/devices/DevicePermissSearch.java
  4. 24 0
      FullCardClient/src/main/java/com/zhongshu/card/client/model/xcx/ProjectXcxModel.java
  5. 2 2
      FullCardServer/src/main/java/com/zhongshu/card/server/core/controller/projectAbout/OrgUserFaceController.java
  6. 10 1
      FullCardServer/src/main/java/com/zhongshu/card/server/core/controller/projectAbout/ProjectWeChatInfoController.java
  7. 2 0
      FullCardServer/src/main/java/com/zhongshu/card/server/core/dao/devices/DevicePermissDao.java
  8. 4 0
      FullCardServer/src/main/java/com/zhongshu/card/server/core/dao/devices/impl/DevicePermissDaoImpl.java
  9. 5 0
      FullCardServer/src/main/java/com/zhongshu/card/server/core/dao/projectAbout/ProjectWeChatInfoDao.java
  10. 4 0
      FullCardServer/src/main/java/com/zhongshu/card/server/core/domain/devices/DevicePermiss.java
  11. 27 0
      FullCardServer/src/main/java/com/zhongshu/card/server/core/event/UserInfoChangeSyncEvent.java
  12. 7 0
      FullCardServer/src/main/java/com/zhongshu/card/server/core/service/base/SuperService.java
  13. 84 0
      FullCardServer/src/main/java/com/zhongshu/card/server/core/service/devices/DevicePermissEventService.java
  14. 23 0
      FullCardServer/src/main/java/com/zhongshu/card/server/core/service/devices/DevicePermissService.java
  15. 6 0
      FullCardServer/src/main/java/com/zhongshu/card/server/core/service/devices/DeviceSyncFromIotService.java
  16. 2 4
      FullCardServer/src/main/java/com/zhongshu/card/server/core/service/gateDoor/GateDoorService.java
  17. 1 0
      FullCardServer/src/main/java/com/zhongshu/card/server/core/service/paySetting/ProjectPaySettingServiceImpl.java
  18. 28 1
      FullCardServer/src/main/java/com/zhongshu/card/server/core/service/projectAbout/CardInfoServiceImpl.java
  19. 28 14
      FullCardServer/src/main/java/com/zhongshu/card/server/core/service/projectAbout/OrgUserFaceService.java
  20. 45 0
      FullCardServer/src/main/java/com/zhongshu/card/server/core/service/projectAbout/ProjectWeChatInfoService.java

+ 1 - 1
FullCardClient/src/main/java/com/zhongshu/card/client/model/base/UserIdAndOidModel.java

@@ -12,7 +12,7 @@ import lombok.NoArgsConstructor;
 @Data
 @AllArgsConstructor
 @NoArgsConstructor
-public class UserIdAndOidModel extends OidModel {
+public class UserIdAndOidModel extends ProjectOidParam {
 
     @Schema(description = "用户userId", example = "")
     private String userId;

+ 13 - 0
FullCardClient/src/main/java/com/zhongshu/card/client/model/devices/DevicePermissModel.java

@@ -9,6 +9,7 @@ import com.zhongshu.card.client.model.org.role.RoleModel;
 import com.zhongshu.card.client.model.school.AreaSimpleModel;
 import com.zhongshu.card.client.model.school.DictInfoSimpleModel;
 import com.zhongshu.card.client.type.DataState;
+import com.zhongshu.card.client.type.OnLineState;
 import com.zhongshu.card.client.type.UserState;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.AllArgsConstructor;
@@ -41,6 +42,18 @@ public class DevicePermissModel extends SuperModel {
     @Schema(description = "设备类型,如 消费机 门禁机")
     private DeviceType deviceType;
 
+    @Schema(description = "是否在线")
+    private OnLineState onLineState;
+
+    private String onLineStateStr;
+
+    public String getOnLineStateStr() {
+        if (onLineState != null) {
+            return onLineState.getRemark();
+        }
+        return "";
+    }
+
     private String deviceTypeStr;
 
     public String getDeviceTypeStr() {

+ 4 - 0
FullCardClient/src/main/java/com/zhongshu/card/client/model/devices/DevicePermissSearch.java

@@ -3,6 +3,7 @@ package com.zhongshu.card.client.model.devices;
 import com.github.microservice.auth.security.type.AuthType;
 import com.github.microservice.models.type.DeviceType;
 import com.zhongshu.card.client.model.base.SuperSearch;
+import com.zhongshu.card.client.type.OnLineState;
 import com.zhongshu.card.client.type.UserState;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.AllArgsConstructor;
@@ -36,6 +37,9 @@ public class DevicePermissSearch extends SuperSearch {
     @Schema(description = "区域所有上级ID路径,如:a1/a12/a123")
     private String areaPaths = "";
 
+    @Schema(description = "是否在线")
+    private OnLineState onLineState;
+
     //---------------用户冗余数据 start--------------
 
     @Schema(description = "用户所属机构的类型")

+ 24 - 0
FullCardClient/src/main/java/com/zhongshu/card/client/model/xcx/ProjectXcxModel.java

@@ -0,0 +1,24 @@
+package com.zhongshu.card.client.model.xcx;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 项目oid参数模型
+ *
+ * @author TRX
+ * @date 2024/9/24
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class ProjectXcxModel {
+
+    @Schema(description = "项目oid")
+    private String projectOid;
+
+    @Schema(description = "项目名称")
+    private String projectName;
+}

+ 2 - 2
FullCardServer/src/main/java/com/zhongshu/card/server/core/controller/projectAbout/OrgUserFaceController.java

@@ -20,7 +20,7 @@ import org.springframework.web.bind.annotation.RestController;
 import javax.validation.Valid;
 
 /**
- * 结构人脸管理
+ * 项目人员人脸管理
  *
  * @author TRX
  * @date 2024/7/26
@@ -44,7 +44,7 @@ public class OrgUserFaceController {
     @Operation(summary = "得到用户人脸信息", description = "得到用户人脸信息")
     @RequestMapping(value = "getUserFace", method = {RequestMethod.POST})
     public ResultContent<OrgUserFaceModel> getUserFace(@RequestBody @Valid UserIdAndOidModel param) {
-        return orgUserFaceService.getUserFaceModel(param.getUserId(), param.getOid());
+        return orgUserFaceService.getUserFaceModel(param.getUserId(), param.getProjectOid());
     }
 
 }

+ 10 - 1
FullCardServer/src/main/java/com/zhongshu/card/server/core/controller/projectAbout/ProjectWeChatInfoController.java

@@ -7,6 +7,7 @@ import com.zhongshu.card.client.model.base.ProjectOidParam;
 import com.zhongshu.card.client.model.feign.ProjectWxPayParam;
 import com.zhongshu.card.client.model.projectAbout.ProjectWeChatInfoModel;
 import com.zhongshu.card.client.model.projectAbout.ProjectWeChatInfoParam;
+import com.zhongshu.card.client.model.xcx.ProjectXcxModel;
 import com.zhongshu.card.server.core.service.projectAbout.ProjectWeChatInfoService;
 import io.swagger.v3.oas.annotations.Hidden;
 import io.swagger.v3.oas.annotations.Operation;
@@ -18,6 +19,7 @@ import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.RestController;
 
 import javax.validation.Valid;
+import java.util.List;
 
 /**
  * 项目的微信小程序设置
@@ -43,10 +45,17 @@ public class ProjectWeChatInfoController {
     @ResourceAuth(value = "user", type = AuthType.User)
     @Operation(summary = "得到项目的小程序配置", description = "得到项目的小程序配置")
     @RequestMapping(value = "getProjectWeChatInfo", method = {RequestMethod.POST})
-    public ResultContent<ProjectWeChatInfoModel> getProjectWeChatInfo(@RequestBody ProjectOidParam param) {
+    public ResultContent<ProjectWeChatInfoModel> getProjectWeChatInfo(
+            @RequestBody ProjectOidParam param) {
         return projectWeChatInfoService.getProjectWeChatInfo(param.getProjectOid());
     }
 
+    @Operation(summary = "小程序-得到小程序关联的项目oid(需要在head设置appId)", description = "得到小程序关联的项目oid")
+    @RequestMapping(value = "getProjectOidForXcx", method = {RequestMethod.GET})
+    public ResultContent<List<ProjectXcxModel>> getProjectOidForXcx() {
+        return projectWeChatInfoService.getProjectOidForXcx();
+    }
+
     //------------------------------feign start -----------------------
     @Operation(hidden = true, summary = "根据小程序appId得到配置", description = "根据小程序appId得到配置")
     @RequestMapping(value = "manager/getProjectWeChatInfoByAppId", method = {RequestMethod.POST})

+ 2 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/dao/devices/DevicePermissDao.java

@@ -31,4 +31,6 @@ public interface DevicePermissDao extends MongoDao<DevicePermiss>, DevicePermiss
 
     List<DevicePermiss> findByDeviceIdInAndDataState(List<String> deviceIds, DataState dataState);
 
+    List<DevicePermiss> findByUserIdInAndProjectOidAndDataState(List<String> userIds, String projectOid, DataState dataState);
+
 }

+ 4 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/dao/devices/impl/DevicePermissDaoImpl.java

@@ -60,6 +60,10 @@ public class DevicePermissDaoImpl extends BaseImpl implements DevicePermissDaoEx
             criteria.and("userOid").is(param.getUserOid());
         }
 
+        if (param.getOnLineState() != null) {
+            criteria.and("onLineState").is(param.getOnLineState());
+        }
+
         // 在这个机构的状态,是否可用
         if (param.getState() != null) {
             criteria.and("state").is(param.getState());

+ 5 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/dao/projectAbout/ProjectWeChatInfoDao.java

@@ -3,6 +3,8 @@ package com.zhongshu.card.server.core.dao.projectAbout;
 import com.github.microservice.components.data.mongo.mongo.dao.MongoDao;
 import com.zhongshu.card.server.core.domain.projectAbout.ProjectWeChatInfo;
 
+import java.util.List;
+
 /**
  * 项目的微信设置
  */
@@ -14,4 +16,7 @@ public interface ProjectWeChatInfoDao extends MongoDao<ProjectWeChatInfo> {
 
     ProjectWeChatInfo findTopByAppId(String appId);
 
+    ProjectWeChatInfo findTopByAppIdOrderByUpdateTimeDesc(String appId);
+
+    List<ProjectWeChatInfo> findByAppIdOrderByUpdateTimeDesc(String appId);
 }

+ 4 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/domain/devices/DevicePermiss.java

@@ -3,6 +3,7 @@ package com.zhongshu.card.server.core.domain.devices;
 import com.github.microservice.auth.security.type.AuthType;
 import com.github.microservice.models.type.DeviceType;
 import com.zhongshu.card.client.type.DataState;
+import com.zhongshu.card.client.type.OnLineState;
 import com.zhongshu.card.client.type.UserState;
 import com.zhongshu.card.server.core.domain.base.SuperMain;
 import com.zhongshu.card.server.core.domain.org.Department;
@@ -52,6 +53,9 @@ public class DevicePermiss extends SuperMain {
     @Schema(description = "网关号")
     private String gateWayId;
 
+    @Schema(description = "是否在线")
+    private OnLineState onLineState;
+
     @Schema(description = "区域信息")
     @DBRef(lazy = true)
     private Area area;

+ 27 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/event/UserInfoChangeSyncEvent.java

@@ -0,0 +1,27 @@
+package com.zhongshu.card.server.core.event;
+
+import lombok.Getter;
+import org.springframework.context.ApplicationEvent;
+
+import java.util.List;
+
+/**
+ * 用户信息发送变化(如:姓名、人脸信息、绑定的卡片等)
+ *
+ * @author TRX
+ * @date 2024/6/26
+ */
+public class UserInfoChangeSyncEvent extends ApplicationEvent {
+
+    @Getter
+    private List<String> userIds;
+
+    @Getter
+    private String projectOid;
+
+    public UserInfoChangeSyncEvent(Object source, List<String> userIds, String projectOid) {
+        super(source);
+        this.userIds = userIds;
+        this.projectOid = projectOid;
+    }
+}

+ 7 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/service/base/SuperService.java

@@ -89,6 +89,13 @@ public abstract class SuperService {
         return authClientSecurityAuthenticationHelper.getParameter(new String[]{"projectoid", "projectOid"});
     }
 
+    public String getHeadParam(String[] keys) {
+        if (keys != null && keys.length > 0) {
+            return authClientSecurityAuthenticationHelper.getParameter(keys);
+        }
+        return "";
+    }
+
     /**
      * 初始Entity的默认参数 oid、createUser (oid为空会抛出异常)
      *

+ 84 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/service/devices/DevicePermissEventService.java

@@ -12,10 +12,12 @@ import com.github.microservice.types.FunctionType;
 import com.zhongshu.card.server.core.dao.devices.DeviceInfoDao;
 import com.zhongshu.card.server.core.domain.devices.DeviceInfo;
 import com.zhongshu.card.server.core.event.DevicePermissChangeEvent;
+import com.zhongshu.card.server.core.event.UserInfoChangeSyncEvent;
 import com.zhongshu.card.server.core.service.openAPI.OpenApiRequestService;
 import lombok.SneakyThrows;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.ObjectUtils;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.event.EventListener;
@@ -50,6 +52,12 @@ public class DevicePermissEventService {
     //线程池
     private ExecutorService executorService = Executors.newFixedThreadPool(SystemUtil.getCpuCoreCount() * 2);
 
+    @Autowired
+    private DevicePermissService devicePermissService;
+
+    @Autowired
+    private ApplicationContext applicationContext;
+
     @Autowired
     private void init(ApplicationContext applicationContext) {
         Runtime.getRuntime().addShutdownHook(new Thread(() -> {
@@ -57,6 +65,42 @@ public class DevicePermissEventService {
         }));
     }
 
+    /**
+     * 通知用户关联信息发送变化
+     *
+     * @param userId
+     * @param projectOid
+     */
+    public void sendUserInfoChangeEvent(String userId, String projectOid) {
+        UserInfoChangeSyncEvent event = new UserInfoChangeSyncEvent(this,
+                List.of(userId), projectOid);
+        applicationContext.publishEvent(event);
+    }
+
+    /**
+     * 通知用户关联信息发送变化
+     *
+     * @param userIds
+     * @param projectOid
+     */
+    public void sendUserInfoChangeEvent(List<String> userIds, String projectOid) {
+        UserInfoChangeSyncEvent event = new UserInfoChangeSyncEvent(this,
+                userIds, projectOid);
+        applicationContext.publishEvent(event);
+    }
+
+    /**
+     * 设备信息发送变化
+     *
+     * @param deviceIds
+     * @param projectOid
+     */
+    public void sendDeviceChangeEvent(List<String> deviceIds, String projectOid) {
+        DevicePermissChangeEvent event = new DevicePermissChangeEvent(this,
+                deviceIds, projectOid);
+        applicationContext.publishEvent(event);
+    }
+
     @EventListener(classes = DevicePermissChangeEvent.class)
     @SneakyThrows
     public void devicePermissChange(DevicePermissChangeEvent event) {
@@ -109,6 +153,46 @@ public class DevicePermissEventService {
         });
     }
 
+    /**
+     * 用户信息发生变化
+     *
+     * @param event
+     */
+    @EventListener(classes = UserInfoChangeSyncEvent.class)
+    @SneakyThrows
+    public void userInfoChange(UserInfoChangeSyncEvent event) {
+        String projectOid = event.getProjectOid();
+        List<String> userIds = event.getUserIds();
+        log.info("userInfoChange; {} {}", projectOid);
+        if (StringUtils.isNotEmpty(projectOid) && ObjectUtils.isNotEmpty(userIds)) {
+            executorService.execute(() -> {
+                List<String> deviceIds = devicePermissService.getUserAllDeviceIds(projectOid, userIds);
+                HashMap<String, List<String>> map = deviceGroupByGateWayId(deviceIds);
+                if (!map.isEmpty()) {
+                    // 遍历发送
+                    map.keySet().stream().forEach(gateWayId -> {
+                        List<String> _deviceIds = map.get(gateWayId);
+                        try {
+                            while (_deviceIds.size() > 0) {
+                                // 统计网关管理的所有设备
+                                int index = Math.min(_deviceIds.size(), IotIdentifierConfig.maxNoticeSize);
+                                List<String> subList = _deviceIds.subList(0, index);
+                                _deviceIds = _deviceIds.subList(index, _deviceIds.size());
+                                // 下发用户信息
+                                sendDeviceAboutUserInfo(gateWayId, subList, projectOid);
+                                if (!_deviceIds.isEmpty()) {
+                                    TimeUnit.SECONDS.sleep(10);
+                                }
+                            }
+                        } catch (Exception e) {
+                            throw new RuntimeException(e);
+                        }
+                    });
+                }
+            });
+        }
+    }
+
     /**
      * 发送设备关联的用户数据
      *

+ 23 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/service/devices/DevicePermissService.java

@@ -88,6 +88,9 @@ public class DevicePermissService extends SuperService {
     @Autowired
     private CardInfoServiceImpl cardInfoService;
 
+    @Autowired
+    private DevicePermissEventService devicePermissEventService;
+
     /**
      * 设备绑定用户
      *
@@ -151,6 +154,7 @@ public class DevicePermissService extends SuperService {
             permiss.setGateWayId(deviceInfo.getGateWayId());
             permiss.setDeviceName(deviceInfo.getDeviceName());
             permiss.setDeviceType(deviceInfo.getDeviceType());
+            permiss.setOnLineState(deviceInfo.getOnLineState());
             permiss.setArea(deviceInfo.getArea());
             permiss.setAreaPaths(deviceInfo.getAreaPaths());
         }
@@ -186,6 +190,9 @@ public class DevicePermissService extends SuperService {
             List<OrganizationUser> organizationUsers = organizationUserDao.findByIdIn(organizationUserIds);
             if (ObjectUtils.isNotEmpty(organizationUsers)) {
                 List<DevicePermiss> list = devicePermissDao.findByOrganizationUserIn(organizationUsers);
+                if (ObjectUtils.isEmpty(list)) {
+                    return;
+                }
                 if (dataOperationType == DataOperationType.Update) {
                     for (DevicePermiss permiss : list) {
                         buildOrgUserInfo(permiss, permiss.getOrganizationUser());
@@ -194,6 +201,10 @@ public class DevicePermissService extends SuperService {
                 } else if (dataOperationType == DataOperationType.Delete) {
                     devicePermissDao.deleteAll(list);
                 }
+                // 通知权限下发
+                String projectOid = list.get(0).getProjectOid();
+                List<String> deviceIds = list.stream().map(it->it.getDeviceId()).collect(Collectors.toUnmodifiableList());
+                devicePermissEventService.sendDeviceChangeEvent(deviceIds, projectOid);
             }
         }
     }
@@ -369,6 +380,18 @@ public class DevicePermissService extends SuperService {
         return Lists.newArrayList();
     }
 
+    public List<String> getUserAllDeviceIds(String projectOid, List<String> userIds) {
+        List<String> deviceIds = Lists.newArrayList();
+        if (StringUtils.isNotEmpty(projectOid) && ObjectUtils.isNotEmpty(userIds)) {
+            List<DevicePermiss> list = devicePermissDao.findByUserIdInAndProjectOidAndDataState(
+                    userIds, projectOid, DataState.Enable);
+            if (ObjectUtils.isNotEmpty(list)) {
+                deviceIds = list.stream().map(it -> it.getDeviceId()).collect(Collectors.toList());
+            }
+        }
+        return deviceIds;
+    }
+
     public DevicePermissModel toModel(DevicePermiss entity) {
         DevicePermissModel model = null;
         if (ObjectUtils.isNotEmpty(entity)) {

+ 6 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/service/devices/DeviceSyncFromIotService.java

@@ -13,6 +13,7 @@ import com.zhongshu.card.server.core.dao.org.OrganizationDao;
 import com.zhongshu.card.server.core.dao.org.OrganizationRelationDao;
 import com.zhongshu.card.server.core.domain.devices.DeviceInfo;
 import com.zhongshu.card.server.core.domain.devices.DeviceBind;
+import com.zhongshu.card.server.core.domain.devices.DevicePermiss;
 import com.zhongshu.card.server.core.service.base.CommonService;
 import com.zhongshu.card.server.core.service.user.OperationLogsService;
 import com.zhongshu.card.server.core.util.CommonUtil;
@@ -101,6 +102,11 @@ public class DeviceSyncFromIotService {
         map.put("lastOnlineTimeStr", DateUtils.paresTime(param.getLastOnlineTime(), DateUtils.FORMAT_LONG));
         commonService.updateData(where, map, DeviceInfo.class.getSimpleName());
         commonService.updateData(where, map, DeviceBind.class.getSimpleName());
+
+        HashMap<String, Object> bindMap = new HashMap<>();
+        bindMap.put("onLineState", CommonUtil.getEnumByName(OnLineState.class, param.getOnLineState()));
+        commonService.updateData(where, bindMap, DevicePermiss.class.getSimpleName());
+
         log.info("syncDeviceOnLineState");
         return ResultContent.buildSuccess();
     }

+ 2 - 4
FullCardServer/src/main/java/com/zhongshu/card/server/core/service/gateDoor/GateDoorService.java

@@ -36,8 +36,7 @@ public class GateDoorService extends SuperService {
      */
     public ResultContent onLine(OnLineParam param) {
         OnLineModel resultModel = new OnLineModel();
-        int i = RandomUtil.nextInt(1000, 100000);
-        resultModel.setMessageId(Long.valueOf(i));
+        resultModel.setMessageId(param.getMqttDataId());
 
         OnLineInfoParam paramFaceInfo = param.getInfo();
         String facesluiceId = "";
@@ -55,8 +54,7 @@ public class GateDoorService extends SuperService {
 
     public ResultContent offLine(OnLineParam param) {
         OnLineModel resultModel = new OnLineModel();
-        int i = RandomUtil.nextInt(1000, 100000);
-        resultModel.setMessageId(Long.valueOf(i));
+        resultModel.setMessageId(param.getMqttDataId());
 
         OnLineAckInfoModel info = new OnLineAckInfoModel();
         info.setFacesluiceId(CommonUtil.UUID());

+ 1 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/service/paySetting/ProjectPaySettingServiceImpl.java

@@ -507,6 +507,7 @@ public class ProjectPaySettingServiceImpl extends SuperService {
                 appConf.setMchSerialNo(model.getMchSerialNo());
                 appConf.setPriKeyPath(model.getPrivateKeyStr());
                 appConf.setApiV3KeyPath(model.getApiV3Key());
+                appConf.setNotifyUrl(model.getNotifyUrl());
                 accountModel.setConf(appConf);
             }
             ProjectPaySetting paySetting = projectPaySettingDao.findTopByProjectOidAndChannelType(projectOid, paymentType);

+ 28 - 1
FullCardServer/src/main/java/com/zhongshu/card/server/core/service/projectAbout/CardInfoServiceImpl.java

@@ -30,7 +30,9 @@ import com.zhongshu.card.server.core.domain.org.UserAccount;
 import com.zhongshu.card.server.core.domain.school.CardInfo;
 import com.zhongshu.card.server.core.domain.school.CardInfoLossRecord;
 import com.zhongshu.card.server.core.domain.school.CardInfoPool;
+import com.zhongshu.card.server.core.event.UserInfoChangeSyncEvent;
 import com.zhongshu.card.server.core.service.base.SuperService;
+import com.zhongshu.card.server.core.service.devices.DevicePermissEventService;
 import com.zhongshu.card.server.core.service.org.OrganizationServiceImpl;
 import com.zhongshu.card.server.core.service.org.OrganizationUserServiceImpl;
 import com.zhongshu.card.server.core.service.orgManager.OrganizationManagerServiceImpl;
@@ -45,6 +47,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.ObjectUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.PageRequest;
 import org.springframework.data.domain.Pageable;
@@ -105,6 +108,12 @@ public class CardInfoServiceImpl extends SuperService implements CardInfoService
     @Autowired
     CardInfoPoolService cardInfoPoolService;
 
+    @Autowired
+    ApplicationContext applicationContext;
+
+    @Autowired
+    private DevicePermissEventService devicePermissEventService;
+
     /**
      * 添加或修改卡片信息
      *
@@ -159,6 +168,7 @@ public class CardInfoServiceImpl extends SuperService implements CardInfoService
         cardInfo.setAboutOid(oidAboutInfo.getOid());
         cardInfo.setAboutAuthType(oidAboutInfo.getAuthType());
         cardInfoDao.save(cardInfo);
+
         return ResultContent.buildSuccess();
     }
 
@@ -262,6 +272,9 @@ public class CardInfoServiceImpl extends SuperService implements CardInfoService
         cardInfoPool.setUseUserId(userId);
         cardInfoPool.setUseTime(System.currentTimeMillis());
         cardInfoPoolDao.save(cardInfoPool);
+
+        // 用户卡片增多
+        devicePermissEventService.sendUserInfoChangeEvent(cardInfo.getUserId(), cardInfo.getProjectOid());
         return ResultContent.buildSuccess();
     }
 
@@ -288,6 +301,9 @@ public class CardInfoServiceImpl extends SuperService implements CardInfoService
             cardInfoPool.setUseTime(null);
             cardInfoPoolDao.save(cardInfoPool);
         }
+
+        // 用户可用卡片减少
+        devicePermissEventService.sendUserInfoChangeEvent(cardInfo.getUserId(), cardInfo.getProjectOid());
         return ResultContent.buildSuccess();
     }
 
@@ -453,6 +469,9 @@ public class CardInfoServiceImpl extends SuperService implements CardInfoService
         cardInfoLossRecord.setCardUserAccount(cardUserAccount);
         cardInfoLossRecord.setOperationType(CardOperationType.Loss);
         cardInfoLossRecordDao.save(cardInfoLossRecord);
+
+        // 卡片信息发送变化
+        devicePermissEventService.sendUserInfoChangeEvent(cardInfo.getUserId(), cardInfo.getProjectOid());
         return ResultContent.buildSuccess();
     }
 
@@ -487,7 +506,8 @@ public class CardInfoServiceImpl extends SuperService implements CardInfoService
         cardInfoLossRecord.setCardUserAccount(userAccount);
         cardInfoLossRecord.setOperationType(CardOperationType.Enable);
         cardInfoLossRecordDao.save(cardInfoLossRecord);
-
+        // 卡片信息发送变化
+        devicePermissEventService.sendUserInfoChangeEvent(cardInfo.getUserId(), cardInfo.getProjectOid());
         return ResultContent.buildSuccess();
     }
 
@@ -549,6 +569,8 @@ public class CardInfoServiceImpl extends SuperService implements CardInfoService
         cardInfoLossRecord.setOperationType(CardOperationType.Enable);
         cardInfoLossRecordDao.save(cardInfoLossRecord);
 
+        // 用户可用卡片发生变化
+        devicePermissEventService.sendUserInfoChangeEvent(cardInfo.getUserId(), cardInfo.getProjectOid());
         return ResultContent.buildSuccess();
     }
 
@@ -658,6 +680,7 @@ public class CardInfoServiceImpl extends SuperService implements CardInfoService
         cardInfoLossRecord.setOperationType(CardOperationType.Enable);
         cardInfoLossRecordDao.save(cardInfoLossRecord);
 
+        devicePermissEventService.sendUserInfoChangeEvent(cardInfo.getUserId(), cardInfo.getProjectOid());
         return ResultContent.buildSuccess();
     }
 
@@ -745,6 +768,7 @@ public class CardInfoServiceImpl extends SuperService implements CardInfoService
             List<String> failDetails = new ArrayList<>();
             List<CardInfoPoolBind2OrgUserParam> cardInfoPools = new ArrayList<>();
             if (ObjectUtils.isNotEmpty(list)) {
+                List<String> userIds = new ArrayList<>();
                 for (CardInfoBindImportParam bindImportParam : list) {
                     startRow++;
                     CardInfoPoolBind2OrgUserParam bind2OrgUserParam = new CardInfoPoolBind2OrgUserParam();
@@ -800,11 +824,14 @@ public class CardInfoServiceImpl extends SuperService implements CardInfoService
                     codeMap.put(code, phone);
                     bind2OrgUserParam.setId(organizationUser.getId());
                     cardInfoPools.add(bind2OrgUserParam);
+                    userIds.add(userAccount.getUserId());
                 }
                 if (ObjectUtils.isNotEmpty(cardInfoPools)) {
                     for (CardInfoPoolBind2OrgUserParam bind2OrgUserParam : cardInfoPools) {
                         bindCardFromPoolByOrgId(bind2OrgUserParam.getPoolId(), bind2OrgUserParam.getId(), bind2OrgUserParam.getRemark());
                     }
+
+                    devicePermissEventService.sendUserInfoChangeEvent(userIds, projectOid);
                 }
                 model.setSuccess(cardInfoPools.size());
                 model.setFailDetails(failDetails);

+ 28 - 14
FullCardServer/src/main/java/com/zhongshu/card/server/core/service/projectAbout/OrgUserFaceService.java

@@ -6,12 +6,16 @@ import com.zhongshu.card.client.model.projectAbout.OrgUserFaceModel;
 import com.zhongshu.card.client.model.projectAbout.OrgUserFaceParam;
 import com.zhongshu.card.server.core.dao.projectAbout.OrgUserFaceDao;
 import com.zhongshu.card.server.core.domain.projectAbout.OrgUserFace;
+import com.zhongshu.card.server.core.event.UserInfoChangeSyncEvent;
 import com.zhongshu.card.server.core.service.base.SuperService;
+import com.zhongshu.card.server.core.service.devices.DevicePermissEventService;
 import com.zhongshu.card.server.core.util.BeanUtils;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.ObjectUtils;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.kafka.common.protocol.types.Field;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
 import org.springframework.stereotype.Service;
 
 import java.util.ArrayList;
@@ -31,6 +35,12 @@ public class OrgUserFaceService extends SuperService {
     @Autowired
     private OrgUserFaceDao orgUserFaceDao;
 
+    @Autowired
+    private ApplicationContext applicationContext;
+
+    @Autowired
+    private DevicePermissEventService devicePermissEventService;
+
     /**
      * 保存用户人脸信息
      *
@@ -38,15 +48,18 @@ public class OrgUserFaceService extends SuperService {
      * @return
      */
     public ResultContent saveFace(OrgUserFaceParam param) {
-        String oid = param.getOid();
-        if (StringUtils.isEmpty(oid)) {
+        String projectOid = param.getProjectOid();
+        if (StringUtils.isEmpty(projectOid)) {
+            projectOid = getCurrentProjectOid();
+        }
+        if (StringUtils.isEmpty(projectOid)) {
             return ResultContent.buildFail("oid不能为空");
         }
         String userId = param.getUserId();
         if (StringUtils.isEmpty(userId)) {
             userId = getCurrentUserId();
         }
-        OrgUserFace orgUserFace = orgUserFaceDao.findTopByUserIdAndProjectOid(userId, oid);
+        OrgUserFace orgUserFace = orgUserFaceDao.findTopByUserIdAndProjectOid(userId, projectOid);
         if (ObjectUtils.isEmpty(orgUserFace)) {
             orgUserFace = new OrgUserFace();
             initEntity(orgUserFace);
@@ -54,17 +67,12 @@ public class OrgUserFaceService extends SuperService {
             initUpdateEntity(orgUserFace);
         }
         BeanUtils.copyProperties(param, orgUserFace);
+        orgUserFace.setProjectOid(projectOid);
         orgUserFaceDao.save(orgUserFace);
-        return ResultContent.buildSuccess();
-    }
 
-    public ResultContent<List<OrgUserFaceModel>> getUserFaceList(String userId, String oid) {
-        List<OrgUserFace> list = getUserFaces(userId, oid);
-        List<OrgUserFaceModel> models = new ArrayList<>();
-        if (ObjectUtils.isNotEmpty(list)) {
-            models = list.stream().map(this::toModel).collect(Collectors.toList());
-        }
-        return ResultContent.buildSuccess(models);
+        // 通知人脸信息发送变化
+        devicePermissEventService.sendUserInfoChangeEvent(orgUserFace.getUserId(), orgUserFace.getProjectOid());
+        return ResultContent.buildSuccess();
     }
 
     public List<OrgUserFace> getUserFaces(String userId, String oid) {
@@ -75,11 +83,17 @@ public class OrgUserFaceService extends SuperService {
         return list;
     }
 
-    public ResultContent<OrgUserFaceModel> getUserFaceModel(String userId, String oid) {
+    public ResultContent<OrgUserFaceModel> getUserFaceModel(String userId, String projectOid) {
         if (StringUtils.isEmpty(userId)) {
             userId = getCurrentUserId();
         }
-        OrgUserFace entity = getUserFace(userId, oid);
+        if (StringUtils.isEmpty(projectOid)) {
+            projectOid = getCurrentProjectOid();
+        }
+        if (StringUtils.isEmpty(projectOid)) {
+            return ResultContent.buildFail("projectOid为空");
+        }
+        OrgUserFace entity = getUserFace(userId, projectOid);
         return ResultContent.buildSuccess(toModel(entity));
     }
 

+ 45 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/service/projectAbout/ProjectWeChatInfoService.java

@@ -1,19 +1,27 @@
 package com.zhongshu.card.server.core.service.projectAbout;
 
 import com.github.microservice.net.ResultContent;
+import com.zhongshu.card.client.model.base.ProjectOidParam;
 import com.zhongshu.card.client.model.projectAbout.ProjectWeChatInfoModel;
 import com.zhongshu.card.client.model.projectAbout.ProjectWeChatInfoParam;
+import com.zhongshu.card.client.model.xcx.ProjectXcxModel;
 import com.zhongshu.card.server.core.dao.org.OrganizationDao;
 import com.zhongshu.card.server.core.dao.projectAbout.ProjectWeChatInfoDao;
 import com.zhongshu.card.server.core.domain.org.Organization;
+import com.zhongshu.card.server.core.domain.projectAbout.ProjectIotInfo;
 import com.zhongshu.card.server.core.domain.projectAbout.ProjectWeChatInfo;
 import com.zhongshu.card.server.core.service.base.SuperService;
 import com.zhongshu.card.server.core.util.BeanUtils;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.ObjectUtils;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
 /**
  * 项目的 微信管理信息设置
  *
@@ -43,6 +51,7 @@ public class ProjectWeChatInfoService extends SuperService {
             return ResultContent.buildFail(String.format("项目oid不存在:%s", projectOid));
         }
         ProjectWeChatInfo projectWeChatInfo = projectWeChatInfoDao.findTopByProjectOid(projectOid);
+        ProjectWeChatInfo appIdTemp = projectWeChatInfoDao.findTopByAppId(param.getAppId());
         if (ObjectUtils.isEmpty(projectWeChatInfo)) {
             projectWeChatInfo = new ProjectWeChatInfo();
             projectWeChatInfo.setIsDelete(Boolean.FALSE);
@@ -50,6 +59,15 @@ public class ProjectWeChatInfoService extends SuperService {
         } else {
             initUpdateEntity(projectWeChatInfo);
         }
+        if (ObjectUtils.isNotEmpty(appIdTemp)
+                && !appIdTemp.getProjectOid().equals(projectOid)) {
+            String _name = "";
+            if (ObjectUtils.isNotEmpty(appIdTemp.getProjectInfo())) {
+                _name = appIdTemp.getProjectInfo().getName();
+            }
+            return ResultContent.buildFail(String.format("appId已绑定项目:%s", _name));
+        }
+
         BeanUtils.copyProperties(param, projectWeChatInfo);
         projectWeChatInfo.setProjectInfo(projectInfo);
         projectWeChatInfo.setProjectName(projectInfo.getName());
@@ -106,6 +124,33 @@ public class ProjectWeChatInfoService extends SuperService {
         return false;
     }
 
+    /**
+     * 更加当前的小程序appId 得到对应的项目oid (appId 存储在head里面)
+     *
+     * @return
+     */
+    public ResultContent<List<ProjectXcxModel>> getProjectOidForXcx() {
+        List<ProjectXcxModel> models = new ArrayList<>();
+        String appId = getHeadParam(new String[]{"appId", "appid"});
+        if (StringUtils.isEmpty(appId)) {
+            return ResultContent.buildFail("未取得appId");
+        }
+
+        List<ProjectWeChatInfo> list = projectWeChatInfoDao.findByAppIdOrderByUpdateTimeDesc(appId);
+        if (ObjectUtils.isNotEmpty(list)) {
+            models = list.stream().map(it -> {
+                ProjectXcxModel model = new ProjectXcxModel();
+                Organization projectInfo = it.getProjectInfo();
+                if (ObjectUtils.isNotEmpty(projectInfo)) {
+                    model.setProjectOid(projectInfo.getOid());
+                    model.setProjectName(projectInfo.getName());
+                }
+                return model;
+            }).collect(Collectors.toUnmodifiableList());
+        }
+        return ResultContent.buildSuccess(models);
+    }
+
     public ProjectWeChatInfoModel toModel(ProjectWeChatInfo entity) {
         ProjectWeChatInfoModel model = null;
         if (ObjectUtils.isNotEmpty(entity)) {