feat(): 消防队在线状态查询逻辑,会议室创建同步当前系统成员信息逻辑,集成第三方视频会议平台

dev
lishiwei 2026-07-16 17:45:44 +08:00
parent d1989af322
commit 9f6cecb671
39 changed files with 2317 additions and 21 deletions

View File

@ -0,0 +1,128 @@
package com.zcloud.zcGbsServicer.web;
import com.alibaba.cola.dto.SingleResponse;
import com.zcloud.zcGbsServicer.api.VideoPlatformServiceI;
import com.zcloud.zcGbsServicer.dto.VideoPlatformDepartmentQry;
import com.zcloud.zcGbsServicer.dto.VideoPlatformFixedRoomLeaveCmd;
import com.zcloud.zcGbsServicer.dto.VideoPlatformFixedRoomLoginCmd;
import com.zcloud.zcGbsServicer.dto.VideoPlatformFixedRoomQry;
import com.zcloud.zcGbsServicer.dto.VideoPlatformMeetingAccessCheckQry;
import com.zcloud.zcGbsServicer.dto.VideoPlatformMeetingMemberQry;
import com.zcloud.zcGbsServicer.dto.VideoPlatformUserQry;
import com.zcloud.zcGbsServicer.dto.VideoRoomAuthRoomCmd;
import com.zcloud.zcGbsServicer.dto.VideoRoomAuthUserCmd;
import com.zcloud.zcGbsServicer.dto.VideoRoomCreateInstantCmd;
import com.zcloud.zcGbsServicer.dto.VideoRoomOnlineRoomQry;
import com.zcloud.zcGbsServicer.dto.clientobject.VideoPlatformConfigCO;
import com.zcloud.zcGbsServicer.dto.clientobject.VideoPlatformCurrentMeetingCO;
import com.zcloud.zcGbsServicer.dto.clientobject.VideoPlatformLoginCO;
import com.zcloud.zcGbsServicer.dto.clientobject.VideoPlatformMeetingAccessCheckCO;
import com.zcloud.zcGbsServicer.dto.clientobject.VideoPlatformMeetingMemberStatusCO;
import com.zcloud.zcGbsServicer.dto.clientobject.VideoPlatformOnlineRoomPageCO;
import com.zcloud.zcGbsServicer.dto.clientobject.VideoPlatformResultCO;
import com.zcloud.zcGbsServicer.dto.clientobject.VideoPlatformTokenCO;
import com.zcloud.zcGbsServicer.dto.clientobject.VideoRoomInstantCO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.Collections;
import java.util.List;
@Api(tags = "消防报警视频会议")
@RestController
@AllArgsConstructor
public class VideoPlatformController {
private final VideoPlatformServiceI videoPlatformService;
@ApiOperation("获取视频平台基础配置")
@GetMapping({"/${application.gateway}/video/platform/config", "/video/platform/config"})
public SingleResponse<VideoPlatformConfigCO> getConfig() {
return videoPlatformService.getConfig();
}
@ApiOperation("生成视频平台调试令牌")
@PostMapping({"/${application.gateway}/api/v1/video/token/generate", "/api/v1/video/token/generate"})
public SingleResponse<VideoPlatformTokenCO> generateToken() {
return videoPlatformService.generateToken();
}
@ApiOperation("创建即时会议")
@PostMapping({"/${application.gateway}/api/v1/room/createInstant", "/api/v1/room/createInstant"})
public SingleResponse<VideoRoomInstantCO> createInstant(@Validated @RequestBody(required = false) VideoRoomCreateInstantCmd cmd) {
return videoPlatformService.createInstant(cmd == null ? new VideoRoomCreateInstantCmd() : cmd);
}
@ApiOperation("会议室授权用户")
@PostMapping({"/${application.gateway}/api/v1/room/authUser", "/api/v1/room/authUser"})
public SingleResponse<VideoPlatformResultCO> authUser(@Validated @RequestBody VideoRoomAuthUserCmd cmd) {
return videoPlatformService.authUser(cmd);
}
@ApiOperation("用户授权会议室")
@PostMapping({"/${application.gateway}/api/v1/room/authRoom", "/api/v1/room/authRoom"})
public SingleResponse<VideoPlatformResultCO> authRoom(@Validated @RequestBody VideoRoomAuthRoomCmd cmd) {
return videoPlatformService.authRoom(cmd);
}
@ApiOperation("获取视频平台登录地址")
@GetMapping({"/${application.gateway}/api/v1/room/loginAddr", "/api/v1/room/loginAddr"})
public SingleResponse<List<String>> getLoginAddr() {
List<String> loginAddrList = videoPlatformService.getLoginAddr();
return SingleResponse.of(loginAddrList == null ? Collections.emptyList() : loginAddrList);
}
@ApiOperation("查询在线视频会议")
@PostMapping({"/${application.gateway}/api/v1/room/onlineRoom", "/api/v1/room/onlineRoom"})
public SingleResponse<VideoPlatformOnlineRoomPageCO> onlineRoom(@RequestBody(required = false) VideoRoomOnlineRoomQry qry) {
return videoPlatformService.onlineRoom(qry == null ? new VideoRoomOnlineRoomQry() : qry);
}
@ApiOperation("查询视频平台组织架构")
@PostMapping({"/${application.gateway}/video/platform/department/list", "/video/platform/department/list"})
public SingleResponse<VideoPlatformResultCO> departmentList(@RequestBody(required = false) VideoPlatformDepartmentQry qry) {
return videoPlatformService.departmentList(qry == null ? new VideoPlatformDepartmentQry() : qry);
}
@ApiOperation("查询视频平台用户")
@PostMapping({"/${application.gateway}/video/platform/user/list", "/video/platform/user/list"})
public SingleResponse<VideoPlatformResultCO> userList(@RequestBody(required = false) VideoPlatformUserQry qry) {
return videoPlatformService.userList(qry == null ? new VideoPlatformUserQry() : qry);
}
@ApiOperation("查看当前固定消防会议")
@PostMapping({"/${application.gateway}/video/platform/fixedRoom/current", "/video/platform/fixedRoom/current"})
public SingleResponse<VideoPlatformCurrentMeetingCO> currentFixedMeeting(@RequestBody(required = false) VideoPlatformFixedRoomQry qry) {
return videoPlatformService.currentFixedMeeting(qry == null ? new VideoPlatformFixedRoomQry() : qry);
}
@ApiOperation("固定消防会议入会校验")
@PostMapping({"/${application.gateway}/video/platform/fixedRoom/access/check", "/video/platform/fixedRoom/access/check"})
public SingleResponse<VideoPlatformMeetingAccessCheckCO> checkFixedMeetingAccess(@RequestBody(required = false) VideoPlatformMeetingAccessCheckQry qry) {
return videoPlatformService.checkFixedMeetingAccess(qry == null ? new VideoPlatformMeetingAccessCheckQry() : qry);
}
@ApiOperation("固定消防会议参会成员状态")
@PostMapping({"/${application.gateway}/video/platform/fixedRoom/members", "/video/platform/fixedRoom/members"})
public SingleResponse<VideoPlatformMeetingMemberStatusCO> fixedMeetingMembers(@RequestBody(required = false) VideoPlatformMeetingMemberQry qry) {
return videoPlatformService.fixedMeetingMembers(qry == null ? new VideoPlatformMeetingMemberQry() : qry);
}
@ApiOperation("获取固定会议室入会参数")
@PostMapping({"/${application.gateway}/video/platform/fixedRoom/login", "/video/platform/fixedRoom/login"})
public SingleResponse<VideoPlatformLoginCO> fixedRoomLogin(@RequestBody(required = false) VideoPlatformFixedRoomLoginCmd cmd) {
return videoPlatformService.fixedRoomLogin(cmd == null ? new VideoPlatformFixedRoomLoginCmd() : cmd);
}
@ApiOperation("固定会议室离会回调")
@PostMapping({"/${application.gateway}/video/platform/fixedRoom/leave", "/video/platform/fixedRoom/leave"})
public SingleResponse<VideoPlatformResultCO> fixedRoomLeave(@RequestBody(required = false) VideoPlatformFixedRoomLeaveCmd cmd) {
return videoPlatformService.fixedRoomLeave(cmd == null ? new VideoPlatformFixedRoomLeaveCmd() : cmd);
}
}

View File

