Commit fed8aa7b by zhangxingmin

push

parent 00b69c0c
......@@ -3,21 +3,15 @@ package com.yd.communication.api.controller;
import com.yd.common.result.Result;
import com.yd.communication.api.service.ApiCoSessionService;
import com.yd.communication.feign.client.ApiCoSessionFeignClient;
import com.yd.communication.feign.request.CreateRequest;
import com.yd.communication.feign.request.EndSessionRequest;
import com.yd.communication.feign.request.JoinRequest;
import com.yd.communication.feign.request.TransferControlRequest;
import com.yd.communication.feign.response.CommonResponse;
import com.yd.communication.feign.response.CreateResponse;
import com.yd.communication.feign.response.JoinResponse;
import com.yd.communication.feign.response.SessionDetailResponse;
import com.yd.communication.feign.request.*;
import com.yd.communication.feign.response.*;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
/**
* 协同会话信息
* 会话信息
*
* @author zxm
* @since 2026-07-28
......@@ -31,7 +25,7 @@ public class ApiCoSessionController implements ApiCoSessionFeignClient {
private ApiCoSessionService apiCoSessionService;
/**
* 创建协同会话
* 创建会话
* @param request 创建会话请求
* @return
*/
......@@ -41,7 +35,7 @@ public class ApiCoSessionController implements ApiCoSessionFeignClient {
}
/**
* 加入协同会话
* 加入会话
* @param request
* @return
*/
......@@ -50,6 +44,16 @@ public class ApiCoSessionController implements ApiCoSessionFeignClient {
}
/**
* 获取会话状态
* @param request
* @return
*/
@Override
public Result<GetStatusResponse> getStatus(GetStatusRequest request) {
return apiCoSessionService.getStatus(request);
}
/**
* 获取会话详情
* @param bizId
* @return
......
......@@ -2,14 +2,8 @@ package com.yd.communication.api.service;
import com.yd.common.result.Result;
import com.yd.communication.feign.dto.RoomRedisInfoDTO;
import com.yd.communication.feign.request.CreateRequest;
import com.yd.communication.feign.request.EndSessionRequest;
import com.yd.communication.feign.request.JoinRequest;
import com.yd.communication.feign.request.TransferControlRequest;
import com.yd.communication.feign.response.CommonResponse;
import com.yd.communication.feign.response.CreateResponse;
import com.yd.communication.feign.response.JoinResponse;
import com.yd.communication.feign.response.SessionDetailResponse;
import com.yd.communication.feign.request.*;
import com.yd.communication.feign.response.*;
import com.yd.communication.service.model.CoSession;
......@@ -19,6 +13,8 @@ public interface ApiCoSessionService {
Result<JoinResponse> join(JoinRequest request);
Result<GetStatusResponse> getStatus(GetStatusRequest request);
Result<SessionDetailResponse> get(String bizId);
Result<CommonResponse> end(EndSessionRequest request);
......
......@@ -4,6 +4,7 @@ import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yd.common.enums.CommonEnum;
import com.yd.common.exception.BusinessException;
import com.yd.common.result.JsonResult;
import com.yd.common.result.Result;
import com.yd.common.utils.ByteArrayMultipartFile;
import com.yd.common.utils.RandomStringGenerator;
......@@ -15,14 +16,10 @@ import com.yd.communication.feign.dto.RoomRedisInfoDTO;
import com.yd.communication.feign.enums.CoSessionStatusEnum;
import com.yd.communication.feign.enums.ControlHolderTypeEnum;
import com.yd.communication.feign.enums.RedisEnum;
import com.yd.communication.feign.request.CreateRequest;
import com.yd.communication.feign.request.EndSessionRequest;
import com.yd.communication.feign.request.JoinRequest;
import com.yd.communication.feign.request.TransferControlRequest;
import com.yd.communication.feign.response.CommonResponse;
import com.yd.communication.feign.response.CreateResponse;
import com.yd.communication.feign.response.JoinResponse;
import com.yd.communication.feign.response.SessionDetailResponse;
import com.yd.communication.feign.request.*;
import com.yd.communication.feign.request.http.GenerateTokenRequest;
import com.yd.communication.feign.response.*;
import com.yd.communication.feign.response.http.GenerateTokenResponse;
import com.yd.communication.service.model.CoSession;
import com.yd.communication.service.service.ICoOperationLogService;
import com.yd.communication.service.service.ICoSessionService;
......@@ -35,12 +32,18 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.UUID;
@Slf4j
......@@ -65,13 +68,27 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
@Value("${co.room.base-url:https://default-domain.com/co/join}")
private String roomBaseUrl;
@Resource
private RestTemplate restTemplate;
@Value("${sfp.api.base-url:https://mdev.anjibao.cn/sfpApi}")
private String sfpApiBaseUrl;
/**
* 客户创建会话(生成共享码)——内部方法
* 客户创建会话
* @param scope
* @param resourceType
* @param resourceId
* @param resourceInit
* @param ownerId
* @param ownerType
* @param userId
* @return
*/
@Transactional(rollbackFor = Exception.class)
public CoSession createSession(String scope, String resourceType, String resourceId,
String resourceInit, String ownerId, String ownerType,
String userId, String token) {
String userId) {
log.info("【创建会话-内部】开始创建, scope={}, resourceType={}, resourceId={}, ownerId={}, ownerType={}, userId={}",
scope, resourceType, resourceId, ownerId, ownerType, userId);
try {
......@@ -107,9 +124,54 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
iCoSessionService.save(session);
log.info("【创建会话-内部】数据库保存成功, id={}", session.getId());
// 获取 Token(调用 /user/generate/token)
String token = null;
try {
// 构建请求体
GenerateTokenRequest tokenRequest = new GenerateTokenRequest();
// 注意:userId 是 String,转为 Long。若 userId 可能为空,需做判空处理
if (StringUtils.isNotBlank(userId)) {
tokenRequest.setSfpUserId(Long.valueOf(userId));
} else {
// 如果 userId 为空,可以尝试用 ownerId 或抛出业务异常,根据业务定
throw new BusinessException("userId 不能为空,无法生成 Token");
}
// 发起 POST 请求
String url = sfpApiBaseUrl + "/user/generate/token";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<GenerateTokenRequest> entity = new HttpEntity<>(tokenRequest, headers);
ResponseEntity<JsonResult> responseEntity = restTemplate.postForEntity(url, entity, JsonResult.class);
if (responseEntity.getStatusCode().is2xxSuccessful()) {
JsonResult body = responseEntity.getBody();
if (body != null && body.isSuccess()) {
// 假设 body.getData() 返回的是 LinkedHashMap,需要转为 GenerateTokenResponse
// 或者直接使用 fastjson 转换
Object data = body.getData();
if (data != null) {
GenerateTokenResponse tokenResp = JSONObject.parseObject(JSONObject.toJSONString(data), GenerateTokenResponse.class);
token = tokenResp.getToken();
}
}
}
if (StringUtils.isBlank(token)) {
log.error("【创建会话】获取Token失败,userId={}", userId);
throw new BusinessException("生成会话 Token 失败,请稍后重试");
}
log.info("【创建会话】获取Token成功,token前缀={}", token.substring(0, Math.min(10, token.length())));
} catch (Exception e) {
log.error("【创建会话】调用生成Token接口异常", e);
throw new BusinessException("生成会话 Token 异常:" + e.getMessage());
}
// 存入 Redis
RoomRedisInfoDTO roomRedisInfoDTO = new RoomRedisInfoDTO();
roomRedisInfoDTO.setToken(token);
roomRedisInfoDTO.setToken(token); // 设置 token
roomRedisInfoDTO.setUserId(userId);
roomRedisInfoDTO.setControlHolderType(session.getControlHolderType());
roomRedisInfoDTO.setControlHolderId(session.getControlHolderId());
......@@ -145,14 +207,14 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
}
/**
* 创建协同会话
* 创建会话
* @param request
* @return
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Result<CreateResponse> create(CreateRequest request) {
log.info("【创建协同会话】收到创建请求, request={}", request);
log.info("【创建会话】收到创建请求, request={}", request);
try {
// 1. 创建会话
CoSession session = createSession(
......@@ -162,17 +224,16 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
request.getResourceInit(),
request.getOwnerId(),
request.getOwnerType(),
request.getUserId(),
request.getToken()
request.getUserId()
);
if (session == null) {
log.warn("【创建协同会话-生成二维码】创建会话失败");
log.warn("【创建会话-生成二维码】创建会话失败");
return Result.success();
}
// 2. 构建房间链接(从配置读取)
String roomLink = roomBaseUrl + "?roomId=" + session.getRoomId() + "&pwd=" + session.getRoomPwd();
log.info("【创建协同会话】生成房间链接: {}", roomLink);
log.info("【创建会话】生成房间链接: {}", roomLink);
// 3. 生成二维码图片字节数组(PNG格式)
byte[] qrCodeBytes = QRCodeUtils.generateQRCode(roomLink, 300, 300);
......@@ -198,14 +259,14 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
// 6. 调用 Feign 上传
Result<ApiUploadResponse> uploadResult = apiOssFeignClient.uploadFileBodyWithJson(multipartFile, requestJson);
if (uploadResult == null || uploadResult.getCode() != 200 || uploadResult.getData() == null) {
log.error("【创建协同会话】OSS上传失败,result={}", uploadResult);
log.error("【创建会话】OSS上传失败,result={}", uploadResult);
throw new BusinessException("二维码上传失败:" + (uploadResult != null ? uploadResult.getMsg() : "未知错误"));
}
// 7. 获取文件访问 URL(假设 ApiUploadResponse 包含 url 字段)
ApiUploadResponse uploadData = uploadResult.getData();
String roomQrCodeUrl = uploadData.getUrl(); // 若字段名为 fileUrl 则对应调整
log.info("【创建协同会话】OSS上传成功,文件URL: {}", roomQrCodeUrl);
log.info("【创建会话】OSS上传成功,文件URL: {}", roomQrCodeUrl);
//8. 更新会话信息表数据
session.setRoomQrCode(roomQrCodeUrl);
......@@ -213,10 +274,17 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
iCoSessionService.saveOrUpdate(session);
//设置房间链接失效时间(用于扫码和链接直接访问,加载页面后调用校验接口判断是否失效)
redisUtil.setCacheObject(RedisEnum.ROOM_LINK.getPrefix() + session.getRoomId() + ":" + session.getRoomPwd(), session.getRoomLink(),
RedisEnum.ROOM_LINK.getTimeout(), RedisEnum.ROOM_LINK.getTimeUnit());
//设置房间链接失效时间(用于扫码和链接直接访问)
redisUtil.setCacheObject(RedisEnum.ROOM_LINK.getPrefix() + session.getRoomId() + ":" + session.getRoomPwd(),
session.getRoomLink(),
RedisEnum.ROOM_LINK.getTimeout(),
RedisEnum.ROOM_LINK.getTimeUnit());
// 计算链接失效时间点(当前时间 + 缓存过期时长)
long expireMillis = RedisEnum.ROOM_LINK.getTimeUnit().toMillis(RedisEnum.ROOM_LINK.getTimeout());
Date expirationDate = new Date(System.currentTimeMillis() + expireMillis);
//9. 组装响应
// 组装响应
CreateResponse response = new CreateResponse();
response.setRoomId(session.getRoomId());
response.setRoomPwd(session.getRoomPwd());
......@@ -224,12 +292,13 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
response.setStatus(session.getStatus());
response.setRoomLink(roomLink);
response.setRoomQrCode(roomQrCodeUrl);
response.setExpirationTime(expirationDate); // 设置过期时间
log.info("【创建协同会话】成功,roomId={}, sessionBizId={}", session.getRoomId(), session.getCoSessionBizId());
log.info("【创建会话】成功,roomId={}, sessionBizId={}", session.getRoomId(), session.getCoSessionBizId());
return Result.success(response);
} catch (Exception e) {
log.error("【创建协同会话】异常", e);
throw new BusinessException("创建协同会话失败:" + e.getMessage());
log.error("【创建会话】异常", e);
throw new BusinessException("创建会话失败:" + e.getMessage());
}
}
......@@ -260,7 +329,7 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
joinResponse.setSessionBizId(session.getCoSessionBizId());
// 获取资源所有者缓存中的登录信息
RoomRedisInfoDTO roomRedisInfoDTO = redisUtil.getCacheObject(RedisEnum.ROOM.getPrefix() + session.getRoomId());
RoomRedisInfoDTO roomRedisInfoDTO = redisUtil.getCacheObject(RedisEnum.ROOM.getPrefix() + session.getRoomId() + ":" + session.getRoomPwd());
if (roomRedisInfoDTO == null) {
log.error("【加入会话】会话发起者缓存信息不存在,roomId={}", session.getRoomId());
throw new BusinessException("会话发起者登录信息失效,建议联系会话发起者再次发起");
......@@ -270,6 +339,10 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
log.info("【加入会话】成功, roomId={}, participantId={}, controlHolderType={}",
session.getRoomId(), session.getParticipantId(), session.getControlHolderType());
//删除房间链接缓存(只能访问一次,下次重新生成)
redisUtil.deleteObject(RedisEnum.ROOM_LINK.getPrefix() + session.getRoomId() + ":" + session.getRoomPwd());
return Result.success(joinResponse);
} catch (Exception e) {
log.error("【加入会话】异常", e);
......@@ -310,11 +383,11 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
log.warn("【加入会话-内部】会话已结束,roomId={}", session.getRoomId());
throw new BusinessException("会话已结束,不能再次加入房间");
}
if (StringUtils.isNotBlank(session.getParticipantId()) && !session.getParticipantId().equals(participantId)) {
log.warn("【加入会话-内部】房间被占用,当前参与者={}, 新参与者={}",
session.getParticipantId(), participantId);
throw new BusinessException("当前房间被占用,不能加入到房间");
}
// if (StringUtils.isNotBlank(session.getParticipantId()) && !session.getParticipantId().equals(participantId)) {
// log.warn("【加入会话-内部】房间被占用,当前参与者={}, 新参与者={}",
// session.getParticipantId(), participantId);
// throw new BusinessException("当前房间被占用,不能加入到房间");
// }
// 若为待开始状态,设置开始时间并转移控制权
if (CoSessionStatusEnum.DKS.getItemValue().equals(session.getStatus())) {
......@@ -374,6 +447,31 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
}
/**
* 获取会话状态
* @param request
* @return
*/
@Override
public Result<GetStatusResponse> getStatus(GetStatusRequest request) {
CoSession coSession = iCoSessionService.lambdaQuery()
.eq(CoSession::getCoSessionBizId,request.getSessionBizId())
.last(" limit 1 ")
.one();
if (coSession == null) {
throw new BusinessException("会话信息不存在");
}
GetStatusResponse response = new GetStatusResponse();
String roomLink = redisUtil.getCacheObject(RedisEnum.ROOM_LINK.getPrefix() + coSession.getRoomId() + ":" + coSession.getRoomPwd());
if (StringUtils.isBlank(roomLink)) {
//2-已失效
response.setStatus(2);
}else {
response.setStatus(1);
}
return Result.success(response);
}
/**
* 获取会话详情
*/
@Override
......
......@@ -2,14 +2,8 @@ package com.yd.communication.feign.client;
import com.yd.common.result.Result;
import com.yd.communication.feign.fallback.ApiCoSessionFeignFallbackFactory;
import com.yd.communication.feign.request.CreateRequest;
import com.yd.communication.feign.request.EndSessionRequest;
import com.yd.communication.feign.request.JoinRequest;
import com.yd.communication.feign.request.TransferControlRequest;
import com.yd.communication.feign.response.CommonResponse;
import com.yd.communication.feign.response.CreateResponse;
import com.yd.communication.feign.response.JoinResponse;
import com.yd.communication.feign.response.SessionDetailResponse;
import com.yd.communication.feign.request.*;
import com.yd.communication.feign.response.*;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
......@@ -25,7 +19,7 @@ import org.springframework.web.bind.annotation.*;
public interface ApiCoSessionFeignClient {
/**
* 创建协同会话
* 创建会话
*
* @param request 创建会话请求
* @return 会话信息
......@@ -34,7 +28,7 @@ public interface ApiCoSessionFeignClient {
Result<CreateResponse> create(@Validated @RequestBody CreateRequest request);
/**
* 顾问加入协同会话(输入共享码)
* 加入会话
*
* @param request 加入会话请求
* @return 会话详情
......@@ -43,6 +37,14 @@ public interface ApiCoSessionFeignClient {
Result<JoinResponse> join(@Validated @RequestBody JoinRequest request);
/**
* 获取会话状态
* @param request
* @return
*/
@PostMapping("/status")
Result<GetStatusResponse> getStatus(@Validated @RequestBody GetStatusRequest request);
/**
* 获取协同会话详情
*
* @param bizId 会话业务ID
......
......@@ -2,14 +2,8 @@ package com.yd.communication.feign.fallback;
import com.yd.common.result.Result;
import com.yd.communication.feign.client.ApiCoSessionFeignClient;
import com.yd.communication.feign.request.CreateRequest;
import com.yd.communication.feign.request.EndSessionRequest;
import com.yd.communication.feign.request.JoinRequest;
import com.yd.communication.feign.request.TransferControlRequest;
import com.yd.communication.feign.response.CommonResponse;
import com.yd.communication.feign.response.CreateResponse;
import com.yd.communication.feign.response.JoinResponse;
import com.yd.communication.feign.response.SessionDetailResponse;
import com.yd.communication.feign.request.*;
import com.yd.communication.feign.response.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;
......@@ -35,6 +29,11 @@ public class ApiCoSessionFeignFallbackFactory implements FallbackFactory<ApiCoSe
}
@Override
public Result<GetStatusResponse> getStatus(GetStatusRequest request) {
return null;
}
@Override
public Result<SessionDetailResponse> get(String bizId) {
return null;
}
......
......@@ -64,10 +64,4 @@ public class CreateRequest {
@NotBlank(message = "资源所有者的登录用户ID不能为空")
private String userId;
/**
* 资源所有者的登录token信息
*/
@NotBlank(message = "资源所有者的登录token信息不能为空")
private String token;
}
\ No newline at end of file
package com.yd.communication.feign.request;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@Data
public class GetStatusRequest {
/**
* 会话唯一业务ID
*/
@NotBlank(message = "会话唯一业务ID不能为空")
private String sessionBizId;
}
package com.yd.communication.feign.request.http;
import lombok.Data;
@Data
public class GenerateTokenRequest {
/**
* 商城用户ID
*/
private Long sfpUserId;
/**
* 分销用户ID
*/
private Long cffpUserId;
}
package com.yd.communication.feign.response;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.util.Date;
/**
* 创建协同会话响应对象
*/
......@@ -37,4 +40,10 @@ public class CreateResponse {
* 协同房间链接(访问链接进入房间)
*/
private String roomLink;
/**
* 链接失效时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm", timezone = "GMT+8")
private Date expirationTime;
}
\ No newline at end of file
package com.yd.communication.feign.response;
import lombok.Data;
@Data
public class GetStatusResponse {
/**
* 1-未失效 2-已失效
*/
private Integer status;
}
package com.yd.communication.feign.response.http;
import lombok.Data;
@Data
public class GenerateTokenResponse {
/**
* token
*/
private String token;
/**
* 商城用户ID
*/
private Long sfpUserId;
/**
* 分销用户ID
*/
private Long cffpUserId;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment