Files
2025-08-03 00:11:15 +08:00

337 lines
8.1 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package movie
import (
"strconv"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/os/gtime"
"nl-video-api/internal/dao"
"nl-video-api/internal/service/movie"
"nl-video-api/utility/response"
)
// EpisodeController 集数控制器
type EpisodeController struct{}
var Episode = &EpisodeController{}
// Create 创建集数
func (c *EpisodeController) Create(r *ghttp.Request) {
var req *movie.EpisodeCreateReq
if err := r.Parse(&req); err != nil {
response.Error(r, 1001, "参数解析失败: "+err.Error())
return
}
episodeService := movie.NewEpisodeService()
err := episodeService.Create(r.Context(), req)
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "创建成功",
"id": req.MovieId,
})
}
// Update 更新集数
func (c *EpisodeController) Update(r *ghttp.Request) {
var req *movie.EpisodeUpdateReq
if err := r.Parse(&req); err != nil {
response.Error(r, 1001, "参数解析失败: "+err.Error())
return
}
// 从URL路径获取ID
if req.Id == 0 {
idStr := r.Get("id").String()
if id, err := strconv.Atoi(idStr); err == nil {
req.Id = id
}
}
if req.Id <= 0 {
response.Error(r, 1001, "集数ID无效")
return
}
episodeService := movie.NewEpisodeService()
err := episodeService.Update(r.Context(), req)
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "更新成功",
})
}
// GetById 获取集数详情
func (c *EpisodeController) GetById(r *ghttp.Request) {
idStr := r.Get("id").String()
id, err := strconv.Atoi(idStr)
if err != nil || id <= 0 {
response.Error(r, 1001, "集数ID无效")
return
}
episodeService := movie.NewEpisodeService()
episode, err := episodeService.GetById(r.Context(), &movie.EpisodeDetailReq{Id: id})
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "获取成功",
"data": episode,
})
}
// GetByMovieId 根据影片ID获取集数列表
func (c *EpisodeController) GetByMovieId(r *ghttp.Request) {
movieIdStr := r.Get("movie_id").String()
movieId, err := strconv.Atoi(movieIdStr)
if err != nil || movieId <= 0 {
response.Error(r, 1001, "影片ID无效")
return
}
episodeService := movie.NewEpisodeService()
episodes, err := episodeService.GetByMovieId(r.Context(), movieId)
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "获取成功",
"list": episodes,
"total": len(episodes),
"movie_id": movieId,
})
}
// Delete 删除集数
func (c *EpisodeController) Delete(r *ghttp.Request) {
idStr := r.Get("id").String()
id, err := strconv.Atoi(idStr)
if err != nil || id <= 0 {
response.Error(r, 1001, "集数ID无效")
return
}
episodeService := movie.NewEpisodeService()
err = episodeService.Delete(r.Context(), &movie.EpisodeDeleteReq{Id: id})
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "删除成功",
})
}
// BatchCreate 批量创建集数
func (c *EpisodeController) BatchCreate(r *ghttp.Request) {
type BatchCreateReq struct {
MovieId int `json:"movie_id" v:"required|min:1#请选择影片"`
Episodes []movie.EpisodeCreateReq `json:"episodes" v:"required#集数列表不能为空"`
}
var req BatchCreateReq
if err := r.Parse(&req); err != nil {
response.Error(r, 1001, "参数解析失败: "+err.Error())
return
}
if len(req.Episodes) == 0 {
response.Error(r, 1001, "集数列表不能为空")
return
}
// 设置影片ID
for i := range req.Episodes {
req.Episodes[i].MovieId = req.MovieId
}
episodeService := movie.NewEpisodeService()
// 由于BatchCreate方法不存在我们逐个创建
successCount := 0
for _, episodeReq := range req.Episodes {
if err := episodeService.Create(r.Context(), &episodeReq); err != nil {
g.Log().Errorf(r.Context(), "创建集数失败: %v", err)
} else {
successCount++
}
}
response.Success(r, g.Map{
"message": "批量创建完成",
"movie_id": req.MovieId,
"total_count": len(req.Episodes),
"success_count": successCount,
"fail_count": len(req.Episodes) - successCount,
})
}
// UploadVideo 上传集数视频
func (c *EpisodeController) UploadVideo(r *ghttp.Request) {
file := r.GetUploadFile("video")
if file == nil {
response.Error(r, 1001, "请选择要上传的视频文件")
return
}
// 验证文件类型
allowedTypes := []string{"video/mp4", "video/avi", "video/mkv", "video/mov", "video/wmv"}
isValidType := false
for _, allowedType := range allowedTypes {
if file.Header.Get("Content-Type") == allowedType {
isValidType = true
break
}
}
if !isValidType {
response.Error(r, 1001, "不支持的视频格式")
return
}
// 检查文件大小限制5GB
maxSize := int64(5 * 1024 * 1024 * 1024)
if file.Size > maxSize {
response.Error(r, 1001, "视频文件过大最大支持5GB")
return
}
// 生成文件名
timestamp := gtime.Now().TimestampStr()
filename := timestamp + "_" + file.Filename
uploadPath := "resource/public/uploads/episodes/" + filename
// 保存文件
if _, err := file.Save(uploadPath); err != nil {
response.Error(r, 1002, "视频上传失败: "+err.Error())
return
}
// 返回文件信息
relativePath := "/uploads/episodes/" + filename
response.Success(r, g.Map{
"message": "上传成功",
"url": relativePath,
"filename": filename,
"size": file.Size,
})
}
// GenerateThumbnail 生成缩略图
func (c *EpisodeController) GenerateThumbnail(r *ghttp.Request) {
videoUrl := r.Get("video_url").String()
if videoUrl == "" {
response.Error(r, 1001, "视频地址不能为空")
return
}
// 生成缩略图文件路径
timestamp := gtime.Now().TimestampStr()
filename := "thumb_" + timestamp + ".jpg"
thumbDir := "resource/public/uploads/thumbnails"
_ = thumbDir + "/" + filename // 避免未使用变量错误
// 提取缩略图 (这里需要实际的视频处理库)
// if err := video.ExtractCover(videoUrl, thumbPath); err != nil {
// response.Error(r, 1002, "生成缩略图失败: "+err.Error())
// return
// }
// 返回缩略图信息
relativePath := "/uploads/thumbnails/" + filename
response.Success(r, g.Map{
"message": "生成成功",
"thumbnail": relativePath,
"filename": filename,
})
}
// GetVideoInfo 获取视频信息
func (c *EpisodeController) GetVideoInfo(r *ghttp.Request) {
videoUrl := r.Get("video_url").String()
if videoUrl == "" {
response.Error(r, 1001, "视频地址不能为空")
return
}
// 获取视频信息 (这里需要实际的视频处理库)
// videoInfo, err := video.GetVideoInfo(videoUrl)
// if err != nil {
// response.Error(r, 1002, "获取视频信息失败: "+err.Error())
// return
// }
// 模拟返回视频信息
videoInfo := g.Map{
"duration": 0,
"width": 1920,
"height": 1080,
"bitrate": "2000kbps",
"format": "mp4",
"size": 0,
"created_at": "",
}
response.Success(r, g.Map{
"message": "获取成功",
"data": videoInfo,
})
}
// BatchUpdateStatus 批量更新集数状态
func (c *EpisodeController) BatchUpdateStatus(r *ghttp.Request) {
type BatchUpdateReq struct {
Ids []int `json:"ids" v:"required#请选择要操作的集数"`
Status int `json:"status" v:"required|in:0,1#状态只能为0或1"`
}
var req BatchUpdateReq
if err := r.Parse(&req); err != nil {
response.Error(r, 1001, "参数解析失败: "+err.Error())
return
}
if len(req.Ids) == 0 {
response.Error(r, 1001, "请选择要操作的集数")
return
}
ctx := r.Context()
successCount := 0
failCount := 0
for _, id := range req.Ids {
updateData := g.Map{
"status": req.Status,
}
episodeDao := dao.NewEpisodeDao()
if err := episodeDao.Update(ctx, id, updateData); err != nil {
g.Log().Errorf(ctx, "批量更新集数状态失败: ID=%d, 错误=%v", id, err)
failCount++
} else {
successCount++
}
}
response.Success(r, g.Map{
"message": "批量更新完成",
"success_count": successCount,
"fail_count": failCount,
"total_count": len(req.Ids),
})
}