@ -14,6 +14,7 @@ import com.zcloud.zcGbsServicer.dto.AlarmRecordPageQry;
import com.zcloud.zcGbsServicer.dto.clientobject.AlarmRecordCO;
import com.zcloud.zcGbsServicer.persistence.dataobject.FireAlarmInfoDO;
import com.zcloud.zcGbsServicer.persistence.dataobject.FireBrigadeDO;
import com.zcloud.zcGbsServicer.persistence.dataobject.FireBrigadeUserDO;
import com.zcloud.zcGbsServicer.persistence.repository.FireAlarmInfoRepository;
import com.zcloud.zcGbsServicer.persistence.repository.FireBrigadeRepository;
import com.zcloud.zcGbsServicer.persistence.repository.FireBrigadeUserRepository;
@ -26,6 +27,7 @@ import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
@ -53,6 +55,14 @@ public class AlarmRecordServiceImpl extends FireAlarmServiceSupport implements A
params.put("pageSize", qry.getPageSize());
params.put("fireBrigadeName", qry.getTeam());
params.put("alarmStatus", parseStatus(qry.getStatus()));
params.put("feedbackOnly", Boolean.TRUE.equals(qry.getMyFeedbackOnly()));
if (Boolean.TRUE.equals(qry.getMyFeedbackOnly())) {
List<String> currentBrigadeIds = getCurrentUserBrigadeBizIds();
if (currentBrigadeIds.isEmpty()) {
return PageResponse.of(Collections.emptyList(), 0, qry.getPageSize(), qry.getPageIndex());
}
params.put("fireBrigadeIds", currentBrigadeIds);
}
PageResponse<FireAlarmInfoDO> page = fireAlarmInfoRepository.listPage(params);
return PageResponse.of(page.getData().stream().map(this::buildCO).collect(Collectors.toList()),
page.getTotalCount(), page.getPageSize(), page.getPageIndex());
@ -80,7 +90,6 @@ public class AlarmRecordServiceImpl extends FireAlarmServiceSupport implements A
record.setLatitude(BigDecimal.valueOf(cmd.getLat()));
record.setAlarmStatus(ALARM_STATUS_ALARMING);
record.setRecordTime(LocalDateTime.now());
record.setMeetingNoticeStatus("INIT");
fireAlarmInfoRepository.save(record);
return SingleResponse.of(buildCO(record));
}
@ -104,7 +113,9 @@ public class AlarmRecordServiceImpl extends FireAlarmServiceSupport implements A
if (!Integer.valueOf(ALARM_STATUS_ALARMING).equals(record.getAlarmStatus())) {
throw new BizException("仅报警中的记录可处置");
}
fillBrigade(record, cmd.getFireBrigadeId(), cmd.getFireBrigadeName());
FireBrigadeDO brigade = resolveHandleBrigade(cmd);
record.setFireBrigadeId(brigade.getFireBrigadeId());
record.setFireBrigadeName(selectText(brigade.getBrigadeName(), cmd.getFireBrigadeName()));
record.setHandleUserId(currentUserId());
record.setHandleUserName(currentUserName());
record.setHandleTime(LocalDateTime.now());
@ -126,7 +137,7 @@ public class AlarmRecordServiceImpl extends FireAlarmServiceSupport implements A
if (!canClearByCurrentUser(record)) {
throw new BizException("仅当前处置消防队成员可消警");
}
record.setClearReason(cmd.getDesc());
record.setClearReason(cmd.getDesc().trim());
record.setClearId(currentUserId());
record.setClearName(currentUserName());
record.setClearTime(LocalDateTime.now());
@ -135,16 +146,29 @@ public class AlarmRecordServiceImpl extends FireAlarmServiceSupport implements A
fireAlarmInfoRepository.updateById(record);
}
private void fillBrigade(FireAlarmInfoDO record, Long fireBrigadePkId, String fireBrigadeName) {
if (fireBrigadePkId == null) {
throw new BizException("请选择处置消防队伍");
private FireBrigadeDO resolveHandleBrigade(AlarmRecordHandleCmd cmd) {
if (cmd.getFireBrigadeId() != null) {
FireBrigadeDO brigade = fireBrigadeRepository.getById(cmd.getFireBrigadeId());
if (brigade == null) {
throw new BizException("处置消防队伍不存在");
}
if (!isCurrentUserInBrigade(brigade.getFireBrigadeId())) {
throw new BizException("只能处置当前登录人所在的消防队报警");
}
return brigade;
}
FireBrigadeDO brigade = fireBrigadeRepository.getById(fireBrigadePkId);
List<FireBrigadeUserDO> relations = currentUserRelations();
if (relations.isEmpty()) {
throw new BizException("当前登录人不是消防队成员,不能执行处置");
}
if (relations.size() > 1) {
throw new BizException("当前登录人存在多个消防队归属,请明确选择处置队伍");
}
FireBrigadeDO brigade = fireBrigadeRepository.getByFireBrigadeId(relations.get(0).getFireBrigadeId());
if (brigade == null) {
throw new BizException("处置消防队伍不存在");
throw new BizException("当前登录人所属消防队不存在");
}
record.setFireBrigadeId(brigade.getFireBrigadeId());
record.setFireBrigadeName(StrUtil.isNotBlank(brigade.getBrigadeName()) ? brigade.getBrigadeName() : fireBrigadeName);
return brigade;
}
private AlarmRecordCO buildCO(FireAlarmInfoDO record) {
@ -226,6 +250,28 @@ public class AlarmRecordServiceImpl extends FireAlarmServiceSupport implements A
return fireBrigadeUserRepository.existsRelation(record.getFireBrigadeId(), currentUserId(), null);
}
private boolean isCurrentUserInBrigade(String fireBrigadeBizId) {
if (StrUtil.isBlank(fireBrigadeBizId) || currentUserId() == null) {
return false;
}
return fireBrigadeUserRepository.existsRelation(fireBrigadeBizId, currentUserId(), null);
}
private List<FireBrigadeUserDO> currentUserRelations() {
if (currentUserId() == null) {
return Collections.emptyList();
}
return fireBrigadeUserRepository.listByUserId(currentUserId());
}
private List<String> getCurrentUserBrigadeBizIds() {
return currentUserRelations().stream()
.map(FireBrigadeUserDO::getFireBrigadeId)
.filter(StrUtil::isNotBlank)
.distinct()
.collect(Collectors.toList());
}
private boolean isValidLongitude(Double lng) {
return lng != null && lng >= -180D && lng <= 180D;
}
@ -234,6 +280,10 @@ public class AlarmRecordServiceImpl extends FireAlarmServiceSupport implements A
return lat != null && lat >= -90D && lat <= 90D;
}
private String selectText(String preferred, String fallback) {
return StrUtil.isNotBlank(preferred) ? preferred : fallback;
}
private long nextId() {
return IdUtil.getSnowflake(1, 1).nextId();
}

View File

@ -1,6 +1,7 @@
package com.zcloud.zcGbsServicer.service;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.cola.dto.PageResponse;
import com.alibaba.cola.dto.SingleResponse;
import com.alibaba.cola.exception.BizException;
@ -11,14 +12,24 @@ import com.zcloud.zcGbsServicer.dto.FireAlarmMeetingRoomPageQry;
import com.zcloud.zcGbsServicer.dto.FireAlarmMeetingRoomUpdateCmd;
import com.zcloud.zcGbsServicer.dto.clientobject.FireAlarmMeetingRoomCO;
import com.zcloud.zcGbsServicer.persistence.dataobject.FireAlarmMeetingRoomDO;
import com.zcloud.zcGbsServicer.persistence.dataobject.FireAlarmMeetingUserDO;
import com.zcloud.zcGbsServicer.persistence.dataobject.FireBrigadeDO;
import com.zcloud.zcGbsServicer.persistence.dataobject.FireBrigadeUserDO;
import com.zcloud.zcGbsServicer.persistence.repository.FireAlarmMeetingRoomRepository;
import com.zcloud.zcGbsServicer.persistence.repository.FireAlarmMeetingUserRepository;
import com.zcloud.zcGbsServicer.persistence.repository.FireBrigadeRepository;
import com.zcloud.zcGbsServicer.persistence.repository.FireBrigadeUserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
@ -26,6 +37,10 @@ public class FireAlarmMeetingRoomServiceImpl extends FireAlarmServiceSupport imp
private final FireAlarmMeetingRoomRepository fireAlarmMeetingRoomRepository;
private final FireAlarmMeetingRoomCoConvertor fireAlarmMeetingRoomCoConvertor;
private final HstVideoPlatformClient hstVideoPlatformClient;
private final FireBrigadeUserRepository fireBrigadeUserRepository;
private final FireBrigadeRepository fireBrigadeRepository;
private final FireAlarmMeetingUserRepository fireAlarmMeetingUserRepository;
@Override
public PageResponse<FireAlarmMeetingRoomCO> listPage(FireAlarmMeetingRoomPageQry qry) {
@ -43,16 +58,35 @@ public class FireAlarmMeetingRoomServiceImpl extends FireAlarmServiceSupport imp
@Override
@Transactional(rollbackFor = Exception.class)
public SingleResponse<FireAlarmMeetingRoomCO> add(FireAlarmMeetingRoomAddCmd cmd) {
if (fireAlarmMeetingRoomRepository.existsByRoomCode(cmd.getRoomCode(), null)) {
throw new BizException("会议室编码已存在");
List<FireAlarmMeetingRoomDO> existingRooms = fireAlarmMeetingRoomRepository.listAll();
if (existingRooms != null && !existingRooms.isEmpty()) {
throw new BizException("已有固定会议室,不能重复创建");
}
Map<String, Object> requestBody = new LinkedHashMap<>();
requestBody.put("roomName", cmd.getRoomName());
if (StrUtil.isNotBlank(cmd.getRoomCode())) {
requestBody.put("roomCode", cmd.getRoomCode());
}
if (StrUtil.isNotBlank(cmd.getRoomPasswordCipher())) {
requestBody.put("password", cmd.getRoomPasswordCipher());
}
Map<String, Object> response = hstVideoPlatformClient.addRoomInfo(requestBody);
hstVideoPlatformClient.ensureSuccess(response, "创建第三方固定会议室");
Map<String, Object> data = castMap(response.get("data"));
FireAlarmMeetingRoomDO room = new FireAlarmMeetingRoomDO();
room.setId(nextId());
room.setFireAlarmMeetingRoomId(nextBizId());
room.setRebuildCount(0);
room.setThirdRoomId(selectText(asText(data.get("roomId")), cmd.getThirdRoomId()));
room.setThirdRoomNo(selectText(asText(data.get("roomNo")), cmd.getThirdRoomNo()));
fillCreateAudit(room);
fillRoom(room, cmd);
fireAlarmMeetingRoomRepository.save(room);
syncAuthUsersForNewRoom(room);
return SingleResponse.of(fireAlarmMeetingRoomCoConvertor.converDOToCO(room));
}
@ -100,6 +134,76 @@ public class FireAlarmMeetingRoomServiceImpl extends FireAlarmServiceSupport imp
room.setRemarks(cmd.getRemarks());
}
private void syncAuthUsersForNewRoom(FireAlarmMeetingRoomDO room) {
String roomId = selectText(room.getThirdRoomId(), room.getThirdRoomNo());
if (StrUtil.isBlank(roomId)) {
return;
}
List<FireBrigadeUserDO> brigadeUsers = fireBrigadeUserRepository.listAll();
if (brigadeUsers == null || brigadeUsers.isEmpty()) {
return;
}
Map<Long, FireAlarmMeetingUserDO> meetingUserMap = fireAlarmMeetingUserRepository.listAll()
.stream()
.filter(u -> u.getLocalUserId() != null && StrUtil.isNotBlank(u.getThirdUserName()))
.collect(Collectors.toMap(FireAlarmMeetingUserDO::getLocalUserId, u -> u, (a, b) -> a));
Set<String> brigadeIds = brigadeUsers.stream()
.map(FireBrigadeUserDO::getFireBrigadeId)
.filter(StrUtil::isNotBlank)
.collect(Collectors.toSet());
Map<String, FireBrigadeDO> brigadeMap = new HashMap<>();
for (String brigadeId : brigadeIds) {
FireBrigadeDO brigade = fireBrigadeRepository.getByFireBrigadeId(brigadeId);
if (brigade != null) {
brigadeMap.put(brigadeId, brigade);
}
}
for (FireBrigadeUserDO brigadeUser : brigadeUsers) {
if (brigadeUser.getUserId() == null) {
continue;
}
FireAlarmMeetingUserDO meetingUser = meetingUserMap.get(brigadeUser.getUserId());
if (meetingUser == null) {
continue;
}
FireBrigadeDO brigade = brigadeMap.get(brigadeUser.getFireBrigadeId());
boolean isLeader = brigade != null && brigade.getLeaderUserId() != null
&& brigade.getLeaderUserId().equals(brigadeUser.getUserId());
int permission = isLeader ? 3 : 2;
Map<String, Object> authBody = new LinkedHashMap<>();
authBody.put("roomUserStr", roomId + "," + permission);
authBody.put("userName", meetingUser.getThirdUserName());
try {
Map<String, Object> authResp = hstVideoPlatformClient.authRoom(authBody);
hstVideoPlatformClient.ensureSuccess(authResp, "用户授权新会议室");
} catch (BizException ex) {
throw new BizException("用户授权新会议室失败", ex);
}
}
}
@SuppressWarnings("unchecked")
private Map<String, Object> castMap(Object value) {
if (!(value instanceof Map)) {
return new HashMap<>();
}
return (Map<String, Object>) value;
}
private String asText(Object value) {
return value == null ? null : String.valueOf(value);
}
private String selectText(String preferred, String fallback) {
return StrUtil.isNotBlank(preferred) ? preferred : fallback;
}
private long nextId() {
return IdUtil.getSnowflake(1, 1).nextId();
}

View File

@ -12,14 +12,21 @@ import com.zcloud.zcGbsServicer.dto.FireBrigadeMemberAddCmd;
import com.zcloud.zcGbsServicer.dto.FireBrigadeMemberPageQry;
import com.zcloud.zcGbsServicer.dto.FireBrigadeMemberUpdateCmd;
import com.zcloud.zcGbsServicer.dto.clientobject.FireBrigadeMemberCO;
import com.zcloud.zcGbsServicer.persistence.dataobject.FireAlarmMeetingRoomDO;
import com.zcloud.zcGbsServicer.persistence.dataobject.FireAlarmMeetingUserDO;
import com.zcloud.zcGbsServicer.persistence.dataobject.FireBrigadeDO;
import com.zcloud.zcGbsServicer.persistence.dataobject.FireBrigadeUserDO;
import com.zcloud.zcGbsServicer.persistence.repository.FireAlarmMeetingRoomRepository;
import com.zcloud.zcGbsServicer.persistence.repository.FireAlarmMeetingUserRepository;
import com.zcloud.zcGbsServicer.persistence.repository.FireBrigadeRepository;
import com.zcloud.zcGbsServicer.persistence.repository.FireBrigadeUserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@ -33,6 +40,10 @@ public class FireBrigadeMemberServiceImpl extends FireAlarmServiceSupport implem
private final FireBrigadeRepository fireBrigadeRepository;
private final FireBrigadeUserRepository fireBrigadeUserRepository;
private final FireAlarmMeetingRoomRepository fireAlarmMeetingRoomRepository;
private final FireAlarmMeetingUserRepository fireAlarmMeetingUserRepository;
private final HstVideoPlatformProperties hstVideoPlatformProperties;
private final HstVideoPlatformClient hstVideoPlatformClient;
private final FireAlarmUserResolver fireAlarmUserResolver;
private final FireBrigadeMemberCoConvertor fireBrigadeMemberCoConvertor;
@ -71,6 +82,7 @@ public class FireBrigadeMemberServiceImpl extends FireAlarmServiceSupport implem
relation.setUserId(userId);
fillMemberSnapshot(relation, cmd);
fillCreateAudit(relation);
syncCreateMeetingUser(relation, brigade);
fireBrigadeUserRepository.save(relation);
return SingleResponse.of(buildCO(relation, brigade, fireAlarmUserResolver.getUserMap(Collections.singleton(userId))));
}
@ -121,6 +133,7 @@ public class FireBrigadeMemberServiceImpl extends FireAlarmServiceSupport implem
}
checkLeaderRelation(relation);
fireBrigadeUserRepository.removeById(id);
syncDeleteMeetingUserIfUnused(relation);
}
@Override
@ -135,7 +148,13 @@ public class FireBrigadeMemberServiceImpl extends FireAlarmServiceSupport implem
checkLeaderRelation(relation);
}
}
fireBrigadeUserRepository.removeByIds(java.util.Arrays.asList(ids));
for (Long id : ids) {
FireBrigadeUserDO relation = fireBrigadeUserRepository.getById(id);
if (relation != null) {
fireBrigadeUserRepository.removeById(id);
syncDeleteMeetingUserIfUnused(relation);
}
}
}
private FireBrigadeDO getBrigade(Long id) {
@ -182,6 +201,171 @@ public class FireBrigadeMemberServiceImpl extends FireAlarmServiceSupport implem
relation.setOrgName(cmd.getOrg());
}
private void syncCreateMeetingUser(FireBrigadeUserDO relation, FireBrigadeDO brigade) {
if (StrUtil.isBlank(hstVideoPlatformProperties.getDefaultUserPassword())) {
throw new BizException("视频平台默认用户密码未配置,不能创建消防会议账号");
}
String thirdUserName = resolveThirdUserName(relation.getUserId());
Map<String, Object> requestBody = new LinkedHashMap<>();
requestBody.put("userName", thirdUserName);
requestBody.put("password", hstVideoPlatformProperties.getDefaultUserPassword());
requestBody.put("passwordType", 0);
requestBody.put("mobile", relation.getPhone());
requestBody.put("nickName", selectText(relation.getUserName(), thirdUserName));
requestBody.put("sex", "女".equals(relation.getGender()) ? "1" : "0");
requestBody.put("departId", StrUtil.blankToDefault(brigade.getThirdDepartId(), "0"));
requestBody.put("adminRole", 2);
Map<String, Object> data = new HashMap<>();
String syncMsg = "第三方账号创建成功";
try {
Map<String, Object> response = hstVideoPlatformClient.addUser(requestBody);
hstVideoPlatformClient.ensureSuccess(response, "创建视频平台用户");
data = castMap(response.get("data"));
syncMsg = selectText(asText(response.get("msg")), syncMsg);
}
catch (BizException ex) {
if (!isAlreadyExists(ex.getMessage())) {
throw new BizException("创建视频平台用户失败:" + ex.getMessage());
}
syncMsg = "第三方账号已存在,已复用";
}
upsertMeetingUserMapping(relation, brigade, thirdUserName, data, syncMsg);
syncRoomAuth(thirdUserName, 2);
}
private void upsertMeetingUserMapping(FireBrigadeUserDO relation, FireBrigadeDO brigade,
String thirdUserName, Map<String, Object> data, String syncMsg) {
FireAlarmMeetingUserDO meetingUser = fireAlarmMeetingUserRepository.getByLocalUserId(relation.getUserId());
boolean isNew = meetingUser == null;
if (meetingUser == null) {
meetingUser = new FireAlarmMeetingUserDO();
meetingUser.setId(nextId());
meetingUser.setFireAlarmMeetingUserId(nextBizId());
fillCreateAudit(meetingUser);
}
else {
fillUpdateAudit(meetingUser);
}
FireAlarmMeetingRoomDO room = fireAlarmMeetingRoomRepository.getByRoomCode(hstVideoPlatformProperties.getDefaultRoomCode());
LocalDateTime now = LocalDateTime.now();
meetingUser.setLocalUserId(relation.getUserId());
meetingUser.setLocalUserName(relation.getUserName());
meetingUser.setLocalPhone(relation.getPhone());
meetingUser.setUserType(1);
meetingUser.setFireBrigadeId(brigade.getFireBrigadeId());
meetingUser.setFireBrigadeName(brigade.getBrigadeName());
meetingUser.setThirdUserId(selectText(asText(data.get("userId")), meetingUser.getThirdUserId()));
meetingUser.setThirdUserName(selectText(asText(data.get("userName")), thirdUserName));
meetingUser.setThirdNickName(selectText(asText(data.get("displayName")), relation.getUserName()));
meetingUser.setThirdDepartId(selectText(asText(data.get("departId")), brigade.getThirdDepartId()));
meetingUser.setThirdDepartName(brigade.getThirdDepartName());
meetingUser.setAuthRoomId(room == null ? hstVideoPlatformProperties.getDefaultRoomNo() : selectText(room.getThirdRoomId(), room.getThirdRoomNo()));
meetingUser.setAuthRoomName(room == null ? "消防报警固定会议室" : room.getRoomName());
meetingUser.setAuthStatus(1);
meetingUser.setAuthTime(now);
meetingUser.setSyncStatus(1);
meetingUser.setSyncMsg(syncMsg);
meetingUser.setLastSyncTime(now);
if (isNew) {
fireAlarmMeetingUserRepository.save(meetingUser);
}
else {
fireAlarmMeetingUserRepository.updateById(meetingUser);
}
}
private void syncRoomAuth(String thirdUserName, int permission) {
if (StrUtil.isBlank(thirdUserName)) {
return;
}
FireAlarmMeetingRoomDO room = fireAlarmMeetingRoomRepository.getByRoomCode(hstVideoPlatformProperties.getDefaultRoomCode());
String roomId = room == null ? hstVideoPlatformProperties.getDefaultRoomNo()
: selectText(room.getThirdRoomId(), room.getThirdRoomNo());
if (StrUtil.isBlank(roomId)) {
return;
}
Map<String, Object> requestBody = new LinkedHashMap<>();
requestBody.put("roomUserStr", roomId + "," + permission);
requestBody.put("userName", thirdUserName);
try {
Map<String, Object> response = hstVideoPlatformClient.authRoom(requestBody);
hstVideoPlatformClient.ensureSuccess(response, permission == 0 ? "解除用户会议室授权" : "用户授权会议室");
} catch (BizException ex) {
throw new BizException("用户授权会议室失败:" + ex.getMessage());
}
}
private void syncDeleteMeetingUserIfUnused(FireBrigadeUserDO relation) {
if (relation == null || relation.getUserId() == null) {
return;
}
List<FireBrigadeUserDO> activeRelations = fireBrigadeUserRepository.listByUserId(relation.getUserId());
if (activeRelations != null && !activeRelations.isEmpty()) {
return;
}
FireAlarmMeetingUserDO meetingUser = fireAlarmMeetingUserRepository.getByLocalUserId(relation.getUserId());
if (meetingUser == null) {
return;
}
if (StrUtil.isNotBlank(meetingUser.getThirdUserName())) {
syncRoomAuth(meetingUser.getThirdUserName(), 0);
Map<String, Object> requestBody = new LinkedHashMap<>();
requestBody.put("userName", meetingUser.getThirdUserName());
try {
Map<String, Object> response = hstVideoPlatformClient.deleteUser(requestBody);
hstVideoPlatformClient.ensureSuccess(response, "删除视频平台用户");
}
catch (BizException ex) {
if (!isAlreadyMissing(ex.getMessage())) {
throw new BizException("删除视频平台用户失败:" + ex.getMessage());
}
}
}
fillUpdateAudit(meetingUser);
meetingUser.setDeleteEnum("TRUE");
meetingUser.setSyncStatus(1);
meetingUser.setSyncMsg("第三方账号已删除,会议账号映射已作废");
meetingUser.setLastSyncTime(LocalDateTime.now());
fireAlarmMeetingUserRepository.updateById(meetingUser);
}
private String resolveThirdUserName(Long localUserId) {
FireAlarmMeetingUserDO meetingUser = fireAlarmMeetingUserRepository.getByLocalUserId(localUserId);
if (meetingUser != null && StrUtil.isNotBlank(meetingUser.getThirdUserName())) {
return meetingUser.getThirdUserName().trim();
}
String userName = StrUtil.blankToDefault(hstVideoPlatformProperties.getFireUserPrefix(), "xfbj") + localUserId;
if (userName.length() > 32) {
return userName.substring(0, 32);
}
return userName;
}
private boolean isAlreadyExists(String message) {
String msg = StrUtil.blankToDefault(message, "").toLowerCase();
return msg.contains("存在") || msg.contains("exist") || msg.contains("duplicate");
}
private boolean isAlreadyMissing(String message) {
String msg = StrUtil.blankToDefault(message, "").toLowerCase();
return msg.contains("不存在") || msg.contains("not exist") || msg.contains("not found");
}
@SuppressWarnings("unchecked")
private Map<String, Object> castMap(Object value) {
if (!(value instanceof Map)) {
return new HashMap<>();
}
return (Map<String, Object>) value;
}
private String asText(Object value) {
return value == null ? null : String.valueOf(value);
}
private String selectText(String preferred, String fallback) {
return StrUtil.isNotBlank(preferred) ? preferred : fallback;
}

