parent
330acd2d79
commit
05963d7c16
|
@ -4,18 +4,27 @@ import com.guwan.backend.entity.LiveRoom;
|
||||||
import com.guwan.backend.entity.LiveRoomDTO;
|
import com.guwan.backend.entity.LiveRoomDTO;
|
||||||
import com.guwan.backend.service.LiveService;
|
import com.guwan.backend.service.LiveService;
|
||||||
import com.guwan.backend.util.Result;
|
import com.guwan.backend.util.Result;
|
||||||
|
import com.guwan.backend.util.SecurityUtil;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
|
@Tag(name = "直播管理", description = "直播相关接口")
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/live")
|
@RequestMapping("/api/live")
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class LiveController {
|
public class LiveController {
|
||||||
|
|
||||||
private final LiveService liveService;
|
private final LiveService liveService;
|
||||||
|
private final SecurityUtil securityUtil;
|
||||||
|
|
||||||
|
@Operation(summary = "创建直播间")
|
||||||
|
@SecurityRequirement(name = "bearer-jwt")
|
||||||
@PostMapping("/room")
|
@PostMapping("/room")
|
||||||
public Result<LiveRoom> createLiveRoom(@RequestBody LiveRoomDTO dto) {
|
public Result<LiveRoom> createLiveRoom(@RequestBody LiveRoomDTO dto) {
|
||||||
try {
|
try {
|
||||||
|
@ -26,9 +35,13 @@ public class LiveController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "开始直播")
|
||||||
|
@SecurityRequirement(name = "bearer-jwt")
|
||||||
@PostMapping("/room/{id}/start")
|
@PostMapping("/room/{id}/start")
|
||||||
public Result<Void> startLive(@PathVariable Long id) {
|
public Result<Void> startLive(@PathVariable Long id) {
|
||||||
try {
|
try {
|
||||||
|
// 检查权限
|
||||||
|
checkPermission(id);
|
||||||
liveService.startLive(id);
|
liveService.startLive(id);
|
||||||
return Result.success();
|
return Result.success();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -37,9 +50,13 @@ public class LiveController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "结束直播")
|
||||||
|
@SecurityRequirement(name = "bearer-jwt")
|
||||||
@PostMapping("/room/{id}/end")
|
@PostMapping("/room/{id}/end")
|
||||||
public Result<Void> endLive(@PathVariable Long id) {
|
public Result<Void> endLive(@PathVariable Long id) {
|
||||||
try {
|
try {
|
||||||
|
// 检查权限
|
||||||
|
checkPermission(id);
|
||||||
liveService.endLive(id);
|
liveService.endLive(id);
|
||||||
return Result.success();
|
return Result.success();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -47,4 +64,19 @@ public class LiveController {
|
||||||
return Result.error(e.getMessage());
|
return Result.error(e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查权限
|
||||||
|
*/
|
||||||
|
private void checkPermission(Long roomId) {
|
||||||
|
LiveRoom room = liveService.getLiveRoom(roomId);
|
||||||
|
if (room == null) {
|
||||||
|
throw new IllegalArgumentException("直播间不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
Long currentUserId = securityUtil.getCurrentUserId();
|
||||||
|
if (!room.getUserId().equals(currentUserId)) {
|
||||||
|
throw new IllegalStateException("无权操作此直播间");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
package com.guwan.backend.dto.live;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Schema(description = "直播间DTO")
|
||||||
|
public class LiveRoomDTO {
|
||||||
|
@Schema(description = "直播间标题")
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
@Schema(description = "直播间描述")
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
@Schema(description = "封面图URL")
|
||||||
|
private String coverUrl;
|
||||||
|
}
|
|
@ -12,6 +12,7 @@ public class LiveRoom {
|
||||||
private String streamKey; // 推流密钥
|
private String streamKey; // 推流密钥
|
||||||
private String rtmpUrl; // RTMP推流地址
|
private String rtmpUrl; // RTMP推流地址
|
||||||
private String hlsUrl; // HLS播放地址
|
private String hlsUrl; // HLS播放地址
|
||||||
|
private String replayUrl; // 回放地址
|
||||||
private String status; // 状态:PREPARING-准备中,LIVING-直播中,ENDED-已结束
|
private String status; // 状态:PREPARING-准备中,LIVING-直播中,ENDED-已结束
|
||||||
private Integer onlineCount; // 在线人数
|
private Integer onlineCount; // 在线人数
|
||||||
private Integer likeCount; // 点赞数
|
private Integer likeCount; // 点赞数
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
package com.guwan.backend.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.guwan.backend.entity.LiveRoom;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface LiveRoomMapper extends BaseMapper<LiveRoom> {
|
||||||
|
}
|
|
@ -5,14 +5,26 @@ public class LiveService {
|
||||||
|
|
||||||
private final LiveRoomMapper liveRoomMapper;
|
private final LiveRoomMapper liveRoomMapper;
|
||||||
private final SrsClient srsClient;
|
private final SrsClient srsClient;
|
||||||
|
private final SecurityUtil securityUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建直播间
|
* 创建直播间
|
||||||
*/
|
*/
|
||||||
public LiveRoom createLiveRoom(LiveRoomDTO dto) {
|
public LiveRoom createLiveRoom(LiveRoomDTO dto) {
|
||||||
|
// 获取当前用户
|
||||||
|
Long userId = securityUtil.getCurrentUserId();
|
||||||
|
String username = securityUtil.getCurrentUsername();
|
||||||
|
if (userId == null) {
|
||||||
|
throw new IllegalStateException("用户未登录");
|
||||||
|
}
|
||||||
|
|
||||||
LiveRoom room = new LiveRoom();
|
LiveRoom room = new LiveRoom();
|
||||||
BeanUtils.copyProperties(dto, room);
|
BeanUtils.copyProperties(dto, room);
|
||||||
|
|
||||||
|
// 设置用户信息
|
||||||
|
room.setUserId(userId);
|
||||||
|
room.setUsername(username);
|
||||||
|
|
||||||
// 生成推流密钥
|
// 生成推流密钥
|
||||||
String streamKey = generateStreamKey();
|
String streamKey = generateStreamKey();
|
||||||
room.setStreamKey(streamKey);
|
room.setStreamKey(streamKey);
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
CREATE TABLE `live_room` (
|
||||||
|
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '直播间ID',
|
||||||
|
`title` varchar(100) NOT NULL COMMENT '直播间标题',
|
||||||
|
`description` text COMMENT '直播间描述',
|
||||||
|
`cover_url` varchar(255) DEFAULT NULL COMMENT '封面图URL',
|
||||||
|
`user_id` bigint NOT NULL COMMENT '主播ID',
|
||||||
|
`username` varchar(50) DEFAULT NULL COMMENT '主播名称',
|
||||||
|
`stream_key` varchar(50) NOT NULL COMMENT '推流密钥',
|
||||||
|
`rtmp_url` varchar(255) NOT NULL COMMENT 'RTMP推流地址',
|
||||||
|
`hls_url` varchar(255) NOT NULL COMMENT 'HLS播放地址',
|
||||||
|
`replay_url` varchar(255) DEFAULT NULL COMMENT '回放地址',
|
||||||
|
`status` varchar(20) NOT NULL COMMENT '状态:PREPARING-准备中,LIVING-直播中,ENDED-已结束',
|
||||||
|
`online_count` int NOT NULL DEFAULT '0' COMMENT '在线人数',
|
||||||
|
`like_count` int NOT NULL DEFAULT '0' COMMENT '点赞数',
|
||||||
|
`created_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
`updated_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `idx_user_id` (`user_id`),
|
||||||
|
KEY `idx_created_time` (`created_time`),
|
||||||
|
UNIQUE KEY `uk_stream_key` (`stream_key`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='直播间表';
|
Loading…
Reference in New Issue