View File

@ -0,0 +1,175 @@
package com.zcloud.zcGbsServicer.service;
import cn.hutool.core.util.StrUtil;
import com.zcloud.zcGbsServicer.persistence.dataobject.FireAlarmMeetingUserDO;
import com.zcloud.zcGbsServicer.persistence.dataobject.FireBrigadeDO;
import com.zcloud.zcGbsServicer.persistence.dataobject.FireBrigadeUserDO;
import com.zcloud.zcGbsServicer.persistence.repository.FireAlarmMeetingUserRepository;
import com.zcloud.zcGbsServicer.persistence.repository.FireBrigadeUserRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
@Slf4j
@Service
@RequiredArgsConstructor
public class FireBrigadeOnlineStatusService {
private static final int USER_ONLINE_IN_MEETING = 1;
private final FireBrigadeUserRepository fireBrigadeUserRepository;
private final FireAlarmMeetingUserRepository fireAlarmMeetingUserRepository;
private final HstVideoPlatformClient hstVideoPlatformClient;
public Map<String, Boolean> calculateOnlineMap(List<FireBrigadeDO> brigades) {
if (brigades == null || brigades.isEmpty()) {
return Collections.emptyMap();
}
Set<String> brigadeBizIds = brigades.stream()
.map(FireBrigadeDO::getFireBrigadeId)
.filter(StrUtil::isNotBlank)
.collect(Collectors.toCollection(LinkedHashSet::new));
if (brigadeBizIds.isEmpty()) {
return Collections.emptyMap();
}
List<FireBrigadeUserDO> allBrigadeUsers = fireBrigadeUserRepository.listAll();
Map<String, List<FireBrigadeUserDO>> brigadeUserMap = allBrigadeUsers.stream()
.filter(item -> item != null && brigadeBizIds.contains(item.getFireBrigadeId()))
.collect(Collectors.groupingBy(FireBrigadeUserDO::getFireBrigadeId, LinkedHashMap::new, Collectors.toList()));
if (brigadeUserMap.isEmpty()) {
return buildOfflineMap(brigadeBizIds);
}
Set<Long> localUserIds = brigadeUserMap.values().stream()
.flatMap(List::stream)
.map(FireBrigadeUserDO::getUserId)
.filter(java.util.Objects::nonNull)
.collect(Collectors.toCollection(LinkedHashSet::new));
if (localUserIds.isEmpty()) {
return buildOfflineMap(brigadeBizIds);
}
Map<Long, String> meetingAccountMap = fireAlarmMeetingUserRepository.listAll().stream()
.filter(item -> item != null && item.getLocalUserId() != null)
.filter(item -> localUserIds.contains(item.getLocalUserId()))
.filter(item -> StrUtil.isNotBlank(item.getThirdUserName()))
.collect(Collectors.toMap(FireAlarmMeetingUserDO::getLocalUserId,
item -> item.getThirdUserName().trim(),
(left, right) -> left,
LinkedHashMap::new));
if (meetingAccountMap.isEmpty()) {
return buildOfflineMap(brigadeBizIds);
}
Set<String> onlineMeetingAccounts = queryOnlineMeetingAccounts(new LinkedHashSet<>(meetingAccountMap.values()));
Map<String, Boolean> result = buildOfflineMap(brigadeBizIds);
if (onlineMeetingAccounts.isEmpty()) {
return result;
}
for (Map.Entry<String, List<FireBrigadeUserDO>> entry : brigadeUserMap.entrySet()) {
boolean online = entry.getValue().stream()
.map(FireBrigadeUserDO::getUserId)
.filter(java.util.Objects::nonNull)
.map(meetingAccountMap::get)
.filter(StrUtil::isNotBlank)
.anyMatch(onlineMeetingAccounts::contains);
result.put(entry.getKey(), online);
}
return result;
}
private Set<String> queryOnlineMeetingAccounts(Set<String> meetingAccounts) {
if (meetingAccounts == null || meetingAccounts.isEmpty()) {
return Collections.emptySet();
}
Set<String> result = new LinkedHashSet<>();
boolean authInvalid = false;
for (String meetingAccount : meetingAccounts) {
if (authInvalid) {
break;
}
try {
List<Map<String, Object>> records = hstVideoPlatformClient.userOnline(meetingAccount);
if (isInMeeting(records)) {
result.add(meetingAccount);
}
}
catch (Exception ex) {
if (isInvalidAuth(ex)) {
authInvalid = true;
log.warn("查询视频平台用户在线状态失败,视频平台 HTTP API 鉴权无效,请检查 key/secret 是否为后台 HTTP API 分配的凭证,当前账号={}",
meetingAccount, ex);
continue;
}
log.warn("查询视频平台用户在线状态失败userName={}", meetingAccount, ex);
}
}
return result;
}
private boolean isInvalidAuth(Exception ex) {
String message = ex == null ? null : ex.getMessage();
return StrUtil.contains(message, "无效认证信息")
|| StrUtil.containsIgnoreCase(message, "1003");
}
private boolean isInMeeting(List<Map<String, Object>> records) {
if (records == null || records.isEmpty()) {
return false;
}
for (Map<String, Object> record : records) {
if (record == null) {
continue;
}
Integer online = asInteger(record.get("online"));
Object roomId = record.get("roomId");
if (hasRoomId(roomId)) {
return true;
}
if (Integer.valueOf(USER_ONLINE_IN_MEETING).equals(online)) {
return true;
}
}
return false;
}
private boolean hasRoomId(Object roomId) {
if (roomId == null) {
return false;
}
return !(roomId instanceof String) || StrUtil.isNotBlank((String) roomId);
}
private Integer asInteger(Object value) {
if (value == null) {
return null;
}
if (value instanceof Number) {
return ((Number) value).intValue();
}
try {
return Integer.valueOf(String.valueOf(value));
}
catch (Exception ex) {
return null;
}
}
private Map<String, Boolean> buildOfflineMap(Set<String> brigadeBizIds) {
Map<String, Boolean> result = new LinkedHashMap<>();
for (String brigadeBizId : brigadeBizIds) {
result.put(brigadeBizId, Boolean.FALSE);
}
return result;
}
}

View File

@ -35,6 +35,7 @@ public class FireBrigadeServiceImpl extends FireAlarmServiceSupport implements F
private final FireBrigadeRepository fireBrigadeRepository;
private final FireBrigadeUserRepository fireBrigadeUserRepository;
private final FireAlarmUserResolver fireAlarmUserResolver;
private final FireBrigadeOnlineStatusService fireBrigadeOnlineStatusService;
private final FireBrigadeCoConvertor fireBrigadeCoConvertor;
@Override
@ -45,8 +46,9 @@ public class FireBrigadeServiceImpl extends FireAlarmServiceSupport implements F
params.put("brigadeName", qry.getName());
PageResponse<FireBrigadeDO> page = fireBrigadeRepository.listPage(params);
Map<Long, ZcloudUserCo> userMap = getLeaderUserMap(page.getData());
Map<String, Boolean> onlineMap = fireBrigadeOnlineStatusService.calculateOnlineMap(page.getData());
List<FireBrigadeCO> data = page.getData().stream()
.map(item -> buildCO(item, userMap))
.map(item -> buildCO(item, userMap, onlineMap))
.collect(Collectors.toList());
return PageResponse.of(data, page.getTotalCount(), page.getPageSize(), page.getPageIndex());
}
@ -67,7 +69,9 @@ public class FireBrigadeServiceImpl extends FireAlarmServiceSupport implements F
fillBrigade(brigade, cmd);
fireBrigadeRepository.save(brigade);
ensureLeaderRelation(brigade);
return SingleResponse.of(buildCO(brigade, getLeaderUserMap(Collections.singletonList(brigade))));
return SingleResponse.of(buildCO(brigade,
getLeaderUserMap(Collections.singletonList(brigade)),
fireBrigadeOnlineStatusService.calculateOnlineMap(Collections.singletonList(brigade))));
}
@Override
@ -95,7 +99,9 @@ public class FireBrigadeServiceImpl extends FireAlarmServiceSupport implements F
if (brigade == null) {
throw new BizException("消防队伍不存在");
}
return buildCO(brigade, getLeaderUserMap(Collections.singletonList(brigade)));
return buildCO(brigade,
getLeaderUserMap(Collections.singletonList(brigade)),
fireBrigadeOnlineStatusService.calculateOnlineMap(Collections.singletonList(brigade)));
}
@Override
@ -159,15 +165,17 @@ public class FireBrigadeServiceImpl extends FireAlarmServiceSupport implements F
relation.setOrgName(brigade.getLeaderDeptName());
}
private FireBrigadeCO buildCO(FireBrigadeDO brigade, Map<Long, ZcloudUserCo> userMap) {
private FireBrigadeCO buildCO(FireBrigadeDO brigade, Map<Long, ZcloudUserCo> userMap,
Map<String, Boolean> onlineMap) {
FireBrigadeCO co = fireBrigadeCoConvertor.converDOToCO(brigade);
ZcloudUserCo leader = brigade.getLeaderUserId() == null ? null : userMap.get(brigade.getLeaderUserId());
co.setLeaderDeptName(selectText(leader == null ? null : leader.getDepartmentName(), co.getLeaderDeptName()));
co.setLeaderName(selectText(leader == null ? null : leader.getName(), co.getLeaderName()));
co.setLeaderPhone(selectText(leader == null ? null : leader.getPhone(), co.getLeaderPhone()));
co.setMemberCount(fireBrigadeUserRepository.listByFireBrigadeId(brigade.getFireBrigadeId()).size());
co.setOnline(Boolean.FALSE);
co.setOnlineText("未统计");
boolean online = onlineMap != null && Boolean.TRUE.equals(onlineMap.get(brigade.getFireBrigadeId()));
co.setOnline(online);
co.setOnlineText(online ? "在线" : "未在线");
return co;
}

View File

@ -0,0 +1,199 @@
package com.zcloud.zcGbsServicer.service;
import cn.hutool.core.util.StrUtil;
import com.alibaba.cola.exception.BizException;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.client.HttpStatusCodeException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriUtils;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Base64;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@Component
@RequiredArgsConstructor
@SuppressWarnings("unchecked")
public class HstVideoPlatformClient {
private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
private final HstVideoPlatformProperties properties;
public String generateToken() {
validateConfig();
long timestamp = System.currentTimeMillis();
String headerJson = "{\"alg\":\"" + StrUtil.blankToDefault(properties.getAlgorithm(), "SHA256") + "\"}";
String payloadJson = "{\"key\":\"" + properties.getAuthKey() + "\",\"timestamp\":" + timestamp + "}";
String header = Base64.getEncoder().encodeToString(headerJson.getBytes(StandardCharsets.UTF_8));
String payload = Base64.getEncoder().encodeToString(payloadJson.getBytes(StandardCharsets.UTF_8));
String signature = sha256Hex(header + payload + properties.getAuthSecret());
return header + "." + payload + "." + signature;
}
public String formatExpireTime() {
return TIME_FORMATTER.format(LocalDateTime.now().plusMinutes(10));
}
public Map<String, Object> createInstant(Map<String, Object> body) {
return post("/api/v1/room/createInstant", body);
}
public Map<String, Object> authUser(Map<String, Object> body) {
return post("/api/v1/room/authUser", body);
}
public Map<String, Object> authRoom(Map<String, Object> body) {
return post("/api/v1/room/authRoom", body);
}
public Map<String, Object> addRoomInfo(Map<String, Object> body) {
return post("/api/v1/room/addRoomInfo", body);
}
public Map<String, Object> onlineRoom(Map<String, Object> body) {
return post("/api/v1/room/onlineRoom", body);
}
public Map<String, Object> departmentList(Map<String, Object> body) {
return post("/api/v1/department/list", body);
}
public Map<String, Object> userList(Map<String, Object> body) {
return post("/api/v1/user/list", body);
}
public Map<String, Object> addUser(Map<String, Object> body) {
return post("/api/v1/user/add", body);
}
public Map<String, Object> deleteUser(Map<String, Object> body) {
return post("/api/v1/user/del", body);
}
public Map<String, Object> participant(Map<String, Object> body) {
return post("/api/v1/room/participant", body);
}
public Map<String, Object> roomLog(Map<String, Object> body) {
return post("/api/v1/room/roomLog", body);
}
public Map<String, Object> userInRoom(Map<String, Object> body) {
return post("/api/v1/room/userInRoom", body);
}
public List<Map<String, Object>> userOnline(String userName) {
if (StrUtil.isBlank(userName)) {
return Collections.emptyList();
}
Map<String, Object> response = get("/api/v1/user/online/"
+ UriUtils.encodePathSegment(userName.trim(), StandardCharsets.UTF_8));
ensureSuccess(response, "获取用户在线状态");
Object data = response.get("data");
if (!(data instanceof List)) {
return Collections.emptyList();
}
return (List<Map<String, Object>>) data;
}
public Map<String, Object> loginAddr() {
return get("/api/v1/room/loginAddr");
}
public void ensureSuccess(Map<String, Object> response, String actionName) {
String code = response == null ? null : asText(response.get("code"));
if (StrUtil.isBlank(code) || "0".equals(code) || "200".equals(code)) {
return;
}
String msg = response == null ? null : asText(response.get("msg"));
throw new BizException(actionName + "失败" + (StrUtil.isBlank(msg) ? "" : "" + msg));
}
private Map<String, Object> post(String path, Map<String, Object> body) {
return request(path, HttpMethod.POST, body == null ? Collections.emptyMap() : body);
}
private Map<String, Object> get(String path) {
return request(path, HttpMethod.GET, null);
}
private Map<String, Object> request(String path, HttpMethod method, Object body) {
validateConfig();
RestTemplate restTemplate = createRestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("Authorization", generateToken());
HttpEntity<?> requestEntity = new HttpEntity<>(body, headers);
try {
ResponseEntity<Map> response = restTemplate.exchange(buildUrl(path), method, requestEntity, Map.class);
return response.getBody() == null ? new LinkedHashMap<>() : response.getBody();
}
catch (HttpStatusCodeException ex) {
throw new BizException("调用视频平台失败:" + ex.getResponseBodyAsString());
}
catch (Exception ex) {
throw new BizException("调用视频平台失败:" + ex.getMessage());
}
}
private RestTemplate createRestTemplate() {
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setConnectTimeout(properties.getConnectTimeoutMs() == null ? 10000 : properties.getConnectTimeoutMs());
requestFactory.setReadTimeout(properties.getReadTimeoutMs() == null ? 15000 : properties.getReadTimeoutMs());
return new RestTemplate(requestFactory);
}
private String buildUrl(String path) {
String baseUrl = StrUtil.blankToDefault(properties.getApiBaseUrl(), properties.getWebBaseUrl());
if (StrUtil.isBlank(baseUrl)) {
throw new BizException("视频平台地址未配置");
}
return StrUtil.removeSuffix(baseUrl.trim(), "/") + path;
}
private void validateConfig() {
if (StrUtil.isBlank(properties.getAuthKey())) {
throw new BizException("视频平台 HTTP API key 未配置");
}
if (StrUtil.isBlank(properties.getAuthSecret())) {
throw new BizException("视频平台 HTTP API secret 未配置");
}
}
private String sha256Hex(String source) {
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] bytes = digest.digest(source.getBytes(StandardCharsets.UTF_8));
StringBuilder builder = new StringBuilder();
for (byte item : bytes) {
String hex = Integer.toHexString(item & 0xFF);
if (hex.length() == 1) {
builder.append('0');
}
builder.append(hex);
}
return builder.toString();
}
catch (Exception ex) {
throw new BizException("生成视频平台令牌失败:" + ex.getMessage());
}
}
private String asText(Object value) {
return value == null ? null : String.valueOf(value);
}
}

View File

@ -0,0 +1,68 @@
package com.zcloud.zcGbsServicer.service;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.List;
@Data
@Component
public class HstVideoPlatformProperties {
@Value("${video.platform.hst.api-base-url:https://5uw.haoshitong.com:28443}")
private String apiBaseUrl;
@Value("${video.platform.hst.web-base-url:https://5uw.haoshitong.com:28443}")
private String webBaseUrl;
@Value("${video.platform.hst.client-id:}")
private String clientId;
@Value("${video.platform.hst.client-secret:}")
private String clientSecret;
@Value("${video.platform.hst.key:}")
private String key;
@Value("${video.platform.hst.secret:}")
private String secret;
@Value("${video.platform.hst.algorithm:SHA256}")
private String algorithm;
@Value("${video.platform.hst.default-room-code:DEFAULT_DUTY_ROOM}")
private String defaultRoomCode;
@Value("${video.platform.hst.default-room-no:20708}")
private String defaultRoomNo;
@Value("${video.platform.hst.default-user-password:}")
private String defaultUserPassword;
@Value("${video.platform.hst.fire-user-prefix:xfbj}")
private String fireUserPrefix;
@Value("${video.platform.hst.default-depart-id:1}")
private String defaultDepartId;
@Value("${video.platform.hst.client-port:1089}")
private String clientPort;
@Value("${video.platform.hst.connect-timeout-ms:10000}")
private Integer connectTimeoutMs;
@Value("${video.platform.hst.read-timeout-ms:15000}")
private Integer readTimeoutMs;
@Value("#{'${video.platform.hst.test-accounts:xfbj00,xfbj01,xfbj02,xfbj03,xfbj04,xfbj05,xfbj06,xfbj07,xfbj08,xfbj09}'.split(',')}")
private List<String> testAccounts;
public String getAuthKey() {
return org.springframework.util.StringUtils.hasText(key) ? key : clientId;
}
public String getAuthSecret() {
return org.springframework.util.StringUtils.hasText(secret) ? secret : clientSecret;
}
}

View File

@ -0,0 +1,772 @@
package com.zcloud.zcGbsServicer.service;
import cn.hutool.core.util.StrUtil;
import com.alibaba.cola.dto.SingleResponse;
import com.alibaba.cola.exception.BizException;
import com.zcloud.zcGbsServicer.api.VideoPlatformServiceI;
import com.zcloud.zcGbsServicer.dto.VideoPlatformDepartmentQry;
import com.zcloud.zcGbsServicer.dto.VideoPlatformFixedRoomLeaveCmd;
import com.zcloud.zcGbsServicer.dto.VideoPlatformFixedRoomLoginCmd;
import com.zcloud.zcGbsServicer.dto.VideoPlatformFixedRoomQry;
import com.zcloud.zcGbsServicer.dto.VideoPlatformMeetingAccessCheckQry;
import com.zcloud.zcGbsServicer.dto.VideoPlatformMeetingMemberQry;
import com.zcloud.zcGbsServicer.dto.VideoPlatformUserQry;
import com.zcloud.zcGbsServicer.dto.VideoRoomAuthRoomCmd;
import com.zcloud.zcGbsServicer.dto.VideoRoomAuthUserCmd;
import com.zcloud.zcGbsServicer.dto.VideoRoomCreateInstantCmd;
import com.zcloud.zcGbsServicer.dto.VideoRoomOnlineRoomQry;
import com.zcloud.zcGbsServicer.dto.clientobject.VideoPlatformConfigCO;
import com.zcloud.zcGbsServicer.dto.clientobject.VideoPlatformCurrentMeetingCO;
import com.zcloud.zcGbsServicer.dto.clientobject.VideoPlatformLoginCO;
import com.zcloud.zcGbsServicer.dto.clientobject.VideoPlatformMeetingAccessCheckCO;
import com.zcloud.zcGbsServicer.dto.clientobject.VideoPlatformMeetingLogCO;
import com.zcloud.zcGbsServicer.dto.clientobject.VideoPlatformMeetingMemberStatusCO;
import com.zcloud.zcGbsServicer.dto.clientobject.VideoPlatformMeetingParticipantCO;
import com.zcloud.zcGbsServicer.dto.clientobject.VideoPlatformOnlineRoomCO;
import com.zcloud.zcGbsServicer.dto.clientobject.VideoPlatformOnlineRoomPageCO;
import com.zcloud.zcGbsServicer.dto.clientobject.VideoPlatformResultCO;
import com.zcloud.zcGbsServicer.dto.clientobject.VideoPlatformTokenCO;
import com.zcloud.zcGbsServicer.dto.clientobject.VideoRoomInstantCO;
import com.zcloud.zcGbsServicer.persistence.dataobject.FireAlarmMeetingRoomDO;
import com.zcloud.zcGbsServicer.persistence.dataobject.FireAlarmMeetingUserDO;
import com.zcloud.zcGbsServicer.persistence.dataobject.FireBrigadeDO;
import com.zcloud.zcGbsServicer.persistence.dataobject.FireBrigadeUserDO;
import com.zcloud.zcGbsServicer.persistence.repository.FireAlarmMeetingRoomRepository;
import com.zcloud.zcGbsServicer.persistence.repository.FireAlarmMeetingUserRepository;
import com.zcloud.zcGbsServicer.persistence.repository.FireBrigadeRepository;
import com.zcloud.zcGbsServicer.persistence.repository.FireBrigadeUserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
@SuppressWarnings("unchecked")
public class VideoPlatformServiceImpl extends FireAlarmServiceSupport implements VideoPlatformServiceI {
private static final int AUTH_STATUS_SUCCESS = 1;
private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
private final HstVideoPlatformProperties properties;
private final HstVideoPlatformClient hstVideoPlatformClient;
private final FireAlarmMeetingRoomRepository fireAlarmMeetingRoomRepository;
private final FireAlarmMeetingUserRepository fireAlarmMeetingUserRepository;
private final FireBrigadeRepository fireBrigadeRepository;
private final FireBrigadeUserRepository fireBrigadeUserRepository;
@Override
public SingleResponse<VideoPlatformConfigCO> getConfig() {
VideoPlatformConfigCO co = new VideoPlatformConfigCO();
co.setApiBaseUrl(properties.getApiBaseUrl());
co.setWebBaseUrl(properties.getWebBaseUrl());
co.setClientPort(properties.getClientPort());
co.setDefaultRoomCode(properties.getDefaultRoomCode());
co.setDefaultRoomNo(properties.getDefaultRoomNo());
co.setDefaultUserPassword(properties.getDefaultUserPassword());
co.setTestAccounts(properties.getTestAccounts());
return SingleResponse.of(co);
}
@Override
public SingleResponse<VideoPlatformTokenCO> generateToken() {
VideoPlatformTokenCO co = new VideoPlatformTokenCO();
co.setToken(hstVideoPlatformClient.generateToken());
co.setExpireTime(hstVideoPlatformClient.formatExpireTime());
co.setApiBaseUrl(properties.getApiBaseUrl());
co.setWebBaseUrl(properties.getWebBaseUrl());
return SingleResponse.of(co);
}
@Override
public SingleResponse<VideoRoomInstantCO> createInstant(VideoRoomCreateInstantCmd cmd) {
String meetingName = StrUtil.blankToDefault(cmd.getMeetingName(), "消防报警即时会议");
String userName = StrUtil.blankToDefault(cmd.getUserName(), currentUserName());
if (StrUtil.isBlank(userName)) {
userName = "消防报警";
}
Map<String, Object> requestBody = new LinkedHashMap<>();
requestBody.put("meetingName", meetingName);
requestBody.put("userName", userName);
putIfNotNull(requestBody, "meetingTemplate", cmd.getMeetingTemplate());
putIfNotNull(requestBody, "meetingType", cmd.getMeetingType());
putIfNotNull(requestBody, "verifyMode", cmd.getVerifyMode());
putIfNotNull(requestBody, "departId", cmd.getDepartId());
putIfNotNull(requestBody, "maxUserCount", cmd.getMaxUserCount());
putIfNotBlank(requestBody, "password", cmd.getPassword());
putIfNotBlank(requestBody, "chairPassword", cmd.getChairPassword());
putIfNotBlank(requestBody, "enableInvite", cmd.getEnableInvite());
putIfNotBlank(requestBody, "enableChairPwd", cmd.getEnableChairPwd());
putIfNotBlank(requestBody, "autoRecord", cmd.getAutoRecord());
putIfNotBlank(requestBody, "roomMode", cmd.getRoomMode());
putIfNotBlank(requestBody, "source", cmd.getSource());
putIfNotBlank(requestBody, "menteeAdvance", cmd.getMenteeAdvance());
Map<String, Object> response = hstVideoPlatformClient.createInstant(requestBody);
hstVideoPlatformClient.ensureSuccess(response, "创建即时会议室");
Map<String, Object> data = castMap(response.get("data"));
VideoRoomInstantCO co = new VideoRoomInstantCO();
co.setMeetingName(selectText(asText(data.get("meetingName")), meetingName));
co.setRoomId(asText(data.get("roomId")));
co.setPassword(selectText(asText(data.get("password")), cmd.getPassword()));
co.setUserName(userName);
co.setCesAddr(properties.getWebBaseUrl());
co.setWebUrl(properties.getWebBaseUrl());
co.setToken(hstVideoPlatformClient.generateToken());
co.setUserPass(properties.getDefaultUserPassword());
co.setGrantType("password");
co.setExpireTime(hstVideoPlatformClient.formatExpireTime());
co.setResultMsg(selectText(asText(response.get("msg")), "即时会议室创建成功"));
co.setInviteCode(asText(data.get("inviteCode")));
co.setMaxUserCount(asInteger(data.get("maxUserCount")));
co.setVerifyMode(asInteger(data.get("verifyMode")));
co.setMeetingType(asInteger(data.get("meetingType")));
co.setMeetingTemplate(asInteger(data.get("meetingTemplate")));
co.setCreateTime(asText(data.get("createTime")));
co.setCreatorId(asText(data.get("creatorId")));
co.setLoginAddrList(safeGetLoginAddr());
return SingleResponse.of(co);
}
@Override
public SingleResponse<VideoPlatformResultCO> authUser(VideoRoomAuthUserCmd cmd) {
Map<String, Object> requestBody = new LinkedHashMap<>();
requestBody.put("roomId", toNumericOrText(String.valueOf(cmd.getRoomId())));
requestBody.put("roomUserStr", cmd.getRoomUserStr().trim());
requestBody.put("authType", cmd.getAuthType() == null ? 1 : cmd.getAuthType());
Map<String, Object> response = hstVideoPlatformClient.authUser(requestBody);
hstVideoPlatformClient.ensureSuccess(response, "会议室授权用户");
return SingleResponse.of(buildResultCO(response));
}
@Override
public SingleResponse<VideoPlatformResultCO> authRoom(VideoRoomAuthRoomCmd cmd) {
Map<String, Object> requestBody = new LinkedHashMap<>();
requestBody.put("roomUserStr", cmd.getRoomUserStr().trim());
requestBody.put("userName", cmd.getUserName().trim());
Map<String, Object> response = hstVideoPlatformClient.authRoom(requestBody);
hstVideoPlatformClient.ensureSuccess(response, "用户授权会议室");
return SingleResponse.of(buildResultCO(response));
}
@Override
public List<String> getLoginAddr() {
Map<String, Object> response = hstVideoPlatformClient.loginAddr();
hstVideoPlatformClient.ensureSuccess(response, "获取登录地址");
Object data = response.get("data");
if (!(data instanceof List)) {
return Collections.emptyList();
}
List<String> result = new ArrayList<>();
for (Object item : (List<?>) data) {
if (item != null) {
result.add(String.valueOf(item));
}
}
return result;
}
@Override
public SingleResponse<VideoPlatformOnlineRoomPageCO> onlineRoom(VideoRoomOnlineRoomQry qry) {
Map<String, Object> requestBody = new LinkedHashMap<>();
putIfNotNull(requestBody, "departId", qry.getDepartId());
requestBody.put("pageNumber", qry.getPageNumber() == null || qry.getPageNumber() <= 0 ? 1 : qry.getPageNumber());
requestBody.put("pageSize", qry.getPageSize() == null || qry.getPageSize() <= 0 ? 10 : qry.getPageSize());
Map<String, Object> response = hstVideoPlatformClient.onlineRoom(requestBody);
hstVideoPlatformClient.ensureSuccess(response, "查询在线会议");
Map<String, Object> data = castMap(response.get("data"));
VideoPlatformOnlineRoomPageCO co = new VideoPlatformOnlineRoomPageCO();
co.setCurrent(asInteger(data.get("current")));
co.setPages(asInteger(data.get("pages")));
co.setSize(asInteger(data.get("size")));
co.setTotal(asInteger(data.get("total")));
co.setRecords(buildOnlineRoomRecords(data.get("records")));
return SingleResponse.of(co);
}
@Override
public SingleResponse<VideoPlatformResultCO> departmentList(VideoPlatformDepartmentQry qry) {
Map<String, Object> requestBody = new LinkedHashMap<>();
if (StrUtil.isNotBlank(qry.getDepartId())) {
requestBody.put("departId", toNumericOrText(qry.getDepartId()));
}
putIfNotBlank(requestBody, "departName", qry.getDepartName());
putIfNotBlank(requestBody, "code", qry.getCode());
requestBody.put("pageNumber", qry.getPageNumber() == null || qry.getPageNumber() <= 0 ? 1 : qry.getPageNumber());
requestBody.put("pageSize", qry.getPageSize() == null || qry.getPageSize() <= 0 ? 100 : qry.getPageSize());
Map<String, Object> response = hstVideoPlatformClient.departmentList(requestBody);
hstVideoPlatformClient.ensureSuccess(response, "查询视频平台组织架构");
return SingleResponse.of(buildResultCO(response));
}
@Override
public SingleResponse<VideoPlatformResultCO> userList(VideoPlatformUserQry qry) {
Map<String, Object> requestBody = new LinkedHashMap<>();
putIfNotBlank(requestBody, "searchKey", qry.getSearchKey());
putIfNotBlank(requestBody, "searchType", qry.getSearchType());
if (StrUtil.isNotBlank(qry.getDepartId())) {
requestBody.put("departId", toNumericOrText(qry.getDepartId()));
}
requestBody.put("pageNumber", qry.getPageNumber() == null || qry.getPageNumber() <= 0 ? 1 : qry.getPageNumber());
requestBody.put("pageSize", qry.getPageSize() == null || qry.getPageSize() <= 0 ? 100 : qry.getPageSize());
Map<String, Object> response = hstVideoPlatformClient.userList(requestBody);
hstVideoPlatformClient.ensureSuccess(response, "查询视频平台用户");
return SingleResponse.of(buildResultCO(response));
}
@Override
public SingleResponse<VideoPlatformCurrentMeetingCO> currentFixedMeeting(VideoPlatformFixedRoomQry qry) {
FixedRoomContext context = resolveFixedRoom(qry.getRoomCode());
VideoPlatformOnlineRoomCO onlineRoom = findOnlineFixedRoom(context);
FireAlarmMeetingUserDO currentMeetingUser = resolveCurrentMeetingUser(qry.getLocalUserId(), false);
VideoPlatformCurrentMeetingCO co = new VideoPlatformCurrentMeetingCO();
co.setRoomCode(context.roomCode);
co.setRoomId(context.roomId);
co.setRoomNo(context.roomNo);
co.setRoomName(onlineRoom == null ? context.roomName : selectText(onlineRoom.getRoomName(), context.roomName));
co.setOnline(onlineRoom != null);
co.setCurUserCount(onlineRoom == null ? 0 : onlineRoom.getCurUserCount());
co.setStatus(onlineRoom == null ? null : onlineRoom.getStatus());
co.setStartTime(onlineRoom == null ? null : onlineRoom.getStartTime());
co.setEndTime(onlineRoom == null ? null : onlineRoom.getEndTime());
co.setThirdUserName(currentMeetingUser == null ? null : currentMeetingUser.getThirdUserName());
co.setUserPass(properties.getDefaultUserPassword());
co.setGrantType("password");
co.setCesAddr(properties.getWebBaseUrl());
co.setWebUrl(properties.getWebBaseUrl());
co.setResultMsg(onlineRoom == null ? "固定会议当前未在线" : "固定会议正在进行");
return SingleResponse.of(co);
}
@Override
public SingleResponse<VideoPlatformMeetingAccessCheckCO> checkFixedMeetingAccess(VideoPlatformMeetingAccessCheckQry qry) {
FixedRoomContext context = resolveFixedRoom(qry.getRoomCode());
Long localUserId = qry.getLocalUserId() == null ? currentUserId() : qry.getLocalUserId();
if (localUserId == null) {
throw new BizException("当前登录用户不存在");
}
FireAlarmMeetingUserDO meetingUser = resolveCurrentMeetingUser(localUserId, true);
FireBrigadeUserDO relation = resolveUserBrigadeRelation(localUserId, qry.getFireBrigadeBizId());
FireBrigadeDO brigade = relation == null ? null : fireBrigadeRepository.getByFireBrigadeId(relation.getFireBrigadeId());
VideoPlatformMeetingAccessCheckCO co = new VideoPlatformMeetingAccessCheckCO();
co.setAllowed(false);
co.setRoomCode(context.roomCode);
co.setRoomId(context.roomId);
co.setRoomName(context.roomName);
co.setLocalUserId(localUserId);
co.setLocalUserName(meetingUser == null ? null : meetingUser.getLocalUserName());
co.setThirdUserName(meetingUser == null ? null : meetingUser.getThirdUserName());
co.setUserPass(properties.getDefaultUserPassword());
if (meetingUser == null || StrUtil.isBlank(meetingUser.getThirdUserName())) {
co.setReason("当前用户未配置视频会议账号");
co.setParticipants(buildParticipants(context, localUserId));
return SingleResponse.of(co);
}
if (relation == null) {
co.setReason("当前用户未加入消防队伍");
co.setParticipants(buildParticipants(context, localUserId));
return SingleResponse.of(co);
}
String fireBrigadeId = relation.getFireBrigadeId();
co.setFireBrigadeId(fireBrigadeId);
co.setFireBrigadeName(brigade == null ? meetingUser.getFireBrigadeName() : brigade.getBrigadeName());
List<VideoPlatformMeetingParticipantCO> participants = buildParticipants(context, localUserId);
co.setParticipants(participants);
for (VideoPlatformMeetingParticipantCO participant : participants) {
if (!Objects.equals(fireBrigadeId, participant.getFireBrigadeId())) {
continue;
}
if (Objects.equals(localUserId, participant.getLocalUserId())) {
co.setAllowed(true);
co.setOccupied(false);
co.setReason("当前用户已在会议中");
return SingleResponse.of(co);
}
co.setAllowed(false);
co.setOccupied(true);
co.setOccupiedUserId(participant.getLocalUserId());
co.setOccupiedUserName(participant.getLocalUserName());
co.setOccupiedThirdUserName(participant.getThirdUserName());
co.setReason("当前消防队伍已有成员在会议中");
return SingleResponse.of(co);
}
co.setAllowed(true);
co.setOccupied(false);
co.setReason("允许入会");
return SingleResponse.of(co);
}
@Override
public SingleResponse<VideoPlatformMeetingMemberStatusCO> fixedMeetingMembers(VideoPlatformMeetingMemberQry qry) {
FixedRoomContext context = resolveFixedRoom(qry.getRoomCode());
List<VideoPlatformMeetingParticipantCO> participants = buildParticipants(context, currentUserId());
VideoPlatformMeetingMemberStatusCO co = new VideoPlatformMeetingMemberStatusCO();
co.setRoomCode(context.roomCode);
co.setRoomId(context.roomId);
co.setRoomName(context.roomName);
co.setParticipantCount(participants.size());
co.setParticipants(participants);
if (Boolean.FALSE.equals(qry.getIncludeLogs())) {
co.setLogQuerySuccess(true);
co.setLogQueryMsg("未查询进退会日志");
co.setLogs(Collections.emptyList());
}
else {
try {
co.setLogs(buildRoomLogs(context, qry));
co.setLogQuerySuccess(true);
co.setLogQueryMsg("查询成功");
}
catch (BizException ex) {
co.setLogs(Collections.emptyList());
co.setLogQuerySuccess(false);
co.setLogQueryMsg(ex.getMessage());
}
}
return SingleResponse.of(co);
}
@Override
public SingleResponse<VideoPlatformLoginCO> fixedRoomLogin(VideoPlatformFixedRoomLoginCmd cmd) {
VideoPlatformMeetingAccessCheckQry checkQry = new VideoPlatformMeetingAccessCheckQry();
checkQry.setRoomCode(cmd.getRoomCode());
checkQry.setLocalUserId(cmd.getLocalUserId());
VideoPlatformMeetingAccessCheckCO access = checkFixedMeetingAccess(checkQry).getData();
if (access == null || !Boolean.TRUE.equals(access.getAllowed())) {
throw new BizException(access == null ? "当前用户不允许入会" : access.getReason());
}
FixedRoomContext context = resolveFixedRoom(cmd.getRoomCode());
String thirdUserName = StrUtil.blankToDefault(cmd.getThirdUserName(), access.getThirdUserName());
if (StrUtil.isBlank(thirdUserName)) {
throw new BizException("当前用户未配置第三方会议账号");
}
VideoPlatformLoginCO co = new VideoPlatformLoginCO();
co.setRoomCode(context.roomCode);
co.setRoomId(context.roomId);
co.setRoomNo(context.roomNo);
co.setMeetingName(context.roomName);
co.setPassword(context.roomPassword);
co.setThirdUserName(thirdUserName.trim());
co.setToken(null);
co.setUserPass(properties.getDefaultUserPassword());
co.setGrantType("password");
co.setCesAddr(properties.getWebBaseUrl());
co.setWebUrl(properties.getWebBaseUrl());
co.setLoginAddrList(Collections.emptyList());
co.setLoginUrl(properties.getWebBaseUrl());
co.setAuthStatus(AUTH_STATUS_SUCCESS);
co.setAuthorizedUserCount(null);
co.setResultMsg("固定会议室入会参数获取成功");
return SingleResponse.of(co);
}
@Override
public SingleResponse<VideoPlatformResultCO> fixedRoomLeave(VideoPlatformFixedRoomLeaveCmd cmd) {
VideoPlatformResultCO co = new VideoPlatformResultCO();
co.setCode("200");
co.setMsg("离会成功");
Map<String, Object> data = new LinkedHashMap<>();
data.put("localUserId", cmd.getLocalUserId() == null ? currentUserId() : cmd.getLocalUserId());
data.put("alarmId", cmd.getAlarmId());
data.put("traceMode", "frontend-sdk");
co.setData(data);
return SingleResponse.of(co);
}
private FixedRoomContext resolveFixedRoom(String roomCode) {
String actualRoomCode = StrUtil.blankToDefault(roomCode, properties.getDefaultRoomCode());
FireAlarmMeetingRoomDO room = fireAlarmMeetingRoomRepository.getByRoomCode(actualRoomCode);
FixedRoomContext context = new FixedRoomContext();
context.room = room;
context.roomCode = actualRoomCode;
context.roomId = resolveRoomId(room);
context.roomNo = resolveRoomNo(room);
context.roomName = resolveRoomName(room);
context.roomPassword = room == null ? null : room.getRoomPasswordCipher();
return context;
}
private FireAlarmMeetingUserDO resolveCurrentMeetingUser(Long localUserId, boolean required) {
Long actualLocalUserId = localUserId == null ? currentUserId() : localUserId;
FireAlarmMeetingUserDO meetingUser = actualLocalUserId == null ? null : fireAlarmMeetingUserRepository.getByLocalUserId(actualLocalUserId);
if (required && meetingUser == null) {
throw new BizException("当前用户未配置会议账号映射");
}
return meetingUser;
}
private FireBrigadeUserDO resolveUserBrigadeRelation(Long localUserId, String fireBrigadeBizId) {
List<FireBrigadeUserDO> relations = fireBrigadeUserRepository.listByUserId(localUserId);
if (relations == null || relations.isEmpty()) {
return null;
}
if (StrUtil.isBlank(fireBrigadeBizId)) {
return relations.get(0);
}
return relations.stream()
.filter(item -> fireBrigadeBizId.trim().equals(item.getFireBrigadeId()))
.findFirst()
.orElse(null);
}
private VideoPlatformOnlineRoomCO findOnlineFixedRoom(FixedRoomContext context) {
Map<String, Object> requestBody = new LinkedHashMap<>();
requestBody.put("pageNumber", 1);
requestBody.put("pageSize", 100);
Map<String, Object> response = hstVideoPlatformClient.onlineRoom(requestBody);
hstVideoPlatformClient.ensureSuccess(response, "查询企业当前会议");
List<VideoPlatformOnlineRoomCO> rooms = buildOnlineRoomRecords(castMap(response.get("data")).get("records"));
for (VideoPlatformOnlineRoomCO room : rooms) {
if (sameRoom(context, room.getRoomId())) {
return room;
}
}
return null;
}
private List<VideoPlatformMeetingParticipantCO> buildParticipants(FixedRoomContext context, Long currentLocalUserId) {
Map<String, Object> requestBody = new LinkedHashMap<>();
requestBody.put("roomId", toNumericOrText(context.roomId));
requestBody.put("pageNumber", 1);
requestBody.put("pageSize", 200);
Map<String, Object> response;
try {
response = hstVideoPlatformClient.participant(requestBody);
hstVideoPlatformClient.ensureSuccess(response, "获取会议当前用户列表");
}
catch (BizException ex) {
if (isRoomNotOnline(ex.getMessage())) {
return Collections.emptyList();
}
throw ex;
}
Map<String, FireAlarmMeetingUserDO> meetingUserMap = buildMeetingUserMap();
List<String> thirdUserNames = extractUserNames(response.get("data"));
List<VideoPlatformMeetingParticipantCO> result = new ArrayList<>();
for (String thirdUserName : thirdUserNames) {
FireAlarmMeetingUserDO meetingUser = meetingUserMap.get(normalize(thirdUserName));
VideoPlatformMeetingParticipantCO co = new VideoPlatformMeetingParticipantCO();
co.setThirdUserName(thirdUserName);
co.setLocalUserId(meetingUser == null ? null : meetingUser.getLocalUserId());
co.setLocalUserName(meetingUser == null ? null : meetingUser.getLocalUserName());
co.setLocalPhone(meetingUser == null ? null : meetingUser.getLocalPhone());
co.setFireBrigadeId(meetingUser == null ? null : meetingUser.getFireBrigadeId());
co.setFireBrigadeName(meetingUser == null ? null : meetingUser.getFireBrigadeName());
co.setCurrentUser(currentLocalUserId != null && Objects.equals(currentLocalUserId, co.getLocalUserId()));
result.add(co);
}
return result;
}
private List<VideoPlatformMeetingLogCO> buildRoomLogs(FixedRoomContext context, VideoPlatformMeetingMemberQry qry) {
Map<String, Object> requestBody = new LinkedHashMap<>();
requestBody.put("departId", resolveRoomLogDepartId(qry));
requestBody.put("startTime", selectText(qry.getStartTime(), TIME_FORMATTER.format(LocalDate.now().atStartOfDay())));
requestBody.put("endTime", selectText(qry.getEndTime(), TIME_FORMATTER.format(LocalDateTime.now())));
Map<String, Object> response = hstVideoPlatformClient.roomLog(requestBody);
hstVideoPlatformClient.ensureSuccess(response, "查询会议室参会人信息");
Map<String, FireAlarmMeetingUserDO> meetingUserMap = buildMeetingUserMap();
List<Map<String, Object>> rows = extractRows(response.get("data"));
List<VideoPlatformMeetingLogCO> result = new ArrayList<>();
for (Map<String, Object> row : rows) {
if (!sameRoom(context, asText(row.get("roomId")))) {
continue;
}
String thirdUserName = selectText(asText(row.get("userName")), asText(row.get("thirdUserName")));
FireAlarmMeetingUserDO meetingUser = meetingUserMap.get(normalize(thirdUserName));
VideoPlatformMeetingLogCO co = new VideoPlatformMeetingLogCO();
co.setRoomId(asText(row.get("roomId")));
co.setRoomName(asText(row.get("roomName")));
co.setThirdUserName(thirdUserName);
co.setLocalUserId(meetingUser == null ? null : meetingUser.getLocalUserId());
co.setLocalUserName(meetingUser == null ? null : meetingUser.getLocalUserName());
co.setFireBrigadeId(meetingUser == null ? null : meetingUser.getFireBrigadeId());
co.setFireBrigadeName(meetingUser == null ? null : meetingUser.getFireBrigadeName());
co.setEnterTime(asText(row.get("enterTime")));
co.setLeaveTime(asText(row.get("leaveTime")));
co.setDuration(asText(row.get("duration")));
co.setStatus(StrUtil.isBlank(co.getLeaveTime()) ? "IN_ROOM" : "LEFT");
result.add(co);
}
return result;
}
private Object resolveRoomLogDepartId(VideoPlatformMeetingMemberQry qry) {
if (StrUtil.isNotBlank(qry.getDepartId())) {
return toNumericOrText(qry.getDepartId());
}
FireAlarmMeetingUserDO meetingUser = resolveCurrentMeetingUser(currentUserId(), false);
if (meetingUser != null && StrUtil.isNotBlank(meetingUser.getThirdUserName())) {
String departId = queryUserDepartId(meetingUser.getThirdUserName());
if (StrUtil.isNotBlank(departId)) {
return toNumericOrText(departId);
}
}
return toNumericOrText(StrUtil.blankToDefault(properties.getDefaultDepartId(), "1"));
}
private String queryUserDepartId(String thirdUserName) {
Map<String, Object> requestBody = new LinkedHashMap<>();
requestBody.put("searchKey", thirdUserName.trim());
requestBody.put("searchType", "1");
requestBody.put("pageNumber", 1);
requestBody.put("pageSize", 20);
Map<String, Object> response = hstVideoPlatformClient.userList(requestBody);
hstVideoPlatformClient.ensureSuccess(response, "查询视频平台用户");
Object data = response.get("data");
if (!(data instanceof Map)) {
return null;
}
Object records = castMap(data).get("records");
if (!(records instanceof List)) {
return null;
}
for (Object item : (List<?>) records) {
if (!(item instanceof Map)) {
continue;
}
Map<String, Object> row = castMap(item);
if (thirdUserName.trim().equalsIgnoreCase(asText(row.get("userName")))) {
return asText(row.get("departId"));
}
}
return null;
}
private Map<String, FireAlarmMeetingUserDO> buildMeetingUserMap() {
List<FireAlarmMeetingUserDO> users = fireAlarmMeetingUserRepository.listAll();
if (users == null || users.isEmpty()) {
return Collections.emptyMap();
}
return users.stream()
.filter(item -> StrUtil.isNotBlank(item.getThirdUserName()))
.collect(Collectors.toMap(item -> normalize(item.getThirdUserName()), item -> item, (first, second) -> first));
}
private List<String> extractUserNames(Object data) {
Object records = extractRecords(data);
if (!(records instanceof List)) {
return Collections.emptyList();
}
List<String> result = new ArrayList<>();
for (Object item : (List<?>) records) {
String userName;
if (item instanceof Map) {
Map<String, Object> row = castMap(item);
userName = selectText(asText(row.get("userName")), selectText(asText(row.get("thirdUserName")), asText(row.get("name"))));
}
else {
userName = asText(item);
}
if (StrUtil.isNotBlank(userName)) {
result.add(userName.trim());
}
}
return result;
}
private List<Map<String, Object>> extractRows(Object data) {
Object records = extractRecords(data);
if (!(records instanceof List)) {
return Collections.emptyList();
}
List<Map<String, Object>> result = new ArrayList<>();
for (Object item : (List<?>) records) {
if (item instanceof Map) {
result.add(castMap(item));
}
}
return result;
}
private Object extractRecords(Object data) {
if (data instanceof List) {
return data;
}
if (!(data instanceof Map)) {
return null;
}
Map<String, Object> map = castMap(data);
Object records = map.get("records");
if (records == null) {
records = map.get("data");
}
if (records == null) {
records = map.get("list");
}
return records;
}
private List<String> safeGetLoginAddr() {
try {
return getLoginAddr();
}
catch (Exception ex) {
return Collections.emptyList();
}
}
private List<VideoPlatformOnlineRoomCO> buildOnlineRoomRecords(Object records) {
if (!(records instanceof List)) {
return Collections.emptyList();
}
List<VideoPlatformOnlineRoomCO> result = new ArrayList<>();
for (Object item : (List<?>) records) {
Map<String, Object> row = castMap(item);
VideoPlatformOnlineRoomCO co = new VideoPlatformOnlineRoomCO();
co.setRoomId(asText(row.get("roomId")));
co.setRoomName(asText(row.get("roomName")));
co.setPassword(asText(row.get("password")));
co.setCurUserCount(asInteger(row.get("curUserCount")));
co.setStartTime(asText(row.get("startTime")));
co.setEndTime(asText(row.get("endTime")));
co.setStatus(asText(row.get("status")));
co.setVerifyMode(asText(row.get("verifyMode")));
co.setMaxUserCount(asInteger(row.get("maxUserCount")));
result.add(co);
}
return result;
}
private VideoPlatformResultCO buildResultCO(Map<String, Object> response) {
VideoPlatformResultCO co = new VideoPlatformResultCO();
co.setCode(selectText(asText(response.get("code")), "200"));
co.setMsg(selectText(asText(response.get("msg")), "success"));
co.setData(response.get("data"));
return co;
}
private boolean sameRoom(FixedRoomContext context, String thirdRoomId) {
if (StrUtil.isBlank(thirdRoomId)) {
return false;
}
String value = thirdRoomId.trim();
return value.equals(context.roomId) || value.equals(context.roomNo);
}
private String resolveRoomId(FireAlarmMeetingRoomDO room) {
if (room == null) {
return properties.getDefaultRoomNo();
}
return selectText(room.getThirdRoomId(), selectText(room.getThirdRoomNo(), properties.getDefaultRoomNo()));
}
private String resolveRoomNo(FireAlarmMeetingRoomDO room) {
if (room == null) {
return properties.getDefaultRoomNo();
}
return selectText(room.getThirdRoomNo(), selectText(room.getThirdRoomId(), properties.getDefaultRoomNo()));
}
private String resolveRoomName(FireAlarmMeetingRoomDO room) {
if (room == null || StrUtil.isBlank(room.getRoomName())) {
return "消防报警固定会议室";
}
return room.getRoomName();
}
private void putIfNotNull(Map<String, Object> target, String key, Object value) {
if (value != null) {
target.put(key, value);
}
}
private void putIfNotBlank(Map<String, Object> target, String key, String value) {
if (StrUtil.isNotBlank(value)) {
target.put(key, value.trim());
}
}
private Map<String, Object> castMap(Object value) {
if (!(value instanceof Map)) {
return new HashMap<>();
}
return (Map<String, Object>) value;
}
private String asText(Object value) {
return value == null ? null : String.valueOf(value);
}
private Integer asInteger(Object value) {
if (value == null) {
return null;
}
if (value instanceof Number) {
return ((Number) value).intValue();
}
try {
return Integer.parseInt(String.valueOf(value));
}
catch (Exception ex) {
return null;
}
}
private Object toNumericOrText(String value) {
if (StrUtil.isBlank(value)) {
return value;
}
if (StrUtil.isNumeric(value)) {
try {
return Long.parseLong(value);
}
catch (Exception ex) {
return value;
}
}
return value;
}
private String selectText(String preferred, String fallback) {
return StrUtil.isNotBlank(preferred) ? preferred : fallback;
}
private String normalize(String value) {
return StrUtil.blankToDefault(value, "").trim().toLowerCase(Locale.ROOT);
}
private boolean isRoomNotOnline(String message) {
String msg = StrUtil.blankToDefault(message, "").toLowerCase(Locale.ROOT);
return msg.contains("不存在") || msg.contains("未开始") || msg.contains("未在线")
|| msg.contains("not exist") || msg.contains("not found") || msg.contains("offline");
}
private static class FixedRoomContext {
private FireAlarmMeetingRoomDO room;
private String roomCode;
private String roomId;
private String roomNo;
private String roomName;
private String roomPassword;
}
}

View File

@ -0,0 +1,56 @@
package com.zcloud.zcGbsServicer.api;
import com.alibaba.cola.dto.SingleResponse;
import com.zcloud.zcGbsServicer.dto.VideoPlatformUserQry;
import com.zcloud.zcGbsServicer.dto.VideoPlatformFixedRoomLeaveCmd;
import com.zcloud.zcGbsServicer.dto.VideoPlatformFixedRoomLoginCmd;
import com.zcloud.zcGbsServicer.dto.VideoPlatformFixedRoomQry;
import com.zcloud.zcGbsServicer.dto.VideoPlatformDepartmentQry;
import com.zcloud.zcGbsServicer.dto.VideoPlatformMeetingAccessCheckQry;
import com.zcloud.zcGbsServicer.dto.VideoPlatformMeetingMemberQry;
import com.zcloud.zcGbsServicer.dto.VideoRoomAuthRoomCmd;
import com.zcloud.zcGbsServicer.dto.VideoRoomAuthUserCmd;
import com.zcloud.zcGbsServicer.dto.VideoRoomCreateInstantCmd;
import com.zcloud.zcGbsServicer.dto.VideoRoomOnlineRoomQry;
import com.zcloud.zcGbsServicer.dto.clientobject.VideoPlatformConfigCO;
import com.zcloud.zcGbsServicer.dto.clientobject.VideoPlatformCurrentMeetingCO;
import com.zcloud.zcGbsServicer.dto.clientobject.VideoPlatformLoginCO;
import com.zcloud.zcGbsServicer.dto.clientobject.VideoPlatformMeetingAccessCheckCO;
import com.zcloud.zcGbsServicer.dto.clientobject.VideoPlatformMeetingMemberStatusCO;
import com.zcloud.zcGbsServicer.dto.clientobject.VideoPlatformOnlineRoomPageCO;
import com.zcloud.zcGbsServicer.dto.clientobject.VideoPlatformResultCO;
import com.zcloud.zcGbsServicer.dto.clientobject.VideoPlatformTokenCO;
import com.zcloud.zcGbsServicer.dto.clientobject.VideoRoomInstantCO;
import java.util.List;
public interface VideoPlatformServiceI {
SingleResponse<VideoPlatformConfigCO> getConfig();
SingleResponse<VideoPlatformTokenCO> generateToken();
SingleResponse<VideoRoomInstantCO> createInstant(VideoRoomCreateInstantCmd cmd);
SingleResponse<VideoPlatformResultCO> authUser(VideoRoomAuthUserCmd cmd);
SingleResponse<VideoPlatformResultCO> authRoom(VideoRoomAuthRoomCmd cmd);
List<String> getLoginAddr();
SingleResponse<VideoPlatformOnlineRoomPageCO> onlineRoom(VideoRoomOnlineRoomQry qry);
SingleResponse<VideoPlatformResultCO> departmentList(VideoPlatformDepartmentQry qry);
SingleResponse<VideoPlatformResultCO> userList(VideoPlatformUserQry qry);
SingleResponse<VideoPlatformCurrentMeetingCO> currentFixedMeeting(VideoPlatformFixedRoomQry qry);
SingleResponse<VideoPlatformMeetingAccessCheckCO> checkFixedMeetingAccess(VideoPlatformMeetingAccessCheckQry qry);
SingleResponse<VideoPlatformMeetingMemberStatusCO> fixedMeetingMembers(VideoPlatformMeetingMemberQry qry);
SingleResponse<VideoPlatformLoginCO> fixedRoomLogin(VideoPlatformFixedRoomLoginCmd cmd);
SingleResponse<VideoPlatformResultCO> fixedRoomLeave(VideoPlatformFixedRoomLeaveCmd cmd);
}

View File

@ -12,4 +12,7 @@ public class AlarmRecordPageQry extends PageQuery {
@ApiModelProperty("报警状态")
private String status;
@ApiModelProperty("是否只查询当前登录人所在消防队的处置数据") // 预留暂未使用
private Boolean myFeedbackOnly;
}

View File

@ -0,0 +1,24 @@
package com.zcloud.zcGbsServicer.dto;
import com.alibaba.cola.dto.Query;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class VideoPlatformDepartmentQry extends Query {
@ApiModelProperty("第三方部门ID精确查询时传")
private String departId;
@ApiModelProperty("第三方部门名称,模糊查询时传")
private String departName;
@ApiModelProperty("部门编码")
private String code;
@ApiModelProperty("页码,默认 1")
private Integer pageNumber;
@ApiModelProperty("每页条数,默认 100")
private Integer pageSize;
}

View File

@ -0,0 +1,15 @@
package com.zcloud.zcGbsServicer.dto;
import com.alibaba.cola.dto.Command;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class VideoPlatformFixedRoomLeaveCmd extends Command {
@ApiModelProperty("消防报警记录主键ID传空时默认按当前用户最近在线记录离会")
private Long alarmId;
@ApiModelProperty("本地用户ID默认取当前登录用户")
private Long localUserId;
}

View File

@ -0,0 +1,27 @@
package com.zcloud.zcGbsServicer.dto;
import com.alibaba.cola.dto.Command;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class VideoPlatformFixedRoomLoginCmd extends Command {
@ApiModelProperty("固定会议室编码,默认 DEFAULT_DUTY_ROOM")
private String roomCode;
@ApiModelProperty("消防报警记录主键ID用于回写当前入会状态")
private Long alarmId;
@ApiModelProperty("本地用户ID默认取当前登录用户")
private Long localUserId;
@ApiModelProperty("第三方平台用户名,优先级高于会议用户映射")
private String thirdUserName;
@ApiModelProperty("授权权限值2 参会人3 管理员,默认 2")
private Integer userRight;
@ApiModelProperty("授权类型0 全量授权1 增量授权,默认 0")
private Integer authType;
}

View File

@ -0,0 +1,15 @@
package com.zcloud.zcGbsServicer.dto;
import com.alibaba.cola.dto.Query;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class VideoPlatformFixedRoomQry extends Query {
@ApiModelProperty("固定会议室编码,默认 DEFAULT_DUTY_ROOM")
private String roomCode;
@ApiModelProperty("本地用户ID默认取当前登录用户")
private Long localUserId;
}

View File

@ -0,0 +1,18 @@
package com.zcloud.zcGbsServicer.dto;
import com.alibaba.cola.dto.Query;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class VideoPlatformMeetingAccessCheckQry extends Query {
@ApiModelProperty("固定会议室编码,默认 DEFAULT_DUTY_ROOM")
private String roomCode;
@ApiModelProperty("本地用户ID默认取当前登录用户")
private Long localUserId;
@ApiModelProperty("消防队伍业务ID不传时按当前用户所在队伍判断")
private String fireBrigadeBizId;
}

View File

@ -0,0 +1,24 @@
package com.zcloud.zcGbsServicer.dto;
import com.alibaba.cola.dto.Query;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class VideoPlatformMeetingMemberQry extends Query {
@ApiModelProperty("固定会议室编码,默认 DEFAULT_DUTY_ROOM")
private String roomCode;
@ApiModelProperty("第三方部门ID不传默认取 video.platform.hst.default-depart-id")
private String departId;
@ApiModelProperty("开始时间,格式 yyyy-MM-dd HH:mm:ss不传默认查询当天")
private String startTime;
@ApiModelProperty("结束时间,格式 yyyy-MM-dd HH:mm:ss不传默认当前时间")
private String endTime;
@ApiModelProperty("是否返回进退会日志,默认 true")
private Boolean includeLogs;
}

View File

@ -0,0 +1,24 @@
package com.zcloud.zcGbsServicer.dto;
import com.alibaba.cola.dto.Query;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class VideoPlatformUserQry extends Query {
@ApiModelProperty("用户名搜索")
private String searchKey;
@ApiModelProperty("搜索类型0 模糊1 精确匹配")
private String searchType;
@ApiModelProperty("第三方部门ID")
private String departId;
@ApiModelProperty("页码,默认 1")
private Integer pageNumber;
@ApiModelProperty("每页条数,默认 100")
private Integer pageSize;
}

View File

@ -0,0 +1,19 @@
package com.zcloud.zcGbsServicer.dto;
import com.alibaba.cola.dto.Command;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@Data
public class VideoRoomAuthRoomCmd extends Command {
@NotBlank(message = "授权会议室串不能为空")
@ApiModelProperty("授权会议室串,格式如 20708,2#20709,3")
private String roomUserStr;
@NotBlank(message = "用户名不能为空")
@ApiModelProperty("三方平台用户名")
private String userName;
}

View File

@ -0,0 +1,23 @@
package com.zcloud.zcGbsServicer.dto;
import com.alibaba.cola.dto.Command;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@Data
public class VideoRoomAuthUserCmd extends Command {
@NotNull(message = "会议室ID不能为空")
@ApiModelProperty("会议室ID")
private Long roomId;
@NotBlank(message = "授权用户串不能为空")
@ApiModelProperty("授权用户串,格式如 mike,2#king,3")
private String roomUserStr;
@ApiModelProperty("授权类型0全量授权1增量授权默认1")
private Integer authType;
}

View File

@ -0,0 +1,69 @@
package com.zcloud.zcGbsServicer.dto;
import com.alibaba.cola.dto.Command;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class VideoRoomCreateInstantCmd extends Command {
@ApiModelProperty("会议名称")
private String meetingName;
@ApiModelProperty("会议室号,仅用于前端展示")
private String roomId;
@ApiModelProperty("会议室密码")
private String password;
@ApiModelProperty("入会用户名")
private String userName;
@ApiModelProperty("平台地址,返回参数使用")
private String cesAddr;
@ApiModelProperty("账号Token返回参数使用")
private String token;
@ApiModelProperty("账号密码,返回参数使用")
private String userPass;
@ApiModelProperty("鉴权方式,返回参数使用")
private String grantType;
@ApiModelProperty("会议模板3表示讨论")
private Integer meetingTemplate;
@ApiModelProperty("会议类型0带会议室会议1即时会议2即时会议并立即开会")
private Integer meetingType;
@ApiModelProperty("校验模式1用户密码验证2会议室密码验证3匿名登录")
private Integer verifyMode;
@ApiModelProperty("组织机构ID")
private Integer departId;
@ApiModelProperty("最大参会人数")
private Integer maxUserCount;
@ApiModelProperty("主席密码")
private String chairPassword;
@ApiModelProperty("是否开启邀请")
private String enableInvite;
@ApiModelProperty("是否开启主席密码")
private String enableChairPwd;
@ApiModelProperty("是否自动录制")
private String autoRecord;
@ApiModelProperty("会议模式")
private String roomMode;
@ApiModelProperty("来源标识")
private String source;
@ApiModelProperty("旁听提前入会配置")
private String menteeAdvance;
}

View File

@ -0,0 +1,18 @@
package com.zcloud.zcGbsServicer.dto;
import com.alibaba.cola.dto.Query;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class VideoRoomOnlineRoomQry extends Query {
@ApiModelProperty("组织机构ID")
private Integer departId;
@ApiModelProperty("第三方页码")
private Integer pageNumber = 1;
@ApiModelProperty("第三方每页条数")
private Integer pageSize = 10;
}

View File

@ -0,0 +1,18 @@
package com.zcloud.zcGbsServicer.dto.clientobject;
import com.alibaba.cola.dto.ClientObject;
import lombok.Data;
import java.util.List;
@Data
public class VideoPlatformConfigCO extends ClientObject {
private String apiBaseUrl;
private String webBaseUrl;
private String clientPort;
private String defaultRoomCode;
private String defaultRoomNo;
private String defaultUserPassword;
private List<String> testAccounts;
}

View File

@ -0,0 +1,24 @@
package com.zcloud.zcGbsServicer.dto.clientobject;
import com.alibaba.cola.dto.ClientObject;
import lombok.Data;
@Data
public class VideoPlatformCurrentMeetingCO extends ClientObject {
private String roomCode;
private String roomId;
private String roomNo;
private String roomName;
private Boolean online;
private Integer curUserCount;
private String status;
private String startTime;
private String endTime;
private String thirdUserName;
private String userPass;
private String grantType;
private String cesAddr;
private String webUrl;
private String resultMsg;
}

View File

@ -0,0 +1,27 @@
package com.zcloud.zcGbsServicer.dto.clientobject;
import com.alibaba.cola.dto.ClientObject;
import lombok.Data;
import java.util.List;
@Data
public class VideoPlatformLoginCO extends ClientObject {
private String roomCode;
private String roomId;
private String roomNo;
private String meetingName;
private String password;
private String thirdUserName;
private String token;
private String userPass;
private String grantType;
private String cesAddr;
private String webUrl;
private String loginUrl;
private List<String> loginAddrList;
private Integer authStatus;
private Integer authorizedUserCount;
private String resultMsg;
}

View File

@ -0,0 +1,27 @@
package com.zcloud.zcGbsServicer.dto.clientobject;
import com.alibaba.cola.dto.ClientObject;
import lombok.Data;
import java.util.List;
@Data
public class VideoPlatformMeetingAccessCheckCO extends ClientObject {
private Boolean allowed;
private String reason;
private String roomCode;
private String roomId;
private String roomName;
private Long localUserId;
private String localUserName;
private String thirdUserName;
private String userPass;
private String fireBrigadeId;
private String fireBrigadeName;
private Boolean occupied;
private Long occupiedUserId;
private String occupiedUserName;
private String occupiedThirdUserName;
private List<VideoPlatformMeetingParticipantCO> participants;
}

View File

@ -0,0 +1,20 @@
package com.zcloud.zcGbsServicer.dto.clientobject;
import com.alibaba.cola.dto.ClientObject;
import lombok.Data;
@Data
public class VideoPlatformMeetingLogCO extends ClientObject {
private String roomId;
private String roomName;
private String thirdUserName;
private Long localUserId;
private String localUserName;
private String fireBrigadeId;
private String fireBrigadeName;
private String enterTime;
private String leaveTime;
private String duration;
private String status;
}

View File

@ -0,0 +1,19 @@
package com.zcloud.zcGbsServicer.dto.clientobject;
import com.alibaba.cola.dto.ClientObject;
import lombok.Data;
import java.util.List;
@Data
public class VideoPlatformMeetingMemberStatusCO extends ClientObject {
private String roomCode;
private String roomId;
private String roomName;
private Integer participantCount;
private List<VideoPlatformMeetingParticipantCO> participants;
private Boolean logQuerySuccess;
private String logQueryMsg;
private List<VideoPlatformMeetingLogCO> logs;
}

View File

@ -0,0 +1,16 @@
package com.zcloud.zcGbsServicer.dto.clientobject;
import com.alibaba.cola.dto.ClientObject;
import lombok.Data;
@Data
public class VideoPlatformMeetingParticipantCO extends ClientObject {
private String thirdUserName;
private Long localUserId;
private String localUserName;
private String localPhone;
private String fireBrigadeId;
private String fireBrigadeName;
private Boolean currentUser;
}

View File

@ -0,0 +1,18 @@
package com.zcloud.zcGbsServicer.dto.clientobject;
import com.alibaba.cola.dto.ClientObject;
import lombok.Data;
@Data
public class VideoPlatformOnlineRoomCO extends ClientObject {
private String roomId;
private String roomName;
private String password;
private Integer curUserCount;
private String startTime;
private String endTime;
private String status;
private String verifyMode;
private Integer maxUserCount;
}

View File

@ -0,0 +1,16 @@
package com.zcloud.zcGbsServicer.dto.clientobject;
import com.alibaba.cola.dto.ClientObject;
import lombok.Data;
import java.util.List;
@Data
public class VideoPlatformOnlineRoomPageCO extends ClientObject {
private Integer current;
private Integer pages;
private Integer size;
private Integer total;
private List<VideoPlatformOnlineRoomCO> records;
}

View File

@ -0,0 +1,12 @@
package com.zcloud.zcGbsServicer.dto.clientobject;
import com.alibaba.cola.dto.ClientObject;
import lombok.Data;
@Data
public class VideoPlatformResultCO extends ClientObject {
private String code;
private String msg;
private Object data;
}

View File

@ -0,0 +1,13 @@
package com.zcloud.zcGbsServicer.dto.clientobject;
import com.alibaba.cola.dto.ClientObject;
import lombok.Data;
@Data
public class VideoPlatformTokenCO extends ClientObject {
private String token;
private String expireTime;
private String apiBaseUrl;
private String webBaseUrl;
}

View File

@ -0,0 +1,30 @@
package com.zcloud.zcGbsServicer.dto.clientobject;
import com.alibaba.cola.dto.ClientObject;
import lombok.Data;
import java.util.List;
@Data
public class VideoRoomInstantCO extends ClientObject {
private String meetingName;
private String roomId;
private String password;
private String userName;
private String cesAddr;
private String token;
private String userPass;
private String grantType;
private String expireTime;
private String resultMsg;
private String webUrl;
private String inviteCode;
private Integer maxUserCount;
private Integer verifyMode;
private Integer meetingType;
private Integer meetingTemplate;
private String createTime;
private String creatorId;
private List<String> loginAddrList;
}

View File

@ -6,11 +6,15 @@ import com.zcloud.zcGbsServicer.persistence.dataobject.FireAlarmInfoDO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface FireAlarmInfoMapper extends BaseMapper<FireAlarmInfoDO> {
IPage<FireAlarmInfoDO> selectPageSql(IPage<FireAlarmInfoDO> page,
@Param("tenantId") Long tenantId,
@Param("fireBrigadeName") String fireBrigadeName,
@Param("alarmStatus") Integer alarmStatus);
@Param("alarmStatus") Integer alarmStatus,
@Param("fireBrigadeIds") List<String> fireBrigadeIds,
@Param("feedbackOnly") Boolean corpinfoId);
}

View File

@ -13,4 +13,6 @@ public interface FireAlarmMeetingRoomRepository extends BaseRepository<FireAlarm
boolean existsByRoomCode(String roomCode, Long excludeId);
FireAlarmMeetingRoomDO getByRoomCode(String roomCode);
java.util.List<FireAlarmMeetingRoomDO> listAll();
}

View File

@ -13,6 +13,7 @@ import com.zcloud.zcGbsServicer.persistence.repository.FireAlarmInfoRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
@Service
@ -26,7 +27,16 @@ public class FireAlarmInfoRepositoryImpl extends BaseRepositoryImpl<FireAlarmInf
IPage<FireAlarmInfoDO> page = new Query<FireAlarmInfoDO>().getPage(params);
String fireBrigadeName = params == null ? null : (String) params.get("fireBrigadeName");
Integer alarmStatus = params == null ? null : (Integer) params.get("alarmStatus");
IPage<FireAlarmInfoDO> result = fireAlarmInfoMapper.selectPageSql(page, AuthContext.getTenantId(), fireBrigadeName, alarmStatus);
List<String> fireBrigadeIds = params == null ? null : (List<String>) params.get("fireBrigadeIds");
Boolean feedbackOnly = params == null ? null : (Boolean) params.get("feedbackOnly");
IPage<FireAlarmInfoDO> result = fireAlarmInfoMapper.selectPageSql(
page,
AuthContext.getTenantId(),
fireBrigadeName,
alarmStatus,
fireBrigadeIds,
feedbackOnly
);
return PageHelper.pageToResponse(result, result.getRecords());
}

View File

@ -2,6 +2,7 @@ package com.zcloud.zcGbsServicer.persistence.repository.impl;
import cn.hutool.core.util.StrUtil;
import com.alibaba.cola.dto.PageResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jjb.saas.framework.auth.utils.AuthContext;
@ -75,4 +76,11 @@ public class FireAlarmMeetingRoomRepositoryImpl extends BaseRepositoryImpl<FireA
}
return this.getOne(wrapper);
}
@Override
public java.util.List<FireAlarmMeetingRoomDO> listAll() {
return this.list(new LambdaQueryWrapper<FireAlarmMeetingRoomDO>()
.eq(FireAlarmMeetingRoomDO::getTenantId, AuthContext.getTenantId())
.eq(FireAlarmMeetingRoomDO::getDeleteEnum, "FALSE"));
}
}

View File

@ -18,6 +18,15 @@
<if test="alarmStatus != null">
AND alarm_status = #{alarmStatus}
</if>
<if test="alarmStatus == null and feedbackOnly != null and feedbackOnly">
AND alarm_status IN (2, 3)
</if>
<if test="fireBrigadeIds != null and fireBrigadeIds.size() > 0">
AND fire_brigade_id IN
<foreach collection="fireBrigadeIds" item="item" open="(" separator="," close=")">
#{item}
</foreach>
</if>
</where>
ORDER BY record_time DESC, create_time DESC
</select>